From: Corey Minyard <cminyard@mvista.com>
To: Linus Torvalds <torvalds@transmeta.com>
Cc: lkml <linux-kernel@vger.kernel.org>
Subject: IPMI fixes for 2.6.0-test7
Date: Thu, 09 Oct 2003 08:35:55 -0500 [thread overview]
Message-ID: <3F85643B.6020701@mvista.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 315 bytes --]
Linus,
The following patch fixes some problems with timing calculations
(primarily for ia64) and adds an operation to send panic strings to the
IPMI event log on a panic. I've sent this several times, and I've had
several requests to get this in before 2.6 goes out. Could you please
apply?
Thanks,
-Corey
[-- Attachment #2: ipmi-2.6.0-test7.diff --]
[-- Type: text/plain, Size: 10720 bytes --]
Index: include/linux/ipmi_msgdefs.h
===================================================================
RCS file: /home/cvs/linux-2.5/include/linux/ipmi_msgdefs.h,v
retrieving revision 1.2
diff -u -r1.2 ipmi_msgdefs.h
--- linux.old/include/linux/ipmi_msgdefs.h 13 Jan 2003 21:20:22 -0000 1.2
+++ linux/include/linux/ipmi_msgdefs.h 9 Oct 2003 11:33:46 -0000
@@ -37,22 +37,32 @@
/* Various definitions for IPMI messages used by almost everything in
the IPMI stack. */
-#define IPMI_NETFN_APP_REQUEST 0x06
-#define IPMI_NETFN_APP_RESPONSE 0x07
+/* NetFNs and commands used inside the IPMI stack. */
-#define IPMI_BMC_SLAVE_ADDR 0x20
+#define IPMI_NETFN_SENSOR_EVENT_REQUEST 0x04
+#define IPMI_NETFN_SENSOR_EVENT_RESPONSE 0x05
+#define IPMI_GET_EVENT_RECEIVER_CMD 0x01
+#define IPMI_NETFN_APP_REQUEST 0x06
+#define IPMI_NETFN_APP_RESPONSE 0x07
#define IPMI_GET_DEVICE_ID_CMD 0x01
-
#define IPMI_CLEAR_MSG_FLAGS_CMD 0x30
#define IPMI_GET_MSG_FLAGS_CMD 0x31
#define IPMI_SEND_MSG_CMD 0x34
#define IPMI_GET_MSG_CMD 0x33
-
#define IPMI_SET_BMC_GLOBAL_ENABLES_CMD 0x2e
#define IPMI_GET_BMC_GLOBAL_ENABLES_CMD 0x2f
#define IPMI_READ_EVENT_MSG_BUFFER_CMD 0x35
+#define IPMI_NETFN_STORAGE_REQUEST 0x0a
+#define IPMI_NETFN_STORAGE_RESPONSE 0x0b
+#define IPMI_ADD_SEL_ENTRY_CMD 0x44
+
+/* The default slave address */
+#define IPMI_BMC_SLAVE_ADDR 0x20
+
#define IPMI_MAX_MSG_LENGTH 80
+
+#define IPMI_CC_NO_ERROR 0
#endif /* __LINUX_IPMI_MSGDEFS_H */
Index: drivers/char/ipmi/Kconfig
===================================================================
RCS file: /home/cvs/linux-2.5/drivers/char/ipmi/Kconfig,v
retrieving revision 1.3
diff -u -r1.3 Kconfig
--- linux.old/drivers/char/ipmi/Kconfig 28 Mar 2003 05:14:18 -0000 1.3
+++ linux/drivers/char/ipmi/Kconfig 9 Oct 2003 11:33:46 -0000
@@ -24,6 +24,18 @@
generate an IPMI event describing the panic to each interface
registered with the message handler.
+config IPMI_PANIC_STRING
+ bool 'Generate OEM events containing the panic string'
+ depends on IPMI_PANIC_EVENT
+ help
+ When a panic occurs, this will cause the IPMI message handler to
+ generate IPMI OEM type f0 events holding the IPMB address of the
+ panic generator (byte 4 of the event), a sequence number for the
+ string (byte 5 of the event) and part of the string (the rest of the
+ event). Bytes 1, 2, and 3 are the normal usage for an OEM event.
+ You can fetch these events and use the sequence numbers to piece the
+ string together.
+
config IPMI_DEVICE_INTERFACE
tristate 'Device interface for IPMI'
depends on IPMI_HANDLER
Index: drivers/char/ipmi/ipmi_msghandler.c
===================================================================
RCS file: /home/cvs/linux-2.5/drivers/char/ipmi/ipmi_msghandler.c,v
retrieving revision 1.7
diff -u -r1.7 ipmi_msghandler.c
--- linux.old/drivers/char/ipmi/ipmi_msghandler.c 24 May 2003 17:02:51 -0000 1.7
+++ linux/drivers/char/ipmi/ipmi_msghandler.c 9 Oct 2003 11:33:48 -0000
@@ -169,6 +169,19 @@
/* My LUN. This should generally stay the SMS LUN, but just in
case... */
unsigned char my_lun;
+
+ /* The event receiver for my BMC, only really used at panic
+ shutdown as a place to store this. */
+ unsigned char event_receiver;
+ unsigned char event_receiver_lun;
+ unsigned char local_sel_device;
+ unsigned char local_event_generator;
+
+ /* A cheap hack, if this is non-null and a message to an
+ interface comes in with a NULL user, call this routine with
+ it. Note that the message will still be freed by the
+ caller. This only works on the system interface. */
+ void (*null_user_handler)(ipmi_smi_t intf, struct ipmi_smi_msg *msg);
};
int
@@ -1465,6 +1478,9 @@
}
if (!found) {
+ /* Special handling for NULL users. */
+ if (!recv_msg->user && intf->null_user_handler)
+ intf->null_user_handler(intf, msg);
/* The user for the message went away, so give up. */
ipmi_free_recv_msg(recv_msg);
} else {
@@ -1733,7 +1749,7 @@
/* Call every 100 ms. */
#define IPMI_TIMEOUT_TIME 100
-#define IPMI_TIMEOUT_JIFFIES (IPMI_TIMEOUT_TIME/(1000/HZ))
+#define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ)/1000)
/* Request events from the queue every second. Hopefully, in the
future, IPMI will add a way to know immediately if an event is
@@ -1813,18 +1829,48 @@
{
}
-static void send_panic_events(void)
+#ifdef CONFIG_IPMI_PANIC_STRING
+static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+{
+ if ((msg->rsp[0] == (IPMI_NETFN_SENSOR_EVENT_RESPONSE << 2))
+ && (msg->rsp[1] == IPMI_GET_EVENT_RECEIVER_CMD)
+ && (msg->rsp[2] == IPMI_CC_NO_ERROR))
+ {
+ /* A get event receiver command, save it. */
+ intf->event_receiver = msg->rsp[3];
+ intf->event_receiver_lun = msg->rsp[4] & 0x3;
+ }
+}
+
+static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
+{
+ if ((msg->rsp[0] == (IPMI_NETFN_APP_RESPONSE << 2))
+ && (msg->rsp[1] == IPMI_GET_DEVICE_ID_CMD)
+ && (msg->rsp[2] == IPMI_CC_NO_ERROR))
+ {
+ /* A get device id command, save if we are an event
+ receiver or generator. */
+ intf->local_sel_device = (msg->rsp[8] >> 2) & 1;
+ intf->local_event_generator = (msg->rsp[8] >> 5) & 1;
+ }
+}
+#endif
+
+static void send_panic_events(char *str)
{
struct ipmi_msg msg;
ipmi_smi_t intf;
- unsigned char data[8];
+ unsigned char data[16];
int i;
- struct ipmi_system_interface_addr addr;
+ struct ipmi_system_interface_addr *si;
+ struct ipmi_addr addr;
struct ipmi_smi_msg smi_msg;
struct ipmi_recv_msg recv_msg;
- addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
- addr.channel = IPMI_BMC_CHANNEL;
+ si = (struct ipmi_system_interface_addr *) &addr;
+ si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+ si->channel = IPMI_BMC_CHANNEL;
+ si->lun = 0;
/* Fill in an event telling that we have failed. */
msg.netfn = 0x04; /* Sensor or Event. */
@@ -1837,12 +1883,13 @@
data[4] = 0x6f; /* Sensor specific, IPMI table 36-1 */
data[5] = 0xa1; /* Runtime stop OEM bytes 2 & 3. */
- /* These used to have the first three bytes of the panic string,
- but not only is that not terribly useful, it's not available
- any more. */
- data[3] = 0;
- data[6] = 0;
- data[7] = 0;
+ /* Put a few breadcrumbs in. Hopefully later we can add more things
+ to make the panic events more useful. */
+ if (str) {
+ data[3] = str[0];
+ data[6] = str[1];
+ data[7] = str[2];
+ }
smi_msg.done = dummy_smi_done_handler;
recv_msg.done = dummy_recv_done_handler;
@@ -1853,10 +1900,11 @@
if (intf == NULL)
continue;
+ /* Send the event announcing the panic. */
intf->handlers->set_run_to_completion(intf->send_info, 1);
i_ipmi_request(NULL,
intf,
- (struct ipmi_addr *) &addr,
+ &addr,
0,
&msg,
&smi_msg,
@@ -1865,6 +1913,130 @@
intf->my_address,
intf->my_lun);
}
+
+#ifdef CONFIG_IPMI_PANIC_STRING
+ /* On every interface, dump a bunch of OEM event holding the
+ string. */
+ if (!str)
+ return;
+
+ for (i=0; i<MAX_IPMI_INTERFACES; i++) {
+ char *p = str;
+ struct ipmi_ipmb_addr *ipmb;
+ int j;
+
+ intf = ipmi_interfaces[i];
+ if (intf == NULL)
+ continue;
+
+ /* First job here is to figure out where to send the
+ OEM events. There's no way in IPMI to send OEM
+ events using an event send command, so we have to
+ find the SEL to put them in and stick them in
+ there. */
+
+ /* Get capabilities from the get device id. */
+ intf->local_sel_device = 0;
+ intf->local_event_generator = 0;
+ intf->event_receiver = 0;
+
+ /* Request the device info from the local MC. */
+ msg.netfn = IPMI_NETFN_APP_REQUEST;
+ msg.cmd = IPMI_GET_DEVICE_ID_CMD;
+ msg.data = NULL;
+ msg.data_len = 0;
+ intf->null_user_handler = device_id_fetcher;
+ i_ipmi_request(NULL,
+ intf,
+ &addr,
+ 0,
+ &msg,
+ &smi_msg,
+ &recv_msg,
+ 0,
+ intf->my_address,
+ intf->my_lun);
+
+ if (intf->local_event_generator) {
+ /* Request the event receiver from the local MC. */
+ msg.netfn = IPMI_NETFN_SENSOR_EVENT_REQUEST;
+ msg.cmd = IPMI_GET_EVENT_RECEIVER_CMD;
+ msg.data = NULL;
+ msg.data_len = 0;
+ intf->null_user_handler = event_receiver_fetcher;
+ i_ipmi_request(NULL,
+ intf,
+ &addr,
+ 0,
+ &msg,
+ &smi_msg,
+ &recv_msg,
+ 0,
+ intf->my_address,
+ intf->my_lun);
+ }
+ intf->null_user_handler = NULL;
+
+ /* Validate the event receiver. The low bit must not
+ be 1 (it must be a valid IPMB address), it cannot
+ be zero, and it must not be my address. */
+ if (((intf->event_receiver & 1) == 0)
+ && (intf->event_receiver != 0)
+ && (intf->event_receiver != intf->my_address))
+ {
+ /* The event receiver is valid, send an IPMB
+ message. */
+ ipmb = (struct ipmi_ipmb_addr *) &addr;
+ ipmb->addr_type = IPMI_IPMB_ADDR_TYPE;
+ ipmb->channel = 0; /* FIXME - is this right? */
+ ipmb->lun = intf->event_receiver_lun;
+ ipmb->slave_addr = intf->event_receiver;
+ } else if (intf->local_sel_device) {
+ /* The event receiver was not valid (or was
+ me), but I am an SEL device, just dump it
+ in my SEL. */
+ si = (struct ipmi_system_interface_addr *) &addr;
+ si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+ si->channel = IPMI_BMC_CHANNEL;
+ si->lun = 0;
+ } else
+ continue; /* No where to send the event. */
+
+
+ msg.netfn = IPMI_NETFN_STORAGE_REQUEST; /* Storage. */
+ msg.cmd = IPMI_ADD_SEL_ENTRY_CMD;
+ msg.data = data;
+ msg.data_len = 16;
+
+ j = 0;
+ while (*p) {
+ int size = strlen(p);
+
+ if (size > 11)
+ size = 11;
+ data[0] = 0;
+ data[1] = 0;
+ data[2] = 0xf0; /* OEM event without timestamp. */
+ data[3] = intf->my_address;
+ data[4] = j++; /* sequence # */
+ /* Always give 11 bytes, so strncpy will fill
+ it with zeroes for me. */
+ strncpy(data+5, p, 11);
+ p += size;
+
+ i_ipmi_request(NULL,
+ intf,
+ &addr,
+ 0,
+ &msg,
+ &smi_msg,
+ &recv_msg,
+ 0,
+ intf->my_address,
+ intf->my_lun);
+ }
+ }
+#endif /* CONFIG_IPMI_PANIC_STRING */
}
#endif /* CONFIG_IPMI_PANIC_EVENT */
@@ -1891,7 +2063,7 @@
}
#ifdef CONFIG_IPMI_PANIC_EVENT
- send_panic_events();
+ send_panic_events(ptr);
#endif
return NOTIFY_DONE;
reply other threads:[~2003-10-09 13:36 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3F85643B.6020701@mvista.com \
--to=cminyard@mvista.com \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@transmeta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.