Skip to content

Commit

Permalink
Finalize SBE PSU FFDC collection - Set FFDC address in PSU
Browse files Browse the repository at this point in the history
Change-Id: Ia2b1012cf2938f34cc6acdbb888b5a489aac98f6
RTC: 164405
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/40453
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Martin Gloff <mgloff@us.ibm.com>
Reviewed-by: Shakeeb A. Pasha B K <shakeebbk@in.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
  • Loading branch information
Dzuy Nguyen authored and dcrowell77 committed Jun 6, 2017
1 parent 728c774 commit 5033ee3
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 95 deletions.
26 changes: 13 additions & 13 deletions src/include/usr/sbeio/sbe_psudd.H
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#include <errl/errlentry.H>
#include <util/singleton.H>
#include <map>

namespace SBEIO
{
Expand Down Expand Up @@ -513,34 +514,33 @@ class SbePsu

~SbePsu();

/**
* @brief populate the iv_ffdcPackageBuffer
* @param[in] i_data FFDC error data
* @param[in] i_len data buffer len to copy
*/

void writeFFDCBuffer(void * i_data, uint8_t i_len);

private:
//---------------------------------------------------------------------
// Local definitions for the device driver
//---------------------------------------------------------------------

/**
* @brief Write FFDC package buffer - holds information exchanged
* between SBE and HB
* @brief Write FFDC package buffer - map of memory allocated
* for each target's FFDC package. Indexed by TARGETING
*/
void * iv_ffdcPackageBuffer;
std::map<TARGETING::Target *, void *> iv_ffdcPackageBuffer;

/**
* @brief FFDC package needs to be 2 pages
*/
const uint8_t ffdcPackageSize = 2;

/**
* @brief zero out the FFDC package buffer
* @brief allocate an ffdc buffer for the proc target
* @param[in] i_target proc to have ffdc buffer allocated
*/
errlHndl_t allocateFFDCBuffer(TARGETING::Target * i_target);

/**
* @brief utility to find an allocated FFDC buffer
* @param[in] i_target proc to that had ffdc buffer allocated
*/
void initFFDCPackageBuffer();
void * findFFDCBufferByTarget(TARGETING::Target * i_target);

/**
* @brief Write request to PSU
Expand Down
205 changes: 123 additions & 82 deletions src/usr/sbeio/sbe_psudd.C
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <sbeio/sbe_ffdc_parser.H>
#include <arch/ppc.H>
#include <kernel/pagemgr.H>
#include <sbeio/sbeioif.H>

trace_desc_t* g_trac_sbeio;
TRAC_INIT(&g_trac_sbeio, SBEIO_COMP_NAME, 6*KILOBYTE, TRACE::BUFFER_SLOW);
Expand Down Expand Up @@ -69,41 +70,21 @@ SbePsu & SbePsu::getTheInstance()
**/
SbePsu::SbePsu()
{
iv_ffdcPackageBuffer = PageManager::allocatePage(ffdcPackageSize, true);
initFFDCPackageBuffer();

/*
* TODO RTC 164405
*
* call performPsuChipOp to tell SBE where to write when SBE is ready
*
* psuCommand l_psuCommand(
* SBE_REQUIRE_RESPONSE,
* SBE_PSU_GENERIC_MESSAGE,
* SBE_CMD_CONTROL_SYSTEM_CONFIG);
*
* psuResponse l_psuResponse;
*
* // Create FFDCPackage struct in psuCommand union
* uint64_t cd4_FFDCPackage_MbxReg2reserved = &iv_ffdcPackageBuffer;
*
* performPsuChipOp(&l_psuCommand,
* &l_psuResponse,
* MAX_PSU_SHORT_TIMEOUT_NS,
* SBE_SYSTEM_CONFIG_REQ_USED_REGS,
* SBE_SYSTEM_CONFIG_RSP_USED_REGS);
*
*/
}

/**
* @brief Destructor
**/
SbePsu::~SbePsu()
{
if(iv_ffdcPackageBuffer != NULL)
std::map<TARGETING::Target *, void *>::iterator l_iter;
for(l_iter = iv_ffdcPackageBuffer.begin();
l_iter != iv_ffdcPackageBuffer.end(); l_iter++)
{
PageManager::freePage(iv_ffdcPackageBuffer);
if(l_iter->second != NULL)
{
PageManager::freePage(l_iter->second);
}
}
}

Expand All @@ -130,6 +111,19 @@ errlHndl_t SbePsu::performPsuChipOp(TARGETING::Target * i_target,

SBE_TRACD(ENTER_MRK "performPsuChipOp");

// If not a SBE_PSU_SET_FFDC_ADDRESS command, we allocate an FFDC buffer
// and set FFDC adress
if(i_pPsuRequest->command != SBE_PSU_SET_FFDC_ADDRESS)
{
errl = allocateFFDCBuffer(i_target);
}
if (errl)
{
SBE_TRACF(ERR_MRK"performPsuChipOp::"
" setFFDC address returned an error");
return errl;
}

//Serialize access to PSU
mutex_lock(&l_psuOpMux);

Expand Down Expand Up @@ -165,17 +159,15 @@ errlHndl_t SbePsu::performPsuChipOp(TARGETING::Target * i_target,

mutex_unlock(&l_psuOpMux);

//@todo-RTC:144313-Remove when we have our FFDC in place
//Temporarily crash with a known RC so that HWSV collects the SBE FFDC
if( errl && (SBE_COMP_ID == errl->moduleId()) )
if( errl && (SBEIO_PSU == errl->moduleId()) )
{
SBE_TRACF( "Forcing shutdown for FSP to collect FFDC" );

//commit the original error after pulling some data out
uint32_t orig_plid = errl->plid();
uint32_t orig_rc = errl->reasonCode();
uint32_t orig_mod = errl->moduleId();
ERRORLOG::errlCommit( errl, SBE_COMP_ID );
ERRORLOG::errlCommit( errl, SBEIO_COMP_ID );
/*@
* @errortype
* @moduleid SBEIO_PSU
Expand Down Expand Up @@ -256,18 +248,23 @@ errlHndl_t SbePsu::writeRequest(TARGETING::Target * i_target,
i_pPsuRequest->mbxReg0,
l_data);

SbeFFDCParser * l_ffdc_parser = new SbeFFDCParser();
l_ffdc_parser->parseFFDCData(iv_ffdcPackageBuffer);
uint8_t l_pkgs = l_ffdc_parser->getTotalPackages();
uint8_t i;
for(i = 0; i < l_pkgs; i++)
void * l_ffdcPkg = findFFDCBufferByTarget(i_target);
if(l_ffdcPkg != NULL)
{
errl->addFFDC( SBE_COMP_ID,
l_ffdc_parser->getFFDCPackage(i),
l_ffdc_parser->getPackageLength(i),
0, // version
ERRORLOG::ERRL_UDT_NOFORMAT, // subversion
false );
SbeFFDCParser * l_ffdc_parser = new SbeFFDCParser();
l_ffdc_parser->parseFFDCData(l_ffdcPkg);
uint8_t l_pkgs = l_ffdc_parser->getTotalPackages();
uint8_t i;
for(i = 0; i < l_pkgs; i++)
{
errl->addFFDC( SBEIO_COMP_ID,
l_ffdc_parser->getFFDCPackage(i),
l_ffdc_parser->getPackageLength(i),
0,
SBEIO_UDT_PARAMETERS,
false );
}
delete l_ffdc_parser;
}

errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
Expand All @@ -277,7 +274,6 @@ errlHndl_t SbePsu::writeRequest(TARGETING::Target * i_target,
i_target->getAttr<TARGETING::ATTR_POSITION>(),
SBEIO_PSU_NOT_READY);

delete l_ffdc_parser;
break; // return with error
}

Expand Down Expand Up @@ -403,18 +399,23 @@ errlHndl_t SbePsu::readResponse(TARGETING::Target * i_target,
i_pPsuRequest->mbxReg0,
o_pPsuResponse->mbxReg4);

SbeFFDCParser * l_ffdc_parser = new SbeFFDCParser();
l_ffdc_parser->parseFFDCData(iv_ffdcPackageBuffer);
uint8_t l_pkgs = l_ffdc_parser->getTotalPackages();
uint8_t i;
for(i = 0; i < l_pkgs; i++)
void * l_ffdcPkg = findFFDCBufferByTarget(i_target);
if(l_ffdcPkg != NULL)
{
errl->addFFDC( SBE_COMP_ID,
l_ffdc_parser->getFFDCPackage(i),
l_ffdc_parser->getPackageLength(i),
0, // version
ERRORLOG::ERRL_UDT_NOFORMAT, // subversion
false );
SbeFFDCParser * l_ffdc_parser = new SbeFFDCParser();
l_ffdc_parser->parseFFDCData(l_ffdcPkg);
uint8_t l_pkgs = l_ffdc_parser->getTotalPackages();
uint8_t i;
for(i = 0; i < l_pkgs; i++)
{
errl->addFFDC( SBEIO_COMP_ID,
l_ffdc_parser->getFFDCPackage(i),
l_ffdc_parser->getPackageLength(i),
0,
SBEIO_UDT_PARAMETERS,
false );
}
delete l_ffdc_parser;
}

errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
Expand All @@ -424,7 +425,6 @@ errlHndl_t SbePsu::readResponse(TARGETING::Target * i_target,
i_target->getAttr<TARGETING::ATTR_POSITION>(),
SBEIO_PSU_RESPONSE_ERROR);

delete l_ffdc_parser;
break;
}

Expand Down Expand Up @@ -483,18 +483,23 @@ errlHndl_t SbePsu::pollForPsuComplete(TARGETING::Target * i_target,
i_timeout,
0);

SbeFFDCParser * l_ffdc_parser = new SbeFFDCParser();
l_ffdc_parser->parseFFDCData(iv_ffdcPackageBuffer);
uint8_t l_pkgs = l_ffdc_parser->getTotalPackages();
uint8_t i;
for(i = 0; i < l_pkgs; i++)
void * l_ffdcPkg = findFFDCBufferByTarget(i_target);
if(l_ffdcPkg != NULL)
{
errl->addFFDC( SBE_COMP_ID,
l_ffdc_parser->getFFDCPackage(i),
l_ffdc_parser->getPackageLength(i),
0, // version
ERRORLOG::ERRL_UDT_NOFORMAT, // subversion
false );
SbeFFDCParser * l_ffdc_parser = new SbeFFDCParser();
l_ffdc_parser->parseFFDCData(l_ffdcPkg);
uint8_t l_pkgs = l_ffdc_parser->getTotalPackages();
uint8_t i;
for(i = 0; i < l_pkgs; i++)
{
errl->addFFDC( SBEIO_COMP_ID,
l_ffdc_parser->getFFDCPackage(i),
l_ffdc_parser->getPackageLength(i),
0,
SBEIO_UDT_PARAMETERS,
false );
}
delete l_ffdc_parser;
}

errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE,
Expand All @@ -504,7 +509,6 @@ errlHndl_t SbePsu::pollForPsuComplete(TARGETING::Target * i_target,
i_target->getAttr<TARGETING::ATTR_POSITION>(),
SBEIO_PSU_RESPONSE_TIMEOUT);

delete l_ffdc_parser;
break;
}

Expand Down Expand Up @@ -576,30 +580,67 @@ errlHndl_t SbePsu::writeScom(TARGETING::Target * i_target,
}

/**
* @brief zero out FFDC Package Buffer
* @brief allocates buffer and sets ffdc address for the proc
*/

void SbePsu::initFFDCPackageBuffer()
errlHndl_t SbePsu::allocateFFDCBuffer(TARGETING::Target * i_target)
{
memset(iv_ffdcPackageBuffer, 0x00, PAGESIZE * ffdcPackageSize);

static mutex_t l_alloMux = MUTEX_INITIALIZER;

uint32_t l_bufSize = getSbeFFDCBufferSize();
errlHndl_t errl = NULL;

uint32_t l_huid = TARGETING::get_huid(i_target);

// Check to see if the buffer has been allocated before allocating
// and setting FFDC address
mutex_lock(&l_alloMux);

if(iv_ffdcPackageBuffer.find(i_target) == iv_ffdcPackageBuffer.end())
{
void * l_ffdcPtr = PageManager::allocatePage(ffdcPackageSize, true);
memset(l_ffdcPtr, 0x00, l_bufSize);

errl = sendSetFFDCAddr(l_bufSize,
0,
mm_virt_to_phys(l_ffdcPtr),
0,
i_target);

if(errl)
{
PageManager::freePage(l_ffdcPtr);
SBE_TRACF(ERR_MRK"Error setting FFDC address for proc huid=0x%08lx", l_huid);
}
else
{
iv_ffdcPackageBuffer.insert(std::pair<TARGETING::Target *, void *>
(i_target, l_ffdcPtr));
SBE_TRACD("Allocated FFDC buffer for proc huid=0x%08lx", l_huid);
}
}

mutex_unlock(&l_alloMux);
return errl;
}

/**
* @brief populate FFDC package buffer
* @param[in] i_data FFDC error data
* @param[in] i_len data buffer len to copy
* @brief find allocated FFDC buffer by the target
*/
void SbePsu::writeFFDCBuffer( void * i_data, uint8_t i_len) {
if(i_len <= PAGESIZE * ffdcPackageSize)
{
initFFDCPackageBuffer();
memcpy(iv_ffdcPackageBuffer, i_data, i_len);
}
else
void * SbePsu::findFFDCBufferByTarget(TARGETING::Target * i_target)
{
void * ffdcBuffer = NULL;

std::map<TARGETING::Target *, void *>::iterator l_iter =
iv_ffdcPackageBuffer.find(i_target);

if(l_iter != iv_ffdcPackageBuffer.end())
{
SBE_TRACF(ERR_MRK"writeFFDCBuffer: Buffer size too large: %d",
i_len);
ffdcBuffer = l_iter->second;
}

return ffdcBuffer;
}

} //end of namespace SBEIO

0 comments on commit 5033ee3

Please sign in to comment.