aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/platform.c8
-rw-r--r--hw/lpc.c25
-rw-r--r--include/errorlog.h1
-rw-r--r--include/platform.h2
4 files changed, 32 insertions, 4 deletions
diff --git a/core/platform.c b/core/platform.c
index de700e7..49ae63a 100644
--- a/core/platform.c
+++ b/core/platform.c
@@ -25,6 +25,7 @@
#include <errorlog.h>
#include <bt.h>
+bool manufacturing_mode = false;
struct platform platform;
DEFINE_LOG_ENTRY(OPAL_RC_ABNORMAL_REBOOT, OPAL_PLATFORM_ERR_EVT, OPAL_CEC,
@@ -130,8 +131,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 7b6071d..5c5b7c6 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>
#include <psi.h>
//#define DBG_IRQ(fmt...) prerror(fmt)
@@ -42,6 +43,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 */
@@ -126,6 +132,9 @@ struct lpcm {
uint32_t sirq_rmasks[4];
};
+
+#define LPC_BUS_DEGRADED_PERF_THRESHOLD 5
+
struct lpc_client_entry {
struct list_node node;
const struct lpc_client *clt;
@@ -775,6 +784,8 @@ static void lpc_dispatch_reset(struct lpcm *lpc)
static void lpc_dispatch_err_irqs(struct lpcm *lpc, uint32_t irqs)
{
const char *sync_err = "Unknown LPC error";
+ static int lpc_bus_err_count;
+ struct opal_err_info *info;
uint32_t err_addr;
int rc;
@@ -803,13 +814,21 @@ static void lpc_dispatch_err_irqs(struct lpcm *lpc, uint32_t irqs)
rc = opb_read(lpc, 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), "LPC[%03x]: %s "
+ log_simple_error(info, "LPC[%03x]: %s "
"Error reading error address register\n",
lpc->chip_id, sync_err);
else
- log_simple_error(&e_info(OPAL_RC_LPC_SYNC), "LPC[%03x]: %s "
- "Error address reg: 0x%08x\n",
+ log_simple_error(info, "LPC[%03x]: %s Error address reg: "
+ "0x%08x\n",
lpc->chip_id, sync_err, err_addr);
}
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