summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDean Sanner <dsanner@us.ibm.com>2013-07-16 14:58:43 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-08-21 15:38:53 -0500
commitb814311a6dc122e761336881130eace63d3533e7 (patch)
tree1330190b59abbe6fc094de1b5afda87abacc100b
parenta6f46d0a9461b96781bc85c9fd82c24d14b5ce42 (diff)
downloadtalos-hostboot-b814311a6dc122e761336881130eace63d3533e7.tar.gz
talos-hostboot-b814311a6dc122e761336881130eace63d3533e7.zip
Handle interrupts on MPIPL
Change-Id: I315d5c802819bf6f16cd6adbffe77530bd42699a Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/5427 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--src/include/kernel/intmsghandler.H4
-rw-r--r--src/include/usr/intr/interrupt.H3
-rw-r--r--src/include/usr/runtime/runtime.H29
-rw-r--r--src/include/usr/runtime/runtime_reasoncodes.H2
-rw-r--r--src/kernel/intmsghandler.C14
-rw-r--r--src/usr/dump/dumpCollect.C74
-rw-r--r--src/usr/dump/dumpCollect.H4
-rw-r--r--src/usr/dump/test/dumptest.H61
-rw-r--r--src/usr/hwas/hostbootIstep.C2
-rw-r--r--src/usr/hwpf/hwp/dram_initialization/dram_initialization.C20
-rw-r--r--src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C452
-rw-r--r--src/usr/hwpf/hwp/start_payload/start_payload.C9
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvctasks.H25
-rw-r--r--src/usr/intr/intrrp.C710
-rw-r--r--src/usr/intr/intrrp.H92
-rw-r--r--src/usr/runtime/hdatservice.C129
-rw-r--r--src/usr/runtime/hdatservice.H48
17 files changed, 1216 insertions, 462 deletions
diff --git a/src/include/kernel/intmsghandler.H b/src/include/kernel/intmsghandler.H
index 3f888f94b..220a7fa30 100644
--- a/src/include/kernel/intmsghandler.H
+++ b/src/include/kernel/intmsghandler.H
@@ -67,7 +67,9 @@ class InterruptMsgHdlr : public MessageHandler
XIRR_ADDR_OFFSET = 4,
MFRR_ADDR_OFFSET = 12,
- INTP_BAR_VALUE = 0xFFFFE000, // upper 32 bits of IPCBAR
+ INTP_BAR_VALUE = 0xFFFFE000, // upper 32 bits of IPCBAR
+
+ INTERPROC_XISR = 2, //IPI XISR is 2
};
/**
diff --git a/src/include/usr/intr/interrupt.H b/src/include/usr/intr/interrupt.H
index f41f8ccf6..473fa7cd3 100644
--- a/src/include/usr/intr/interrupt.H
+++ b/src/include/usr/intr/interrupt.H
@@ -90,7 +90,7 @@ namespace INTR
enum ISNvalue_t
{
- ISN_FSP = 0,
+ ISN_PSI = 0,
ISN_OCC = 1,
ISN_FSI = 2,
FSP_MAILBOX = 2,
@@ -138,6 +138,7 @@ namespace INTR
MSG_INTR_DISABLE, //!< Disable external interrupts
MSG_INTR_SHUTDOWN, //!< Call to shutdown interrupt presenter
MSG_INTR_ENABLE_PSI_INTR, //!< Enable PSI interrupts
+ MSG_INTR_MPIPL_CLEANUP, //!< Clean up interrupts on MPIPL
};
/**
diff --git a/src/include/usr/runtime/runtime.H b/src/include/usr/runtime/runtime.H
index 59233c566..0536d2c63 100644
--- a/src/include/usr/runtime/runtime.H
+++ b/src/include/usr/runtime/runtime.H
@@ -96,6 +96,35 @@ errlHndl_t get_host_data_section( SectionId i_section,
size_t& o_dataSize );
const size_t DATA_SIZE_UNKNOWN = 0xFFFFFFFFFFFFFFFF;
+/**
+ * @brief Update the actual count of section. Only supported for
+ * memory dump results table
+ *
+ * @param[in] i_section Chunk of data to find
+ * @param[out] i_count Actual countPhysical memory address of data
+ *
+ * @return errlHndl_t NULL on success
+ */
+errlHndl_t update_host_data_section_actual( SectionId i_section,
+ uint16_t i_count );
+
+/**
+ * @brief This function updates the actual count for the MDRT
+ * May be called at anytime, but the actual value is updated
+ * to the SPIRA during populate_attributes
+ *
+ */
+void update_MDRT_Count(uint16_t i_count);
+
+/**
+ * @brief This function writes the stored count for the MDRT
+ * out to the SPIRA
+ *
+ * @return errlHndl_t
+ */
+errlHndl_t write_MDRT_Count(void);
+
+
}
#endif
diff --git a/src/include/usr/runtime/runtime_reasoncodes.H b/src/include/usr/runtime/runtime_reasoncodes.H
index cda640d85..3c888abf1 100644
--- a/src/include/usr/runtime/runtime_reasoncodes.H
+++ b/src/include/usr/runtime/runtime_reasoncodes.H
@@ -45,7 +45,7 @@ namespace RUNTIME
MOD_TCE_INIT = 0x0D, /**< tce.C */
MOD_TCE_MAP = 0x0E, /**< tce.C */
MOD_HDATSERVICE_FINDSPIRA = 0x0F, /** hdatservice.C */
-
+ MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL = 0x10, /**< hdatservice.C */
};
enum RuntimeReasonCode
diff --git a/src/kernel/intmsghandler.C b/src/kernel/intmsghandler.C
index 4a9ae26e7..03b8996d3 100644
--- a/src/kernel/intmsghandler.C
+++ b/src/kernel/intmsghandler.C
@@ -139,6 +139,20 @@ void InterruptMsgHdlr::handleInterrupt()
// by writing the xirr back with the value read.
printk("XIRR @ %lx = %x\n",xirrAddress,xirr);
+
+ //If this is an IPI -- clean it up
+ if((xirr & 0x00FFFFFF) == INTERPROC_XISR)
+ {
+ uint64_t mfrrAddress =
+ cv_ipc_base_address + mmio_offset(pir) + MFRR_ADDR_OFFSET;
+
+ // Ignore HRMOR setting
+ mfrrAddress |= 0x8000000000000000ul;
+ uint8_t mfrr = 0xFF;
+
+ asm volatile("stbcix %0,0,%1" :: "r" (mfrr) , "r" (mfrrAddress));
+ asm volatile("stwcix %0,0,%1" :: "r" (xirr) , "r" (xirrAddress));
+ }
}
}
diff --git a/src/usr/dump/dumpCollect.C b/src/usr/dump/dumpCollect.C
index 8f85f44a9..f0089311c 100644
--- a/src/usr/dump/dumpCollect.C
+++ b/src/usr/dump/dumpCollect.C
@@ -113,6 +113,9 @@ errlHndl_t doDumpCollect(void)
int rc = 0;
bool invalidSrcSize = false;
bool invalidDestSize = false;
+ bool l_contiguous = false;
+ uint64_t l_prevSrcAddr = 0xFFFFFFFFFFFFFFFF;
+ uint32_t l_resultCount = 0x0;
// local src table info
uint64_t *vaSrcTableAddr = 0;
@@ -190,14 +193,18 @@ errlHndl_t doDumpCollect(void)
}
vaMapSrcTableAddr =
- (static_cast<uint64_t*>(mmio_dev_map(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(curSrcTableAddr)),
- THIRTYTWO_GB)));
+ (static_cast<uint64_t*>(mm_block_map(
+ reinterpret_cast<void*>(ALIGN_PAGE_DOWN
+ (curSrcTableAddr & RM_TOP_NIBBLE_MASK)),
+ THIRTYTWO_GB)));
vaSrcTableAddr = vaMapSrcTableAddr;
vaMapDestTableAddr =
- (static_cast<uint64_t*>(mmio_dev_map(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(curDestTableAddr)),
- THIRTYTWO_GB)));
+ (static_cast<uint64_t*>(mm_block_map(
+ reinterpret_cast<void*>(ALIGN_PAGE_DOWN
+ (curDestTableAddr & RM_TOP_NIBBLE_MASK)),
+ THIRTYTWO_GB)));
vaDestTableAddr = vaMapDestTableAddr;
@@ -212,6 +219,7 @@ errlHndl_t doDumpCollect(void)
// Current Destination physical and Va address
TRACFCOMP(g_trac_dump, "HBDumpCopySrcToDest DestTableIndex = %d, DestTableAddr = %.16X, VA = %.16X", curDestIndex, curDestTableAddr, vaDestTableAddr);
+ resultsTableEntry->dataSize = 0x0;
while(1)
{
@@ -219,7 +227,8 @@ errlHndl_t doDumpCollect(void)
if (bytesLeftInSrc == 0)
{
// unmap the previous src entry
- rc = mmio_dev_unmap(reinterpret_cast<void*>(vaMapSrcTableAddr));
+ rc = mm_block_unmap(
+ reinterpret_cast<void*>(vaMapSrcTableAddr));
if (rc != 0)
{
@@ -275,8 +284,10 @@ errlHndl_t doDumpCollect(void)
// map the MDST entry to a device such that we can read and write from that memory
// address
vaMapSrcTableAddr =
- (static_cast<uint64_t*>(mmio_dev_map(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(curSrcTableAddr)),
- THIRTYTWO_GB)));
+ (static_cast<uint64_t*>(mm_block_map(
+ reinterpret_cast<void*>(ALIGN_PAGE_DOWN
+ (curSrcTableAddr & RM_TOP_NIBBLE_MASK)),
+ THIRTYTWO_GB)));
vaSrcTableAddr = vaMapSrcTableAddr;
@@ -291,8 +302,8 @@ errlHndl_t doDumpCollect(void)
if (bytesLeftInDest == 0)
{
// unmap the previous dest entry
- rc = mmio_dev_unmap(reinterpret_cast<void*>(vaMapDestTableAddr));
-
+ rc = mm_block_unmap(
+ reinterpret_cast<void*>(vaMapDestTableAddr));
if (rc != 0)
{
/*@
@@ -358,6 +369,20 @@ errlHndl_t doDumpCollect(void)
curDestTableAddr = destTableEntry[curDestIndex].dataAddr;
bytesLeftInDest = destTableEntry[curDestIndex].dataSize;
+ //check to see if this destination addr is contiguous
+ l_contiguous = false;
+ if(curDestIndex !=0)
+ {
+ if(((destTableEntry[curDestIndex-1].dataAddr +
+ destTableEntry[curDestIndex-1].dataSize)
+ == curDestTableAddr)
+ && (l_prevSrcAddr == curSrcTableAddr))
+ {
+ l_contiguous = true;
+
+ }
+ }
+
// If the current dest addr or the size to copy are zero.
if ((curDestTableAddr == 0) || (bytesLeftInDest == 0))
{
@@ -410,8 +435,10 @@ errlHndl_t doDumpCollect(void)
// map the MDDT to a VA addresss
vaMapDestTableAddr =
- (static_cast<uint64_t*>(mmio_dev_map(reinterpret_cast<void*>(ALIGN_PAGE_DOWN(curDestTableAddr)),
- THIRTYTWO_GB)));
+ (static_cast<uint64_t*>(mm_block_map(
+ reinterpret_cast<void*>(ALIGN_PAGE_DOWN
+ (curDestTableAddr & RM_TOP_NIBBLE_MASK)),
+ THIRTYTWO_GB)));
vaDestTableAddr = vaMapDestTableAddr;
@@ -434,11 +461,23 @@ errlHndl_t doDumpCollect(void)
if (curResultIndex < maxResultEntries)
{
// Update the results table
- resultsTableEntry->srcAddr = curSrcTableAddr;
- resultsTableEntry->destAddr = curDestTableAddr;
- resultsTableEntry->dataSize = sizeToCopy;
- resultsTableEntry++;
- curResultIndex++;
+ if(l_contiguous)
+ {
+ (resultsTableEntry-1)->dataSize +=sizeToCopy;
+ }
+ else
+ {
+ resultsTableEntry->srcAddr = curSrcTableAddr;
+ resultsTableEntry->destAddr = curDestTableAddr;
+ resultsTableEntry->dataSize = sizeToCopy;
+ resultsTableEntry++;
+ l_resultCount++;
+ curResultIndex++;
+ if (curResultIndex < maxResultEntries)
+ {
+ resultsTableEntry->dataSize = 0x0;
+ }
+ }
}
else
{
@@ -476,6 +515,7 @@ errlHndl_t doDumpCollect(void)
curDestTableAddr += sizeToCopy;
vaSrcTableAddr += addrOffset;
vaDestTableAddr += addrOffset;
+ l_prevSrcAddr = curSrcTableAddr; //src address last used
} // end of while loop
@@ -525,6 +565,8 @@ errlHndl_t doDumpCollect(void)
break;
}
+ //Update actual count in RUNTIME
+ RUNTIME::update_MDRT_Count(l_resultCount);
}while(0);// end of do-while loop
// Got an errorlog back from get_host_data_sections
diff --git a/src/usr/dump/dumpCollect.H b/src/usr/dump/dumpCollect.H
index 09816848b..b7bf59c6f 100644
--- a/src/usr/dump/dumpCollect.H
+++ b/src/usr/dump/dumpCollect.H
@@ -32,6 +32,10 @@
namespace DUMP
{
+ enum
+ {
+ RM_TOP_NIBBLE_MASK = 0x0FFFFFFFFFFFFFFFULL,
+ };
/**
* @brief This routine retrieves first entry of the MDST, MDDT and
diff --git a/src/usr/dump/test/dumptest.H b/src/usr/dump/test/dumptest.H
index 022fecd64..fbd4523aa 100644
--- a/src/usr/dump/test/dumptest.H
+++ b/src/usr/dump/test/dumptest.H
@@ -122,14 +122,14 @@ class DumpTest: public CxxTest::TestSuite
uint64_t src_data[8] = {DUMP_TEST_SRC_DATA_AREA, 64, // 450000
DUMP_TEST_SRC_DATA_AREA + 64, 64,
- DUMP_TEST_SRC_DATA_AREA + 128, 64,
- DUMP_TEST_SRC_DATA_AREA + 192, 64};
+ DUMP_TEST_SRC_DATA_AREA + 192, 64,
+ DUMP_TEST_SRC_DATA_AREA + 256, 64};
uint64_t dst_data[8] = {DUMP_TEST_DST_DATA_AREA, 64, // 460000
DUMP_TEST_DST_DATA_AREA + 64, 64,
- DUMP_TEST_DST_DATA_AREA + 128, 64,
- DUMP_TEST_DST_DATA_AREA + 192, 64};
+ DUMP_TEST_DST_DATA_AREA + 256, 64,
+ DUMP_TEST_DST_DATA_AREA + 512, 64};
// Put the src addresses defined above into the MDST
@@ -166,18 +166,14 @@ class DumpTest: public CxxTest::TestSuite
uint64_t result_data[] = {
DUMP_TEST_SRC_DATA_AREA,
DUMP_TEST_DST_DATA_AREA,
- 64, 0,
-
- DUMP_TEST_SRC_DATA_AREA+64,
- DUMP_TEST_DST_DATA_AREA+64,
- 64, 0,
+ 64 *2, 0,
- DUMP_TEST_SRC_DATA_AREA+128,
- DUMP_TEST_DST_DATA_AREA+128,
+ DUMP_TEST_SRC_DATA_AREA+192,
+ DUMP_TEST_DST_DATA_AREA+256,
64, 0,
- DUMP_TEST_SRC_DATA_AREA+192,
- DUMP_TEST_DST_DATA_AREA+192,
+ DUMP_TEST_SRC_DATA_AREA+256,
+ DUMP_TEST_DST_DATA_AREA+512,
64, 0,
};
@@ -268,7 +264,7 @@ class DumpTest: public CxxTest::TestSuite
if (src_rc!=0)
{
TRACFCOMP(g_trac_dump, "DumpTest::DumpCollect:1 : Results Data mismatch rc = %d", src_rc);
- TS_FAIL( "DumpTest::DumpCollect ERROR : Unexpected error data mismatch in results table" );
+ TS_FAIL( "DumpTest::DumpCollect ERROR : Unexpected error DATA mismatch in results" );
}
@@ -303,8 +299,10 @@ class DumpTest: public CxxTest::TestSuite
if (result_rc!=0)
{
- TRACFCOMP(g_trac_dump, "DumpTest::DumpCollect:1 : Results Data mismatch rc = %d", result_rc);
- TS_FAIL( "DumpTest::DumpCollect ERROR : Unexpected error data mismatch in results table" );
+ TRACFCOMP(g_trac_dump, "DumpTest::DumpCollect:1 : Results Table mismatch rc = %d", result_rc);
+ TRACFBIN( g_trac_dump, "MDRT=", resultTablePtr, sizeof(result_data) );
+ TRACFBIN( g_trac_dump, "expected=", result_data, sizeof(result_data) );
+ TS_FAIL( "DumpTest::DumpCollect ERROR : Unexpected mismatch in results table" );
}
}
@@ -353,10 +351,10 @@ class DumpTest: public CxxTest::TestSuite
DUMP_TEST_SRC_DATA_AREA+256 + 128,64, // 4500180
DUMP_TEST_SRC_DATA_AREA+256 + 192, 64}; // 45001C0
- uint64_t dst_data[8] = {DUMP_TEST_DST_DATA_AREA+1024, 64, // 4600400
- DUMP_TEST_DST_DATA_AREA+1024 + 64, 32, // 4600440
- DUMP_TEST_DST_DATA_AREA+1024 + 96, 32, // 4600480
- DUMP_TEST_DST_DATA_AREA+1024+ 128, 128}; // 46004C0
+ uint64_t dst_data[8] = {DUMP_TEST_DST_DATA_AREA+1024, 64, //4600400
+ DUMP_TEST_DST_DATA_AREA+1024 + 64, 32, //4600440
+ DUMP_TEST_DST_DATA_AREA+1024 + 256, 32, //4600500
+ DUMP_TEST_DST_DATA_AREA+1024 + 128, 128};//4600520
memcpy(srcTablePtr, src_data, sizeof(src_data));
memcpy(dstTablePtr, dst_data, sizeof(dst_data));
@@ -388,18 +386,15 @@ class DumpTest: public CxxTest::TestSuite
// results output data expected
uint64_t result_data[] = {
DUMP_TEST_SRC_DATA_AREA+256,
- DUMP_TEST_DST_DATA_AREA+1024, 64, 0,
-
- DUMP_TEST_SRC_DATA_AREA+256+64,
- DUMP_TEST_DST_DATA_AREA+1024+64, 32, 0,
+ DUMP_TEST_DST_DATA_AREA+1024, 96, 0,
DUMP_TEST_SRC_DATA_AREA+256+64+32,
- DUMP_TEST_DST_DATA_AREA+1024+64+32, 32, 0,
+ DUMP_TEST_DST_DATA_AREA+1024+256, 32, 0,
DUMP_TEST_SRC_DATA_AREA+256+128,
DUMP_TEST_DST_DATA_AREA+1024+128, 64, 0,
- DUMP_TEST_SRC_DATA_AREA+256+192,
+ DUMP_TEST_SRC_DATA_AREA+256+128+64,
DUMP_TEST_DST_DATA_AREA+1024+128+64, 64, 0,
};
@@ -509,7 +504,7 @@ class DumpTest: public CxxTest::TestSuite
if (src_rc!=0)
{
TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenDest:1 : Results Data mismatch rc = %d for index = %d", src_rc, i);
- TS_FAIL( "DumpTest::DumpCollectUnevenDest ERROR : Unexpected error data mismatch in results table" );
+ TS_FAIL( "DumpTest::DumpCollectUnevenDest ERROR : Unexpected error data mismatch in results data" );
}
@@ -618,8 +613,10 @@ class DumpTest: public CxxTest::TestSuite
if (result_rc!=0)
{
- TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenDest : Results Data mismatch rc = %d", result_rc);
- TS_FAIL( "DumpTest::DumpCollectUnevenDest ERROR : Unexpected error data mismatch in results table" );
+ TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenDest : Results Table mismatch rc = %d", result_rc);
+ TRACFBIN( g_trac_dump, "MDRT=", resultTablePtr, sizeof(result_data) );
+ TRACFBIN( g_trac_dump, "expected=", result_data, sizeof(result_data) );
+ TS_FAIL( "DumpTest::DumpCollectUnevenDest ERROR : Unexpected error TABLE mismatch in results table" );
}
}
@@ -1128,8 +1125,10 @@ class DumpTest: public CxxTest::TestSuite
if (result_rc!=0)
{
- TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenSRC:1 : Results Data mismatch rc = %d", result_rc);
- TS_FAIL( "DumpTest::DumpCollectUnevenSrc ERROR : Unexpected error data mismatch in results table" );
+ TRACFCOMP(g_trac_dump, "DumpTest::DumpCollectUnevenSRC:1 : Results Table mismatch rc = %d", result_rc);
+ TRACFBIN( g_trac_dump, "MDRT=", resultTablePtr, sizeof(result_data) );
+ TRACFBIN( g_trac_dump, "expected=", result_data, sizeof(result_data) );
+ TS_FAIL( "DumpTest::DumpCollectUnevenSrc ERROR : Unexpected error TABLE mismatch in results table" );
}
}
diff --git a/src/usr/hwas/hostbootIstep.C b/src/usr/hwas/hostbootIstep.C
index 20552389b..06a591547 100644
--- a/src/usr/hwas/hostbootIstep.C
+++ b/src/usr/hwas/hostbootIstep.C
@@ -40,6 +40,7 @@
#include <targeting/attrsync.H>
#include <diag/prdf/prdfMain.H>
+#include <intr/interrupt.H>
namespace HWAS
{
@@ -115,6 +116,7 @@ void* host_discover_targets( void *io_pArgs )
// Sync attributes from Fsp
errl = syncAllAttributesFromFsp();
+
}
else
{
diff --git a/src/usr/hwpf/hwp/dram_initialization/dram_initialization.C b/src/usr/hwpf/hwp/dram_initialization/dram_initialization.C
index 9d17ceb34..09d3f6e53 100644
--- a/src/usr/hwpf/hwp/dram_initialization/dram_initialization.C
+++ b/src/usr/hwpf/hwp/dram_initialization/dram_initialization.C
@@ -853,7 +853,6 @@ void* call_host_mpipl_service( void *io_pArgs )
TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
"SUCCESS : proc_mpipl_ex_cleanup" );
-
// currently according to Adriana, the dump calls should only cause an
// istep failure when the dump collect portion of this step fails.. We
// will not fail the istep on any mbox message failures. instead we will
@@ -861,8 +860,20 @@ void* call_host_mpipl_service( void *io_pArgs )
errlHndl_t l_errMsg = NULL;
- // Need to load the dump module
- l_err = VFS::module_load( "libdump.so" );
+ // Dump relies upon the runtime module
+ // Not declaring in istep DEP list cause if we load it
+ // we want it to stay loaded
+ if ( !VFS::module_is_loaded( "libruntime.so" ) )
+ {
+ l_err = VFS::module_load( "libruntime.so" );
+
+ if ( l_err )
+ {
+ // load module returned with errl set
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "Could not load runtime module" );
+ }
+ }
// If dump module successfull loaded then continue with DumpCollect and
// messaging
@@ -952,8 +963,7 @@ void* call_host_mpipl_service( void *io_pArgs )
{
TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
"ERROR : returned from VFS::module_load (libdump.so)" );
- }
-
+ }
}
// If got an error in the procedure or collection of the dump kill the istep
diff --git a/src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C b/src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C
index d6593564f..17575d8ee 100644
--- a/src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C
+++ b/src/usr/hwpf/hwp/dram_initialization/host_mpipl_service/proc_mpipl_ex_cleanup.C
@@ -20,8 +20,8 @@
/* Origin: 30 */
/* */
/* IBM_PROLOG_END_TAG */
-// $Id: proc_mpipl_ex_cleanup.C,v 1.4 2013/02/02 21:02:23 belldi Exp $
-// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_mpipl_ex_cleanup.C,v $
+// $Id: proc_mpipl_ex_cleanup.C,v 1.5 2013/07/18 13:38:04 stillgs Exp $
+// $Source: /afs/awd.austin.ibm.com/proj/p9/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/proc_mpipl_ex_cleanup.C,v $
//------------------------------------------------------------------------------
// *|
// *! (C) Copyright International Business Machines Corp. 2012
@@ -34,11 +34,11 @@
// *! OWNER NAME : Dion Bell Email: belldi@us.ibm.com
// *! BACKUP NAME : Dion Bell Email: belldi@us.ibm.com
// *!
-// *!
-// *!
-// *!
+// *!
+// *!
+// *!
// *! Additional Note(s):
-// *!
+// *!
// *!
//------------------------------------------------------------------------------
@@ -46,6 +46,7 @@
// Includes
//------------------------------------------------------------------------------
#include "proc_mpipl_ex_cleanup.H"
+#include "p8_scom_addresses.H"
extern "C"
{
@@ -53,301 +54,222 @@ extern "C"
//------------------------------------------------------------------------------
// name: proc_mpipl_ex_cleanup
//------------------------------------------------------------------------------
- // purpose:
+ // purpose:
// Undo step that prepared fast-winkled cores for scanning and set up deep winkle mode
// SCOM regs:
- // 1) GP3 Register (NA in PERV CPLT)
- //
- // Murano (6 regs)
- // 00000000140F0014 (PCB2)
- // 00000000150F0014 (PCB2)
- // 00000000160F0014 (PCB2)
- // 000000001C0F0014 (PCB2)
- // 000000001D0F0014 (PCB2)
- // 000000001E0F0014 (PCB2)
- //
- //
- // Venice (12 regs)
- // 00000000110F0014 (PCB2)
- // 00000000120F0014 (PCB2)
- // 00000000130F0014 (PCB2)
- // 00000000140F0014 (PCB2)
- // 00000000150F0014 (PCB2)
- // 00000000160F0014 (PCB2)
- // 00000000190F0014 (PCB2)
- // 000000001A0F0014 (PCB2)
- // 000000001B0F0014 (PCB2)
- // 000000001C0F0014 (PCB2)
- // 000000001D0F0014 (PCB2)
- // 000000001E0F0014 (PCB2)
+ // 1) GP3 Register (NA in PERV CPLT)
//
// bit 27 (TP_LVLTRANS_FENCE): Electrical winkel fence. Mainly used by power management.
//
// 2) PowerManagement GP0 reg
//
- // Murano (6 regs)
- // 00000000140F0102(PCB2)
- // 00000000150F0102(PCB2)
- // 00000000160F0102(PCB2)
- // 000000001C0F0102(PCB2)
- // 000000001D0F0102(PCB2)
- // 000000001E0F0102(PCB2)
- //
- // Venice (12 regs)
- // 00000000110F0102(PCB2)
- // 00000000120F0102(PCB2)
- // 00000000130F0102(PCB2)
- // 00000000140F0102(PCB2)
- // 00000000150F0102(PCB2)
- // 00000000160F0102(PCB2)
- // 00000000190F0102(PCB2)
- // 000000001A0F0102(PCB2)
- // 000000001B0F0102(PCB2)
- // 000000001C0F0102(PCB2)
- // 000000001D0F0102(PCB2)
- // 000000001E0F0102(PCB2)
- //
// bit 22 (TP_TC_PERVASIVE_ECO_FENCE): Pervasive ECO fence
//
// bit 39 (PM_SLV_WINKLE_FENCE): Fence off the powered off chiplet in winkle. - Logical fence/hold for pcb_slave and pcb_slave_pm. For electrical fence see bit 23.
//
- // 3) PowerManagement GP1
- //
- // Murano (6 regs)
- // 0x00000000140F0105 (PCB2)
- // 0x00000000150F0105 (PCB2)
- // 0x00000000160F0105 (PCB2)
- // 0x000000001C0F0105 (PCB2)
- // 0x000000001D0F0105 (PCB2)
- // 0x000000001E0F0105 (PCB2)
- //
- // Venice (12 regs)
- // 0x00000000110F0105 (PCB2)
- // 0x00000000120F0105 (PCB2)
- // 0x00000000130F0105 (PCB2)
- // 0x00000000140F0105 (PCB2)
- // 0x00000000150F0105 (PCB2)
- // 0x00000000160F0105 (PCB2)
- // 0x00000000190F0105 (PCB2)
- // 0x000000001A0F0105 (PCB2)
- // 0x000000001B0F0105 (PCB2)
- // 0x000000001C0F0105 (PCB2)
- // 0x000000001D0F0105 (PCB2)
- // 0x000000001E0F0105 (PCB2)
+ // 3) PowerManagement GP1
//
// Bit 5: WINKLE_POWER_OFF_SEL: Winkle Power Off Select:
// Selects which voltage level to place the Core and ECO domain PFETs upon Winkle entry. 0 = Vret (Fast Winkle Mode), 1 = Voff (Deep Winkle Mode). Depending on the setting of pmicr_latency_en, this bit is controlled with a PCB-write (0) or by the PMICR in the core (1).
//
// Bit 15: PMICR_LATENCY_EN: Selects how the sleep/winkle latency (which is deep/fast) is controlled. If asserted the PMICR controls the winkle/sleep_power_off_sel in PMGP1, otherwise those bits are controlled via SCOM by OCC.
- // parameters:
+ // parameters:
// 'i_target' is chip target
//
- // returns:
+ // returns:
// FAPI_RC_SUCCESS (success, EX chiplets entered fast winkle)
- //
+ //
// getscom/putscom/getattribute fapi errors
// fapi error assigned from eCMD function failure
//
//------------------------------------------------------------------------------
fapi::ReturnCode proc_mpipl_ex_cleanup(const fapi::Target & i_target) {
- const char *procedureName = "proc_mpipl_ex_cleanup";
- fapi::ReturnCode rc; //fapi return code
- uint32_t rc_ecmd; //ecmd return code value
- const uint32_t data_size = 64; //Size of data buffer
- ecmdDataBufferBase fsi_data(data_size); //64-bit data buffer
- uint8_t attr_chip_unit_pos; //EX chiplet's unit offset within chip with respect to similar EX units
- const uint64_t EX_OFFSET_MULT = 0x01000000; //Multiplier used to calculate offset for respective EX chiplet
- uint64_t EX_GP3_REG_0x1X0F0014; //Addr of GP3 reg PCB2 for respective EX chiplet
- const uint64_t EX_GP3_REG_PCB2_ADDR = 0x00000000100F0014; //Addr of GP3 reg PCB2 (minus offset for EX chiplet)
- const uint32_t EX_GP3_REG_PCB2_BIT_POS27 = 27; //Bit 27 of GP3 reg PCB2
- uint64_t EX_PMGP0_REG_0x1X0F0102; //Addr of PM GP0 reg PCB2 for respective EX chiplet
- const uint64_t EX_PMGP0_REG_PCB2_ADDR = 0x00000000100F0102; //Addr of PM GP0 reg PCB2 (minus offset for EX chiplet)
- const uint32_t EX_PMGP0_REG_PCB2_BIT_POS22 = 22; //Bit 22 of PM GP0 reg PCB2
- const uint32_t EX_PMGP0_REG_PCB2_BIT_POS39 = 39; //Bit 39 of PM GP0 reg PCB2
- uint64_t EX_PMGP1_REG_0x1X0F0103; //Variable address, PM GP1 reg PCB for respective EX chiplet
- const uint64_t EX_PMGP1_REG_PCB_ADDR = 0x00000000100F0103; //PM GP1 reg PCB addr (minus offset for EX chiplet)
- uint64_t EX_PMGP1_REG_0x1X0F0104; //Variable address, PM GP1 reg PCB1 for respective EX chiplet
- const uint64_t EX_PMGP1_REG_PCB1_ADDR = 0x00000000100F0104; //PM GP1 reg PCB1 addr (minus offset for EX chiplet)
- uint64_t EX_PMGP1_REG_0x1X0F0105; //Variable address, PM GP1 reg PCB2 for respective EX chiplet
- const uint64_t EX_PMGP1_REG_PCB2_ADDR = 0x00000000100F0105; //PM GP1 reg PCB2 addr (minus offset for EX chiplet)
- const uint32_t EX_PMGP1_REG_PCB2_BIT_POS5 = 5; //Bit 5 (WINKLE_POWER_OFF_SEL) of PM GP1 reg PCB2
- const uint32_t EX_PMGP1_REG_PCB2_BIT_POS15 = 15; //Bit 15 (PMICR_LATENCY_EN) of PM GP1 reg PCB2
+ const char *procedureName = "proc_mpipl_ex_cleanup";
+ fapi::ReturnCode rc; //fapi return code
+ uint32_t rc_ecmd = 0; //ecmd return code value
+ ecmdDataBufferBase fsi_data(64); //64-bit data buffer
+ uint8_t attr_chip_unit_pos; //EX chiplet's unit offset within chip with respect to similar EX units
+ const uint64_t EX_OFFSET_MULT = 0x01000000; //Multiplier used to calculate offset for respective EX chiplet
- fapi::TargetType l_chiplet_type = fapi::TARGET_TYPE_EX_CHIPLET; //Type of chiplet is EX chiplet
- fapi::TargetState l_chiplet_state = fapi::TARGET_STATE_FUNCTIONAL; //State of chiplet is functional
- std::vector<fapi::Target> v_ex_chiplets; //Vector of EX chiplets
- std::vector<fapi::Target>::iterator entry_pos; //Position of entry
- std::vector<fapi::Target>::iterator end_pos; //End of vector
-
- rc = fapiGetChildChiplets(i_target, l_chiplet_type, v_ex_chiplets, l_chiplet_state); //Get vector of EX chiplets
- entry_pos = v_ex_chiplets.begin(); //first element of vector
- end_pos = v_ex_chiplets.end(); //end of vector
-
- //Parse thru EX chiplets and prepare fast-winkled cores for scanning
- while(entry_pos != end_pos ) {
- // Get EX chiplet number
- rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*entry_pos), attr_chip_unit_pos);
- if (rc) {
- FAPI_ERR("%s: fapiGetAttribute error (ATTR_CHIP_UNIT_POS)", procedureName);
- return rc;
- }
- FAPI_DBG("EX chiplet pos = 0x%02X", attr_chip_unit_pos);
-
- EX_GP3_REG_0x1X0F0014 = EX_GP3_REG_PCB2_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of GP3 reg (PCB2) for respective EX chiplet
- FAPI_DBG("GP3 reg (PCB2), addr=0x%08llX", EX_GP3_REG_0x1X0F0014);
-
- EX_PMGP0_REG_0x1X0F0102 = EX_PMGP0_REG_PCB2_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of PM GP0 reg (PCB2) for respective EX chiplet
- FAPI_DBG("PM GP0 reg (PCB2), addr=0x%08llX", EX_PMGP0_REG_0x1X0F0102 );
-
- EX_PMGP1_REG_0x1X0F0103 = EX_PMGP1_REG_PCB_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of PM GP1 reg (PCB) for respective EX chiplet
- FAPI_DBG("PM GP1 reg (PCB), addr=0x%08llX", EX_PMGP1_REG_0x1X0F0103);
-
- EX_PMGP1_REG_0x1X0F0104 = EX_PMGP1_REG_PCB1_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of PM GP1 reg (PCB1) for respective EX chiplet
- FAPI_DBG("PM GP1 reg (PCB1), addr=0x%08llX", EX_PMGP1_REG_0x1X0F0104);
-
- EX_PMGP1_REG_0x1X0F0105 = EX_PMGP1_REG_PCB2_ADDR + (EX_OFFSET_MULT * attr_chip_unit_pos); //Addr of PM GP1 reg (PCB2) for respective EX chiplet
- FAPI_DBG("PM GP1 reg (PCB2), addr=0x%08llX", EX_PMGP1_REG_0x1X0F0105);
-
+ uint64_t address; // Varible for computed addresses
+ uint64_t offset;
+ char reg_name[32]; // Character array for register names
- //Undo step that prepared fast-winkled cores for scanning
- //
- //1) Drop PB Electrical Fence (EX_GP3_OR_0x100F0014(27)=1)
- rc_ecmd = fsi_data.flushTo0();
- if(rc_ecmd) {
- FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 0's", procedureName, rc_ecmd);
- rc.setEcmdError(rc_ecmd);
- return rc;
- }
- FAPI_DBG("Asserting bit 27 of ecmdDataBufferBase that stores value of GP3 reg (addr: 0x%08llX)", EX_GP3_REG_0x1X0F0014);
- rc_ecmd = fsi_data.setBit(EX_GP3_REG_PCB2_BIT_POS27);
- if(rc_ecmd) {
- FAPI_ERR("%s: Error (%u): Could not assert bit 27 of ecmdDataBufferBase that stores value of GP3 reg (addr: 0x%08llX)", procedureName, rc_ecmd, EX_GP3_REG_0x1X0F0014);
- rc.setEcmdError(rc_ecmd);
- return rc;
- }
-
- FAPI_DBG("ecmdDataBufferBase storing value of GP3 reg (addr: 0x%08llX), val=0x%016llX", EX_GP3_REG_0x1X0F0014, fsi_data.getDoubleWord((uint32_t) 0));
- rc = fapiPutScom( i_target, EX_GP3_REG_0x1X0F0014, fsi_data );
- if (rc) {
- FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_GP3_REG_0x1X0F0014);
- return rc;
- }
-
- //2) Drop logical Pervasive/PCBS-PM fence (EX_PMGP0_OR_0x100F0102(39)=1)
- rc_ecmd = fsi_data.flushTo0();
- if(rc_ecmd) {
- FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 0's", procedureName, rc_ecmd);
- rc.setEcmdError(rc_ecmd);
- return rc;
- }
+ // Relevant PMGP0 bits
+// const uint32_t PM_DISABLE = 0;
+ const uint32_t BLOCK_REG_WKUP_SOURCE = 53;
- FAPI_DBG("Asserting bit 39 of ecmdDataBufferBase that stores value of PM GP0 reg (addr: 0x%08llX)", EX_PMGP0_REG_0x1X0F0102 );
- rc_ecmd = fsi_data.setBit(EX_PMGP0_REG_PCB2_BIT_POS39);
- if(rc_ecmd) {
- FAPI_ERR("%s: Error (%u): Could not assert bit 39 of ecmdDataBufferBase that stores value of PM GP0 reg (addr: 0x%08llX)", procedureName, rc_ecmd, EX_PMGP0_REG_0x1X0F0102);
- rc.setEcmdError(rc_ecmd);
- return rc;
- }
-
- FAPI_DBG("ecmdDataBufferBase storing value of PM GP0 reg (addr: 0x%08llX), val=0x%016llX", EX_PMGP0_REG_0x1X0F0102, fsi_data.getDoubleWord((uint32_t) 0));
- rc = fapiPutScom( i_target, EX_PMGP0_REG_0x1X0F0102, fsi_data );
- if (rc) {
- FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_PMGP0_REG_0x1X0F0102);
- return rc;
- }
-
- //3) Drop Pervasive Extended Cache Option (ECO) fence (EX_PMGP0_OR_0x100F0102(22)=1)
- rc_ecmd = fsi_data.flushTo0();
- if(rc_ecmd) {
- FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 0's", procedureName, rc_ecmd);
- rc.setEcmdError(rc_ecmd);
- return rc;
- }
-
- FAPI_DBG("Asserting bit 22 of ecmdDataBufferBase that stores value of PM GP0 reg (addr: 0x%08llX)", EX_PMGP0_REG_0x1X0F0102 );
- rc_ecmd = fsi_data.setBit(EX_PMGP0_REG_PCB2_BIT_POS22);
- if(rc_ecmd) {
- FAPI_ERR("%s: Error (%u): Could not assert bit 22 of ecmdDataBufferBase that stores value of PM GP0 reg (addr: 0x%08llX)", procedureName, rc_ecmd, EX_PMGP0_REG_0x1X0F0102);
- rc.setEcmdError(rc_ecmd);
- return rc;
- }
-
- FAPI_DBG("ecmdDataBufferBase storing value of PM GP0 reg (addr: 0x%08llX), val=0x%016llX", EX_PMGP0_REG_0x1X0F0102, fsi_data.getDoubleWord((uint32_t) 0));
- rc = fapiPutScom( i_target, EX_PMGP0_REG_0x1X0F0102, fsi_data );
- if (rc) {
- FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_PMGP0_REG_0x1X0F0102);
- return rc;
- }
-
+ // Relevant PMGP1 bits
+ const uint32_t WINKLE_POWER_OFF_SEL = 5;
- // Check bit 15 (PMICR_LATENCY_EN) of PM GP1 reg is 0, so bit 5 (WINKLE_POWER_OFF_SEL) of PM GP1 reg is controlled via SCOM write
- //
- FAPI_DBG("Checking bit 15 (PMICR_LATENCY_EN) of PM GP1 reg (addr: 0x%08llX) is 0", EX_PMGP1_REG_0x1X0F0103);
- rc = fapiGetScom(i_target, EX_PMGP1_REG_0x1X0F0103, fsi_data);
- if (rc) {
- FAPI_ERR("%s: fapiGetScom error (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_0x1X0F0103);
- return rc;
- }
- FAPI_DBG("PM GP1 reg (addr: 0x%08llX), val=0x%016llX", EX_PMGP1_REG_0x1X0F0103, fsi_data.getDoubleWord((uint32_t) 0));
-
- //Check whether bit 15 (PMICR_LATENCY_EN) of PowerManagement GP1 reg is 1
- if( fsi_data.getBit(EX_PMGP1_REG_PCB2_BIT_POS15) ) {
- FAPI_DBG("Bit pos %u (PMICR_LATENCY_EN) of PM GP1 reg (addr: 0x%08llX) is 1", EX_PMGP1_REG_PCB2_BIT_POS15, EX_PMGP1_REG_0x1X0F0103);
- FAPI_DBG("Clearing bit pos %u (PMICR_LATENCY_EN) of PM GP1 reg (addr: 0x%08llX)", EX_PMGP1_REG_PCB2_BIT_POS15, EX_PMGP1_REG_0x1X0F0103);
-
- //Clear bit 15 (PMICR_LATENCY_EN) of PM GP1 reg
- rc_ecmd = fsi_data.flushTo1();
- if(rc_ecmd) {
- FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 1's", procedureName, rc_ecmd);
- rc.setEcmdError(rc_ecmd);
- return rc;
- }
- rc_ecmd = fsi_data.clearBit(EX_PMGP1_REG_PCB2_BIT_POS15);
- if(rc_ecmd) {
- FAPI_ERR("%s: Could not clear bit pos %u of PM GP1 reg (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_PCB2_BIT_POS15, EX_PMGP1_REG_0x1X0F0104);
- rc.setEcmdError(rc_ecmd);
- return rc;
+ std::vector<fapi::Target> v_ex_chiplets; //Vector of EX chiplets
+
+
+ do
+ {
+ //Entering fapi function
+ FAPI_INF("Entering %s", procedureName);
+
+ //Get vector of EX chiplets
+ rc = fapiGetChildChiplets( i_target,
+ fapi::TARGET_TYPE_EX_CHIPLET,
+ v_ex_chiplets,
+ fapi::TARGET_STATE_FUNCTIONAL);
+ if (rc)
+ {
+ FAPI_ERR("%s: fapiGetChildChiplets error", procedureName);
+ break;
}
- //Write data to PM GP1 reg
- rc = fapiPutScom(i_target, EX_PMGP1_REG_0x1X0F0104, fsi_data);
- if (rc) {
- FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_0x1X0F0104);
- return rc;
+ FAPI_INF("Processing target %s", i_target.toEcmdString());
+
+ //Parse thru EX chiplets and prepare fast-winkled cores for deep operations
+ //Loop thru EX chiplets in vector
+ for (uint32_t counter = 0; counter < v_ex_chiplets.size(); counter++)
+ {
+
+ // Get EX chiplet number
+ rc = FAPI_ATTR_GET( ATTR_CHIP_UNIT_POS,
+ &(v_ex_chiplets[counter]),
+ attr_chip_unit_pos);
+ if (rc)
+ {
+ FAPI_ERR("%s: fapiGetAttribute error (ATTR_CHIP_UNIT_POS)", procedureName);
+ break;
+ }
+ FAPI_INF("EX chiplet pos = 0x%02X", attr_chip_unit_pos);
+
+
+ // Calculate the address offset based on chiplet number
+ offset = EX_OFFSET_MULT * attr_chip_unit_pos;
+
+ // -----------------------------------------------------------------
+ FAPI_DBG("\tOriginal register contents");
+ address = EX_GP3_0x100F0012 + offset;
+ strcpy(reg_name, "GP3");
+ rc = fapiGetScom( i_target, address, fsi_data );
+ if (rc)
+ {
+ FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
+ break;
+ }
+ FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
+
+ address = EX_PMGP0_0x100F0100 + offset;
+ strcpy(reg_name, "PMGP0");
+ rc = fapiGetScom( i_target, address, fsi_data );
+ if (rc)
+ {
+ FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
+ break;
+ }
+ FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
+
+ address = EX_PMGP1_0x100F0103 + offset;
+ strcpy(reg_name, "PMGP1");
+ rc = fapiGetScom( i_target, address, fsi_data );
+ if (rc)
+ {
+ FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
+ break;
+ }
+ FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
+ // -----------------------------------------------------------------
+
+ // Clean up configuration remnants of the fast-winkle configuration
+ // that was used to flush the chiplets after checkstop. EX chiplets
+ // will have been through SBE EX Init with certain step skippled due
+ // to MPIPL.
+
+ FAPI_INF("Re-establish Deep Winkle mode default");
+ address = EX_PMGP1_OR_0x100F0105 + offset;
+ strcpy(reg_name, "PMGP1 OR");
+
+ rc_ecmd |= fsi_data.flushTo0();
+ rc_ecmd |= fsi_data.setBit(WINKLE_POWER_OFF_SEL);
+ if(rc_ecmd)
+ {
+ FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX) with rc %x", reg_name, address, rc_ecmd);
+ rc.setEcmdError(rc_ecmd);
+ break;
+ }
+ rc = fapiPutScom(i_target, address, fsi_data);
+ if (rc)
+ {
+ FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address);
+ break;
+ }
+
+ FAPI_INF("Clear block wakeup sources to PM logic. PM is NOT re-enabled");
+ // (eg clear Block Interrrupt Sources)
+ address = EX_PMGP0_AND_0x100F0101 + offset;
+ strcpy(reg_name, "PMGP0 AND");
+
+ rc_ecmd |= fsi_data.flushTo1();
+// rc_ecmd |= fsi_data.clearBit(PM_DISABLE);
+ rc_ecmd |= fsi_data.clearBit(BLOCK_REG_WKUP_SOURCE);
+ if(rc_ecmd)
+ {
+ FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX)", reg_name, address);
+ rc.setEcmdError(rc_ecmd);
+ break;
+ }
+ rc = fapiPutScom(i_target, address, fsi_data);
+ if (rc)
+ {
+ FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address);
+ break;
+ }
+
+ // -----------------------------------------------------------------
+ FAPI_DBG("\tUpdated register contents");
+ address = EX_GP3_0x100F0012 + offset;
+ strcpy(reg_name, "GP3");
+ rc = fapiGetScom( i_target, address, fsi_data );
+ if (rc)
+ {
+ FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
+ break;
+ }
+ FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
+
+ address = EX_PMGP0_0x100F0100 + offset;
+ strcpy(reg_name, "PMGP0");
+ rc = fapiGetScom( i_target, address, fsi_data );
+ if (rc)
+ {
+ FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
+ break;
+ }
+ FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
+
+ address = EX_PMGP1_0x100F0103 + offset;
+ strcpy(reg_name, "PMGP1");
+ rc = fapiGetScom( i_target, address, fsi_data );
+ if (rc)
+ {
+ FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address);
+ break;
+ }
+ FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0));
+ // -----------------------------------------------------------------
+ } // chiplet loop
+
+ // Error exit from above loop
+ // Not really needed as outer while(0) is next but here for consistent structure
+ if (!rc.ok())
+ {
+ break;
}
- }
-
- // Assert bit 5 (WINKLE_POWER_OFF_SEL) of PM GP1 reg
- rc_ecmd = fsi_data.flushTo0();
- if(rc_ecmd) {
- FAPI_ERR("%s: Error (%u): Could not flush ecmdDataBufferBase to 0's", procedureName, rc_ecmd);
- rc.setEcmdError(rc_ecmd);
- return rc;
- }
- rc_ecmd = fsi_data.setBit(EX_PMGP1_REG_PCB2_BIT_POS5);
- if(rc_ecmd) {
- FAPI_ERR("%s: Could not assert bit pos %u of PM GP1 reg (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_PCB2_BIT_POS5, EX_PMGP1_REG_0x1X0F0105);
- rc.setEcmdError(rc_ecmd);
- return rc;
- }
- rc = fapiPutScom(i_target, EX_PMGP1_REG_0x1X0F0105, fsi_data);
- if (rc) {
- FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX)", procedureName, EX_PMGP1_REG_0x1X0F0105);
- return rc;
- }
-
- entry_pos++; //Point to next EX chiplet
- }
+ } while (0);
//Exiting fapi function
- FAPI_DBG("Exiting fapi function: %s", procedureName);
-
+ FAPI_INF("Exiting %s", procedureName);
+
return rc;
}
-
-
-
+
} // extern "C"
diff --git a/src/usr/hwpf/hwp/start_payload/start_payload.C b/src/usr/hwpf/hwp/start_payload/start_payload.C
index 36c076026..f7b132295 100644
--- a/src/usr/hwpf/hwp/start_payload/start_payload.C
+++ b/src/usr/hwpf/hwp/start_payload/start_payload.C
@@ -300,6 +300,15 @@ void* call_host_runtime_setup( void *io_pArgs )
}
else
{
+ //Update the MDRT value
+ l_err = RUNTIME::write_MDRT_Count();
+ if(l_err != NULL)
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
+ "write_MDRT_Count failed" );
+ break;
+ }
+
// Write the HostServices attributes into mainstore
l_err = RUNTIME::populate_attributes();
if ( l_err )
diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H
index 358701fb4..0a5b2dc19 100644
--- a/src/usr/initservice/extinitsvc/extinitsvctasks.H
+++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H
@@ -65,6 +65,19 @@ const TaskInfo g_exttaskinfolist[] = {
},
/**
+ * @brief FSI Device Driver
+ */
+
+ {
+ "libfsi.so" , // taskname
+ NULL, // no pointer to fn
+ {
+ INIT_TASK, // task type
+ EXT_IMAGE, // Extended Module
+ }
+ },
+
+ /**
* @brief External interrupt resource provider
*/
{
@@ -103,18 +116,6 @@ const TaskInfo g_exttaskinfolist[] = {
},
- /**
- * @brief FSI Device Driver
- */
-
- {
- "libfsi.so" , // taskname
- NULL, // no pointer to fn
- {
- INIT_TASK, // task type
- EXT_IMAGE, // Extended Module
- }
- },
/**
* @brief FSI SCOM Device Driver
diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C
index 11339dbc6..a07fb980c 100644
--- a/src/usr/intr/intrrp.C
+++ b/src/usr/intr/intrrp.C
@@ -45,6 +45,7 @@
#include <sys/time.h>
#include <sys/vfs.h>
#include <hwas/common/hwasCallout.H>
+#include <fsi/fsiif.H>
#define INTR_TRACE_NAME INTR_COMP_NAME
@@ -73,7 +74,7 @@ const uint32_t IntrRp::cv_PE_BAR_SCOM_LIST[] =
};
trace_desc_t * g_trac_intr = NULL;
-TRAC_INIT(&g_trac_intr, INTR_TRACE_NAME, KILOBYTE, TRACE::BUFFER_SLOW);
+TRAC_INIT(&g_trac_intr, INTR_TRACE_NAME, 16*KILOBYTE, TRACE::BUFFER_SLOW);
/**
* setup _start and handle barrier
@@ -609,6 +610,133 @@ errlHndl_t IntrRp::setBAR(TARGETING::Target * i_target,
return err;
}
+errlHndl_t IntrRp::getPsiIRSN(TARGETING::Target * i_target, uint32_t& o_irsn)
+{
+ errlHndl_t err = NULL;
+
+ // Setup PHBISR
+ // EN.TPC.PSIHB.PSIHB_ISRN_REG set to 0x00030003FFFF0000
+ PSIHB_ISRN_REG_t reg;
+ size_t scom_len = sizeof(uint64_t);
+
+ do{
+ err = deviceRead
+ ( i_target,
+ &reg,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG));
+
+ if(err)
+ {
+ break;
+ }
+
+ o_irsn = reg.irsn & reg.mask;
+ }while(0);
+
+
+ TRACFCOMP(g_trac_intr,"PSIHB_ISRN: 0x%x",o_irsn);
+
+ return err;
+}
+
+errlHndl_t IntrRp::getNxIRSN(TARGETING::Target * i_target, uint32_t& o_irsn)
+{
+ errlHndl_t err = NULL;
+
+ size_t scom_len = sizeof(uint64_t);
+ uint64_t reg = 0x0;
+
+ do{
+ err = deviceRead
+ ( i_target,
+ &reg,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(NX_BUID_SCOM_ADDR));
+
+ if(err)
+ {
+ break;
+ }
+
+ o_irsn = ((static_cast<uint32_t>(reg >> NX_IRSN_COMP_SHIFT)
+ & NX_IRSN_COMP_MASK) &
+ ((static_cast<uint32_t>(reg >> NX_IRSN_MASK_SHIFT)
+ & NX_IRSN_MASK_MASK) || NX_IRSN_UPPER_MASK));
+ }while(0);
+
+
+ TRACFCOMP(g_trac_intr,"NX_ISRN: 0x%x",o_irsn);
+
+ return err;
+}
+
+
+errlHndl_t IntrRp::getPcieIRSNs(TARGETING::Target * i_target,
+ std::vector<uint32_t> &o_irsn)
+{
+ errlHndl_t err = NULL;
+ o_irsn.clear();
+
+ uint64_t reg = 0;
+ uint64_t mask = 0;
+
+ size_t scom_len = sizeof(uint64_t);
+
+ do{
+ // PE
+ for(size_t i = 0;
+ i < sizeof(cv_PE_IRSN_COMP_SCOM_LIST)
+ /sizeof(cv_PE_IRSN_COMP_SCOM_LIST[0]);
+ ++i)
+ {
+ scom_len = sizeof(uint64_t);
+ err = deviceRead
+ (
+ i_target,
+ &reg,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(cv_PE_IRSN_COMP_SCOM_LIST[i])
+ );
+ if(err)
+ {
+ break;
+ }
+
+
+ scom_len = sizeof(uint64_t);
+ err = deviceRead
+ (
+ i_target,
+ &mask,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(cv_PE_IRSN_MASK_SCOM_LIST[i])
+ );
+ if(err)
+ {
+ break;
+ }
+
+ uint64_t l_irsn64 = reg & mask;
+ reg >>= PE_IRSN_SHIFT;
+ mask >>=PE_IRSN_SHIFT;
+ l_irsn64 >>=PE_IRSN_SHIFT;
+ uint32_t l_irsn = l_irsn64;
+ TRACFCOMP(g_trac_intr,"PE_ISRN[0x%08x] PE%d ", l_irsn, i);
+ if(l_irsn != 0x0)
+ {
+ o_irsn.push_back(l_irsn);
+ }
+ }
+ if(err)
+ {
+ break;
+ }
+ }while(0);
+
+ return err;
+}
+
errlHndl_t IntrRp::initIRSCReg(TARGETING::Target * i_target)
{
@@ -688,6 +816,11 @@ errlHndl_t IntrRp::initXIVR(enum ISNvalue_t i_isn, bool i_enable)
switch(i_isn)
{
+ case ISN_PSI:
+ xivr.priority = PsiHbXivr::PSI_PRIO;
+ scom_addr = PsiHbXivr::PSI_XIVR_ADRR;
+ break;
+
case ISN_OCC:
xivr.priority = PsiHbXivr::OCC_PRIO;
scom_addr = PsiHbXivr::OCC_XIVR_ADRR;
@@ -792,6 +925,7 @@ errlHndl_t IntrRp::maskXIVR(TARGETING::Target *i_target)
static const XIVR_INFO xivr_info[] =
{
+ {ISN_PSI, PsiHbXivr::PSI_XIVR_ADRR},
{ISN_OCC, PsiHbXivr::OCC_XIVR_ADRR},
{ISN_FSI, PsiHbXivr::FSI_XIVR_ADRR},
{ISN_LPC, PsiHbXivr::LPC_XIVR_ADRR},
@@ -1186,12 +1320,12 @@ errlHndl_t IntrRp::hw_disableRouting(TARGETING::Target * i_proc,
PSIHB_ISRN_REG_t reg;
err = deviceRead
- (
- i_proc,
- &reg,
- scom_len,
- DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG)
- );
+ (
+ i_proc,
+ &reg,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG)
+ );
if(err)
{
@@ -1200,23 +1334,23 @@ errlHndl_t IntrRp::hw_disableRouting(TARGETING::Target * i_proc,
switch(i_rx_tx)
{
- case INTR_UPSTREAM:
- reg.uie = 0; //upstream interrupt enable = 0 (disable)
- break;
+ case INTR_UPSTREAM:
+ reg.uie = 0; //upstream interrupt enable = 0 (disable)
+ break;
- case INTR_DOWNSTREAM:
- reg.die = 0; //downstream interrupt enable = 0 (disable)
- break;
+ case INTR_DOWNSTREAM:
+ reg.die = 0; //downstream interrupt enable = 0 (disable)
+ break;
}
scom_len = sizeof(uint64_t);
err = deviceWrite
- (
- i_proc,
- &reg,
- scom_len,
- DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG)
- );
+ (
+ i_proc,
+ &reg,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG)
+ );
if(err)
{
@@ -1245,13 +1379,13 @@ errlHndl_t IntrRp::hw_disableRouting(TARGETING::Target * i_proc,
switch(i_rx_tx)
{
case INTR_UPSTREAM:
- // reset bit PE_IRSN_RX
- reg &= ~((1ull << (63-PE_IRSN_RX)));
+ // reset bit PE_IRSN_UPSTREAM
+ reg &= ~((1ull << (63-PE_IRSN_UPSTREAM)));
break;
case INTR_DOWNSTREAM:
- // reset bit PE_IRSN_TX
- reg &= ~((1ull << (63-PE_IRSN_TX)));
+ // reset bit PE_IRSN_DOWNSTREAM
+ reg &= ~((1ull << (63-PE_IRSN_DOWNSTREAM)));
break;
}
@@ -1328,12 +1462,12 @@ errlHndl_t IntrRp::hw_resetIRSNregs(TARGETING::Target * i_proc)
// all other fields = 0
err = deviceWrite
- (
- i_proc,
- &reg1,
- scom_len,
- DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG)
- );
+ (
+ i_proc,
+ &reg1,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(PSIHB_ISRN_REG_t::PSIHB_ISRN_REG)
+ );
if(err)
{
break;
@@ -1397,158 +1531,476 @@ errlHndl_t IntrRp::hw_resetIRSNregs(TARGETING::Target * i_proc)
return err;
}
+//----------------------------------------------------------------------------
+
+errlHndl_t IntrRp::blindIssueEOIs(TARGETING::Target * i_proc)
+{
+ errlHndl_t err = NULL;
+
+ TARGETING::TargetHandleList procCores;
+ getChildChiplets(procCores, i_proc, TYPE_CORE, false); //state can change
+
+ do
+ {
+ //Issue eio to IPIs first
+ for(TARGETING::TargetHandleList::iterator
+ core = procCores.begin();
+ core != procCores.end();
+ ++core)
+ {
+ FABRIC_CHIP_ID_ATTR chip = i_proc->getAttr<ATTR_FABRIC_CHIP_ID>();
+ FABRIC_NODE_ID_ATTR node = i_proc->getAttr<ATTR_FABRIC_NODE_ID>();
+ CHIP_UNIT_ATTR coreId =
+ (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+
+ PIR_t pir(0);
+ pir.nodeId = node;
+ pir.chipId = chip;
+ pir.coreId = coreId;
+
+ size_t threads = cpu_thread_count();
+ for(size_t thread = 0; thread < threads; ++thread)
+ {
+ pir.threadId = thread;
+ uint64_t xirrAddr = iv_baseAddr +
+ cpuOffsetAddr(pir);
+ uint32_t * xirrPtr =
+ reinterpret_cast<uint32_t*>(xirrAddr + XIRR_OFFSET);
+ uint8_t * mfrrPtr = reinterpret_cast<uint8_t*>(
+ xirrAddr + MFRR_OFFSET);
+
+ //need to set mfrr to 0xFF first
+ TRACDCOMP(g_trac_intr,"Clearing IPI to xirrPtr[%p]", xirrPtr);
+ *mfrrPtr = 0xFF;
+ *xirrPtr = 0xFF000002;
+ }
+ }
+
+ PIR_t pir(iv_masterCpu);
+ pir.threadId = 0;
+ //Can just write all EOIs to master core thread 0 XIRR
+ uint64_t xirrAddr = iv_baseAddr + cpuOffsetAddr(pir);
+ volatile uint32_t * xirrPtr =
+ reinterpret_cast<uint32_t*>(xirrAddr +XIRR_OFFSET);
+
+
+ //Issue eio to PSI logic
+ uint32_t l_psiBaseIsn;
+ err = getPsiIRSN(i_proc, l_psiBaseIsn);
+ if(err)
+ {
+ break;
+ }
+
+ //Only issue if ISN is non zero (ie set)
+ if(l_psiBaseIsn)
+ {
+ l_psiBaseIsn |= 0xFF000000;
+ uint32_t l_psiMaxIsn = l_psiBaseIsn + ISN_HOST;
+
+ TRACFCOMP(g_trac_intr,"Issuing EOI to PSIHB range %x - %x",
+ l_psiBaseIsn, l_psiMaxIsn);
+
+ for(uint32_t l_isn = l_psiBaseIsn; l_isn < l_psiMaxIsn; ++l_isn)
+ {
+ TRACDCOMP(g_trac_intr," xirrPtr[%p] xirr[%x]\n", xirrPtr, l_isn);
+ *xirrPtr = l_isn;
+ }
+ }
+
+
+ //Issue EIOs to PE (PCIE) ISN
+ std::vector<uint32_t> l_peIsn;
+ err = getPcieIRSNs(i_proc, l_peIsn);
+ if(err)
+ {
+ break;
+ }
+
+ for(std::vector<uint32_t>::iterator peIsn = l_peIsn.begin();
+ peIsn != l_peIsn.end();
+ ++peIsn)
+ {
+ //now need to issue on all SN up to 2048
+ uint32_t l_peBaseIsn = (*peIsn) | 0xFF000000;
+ uint32_t l_peMaxIsn = l_peBaseIsn + MAX_PE_IRSN_SN;
+ TRACFCOMP(g_trac_intr,"Issuing EOI to PCIE range %x - %x",
+ l_peBaseIsn, l_peMaxIsn);
+
+ for(uint32_t l_isn = l_peBaseIsn; l_isn < l_peMaxIsn; ++l_isn)
+ {
+ *xirrPtr = l_isn;
+ }
+ }
+
+ //Issue eio to NX logic
+ uint32_t l_nxBaseIsn;
+ err = getNxIRSN(i_proc, l_nxBaseIsn);
+ if(err)
+ {
+ break;
+ }
+
+ //Only issue if ISN is non zero (ie set)
+ if(l_nxBaseIsn)
+ {
+ l_nxBaseIsn |= 0xFF000000;
+ uint32_t l_nxMaxIsn = l_nxBaseIsn + MAX_NX_IRSN_SN;
+ TRACFCOMP(g_trac_intr,"Issuing EOI to NX range % - %x",
+ l_nxBaseIsn, l_nxMaxIsn);
+
+ for(uint32_t l_isn = l_nxBaseIsn; l_isn < l_nxMaxIsn; ++l_isn)
+ {
+ *xirrPtr = l_isn;
+ }
+ }
+ } while(0);
+ return err;
+}
+
//----------------------------------------------------------------------------
-errlHndl_t IntrRp::hw_disableIntrMpIpl()
+errlHndl_t IntrRp::findProcs_Cores(TARGETING::TargetHandleList & o_procs,
+ TARGETING::TargetHandleList& o_cores)
{
errlHndl_t err = NULL;
+
do
{
+ //Build a list of "functional" processors. This needs to be
+ //done without targetting support (just blueprint) since
+ //on MPIPL the targeting information is obtained in
+ //discover_targets -- much later in the IPL.
+
+ //Since this is MPIPL we will rely on two things:
+ // 1) FSI will be active to present chips
+ // 2) The MPIPL HW bit in CFAM 2839 will be set
+
+ //force FSI to init so we can rely on slave data
+ err = FSI::initializeHardware();
+ if(err)
+ {
+ break;
+ }
+
TARGETING::TargetHandleList procChips;
- getAllChips(procChips, TYPE_PROC);
+ TARGETING::PredicateCTM predProc( TARGETING::CLASS_CHIP,
+ TARGETING::TYPE_PROC );
- TARGETING::TargetHandleList procCores;
- getAllChiplets(procCores, TYPE_CORE);
+ TARGETING::TargetService& tS = TARGETING::targetService();
+ TARGETING::Target * sysTarget = NULL;
+ tS.getTopLevelTarget( sysTarget );
+ assert( sysTarget != NULL );
+
+ TARGETING::Target* masterProcTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle(
+ masterProcTarget );
+
+ tS.getAssociated( procChips,
+ sysTarget,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL,
+ &predProc );
- // Disable upstream intr routing on all processor chips
for(TARGETING::TargetHandleList::iterator proc = procChips.begin();
proc != procChips.end();
++proc)
{
- // disable upstream intr routing
- err = hw_disableRouting(*proc,INTR_UPSTREAM);
- if(err)
+ //if master proc -- just add it as we are running on it
+ if (*proc == masterProcTarget)
{
- break;
+ o_procs.push_back(*proc);
+ continue;
+ }
+
+ //First see if present
+ if(FSI::isSlavePresent(*proc))
+ {
+ TRACFCOMP(g_trac_intr,"Proc %x detected via FSI", TARGETING::get_huid(*proc));
+
+ //Second check to see if MPIPL bit is on cfam "2839" which
+ //Note 2839 is ecmd addressing, real address is 0x28E4 (byte)
+ uint64_t l_addr = 0x28E4;
+ uint32_t l_data = 0;
+ size_t l_size = sizeof(uint32_t);
+ err = deviceRead(*proc,
+ &l_data,
+ l_size,
+ DEVICE_FSI_ADDRESS(l_addr));
+ if (err)
+ {
+ TRACFCOMP(g_trac_intr,"Failed to read CFAM 2838 on %x",
+ TARGETING::get_huid(*proc));
+ break;
+ }
+
+ TRACFCOMP(g_trac_intr,"Proc %x 2839 val [%x]", TARGETING::get_huid(*proc),
+ l_data);
+
+ if(l_data & 0x80000000)
+ {
+ //Chip is present and functional -- add it to our list
+ o_procs.push_back(*proc);
+
+ //Also need to force it to use Xscom
+ //Note that it has to support (ie it is part of the SMP)
+ ScomSwitches l_switches =
+ (*proc)->getAttr<ATTR_SCOM_SWITCHES>();
+
+ l_switches.useFsiScom = 0;
+ l_switches.useXscom = 1;
+
+ (*proc)->setAttr<ATTR_SCOM_SWITCHES>(l_switches);
+ }
}
}
- if(err)
+ if (err)
{
break;
}
- // Set interrupt presenter to allow all interrupts
- for(TARGETING::TargetHandleList::iterator
- core = procCores.begin();
- core != procCores.end();
+
+ //Build up a list of all possible cores (don't care if func/present,
+ //just that they exist in the blueprint
+ TARGETING::TargetHandleList l_cores;
+ for(TARGETING::TargetHandleList::iterator proc = o_procs.begin();
+ proc != o_procs.end();
+ ++proc)
+ {
+ l_cores.clear();
+ getChildChiplets(l_cores, *proc, TYPE_CORE, false);
+ for(TARGETING::TargetHandleList::iterator core = l_cores.begin();
+ core != l_cores.end();
+ ++core)
+ {
+ o_cores.push_back(*core);
+ }
+ }
+ }while(0);
+
+ return err;
+}
+
+void IntrRp::allowAllInterrupts(TARGETING::Target* i_core)
+{
+ const TARGETING::Target * proc = getParentChip(i_core);
+
+ FABRIC_CHIP_ID_ATTR chip = proc->getAttr<ATTR_FABRIC_CHIP_ID>();
+ FABRIC_NODE_ID_ATTR node = proc->getAttr<ATTR_FABRIC_NODE_ID>();
+ CHIP_UNIT_ATTR coreId = i_core->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+
+ PIR_t pir(0);
+ pir.nodeId = node;
+ pir.chipId = chip;
+ pir.coreId = coreId;
+
+ size_t threads = cpu_thread_count();
+ for(size_t thread = 0; thread < threads; ++thread)
+ {
+ pir.threadId = thread;
+ uint64_t cpprAddr=cpuOffsetAddr(pir)+iv_baseAddr+CPPR_OFFSET;
+ uint8_t *cppr = reinterpret_cast<uint8_t*>(cpprAddr);
+ *cppr = 0xff; // allow all interrupts
+ }
+
+}
+
+void IntrRp::disableAllInterrupts(TARGETING::Target* i_core)
+{
+ const TARGETING::Target * proc = getParentChip(i_core);
+
+ FABRIC_CHIP_ID_ATTR chip = proc->getAttr<ATTR_FABRIC_CHIP_ID>();
+ FABRIC_NODE_ID_ATTR node = proc->getAttr<ATTR_FABRIC_NODE_ID>();
+ CHIP_UNIT_ATTR coreId = i_core->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+
+ PIR_t pir(0);
+ pir.nodeId = node;
+ pir.chipId = chip;
+ pir.coreId = coreId;
+
+ size_t threads = cpu_thread_count();
+ for(size_t thread = 0; thread < threads; ++thread)
+ {
+ pir.threadId = thread;
+ disableInterruptPresenter(pir);
+ }
+}
+
+void IntrRp::drainMpIplInterrupts(TARGETING::TargetHandleList & i_cores)
+{
+ TRACFCOMP(g_trac_intr,"Drain pending interrupts");
+ bool interrupt_found = false;
+ size_t retryCount = 10;
+
+ do
+ {
+ interrupt_found = false;
+ nanosleep(0,1000000); // 1 ms
+
+ for(TARGETING::TargetHandleList::iterator
+ core = i_cores.begin();
+ core != i_cores.end();
++core)
{
const TARGETING::Target * proc = getParentChip(*core);
FABRIC_CHIP_ID_ATTR chip = proc->getAttr<ATTR_FABRIC_CHIP_ID>();
FABRIC_NODE_ID_ATTR node = proc->getAttr<ATTR_FABRIC_NODE_ID>();
- CHIP_UNIT_ATTR coreId =
- (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+ CHIP_UNIT_ATTR coreId =
+ (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>();
PIR_t pir(0);
pir.nodeId = node;
pir.chipId = chip;
pir.coreId = coreId;
+ TRACFCOMP(g_trac_intr," n%d p%d c%d", node, chip, coreId);
size_t threads = cpu_thread_count();
for(size_t thread = 0; thread < threads; ++thread)
{
pir.threadId = thread;
- uint64_t cpprAddr=cpuOffsetAddr(pir)+iv_baseAddr+CPPR_OFFSET;
- uint8_t *cppr = reinterpret_cast<uint8_t*>(cpprAddr);
- *cppr = 0xff; // allow all interrupts
+ uint64_t xirrAddr = iv_baseAddr +
+ cpuOffsetAddr(pir) + XIRR_RO_OFFSET;
+ uint32_t * xirrPtr =
+ reinterpret_cast<uint32_t*>(xirrAddr);
+ uint32_t xirr = *xirrPtr & 0x00FFFFFF;
+ TRACDCOMP(g_trac_intr," xirrPtr[%p] xirr[%x]\n", xirrPtr, xirr);
+ if(xirr)
+ {
+ // Found pending interrupt!
+ interrupt_found = true;
+
+ TRACFCOMP(g_trac_intr,
+ ERR_MRK
+ "Pending interrupt found on MPIPL."
+ " CpuId:0x%x XIRR:0x%x",
+ pir.word,
+ xirr);
+ uint8_t * mfrrPtr =
+ reinterpret_cast<uint8_t*>(xirrAddr + MFRR_OFFSET);
+ // Signal EOI - read then write xirr value
+ ++xirrPtr; // move to RW XIRR reg
+ volatile uint32_t xirr_rw = *xirrPtr;
+
+ //If IPI need to set mfrr to 0xFF
+ if(INTERPROC_XISR == xirr)
+ {
+ *mfrrPtr = 0xFF;
+ }
+
+ *xirrPtr = xirr_rw;
+ --xirrPtr; // back to RO XIRR reg
+ }
}
}
+ } while(interrupt_found == true && --retryCount != 0);
- // Now look for interrupts
- bool interrupt_found = false;
- size_t retryCount = 10;
+ if(interrupt_found && (retryCount == 0))
+ {
+ // traces above should identify stuck interrupt
+ INITSERVICE::doShutdown(INTR::RC_PERSISTANT_INTERRUPTS);
+ }
+}
+
+
+
+errlHndl_t IntrRp::hw_disableIntrMpIpl()
+{
+ errlHndl_t err = NULL;
+ TARGETING::TargetHandleList funcProc, procCores;
+
+ //Need to clear out all pending interrupts. This includes
+ //ones that PHYP already accepted and ones "hot" in the XIRR
+ //register. Must be done for all processors prior to opening
+ //up traffic for mailbox (since we switch the IRSN). PHYP
+ //can route PSI interrupts to any chip in the system so all
+ //must be cleaned up prior to switching
- do
+ do
+ {
+ //Get the procs/cores
+ err = findProcs_Cores(funcProc, procCores);
+ if(err)
{
- interrupt_found = false;
- nanosleep(0,1000000); // 1 ms
+ break;
+ }
- for(TARGETING::TargetHandleList::iterator
- core = procCores.begin();
- core != procCores.end();
- ++core)
- {
- const TARGETING::Target * proc = getParentChip(*core);
-
- FABRIC_CHIP_ID_ATTR chip =
- proc->getAttr<ATTR_FABRIC_CHIP_ID>();
- FABRIC_NODE_ID_ATTR node =
- proc->getAttr<ATTR_FABRIC_NODE_ID>();
- CHIP_UNIT_ATTR coreId =
- (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>();
-
- PIR_t pir(0);
- pir.nodeId = node;
- pir.chipId = chip;
- pir.coreId = coreId;
-
- size_t threads = cpu_thread_count();
- for(size_t thread = 0; thread < threads; ++thread)
- {
- pir.threadId = thread;
- uint64_t xirrAddr = iv_baseAddr +
- cpuOffsetAddr(pir) + XIRR_RO_OFFSET;
- uint32_t * xirrPtr =
- reinterpret_cast<uint32_t*>(xirrAddr);
- uint32_t xirr = *xirrPtr & 0x00FFFFFF;
- if(xirr) // pending interrupt
- {
- // Found pending interrupt!
- interrupt_found = true;
-
- TRACFCOMP(g_trac_intr,
- ERR_MRK
- "Pending interrupt found on MPIPL."
- " CpuId:0x%x XIRR:0x%x",
- pir.word,
- xirr);
- // Signal EOI - read then write xirr value
- ++xirrPtr; // move to RW XIRR reg
- volatile uint32_t xirr_rw = *xirrPtr;
- *xirrPtr = xirr_rw;
- --xirrPtr; // back to RO XIRR reg
- }
- }
- }
- } while(interrupt_found == true && --retryCount != 0);
+ //since HB will need to use PSI interrupt block, we need to
+ //perform the extra step of disabling FSP PSI interrupts at
+ //source(theoretically upstream disable should have handled,
+ //but it seesms to slip through somehow and doesn't get fully
+ //cleaned up cause we clear the XIVR
+ for(TARGETING::TargetHandleList::iterator proc = funcProc.begin();
+ (proc != funcProc.end()) && !err;
+ ++proc)
+ {
+ uint64_t reg = PSI_FSP_INT_ENABLE;
+ size_t scom_len = sizeof(uint64_t);
+ err = deviceWrite
+ (
+ (*proc),
+ &reg,
+ scom_len,
+ DEVICE_SCOM_ADDRESS(PSI_HBCR_AND_SCOM_ADDR)
+ );
+ }
+ if(err)
+ {
+ break;
+ }
- if(interrupt_found && (retryCount == 0))
+ // Disable upstream intr routing on all processor chips
+ TRACFCOMP(g_trac_intr,"Disable upstream interrupt");
+ for(TARGETING::TargetHandleList::iterator proc = funcProc.begin();
+ (proc != funcProc.end()) && !err;
+ ++proc)
+ {
+ // disable upstream intr routing
+ err = hw_disableRouting(*proc,INTR_UPSTREAM);
+ }
+ if(err)
{
- // traces above should identify stuck interrupt
- INITSERVICE::doShutdown(INTR::RC_PERSISTANT_INTERRUPTS);
+ break;
}
- // Disable all interrupt presenters
+ // Set interrupt presenter to allow all interrupts
+ TRACFCOMP(g_trac_intr,"Allow interrupts");
for(TARGETING::TargetHandleList::iterator
core = procCores.begin();
core != procCores.end();
++core)
{
- const TARGETING::Target * proc = getParentChip(*core);
+ allowAllInterrupts(*core);
+ }
- FABRIC_CHIP_ID_ATTR chip = proc->getAttr<ATTR_FABRIC_CHIP_ID>();
- FABRIC_NODE_ID_ATTR node = proc->getAttr<ATTR_FABRIC_NODE_ID>();
- CHIP_UNIT_ATTR coreId =
- (*core)->getAttr<TARGETING::ATTR_CHIP_UNIT>();
+ // Now look for interrupts
+ drainMpIplInterrupts(procCores);
- PIR_t pir(0);
- pir.nodeId = node;
- pir.chipId = chip;
- pir.coreId = coreId;
+ // Issue blind EOIs to all threads IPIs and to clean up stale XIRR
+ TRACFCOMP(g_trac_intr,"Issue blind EOIs to all ISRN and IPIs");
+ for(TARGETING::TargetHandleList::iterator proc = funcProc.begin();
+ (proc != funcProc.end()) && !err;
+ ++proc)
+ {
+ err = blindIssueEOIs(*proc);
+ }
+ if(err)
+ {
+ break;
+ }
- size_t threads = cpu_thread_count();
- for(size_t thread = 0; thread < threads; ++thread)
- {
- pir.threadId = thread;
- disableInterruptPresenter(pir);
- }
+ // Disable all interrupt presenters
+ for(TARGETING::TargetHandleList::iterator core = procCores.begin();
+ core != procCores.end();
+ ++core)
+ {
+ disableAllInterrupts(*core);
}
// disable downstream routing and clean up IRSN regs
- for(TARGETING::TargetHandleList::iterator proc = procChips.begin();
- proc != procChips.end();
+ for(TARGETING::TargetHandleList::iterator proc = funcProc.begin();
+ proc != funcProc.end();
++proc)
{
// disable downstream routing
@@ -1564,6 +2016,15 @@ errlHndl_t IntrRp::hw_disableIntrMpIpl()
{
break;
}
+
+ //Now mask off all XIVRs under the PSI unit
+ //This prevents hot PSI mbox interrupts from flowing up to HB
+ //and allows PHYP to deal with them
+ err = maskXIVR(*proc);
+ if(err)
+ {
+ break;
+ }
}
if(err)
{
@@ -1573,6 +2034,7 @@ errlHndl_t IntrRp::hw_disableIntrMpIpl()
return err;
}
+
void IntrRp::cleanCheck()
{
TARGETING::TargetHandleList procCores;
@@ -1847,5 +2309,3 @@ uint64_t INTR::getIntpAddr(const TARGETING::Target * i_ex, uint8_t i_thread)
pir.word & (InterruptMsgHdlr::P8_PIR_THREADID_MSK |
InterruptMsgHdlr::P8_PIR_COREID_MSK)));
}
-
-
diff --git a/src/usr/intr/intrrp.H b/src/usr/intr/intrrp.H
index a05bff542..488f27706 100644
--- a/src/usr/intr/intrrp.H
+++ b/src/usr/intr/intrrp.H
@@ -123,6 +123,14 @@ namespace INTR
// Used to enable/disable and control interrupt routing
NX_BUID_SCOM_ADDR = 0x0201308E, //INTR CTRL for NX
NX_BUID_ENABLE = 0, //INTR Enable bit for NX
+ NX_IRSN_COMP_MASK = 0x7FFFF,
+ NX_IRSN_MASK_MASK = 0x1FFF,
+ NX_IRSN_UPPER_MASK = 0x7E000,
+ NX_IRSN_COMP_SHIFT = 44,
+ NX_IRSN_MASK_SHIFT = 31,
+ MAX_NX_IRSN_SN = 32,
+
+
PE0_IRSN_COMP_SCOM_ADDR = 0x0201201A, //INTR IRSN compare
PE0_IRSN_MASK_SCOM_ADDR = 0x0201201B, //INTR IRSN mask
@@ -137,8 +145,14 @@ namespace INTR
PE2_BAREN_SCOM_ADDR = 0x02012845, //INTR enable/disable
// Bit pos in PEx_BAREN_SCOM register
- PE_IRSN_RX = 3, // upstream enable
- PE_IRSN_TX = 4, // downstream enable
+ PE_IRSN_DOWNSTREAM = 3, // downstream (PE RX enable)
+ PE_IRSN_UPSTREAM = 4, // upstream (PE TX enable)
+ PE_IRSN_SHIFT = 45,
+ MAX_PE_IRSN_SN = 2048,
+
+
+ PSI_FSP_INT_ENABLE = 0x1000000000000000ULL,
+ PSI_HBCR_AND_SCOM_ADDR = 0x02010913,
};
enum INTR_ROUTING_t
@@ -228,7 +242,9 @@ namespace INTR
LPC_PRIO = 0x40,
LCL_ERR_PRIO = 0x10,
HOST_PRIO = 0x50,
+ PSI_PRIO = 0x60,
+ PSI_XIVR_ADRR = 0x02010910,
OCC_XIVR_ADRR = 0x02010916,
FSI_XIVR_ADRR = 0x02010917,
LPC_XIVR_ADRR = 0x02010918,
@@ -282,7 +298,6 @@ namespace INTR
typedef std::vector<TARGETING::Target *> ChipList_t;
typedef std::vector<ISNvalue_t> ISNList_t;
-
msg_q_t iv_msgQ; //!< Kernel Interrupt message queue
Registry_t iv_registry; //!< registered interrupt type
uint64_t iv_baseAddr; //!< Base address of hw INTR regs
@@ -419,6 +434,14 @@ namespace INTR
errlHndl_t hw_disableRouting(TARGETING::Target * i_proc,
INTR_ROUTING_t i_rx_tx);
+ /*
+ * During MPIPL issue EOIs (blind) to all ISNs
+ * @param i_proc The processor chip target to issue EOIs for
+ * @return an error handle on error
+ */
+ errlHndl_t blindIssueEOIs(TARGETING::Target * i_proc);
+
+
/**
* Reset ISRN value in hardware regs
* @param i_proc The target processor
@@ -427,11 +450,74 @@ namespace INTR
errlHndl_t hw_resetIRSNregs(TARGETING::Target * i_proc);
/**
+ * Build a list of "functional" processors. This needs to be
+ * done without targetting support (just blueprint) since
+ * on MPIPL the targeting information is obtained in
+ * discover_targets -- much later in the IPL.
+ *
+
+ * @param o_proc List of "functional" processors on SMP
+ * @param o_cores List of cores under functional processors
+ * @return an error handle on error
+ */
+ errlHndl_t findProcs_Cores(TARGETING::TargetHandleList & o_procs,
+ TARGETING::TargetHandleList& o_cores);
+
+ /**
* disableHwMpIpl
*/
errlHndl_t hw_disableIntrMpIpl();
/**
+ * Read the Psi interrupt source number out of the HW
+ *
+ * @param i_target Processor target to read value from
+ * @param o_irsn IRSN of the PSI unit for the processor
+ * @return an error handle on error
+ */
+ errlHndl_t getPsiIRSN(TARGETING::Target * i_target,
+ uint32_t& o_irsn);
+
+ /**
+ * Read the PCIE interrupt source numbers out of the HW
+ *
+ * @param i_target Processor target to read value from
+ * @param o_irsn List of IRSN for the PCIE units
+ * @return an error handle on error
+ */
+ errlHndl_t getPcieIRSNs(TARGETING::Target * i_target,
+ std::vector<uint32_t> &o_irsn);
+
+ /**
+ * Read the NX interrupt source number out of the HW
+ *
+ * @param i_target Processor target to read value from
+ * @param o_irsn IRSN of the NX unit for the processor
+ * @return an error handle on error
+ */
+ errlHndl_t getNxIRSN(TARGETING::Target * i_target,
+ uint32_t& o_irsn);
+
+
+ /**
+ * Drain all outstanding interrupts during MPIPL
+ * @param i_cores List of all existing cores on functional procs
+ */
+ void drainMpIplInterrupts(TARGETING::TargetHandleList & i_cores);
+
+ /**
+ * Disable all interrupts on passed in core
+ * @param i_core Core to disable interrupts on
+ */
+ void disableAllInterrupts(TARGETING::Target* i_core);
+
+ /**
+ * Allow all interrupts on passed in core
+ * @param i_core Core to enable interrupts on
+ */
+ void allowAllInterrupts(TARGETING::Target* i_core);
+
+ /**
* cleanCheck - verify there are no active interrupts
*/
void cleanCheck();
diff --git a/src/usr/runtime/hdatservice.C b/src/usr/runtime/hdatservice.C
index 4de60449b..f6d70d19b 100644
--- a/src/usr/runtime/hdatservice.C
+++ b/src/usr/runtime/hdatservice.C
@@ -299,6 +299,7 @@ hdatService::hdatService(void)
:iv_spiraL(NULL)
,iv_spiraH(NULL)
,iv_spiraS(NULL)
+,iv_mdrtCnt(0)
{
}
@@ -600,7 +601,6 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section,
errhdl = findSpira();
if( errhdl ) { break; }
-
// NACA
if( RUNTIME::NACA == i_section )
{
@@ -929,7 +929,7 @@ errlHndl_t hdatService::getHostDataSection( SectionId i_section,
//Note - there is no header for the MDRT
//return the total allocated size since it is empty at first
- o_dataSize = tuple->hdatAllocSize * tuple->hdatAllocSize;
+ o_dataSize = tuple->hdatAllocSize * tuple->hdatAllocCnt;
errhdl = getSpiraTupleVA(tuple, o_dataAddr);
if( errhdl ) { break; }
@@ -1157,6 +1157,115 @@ errlHndl_t hdatService::findSpira( void )
return errhdl;
}
+errlHndl_t hdatService::updateHostDataSectionActual( SectionId i_section,
+ uint16_t i_count )
+{
+ errlHndl_t errhdl = NULL;
+ TRACFCOMP( g_trac_runtime, "RUNTIME::updateHostDataSectionActual( i_section=%d )", i_section);
+
+ do
+ {
+ //Always force a load (mapping)
+ errhdl = loadHostData();
+ if(errhdl)
+ {
+ break;
+ }
+
+ TARGETING::Target * sys = NULL;
+ TARGETING::targetService().getTopLevelTarget( sys );
+ assert(sys != NULL);
+
+ // Figure out what kind of payload we have
+ TARGETING::ATTR_PAYLOAD_KIND_type payload_kind
+ = sys->getAttr<TARGETING::ATTR_PAYLOAD_KIND>();
+
+ if( TARGETING::PAYLOAD_KIND_NONE == payload_kind )
+ {
+ // we're all done -- don't need to do anything
+ break;
+ }
+ //If payload is not (PHYP or Sapphire w/fsp)
+ else if( !((TARGETING::PAYLOAD_KIND_PHYP == payload_kind ) ||
+ ((TARGETING::PAYLOAD_KIND_SAPPHIRE == payload_kind ) &&
+ !INITSERVICE::spLess())))
+ {
+ TRACFCOMP( g_trac_runtime, "get_host_data_section> There is no host data for PAYLOAD_KIND=%d", payload_kind );
+ /*@
+ * @errortype
+ * @moduleid RUNTIME::MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL
+ * @reasoncode RUNTIME::RC_INVALID_PAYLOAD_KIND
+ * @userdata1 ATTR_PAYLOAD_KIND
+ * @userdata2 Requested Section
+ * @devdesc There is no host data for specified kind of payload
+ */
+ errhdl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ RUNTIME::MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL,
+ RUNTIME::RC_INVALID_PAYLOAD_KIND,
+ payload_kind,
+ i_section);
+ errhdl->collectTrace("RUNTIME",1024);
+ break;
+ }
+
+ // Setup the SPIRA pointers
+ errhdl = findSpira();
+ if( errhdl ) { break; }
+
+
+ // MS DUMP Results Table - MDRT
+ if( RUNTIME::MS_DUMP_RESULTS_TBL == i_section )
+ {
+ //For security we can't trust the FSP's payload attribute
+ // on MPIPLs for the dump tables.
+ //@todo: RTC:59171
+
+ // Find the right tuple and verify it makes sense
+ hdat5Tuple_t* tuple = NULL;
+ if( iv_spiraS )
+ {
+ tuple = &(iv_spiraS->hdatDataArea[SPIRAH_MS_DUMP_RSLT_TBL]);
+ }
+ else if( unlikely(iv_spiraL != NULL) )
+ {
+ tuple = &(iv_spiraL->hdatDataArea[SPIRAL_MS_DUMP_RSLT_TBL]);
+ }
+ TRACFCOMP( g_trac_runtime, "MS_DUMP_RESULTS_TBL tuple=%p, count=%x", tuple, i_count);
+ errhdl = check_tuple( i_section,
+ tuple );
+ if( errhdl ) { break; }
+
+ tuple->hdatActualCnt = i_count;
+ }
+ // Not sure how we could get here...
+ else
+ {
+ TRACFCOMP( g_trac_runtime, "get_host_data_section> Unknown section %d", i_section );
+ /*@
+ * @errortype
+ * @moduleid RUNTIME::MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL
+ * @reasoncode RUNTIME::RC_INVALID_SECTION
+ * @userdata1 Section Id
+ * @userdata2 <unused>
+ * @devdesc Unknown section requested
+ */
+ errhdl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ RUNTIME::MOD_HDATSERVICE_UPDATE_SECTION_ACTUAL,
+ RUNTIME::RC_INVALID_SECTION,
+ i_section,
+ 0);
+ errhdl->collectTrace("RUNTIME",1024);
+ break;
+ }
+
+ if( errhdl ) { break; }
+
+ } while(0);
+
+ return errhdl;
+}
+
/********************
Public Methods
********************/
@@ -1183,6 +1292,22 @@ errlHndl_t get_host_data_section( SectionId i_section,
getHostDataSection(i_section,i_instance, o_dataAddr, o_dataSize);
}
+errlHndl_t update_host_data_section_actual( SectionId i_section,
+ uint16_t i_count )
+{
+ return Singleton<hdatService>::instance().
+ updateHostDataSectionActual(i_section,i_count);
+}
+
+void update_MDRT_Count(uint16_t i_count )
+{
+ Singleton<hdatService>::instance().updateMdrtCount(i_count);
+}
+
+errlHndl_t write_MDRT_Count( void )
+{
+ return Singleton<hdatService>::instance().writeMdrtCount();
+}
};
/********************
diff --git a/src/usr/runtime/hdatservice.H b/src/usr/runtime/hdatservice.H
index 542c7be32..0b670273a 100644
--- a/src/usr/runtime/hdatservice.H
+++ b/src/usr/runtime/hdatservice.H
@@ -95,6 +95,17 @@ namespace RUNTIME
uint64_t& o_dataAddr,
size_t& o_dataSize );
+ /**
+ * @brief Update the actual count of section. Only supported for
+ * memory dump results table
+ *
+ * @param[in] i_section Chunk of data to find
+ * @param[in] i_count Actual count
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t updateHostDataSectionActual( SectionId i_section,
+ uint16_t i_count );
protected:
/**
@@ -219,6 +230,43 @@ namespace RUNTIME
* SPIRA-S
*/
hdatSpira_t* iv_spiraS;
+
+ /**
+ * Count of number of MDRT entries present
+ * on MPIPL/Dump. A value of 0 implies it
+ * doesn't need to be written
+ */
+ uint16_t iv_mdrtCnt;
+
+ public:
+ /**
+ * @brief Update the actual count of MDRT. Called by dump
+ * and needs to be saved away till populate_attributes. Can't
+ * be directly written by dump since FSP will load new value over
+
+ * @param[in] i_count Actual count for MDRT entries
+ *
+ */
+ void updateMdrtCount( uint16_t i_count )
+ {
+ iv_mdrtCnt = i_count;
+ }
+
+ /**
+ * @brief Write the MDRT stored value to SPIRA
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t writeMdrtCount( void )
+ {
+ errlHndl_t l_err = NULL;
+ if(iv_mdrtCnt)
+ {
+ l_err = updateHostDataSectionActual(
+ MS_DUMP_RESULTS_TBL,iv_mdrtCnt);
+ }
+ return l_err;
+ }
};
};
OpenPOWER on IntegriCloud