diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2015-04-29 15:01:52 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-05-01 15:38:28 +1000 |
commit | a653df93b2d22691ac1583584c8292e6e421464f (patch) | |
tree | 1b9927b726e5f7eff67a47855e09cb7de7d3bed0 /hw/bt.c | |
parent | 96ed5814761ca57ff2338d4501c4e40bf213f8e2 (diff) | |
download | skiboot-a653df93b2d22691ac1583584c8292e6e421464f.zip skiboot-a653df93b2d22691ac1583584c8292e6e421464f.tar.gz skiboot-a653df93b2d22691ac1583584c8292e6e421464f.tar.bz2 |
Add xscom_ok() and lpc_ok() to check XSCOM and LPC usabilityskiboot-5.0.1
his primarily checks whether the caller already holds the corresponding
locks to avoid re-entrancy in some of the deep error path such as when
XSCOM itself triggers an error log. It will be extended in the case of
LPC to also handle known HW error states.
We use them to avoid queuing/polling in the BT driver and to discard
characters in the UART driver.
Note: This will not normally involve a loss of log to the UART as the
UART driver is also protected by the console suspend mechanism. So
this is a safety mechanism only.
This fixes issues where the generation of error logs inside the LPC or
XSCOM drivers could cause a re-entrancy (via the BT interface)
causing deadlocks. Now, the error logs IPMI messages will be queued up
and delivered later on the next poll handler.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/bt.c')
-rw-r--r-- | hw/bt.c | 11 |
1 files changed, 9 insertions, 2 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) { |