aboutsummaryrefslogtreecommitdiff
path: root/core/ipmi.c
diff options
context:
space:
mode:
authorStewart Smith <stewart@linux.ibm.com>2019-05-01 17:05:56 +1000
committerOliver O'Halloran <oohall@gmail.com>2019-05-09 15:06:39 +1000
commitf01cd777adb16cbab93215d26159aa1c4606112c (patch)
treede841e5f2ddf3543003d34f5f4297bddc2b05a7b /core/ipmi.c
parent22057f868f3b2b1fd02647a738f6da0858b5eb6c (diff)
downloadskiboot-f01cd777adb16cbab93215d26159aa1c4606112c.zip
skiboot-f01cd777adb16cbab93215d26159aa1c4606112c.tar.gz
skiboot-f01cd777adb16cbab93215d26159aa1c4606112c.tar.bz2
ipmi: ensure forward progress on ipmi_queue_msg_sync()
BT responses are handled using a timer doing the polling. To hope to get an answer to an IPMI synchronous message, the timer needs to run. We can't just check all timers though as there may be a timer that wants a lock that's held by a code path calling ipmi_queue_msg_sync(), and if we did enforce that as a requirement, it's a pretty subtle API that is asking to be broken. So, if we just run a poll function to crank anything that the IPMI backend needs, then we should be fine. This issue shows up very quickly under QEMU when loading the first flash resource with the IPMI HIOMAP backend. Reported-by: Cédric Le Goater <clg@kaod.org> Signed-off-by: Stewart Smith <stewart@linux.ibm.com> Reviewed-by: Andrew Jeffery <andrew@aj.id.au> Reviewed-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'core/ipmi.c')
-rw-r--r--core/ipmi.c12
1 files changed, 11 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)