aboutsummaryrefslogtreecommitdiff
path: root/hw/bt.c
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2014-11-05 14:40:47 +1100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-11-12 16:41:25 +1100
commit983db8cc4b6444de8df2ce1a273f3f3b9eec12c3 (patch)
treed174e343455e207fcd449bb9b2e664f5a368bedf /hw/bt.c
parentd51cbd7c69b4669dddb34b100197d045d7f06c2d (diff)
downloadskiboot-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.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/hw/bt.c b/hw/bt.c
index 1d4e677..c57b883 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -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++;