diff options
author | Alistair Popple <alistair@popple.id.au> | 2015-06-18 16:11:48 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-06-19 07:37:36 +1000 |
commit | 130c16cdb66b3662bc6b31b769b2a085506c41de (patch) | |
tree | ecf25c49b14b23d531247e6b6d19a059eb8bf283 /hw | |
parent | 31ab1933d7fbb37e9bee7ea69b76419fa3b2ac8d (diff) | |
download | skiboot-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.c | 6 |
1 files changed, 5 insertions, 1 deletions
@@ -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)) |