All of lore.kernel.org
 help / color / mirror / Atom feed
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.