[Skiboot] [PATCH 1/4] ipmi: handle SMS_ATN events

Joel Stanley joel at jms.id.au
Thu Feb 5 14:10:02 AEDT 2015


From: Jeremy Kerr <jeremy.kerr at au.ibm.com>

When the bt interface sets the SMS_ATN flag, we perform a Get Message
Flags to determine what messages are available.

The only message type currently processed is the Event Message Buffer,
which provides SEL messages for indicating OEM specific events such as
graceful system shutdown and PNOR access requested. These events will be
handled by the IPMI layer in skiboot.

Signed-off-by: Jeremy Kerr <jk at ozlabs.org>
Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 core/ipmi.c    | 40 ++++++++++++++++++++++++++++++++++++++++
 hw/bt.c        |  6 ++++++
 include/ipmi.h | 15 +++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/core/ipmi.c b/core/ipmi.c
index 14c35f3..35bfead 100644
--- a/core/ipmi.c
+++ b/core/ipmi.c
@@ -103,6 +103,46 @@ void ipmi_cmd_done(uint8_t cmd, uint8_t netfn, uint8_t cc, struct ipmi_msg *msg)
 	   completion functions. */
 }
 
+static void ipmi_read_event_complete(struct ipmi_msg *msg)
+{
+	prlog(PR_DEBUG, "IPMI read event %02x complete: %d bytes. cc: %02x\n",
+	      msg->cmd, msg->resp_size, msg->cc);
+
+	/* TODO: Handle power control & PNOR handshake events */
+
+	ipmi_free_msg(msg);
+}
+
+static void ipmi_get_message_flags_complete(struct ipmi_msg *msg)
+{
+	uint8_t flags = msg->data[0];
+
+	ipmi_free_msg(msg);
+
+	prlog(PR_DEBUG, "IPMI Get Message Flags: %02x\n", flags);
+
+	/* Message available in the event buffer? Queue a Read Event command
+	 * to retrieve it. The flag is cleared by performing a read */
+	if (flags & IPMI_MESSAGE_FLAGS_EVENT_BUFFER) {
+		msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_READ_EVENT,
+				ipmi_read_event_complete, NULL, NULL, 0, 16);
+		ipmi_queue_msg(msg);
+	}
+}
+
+void ipmi_sms_attention(void)
+{
+	struct ipmi_msg *msg;
+
+	/* todo: when we handle multiple IPMI interfaces, we'll need to
+	 * ensure that this message is associated with the appropriate
+	 * backend. */
+	msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_GET_MESSAGE_FLAGS,
+			ipmi_get_message_flags_complete, NULL, NULL, 0, 1);
+
+	ipmi_queue_msg(msg);
+}
+
 void ipmi_register_backend(struct ipmi_backend *backend)
 {
 	/* We only support one backend at the moment */
diff --git a/hw/bt.c b/hw/bt.c
index afdd5df..d5c71a8 100644
--- a/hw/bt.c
+++ b/hw/bt.c
@@ -418,12 +418,18 @@ static int bt_add_ipmi_msg(struct ipmi_msg *ipmi_msg)
 void bt_irq(void)
 {
 	uint8_t ireg = bt_inb(BT_INTMASK);
+	uint8_t ctrl = bt_inb(BT_CTRL);
 
 	bt.irq_ok = true;
 	if (ireg & BT_INTMASK_B2H_IRQ) {
 		bt_outb(BT_INTMASK_B2H_IRQ | BT_INTMASK_B2H_IRQEN, BT_INTMASK);
 		bt_poll(NULL, NULL);
 	}
+
+	if (ctrl & BT_CTRL_SMS_ATN) {
+		bt_outb(BT_CTRL_SMS_ATN, BT_CTRL);
+		ipmi_sms_attention();
+	}
 }
 
 /*
diff --git a/include/ipmi.h b/include/ipmi.h
index 50de293..740b82a 100644
--- a/include/ipmi.h
+++ b/include/ipmi.h
@@ -76,6 +76,14 @@
 #define   IPMI_PWR_SYS_UNKNOWN			0x2a
 #define   IPMI_PWR_NOCHANGE                     0x7f
 
+/* 22.{3,4} Clear / Get message flags */
+#define	IPMI_MESSAGE_FLAGS_RX_MESSAGE_QUEUE	(1<<0)
+#define IPMI_MESSAGE_FLAGS_EVENT_BUFFER		(1<<1)
+#define IPMI_MESSAGE_FLAGS_WATCHDOG_PRE_TIMEOUT	(1<<3)
+#define IPMI_MESSAGE_FLAGS_OEM0			(1<<5)
+#define IPMI_MESSAGE_FLAGS_OEM1			(1<<6)
+#define IPMI_MESSAGE_FLAGS_OEM2			(1<<7)
+
 #define IPMI_CODE(netfn, cmd)		((netfn) << 8 | (cmd))
 #define IPMI_CMD(code)			((code) & 0xff)
 #define IPMI_NETFN(code)		((code) >> 8 & 0xff)
@@ -93,6 +101,10 @@
 #define IPMI_CHASSIS_CONTROL		IPMI_CODE(IPMI_NETFN_CHASSIS, 0x02)
 #define IPMI_SET_POWER_STATE		IPMI_CODE(IPMI_NETFN_APP, 0x06)
 #define IPMI_GET_POWER_STATE		IPMI_CODE(IPMI_NETFN_APP, 0x07)
+#define IPMI_CLEAR_MESSAGE_FLAGS	IPMI_CODE(IPMI_NETFN_APP, 0x30)
+#define IPMI_GET_MESSAGE_FLAGS		IPMI_CODE(IPMI_NETFN_APP, 0x31)
+#define IPMI_GET_MESSAGE		IPMI_CODE(IPMI_NETFN_APP, 0x33)
+#define IPMI_READ_EVENT			IPMI_CODE(IPMI_NETFN_APP, 0x35)
 
 #define IPMI_PARTIAL_ADD_ESEL		IPMI_CODE(IPMI_NETFN_OEM, 0xf0)
 
@@ -163,6 +175,9 @@ struct ipmi_msg *ipmi_mkmsg(int interface, uint32_t code,
 			    void *user_data, void *req_data, size_t req_size,
 			    size_t resp_size);
 
+/* called by backend code to indicate a SMS_ATN event */
+void ipmi_sms_attention(void);
+
 /* Add an ipmi message to the queue */
 int ipmi_queue_msg(struct ipmi_msg *msg);
 
-- 
2.1.4



More information about the Skiboot mailing list