aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVipin K Parashar <vipin@linux.vnet.ibm.com>2016-08-07 00:38:00 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-08-25 16:31:37 +1000
commit3aafb0b72caa6c0a2d0203e23a953668b5c63ad5 (patch)
tree072564f90d84b0360cae3683cba6e1b8f15c2d16
parentbc96a448f571a03afc591b5e6fe120821cbf7fa7 (diff)
downloadskiboot-3aafb0b72caa6c0a2d0203e23a953668b5c63ad5.zip
skiboot-3aafb0b72caa6c0a2d0203e23a953668b5c63ad5.tar.gz
skiboot-3aafb0b72caa6c0a2d0203e23a953668b5c63ad5.tar.bz2
lpc: Log LPC SYNC errors as unrecoverable ones for manufacturing
High volume of SYNC errors onto LPC bus cause degraded system performance and are likely due to bad hardware present onto system. Thus once LPC SYNC errors cross a certain threshold, OPAL should log them onto BMC as unrecoverable errors in manufacturing mode. This will help manufacturing screen bad parts, causing such errors. Cc: stable Signed-off-by: Vipin K Parashar <vipin@linux.vnet.ibm.com> [stewart@linux.vnet.ibm.com: s/mfg/manufacturing/] Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com> (cherry picked from commit 51b9eeb66ebbd1706248d8f2277afa9b7dcdbc3b) Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--core/platform.c8
-rw-r--r--hw/lpc.c27
-rw-r--r--include/errorlog.h1
-rw-r--r--include/platform.h2
4 files changed, 32 insertions, 6 deletions
diff --git a/core/platform.c b/core/platform.c
index de6e406..140a5b0 100644
--- a/core/platform.c
+++ b/core/platform.c
@@ -24,6 +24,7 @@
#include <xscom.h>
#include <errorlog.h>
+bool manufacturing_mode = false;
struct platform platform;
DEFINE_LOG_ENTRY(OPAL_RC_ABNORMAL_REBOOT, OPAL_PLATFORM_ERR_EVT, OPAL_CEC,
@@ -124,8 +125,13 @@ void probe_platform(void)
struct platform *platforms = &__platforms_start;
unsigned int i;
- platform = generic_platform;
+ /* Detect Manufacturing mode */
+ if (dt_find_property(dt_root, "ibm,manufacturing-mode")) {
+ prlog(PR_NOTICE, "PLAT: Manufacturing mode ON\n");
+ manufacturing_mode = true;
+ }
+ platform = generic_platform;
for (i = 0; &platforms[i] < &__platforms_end; i++) {
if (platforms[i].probe && platforms[i].probe()) {
platform = platforms[i];
diff --git a/hw/lpc.c b/hw/lpc.c
index 32cb7b1..e682557 100644
--- a/hw/lpc.c
+++ b/hw/lpc.c
@@ -25,6 +25,7 @@
#include <timebase.h>
#include <errorlog.h>
#include <opal-api.h>
+#include <platform.h>
//#define DBG_IRQ(fmt...) prerror(fmt)
#define DBG_IRQ(fmt...) do { } while(0)
@@ -41,6 +42,11 @@ DEFINE_LOG_ENTRY(OPAL_RC_LPC_SYNC, OPAL_PLATFORM_ERR_EVT, OPAL_LPC,
OPAL_MISC_SUBSYSTEM, OPAL_PREDICTIVE_ERR_GENERAL,
OPAL_NA);
+/* Used exclusively in manufacturing mode */
+DEFINE_LOG_ENTRY(OPAL_RC_LPC_SYNC_PERF, OPAL_PLATFORM_ERR_EVT, OPAL_LPC,
+ OPAL_MISC_SUBSYSTEM, OPAL_UNRECOVERABLE_ERR_DEGRADE_PERF,
+ OPAL_NA);
+
#define ECCB_CTL 0 /* b0020 -> b00200 */
#define ECCB_STAT 2 /* b0022 -> b00210 */
#define ECCB_DATA 3 /* b0023 -> b00218 */
@@ -110,6 +116,9 @@ DEFINE_LOG_ENTRY(OPAL_RC_LPC_SYNC, OPAL_PLATFORM_ERR_EVT, OPAL_LPC,
LPC_HC_IRQ_BM_TAR_ERR)
#define LPC_HC_ERROR_ADDRESS 0x40
+
+#define LPC_BUS_DEGRADED_PERF_THRESHOLD 5
+
struct lpc_client_entry {
struct list_node node;
const struct lpc_client *clt;
@@ -662,8 +671,10 @@ static void lpc_dispatch_reset(struct proc_chip *chip)
static void lpc_dispatch_err_irqs(struct proc_chip *chip, uint32_t irqs)
{
int rc;
+ struct opal_err_info *info;
const char *sync_err = "Unknown LPC error";
uint32_t err_addr;
+ static int lpc_bus_err_count;
/* Write back to clear error interrupts, we clear SerIRQ later
* as they are handled as level interrupts
@@ -690,13 +701,19 @@ static void lpc_dispatch_err_irqs(struct proc_chip *chip, uint32_t irqs)
rc = opb_read(chip, lpc_reg_opb_base + LPC_HC_ERROR_ADDRESS,
&err_addr, 4);
+
+ lpc_bus_err_count++;
+ if (manufacturing_mode && (lpc_bus_err_count > LPC_BUS_DEGRADED_PERF_THRESHOLD))
+ info = &e_info(OPAL_RC_LPC_SYNC_PERF);
+ else
+ info = &e_info(OPAL_RC_LPC_SYNC);
+
if (rc)
- log_simple_error(&e_info(OPAL_RC_LPC_SYNC), "%s "
- "Error address: Unknown\n", sync_err);
+ log_simple_error(info, "%s Error address: Unknown\n",
+ sync_err);
else
- log_simple_error(&e_info(OPAL_RC_LPC_SYNC), "%s "
- "Error address: 0x%08x\n",
- sync_err, err_addr);
+ log_simple_error(info, "%s Error address: 0x%08x\n",
+ sync_err, err_addr);
}
static void lpc_dispatch_ser_irqs(struct proc_chip *chip, uint32_t irqs,
diff --git a/include/errorlog.h b/include/errorlog.h
index f89eac9..247198b 100644
--- a/include/errorlog.h
+++ b/include/errorlog.h
@@ -266,6 +266,7 @@ enum opal_reasoncode {
OPAL_RC_LPC_READ = OPAL_SRC_COMPONENT_LPC | 0x10,
OPAL_RC_LPC_WRITE = OPAL_SRC_COMPONENT_LPC | 0x11,
OPAL_RC_LPC_SYNC = OPAL_SRC_COMPONENT_LPC | 0x12,
+ OPAL_RC_LPC_SYNC_PERF = OPAL_SRC_COMPONENT_LPC | 0x13,
/* OP_PANEL */
OPAL_RC_PANEL_WRITE = OPAL_SRC_COMPONENT_OP_PANEL | 0x10,
/* PSI */
diff --git a/include/platform.h b/include/platform.h
index 062a941..334c0a4 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -175,6 +175,8 @@ extern struct platform __platforms_end;
extern struct platform platform;
+extern bool manufacturing_mode;
+
#define DECLARE_PLATFORM(name)\
static const struct platform __used __section(".platforms") name ##_platform