diff options
-rw-r--r-- | core/ipmi.c | 12 | ||||
-rw-r--r-- | hw/bt.c | 6 | ||||
-rw-r--r-- | hw/fsp/fsp-ipmi.c | 2 | ||||
-rw-r--r-- | include/ipmi.h | 9 |
4 files changed, 28 insertions, 1 deletions
diff --git a/core/ipmi.c b/core/ipmi.c index 2bf3f4d..9cf5aa6 100644 --- a/core/ipmi.c +++ b/core/ipmi.c @@ -182,8 +182,18 @@ void ipmi_queue_msg_sync(struct ipmi_msg *msg) ipmi_queue_msg_head(msg); unlock(&sync_lock); - while (sync_msg == msg) + /* + * BT response handling relies on a timer. We can't just run all + * timers because we may have been called with a lock that a timer + * wants, and they're generally not written to cope with that. + * So, just run whatever the IPMI backend needs to make forward + * progress. + */ + while (sync_msg == msg) { + if (msg->backend->poll) + msg->backend->poll(); time_wait_ms(10); + } } static void ipmi_read_event_complete(struct ipmi_msg *msg) @@ -526,6 +526,11 @@ static void bt_poll(struct timer *t __unused, void *data __unused, bt.irq_ok ? TIMER_POLL : msecs_to_tb(BT_DEFAULT_POLL_MS)); } +static void bt_ipmi_poll(void) +{ + bt_poll(NULL, NULL, mftb()); +} + static void bt_add_msg(struct bt_msg *bt_msg) { bt_msg->tb = 0; @@ -647,6 +652,7 @@ static struct ipmi_backend bt_backend = { .queue_msg_head = bt_add_ipmi_msg_head, .dequeue_msg = bt_del_ipmi_msg, .disable_retry = bt_disable_ipmi_msg_retry, + .poll = bt_ipmi_poll, }; static struct lpc_client bt_lpc_client = { diff --git a/hw/fsp/fsp-ipmi.c b/hw/fsp/fsp-ipmi.c index d262cee..8c65e6c 100644 --- a/hw/fsp/fsp-ipmi.c +++ b/hw/fsp/fsp-ipmi.c @@ -254,6 +254,8 @@ static struct ipmi_backend fsp_ipmi_backend = { .queue_msg = fsp_ipmi_queue_msg, .queue_msg_head = fsp_ipmi_queue_msg_head, .dequeue_msg = fsp_ipmi_dequeue_msg, + /* FIXME if ever use ipmi_queue_msg_sync on FSP */ + .poll = NULL, }; static bool fsp_ipmi_send_response(uint32_t cmd) diff --git a/include/ipmi.h b/include/ipmi.h index 4999bb5..ea5a0a9 100644 --- a/include/ipmi.h +++ b/include/ipmi.h @@ -182,6 +182,15 @@ struct ipmi_backend { int (*queue_msg_head)(struct ipmi_msg *); int (*dequeue_msg)(struct ipmi_msg *); void (*disable_retry)(struct ipmi_msg *); + /* + * When processing a synchronous IPMI message, pollers may not run, and + * neither may timers (as the synchronous IPMI message may be being + * done with locks held, which a timer may then try to also take). + * + * So, ensure we have a way to drive any state machines that an IPMI + * backend may neeed to crank to ensure forward progress. + */ + void (*poll)(void); }; extern struct ipmi_backend *ipmi_backend; |