diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/hwas/common/hwasCommon.H | 10 | ||||
-rw-r--r-- | src/usr/hwas/common/hwas.C | 104 | ||||
-rw-r--r-- | src/usr/hwas/test/hwas1test.H | 229 |
3 files changed, 325 insertions, 18 deletions
diff --git a/src/include/usr/hwas/common/hwasCommon.H b/src/include/usr/hwas/common/hwasCommon.H index 3c217c606..7462571b4 100644 --- a/src/include/usr/hwas/common/hwasCommon.H +++ b/src/include/usr/hwas/common/hwasCommon.H @@ -179,10 +179,14 @@ const uint32_t VPD_CP00_PG_XBUS_PG_MASK = 0x00170; const uint32_t VPD_CP00_PG_XBUS_IOX[3] = {0x0040, 0x0020, 0x0010}; const uint32_t VPD_CP00_PG_MCxx_INDEX[4] = {7, 7, 8, 8}; // by MCS -// all good - 3:VITAL, 4:PRV, 5:MCA01, 6:IOM01+, 7:IOM23+, 14:PLLMEM -// all good - 3:VITAL, 4:PRV, 5:MCA23, 6:IOM45+, 7:IOM67+, 14:PLLMEM +// Nimbus: +// all good - 3:VITAL, 4:PRV, 5:MC01, 6:IOM01+, 7:IOM23+, 14:PLLMEM +// all good - 3:VITAL, 4:PRV, 5:MC23, 6:IOM45+, 7:IOM67+, 14:PLLMEM +// Cumulus: +// all good - 3:VITAL, 4:PRV, 5:MC01, 6:IOM01, 7:IOM01PPE, 14:PLLMEM +// all good - 3:VITAL, 4:PRV, 5:MC23, 6:IOM23, 7:IOM23PPE, 14:PLLMEM const uint32_t VPD_CP00_PG_MCxx_GOOD = 0xE0FD; -const uint32_t VPD_CP00_PG_MCxx_PG_MASK = 0x0300; +const uint32_t VPD_CP00_PG_MCxx_PG_MASK = 0x0300; // Nimbus only // iom0 and iom4 need to be good for zqcal to work on any // of the MCAs on that side const uint32_t VPD_CP00_PG_MCA_MAGIC_PORT_MASK = 0x0200; diff --git a/src/usr/hwas/common/hwas.C b/src/usr/hwas/common/hwas.C index 8951c9dfe..76a4c4916 100644 --- a/src/usr/hwas/common/hwas.C +++ b/src/usr/hwas/common/hwas.C @@ -350,7 +350,9 @@ errlHndl_t discoverTargets() { // look at the 'nest' logic to override the // functionality of this proc - chipFunctional = isChipFunctional(pTarget, pgData); + chipFunctional = + isChipFunctional(pTarget, + pgData); // Fill in a dummy restrict list l_procEntry.target = pTarget; @@ -386,7 +388,8 @@ errlHndl_t discoverTargets() { // if the chip is functional, then look through the // partialGood vector to see if its chiplets // are functional - descFunctional = isDescFunctional(pDesc, pgData); + descFunctional = isDescFunctional(pDesc, + pgData); } if (pDesc->getAttr<ATTR_TYPE>() == TYPE_PERV) @@ -631,10 +634,9 @@ bool isDescFunctional(const TARGETING::TargetHandle_t &i_desc, } else // Check PBIOO0 bit in N1 entry - // @TODO RTC:134608 PBIOO0 seems to be good with Nimbus and Cumulus - // except Nimbus Sforza (without optics and NVLINK) - // so is it associated with all OBUS entries or just - // with OBUS0 and OBUS3 -- verify this + // Rule 3 / Rule 4 PBIOO0 to be good with Nimbus and Cumulus except + // Nimbus Sforza (without optics and NVLINK), so is + // associated with all OBUS entries if ((i_pgData[VPD_CP00_PG_N1_INDEX] & VPD_CP00_PG_N1_PBIOO0) != 0) { @@ -649,8 +651,8 @@ bool isDescFunctional(const TARGETING::TargetHandle_t &i_desc, } else // Check PBIOO1 bit in N1 entry if second or third OBUS - // @TODO RTC:134608 PBIOO1 seems to be associated with OBUS1 and OBUS2 - // which only are valid on a Cumulus -- verify this + // Rule 4 PBIOO1 to be associated with OBUS1 and OBUS2 which only are + // valid on a Cumulus if (((1 == indexOB) || (2 == indexOB)) && ((i_pgData[VPD_CP00_PG_N1_INDEX] & VPD_CP00_PG_N1_PBIOO1) != 0)) @@ -819,7 +821,7 @@ bool isDescFunctional(const TARGETING::TargetHandle_t &i_desc, l_descFunctional = false; } } - else + else // MCBIST is found on Nimbus chips if (i_desc->getAttr<ATTR_TYPE>() == TYPE_MCBIST) { ATTR_CHIP_UNIT_type indexMCBIST = @@ -886,7 +888,7 @@ bool isDescFunctional(const TARGETING::TargetHandle_t &i_desc, } } - else + else // MCS is found on Nimbus chips if (i_desc->getAttr<ATTR_TYPE>() == TYPE_MCS) { ATTR_CHIP_UNIT_type indexMCS = @@ -952,7 +954,7 @@ bool isDescFunctional(const TARGETING::TargetHandle_t &i_desc, l_descFunctional = false; } } - else + else // MCA is found on Nimbus chips if (i_desc->getAttr<ATTR_TYPE>() == TYPE_MCA) { ATTR_CHIP_UNIT_type indexMCA = @@ -987,6 +989,80 @@ bool isDescFunctional(const TARGETING::TargetHandle_t &i_desc, l_descFunctional = false; } } + else // MC/MI/DMI is found on Cumulus chips + if ((i_desc->getAttr<ATTR_TYPE>() == TYPE_MC) || + (i_desc->getAttr<ATTR_TYPE>() == TYPE_MI) || + (i_desc->getAttr<ATTR_TYPE>() == TYPE_DMI)) + { + ATTR_CHIP_UNIT_type index = + i_desc->getAttr<ATTR_CHIP_UNIT>(); + + // 2 MCs/chip, 2 MIs/MC, 2 DMIs/MI + size_t indexMC = 0; + size_t indexMI = 0; + + if (i_desc->getAttr<ATTR_TYPE>() == TYPE_MC) + { + indexMC = index; + indexMI = index * 2; + } + else + if (i_desc->getAttr<ATTR_TYPE>() == TYPE_MI) + { + indexMI = index; + indexMC = index / 2; + } + else + if (i_desc->getAttr<ATTR_TYPE>() == TYPE_DMI) + { + indexMI = index / 2; + indexMC = index / 4; + } + + // Check MCS01 bit in N3 entry if first MC + if ((0 == indexMC) && + ((i_pgData[VPD_CP00_PG_N3_INDEX] & + VPD_CP00_PG_N3_MCS01) != 0)) + { + HWAS_INF("pDesc %.8X - MC%d pgData[%d]: " + "actual 0x%04X, expected 0x%04X - bad", + i_desc->getAttr<ATTR_HUID>(), indexMC, + VPD_CP00_PG_N3_INDEX, + i_pgData[VPD_CP00_PG_N3_INDEX], + (i_pgData[VPD_CP00_PG_N3_INDEX] & + ~VPD_CP00_PG_N3_MCS01)); + l_descFunctional = false; + } + else + // Check MCS23 bit in N1 entry if second MC + if ((1 == indexMC) && + ((i_pgData[VPD_CP00_PG_N1_INDEX] & + VPD_CP00_PG_N1_MCS23) != 0)) + { + HWAS_INF("pDesc %.8X - MC%d pgData[%d]: " + "actual 0x%04X, expected 0x%04X - bad", + i_desc->getAttr<ATTR_HUID>(), indexMC, + VPD_CP00_PG_N1_INDEX, + i_pgData[VPD_CP00_PG_N1_INDEX], + (i_pgData[VPD_CP00_PG_N1_INDEX] & + ~VPD_CP00_PG_N1_MCS23)); + l_descFunctional = false; + } + else + // Check bits in MCxx entry except those in partial good region + if (i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMI]] != + VPD_CP00_PG_MCxx_GOOD) + { + HWAS_INF("pDesc %.8X - MC%d pgData[%d]: " + "actual 0x%04X, expected 0x%04X - bad", + i_desc->getAttr<ATTR_HUID>(), indexMC, + VPD_CP00_PG_MCxx_INDEX[indexMI], + i_pgData[VPD_CP00_PG_MCxx_INDEX[indexMI]], + VPD_CP00_PG_MCxx_GOOD); + l_descFunctional = false; + } + + } else if (i_desc->getAttr<ATTR_TYPE>() == TYPE_OBUS_BRICK) { @@ -2134,7 +2210,7 @@ void invokePresentByAssoc() #endif // get the functional membufs - // note: do not expect membufs for NIMBUS + // note: do not expect membufs for NIMBUS TargetHandleList l_funcMembufTargetList; getAllChips(l_funcMembufTargetList, TYPE_MEMBUF, true ); l_funcTargetList.insert(l_funcTargetList.begin(), @@ -2265,7 +2341,7 @@ void presentByAssoc(TargetInfoVector& io_funcTargets, size_t l_MIIndex = __INT_MAX__; size_t l_DMIIndex = __INT_MAX__; size_t l_MEMBUFIndex = __INT_MAX__; - size_t l_MBAIndex = __INT_MAX__; + size_t l_MBAIndex = __INT_MAX__; size_t i = 0; // Perform presentByAssoc algorithm @@ -2726,7 +2802,7 @@ void presentByAssoc(TargetInfoVector& io_funcTargets, else if ( l_MEMBUFIndex != __INT_MAX__) { i = l_MEMBUFIndex; - } + } //Backtrack to last DMI (CUMULUS),if no MEMBUF has been seen yet else if ( l_DMIIndex != __INT_MAX__ ) { diff --git a/src/usr/hwas/test/hwas1test.H b/src/usr/hwas/test/hwas1test.H index 0eca4045a..4b1e9ccd0 100644 --- a/src/usr/hwas/test/hwas1test.H +++ b/src/usr/hwas/test/hwas1test.H @@ -1422,7 +1422,234 @@ public: break; - case TYPE_OBUS_BRICK: + case TYPE_MC: + TS_INFO( "testHWASisDescFunctional: " + "MC%d is not functional", l_chipUnit); + if (l_chipUnit) + { + pgData[VPD_CP00_PG_N1_INDEX] |= + (uint16_t)VPD_CP00_PG_N1_MCS23; + } + else + { + pgData[VPD_CP00_PG_N3_INDEX] |= + (uint16_t)VPD_CP00_PG_N3_MCS01; + } + + if (isDescFunctional(pDesc, pgData)) + { + TS_FAIL("testHWASisDescFunctional>" + "functional = 0x%x, should be false, " + "N1/N3 for MC%d = 0x%04x.", + isDescFunctional(pDesc, pgData), + l_chipUnit, + l_chipUnit ? pgData[VPD_CP00_PG_N1_INDEX] + : pgData[VPD_CP00_PG_N3_INDEX]); + } + + if (l_chipUnit) + { + pgData[VPD_CP00_PG_N1_INDEX] = + (uint16_t)VPD_CP00_PG_N1_GOOD; + } + else + { + pgData[VPD_CP00_PG_N3_INDEX] = + (uint16_t)VPD_CP00_PG_N3_GOOD; + } + + for (l_mask = 0x8000; + l_mask > 0; + l_mask >>= 1) + { + if (pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit * 2]] + & l_mask) + { + // Turn off a bit that should be on + pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit * 2]] + &= ~l_mask; + } + else + { + // Turn on a bit that should be off + pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit * 2]] + |= l_mask; + } + + if (isDescFunctional(pDesc, pgData)) + { + TS_FAIL("testHWASisDescFunctional>" + "functional = 0x%x, should be false, " + "MC%s for MC%d = 0x%04x, " + "mask = 0x%04x.", + isDescFunctional(pDesc, pgData), + l_chipUnit ? "01" : "23", + l_chipUnit, + pgData[VPD_CP00_PG_MCxx_INDEX + [l_chipUnit * 2]], + l_mask); + } + + // Restore the "all good" data + pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit * 2]] = + (uint16_t)VPD_CP00_PG_MCxx_GOOD; + } + + break; + + case TYPE_MI: + TS_INFO( "testHWASisDescFunctional: " + "MI%d is not functional", l_chipUnit); + if (l_chipUnit / 2) + { + pgData[VPD_CP00_PG_N1_INDEX] |= + (uint16_t)VPD_CP00_PG_N1_MCS23; + } + else + { + pgData[VPD_CP00_PG_N3_INDEX] |= + (uint16_t)VPD_CP00_PG_N3_MCS01; + } + + if (isDescFunctional(pDesc, pgData)) + { + TS_FAIL("testHWASisDescFunctional>" + "functional = 0x%x, should be false, " + "N1/N3 for MI%d = 0x%04x.", + isDescFunctional(pDesc, pgData), + l_chipUnit, + (l_chipUnit / 2) + ? pgData[VPD_CP00_PG_N1_INDEX] + : pgData[VPD_CP00_PG_N3_INDEX]); + } + + if (l_chipUnit / 2) + { + pgData[VPD_CP00_PG_N1_INDEX] = + (uint16_t)VPD_CP00_PG_N1_GOOD; + } + else + { + pgData[VPD_CP00_PG_N3_INDEX] = + (uint16_t)VPD_CP00_PG_N3_GOOD; + } + + for (l_mask = 0x8000; + l_mask > 0; + l_mask >>= 1) + { + if (pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit]] + & l_mask) + { + // Turn off a bit that should be on + pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit]] + &= ~l_mask; + } + else + { + // Turn on a bit that should be off + pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit]] + |= l_mask; + } + + if (isDescFunctional(pDesc, pgData)) + { + TS_FAIL("testHWASisDescFunctional>" + "functional = 0x%x, should be false, " + "MC%s for MI%d = 0x%04x, " + "mask = 0x%04x.", + isDescFunctional(pDesc, pgData), + (l_chipUnit / 2) ? "01" : "23", + l_chipUnit, + pgData[VPD_CP00_PG_MCxx_INDEX + [l_chipUnit]], + l_mask); + } + + // Restore the "all good" data + pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit]] = + (uint16_t)VPD_CP00_PG_MCxx_GOOD; + } + + break; + + case TYPE_DMI: + TS_INFO( "testHWASisDescFunctional: " + "DMI%d is not functional", l_chipUnit); + if (l_chipUnit / 4) + { + pgData[VPD_CP00_PG_N1_INDEX] |= + (uint16_t)VPD_CP00_PG_N1_MCS23; + } + else + { + pgData[VPD_CP00_PG_N3_INDEX] |= + (uint16_t)VPD_CP00_PG_N3_MCS01; + } + + if (isDescFunctional(pDesc, pgData)) + { + TS_FAIL("testHWASisDescFunctional>" + "functional = 0x%x, should be false, " + "N1/N3 for DMI%d = 0x%04x.", + isDescFunctional(pDesc, pgData), + l_chipUnit, + (l_chipUnit / 4) + ? pgData[VPD_CP00_PG_N1_INDEX] + : pgData[VPD_CP00_PG_N3_INDEX]); + } + + if (l_chipUnit / 4) + { + pgData[VPD_CP00_PG_N1_INDEX] = + (uint16_t)VPD_CP00_PG_N1_GOOD; + } + else + { + pgData[VPD_CP00_PG_N3_INDEX] = + (uint16_t)VPD_CP00_PG_N3_GOOD; + } + + for (l_mask = 0x8000; + l_mask > 0; + l_mask >>= 1) + { + if (pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit / 2]] + & l_mask) + { + // Turn off a bit that should be on + pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit / 2]] + &= ~l_mask; + } + else + { + // Turn on a bit that should be off + pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit / 2]] + |= l_mask; + } + + if (isDescFunctional(pDesc, pgData)) + { + TS_FAIL("testHWASisDescFunctional>" + "functional = 0x%x, should be false, " + "MC%s for DMI%d = 0x%04x, " + "mask = 0x%04x.", + isDescFunctional(pDesc, pgData), + (l_chipUnit / 4) ? "01" : "23", + l_chipUnit, + pgData[VPD_CP00_PG_MCxx_INDEX + [l_chipUnit / 2]], + l_mask); + } + + // Restore the "all good" data + pgData[VPD_CP00_PG_MCxx_INDEX[l_chipUnit / 2]] = + (uint16_t)VPD_CP00_PG_MCxx_GOOD; + } + + break; + + case TYPE_OBUS_BRICK: { //Two cases here: //OBRICK==SMP --> Target should be present regardless of PG |