diff options
Diffstat (limited to 'src/usr/diag')
9 files changed, 262 insertions, 30 deletions
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 8957b59ed..7fac67314 100755 --- a/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.C +++ b/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.C @@ -769,6 +769,28 @@ int32_t getDimmSpareConfig( TargetHandle_t i_mba, CenRank i_rank, } //------------------------------------------------------------------------------ +errlHndl_t getFapiDimmDqAttr( TargetHandle_t i_target, + uint8_t *io_dqMapPtr ) +{ + uint8_t (&l_wiringData)[DIMM_DQ_NUM_DQS] = + *(reinterpret_cast<uint8_t(*)[DIMM_DQ_NUM_DQS]>(io_dqMapPtr)); + + // We have a DIMM target to get the DQ map for + // (need FAPI target from normal HWSV target) + fapi::Target l_fapiDimm = getFapiTarget(i_target); + + // Read the attribute + // (suppose to return a 1:1 mapping for Centaur DIMMs) + fapi::ReturnCode l_fapiRc; + l_fapiRc = FAPI_ATTR_GET(ATTR_CEN_DQ_TO_DIMM_CONN_DQ, + &l_fapiDimm, l_wiringData ); + + errlHndl_t l_fapiElog = fapi::fapiRcToErrl(l_fapiRc); + + return(l_fapiElog); +} // end function getFapiDimmDqAttr + +//------------------------------------------------------------------------------ int32_t getMemBufRawCardType( TargetHandle_t i_mba, WiringType & o_cardType ) 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 3c5da9ebf..8b07545b8 100755 --- a/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.H +++ b/src/usr/diag/prdf/common/framework/service/prdfPlatServices_common.H @@ -339,6 +339,15 @@ int32_t getDimmSpareConfig( TARGETING::TargetHandle_t i_mba, CenRank i_rank, int32_t getMemBufRawCardType( TARGETING::TargetHandle_t i_mbaTarget, CEN_SYMBOL::WiringType & o_wiringType ); +/** + * @brief get DIMM DQ map from FAPI routines + * @param i_target DIMM target + * @param io_dqMapPtr Pointer to area to receive DIMM DQ map (80 bytes) + * @return Non-Null if error log occurs + */ +errlHndl_t getFapiDimmDqAttr( TARGETING::TargetHandle_t i_target, + uint8_t *io_dqMapPtr ); + //############################################################################## //## Maintenance Command class wrapper //############################################################################## diff --git a/src/usr/diag/prdf/common/framework/service/prdfRasServices_common.C b/src/usr/diag/prdf/common/framework/service/prdfRasServices_common.C index 6471b4955..23ed75f69 100644 --- a/src/usr/diag/prdf/common/framework/service/prdfRasServices_common.C +++ b/src/usr/diag/prdf/common/framework/service/prdfRasServices_common.C @@ -37,6 +37,7 @@ #include <prdfCallouts.H> #include <prdfMemoryMru.H> #include <prdfPlatServices.H> +#include <prdfCenLogParse.H> // For compression routines #define PRDF_COMPRESSBUFFER_COMPRESS_FUNCTIONS @@ -71,6 +72,8 @@ using namespace TARGETING; + + namespace PRDF { @@ -603,6 +606,86 @@ errlHndl_t ErrDataService::GenerateSrcPfa( ATTENTION_TYPE i_attnType, severityParm, l_diagUpdate ); } + + // If we have a valid symbol in the memory MRU object, then we + // should have one DIMM called out that we want the DQ map for. + // If the symbol is not valid, then we will do nothing. If the + // symbol is valid, but we have multiple callouts, then there is + // probably something wrong. + CenSymbol l_cenSymbol = memMru.getSymbol(); + if (l_cenSymbol.isValid()) + { + if (1 == partList.size()) + { + // Will make extra check that we have a DIMM + TARGETING::TYPE l_type; + l_type = getTargetType( partList[0] ); + + if (TARGETING::TYPE_DIMM == l_type) + { + // Will be storing the CEN/IS DIMM indicator, cardtype, + // and the 32 bit memmru prior to the 80 byte mapping + memMruDqInfo l_memData; + memset(&l_memData, 0, sizeof(memMruDqInfo)); + + // Call routine to read the FAPI attribute for DQ map + errlHndl_t l_fapiElog; + l_fapiElog = getFapiDimmDqAttr(partList[0], + &(l_memData.dqMapping[0])); + + if (NULL == l_fapiElog) + { + bool l_bufDimm; + CEN_SYMBOL::WiringType l_cardWireType; + int32_t l_chkRc; + // Get MBA target from DIMM + TargetHandle_t l_mba; + l_mba = getConnectedParent(partList[0], TYPE_MBA); + // Track if centaur or IS DIMM + l_chkRc = isMembufOnDimm(l_mba, l_bufDimm); + l_chkRc |= getMemBufRawCardType(l_mba, + l_cardWireType); + + if (SUCCESS == l_chkRc) + { // Put data into structure + l_memData.bufferedDimm = l_bufDimm; + l_memData.cardType = l_cardWireType; + } + else + { // unable to determine anything + l_memData.cardType = MEMRU_WIRING_UNKNOWN; + } + + // Get the 32 bit representation of MemMru + l_memData.memMru32bits = memMru.toUint32(); + + // Add mapping to ELOG and parser will print it + PRDF_ADD_FFDC( iv_errl, (const char*)(&l_memData), + sizeof(memMruDqInfo), + ErrlVer1, ErrlMruData_2 ); + } // end if success reading attribute + else + { + PRDF_ERR( PRDF_FUNC "Fail on Read DQ mapping"); + PRDF_COMMIT_ERRL(l_fapiElog, ERRL_ACTION_REPORT); + } // end else error reading attribute + + } // end if DIMM target + else + { + PRDF_ERR( PRDF_FUNC "Not DIMM Target (%08X)", + l_type ); + } // end else NOT DIMM + + } // end if just one part called out + else + { // more than one part called out + PRDF_ERR( PRDF_FUNC "Valid Symbol with multiple parts (%d)", + partList.size() ); + } // end else multiple parts called out with valid symbol + + } // if valid centaur symbol + } else if ( PRDcalloutData::TYPE_SYMFRU == thiscallout.getType() ) { diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfMemoryMru.H b/src/usr/diag/prdf/common/plat/pegasus/prdfMemoryMru.H index 2d3d26309..bc8090272 100755 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfMemoryMru.H +++ b/src/usr/diag/prdf/common/plat/pegasus/prdfMemoryMru.H @@ -32,6 +32,7 @@ #include <prdfMemoryMruData.H> #include <prdfPlatServices.H> #include <prdfCenSymbol.H> +#include <prdfParserEnums.H> namespace PRDF { @@ -81,6 +82,12 @@ class MemoryMru /** @return A list of targets that are represented by this MemoryMru. */ TARGETING::TargetHandleList getCalloutList() const; + /** + * @brief Allows reading the symbol information + * @return 'centaur symbol object' + */ + CenSymbol getSymbol() { return iv_symbol; } + private: // instance variables MemoryMruData::MemMruMeld iv_memMruMeld; diff --git a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C index f0a263200..1228d9b61 100644 --- a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C +++ b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.C @@ -1961,59 +1961,107 @@ void getBadDqBitmapEntry( uint8_t * i_buffer, char * o_str ) //------------------------------------------------------------------------------ // Helper function for parseMemMruData() -int32_t getMemMruDramSite( MemoryMruData::MemMruMeld i_memMruData, +int32_t getMemMruDramSite( memMruDqInfo &i_memDqStruct, char * o_data ) { + char l_dqMapBuffer[4]; + memset (l_dqMapBuffer, 0, 4); int32_t o_rc = SUCCESS; + MemoryMruData::MemMruMeld mm; mm.u = i_memDqStruct.memMru32bits; + do { // Get the symbol and adjust for ECC spare, if needed. - uint8_t symbol = transEccSpare( i_memMruData.s.symbol, - i_memMruData.s.eccSpared ); + uint8_t symbol = transEccSpare( mm.s.symbol, + mm.s.eccSpared ); - uint8_t type = i_memMruData.s.wiringType; - uint8_t mbaPos = i_memMruData.s.mbaPos; + uint8_t type = i_memDqStruct.cardType; + uint8_t mbaPos = mm.s.mbaPos; uint8_t ps = symbol2PortSlct( symbol ); - uint8_t mrank = i_memMruData.s.mrank; + uint8_t mrank = mm.s.mrank; // Get the DRAM site location information. bool x4Dram; const char * cardName; - const char ** dqMap; const char ** dramMap; - o_rc = getDramSiteInfo( type, mbaPos, ps, mrank, x4Dram, - cardName, dqMap, dramMap ); + const char ** dqMap; + + // This routine will only succeed on CDIMMs + if (i_memDqStruct.bufferedDimm) + { + o_rc = getDramSiteInfo( type, mbaPos, ps, mrank, x4Dram, + cardName, dqMap, dramMap ); + } + if ( SUCCESS != o_rc ) break; // Get the DQ and DRAM indexes for site location tables. uint8_t dqIdx = transDramSpare( symbol2CenDq(symbol), - i_memMruData.s.dramSpared ); + mm.s.dramSpared ); uint8_t dramIdx = dqSiteIdx2DramSiteIdx( dqIdx, x4Dram ); // Add the DRAM site data based on the pin info. strcpy( o_data, "" ); - switch ( i_memMruData.s.pins ) + switch ( mm.s.pins ) { case EVEN_SYMBOL_DQ: - strcat( o_data, dqMap[dqIdx] ); + if (i_memDqStruct.bufferedDimm) + { + strcat( o_data, dqMap[dqIdx] ); + } + else + { + snprintf( l_dqMapBuffer, 4, "%d", + i_memDqStruct.dqMapping[dqIdx] ); + strcat( o_data, l_dqMapBuffer ); + } break; case ODD_SYMBOL_DQ: - strcat( o_data, dqMap[dqIdx+1] ); + if (i_memDqStruct.bufferedDimm) + { + strcat( o_data, dqMap[dqIdx+1] ); + } + else + { + snprintf( l_dqMapBuffer, 4, "%d", + i_memDqStruct.dqMapping[dqIdx+1] ); + strcat( o_data, l_dqMapBuffer ); + } break; case BOTH_SYMBOL_DQS: - strcat( o_data, dqMap[dqIdx] ); - strcat( o_data, ", " ); - strcat( o_data, dqMap[dqIdx+1] ); + if (i_memDqStruct.bufferedDimm) + { + strcat( o_data, dqMap[dqIdx] ); + strcat( o_data, ", " ); + strcat( o_data, dqMap[dqIdx+1] ); + } + else + { + snprintf( l_dqMapBuffer, 10, "%d, %d", + i_memDqStruct.dqMapping[dqIdx], + i_memDqStruct.dqMapping[dqIdx+1] ); + strcat( o_data, l_dqMapBuffer ); + } break; case NO_SYMBOL_DQS: // blaming relevant dram since we aren't sure of DQ - strcat( o_data, dramMap[dramIdx] ); + if (i_memDqStruct.bufferedDimm) + { + strcat( o_data, dramMap[dramIdx] ); + } + else + { + snprintf( l_dqMapBuffer, 10, "%d, %d", + i_memDqStruct.dqMapping[dqIdx], + i_memDqStruct.dqMapping[dqIdx+1] ); + strcat( o_data, l_dqMapBuffer ); + } break; default: @@ -2026,12 +2074,11 @@ int32_t getMemMruDramSite( MemoryMruData::MemMruMeld i_memMruData, return o_rc; } //------------------------------------------------------------------------------ - -bool parseMemMruData( ErrlUsrParser & i_parser, uint32_t i_memMru ) +bool parseMemMruData( ErrlUsrParser & i_parser, memMruDqInfo &i_memDqStruct ) { bool o_rc = true; - MemoryMruData::MemMruMeld mm; mm.u = i_memMru; + MemoryMruData::MemMruMeld mm; mm.u = i_memDqStruct.memMru32bits; uint8_t nodePos = mm.s.nodePos; uint8_t cenPos = (mm.s.procPos << 3) | mm.s.cenPos; @@ -2064,13 +2111,25 @@ bool parseMemMruData( ErrlUsrParser & i_parser, uint32_t i_memMru ) if ( SYMBOLS_PER_RANK > mm.s.symbol ) { char dramSite_str[DATA_SIZE] = { '\0' }; - getMemMruDramSite( mm, dramSite_str ); + + getMemMruDramSite( i_memDqStruct, dramSite_str ); + + char l_sitePinString[5]; + if (i_memDqStruct.bufferedDimm) + { + strcpy(l_sitePinString, "Site"); + } + else + { + strcpy(l_sitePinString, "DQ"); + } snprintf( data, DATA_SIZE, - "Symbol:%d Pins:%d S:%c E:%c Site:%s", + "Symbol:%d Pins:%d S:%c E:%c %s:%s", mm.s.symbol, mm.s.pins, (1 == mm.s.dramSpared) ? 'Y' : 'N', (1 == mm.s.eccSpared) ? 'Y' : 'N', + l_sitePinString, dramSite_str ); } } @@ -2078,7 +2137,9 @@ bool parseMemMruData( ErrlUsrParser & i_parser, uint32_t i_memMru ) // Ouptut should look like: // | mba(n0p0c0) Rank:M7 : Special: CALLOUT_RANK | // | mba(n7p63c1) Rank:M0S7 : Symbol: 71 Pins: 3 Spared: false | - // | mba(n0p4c0) Rank:M0S0 : DRAM Site: DA03.d1 | + // | mba(n0p4c0) Rank:M0S0 : Site/Pin: DA03.d1 | + // or for IS DIMM we would see the last line be: + // | mba(n0p4c0) Rank:M0S0 : Site/Pin: 25 | i_parser.PrintString( header, data ); diff --git a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H index b5385bfb7..8a2e3f368 100644 --- a/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H +++ b/src/usr/diag/prdf/common/plugins/prdfCenLogParse.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2014 */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -31,6 +31,7 @@ #define __prdfCenLogParse_H #include <stdint.h> +#include <prdfMemoryMruData.H> class ErrlUsrParser; @@ -52,7 +53,7 @@ namespace FSP * @param i_parser The error log parser. * @param i_memMru The MemoryMru data. */ -bool parseMemMruData( ErrlUsrParser & i_parser, uint32_t i_memMru ); +bool parseMemMruData( ErrlUsrParser & i_parser, memMruDqInfo &i_memDqStruct ); /** * @brief Parses Memory UE table. diff --git a/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C b/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C index a996e6c3c..f141b384d 100644 --- a/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C +++ b/src/usr/diag/prdf/common/plugins/prdfLogParse_common.C @@ -590,7 +590,6 @@ bool parsePfaData( void * i_buffer, uint32_t i_buflen, strcat( data, "(MemoryMru) " ); strcat( data, tmpStr ); i_parser.PrintString( header, data ); - parseMemMruData( i_parser, pfa.mruList[i].callout ); break; case PRDcalloutData::TYPE_SYMFRU: @@ -685,14 +684,49 @@ bool parseMemMru( void * i_buffer, uint32_t i_buflen, ErrlUsrParser & i_parser ) char header[72]; snprintf( header, 72, "MemoryMru (0x%08x)", memMru ); i_parser.PrintHeading( header ); - - o_rc = parseMemMruData( i_parser, memMru ); } return o_rc; } //------------------------------------------------------------------------------ +bool parseDqMap( void * i_buffer, uint32_t i_buflen, ErrlUsrParser & i_parser ) +{ + bool o_rc = true; + size_t l_size = sizeof(memMruDqInfo); + + i_parser.PrintBlank(); + + if ( i_buflen != l_size ) + { + i_parser.PrintString( " ERROR", + "Unable to parse Mem DQ " ); + i_parser.PrintBlank(); + } + else + { + // Data on input::has DQ mapping and a few other fields in a structure + memMruDqInfo l_memData; + UtilMem membuf( i_buffer, i_buflen ); + membuf >> l_memData; + + char header[72]; + snprintf( header, 72, "MemoryMru (0x%08x)", l_memData.memMru32bits); + i_parser.PrintHeading( header ); + + o_rc = parseMemMruData( i_parser, l_memData ); + + } + + // want to see the bitmap/data in any case + i_parser.PrintHexDump( i_buffer, i_buflen ); + + return o_rc; + +} // end parseDqMap + + +//------------------------------------------------------------------------------ bool parsePnorFirData( uint8_t * i_buffer, uint32_t i_buflen, ErrlUsrParser & i_parser ) @@ -772,6 +806,10 @@ bool logDataParse( ErrlUsrParser & i_parser, void * i_buffer, rc = parseMemMru( i_buffer, i_buflen, i_parser ); break; + case ErrlMruData_2: + rc = parseDqMap( i_buffer, i_buflen, i_parser ); + break; + default: printUnknown( i_parser, i_ver, i_sst ); i_parser.PrintHexDump(i_buffer, i_buflen); @@ -856,4 +894,3 @@ bool srcDataParse( ErrlUsrParser & i_parser, const SrciSrc & i_src ) } //end namespace HOSTBOOT/FSP } // end namespace PRDF - diff --git a/src/usr/diag/prdf/common/plugins/prdfMemoryMruData.H b/src/usr/diag/prdf/common/plugins/prdfMemoryMruData.H index d70a6c2da..136f0994e 100644 --- a/src/usr/diag/prdf/common/plugins/prdfMemoryMruData.H +++ b/src/usr/diag/prdf/common/plugins/prdfMemoryMruData.H @@ -37,6 +37,18 @@ namespace PRDF { +// Structure to contain memory DQ mapping and related info +struct memMruDqInfo +{ + uint32_t memMru32bits; // 32 bit MemoryMru format + uint32_t cardType :8; // cardType for Centaur DIMMs + uint32_t bufferedDimm :1; // Centaur DIMM (1) or IS DIMM (0) + uint32_t reserved :23; // Future use / nice boundary + uint8_t dqMapping[80]; // CenDQ to DimmDQ mapping +}; + +#define MEMRU_WIRING_UNKNOWN 0xFF + #ifdef PRDF_HOSTBOOT_ERRL_PLUGIN namespace HOSTBOOT { @@ -49,7 +61,6 @@ namespace FSP namespace MemoryMruData { - /** Typically a MemoryMru callout is associated with a symbol (single DIMM * callout), however, there are times were we cannot isolate down that far and * instead need to callout a rank (pair of DIMMs) and the associated MBA. diff --git a/src/usr/diag/prdf/common/plugins/prdfPfa5Data.h b/src/usr/diag/prdf/common/plugins/prdfPfa5Data.h index a5ebf5d1d..a26c86ca5 100644 --- a/src/usr/diag/prdf/common/plugins/prdfPfa5Data.h +++ b/src/usr/diag/prdf/common/plugins/prdfPfa5Data.h @@ -72,6 +72,7 @@ enum ErrlSubsect ErrlCapData_2 = 2, ErrlMruData_1 = 61, // This will only be used in non-attenion code when // we want to add MRU. + ErrlMruData_2 = 62, // For the 80 byte centaur DQ pin map ErrlString = 10, }; |