diff options
-rw-r--r-- | src/usr/diag/prdf/common/plat/p9/p9_eq_regs.rule | 38 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/p9/p9_mca_regs.rule | 18 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/p9/p9_nimbus.rule | 4 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/p9/p9_nimbus_actions.rule | 23 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/p9/p9_nimbus_regs.rule | 16 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/p9/p9_obus_regs.rule | 38 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/p9/p9_pec_regs.rule | 38 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/p9/p9_xbus_regs.rule | 46 | ||||
-rw-r--r--[-rwxr-xr-x] | src/usr/diag/prdf/common/plat/p9/prdfP9Pll.C | 428 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/p9/prdfP9Pll.H | 46 | ||||
-rw-r--r--[-rwxr-xr-x] | src/usr/diag/prdf/common/plat/p9/prdfP9PllDomain.C | 237 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/prdfPllDomain.H | 6 | ||||
-rwxr-xr-x | src/usr/diag/prdf/common/rule/prdrExpr.H | 12 |
13 files changed, 844 insertions, 106 deletions
diff --git a/src/usr/diag/prdf/common/plat/p9/p9_eq_regs.rule b/src/usr/diag/prdf/common/plat/p9/p9_eq_regs.rule new file mode 100644 index 000000000..49a9ce5a1 --- /dev/null +++ b/src/usr/diag/prdf/common/plat/p9/p9_eq_regs.rule @@ -0,0 +1,38 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/diag/prdf/common/plat/p9/p9_eq_regs.rule $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016,2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + register EQ_ERROR_REG + { + name "EQ PCB Slave error reg"; + scomaddr 0x130F001F; + capture group PllFIRs; + }; + + register EQ_CONFIG_REG + { + name "EQ PCB Slave config reg"; + scomaddr 0x130F001E; + capture group PllFIRs; + }; + diff --git a/src/usr/diag/prdf/common/plat/p9/p9_mca_regs.rule b/src/usr/diag/prdf/common/plat/p9/p9_mca_regs.rule index 82c4163de..0317b5914 100644 --- a/src/usr/diag/prdf/common/plat/p9/p9_mca_regs.rule +++ b/src/usr/diag/prdf/common/plat/p9/p9_mca_regs.rule @@ -155,3 +155,21 @@ scomaddr 0x07010A1F; capture group default; }; + + ############################################################################ + # PCB Slave Error Regs + ############################################################################ + + register MC_ERROR_REG + { + name "MC PCB Slave error reg"; + scomaddr 0x070F001F; + capture group PllFIRs; + }; + + register MC_CONFIG_REG + { + name "MC PCB Slave config reg"; + scomaddr 0x070F001E; + capture group PllFIRs; + }; diff --git a/src/usr/diag/prdf/common/plat/p9/p9_nimbus.rule b/src/usr/diag/prdf/common/plat/p9/p9_nimbus.rule index 86f680bd0..419ac484c 100644 --- a/src/usr/diag/prdf/common/plat/p9/p9_nimbus.rule +++ b/src/usr/diag/prdf/common/plat/p9/p9_nimbus.rule @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2016 +# Contributors Listed Below - COPYRIGHT 2016,2017 # [+] International Business Machines Corp. # # @@ -2126,7 +2126,7 @@ group gTP_LFIR filter singlebit /** TP_LFIR[21] * local errors from PORT2 ( error) */ - (rTP_LFIR, bit(21)) ? defaultMaskedError; + (rTP_LFIR, bit(21)) ? PcbSlaveInternalParity; /** TP_LFIR[22] * FIR error from SBE diff --git a/src/usr/diag/prdf/common/plat/p9/p9_nimbus_actions.rule b/src/usr/diag/prdf/common/plat/p9/p9_nimbus_actions.rule index 900f66bde..190bbc944 100644 --- a/src/usr/diag/prdf/common/plat/p9/p9_nimbus_actions.rule +++ b/src/usr/diag/prdf/common/plat/p9/p9_nimbus_actions.rule @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2016 +# Contributors Listed Below - COPYRIGHT 2016,2017 # [+] International Business Machines Corp. # # @@ -29,3 +29,24 @@ actionclass level2_M_self_L_th_32perDay threshold32pday; }; +/** PLL Threshold of 2 per 5 mins */ +actionclass thresholdPll +{ + threshold( field(2 / 5 min) ); +}; + +# This action is for the case where TP_LFIR[21] comes on +# but PLL code does not isolate to any PLL errors. The +# threshold is the same as PLL one 2 per 5 mins with +# callout/gard the chip at threshold along with PLL scom +# data captured. +/** PCB Slave Internal parity error action */ +actionclass PcbSlaveInternalParity +{ + capture(PllFIRs); + calloutSelfHigh; + thresholdPll; + funccall("capturePllFfdc"); + funccall("clearParityError"); +}; + diff --git a/src/usr/diag/prdf/common/plat/p9/p9_nimbus_regs.rule b/src/usr/diag/prdf/common/plat/p9/p9_nimbus_regs.rule index d1a9bfc7c..f15925bc4 100644 --- a/src/usr/diag/prdf/common/plat/p9/p9_nimbus_regs.rule +++ b/src/usr/diag/prdf/common/plat/p9/p9_nimbus_regs.rule @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2016 +# Contributors Listed Below - COPYRIGHT 2016,2017 # [+] International Business Machines Corp. # # @@ -67,3 +67,17 @@ scomaddr 0x00040020; capture group default; }; + + register TP_ERROR_REG + { + name "TP PCB Slave error reg"; + scomaddr 0x010F001F; + capture group PllFIRs; + }; + + register TP_CONFIG_REG + { + name "TP PCB Slave config reg"; + scomaddr 0x010F001E; + capture group PllFIRs; + }; diff --git a/src/usr/diag/prdf/common/plat/p9/p9_obus_regs.rule b/src/usr/diag/prdf/common/plat/p9/p9_obus_regs.rule new file mode 100644 index 000000000..217530f07 --- /dev/null +++ b/src/usr/diag/prdf/common/plat/p9/p9_obus_regs.rule @@ -0,0 +1,38 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/diag/prdf/common/plat/p9/p9_obus_regs.rule $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016,2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + register OBUS_ERROR_REG + { + name "OBUS PCB Slave error reg"; + scomaddr 0x090F001F; + capture group PllFIRs; + }; + + register OBUS_CONFIG_REG + { + name "OBUS PCB Slave config reg"; + scomaddr 0x090F001E; + capture group PllFIRs; + }; + diff --git a/src/usr/diag/prdf/common/plat/p9/p9_pec_regs.rule b/src/usr/diag/prdf/common/plat/p9/p9_pec_regs.rule new file mode 100644 index 000000000..29093f11f --- /dev/null +++ b/src/usr/diag/prdf/common/plat/p9/p9_pec_regs.rule @@ -0,0 +1,38 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/diag/prdf/common/plat/p9/p9_pec_regs.rule $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016,2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + register PCI_ERROR_REG + { + name "PCI PCB Slave error reg"; + scomaddr 0x0D0F001F; + capture group PllFIRs; + }; + + register PCI_CONFIG_REG + { + name "PCI PCB Slave config reg"; + scomaddr 0x0D0F001E; + capture group PllFIRs; + }; + diff --git a/src/usr/diag/prdf/common/plat/p9/p9_xbus_regs.rule b/src/usr/diag/prdf/common/plat/p9/p9_xbus_regs.rule new file mode 100644 index 000000000..d9e16d3ef --- /dev/null +++ b/src/usr/diag/prdf/common/plat/p9/p9_xbus_regs.rule @@ -0,0 +1,46 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/diag/prdf/common/plat/p9/p9_xbus_regs.rule $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2016,2017 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG +############################################################################### +# Additional registers for XBUS, not defined in XML +############################################################################### + + ########################################################################### + # XBUS Chiplet PLL Registers + ########################################################################### + + register XBUS_ERROR_REG + { + name "XBUS PCB Slave error reg"; + scomaddr 0x060F001F; + capture group PllFIRs; + }; + + register XBUS_CONFIG_REG + { + name "XBUS PCB Slave config reg"; + scomaddr 0x060F001E; + capture group PllFIRs; + }; + diff --git a/src/usr/diag/prdf/common/plat/p9/prdfP9Pll.C b/src/usr/diag/prdf/common/plat/p9/prdfP9Pll.C index 0d2cce7c3..9b85be962 100755..100644 --- a/src/usr/diag/prdf/common/plat/p9/prdfP9Pll.C +++ b/src/usr/diag/prdf/common/plat/p9/prdfP9Pll.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -39,6 +39,7 @@ #include <prdfGlobal_common.H> #include <UtilHash.H> #include <prdfFsiCapUtil.H> +#include <prdfP9Pll.H> using namespace TARGETING; @@ -46,6 +47,7 @@ namespace PRDF { using namespace PlatServices; +using namespace PLL; namespace Proc { @@ -58,20 +60,262 @@ enum OSC_SW_MF_REF = 37, }; +void ClearChipletParityError(ExtensibleChip * i_chip, + TARGETING::TYPE i_chpltType) +{ + #define PRDF_FUNC "[Proc::ClearChipletParityError ]" + + int32_t rc = SUCCESS; + const char * errRegStr = NULL; + + switch (i_chpltType) + { + case TYPE_PROC: + errRegStr = "TP_ERROR_REG"; + break; + case TYPE_OBUS: + errRegStr = "OBUS_ERROR_REG"; + break; + case TYPE_XBUS: + errRegStr = "XBUS_ERROR_REG"; + break; + case TYPE_PEC: + errRegStr = "PCI_ERROR_REG"; + break; + case TYPE_MCA: + errRegStr = "MC_ERROR_REG"; + break; + case TYPE_EQ: + errRegStr = "EQ_ERROR_REG"; + break; + case TYPE_CORE: + errRegStr = "EC_ERROR_REG"; + break; + default: + // Unexpected chiplet type, just return + PRDF_ERR(PRDF_FUNC "Unexpected chiplet type %x for for 0x%08x", + i_chpltType, i_chip->getHuid()); + return; + } + + ExtensibleChipList chpltList = + PlatServices::getConnected(i_chip, i_chpltType); + + for ( auto chplt : chpltList ) + { + SCAN_COMM_REGISTER_CLASS * errReg = chplt->getRegister(errRegStr); + + errReg->setAllBits(); + rc = errReg->Write(); + if (rc != SUCCESS) + { + PRDF_ERR(PRDF_FUNC "%s write failed for 0x%08x", + errRegStr, chplt->getHuid()); + continue; + } + } + #undef PRDF_FUNC +} + +void ClearChipletPll(ExtensibleChip * i_chip, TARGETING::TYPE i_chpltType) +{ + #define PRDF_FUNC "[Proc::ClearChipletPll] " + + int32_t rc = SUCCESS; + const char * errRegStr = NULL; + + switch (i_chpltType) + { + case TYPE_PROC: + errRegStr = "TP_ERROR_REG"; + break; + case TYPE_OBUS: + errRegStr = "OBUS_ERROR_REG"; + break; + case TYPE_XBUS: + errRegStr = "XBUS_ERROR_REG"; + break; + case TYPE_PEC: + errRegStr = "PCI_ERROR_REG"; + break; + case TYPE_MCA: + errRegStr = "MC_ERROR_REG"; + break; + default: + // Unexpected chiplet type, just return + PRDF_ERR(PRDF_FUNC "Unexpected chiplet type %x for for 0x%08x", + i_chpltType, i_chip->getHuid()); + return; + } + + ExtensibleChipList chpltList = + PlatServices::getConnected(i_chip, i_chpltType); + + for ( auto chplt : chpltList ) + { + SCAN_COMM_REGISTER_CLASS * errReg = chplt->getRegister(errRegStr); + + rc = errReg->ForceRead(); + + if (rc != SUCCESS) + { + PRDF_ERR(PRDF_FUNC "%s read failed for 0x%08x", + errRegStr, chplt->getHuid()); + continue; + } + + // Clear PLL error bits by writing 1's + errReg->SetBitFieldJustified(25, 4, 0xF); + rc = errReg->Write(); + if (rc != SUCCESS) + { + PRDF_ERR(PRDF_FUNC "%s write failed for 0x%08x", + errRegStr, chplt->getHuid()); + continue; + } + + } + + #undef PRDF_FUNC +} + +void MaskChipletPll(ExtensibleChip * i_chip, TARGETING::TYPE i_chpltType) +{ + #define PRDF_FUNC "[Proc::MaskChipletPll] " + + int32_t rc = SUCCESS; + const char * cfgRegStr = NULL; + + switch (i_chpltType) + { + case TYPE_PROC: + cfgRegStr = "TP_CONFIG_REG"; + break; + case TYPE_OBUS: + cfgRegStr = "OBUS_CONFIG_REG"; + break; + case TYPE_XBUS: + cfgRegStr = "XBUS_CONFIG_REG"; + break; + case TYPE_PEC: + cfgRegStr = "PCI_CONFIG_REG"; + break; + case TYPE_MCA: + cfgRegStr = "MC_CONFIG_REG"; + break; + default: + // Unexpected chiplet type, just return + PRDF_ERR(PRDF_FUNC "Unexpected chiplet type %x for for 0x%08x", + i_chpltType, i_chip->getHuid()); + return; + } + + ExtensibleChipList chpltList = + PlatServices::getConnected(i_chip, i_chpltType); + + for ( auto chplt : chpltList ) + { + SCAN_COMM_REGISTER_CLASS * cfgReg = chplt->getRegister(cfgRegStr); + rc = cfgReg->Read(); + + if (rc != SUCCESS) + { + PRDF_ERR(PRDF_FUNC "%s read failed for 0x%08x", chplt->getHuid()); + continue; + } + + cfgReg->SetBit(12); + rc = cfgReg->Write(); + if (rc != SUCCESS) + { + PRDF_ERR(PRDF_FUNC "%s write failed for 0x%08x", + cfgRegStr, chplt->getHuid()); + continue; + } + } + #undef PRDF_FUNC +} + +bool CheckChipletPll(ExtensibleChip * i_chip, TARGETING::TYPE i_chpltType) +{ + #define PRDF_FUNC "[Proc::CheckChipletPll] " + + int32_t rc = SUCCESS; + bool pllErrFound = false; + const char * errRegStr = NULL; + const char * cfgRegStr = NULL; + + switch (i_chpltType) + { + case TYPE_PROC: + errRegStr = "TP_ERROR_REG"; + cfgRegStr = "TP_CONFIG_REG"; + break; + case TYPE_OBUS: + errRegStr = "OBUS_ERROR_REG"; + cfgRegStr = "OBUS_CONFIG_REG"; + break; + case TYPE_XBUS: + errRegStr = "XBUS_ERROR_REG"; + cfgRegStr = "XBUS_CONFIG_REG"; + break; + case TYPE_PEC: + errRegStr = "PCI_ERROR_REG"; + cfgRegStr = "PCI_CONFIG_REG"; + break; + case TYPE_MCA: + errRegStr = "MC_ERROR_REG"; + cfgRegStr = "MC_CONFIG_REG"; + break; + default: + // Unexpected chiplet type, just return false + PRDF_ERR(PRDF_FUNC "Unexpected chiplet type %x for for 0x%08x", + i_chpltType, i_chip->getHuid()); + return false; + } + + ExtensibleChipList chpltList = + PlatServices::getConnected(i_chip, i_chpltType); + + for ( auto chplt : chpltList ) + { + SCAN_COMM_REGISTER_CLASS * errReg = chplt->getRegister(errRegStr); + SCAN_COMM_REGISTER_CLASS * cfgReg = chplt->getRegister(cfgRegStr); + + rc = errReg->ForceRead(); + rc |= cfgReg->Read(); + + if (rc != SUCCESS) + { + PRDF_ERR(PRDF_FUNC "%s read failed for 0x%08x", + errRegStr, chplt->getHuid()); + continue; + } + + // Check if chiplet is reporting a PLL unlock in bits 25-28 + if ((errReg->GetBitFieldJustified(25, 4) != 0) && + (! cfgReg->IsBitSet(12))) // And not masked + { + pllErrFound = true; + break; + } + } + + return pllErrFound; + #undef PRDF_FUNC +} + /** - * @brief Query the PLL chip for a PLL error on P9 - * @param i_chip P9 chip - * @param o_result set to true in the presence of PLL error - * @returns Failure or Success of query. - * @note - */ -int32_t QueryPll( ExtensibleChip * i_chip, - bool & o_result) + * @brief Examine chiplets to determine which type of PLL error has ocurred + * @param i_chip P9 chip + * @param o_errType enum indicating which type of PLL error is detected + * @returns Failure or Success + */ +int32_t CheckErrorType( ExtensibleChip * i_chip, uint32_t & o_errType ) { - #define PRDF_FUNC "[Proc::QueryPll] " + #define PRDF_FUNC "[Proc::CheckErrorType] " int32_t rc = SUCCESS; - o_result = false; SCAN_COMM_REGISTER_CLASS * TP_LFIR = i_chip->getRegister("TP_LFIR"); @@ -96,20 +340,104 @@ int32_t QueryPll( ExtensibleChip * i_chip, break; } - if ( ((! TP_LFIRmask->IsBitSet(PLL_UNLOCK)) && - TP_LFIR->IsBitSet(PLL_UNLOCK)) || - ((! TP_LFIRmask->IsBitSet(OSC_SW_SYS_REF)) && - TP_LFIR->IsBitSet(OSC_SW_SYS_REF)) || - ((! TP_LFIRmask->IsBitSet(OSC_SW_MF_REF)) && - TP_LFIR->IsBitSet(OSC_SW_MF_REF)) ) + if ((! TP_LFIRmask->IsBitSet(OSC_SW_SYS_REF)) && + TP_LFIR->IsBitSet(OSC_SW_SYS_REF)) + { + o_errType |= SYS_OSC_FAILOVER; + } + if ((! TP_LFIRmask->IsBitSet(OSC_SW_MF_REF)) && + TP_LFIR->IsBitSet(OSC_SW_MF_REF)) { - o_result = true; + o_errType |= PCI_OSC_FAILOVER; } - } while(0); + if ((! TP_LFIRmask->IsBitSet(PLL_UNLOCK)) && + TP_LFIR->IsBitSet(PLL_UNLOCK)) + { + // Check TP, XBUS, OBUS and MC Chiplets for sys ref unlock + if (CheckChipletPll(i_chip, TYPE_PROC) || + CheckChipletPll(i_chip, TYPE_XBUS) || + CheckChipletPll(i_chip, TYPE_OBUS) || + CheckChipletPll(i_chip, TYPE_MCA)) + { + o_errType |= SYS_PLL_UNLOCK; + } + + // Check PCIE chiplet for MF ref unlock + if (CheckChipletPll(i_chip, TYPE_PEC)) + { + o_errType |= PCI_PLL_UNLOCK; + } + } + } while (0); + + return rc; + + #undef PRDF_FUNC +} +PRDF_PLUGIN_DEFINE_NS( p9_nimbus, Proc, CheckErrorType ); - if( rc != SUCCESS ) +/** + * @brief Clear Chiplet PCB slave reg parity errors + * @param i_chip P9 chip + * @returns Failure or Success + */ +int32_t clearParityError( ExtensibleChip * i_chip) +{ + #define PRDF_FUNC "[Proc::clearParityError] " + int32_t rc = SUCCESS; + + // Clear Chiplet parity error bits + ClearChipletParityError(i_chip, TYPE_PROC); + ClearChipletParityError(i_chip, TYPE_XBUS); + ClearChipletParityError(i_chip, TYPE_OBUS); + ClearChipletParityError(i_chip, TYPE_MCA); + ClearChipletParityError(i_chip, TYPE_PEC); + ClearChipletParityError(i_chip, TYPE_EQ); + ClearChipletParityError(i_chip, TYPE_CORE); + + // Clear TPLFIR[21] + SCAN_COMM_REGISTER_CLASS * TP_LFIR_and = + i_chip->getRegister("TP_LFIR_AND"); + TP_LFIR_and->setAllBits(); + TP_LFIR_and->ClearBit(PLL_UNLOCK); + rc = TP_LFIR_and->Write(); + if (rc != SUCCESS) + { + PRDF_ERR(PRDF_FUNC "TP_LFIR_AND write failed" + "for 0x%08x", i_chip->GetId()); + } + + return rc; + #undef PRDF_FUNC +} +PRDF_PLUGIN_DEFINE_NS( p9_nimbus, Proc, clearParityError ); + +/** + * @brief Query the PLL chip for a PLL error on P9 + * @param i_chip P9 chip + * @param o_result set to true in the presence of PLL error + * @returns Failure or Success of query. + * @note + */ +int32_t QueryPll( ExtensibleChip * i_chip, + bool & o_result) +{ + #define PRDF_FUNC "[Proc::QueryPll] " + + int32_t rc = SUCCESS; + o_result = false; + + uint32_t errType = 0; + + rc = CheckErrorType(i_chip, errType); + + if (rc == SUCCESS) + { + o_result = (errType != 0); + } + else { PRDF_ERR(PRDF_FUNC "failed for proc: 0x%.8X", i_chip->getHuid()); @@ -136,6 +464,13 @@ int32_t ClearPll( ExtensibleChip * i_chip, if (CHECK_STOP != i_sc.service_data->getPrimaryAttnType()) { + // Clear Pll bits in chiplet PCB Slave error regs + ClearChipletPll(i_chip, TYPE_PROC); + ClearChipletPll(i_chip, TYPE_XBUS); + ClearChipletPll(i_chip, TYPE_OBUS); + ClearChipletPll(i_chip, TYPE_MCA); + ClearChipletPll(i_chip, TYPE_PEC); + // Clear TP_LFIR SCAN_COMM_REGISTER_CLASS * TP_LFIRand = i_chip->getRegister("TP_LFIR_AND"); @@ -166,21 +501,50 @@ PRDF_PLUGIN_DEFINE_NS( p9_nimbus, Proc, ClearPll ); * @note */ int32_t MaskPll( ExtensibleChip * i_chip, - STEP_CODE_DATA_STRUCT & i_sc ) + STEP_CODE_DATA_STRUCT & i_sc, + uint32_t i_errType ) { int32_t rc = SUCCESS; - SCAN_COMM_REGISTER_CLASS * tpmask_or = - i_chip->getRegister("TP_LFIR_MASK_OR"); - tpmask_or->clearAllBits(); - tpmask_or->SetBit(PLL_UNLOCK); - tpmask_or->SetBit(OSC_SW_SYS_REF); - tpmask_or->SetBit(OSC_SW_MF_REF); - - rc = tpmask_or->Write(); - if (rc != SUCCESS) + + if (SYS_PLL_UNLOCK & i_errType) + { + MaskChipletPll(i_chip, TYPE_PROC); + MaskChipletPll(i_chip, TYPE_XBUS); + MaskChipletPll(i_chip, TYPE_OBUS); + MaskChipletPll(i_chip, TYPE_MCA); + } + + if (PCI_PLL_UNLOCK & i_errType) + { + MaskChipletPll(i_chip, TYPE_PEC); + } + + if (SYS_OSC_FAILOVER & i_errType) { - PRDF_ERR("[Proc::MaskPll] TP_LFIR_AND write failed" - "for chip: 0x%08x", i_chip->getHuid()); + SCAN_COMM_REGISTER_CLASS * tpmask_or = + i_chip->getRegister("TP_LFIR_MASK_OR"); + tpmask_or->clearAllBits(); + tpmask_or->SetBit(OSC_SW_SYS_REF); + rc = tpmask_or->Write(); + if (rc != SUCCESS) + { + PRDF_ERR("[Proc::MaskPll] TP_LFIR_MSK write failed" + "for chip: 0x%08x", i_chip->getHuid()); + } + } + + if (PCI_OSC_FAILOVER & i_errType) + { + SCAN_COMM_REGISTER_CLASS * tpmask_or = + i_chip->getRegister("TP_LFIR_MASK_OR"); + tpmask_or->clearAllBits(); + tpmask_or->SetBit(OSC_SW_MF_REF); + rc = tpmask_or->Write(); + if (rc != SUCCESS) + { + PRDF_ERR("[Proc::MaskPll] TP_LFIR_MSK write failed" + "for chip: 0x%08x", i_chip->getHuid()); + } } return rc; diff --git a/src/usr/diag/prdf/common/plat/p9/prdfP9Pll.H b/src/usr/diag/prdf/common/plat/p9/prdfP9Pll.H new file mode 100644 index 000000000..baca4875a --- /dev/null +++ b/src/usr/diag/prdf/common/plat/p9/prdfP9Pll.H @@ -0,0 +1,46 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/common/plat/p9/prdfP9Pll.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __prdfP9Pll_H +#define __prdfP9Pll_H + +namespace PRDF +{ +namespace PLL +{ + +typedef enum +{ + SYS_PLL_UNLOCK = 0x01, + PCI_PLL_UNLOCK = 0x02, + SYS_OSC_FAILOVER = 0x04, + PCI_OSC_FAILOVER = 0x08, +} PllErrorType; + +} // end namespace PLL +} // end namespace PRDF + + +#endif // __prdfP9Pll_H + diff --git a/src/usr/diag/prdf/common/plat/p9/prdfP9PllDomain.C b/src/usr/diag/prdf/common/plat/p9/prdfP9PllDomain.C index 58599f483..86504c871 100755..100644 --- a/src/usr/diag/prdf/common/plat/p9/prdfP9PllDomain.C +++ b/src/usr/diag/prdf/common/plat/p9/prdfP9PllDomain.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,6 +40,7 @@ #include <prdfGlobal.H> #include <iipSystem.h> #include <UtilHash.H> +#include <prdfP9Pll.H> #include <prdfP9ProcMbCommonExtraSig.H> @@ -49,6 +50,7 @@ namespace PRDF { using namespace PlatServices; +using namespace PLL; //------------------------------------------------------------------------------ @@ -82,8 +84,11 @@ bool PllDomain::Query(ATTENTION_TYPE attentionType) { ExtensibleChipFunction * l_query = l_chip->getExtensibleFunction("QueryPll"); - int32_t rc = (*l_query)(l_chip,PluginDef::bindParm<bool &>(atAttn)); - // if rc then scom read failed - Error log has already been generated + int32_t rc = (*l_query) + (l_chip,PluginDef::bindParm<bool &>(atAttn)); + + // if rc then scom read failed + // Error log has already been generated if( PRD_POWER_FAULT == rc ) { PRDF_ERR( "prdfPllDomain::Query() Power Fault detected!" ); @@ -106,31 +111,40 @@ int32_t PllDomain::Analyze(STEP_CODE_DATA_STRUCT & serviceData, ATTENTION_TYPE attentionType) { #define PRDF_FUNC "[PllDomain::Analyze] " - typedef ExtensibleChip * ChipPtr; - CcAutoDeletePointerVector<ChipPtr> chip(new ChipPtr[GetSize()]()); - int count = 0; + std::vector<ExtensibleChip *> sysRefList; + std::vector<ExtensibleChip *> pciList; + std::vector<ExtensibleChip *> mfFoList; + std::vector<ExtensibleChip *> sysRefFoList; int32_t rc = SUCCESS; + uint32_t mskErrType = 0; // Due to clock issues some chips may be moved to non-functional during // analysis. In this case, these chips will need to be removed from their // domains. - typedef std::vector<ExtensibleChip *> NonFuncChips; - NonFuncChips nfchips; + std::vector<ExtensibleChip *> nfchips; - // Count # of chips that had PLL error + // Examine each chip in domain for(unsigned int index = 0; index < GetSize(); ++index) { + uint32_t l_errType = 0; + ExtensibleChip * l_chip = LookUp(index); - bool atAttn = false; + // Check if this chip has a clock error ExtensibleChipFunction * l_query = - l_chip->getExtensibleFunction("QueryPll"); - rc |= (*l_query)(l_chip,PluginDef::bindParm<bool &>(atAttn)); + l_chip->getExtensibleFunction("CheckErrorType"); + rc |= (*l_query)(l_chip, + PluginDef::bindParm<uint32_t &> (l_errType)); - if ( atAttn ) + if ( !PlatServices::isFunctional(l_chip->getTrgt()) ) + { + // The chip is now non-functional. + nfchips.push_back( l_chip ); + } + + // Get this chip's capture data for any error + if (0 != l_errType) { - chip()[count] = LookUp(index); - ++count; l_chip->CaptureErrorData( serviceData.service_data->GetCaptureData()); // Capture PllFIRs group @@ -146,21 +160,30 @@ int32_t PllDomain::Analyze(STEP_CODE_DATA_STRUCT & serviceData, (*l_captureFfdc)( l_chip, PluginDef::bindParm<STEP_CODE_DATA_STRUCT &>(serviceData) ); } - - } - else if ( !PlatServices::isFunctional(l_chip->getTrgt()) ) - { - // The chip is now non-functional. - nfchips.push_back( l_chip ); } - } + + // Update error lists + if (l_errType & SYS_PLL_UNLOCK) + sysRefList.push_back( l_chip ); + if (l_errType & PCI_PLL_UNLOCK) + pciList.push_back( l_chip ); + if (l_errType & SYS_OSC_FAILOVER) + mfFoList.push_back( l_chip ); + if (l_errType & PCI_OSC_FAILOVER) + sysRefFoList.push_back( l_chip ); + + + } // end for each chip in domain // Remove all non-functional chips. - for ( NonFuncChips::iterator i = nfchips.begin(); i != nfchips.end(); i++ ) + for ( auto i : nfchips ) { - systemPtr->RemoveStoppedChips( (*i)->getTrgt() ); + systemPtr->RemoveStoppedChips( i->getTrgt() ); } + // TODO: RTC 155673 - use attributes to callout active clock sources + // For Nimbus sys ref and mf ref clock source is the same + // always suspect the clock source closeClockSource.Resolve(serviceData); if(&closeClockSource != &farClockSource) @@ -168,59 +191,142 @@ int32_t PllDomain::Analyze(STEP_CODE_DATA_STRUCT & serviceData, farClockSource.Resolve(serviceData); } - const uint32_t tmpCount = serviceData.service_data->getMruListSize(); + if (sysRefList.size() > 0 || pciList.size() > 0) + { + iv_threshold.Resolve(serviceData); + } - // If only one detected the error, add it to the callout list. - if ( 1 == count ) + if (sysRefList.size() > 0 ) { - // Call this chip's CalloutPll plugin if it exists. - ExtensibleChipFunction * l_callout = - chip()[0]->getExtensibleFunction( "CalloutPll", true ); - if ( NULL != l_callout ) + // Test for threshold + if(serviceData.service_data->IsAtThreshold()) { - (*l_callout)( chip()[0], - PluginDef::bindParm<STEP_CODE_DATA_STRUCT &>(serviceData) ); + mskErrType |= SYS_PLL_UNLOCK; } - // If CalloutPll plugin does not add anything new to the callout - // list, callout this chip - if ( tmpCount == serviceData.service_data->getMruListSize() ) + // Set Signature + serviceData.service_data->GetErrorSignature()-> + setChipId(sysRefList[0]->getHuid()); + serviceData.service_data->SetErrorSig( PRDFSIG_PLL_ERROR ); + + // If only one detected sys ref error, add it to the callout list. + if (sysRefList.size() == 1) { - // No additional callouts were made so add this chip to the list. - serviceData.service_data->SetCallout( chip()[0]->getTrgt()); + const uint32_t tmpCount = + serviceData.service_data->getMruListSize(); + + // Call this chip's CalloutPll plugin if it exists. + ExtensibleChipFunction * l_callout = + sysRefList[0]->getExtensibleFunction( "CalloutPll", true ); + if ( NULL != l_callout ) + { + (*l_callout)( sysRefList[0], + PluginDef::bindParm<STEP_CODE_DATA_STRUCT &>(serviceData) ); + } + + // If CalloutPll plugin does not add anything new to the callout + // list, callout this chip + if ( tmpCount == serviceData.service_data->getMruListSize() ) + { + // No additional callouts were made so add this chip to the list + serviceData.service_data->SetCallout( sysRefList[0]->getTrgt()); + } } } - iv_threshold.Resolve(serviceData); + if (pciList.size() > 0) + { + // Test for threshold + if(serviceData.service_data->IsAtThreshold()) + { + mskErrType |= PCI_PLL_UNLOCK; + } + + // Set Signature + serviceData.service_data->GetErrorSignature()-> + setChipId(pciList[0]->getHuid()); + serviceData.service_data->SetErrorSig( PRDFSIG_PLL_ERROR ); + + // If only one detected sys ref error, add it to the callout list. + if (pciList.size() == 1) + { + const uint32_t tmpCount = + serviceData.service_data->getMruListSize(); + + // Call this chip's CalloutPll plugin if it exists. + ExtensibleChipFunction * l_callout = + pciList[0]->getExtensibleFunction( "CalloutPll", true ); + if ( NULL != l_callout ) + { + (*l_callout)( pciList[0], + PluginDef::bindParm<STEP_CODE_DATA_STRUCT &>(serviceData) ); + } - // Test for threshold - if(serviceData.service_data->IsAtThreshold()) + // If CalloutPll plugin does not add anything new to the callout + // list, callout this chip + if ( tmpCount == serviceData.service_data->getMruListSize() ) + { + // No additional callouts were made so add this chip to the list + serviceData.service_data->SetCallout( sysRefList[0]->getTrgt()); + } + } + + } + + // TODO: RTC 155673 - Handle redundant Osc failovers + // Shouldn't see these on nimbus + if (mfFoList.size() > 0) + { + PRDF_ERR( PRDF_FUNC "Unexpected PCI osc failover detected" ); + mskErrType |= PCI_OSC_FAILOVER; + serviceData.service_data->SetCallout( NextLevelSupport_ENUM, MRU_LOW ); + } + if (sysRefFoList.size() > 0) + { + PRDF_ERR( PRDF_FUNC "Unexpected Sys osc failover detected" ); + mskErrType |= SYS_OSC_FAILOVER; + serviceData.service_data->SetCallout( NextLevelSupport_ENUM, MRU_LOW ); + } + + if (serviceData.service_data->IsAtThreshold()) { - // Mask in all chips in domain + // Mask appropriate errors on all chips in domain ExtensibleDomainFunction * l_mask = getExtensibleFunction("MaskPll"); (*l_mask)(this, - PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(serviceData)); + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&, uint32_t> + (serviceData, mskErrType)); + } + + // Run PLL Post Analysis on any analyzed chips in this domain. + for(auto l_chip : sysRefList) + { + // Send any special messages indicating there was a PLL error. + ExtensibleChipFunction * l_pllPostAnalysis = + l_chip->getExtensibleFunction("PllPostAnalysis", true); + (*l_pllPostAnalysis)(l_chip, + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(serviceData)); + } + + for(auto l_chip : pciList) + { + // Send any special messages indicating there was a PLL error. + ExtensibleChipFunction * l_pllPostAnalysis = + l_chip->getExtensibleFunction("PllPostAnalysis", true); + (*l_pllPostAnalysis)(l_chip, + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(serviceData)); + } + + for(auto l_chip : mfFoList) + { + // Send any special messages indicating there was a PLL error. + ExtensibleChipFunction * l_pllPostAnalysis = + l_chip->getExtensibleFunction("PllPostAnalysis", true); + (*l_pllPostAnalysis)(l_chip, + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(serviceData)); } - // Set Signature - serviceData.service_data->GetErrorSignature()-> - setChipId(chip()[0]->getHuid()); - serviceData.service_data->SetErrorSig( PRDFSIG_PLL_ERROR ); - -#ifndef __HOSTBOOT_MODULE - // Set dump flag dg09a - serviceData.service_data->SetDump(iv_dumpContent,chip()[0]->getTrgt()); -#endif - - // Clear PLLs from this domain. - ExtensibleDomainFunction * l_clear = getExtensibleFunction("ClearPll"); - (*l_clear)(this, - PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(serviceData)); - - // Run any PLL Post Analysis functions from this domain. - for(int i = 0; i < count; i++) + for(auto l_chip : sysRefFoList) { - ExtensibleChip * l_chip = chip()[i]; // Send any special messages indicating there was a PLL error. ExtensibleChipFunction * l_pllPostAnalysis = l_chip->getExtensibleFunction("PllPostAnalysis", true); @@ -278,7 +384,8 @@ PRDF_PLUGIN_DEFINE( PllDomain, ClearPll ); //------------------------------------------------------------------------------ int32_t PllDomain::MaskPll( ExtensibleDomain * i_domain, - STEP_CODE_DATA_STRUCT & i_sc ) + STEP_CODE_DATA_STRUCT & i_sc, + uint32_t i_errType ) { PllDomain * l_domain = (PllDomain *) i_domain; @@ -289,7 +396,8 @@ int32_t PllDomain::MaskPll( ExtensibleDomain * i_domain, ExtensibleChipFunction * l_mask = l_chip->getExtensibleFunction("MaskPll"); (*l_mask)( l_chip, - PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(i_sc) ); + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&, uint32_t> + (i_sc, i_errType) ); } // Mask children domains. @@ -300,7 +408,8 @@ int32_t PllDomain::MaskPll( ExtensibleDomain * i_domain, ExtensibleDomainFunction * l_mask = (i->second)->getExtensibleFunction("MaskPll"); (*l_mask)( i->second, - PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(i_sc) ); + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&, uint32_t> + (i_sc, i_errType) ); } return SUCCESS; diff --git a/src/usr/diag/prdf/common/plat/prdfPllDomain.H b/src/usr/diag/prdf/common/plat/prdfPllDomain.H index 0deedf092..5948cc2e8 100644 --- a/src/usr/diag/prdf/common/plat/prdfPllDomain.H +++ b/src/usr/diag/prdf/common/plat/prdfPllDomain.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -139,10 +139,12 @@ class PllDomain : public RuleChipDomain, public ExtensibleDomain, * domain and its subdomains. * @param i_domain The target PLL domain. * @param i_sc The step code data struct. + * @param i_errType type of PLL error needing masking * @return SUCCESS */ static int32_t MaskPll( ExtensibleDomain * i_domain, - STEP_CODE_DATA_STRUCT & i_sc ); + STEP_CODE_DATA_STRUCT & i_sc, + uint32_t i_errType ); /** * @brief Domain level plugin function used to mask PLL attentions in a diff --git a/src/usr/diag/prdf/common/rule/prdrExpr.H b/src/usr/diag/prdf/common/rule/prdrExpr.H index 57a3d3ecc..09a0968ee 100755 --- a/src/usr/diag/prdf/common/rule/prdrExpr.H +++ b/src/usr/diag/prdf/common/rule/prdrExpr.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -299,7 +299,8 @@ class ExprOp1 : public Expr int output(FILE * i_file) { PRDR_FWRITE(&cv_op, 1, 1, i_file); - cv_arg->output(i_file); + if (NULL != cv_arg) + cv_arg->output(i_file); return 0; }; @@ -338,8 +339,10 @@ class ExprOp2 : public Expr int output(FILE * i_file) { PRDR_FWRITE(&cv_op, 1, 1, i_file); - cv_arg[0]->output(i_file); - cv_arg[1]->output(i_file); + if (NULL != cv_arg[0]) + cv_arg[0]->output(i_file); + if (NULL != cv_arg[1]) + cv_arg[1]->output(i_file); return 0; }; @@ -665,6 +668,7 @@ class ExprAct_Thresh : public Expr { cv_thresholdTime[0] = i_fieldTime; cv_thresholdTime[1] = i_mfgTime; + cv_3 = 0; }; int output(FILE * i_file) |