7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER START
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The contents of this file are subject to the terms of the
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Common Development and Distribution License (the "License").
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * You may not use this file except in compliance with the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * See the License for the specific language governing permissions
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and limitations under the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * When distributing Covered Code, include this CDDL HEADER in each
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If applicable, add the following below this CDDL HEADER, with the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * fields enclosed by brackets "[]" replaced with your own identifying
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * information: Portions Copyright [yyyy] [name of copyright owner]
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER END
20c794b39650d115e17a15983b6b82e46238cf45gavinm * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Use is subject to license terms.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#pragma ident "%Z%%M% %I% %E% SMI"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Given a physical address and an optional syndrome, determine the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * name of the memory module that contains it.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ((val) & (((2ULL << (high)) - 1) & ~((1ULL << (low)) - 1)))
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * iaddr_gen generates a "normalized" DRAM controller input address
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * from a system address (physical address) if it falls within the
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * mapped range for this memory controller. Normalisation is
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * performed by subtracting the node base address from the system address,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * allowing from hoisting, and excising any bits being used in node
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * interleaving.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiiaddr_gen(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm uint64_t mcnum, base, lim, dramaddr, ilen, ilsel, top, holesz;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "iaddr_gen: failed to "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "lookup required properties");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * A node with no mapped memory (no active chip-selects is usually
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * mapped with base and lim both zero. We'll cover that case and
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * any other where the range is 0.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "iaddr_gen: PA 0x%llx not "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "in range [0x%llx, 0x%llx] of MC %d\n", pa, base, lim,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Rev E and later added the DRAM Hole Address Register for
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * memory hoisting. In earlier revisions memory hoisting is
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * achieved by following some algorithm to modify the CS bases etc,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and this pa to unum algorithm will simply see those modified
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * values. But if the Hole Address Register is being used then
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * we need to reduce any address at or above 4GB by the size of
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * the hole.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "iaddr_gen: dram hole "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "valid; pa decremented from 0x%llx to 0x%llx for "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (ilen != 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((pailsel = BITS(pa, 14, 12) >> 12 & ilen) != ilsel) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "PA 0x%llx in a %d-way node interleave indicates "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "selection %d, MC %d has ilsel of %d\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "iaddr_gen: PA 0x%llx in range "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "[0x%llx, 0x%llx] of MC %d; normalized address for cs compare "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * cs_match determines whether the given DRAM controller input address
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * would be responded to by the given chip-select (which may or may not
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * be interleaved with other chip-selects). Since we include nodes
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * for spare chip-selects (if any) and those marked TestFail (if any)
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * we must check chip-select-bank-enable.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindics_match(struct mcamd_hdl *hdl, uint64_t iaddr, mcamd_node_t *cs)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "cs_match: failed to lookup "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "required properties\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "cs_match: iaddr 0x%llx "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "does %smatch CS %d (base 0x%llx, mask 0x%llx)\n", iaddr,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "cs_match: iaddr 0x%llx "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "does not match disabled CS %d\n", iaddr, (int)csnum);
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Given a chip-select node determine whether it has been substituted
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * by the online spare chip-select.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinmcs_sparedto(struct mcamd_hdl *hdl, mcamd_node_t *cs, mcamd_node_t *mc)
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_ERR, "cs_sparedto: failed to "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "lookup required properties\n");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm if ((badcsnum == MC_INVALNUM && sparecsnum == MC_INVALNUM) ||
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm if (!mcamd_get_numprop(hdl, cs, MCAMD_PROP_NUM, &tmpcsnum)) {
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "fail to lookup csnum - cannot reroute to spare\n");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "cs_sparedto: cs#%d is "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "redirected to active online spare of cs#%d\n", csnum,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_ERR, "cs_sparedto: cs#%d is "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "redirected but cannot find spare cs# - cannout reroute to "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Having determined which node and chip-select an address maps to,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * as well as whether it is a dimm1, dimm2 or dimm1/dimm2 pair
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * involved, fill the unum structure including an optional dimm offset
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiunum_fill(struct mcamd_hdl *hdl, mcamd_node_t *cs, int which,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "unum_fill: failed to "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "lookup required properties\n");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm !mcamd_get_numprop(hdl, cs, MCAMD_PROP_CSDIMM1, &dimm1) ||
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm !mcamd_get_numprop(hdl, cs, MCAMD_PROP_CSDIMM2, &dimm2)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "unum_fill: failed to "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "lookup dimm1/dimm2 properties\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (i = 0; i < MC_UNUM_NDIMM; i++) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * We wish to calculate a dimm offset. In the paired case we will
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * lookup dimm1 (see offsetdimm above).
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (dimm = mcamd_dimm_next(hdl, mc, NULL); dimm != NULL;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!mcamd_get_numprop(hdl, dimm, MCAMD_PROP_NUM, &dnum)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "unum_fill: failed "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "to lookup dimm number property\n");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "unum_fill: failed to "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "find dimm with number %d for offset calculation\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * mc_pa_to_offset sets the offset to an invalid value if
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * it hits an error.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm (void) mc_pa_to_offset(hdl, mc, cs, iaddr, &unump->unum_offset);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * We have translated a system address to a (node, chip-select), and wish
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * to determine the associated dimm or dimms.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * A (node, chip-select) pair identifies one (in 64-bit MC mode) or two (in
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * 128-bit MC mode) DIMMs. In the case of a single dimm it is usually in a
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * lodimm (channel A) slot, but if mismatched dimm support is present it may
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * be an updimm (channel B).
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Where just one dimm is associated with the chip-select we are done.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Where there are two dimms associated with the chip-select we can
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * use the ECC type and/or syndrome to determine which of the pair we
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * resolve to, if the error is correctable. If the error is uncorrectable
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * then in 64/8 ECC mode we can still resolve to a single dimm (since ECC
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * is calculated and checked on each half of the data separately), but
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * in ChipKill mode we cannot resolve down to a single dimm.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinmmc_whichdimm(struct mcamd_hdl *hdl, mcamd_node_t *cs, uint64_t pa,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Read the associated dimm instance numbers. The provider must
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * assure that if there is just one dimm then it is in the first
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * property, and if there are two then the first must be on
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * channel A.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_ERR, "mc_whichdimm: failed to "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "lookup required properties");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm ndimm = (dimm1 != MC_INVALNUM) + (dimm2 != MC_INVALNUM);
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm if (ndimm == 0) {
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_ERR, "mc_whichdimm: found no "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "dimms associated with chip-select");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_whichdimm: just one "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "dimm associated with this chip-select");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * 64/8 ECC is checked separately for the upper and lower
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * halves, so even an uncorrectable error is contained within
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm * one of the two halves. If we have sufficient address resolution
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm * then we can determine which DIMM.
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_whichdimm: 64/8 "
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm "ECC in 128-bit mode, PA 0x%llx is in %s half\n",
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm "64/8 ECC in 128-bit mode, PA 0x%llx with least "
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm "significant valid bit %d cannot be resolved to "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * ChipKill ECC
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * A correctable ChipKill syndrome and we can tell
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * which half the error was in from the symbol number.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (mcamd_cksym_decode(hdl, sym, &lobit, &hibit, &data,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * An uncorrectable error while in ChipKill ECC mode - can't
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * tell which dimm or dimms the errors lie within.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "uncorrectable ChipKill, could be either LODIMM "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "or UPDIMM\n");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Brute-force BKDG pa to cs translation, coded to look as much like the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * BKDG code as possible.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindimc_bkdg_patounum(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Raw registers as per BKDG
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Variables as per BKDG
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mc, MCAMD_PROP_REV, &rev, NULL) || !mcamd_get_cfgregs(hdl,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "mc_bkdg_patounm: failed "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "to lookup required properties and registers\n");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * BKDG line to skip Why
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * F1Offset = ... Register already read,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * DramBase = Get_PCI() and retrieved above.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * DramEn = ... Function only called for enabled nodes.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm /* DramLimit = Get_PCI() Retrieved above */
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm /* HoleEn = ... Retrieved above */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!(DramBase <= SystemAddr && SystemAddr <= DramLimit)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_bkdg_patounum: "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "SystemAddr 0x%x derived from PA 0x%llx is not in the "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "address range [0x%x, 0x%x] of MC %d\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* not this node */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_bkdg_patounum: "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "Node interleaving, MC node %d not selected\n",
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "failed to read cs registers\n");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * BKDG line to skip Why
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * F2Offset = Register already read,
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * F2MaskOffset (rev F) Register already read
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * CSBase = Register already read
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * CSEn = We only keep enabled cs.
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm /* CSMask = Get_PCI() Retrieved above */
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm /* CSMask = Get_PCI() Retrieved above */
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm if (CSEn && (InputAddr & ~CSMask) == (CSBase & ~CSMask)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mc_bkdg_patounum: "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The BKDG algorithm drops low-order bits that
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * are unimportant in deriving chip-select but are
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * included in row/col/bank mapping, so do not
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * perform offset calculation in this case.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (unum_fill(hdl, cs, which, InputAddr, unump, 0) < 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_ERR, "mc_bkdg_patounum: in range "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * Called for each memory controller to see if the given address is
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * mapped to this node (as determined in iaddr_gen) and, if so, which
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * chip-select on this node responds.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindimc_patounum(struct mcamd_hdl *hdl, mcamd_node_t *mc, uint64_t pa,
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm uint8_t valid_lo, uint32_t synd, int syndtype, mc_unum_t *unump)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * We perform the translation twice, once using the brute-force
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * approach of the BKDG and again using a more elegant but more
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * difficult to review against the BKDG approach.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "BKDG brute-force method begins\n");
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm bkdgres = mc_bkdg_patounum(hdl, mc, pa, valid_lo, synd,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "BKDG brute-force method ends\n");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * If the spare chip-select has been swapped in for the one just
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * matched then it is really the spare that we are after. Note that
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * when the swap is done the csbase, csmask and CSBE of the spare
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * rank do not change - accesses to the bad rank (as nominated in
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm * the Online Spare Control Register) are redirect to the spare.
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm if ((which = mc_whichdimm(hdl, cs, pa, valid_lo, synd,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "bkdgres=%d res=0\n", bkdgres);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* offset is not checked - see note in BKDG algorithm */
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm mcamd_dprintf(hdl, MCAMD_DBG_ERR, "BKDG alg failed while "
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "ours succeeded\n");
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm } else if (!(unump->unum_board == bkdg_unum.unum_board &&
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "BKDG: node %d mc %d cs %d dimm(s) %d/%d\n"
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm "Ours: node 5d mc %d cs %d dimm(s) %d/%d\n",
8a40a695ee676a322b094e9afe5375567bfb51e3gavinm bkdg_unum.unum_chip, bkdg_unum.unum_mc, bkdg_unum.unum_cs,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#endif /* DEBUG */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "Result: chip %d mc %d cs %d "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindimcamd_patounum(struct mcamd_hdl *hdl, mcamd_node_t *root, uint64_t pa,
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm uint8_t valid_hi, uint8_t valid_lo, uint32_t synd, int syndtype,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_patounum: pa=0x%llx, "
4156fc34b973159b0334e05ae5ec19344487bdc0gavinm mcamd_dprintf(hdl, MCAMD_DBG_FLOW, "mcamd_patounum: require "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (0);