diff options
author | Alistair Popple <alistair@popple.id.au> | 2014-09-15 10:58:10 +1000 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-10-01 14:25:26 +1000 |
commit | b652c6004db44c6ba1371e90b6a5da7213b40522 (patch) | |
tree | 739b7d86f52e3770f9f20f491895735fbe6a25fb /hw | |
parent | 6a2019f7227ba5a65dfe28aaeb5c9fc5c5bcfea8 (diff) | |
download | skiboot-b652c6004db44c6ba1371e90b6a5da7213b40522.zip skiboot-b652c6004db44c6ba1371e90b6a5da7213b40522.tar.gz skiboot-b652c6004db44c6ba1371e90b6a5da7213b40522.tar.bz2 |
bt: Add message timeout
This patch adds message timeouts to the bt layer. When a response to a
message is not recieved within a given time we call the error callback
with a completion code indicating a timeout.
Signed-off-by: Alistair Popple <alistair@popple.id.au>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/bt.c | 40 | ||||
-rw-r--r-- | hw/ipmi/ipmi-rtc.c | 17 |
2 files changed, 50 insertions, 7 deletions
@@ -18,7 +18,7 @@ #include <lpc.h> #include <lock.h> #include <device.h> -#include <time.h> +#include <timebase.h> #include <ipmi.h> #include <bt.h> @@ -53,6 +53,11 @@ */ #define BT_MAX_QUEUE_LEN 5 +/* + * How long (in TB ticks) before a message is timed out. + */ +#define BT_MSG_TIMEOUT (secs_to_tb(1)) + enum bt_states { BT_STATE_IDLE = 0, BT_STATE_RESP_WAIT, @@ -67,6 +72,7 @@ const char *state_str[] = { struct bt_msg { struct list_node link; + unsigned long tb; uint8_t seq; uint8_t lun; struct ipmi_msg ipmi_msg; @@ -117,12 +123,21 @@ static inline void bt_set_state(enum bt_states next_state) bt.state = next_state; } +static void bt_msg_del(struct bt_msg *bt_msg) +{ + list_del(&bt_msg->link); + bt.queue_len--; + ipmi_cmd_done(bt_msg->ipmi_msg.cmd, bt_msg->ipmi_msg.netfn + 1, + IPMI_TIMEOUT_ERR, &bt_msg->ipmi_msg); +} + 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); bt_msg->lun = 0; lock(&bt.lock); + bt_msg->tb = mftb(); bt_msg->seq = ipmi_seq++; list_add_tail(&bt.msgq, &bt_msg->link); bt.queue_len++; @@ -132,10 +147,7 @@ static int bt_add_ipmi_msg(struct ipmi_msg *ipmi_msg) 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); + bt_msg_del(bt_msg); } unlock(&bt.lock); @@ -295,11 +307,29 @@ static bool bt_get_resp(void) return false; } +static void bt_expire_old_msg(void) +{ + unsigned long tb; + struct bt_msg *bt_msg, *next; + + lock(&bt.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); + } + } + unlock(&bt.lock); +} + static void bt_poll(void *data __unused) { bool ret = true; do { + bt_expire_old_msg(); + switch(bt.state) { case BT_STATE_IDLE: ret = bt_try_send_msg(); diff --git a/hw/ipmi/ipmi-rtc.c b/hw/ipmi/ipmi-rtc.c index 7ac33ff..7dc7f59 100644 --- a/hw/ipmi/ipmi-rtc.c +++ b/hw/ipmi/ipmi-rtc.c @@ -24,7 +24,13 @@ /* Sane default (2014/01/01) */ static time_t time = 1388494800; -static enum {idle, waiting, updated} time_status; +static enum {idle, waiting, updated, error} time_status; + +static void get_sel_time_error(struct ipmi_msg *msg) +{ + time_status = error; + ipmi_free_msg(msg); +} static void get_sel_time_complete(struct ipmi_msg *msg) { @@ -33,6 +39,7 @@ static void get_sel_time_complete(struct ipmi_msg *msg) memcpy(&result, msg->data, 4); time = le32_to_cpu(result); time_status = updated; + ipmi_free_msg(msg); } static int64_t ipmi_get_sel_time(void) @@ -44,6 +51,8 @@ static int64_t ipmi_get_sel_time(void) if (!msg) return OPAL_HARDWARE; + msg->error = get_sel_time_error; + return ipmi_queue_msg(msg); } @@ -59,7 +68,6 @@ static int64_t ipmi_set_sel_time(uint32_t tv) return ipmi_queue_msg(msg); } -void bt_poll(void *data __unused); static int64_t ipmi_opal_rtc_read(uint32_t *y_m_d, uint64_t *h_m_s_m) { @@ -84,6 +92,11 @@ static int64_t ipmi_opal_rtc_read(uint32_t *y_m_d, time_status = idle; ret = OPAL_SUCCESS; break; + + case error: + time_status = idle; + ret = OPAL_HARDWARE; + break; } return ret; |