diff options
-rw-r--r-- | core/platform.c | 8 | ||||
-rw-r--r-- | hw/lpc.c | 25 | ||||
-rw-r--r-- | include/errorlog.h | 1 | ||||
-rw-r--r-- | include/platform.h | 2 |
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]; @@ -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 |