@@ -19,8 +19,13 @@
#include <ipmi.h>
#include <opal.h>
#include <device.h>
+#include <lock.h>
+#include <cpu.h>
+#include <timebase.h>
struct ipmi_backend *ipmi_backend = NULL;
+static struct lock sync_lock = LOCK_UNLOCKED;
+static struct ipmi_msg *sync_msg = NULL;
void ipmi_free_msg(struct ipmi_msg *msg)
{
@@ -109,6 +114,24 @@ void ipmi_cmd_done(uint8_t cmd, uint8_t netfn, uint8_t cc, struct ipmi_msg *msg)
/* At this point the message has should have been freed by the
completion functions. */
+
+ /* If this is a synchronous message flag that we are done */
+ if (msg == sync_msg)
+ sync_msg = NULL;
+}
+
+void ipmi_queue_msg_sync(struct ipmi_msg *msg)
+{
+ lock(&sync_lock);
+
+ assert(!sync_msg);
+ sync_msg = msg;
+ ipmi_queue_msg(msg);
+
+ while (sync_msg)
+ time_wait_ms(100);
+
+ unlock(&sync_lock);
}
static void ipmi_read_event_complete(struct ipmi_msg *msg)
@@ -193,6 +193,10 @@ int ipmi_queue_msg(struct ipmi_msg *msg);
/* Add an ipmi message to the start of the queue */
int ipmi_queue_msg_head(struct ipmi_msg *msg);
+/* Synchronously send an ipmi message. This won't return until the
+ * messages callback has been called. */
+void ipmi_queue_msg_sync(struct ipmi_msg *msg);
+
/* Process a completed message */
void ipmi_cmd_done(uint8_t cmd, uint8_t netfn, uint8_t cc, struct ipmi_msg *msg);
This patch adds support for sending ipmi messages synchronously. This is necessary to allow messages to be sent during skiboot initialisation as interrupt servicing/polling is controlled by the host operating system which is not yet running. Signed-off-by: Alistair Popple <alistair@popple.id.au> --- core/ipmi.c | 23 +++++++++++++++++++++++ include/ipmi.h | 4 ++++ 2 files changed, 27 insertions(+)