diff options
author | Alistair Popple <alistair@popple.id.au> | 2014-11-05 14:40:47 +1100 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-11-12 16:41:25 +1100 |
commit | 983db8cc4b6444de8df2ce1a273f3f3b9eec12c3 (patch) | |
tree | d174e343455e207fcd449bb9b2e664f5a368bedf /hw/bt.c | |
parent | d51cbd7c69b4669dddb34b100197d045d7f06c2d (diff) | |
download | skiboot-983db8cc4b6444de8df2ce1a273f3f3b9eec12c3.zip skiboot-983db8cc4b6444de8df2ce1a273f3f3b9eec12c3.tar.gz skiboot-983db8cc4b6444de8df2ce1a273f3f3b9eec12c3.tar.bz2 |
bt: Fix message timeouts
The initial timeout scheme started a message timeout when it was added
to the queue rather than when transmission was started. To avoid
timing out messages that just got stuck behind a couple of slow ones
we should instead just check that the active message has not timed
out.
This patch ensures timeout values are only checked for the currently
active message.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'hw/bt.c')
-rw-r--r-- | hw/bt.c | 21 |
1 files changed, 14 insertions, 7 deletions
@@ -188,6 +188,7 @@ static bool bt_try_send_msg(void) for (i = 0; i < ipmi_msg->req_size; i++) bt_outb(ipmi_msg->data[i], BT_HOST2BMC); + bt_msg->tb = mftb(); bt_outb(BT_CTRL_H2B_ATN, BT_CTRL); bt_set_state(BT_STATE_RESP_WAIT); unlock(&bt.msgq_lock); @@ -299,15 +300,21 @@ static bool bt_get_resp(void) static void bt_expire_old_msg(void) { unsigned long tb; - struct bt_msg *bt_msg, *next; + struct bt_msg *bt_msg; lock(&bt.msgq_lock); tb = mftb(); - list_for_each_safe(&bt.msgq, bt_msg, next, link) { - if ((bt_msg->tb + BT_MSG_TIMEOUT) < tb) { - prerror("BT: Expiring old messsage number 0x%02x\n", bt_msg->seq); - bt_msg_del(bt_msg); - } + bt_msg = list_top(&bt.msgq, struct bt_msg, link); + + if (bt_msg && bt_msg->tb > 0 && (bt_msg->tb + BT_MSG_TIMEOUT) < tb) { + prerror("BT: Expiring old messsage number 0x%02x\n", bt_msg->seq); + bt_msg_del(bt_msg); + + /* Timing out a message is inherently racy as the BMC + may start writing just as we decide to kill the + message. Hopefully resetting the interface is + sufficient to guard against such things. */ + bt_reset_interface(); } unlock(&bt.msgq_lock); } @@ -367,7 +374,7 @@ static int bt_add_ipmi_msg(struct ipmi_msg *ipmi_msg) struct bt_msg *bt_msg = container_of(ipmi_msg, struct bt_msg, ipmi_msg); lock(&bt.msgq_lock); - bt_msg->tb = mftb(); + bt_msg->tb = 0; bt_msg->seq = ipmi_seq++; list_add_tail(&bt.msgq, &bt_msg->link); bt.queue_len++; |