diff options
author | Chris Phan <cphan@us.ibm.com> | 2014-09-16 21:18:07 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2014-09-22 13:26:06 -0500 |
commit | fe787082ffbf72795dc3c58d09e0a7ed45600da2 (patch) | |
tree | ae18464ab2b6abc2b79dc25273bef0714812e88a /src | |
parent | 83e47c8df68c5736a8bb080d0a250df77c82f935 (diff) | |
download | talos-hostboot-fe787082ffbf72795dc3c58d09e0a7ed45600da2.tar.gz talos-hostboot-fe787082ffbf72795dc3c58d09e0a7ed45600da2.zip |
PRD: change osc callout and threshold design
Change-Id: Ib54734a1db5d17f4ea13ddd80f91fc4dae7aef3a
CQ: SW278778
Backport: release-fips820
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/13461
Tested-by: Jenkins Server
Reviewed-by: Prem Shanker Jha <premjha2@in.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Reviewed-by: Zane Shelley <zshelle@us.ibm.com>
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/13519
Diffstat (limited to 'src')
12 files changed, 458 insertions, 57 deletions
diff --git a/src/usr/diag/prdf/common/framework/config/prdfPllDomain.C b/src/usr/diag/prdf/common/framework/config/prdfPllDomain.C index 4afa855a2..5b87ca01c 100755 --- a/src/usr/diag/prdf/common/framework/config/prdfPllDomain.C +++ b/src/usr/diag/prdf/common/framework/config/prdfPllDomain.C @@ -142,9 +142,11 @@ bool PllDomain::Query(ATTENTION_TYPE attentionType) 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; + bool oscSource[2] = { false, false }; int32_t rc = SUCCESS; // Due to clock issues some chips may be moved to non-functional during @@ -182,6 +184,25 @@ int32_t PllDomain::Analyze(STEP_CODE_DATA_STRUCT & serviceData, (*l_captureFfdc)( l_chip, PluginDef::bindParm<STEP_CODE_DATA_STRUCT &>(serviceData) ); } + + // Only continue for pcie domain to get osc pos + if ( CLOCK_DOMAIN_IO != GetId() ) + { + break; + } + + // Figure out which pcie osc is active for this proc + uint32_t oscPos = getIoOscPos(l_chip, serviceData); + + if ( oscPos < MAX_PCIE_OSC_PER_NODE ) + { + oscSource[oscPos] = true; + } + else + { + PRDF_ERR(PRDF_FUNC"getOscPos returned error for chip: " + "0x%08x", l_chip->GetId()); + } } else if ( !PlatServices::isFunctional(l_chip->GetChipHandle()) ) { @@ -203,11 +224,17 @@ int32_t PllDomain::Analyze(STEP_CODE_DATA_STRUCT & serviceData, farClockSource.Resolve(serviceData); } + const uint32_t tmpCount = serviceData.service_data->getMruListSize(); + // If only one detected the error, add it to the callout list. - if ( 1 == count ) + // Or if multiple chips report errors but no callout for PCIe case. + // This could happen for PCIe PLL since pcie clock resolution defer + // the osc callout to PllPcie chip plugin. + if (( 1 == count ) || + (( 1 < count ) && + ( 0 == tmpCount ) && + ( CLOCK_DOMAIN_IO == GetId() ))) { - const uint32_t tmpCount = serviceData.service_data->getMruListSize(); - // Call this chip's CalloutPll plugin if it exists. ExtensibleChipFunction * l_callout = chip()[0]->getExtensibleFunction( CalloutPllFunc, true ); @@ -217,21 +244,88 @@ int32_t PllDomain::Analyze(STEP_CODE_DATA_STRUCT & serviceData, PluginDef::bindParm<STEP_CODE_DATA_STRUCT &>(serviceData) ); } - if ( tmpCount == serviceData.service_data->getMruListSize() ) + // If CalloutPll plugin does not add anything new to the callout + // or for pcie io domain and only 1 proc reports error, then + // call it out in addition to the pcie osc already called out in + // CalloutPllFunc plugin + if (( tmpCount == serviceData.service_data->getMruListSize() ) || + (( CLOCK_DOMAIN_IO == GetId() ) && ( 1 == count ))) { // No additional callouts were made so add this chip to the list. serviceData.service_data->SetCallout( chip()[0]->GetChipHandle()); } } - iv_threshold.Resolve(serviceData); + // PCIe domains uses two threshold resolutions one per osc + if ( CLOCK_DOMAIN_IO == GetId() ) + { + if ( true == oscSource[0] ) + { + iv_threshold.Resolve(serviceData); + } + + if ( true == oscSource[1] ) + { + iv_threshold2.Resolve(serviceData); + } + + if (( false == oscSource[0] ) && ( false == oscSource[1] )) + { + PRDF_ERR(PRDF_FUNC"can't threshold IO domain due to no available " + "pcie osc source - count:%d, chip 0x%08x", + count, chip()[0]->GetId()); + } + } + // Proc and mem domains only use one threshold resolution + else + { + iv_threshold.Resolve(serviceData); + } + // Test for threshold if(serviceData.service_data->IsAtThreshold()) { - // Mask in all chips in domain - ExtensibleDomainFunction * l_mask = getExtensibleFunction("MaskPll"); - (*l_mask)(this, + // Only mask chips connected to fault pcie osc + if ( CLOCK_DOMAIN_IO == GetId() ) + { + uint32_t oscPos = MAX_PCIE_OSC_PER_NODE; + if ( true == oscSource[0] ) + { + // Mask pcie pll error in chips connected to pcie osc-0 + oscPos = 0; + ExtensibleDomainFunction * l_mask = + getExtensibleFunction("MaskPllIo"); + (*l_mask)(this, + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&, uint32_t> + (serviceData, oscPos)); + } + + if ( true == oscSource[1] ) + { + // Mask pcie pll error in chips connected to pcie osc-1 + oscPos = 1; + ExtensibleDomainFunction * l_mask = + getExtensibleFunction("MaskPllIo"); + (*l_mask)(this, + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&, uint32_t> + (serviceData, oscPos)); + } + + if (( false == oscSource[0] ) && ( false == oscSource[1] )) + { + PRDF_ERR(PRDF_FUNC"can't mask pcie pll error due to no " + "available pcie osc source - count:%d, chip 0x%08x", + count, chip()[0]->GetId()); + } + } + else + { + // Mask in all chips in domain + ExtensibleDomainFunction * l_mask = + getExtensibleFunction("MaskPll"); + (*l_mask)(this, PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(serviceData)); + } } // Set Signature serviceData.service_data->GetErrorSignature()->setChipId(chip()[0]->GetId()); @@ -259,6 +353,8 @@ int32_t PllDomain::Analyze(STEP_CODE_DATA_STRUCT & serviceData, } return rc; + + #undef PRDF_FUNC } //------------------------------------------------------------------------------ @@ -314,18 +410,12 @@ int32_t PllDomain::MaskPll( ExtensibleDomain * i_domain, { PllDomain * l_domain = (PllDomain *) i_domain; - const char * maskPllFuncName = "MaskPll"; - if ( CLOCK_DOMAIN_IO == l_domain->GetId() ) - { - maskPllFuncName = "MaskPllIo"; - } - // Mask children chips. for ( uint32_t i = 0; i < l_domain->GetSize(); i++ ) { ExtensibleChip * l_chip = l_domain->LookUp(i); ExtensibleChipFunction * l_mask = - l_chip->getExtensibleFunction(maskPllFuncName); + l_chip->getExtensibleFunction("MaskPll"); (*l_mask)( l_chip, PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(i_sc) ); } @@ -347,5 +437,42 @@ PRDF_PLUGIN_DEFINE( PllDomain, MaskPll ); //------------------------------------------------------------------------------ +int32_t PllDomain::MaskPllIo( ExtensibleDomain * i_domain, + STEP_CODE_DATA_STRUCT & i_sc, + uint32_t i_oscPos ) +{ + PllDomain * l_domain = (PllDomain *) i_domain; + + // Mask children chips. + for ( uint32_t i = 0; i < l_domain->GetSize(); i++ ) + { + ExtensibleChip * l_chip = l_domain->LookUp(i); + ExtensibleChipFunction * l_mask = + l_chip->getExtensibleFunction("MaskPllIo"); + + // io pcie domain needs osc pos info + (*l_mask)( l_chip, + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&, uint32_t> + (i_sc, i_oscPos) ); + } + + // Mask children domains - not used in PCIe but leave it here for now + // This looks like a recursive call. It calls other domains of Mask. + ParentDomain<ExtensibleDomain>::iterator i; + for (i = l_domain->getBeginIterator(); i != l_domain->getEndIterator(); i++) + { + ExtensibleDomainFunction * l_mask = + (i->second)->getExtensibleFunction("MaskPll"); + (*l_mask)( i->second, + PluginDef::bindParm<STEP_CODE_DATA_STRUCT&>(i_sc) ); + } + + return SUCCESS; +} +PRDF_PLUGIN_DEFINE( PllDomain, MaskPllIo ); + + +//------------------------------------------------------------------------------ + } // end namespace PRDF diff --git a/src/usr/diag/prdf/common/framework/config/prdfPllDomain.H b/src/usr/diag/prdf/common/framework/config/prdfPllDomain.H index 77ba5d841..11fea8d71 100755 --- a/src/usr/diag/prdf/common/framework/config/prdfPllDomain.H +++ b/src/usr/diag/prdf/common/framework/config/prdfPllDomain.H @@ -144,6 +144,18 @@ class PllDomain : public RuleChipDomain, public ExtensibleDomain, static int32_t MaskPll( ExtensibleDomain * i_domain, STEP_CODE_DATA_STRUCT & i_sc ); + /** + * @brief Domain level plugin function used to mask PLL attentions in a + * domain and its subdomains. + * @param i_domain The target PLL domain. + * @param i_sc The step code data struct. + * @param i_oscPos osc position (only used by IO pcie domain) + * @return SUCCESS + */ + static int32_t MaskPllIo( ExtensibleDomain * i_domain, + STEP_CODE_DATA_STRUCT & i_sc, + uint32_t i_oscPos ); + protected: /** @@ -170,6 +182,12 @@ private: // Data Resolution & iv_threshold; + // This resolution is used for the 2nd pcie osc only + // since the redundant pcie oscs are at the node + // level and can dynamically switch or config + // during the IPL + Resolution & iv_threshold2; + #ifndef __HOSTBOOT_MODULE hwTableContent iv_dumpContent; #endif @@ -196,6 +214,9 @@ PllDomain::PllDomain( DOMAIN_ID domain_id, Resolution & clockSource, farClockSource(clockSource), iv_threshold( ResolutionFactory::Access().GetThresholdResolution( 1, ThresholdResolution::cv_pllDefault, + i_mfgThresh ) ), + iv_threshold2( ResolutionFactory::Access().GetThresholdResolution( 1, + ThresholdResolution::cv_pllDefault, i_mfgThresh ) ) { InitChipPluginFuncs(); @@ -211,6 +232,9 @@ PllDomain::PllDomain( DOMAIN_ID domain_id, Resolution & secondClockSource, farClockSource(clockSource), iv_threshold( ResolutionFactory::Access().GetThresholdResolution( 1, ThresholdResolution::cv_pllDefault, + i_mfgThresh ) ), + iv_threshold2( ResolutionFactory::Access().GetThresholdResolution( 1, + ThresholdResolution::cv_pllDefault, i_mfgThresh ) ) { InitChipPluginFuncs(); @@ -229,6 +253,9 @@ PllDomain::PllDomain( DOMAIN_ID domain_id, Resolution & clockSource, iv_threshold( ResolutionFactory::Access().GetThresholdResolution( 1, ThresholdResolution::cv_pllDefault, i_mfgThresh ) ), + iv_threshold2( ResolutionFactory::Access().GetThresholdResolution( 1, + ThresholdResolution::cv_pllDefault, + i_mfgThresh ) ), iv_dumpContent(i_hwdc) { InitChipPluginFuncs(); @@ -246,6 +273,9 @@ PllDomain::PllDomain( DOMAIN_ID domain_id, Resolution & secondClockSource, iv_threshold( ResolutionFactory::Access().GetThresholdResolution( 1, ThresholdResolution::cv_pllDefault, i_mfgThresh ) ), + iv_threshold2( ResolutionFactory::Access().GetThresholdResolution( 1, + ThresholdResolution::cv_pllDefault, + i_mfgThresh ) ), iv_dumpContent(i_hwdc) { InitChipPluginFuncs(); diff --git a/src/usr/diag/prdf/common/framework/resolution/prdfClockResolution.C b/src/usr/diag/prdf/common/framework/resolution/prdfClockResolution.C index 0bffe92c5..3ee6b3e4d 100755 --- a/src/usr/diag/prdf/common/framework/resolution/prdfClockResolution.C +++ b/src/usr/diag/prdf/common/framework/resolution/prdfClockResolution.C @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2001,2014 */ +/* Contributors Listed Below - COPYRIGHT 2012,2014 */ +/* [+] 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. */ @@ -45,15 +47,13 @@ int32_t ClockResolution::Resolve(STEP_CODE_DATA_STRUCT & serviceData) uint32_t l_rc = SUCCESS; // callout clock osc if ( (iv_targetType == TYPE_PROC) || - (iv_targetType == TYPE_PCI) || (iv_targetType == TYPE_MEMBUF) ) { - // Get clock card. - TYPE oscType = (iv_targetType == TYPE_PCI) ? - TYPE_OSCPCICLK : TYPE_OSCREFCLK; - + // even though we pass in pos=0 for systemref clk, + // getActiveRefClk will make sure it returns the active osc. TargetHandle_t l_ptargetClock = - PlatServices::getClockId(iv_ptargetClock, oscType); + PlatServices::getActiveRefClk(iv_ptargetClock, + TYPE_OSCREFCLK, 0); // Callout this chip if nothing else. if(NULL == l_ptargetClock) @@ -70,11 +70,16 @@ int32_t ClockResolution::Resolve(STEP_CODE_DATA_STRUCT & serviceData) #else serviceData.service_data->SetCallout( PRDcallout(l_ptargetClock, - iv_targetType == TYPE_PCI ? - PRDcalloutData::TYPE_PCICLK : - PRDcalloutData::TYPE_PROCCLK)); + PRDcalloutData::TYPE_PROCCLK)); #endif } + else if (iv_targetType == TYPE_PCI) + { + // The PCIe OSC callout is being done inside + // chip plugins (prdfP8PllPcie) since the connected + // OSC can dynamically change and requires + // reading chip reg to figure out. + } // Get all connected chips for non-CLOCK_CARD types. else { diff --git a/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.C b/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.C index a564c8c5c..18023a4a7 100755 --- a/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.C +++ b/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.C @@ -108,6 +108,38 @@ fapi::Target getFapiTarget( TARGETING::TargetHandle_t i_target ) //## Processor specific functions //############################################################################## +uint32_t getIoOscPos( ExtensibleChip * i_chip, + STEP_CODE_DATA_STRUCT & io_sc) +{ + #define PRDF_FUNC "[PlatServices::getIoOscPos] " + uint32_t o_oscPos = MAX_PCIE_OSC_PER_NODE; + + do + { + uint32_t u32Data = 0; + + int32_t tmpRc = getCfam( i_chip, io_sc, 0x2819, u32Data ); + + if ( SUCCESS != tmpRc ) + { + PRDF_ERR( PRDF_FUNC"getCfam of 0x2819 returned error for " + "chip 0x%08x", i_chip->GetId() ); + break; + } + + // 2819 [ 16 ] == 1 ( OSC 0 is active ) + // 2819 [ 16 ] == 0 ( OSC 1 is active ) + uint32_t tmpData = ( u32Data >> 15 ) & 0x1; + o_oscPos = (tmpData == 1 ? 0:1); + + } while(0); + + return o_oscPos; + + #undef PRDF_FUNC +} + + //############################################################################## //## Lane Repair functions //############################################################################## diff --git a/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.H b/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.H index 57a455751..75825400f 100755 --- a/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.H +++ b/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.H @@ -162,6 +162,15 @@ void initiateUnitDump( TARGETING::TargetHandle_t i_target, */ void collectSBE_FFDC(TARGETING::TargetHandle_t i_procTarget); +/** + * @brief get the active pcie osc pos for this proc + * @param i_chip P8 chip + * @param i_sc service data collector + * @return active osc position + */ +uint32_t getIoOscPos( ExtensibleChip * i_chip, + STEP_CODE_DATA_STRUCT & io_sc ); + //############################################################################## //## Lane Repair functions //############################################################################## @@ -500,6 +509,31 @@ mss_MaintCmdWrapper * createMssCmd( mss_MaintCmdWrapper::CmdType i_cmdType, void captureFsiStatusReg( ExtensibleChip * i_chip, STEP_CODE_DATA_STRUCT & io_sc ); +/** + * @brief get cfam data + * @param i_chip Extensible chip + * @param i_sc service data collector + * @param i_addr address + * @param o_data returned data + * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. + */ +int32_t getCfam( ExtensibleChip * i_chip, + STEP_CODE_DATA_STRUCT & io_sc, + const uint32_t i_addr, + uint32_t & o_data); + +/** + * @brief get sysref clk target for the given proc target. + * @param i_procTarget proc target. + * @param i_peerType Type of peer clock source + * @param i_oscPos OSC position (0 or 1) + * @return Handle_t of systemref clock target. + */ +TARGETING::TargetHandle_t getActiveRefClk( + TARGETING::TargetHandle_t i_procTarget, + TARGETING::TYPE i_connType, + uint32_t i_oscPos); + } // end namespace PlatServices } // end namespace PRDF diff --git a/src/usr/diag/prdf/common/framework/service/prdfTargetServices.C b/src/usr/diag/prdf/common/framework/service/prdfTargetServices.C index fc8eea822..2cb06d287 100755 --- a/src/usr/diag/prdf/common/framework/service/prdfTargetServices.C +++ b/src/usr/diag/prdf/common/framework/service/prdfTargetServices.C @@ -890,6 +890,8 @@ uint32_t getTargetPosition( TARGETING::TargetHandle_t i_target ) { case TYPE_PROC: case TYPE_OSC: + case TYPE_OSCPCICLK: + case TYPE_OSCREFCLK: { uint16_t tmpPos = 0; if ( !i_target->tryGetAttr<ATTR_POSITION>(tmpPos) ) @@ -1300,15 +1302,24 @@ uint8_t getRanksPerDimm( TargetHandle_t i_mba, uint8_t i_ds ) TARGETING::TargetHandle_t getClockId(TARGETING::TargetHandle_t i_pGivenTarget, - TARGETING ::TYPE i_connType) + TARGETING ::TYPE i_connType, + uint32_t i_oscPos) { #define PRDF_FUNC "[PlatServices::getClockId] " + TargetHandleList l_clockCardlist; TargetHandle_t l_target = i_pGivenTarget; TargetHandle_t o_pClockCardHandle = NULL; do { + if ( i_oscPos >= MAX_PCIE_OSC_PER_NODE ) + { + PRDF_ERR(PRDF_FUNC"target: 0x%.8X - invalid " + "i_oscPos: %d", getHuid(i_pGivenTarget), i_oscPos); + break; + } + // If membuf target, use the connected proc target if(TYPE_MEMBUF == getTargetType(i_pGivenTarget)) { @@ -1344,13 +1355,14 @@ TARGETING::TargetHandle_t getClockId(TARGETING::TargetHandle_t l_itr != l_clockCardlist.end(); ++l_itr) { - PRDF_TRAC(PRDF_FUNC"OSC 0x%.8X is connected to proc 0x%.8X", - getHuid(*l_itr), getHuid(l_target)); - } + PRDF_TRAC(PRDF_FUNC"OSC 0x%.8X, pos: %d is connected to " + "proc 0x%.8X, inputOscPos: %d", getHuid(*l_itr), + getTargetPosition(*l_itr), getHuid(l_target), i_oscPos); - if( 0 < l_clockCardlist.size()) - { - o_pClockCardHandle = l_clockCardlist[0]; + if ( i_oscPos == getTargetPosition(*l_itr) ) + { + o_pClockCardHandle = *l_itr; + } } } while(0); diff --git a/src/usr/diag/prdf/common/framework/service/prdfTargetServices.H b/src/usr/diag/prdf/common/framework/service/prdfTargetServices.H index cbb965b8e..ff3a34a05 100755 --- a/src/usr/diag/prdf/common/framework/service/prdfTargetServices.H +++ b/src/usr/diag/prdf/common/framework/service/prdfTargetServices.H @@ -374,13 +374,15 @@ uint8_t getRanksPerDimm( TARGETING::TargetHandle_t i_mbaTarget, uint8_t i_ds ); * @brief Gets handle of the clock card for the given target. * @param i_pTargetHandle Handle of a functional unit. * @param i_peerType Type of peer clock source + * @param i_oscPos OSC position (0 or 1) * @return Handle_t of clock source. * @pre None. * @post None. */ TARGETING::TargetHandle_t getClockId(TARGETING::TargetHandle_t i_pTargetHandle, - TARGETING::TYPE i_peerType); + TARGETING::TYPE i_peerType, + uint32_t i_oscPos); //############################################################################## //## MNFG Policy Flag Functions diff --git a/src/usr/diag/prdf/common/plat/pegasus/Proc.rule b/src/usr/diag/prdf/common/plat/pegasus/Proc.rule index dfbedfb1f..8c97fcbe0 100755 --- a/src/usr/diag/prdf/common/plat/pegasus/Proc.rule +++ b/src/usr/diag/prdf/common/plat/pegasus/Proc.rule @@ -5,7 +5,9 @@ # # OpenPOWER HostBoot Project # -# COPYRIGHT International Business Machines Corp. 2012,2014 +# Contributors Listed Below - COPYRIGHT 2012,2014 +# [+] 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. @@ -160,6 +162,13 @@ chip Proc capture group never; }; + register PCIE_OSC_SWITCH + { + name "TPC.FSI.FSI_MAILBOX.FSXCOMP.FSXLOG.SNS1LTH"; + scomaddr 0x00002819; + capture group never; + }; + }; ############################################################################## diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfP8PllPcie.C b/src/usr/diag/prdf/common/plat/pegasus/prdfP8PllPcie.C index b1a02aa03..a27e4bc57 100755 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfP8PllPcie.C +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfP8PllPcie.C @@ -199,6 +199,15 @@ int32_t ClearPllIo( ExtensibleChip * i_chip, int32_t tmpRC = SUCCESS; SCAN_COMM_REGISTER_CLASS * pciErrReg = i_chip->getRegister("PCI_ERROR_REG"); + + tmpRC = pciErrReg->Read(); + if (tmpRC != SUCCESS) + { + PRDF_ERR(PRDF_FUNC"PCI_ERROR_REG read failed" + "for chip: 0x%08x", i_chip->GetId()); + rc |= tmpRC; + } + pciErrReg->ClearBit(PLL_ERROR_BIT); tmpRC = pciErrReg->Write(); if (tmpRC != SUCCESS) @@ -238,22 +247,55 @@ PRDF_PLUGIN_DEFINE( Proc, ClearPllIo ); * @brief Mask the PLL error for P8 Plugin * @param i_chip P8 chip * @param i_sc The step code data struct + * @param i_oscPos active osc position * @returns Failure or Success of query. * @note */ int32_t MaskPllIo( ExtensibleChip * i_chip, - STEP_CODE_DATA_STRUCT & i_sc ) + STEP_CODE_DATA_STRUCT & i_sc, + uint32_t i_oscPos ) { #define PRDF_FUNC "[Proc::MaskPllIo] " int32_t rc = SUCCESS; - if (CHECK_STOP != i_sc.service_data->GetAttentionType()) + do { + if (CHECK_STOP == i_sc.service_data->GetAttentionType()) + { + break; + } + + if ( i_oscPos >= MAX_PCIE_OSC_PER_NODE ) + { + PRDF_ERR(PRDF_FUNC"invalid oscPos: %d for chip: " + "0x%08x", i_oscPos, i_chip->GetId()); + rc = FAIL; + break; + } + + uint32_t oscPos = getIoOscPos( i_chip, i_sc ); + + if ( oscPos != i_oscPos ) + { + PRDF_DTRAC(PRDF_FUNC"skip masking for chip: 0x%08x, " + "oscPos: %d, i_oscPos: %d", + i_chip->GetId(), oscPos, i_oscPos); + break; + } + // fence off pci osc error reg bit SCAN_COMM_REGISTER_CLASS * pciConfigReg = i_chip->getRegister("PCI_CONFIG_REG"); + rc = pciConfigReg->Read(); + if (rc != SUCCESS) + { + PRDF_ERR(PRDF_FUNC"PCI_CONFIG_REG read failed" + "for 0x%08x", i_chip->GetId()); + break; + } + if(!pciConfigReg->IsBitSet(PLL_ERROR_MASK)) { pciConfigReg->SetBit(PLL_ERROR_MASK); @@ -270,7 +312,7 @@ int32_t MaskPllIo( ExtensibleChip * i_chip, // pll error reg bits, we can't mask it or we will not // see any PLL errors reported from the error regs - } // if not checkstop + } while(0); return rc; @@ -285,7 +327,7 @@ PRDF_PLUGIN_DEFINE( Proc, MaskPllIo ); * @returns Success */ int32_t capturePllFfdcIo( ExtensibleChip * i_chip, - STEP_CODE_DATA_STRUCT & io_sc ) + STEP_CODE_DATA_STRUCT & io_sc ) { // Add FSI status reg captureFsiStatusReg( i_chip, io_sc ); @@ -294,6 +336,61 @@ int32_t capturePllFfdcIo( ExtensibleChip * i_chip, } PRDF_PLUGIN_DEFINE( Proc, capturePllFfdcIo ); +/** + * @brief calling out active pcie osc connected to this proc + * @param i_chip P8 chip + * @param i_sc service data collector + * @returns Success + */ +int32_t CalloutPllIo( ExtensibleChip * i_chip, + STEP_CODE_DATA_STRUCT & io_sc ) +{ + #define PRDF_FUNC "[Proc::CalloutPllIo] " + + int32_t rc = SUCCESS; + + do + { + uint32_t oscPos = getIoOscPos( i_chip, io_sc ); + + // oscPos will be checked inside getClockId and in case + // a connected osc is not found, will use the proc target + // this is the hostboot path since it's used the proc + // target and clock type. + TargetHandle_t connectedOsc = getClockId( i_chip->GetChipHandle(), + TYPE_OSCPCICLK, + oscPos ); + + if ( NULL == connectedOsc ) + { + PRDF_ERR(PRDF_FUNC"Failed to get connected PCIe OSC for " + "chip 0x%08x, oscPos: %d",i_chip->GetId(), oscPos ); + connectedOsc = i_chip->GetChipHandle(); + } + + PRDF_DTRAC(PRDF_FUNC"PCIe OSC: 0x%08x connected to " + "proc: 0x%08x", getHuid(connectedOsc), i_chip->GetId()); + + // callout the clock source + // HB does not have the osc target modeled + // so we need to use the proc target with + // osc clock type to call out + #ifndef __HOSTBOOT_MODULE + io_sc.service_data->SetCallout(connectedOsc); + #else + io_sc.service_data->SetCallout( + PRDcallout(connectedOsc, + PRDcalloutData::TYPE_PCICLK)); + #endif + + } while(0); + + return rc; + + #undef PRDF_FUNC +} +PRDF_PLUGIN_DEFINE( Proc, CalloutPllIo ); + } // end namespace Proc } // end namespace PRDF diff --git a/src/usr/diag/prdf/common/plugins/prdfParserEnums.H b/src/usr/diag/prdf/common/plugins/prdfParserEnums.H index 73c7d3895..bcab4da4c 100644 --- a/src/usr/diag/prdf/common/plugins/prdfParserEnums.H +++ b/src/usr/diag/prdf/common/plugins/prdfParserEnums.H @@ -67,6 +67,8 @@ enum PositionBounds MAX_DIMM_PER_PORT = 2, MAX_L4_PER_MEMBUF = 1, + MAX_PCIE_OSC_PER_NODE = 2, + INVALID_POSITION_BOUND = 0xffffffff, }; diff --git a/src/usr/diag/prdf/framework/service/prdfPlatServices.C b/src/usr/diag/prdf/framework/service/prdfPlatServices.C index 1c7eddc76..cb20e8a44 100644 --- a/src/usr/diag/prdf/framework/service/prdfPlatServices.C +++ b/src/usr/diag/prdf/framework/service/prdfPlatServices.C @@ -267,10 +267,14 @@ bool isSmpCoherent() { return false; } //## util functions //############################################################################## -void captureFsiStatusReg( ExtensibleChip * i_chip, - STEP_CODE_DATA_STRUCT & io_sc ) +int32_t getCfam( ExtensibleChip * i_chip, + STEP_CODE_DATA_STRUCT & io_sc, + const uint32_t i_addr, + uint32_t & o_data) { - #define PRDF_FUNC "[PlatServices::captureFsiStatusReg] " + #define PRDF_FUNC "[PlatServices::getCfam] " + + int32_t rc = SUCCESS; do { @@ -293,36 +297,83 @@ void captureFsiStatusReg( ExtensibleChip * i_chip, errlHndl_t errH = NULL; ecmdDataBufferBase cfamData(32); - uint32_t u32Data = 0; PRD_FAPI_TO_ERRL(errH, fapiGetCfamRegister, - PlatServices::getFapiTarget(i_chip->GetChipHandle()), - 0x00001007, + PlatServices::getFapiTarget(l_procTgt), + i_addr, cfamData); - if(errH) + if ( NULL == errH ) { - PRDF_ERR( PRDF_FUNC"chip: 0x%.8X, failed to get " - "CFAM_FSI_STATUS: 0x%X", - i_chip->GetId(), cfamData.getWord( 0 ) ); + o_data = cfamData.getWord(0); + } + else + { + rc = FAIL; + PRDF_ERR( PRDF_FUNC"chip: 0x%.8X, failed to get cfam address: " + "0x%X", i_chip->GetId(), i_addr ); PRDF_COMMIT_ERRL(errH, ERRL_ACTION_SA|ERRL_ACTION_REPORT); break; } - u32Data = cfamData.getWord(0); + + } while(0); + + + return rc; + + #undef PRDF_FUNC +} + +void captureFsiStatusReg( ExtensibleChip * i_chip, + STEP_CODE_DATA_STRUCT & io_sc ) +{ + #define PRDF_FUNC "[PlatServices::captureFsiStatusReg] " + + uint32_t u32Data = 0; + int32_t rc = getCfam( i_chip, io_sc, 0x00001007, u32Data ); + + if ( SUCCESS == rc ) + { BIT_STRING_ADDRESS_CLASS bs (0, 32, (CPU_WORD *) &u32Data); io_sc.service_data->GetCaptureData().Add( i_chip->GetChipHandle(), ( Util::hashString("CFAM_FSI_STATUS") ^ i_chip->getSignatureOffset() ), - bs); - } while(0); + bs); + } + + // only get this for proc chip + if ( TYPE_PROC == getTargetType(i_chip->GetChipHandle()) ) + { + rc = getCfam( i_chip, io_sc, 0x00002819, u32Data ); + + if ( SUCCESS == rc ) + { + BIT_STRING_ADDRESS_CLASS bs (0, 32, (CPU_WORD *) &u32Data); + + io_sc.service_data->GetCaptureData().Add( + i_chip->GetChipHandle(), + ( Util::hashString("PCIE_OSC_SWITCH") ^ + i_chip->getSignatureOffset() ), + bs); + } + } #undef PRDF_FUNC } +TARGETING::TargetHandle_t getActiveRefClk(TARGETING::TargetHandle_t + i_procTarget, + TARGETING::TYPE i_connType, + uint32_t i_oscPos) +{ + return PlatServices::getClockId( i_procTarget, + i_connType, + i_oscPos ); +} } // end namespace PlatServices diff --git a/src/usr/diag/prdf/test/prdfTest_ProcTpLFir.H b/src/usr/diag/prdf/test/prdfTest_ProcTpLFir.H index c54f64ead..2bd7140fb 100755 --- a/src/usr/diag/prdf/test/prdfTest_ProcTpLFir.H +++ b/src/usr/diag/prdf/test/prdfTest_ProcTpLFir.H @@ -81,7 +81,7 @@ class PTPLFIR:public CxxTest::TestSuite // PB_ERROR_REG PRDS_SCR_WRITE("NODE{0}:PROC{0}", 0x020F001F, - 0x0000006000000001); + 0x0000000000000001); //PRDS_SCR_EXPECT("NODE{0}:PROC{0}", 0x020F001F, //0x0000000000000001); @@ -93,7 +93,7 @@ class PTPLFIR:public CxxTest::TestSuite // ABUS_ERROR_REG PRDS_SCR_WRITE("NODE{0}:PROC{0}", 0x080F001F, - 0x0000004000000001); + 0x0000000000000001); //PRDS_SCR_EXPECT("NODE{0}:PROC{0}", 0x080F001F, //0x0000000000000001); @@ -105,7 +105,7 @@ class PTPLFIR:public CxxTest::TestSuite // EX_ERROR_REG PRDS_SCR_WRITE("NODE{0}:PROC{0}:EX{4}", 0x100F001F, - 0x0000004000000001); + 0x0000000000000001); //PRDS_SCR_EXPECT("NODE{0}:PROC{0}:EX{4}", 0x100F001F, //0x0000000000000001); @@ -158,7 +158,7 @@ class PTPLFIR:public CxxTest::TestSuite // PB_ERROR_REG PRDS_SCR_WRITE("NODE{0}:PROC{0}", 0x020F001F, - 0x0000006000000001); + 0x0000000000000001); //PRDS_SCR_EXPECT("NODE{0}:PROC{0}", 0x020F001F, //0x0000000000000001); @@ -170,7 +170,7 @@ class PTPLFIR:public CxxTest::TestSuite // ABUS_ERROR_REG PRDS_SCR_WRITE("NODE{0}:PROC{0}", 0x080F001F, - 0x0000004000000001); + 0x0000000000000001); //PRDS_SCR_EXPECT("NODE{0}:PROC{0}", 0x080F001F, //0x0000000000000001); @@ -182,7 +182,7 @@ class PTPLFIR:public CxxTest::TestSuite // EX_ERROR_REG PRDS_SCR_WRITE("NODE{0}:PROC{0}:EX{4}", 0x100F001F, - 0x0000004000000001); + 0x0000000000000001); //PRDS_SCR_EXPECT("NODE{0}:PROC{0}:EX{4}", 0x100F001F, //0x0000000000000001); |