fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * CDDL HEADER START
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * The contents of this file are subject to the terms of the
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * Common Development and Distribution License (the "License").
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * You may not use this file except in compliance with the License.
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * See the License for the specific language governing permissions
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * and limitations under the License.
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * When distributing Covered Code, include this CDDL HEADER in each
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * If applicable, add the following below this CDDL HEADER, with the
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * fields enclosed by brackets "[]" replaced with your own identifying
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * information: Portions Copyright [yyyy] [name of copyright owner]
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * CDDL HEADER END
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * Use is subject to license terms.
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * mbd_label: If a DIMM associated with this branch is located on a memory
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * expansion board or riser board, return (pointer to) the label of that board;
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * otherwise return NULL.
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * We assume that there will be at most one such board for any branch.
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsienmbd_label(fmd_hdl_t *hdl, cmd_branch_t *branch, const char *nacname)
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien for (bm = cmd_list_next(&branch->branch_dimms); bm != NULL;
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien if ((p = strstr(dimm->dimm_unum, nacname)) != NULL) {
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien p = strchr(p, '/'); /* include instance number */
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien *(p + s) = '\0';
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdcmd_branch_add_dimm(fmd_hdl_t *hdl, cmd_branch_t *branch, cmd_dimm_t *dimm)
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd bm = fmd_hdl_zalloc(hdl, sizeof (cmd_branch_memb_t), FMD_SLEEP);
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdcmd_branch_remove_dimm(fmd_hdl_t *hdl, cmd_branch_t *branch, cmd_dimm_t *dimm)
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd for (bm = cmd_list_next(&branch->branch_dimms); bm != NULL;
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd "Attempt to disconnect dimm from non-parent branch\n");
70818f5837509317d1f5dac4d82d7b5a2d547c29tsienbranch_dimm_create(fmd_hdl_t *hdl, char *dimm_unum, char **serids,
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien fmri = cmd_mem_fmri_create(dimm_unum, serids, nserids);
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd if (fmri != NULL && (fmd_nvl_fmri_expand(hdl, fmri) == 0)) {
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsienstatic fmd_hdl_t *br_hdl; /* for use by callbacks */
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien/*ARGSUSED*/
70818f5837509317d1f5dac4d82d7b5a2d547c29tsienbranch_dimm_cb(topo_hdl_t *thp, tnode_t *node, void *arg)
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien if ((nvlist_lookup_string(rsrc, FM_FMRI_MEM_UNUM, &lbl) != 0) ||
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien (nvlist_lookup_string_array(rsrc, FM_FMRI_MEM_SERIAL_ID,
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * Massage the unum of the candidate DIMM as follows:
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * a) remove any trailing J number. Use result for cmd_dimm_t.
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * b) for branch membership purposes only, remove reference to
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * a riser card (MR%d) if one exists.
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien (void) strcpy(p, q);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * For benefit of Batoka-like platforms, start comparison with
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * "CMP", so that any leading "MEM" or "CPU" makes no difference.
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien if ((p != NULL) && (q != NULL) && strncmp(p, q, strlen(p)) == 0) {
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien dimm = branch_dimm_create(br_hdl, cx, serids, nserids);
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * The cmd_dimm_t structure created for a DIMM in a branch never has a
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * Jxxx in its unum; the cmd_dimm_t structure created for a DIMM containing
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * a page, or in a bank (i.e. for ECC errors)-always-has a Jxxx in its
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * unum. Therefore the set of cmd_dimm_t's created for a branch is always
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * disjoint from the set of cmd_dimm_t's created for pages and/or banks, so
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * the cmd_dimm_create will never link a 'branch' cmd_dimm_t into bank.
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * Faulting a DIMM for ECC will not prevent subsequent faulting of "same"
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * dimm for FBR/FBU and vice versa
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdbranch_dimmlist_create(fmd_hdl_t *hdl, cmd_branch_t *branch)
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien return (0);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien return (0);
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien for (dimm_count = 0, bp = cmd_list_next(&branch->branch_dimms);
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien bp != NULL; bp = cmd_list_next(bp), dimm_count++)
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsienfru_by_label_cb(topo_hdl_t *thp, tnode_t *node, void *arg)
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien return (TOPO_WALK_NEXT); /* no label, try next */
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien (topo_node_fru(node, &br_memb_nvl, NULL, &err) == 0)) {
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien if (((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) != NULL) &&
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien fru_by_label_cb, (void *)target, &err)) != NULL)) {
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsienadd_bdflt_to_case(fmd_hdl_t *hdl, char *label, const char *fltnm,
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien flt = cmd_nvl_create_fault(hdl, fltnm, board_cert,
13faa91230bde46da937bf33010b9accc5bdeb59sd * For t5440, the memory channel goes like this:
13faa91230bde46da937bf33010b9accc5bdeb59sd * VF -> cpuboard -> D0 -> motherboard -> memboard -> D[1..3]
13faa91230bde46da937bf33010b9accc5bdeb59sd * If there is a dimm on the memory board, the memory board,
13faa91230bde46da937bf33010b9accc5bdeb59sd * motherboard, cpuboard, and dimms are in the suspect list.
13faa91230bde46da937bf33010b9accc5bdeb59sd * If there is no dimm on the memory board, the cpu board and
13faa91230bde46da937bf33010b9accc5bdeb59sd * the dimms are in the suspect list
13faa91230bde46da937bf33010b9accc5bdeb59sd * The board certainty = total board certainty / number of
13faa91230bde46da937bf33010b9accc5bdeb59sd * the faulty boards in the suspect list.
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdcmd_branch_create_fault(fmd_hdl_t *hdl, cmd_branch_t *branch,
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd /* attach the dimms to the branch */
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien if ((membd_label = mbd_label(hdl, branch, "MEM")) != NULL) {
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien board_cert = CMD_BOARDS_CERT / 3; /* CPU, MEM, MB */
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * Batoka with memory expansion. CPU expansion board will
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * be added below. Add memory expansion board and motherboard
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * FRUs here.
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien add_bdflt_to_case(hdl, membd_label, fltnm, board_cert,
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien } else if ((membd_label = mbd_label(hdl, branch, "MR")) != NULL) {
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * Maramba or similar platform with mezzanine board.
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * Motherboard FRU will be added below. Add the mezzanine
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * board here.
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien add_bdflt_to_case(hdl, membd_label, fltnm, board_cert,
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien board_cert = CMD_BOARDS_CERT; /* only MB or CPU */
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * The code which follows adds to the suspect list the FRU which
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * contains the ereport 'detector'. This can be either a CPU
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * expansion board (Batoka), or motherboard (Huron, Maramba, or
2d6aa547f868d751d00f1f2e70171d9dc9317af1Louis Tsien * derivative).
13faa91230bde46da937bf33010b9accc5bdeb59sd flt = cmd_boardfru_create_fault(hdl, asru, fltnm, board_cert, fruloc);
13faa91230bde46da937bf33010b9accc5bdeb59sd fmd_case_add_suspect(hdl, branch->branch_case.cc_cp, flt);
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd /* create dimm faults */
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd for (bm = cmd_list_next(&branch->branch_dimms); bm != NULL;
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd fmd_hdl_debug(hdl, "branch_create: creating new branch %s\n", b_unum);
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd branch = fmd_hdl_zalloc(hdl, sizeof (cmd_branch_t), FMD_SLEEP);
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd cmd_bufname(branch->branch_bufname, sizeof (branch->branch_bufname),
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd cmd_fmri_init(hdl, &branch->branch_asru, asru, "branch_asru_%s",
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd (void) nvlist_lookup_string(branch->branch_asru_nvl, FM_FMRI_MEM_UNUM,
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdcmd_branch_lookup_by_unum(fmd_hdl_t *hdl, const char *unum)
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * fbr/fbu unum dimm does not have a J number
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd for (branch = cmd_list_next(&cmd.cmd_branches); branch != NULL;
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd fmd_hdl_debug(hdl, "branch_lookup_by_unum: no branch is found\n");
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd for (branch = cmd_list_next(&cmd.cmd_branches); branch != NULL;
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd fmd_hdl_debug(hdl, "cmd_branch_lookup: discarding old \n");
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdbranch_wrapv0(fmd_hdl_t *hdl, cmd_branch_pers_t *pers, size_t psz)
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd fmd_hdl_abort(hdl, "size of state doesn't match size of "
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd "version 0 state (%u bytes).\n",
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd branch = fmd_hdl_zalloc(hdl, sizeof (cmd_branch_t), FMD_SLEEP);
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdcmd_branch_restore(fmd_hdl_t *hdl, fmd_case_t *cp, cmd_case_ptr_t *ptr)
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd for (branch = cmd_list_next(&cmd.cmd_branches); branch != NULL;
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd fmd_hdl_debug(hdl, "restoring branch from %s\n", ptr->ptr_name);
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd if ((branchsz = fmd_buf_size(hdl, NULL, ptr->ptr_name)) == 0) {
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd "not exist in saved state\n",
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd "branch buffer referenced by case %s "
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd "is out of bounds (is %u bytes, max %u, min %u)\n",
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd "for branch state referenced by case %s.\n",
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd if ((errno = nvlist_lookup_string(branch->branch_asru_nvl,
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd cmd_mem_case_restore(hdl, &branch->branch_case, cp, "branch",
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd /* No need to rewrite the FMRIs in the branch - they don't change */
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd fmd_buf_write(hdl, NULL, branch->branch_bufname, &branch->branch_pers,
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdstatic void
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdbranch_dimmlist_free(fmd_hdl_t *hdl, cmd_branch_t *branch)
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd while ((bm = cmd_list_next(&branch->branch_dimms)) != NULL) {
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdstatic void
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sdbranch_free(fmd_hdl_t *hdl, cmd_branch_t *branch, int destroy)
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd fmd_hdl_debug(hdl, "Free branch %s\n", branch->branch_unum);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien/*ARGSUSED*/
70818f5837509317d1f5dac4d82d7b5a2d547c29tsienbranch_exist_cb(topo_hdl_t *thp, tnode_t *node, void *arg)
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * for branch membership purposes only, remove reference to
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien * a riser card (MR%d) if one exists.
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien (void) strcpy(p, q);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien return (0);
70818f5837509317d1f5dac4d82d7b5a2d547c29tsien return (0);
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * If the case has been solved, don't need to check the dimmlist
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * If the case has not been solved, the branch is valid if there is least one
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd * existing dimm in the branch
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd for (branch = cmd_list_next(&cmd.cmd_branches); branch != NULL;
fbd1c0dae6f4a2ccc2ce0527c7f19d3dd5ea90b8sd while ((branch = cmd_list_next(&cmd.cmd_branches)) != NULL)