aboutsummaryrefslogtreecommitdiff
path: root/hw/bt.c
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2014-09-15 10:58:09 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-10-01 14:25:26 +1000
commit6a2019f7227ba5a65dfe28aaeb5c9fc5c5bcfea8 (patch)
tree29fced455aab5f888ae766e791cedec7c8da886c /hw/bt.c
parent7f414dbb7f7851eccbe98875b1a2cb155b592f3e (diff)
downloadskiboot-6a2019f7227ba5a65dfe28aaeb5c9fc5c5bcfea8.zip
skiboot-6a2019f7227ba5a65dfe28aaeb5c9fc5c5bcfea8.tar.gz
skiboot-6a2019f7227ba5a65dfe28aaeb5c9fc5c5bcfea8.tar.bz2
bt: Limit the outstanding message queue length
This patch ensures that the number of outstanding messages in the bt interface queue can not grow unchecked. If adding a message to the queue causes it to exceed the maximum size we remove the oldest message from the queue. Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'hw/bt.c')
-rw-r--r--hw/bt.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/hw/bt.c b/hw/bt.c
index cd4b7e0..9f237d4 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -48,6 +48,11 @@
*/
#define POLL_TIMEOUT 10000
+/*
+ * Maximum number of outstanding messages to allow in the queue.
+ */
+#define BT_MAX_QUEUE_LEN 5
+
enum bt_states {
BT_STATE_IDLE = 0,
BT_STATE_RESP_WAIT,
@@ -72,6 +77,7 @@ struct bt {
enum bt_states state;
struct lock lock;
struct list_head msgq;
+ int queue_len;
};
static struct bt bt;
@@ -119,6 +125,18 @@ static int bt_add_ipmi_msg(struct ipmi_msg *ipmi_msg)
lock(&bt.lock);
bt_msg->seq = ipmi_seq++;
list_add_tail(&bt.msgq, &bt_msg->link);
+ bt.queue_len++;
+ if (bt.queue_len > BT_MAX_QUEUE_LEN) {
+ /* Maximum ueue lenght exceeded - remove the oldest message
+ from the queue. */
+ prerror("BT: Maximum queue length exceeded\n");
+ bt_msg = list_tail(&bt.msgq, struct bt_msg, link);
+ assert(bt_msg);
+ list_del(&bt_msg->link);
+ bt.queue_len--;
+ ipmi_cmd_done(bt_msg->ipmi_msg.cmd, bt_msg->ipmi_msg.netfn,
+ IPMI_TIMEOUT_ERR, &bt_msg->ipmi_msg);
+ }
unlock(&bt.lock);
return 0;
@@ -265,6 +283,7 @@ static bool bt_get_resp(void)
/* Make sure the other side is idle before we move to the idle state */
bt_set_state(BT_STATE_B_BUSY);
list_del(&bt_msg->link);
+ bt.queue_len--;
unlock(&bt.lock);
/*
@@ -342,6 +361,7 @@ static int bt_del_ipmi_msg(struct ipmi_msg *ipmi_msg)
lock(&bt.lock);
list_del(&bt_msg->link);
+ bt.queue_len--;
unlock(&bt.lock);
return 0;
}
@@ -383,6 +403,7 @@ void bt_init(void)
*/
bt_set_state(BT_STATE_B_BUSY);
list_head_init(&bt.msgq);
+ bt.queue_len = 0;
opal_add_poller(bt_poll, NULL);