aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2015-06-18 16:11:48 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-06-19 07:37:36 +1000
commit130c16cdb66b3662bc6b31b769b2a085506c41de (patch)
treeecf25c49b14b23d531247e6b6d19a059eb8bf283 /hw
parent31ab1933d7fbb37e9bee7ea69b76419fa3b2ac8d (diff)
downloadskiboot-130c16cdb66b3662bc6b31b769b2a085506c41de.zip
skiboot-130c16cdb66b3662bc6b31b769b2a085506c41de.tar.gz
skiboot-130c16cdb66b3662bc6b31b769b2a085506c41de.tar.bz2
hw/bt: Fix bt_msg_del locking
bt_msg_del() calls ipmi_cmd_done() to free the message and process any error callbacks. However it should drop the lock prior to calling ipmi_cmd_done() as some error callbacks may try to queue ipmi messages leading to a dead lock. Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/bt.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/hw/bt.c b/hw/bt.c
index da59b14..7913249 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -133,12 +133,15 @@ static inline void bt_set_state(enum bt_states next_state)
bt.state = next_state;
}
+/* Must be called with bt.lock held */
static void bt_msg_del(struct bt_msg *bt_msg)
{
list_del(&bt_msg->link);
bt.queue_len--;
+ unlock(&bt.lock);
ipmi_cmd_done(bt_msg->ipmi_msg.cmd, bt_msg->ipmi_msg.netfn + (1 << 2),
IPMI_TIMEOUT_ERR, &bt_msg->ipmi_msg);
+ lock(&bt.lock);
}
static void bt_init_interface(void)
@@ -363,11 +366,12 @@ static void bt_poll(struct timer *t __unused, void *data __unused)
/* If we can't get the lock assume someone else will notice
* the new message and process it. */
lock(&bt.lock);
- bt_ctrl = bt_inb(BT_CTRL);
print_debug_queue_info();
bt_expire_old_msg();
+ bt_ctrl = bt_inb(BT_CTRL);
+
/* Is there a response waiting for us? */
if (bt.state == BT_STATE_RESP_WAIT &&
(bt_ctrl & BT_CTRL_B2H_ATN))