diff options
author | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-05-01 16:42:45 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-05-01 16:42:45 +1000 |
commit | a7d8258c329a3dfff36d348bd3cc3a7171a1267f (patch) | |
tree | 289fe2e8396cbc5857e4c4c4521e4893fa273160 | |
parent | 6a3cad272e4c494541c2fa5d9b5d893e17adcde3 (diff) | |
parent | a653df93b2d22691ac1583584c8292e6e421464f (diff) | |
download | skiboot-a7d8258c329a3dfff36d348bd3cc3a7171a1267f.zip skiboot-a7d8258c329a3dfff36d348bd3cc3a7171a1267f.tar.gz skiboot-a7d8258c329a3dfff36d348bd3cc3a7171a1267f.tar.bz2 |
Merge branch 'stable', skiboot-5.0.1
-rw-r--r-- | hw/bt.c | 11 | ||||
-rw-r--r-- | hw/lpc-uart.c | 4 | ||||
-rw-r--r-- | hw/lpc.c | 12 | ||||
-rw-r--r-- | hw/xscom.c | 29 | ||||
-rw-r--r-- | include/lpc.h | 6 | ||||
-rw-r--r-- | include/xscom.h | 5 |
6 files changed, 47 insertions, 20 deletions
@@ -350,7 +350,8 @@ static void print_debug_queue_info(void) {} static void bt_send_and_unlock(void) { - if (bt.state == BT_STATE_IDLE && !list_empty(&bt.msgq)) + if (lpc_ok() && + bt.state == BT_STATE_IDLE && !list_empty(&bt.msgq)) bt_send_msg(); unlock(&bt.lock); @@ -361,6 +362,10 @@ static void bt_poll(struct timer *t __unused, void *data __unused) { uint8_t bt_ctrl; + /* Don't do anything if the LPC bus is offline */ + if (!lpc_ok()) + return; + /* If we can't get the lock assume someone else will notice * the new message and process it. */ lock(&bt.lock); @@ -440,7 +445,9 @@ static int bt_add_ipmi_msg(struct ipmi_msg *ipmi_msg) void bt_irq(void) { - uint8_t ireg = bt_inb(BT_INTMASK); + uint8_t ireg; + + ireg = bt_inb(BT_INTMASK); bt.irq_ok = true; if (ireg & BT_INTMASK_B2H_IRQ) { diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c index 2e6114a..7c3190e 100644 --- a/hw/lpc-uart.c +++ b/hw/lpc-uart.c @@ -135,6 +135,10 @@ static size_t uart_con_write(const char *buf, size_t len) { size_t written = 0; + /* If LPC bus is bad, we just swallow data */ + if (!lpc_ok()) + return written; + lock(&uart_lock); while(written < len) { if (tx_room == 0) { @@ -500,3 +500,15 @@ void lpc_used_by_console(void) unlock(&chip->lpc_lock); } } + +bool lpc_ok(void) +{ + struct proc_chip *chip; + + if (lpc_default_chip_id < 0) + return false; + if (!xscom_ok()) + return false; + chip = get_chip(lpc_default_chip_id); + return !lock_held_by_me(&chip->lpc_lock); +} @@ -342,7 +342,6 @@ static uint32_t xscom_decode_chiplet(uint32_t partid, uint64_t *pcb_addr) */ int xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val) { - bool need_unlock; uint32_t gcid; int rc; @@ -360,12 +359,8 @@ int xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val) return OPAL_PARAMETER; } - /* - * HW822317 requires locking. We use a recursive lock as error - * conditions might cause printf's which might then try to take - * the lock again - */ - need_unlock = lock_recursive(&xscom_lock); + /* HW822317 requires us to do global locking */ + lock(&xscom_lock); /* Direct vs indirect access */ if (pcb_addr & XSCOM_ADDR_IND_FLAG) @@ -374,8 +369,7 @@ int xscom_read(uint32_t partid, uint64_t pcb_addr, uint64_t *val) rc = __xscom_read(gcid, pcb_addr & 0x7fffffff, val); /* Unlock it */ - if (need_unlock) - unlock(&xscom_lock); + unlock(&xscom_lock); return rc; } @@ -383,7 +377,6 @@ opal_call(OPAL_XSCOM_READ, xscom_read, 3); int xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val) { - bool need_unlock; uint32_t gcid; int rc; @@ -401,12 +394,8 @@ int xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val) return OPAL_PARAMETER; } - /* - * HW822317 requires locking. We use a recursive lock as error - * conditions might cause printf's which might then try to take - * the lock again - */ - need_unlock = lock_recursive(&xscom_lock); + /* HW822317 requires us to do global locking */ + lock(&xscom_lock); /* Direct vs indirect access */ if (pcb_addr & XSCOM_ADDR_IND_FLAG) @@ -415,8 +404,7 @@ int xscom_write(uint32_t partid, uint64_t pcb_addr, uint64_t val) rc = __xscom_write(gcid, pcb_addr & 0x7fffffff, val); /* Unlock it */ - if (need_unlock) - unlock(&xscom_lock); + unlock(&xscom_lock); return rc; } opal_call(OPAL_XSCOM_WRITE, xscom_write, 3); @@ -546,3 +534,8 @@ void xscom_used_by_console(void) lock(&xscom_lock); unlock(&xscom_lock); } + +bool xscom_ok(void) +{ + return !lock_held_by_me(&xscom_lock); +} diff --git a/include/lpc.h b/include/lpc.h index 5611c54..a0990fd 100644 --- a/include/lpc.h +++ b/include/lpc.h @@ -27,6 +27,12 @@ extern void lpc_init(void); /* Check for a default bus */ extern bool lpc_present(void); +/* Return of LPC is currently usable. This can be false if the caller + * currently holds a lock that would make it unsafe, or the LPC bus + * is known to be in some error condition (TBI). + */ +extern bool lpc_ok(void); + /* Handle the interrupt from LPC source */ extern void __attrconst lpc_interrupt(uint32_t chip_id); diff --git a/include/xscom.h b/include/xscom.h index b1ecaf5..a841261 100644 --- a/include/xscom.h +++ b/include/xscom.h @@ -173,6 +173,11 @@ extern void xscom_init(void); /* Mark XSCOM lock as being in console path */ extern void xscom_used_by_console(void); +/* Returns true if XSCOM can be used. Typically this returns false if + * the current CPU holds the XSCOM lock (to avoid re-entrancy from error path). + */ +extern bool xscom_ok(void); + extern int64_t xscom_read_cfam_chipid(uint32_t partid, uint32_t *chip_id); #endif /* __XSCOM_H */ |