aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/ipmi.c12
-rw-r--r--hw/bt.c6
-rw-r--r--hw/fsp/fsp-ipmi.c2
-rw-r--r--include/ipmi.h9
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)
diff --git a/hw/bt.c b/hw/bt.c
index 9febe8e..a0ff0db 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -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;