summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/lpc/lpcdd.C15
-rw-r--r--src/usr/lpc/lpcdd.H15
-rw-r--r--src/usr/xscom/xscom.C48
3 files changed, 75 insertions, 3 deletions
diff --git a/src/usr/lpc/lpcdd.C b/src/usr/lpc/lpcdd.C
index a8a23fde1..81577a5b0 100644
--- a/src/usr/lpc/lpcdd.C
+++ b/src/usr/lpc/lpcdd.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2016 */
+/* Contributors Listed Below - COPYRIGHT 2014,2017 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -363,6 +363,19 @@ errlHndl_t create_altmaster_objects( bool i_create,
return l_err;
}
+
+/**
+ * @brief Block/unblock all LPC operations
+ * @param[in] i_block true: block ops, false: allow ops
+ *
+ */
+void block_lpc_ops( bool i_block )
+{
+ // Note: this is ignoring the alt-master because the usecase for
+ // this function is only applicable for DD1
+ Singleton<LpcDD>::instance().lock(i_block);
+}
+
}; //namespace LPC
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/usr/lpc/lpcdd.H b/src/usr/lpc/lpcdd.H
index 1b4e3c5bd..f4bd04176 100644
--- a/src/usr/lpc/lpcdd.H
+++ b/src/usr/lpc/lpcdd.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2016 */
+/* Contributors Listed Below - COPYRIGHT 2014,2017 */
/* [+] Google Inc. */
/* [+] International Business Machines Corp. */
/* */
@@ -132,6 +132,19 @@ class LpcDD
};
/**
+ * @brief Block/unblock all LPC operations
+ * @param[in] i_block true: block ops, false: allow ops
+ */
+ void lock( bool i_block )
+ {
+ if( i_block ) {
+ mutex_lock(ivp_mutex);
+ } else {
+ mutex_unlock(ivp_mutex);
+ }
+ };
+
+ /**
* @brief Constructor
* @param[in] Processor target associated with the ECCB logic
*/
diff --git a/src/usr/xscom/xscom.C b/src/usr/xscom/xscom.C
index fb487c55b..b112b2294 100644
--- a/src/usr/xscom/xscom.C
+++ b/src/usr/xscom/xscom.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2016 */
+/* Contributors Listed Below - COPYRIGHT 2011,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -47,6 +47,7 @@
#include <errl/errludlogregister.H>
#include <xscom/piberror.H>
#include <arch/pirformat.H>
+#include <lpc/lpcif.H>
// Trace definition
trace_desc_t* g_trac_xscom = NULL;
@@ -701,6 +702,38 @@ void collectXscomFFDC(TARGETING::Target* i_target,
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
+bool checkForLpcBug( void )
+{
+ // See HW400314 for description of hardware bug
+ // The Power Bus Snooper Interface on the ADU is shared by both PIB
+ // and LPC. Once an error occurred in the Xscom while accessing the
+ // PIB space, the interface is overriding the data that is sent out
+ // as all ?F? for any operation which may be XSCOM to PIB address
+ // space or to a LPC address Space. Further XSCOM operation are
+ // locked till the pending error is cleared. But an XSCOM Status
+ // pmisc is sent with pib response info (in this case the type of
+ // the error) and for the next operations i.e. XSCOM to PIB or to
+ // LPC it sends info value as 1 which indicates ADU has pending
+ // XSCOM Error. This is indicated in the (48 :50) bits in the address
+ // sent.
+
+ ProcessorCoreType l_coreType = cpu_core_type();
+ uint8_t l_ddLevel = cpu_dd_level();
+
+ // Bug is only present in Nimbus DD1
+ if( (l_coreType == CORE_POWER9_NIMBUS) && (l_ddLevel == 0x10) )
+ {
+ TRACFCOMP( g_trac_xscom, "Activating LPC mutex workaround" );
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
errlHndl_t xscomPerformOp(DeviceFW::OperationType i_opType,
TARGETING::Target* i_target,
void* io_buffer,
@@ -738,6 +771,13 @@ errlHndl_t xscomPerformOp(DeviceFW::OperationType i_opType,
// Pin this thread to current CPU
task_affinity_pin();
+ // Block the LPC driver from running while an xscom is in progress
+ static bool l_hasLpcBug = checkForLpcBug();
+ if( l_hasLpcBug )
+ {
+ LPC::block_lpc_ops(true);
+ }
+
// Lock other XSCom in this same thread from running
l_XSComMutex = mmio_xscom_mutex();
mutex_lock(l_XSComMutex);
@@ -778,6 +818,12 @@ errlHndl_t xscomPerformOp(DeviceFW::OperationType i_opType,
// Unlock
mutex_unlock(l_XSComMutex);
+ // Unblock the LPC driver
+ if( l_hasLpcBug )
+ {
+ LPC::block_lpc_ops(false);
+ }
+
// Done, un-pin
task_affinity_unpin();
OpenPOWER on IntegriCloud