summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMissy Connell <missyc@us.ibm.com>2011-12-06 13:06:18 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-01-24 14:43:04 -0600
commit52b60aea13ffc9a8d67a6714e1416402fd203139 (patch)
tree209e89b8fdeb35126712c2d75bb49b6eb396be36 /src
parent8514ef2acf01728b5a07fbd3c94999375cc0aec6 (diff)
downloadtalos-hostboot-52b60aea13ffc9a8d67a6714e1416402fd203139.tar.gz
talos-hostboot-52b60aea13ffc9a8d67a6714e1416402fd203139.zip
Indirect SCOM support
Added locking Change-Id: If2b3c2d69bb533a65cd9b41c1eaf595e979f93aa Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/562 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/usr/scom/scom.C113
-rw-r--r--src/usr/scom/scom.H36
-rw-r--r--src/usr/scom/test/scomtest.H142
-rw-r--r--src/usr/targeting/xmltohb/attribute_types.xml13
-rw-r--r--src/usr/targeting/xmltohb/target_types.xml8
5 files changed, 303 insertions, 9 deletions
diff --git a/src/usr/scom/scom.C b/src/usr/scom/scom.C
index ed5ffb306..8bfdbf004 100644
--- a/src/usr/scom/scom.C
+++ b/src/usr/scom/scom.C
@@ -55,6 +55,8 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
TARGETING::TYPE_MEMBUF,
scomPerformOp);
+
+
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
@@ -65,6 +67,112 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
va_list i_args)
{
errlHndl_t l_err = NULL;
+ mutex_t* l_mutex = NULL;
+
+ uint64_t l_scomAddr = va_arg(i_args,uint64_t);
+
+ // If the indirect scom bit is 0, then doing a regular scom
+ if( (l_scomAddr & 0x8000000000000000) == 0)
+ {
+ l_err = doScomOp(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ i_accessType,
+ l_scomAddr);
+ }
+ // We are performing an indirect scom.
+ else
+ {
+ uint64_t l_io_buffer;
+ uint64_t temp_scomAddr;
+
+ memcpy(&l_io_buffer, io_buffer, 8);
+ memcpy(&temp_scomAddr, &l_scomAddr, 8);
+
+ // Get the 20bit indirect scom address
+ temp_scomAddr = temp_scomAddr & 0x001FFFFF00000000;
+
+ // Zero out the indirect address location.. leave the 16bits of data
+ l_io_buffer = l_io_buffer & 0x000000000000FFFF;
+
+ // OR in the 20bit indirect address
+ l_io_buffer = l_io_buffer | temp_scomAddr;
+
+ // zero out the indirect address from the buffer..
+ l_scomAddr = l_scomAddr & 0x00000000EFFFFFFFF;
+
+ // If we are doing a read. We need to do a write first..
+ if(i_opType == DeviceFW::READ)
+ {
+
+ // use the chip-specific mutex attribute
+ l_mutex = i_target->getHbMutexAttr<TARGETING::ATTR_SCOM_IND_MUTEX>();
+
+ mutex_lock(l_mutex);
+
+ // turn the read bit on.
+ l_io_buffer = l_io_buffer | 0x8000000000000000;
+
+ // perform write before the read with the new
+ // IO_buffer with the imbedded indirect scom addr.
+ l_err = doScomOp(DeviceFW::WRITE,
+ i_target,
+ & l_io_buffer,
+ io_buflen,
+ i_accessType,
+ l_scomAddr);
+
+ if (l_err != NULL)
+ {
+ mutex_unlock(l_mutex);
+ return l_err;
+ }
+
+ // Now perform the op requested using the passed in
+ // IO_Buffer to pass the read data back to caller.
+ l_err = doScomOp(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ i_accessType,
+ l_scomAddr);
+
+ mutex_unlock(l_mutex);
+
+ }
+ else //write
+ {
+
+ // Turn the read bit off.
+ l_io_buffer = l_io_buffer & 0x7FFFFFFFFFFFFFFF;
+
+ // Now perform the op requested using the
+ // locai io_buffer with the indirect addr imbedded.
+ l_err = doScomOp(i_opType,
+ i_target,
+ & l_io_buffer,
+ io_buflen,
+ i_accessType,
+ l_scomAddr);
+ }
+ }
+
+ return l_err;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+errlHndl_t doScomOp(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ uint64_t i_addr)
+{
+
+ errlHndl_t l_err = NULL;
do{
//Always XSCOM the Master Sentinel
@@ -76,7 +184,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
i_target,
io_buffer,
io_buflen,
- DEVICE_XSCOM_ADDRESS(va_arg(i_args,uint64_t)));
+ DEVICE_XSCOM_ADDRESS(i_addr));
break;
}
else if(i_target->getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useFsiScom)
@@ -85,7 +193,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
i_target,
io_buffer,
io_buflen,
- DEVICE_FSISCOM_ADDRESS(va_arg(i_args,uint64_t)));
+ DEVICE_FSISCOM_ADDRESS(i_addr));
if( l_err ) { break; }
}
else
@@ -101,5 +209,4 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
}
-
} // end namespace
diff --git a/src/usr/scom/scom.H b/src/usr/scom/scom.H
index d91eb41ee..f39720aae 100644
--- a/src/usr/scom/scom.H
+++ b/src/usr/scom/scom.H
@@ -34,10 +34,9 @@ namespace SCOM
/**
- * @brief Performs an SCom operation
- * This function performs an SCom Read/Write operation. It follows a
- * pre-defined prototype functions in order to be registered with the
- * device-driver framework.
+ * @brief Performs a SCom operation
+ * This function performs a SCOM operation by calling doScomOP. It
+ * handles whether the address a regular or an indirect SCOM address
*
* @param[in] i_opType Operation type, see DeviceFW::OperationType
* in driverif.H
@@ -63,6 +62,35 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType,
va_list i_args);
+/**
+ * @brief Performs a SCom operation
+ * This function performs an SCom Read/Write operation. It follows a
+ * pre-defined prototype functions in order to be registered with the
+ * device-driver framework.
+ *
+ * @param[in] i_opType Operation type, see DeviceFW::OperationType
+ * in driverif.H
+ * @param[in] i_target SCom target
+ * @param[in/out] io_buffer Read: pointer to output data storage
+ * Write: pointer to data to be written
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output: Read: size of output data
+ * Write: size of data written
+ * @param[in] i_accessType Select from DeviceFW::AccessType enum
+ * (usrif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * In this function, there's only one argument,
+ * which is the SCom address value.
+ *
+ * @return errlHndl_t
+ */
+errlHndl_t doScomOp(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ uint64_t i_addr);
+
}; // End namespace
diff --git a/src/usr/scom/test/scomtest.H b/src/usr/scom/test/scomtest.H
index 5c8fab902..7545b795b 100644
--- a/src/usr/scom/test/scomtest.H
+++ b/src/usr/scom/test/scomtest.H
@@ -35,7 +35,7 @@
#include <errl/errltypes.H>
#include <devicefw/userif.H>
#include <fsi/fsiif.H>
-
+#include <sys/time.h> //mc99 remove
extern trace_desc_t* g_trac_scom;
@@ -336,11 +336,149 @@ public:
}
+ /**
+ * @brief SCOM test Indirect SCOM
+ *
+ */
+
+ void test_IndirectScom(void)
+ {
+ TRACFCOMP( g_trac_scom, "ScomTest::test_IndirectScomReadWrite> Start" );
+
+ uint64_t fails = 0;
+ uint64_t total = 0;
+ errlHndl_t l_err = NULL;
+
+
+ // Setup some targets to use
+ enum {
+ myPROC9,
+ NUM_TARGETS
+ };
+ TARGETING::Target* scom_targets[NUM_TARGETS];
+ for( uint64_t x = 0; x < NUM_TARGETS; x++ )
+ {
+ scom_targets[x] = NULL;
+ }
+
+
+ // Target Proc 9 - the FSI wrap-back connection in simics
+ TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL);
+ epath.addLast(TARGETING::TYPE_SYS,0);
+ epath.addLast(TARGETING::TYPE_NODE,0);
+ epath.addLast(TARGETING::TYPE_PROC,9);
+
+ scom_targets[myPROC9] = TARGETING::targetService().toTarget(epath);
+
+ for( uint64_t x = 0; x < NUM_TARGETS; x++ )
+ {
+ //only run if the target exists
+ if(scom_targets[x] == NULL)
+ {
+ TRACFCOMP( g_trac_scom, "ScomTest - TARGET = NULL - 1 x = %d", x);
+ continue;
+ }
+ else if ((scom_targets[x]->getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useXscom == 0) &&
+ (scom_targets[x]->getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useFsiScom == 0))
+ {
+ // If both FSI and XSCOM are not enabled.. then ignore..
+ TRACFCOMP(g_trac_scom, "INDIRECT SCOM>> SKIPPING ");
+ scom_targets[x] = NULL; //remove from our list
+ }
+
+ }
+
+ // scratch data to use
+ //@fixme: Need to either fabricate some fake registers to use or save off data before modifying SCOMs to avoid
+ // corrupting the HW.
+
+ struct {
+ TARGETING::Target* target;
+ uint64_t addr;
+ uint64_t data;
+ } test_data[] = {
+ { scom_targets[myPROC9], 0x80040C0102011A3F ,0x1234432112344321},
+ { scom_targets[myPROC9], 0x800C140002011E3F, 0x123443211234ABAB},
+ };
+ const uint64_t NUM_ADDRS = sizeof(test_data)/sizeof(test_data[0]);
+
+
+ size_t op_size = sizeof(uint32_t);
+
+ // write all the test registers
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ //only run if the target exists
+ if(test_data[x].target == NULL)
+ {
+ continue;
+ }
+
+ op_size = sizeof(uint64_t);
+
+ total++;
+ l_err = deviceWrite( test_data[x].target,
+ &(test_data[x].data),
+ op_size,
+ DEVICE_SCOM_ADDRESS(test_data[x].addr) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScom_proc> [%d] Write: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() );
+ TS_FAIL( "ScomTest::test_IndirectScom_proc> ERROR : Unexpected error log from write1" );
+ fails++;
+ errlCommit(l_err,SCOM_COMP_ID);
+ delete l_err;
+ }
+ }
+
+ // allocate space for read data
+ uint64_t read_data[NUM_ADDRS];
+
+ memset(read_data, 0, sizeof read_data);
+
+ // read all the test registers
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ //only run if the target exists
+ if(test_data[x].target == NULL)
+ {
+ continue;
+ }
+
+ op_size = sizeof(uint64_t);
+
+ total++;
+ l_err = deviceRead( test_data[x].target,
+ &(read_data[x]),
+ op_size,
+ DEVICE_SCOM_ADDRESS(test_data[x].addr) );
+
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomreadWrite_proc> [%d] Read: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() );
+ TS_FAIL( "ScomTest::test_IndirectScomreadWrite_proc> ERROR : Unexpected error log from write1" );
+ fails++;
+ errlCommit(l_err,SCOM_COMP_ID);
+ delete l_err;
+ }
+ else if((read_data[x] & 0x000000000000FFFF) != (test_data[x].data & 0x000000000000FFFF))
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomreadWrite_proc> [%d] Read: Data miss-match : addr=0x%X, read_data=0x%llx, write_data=0x%llx", x, test_data[x].addr, read_data[x], test_data[x].data);
+ TS_FAIL( "ScomTest::test_IndirectScomreadWrite_proc> ERROR : Data miss-match between read and expected data" );
+ fails++;
+ }
+
+ }
+
+ TRACFCOMP( g_trac_scom, "ScomTest::test_IndirectScomreadWrite_proc> %d/%d fails", fails, total );
+
+ }
+
//@todo - write tests to verify connection between XSCOM and FSISCOM
//@todo - write error path testcase for FSI scom using bad address
- //@todo - indirect scom
+
//@todo - address translation
diff --git a/src/usr/targeting/xmltohb/attribute_types.xml b/src/usr/targeting/xmltohb/attribute_types.xml
index 9adbbb126..94785e06a 100644
--- a/src/usr/targeting/xmltohb/attribute_types.xml
+++ b/src/usr/targeting/xmltohb/attribute_types.xml
@@ -2768,4 +2768,17 @@
</hwpfToHbAttrMap>
</attribute>
+<attribute>
+ <id>SCOM_IND_MUTEX</id>
+ <description>Mutex for Indirect SCOM read operation</description>
+ <simpleType>
+ <hbmutex>
+ <default>0</default>
+ </hbmutex>
+ </simpleType>
+ <persistency>volatile-zeroed</persistency>
+ <readable/>
+ <writeable/>
+</attribute>
+
</attributes>
diff --git a/src/usr/targeting/xmltohb/target_types.xml b/src/usr/targeting/xmltohb/target_types.xml
index a4be0cab1..67e922b5d 100644
--- a/src/usr/targeting/xmltohb/target_types.xml
+++ b/src/usr/targeting/xmltohb/target_types.xml
@@ -144,6 +144,10 @@
<attribute>
<id>FSI_SCOM_MUTEX</id>
</attribute>
+ <attribute>
+ <id>SCOM_IND_MUTEX</id>
+ </attribute>
+
</targetType>
<targetType>
@@ -685,6 +689,10 @@
<attribute>
<id>FSI_SCOM_MUTEX</id>
</attribute>
+ <attribute>
+ <id>SCOM_IND_MUTEX</id>
+ </attribute>
+
</targetType>
<!-- Centaur MBS -->
OpenPOWER on IntegriCloud