Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c9f98d1 authored by Corey Minyard's avatar Corey Minyard
Browse files

ipmi: Make IPMI panic strings always available



They were set by config items, but people complained that they were
never turned on.  So have them always available and enabled by a
module parameter.

Signed-off-by: default avatarCorey Minyard <cminyard@mvista.com>
parent b72fce52
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -81,7 +81,9 @@ If you want the driver to put an event into the event log on a panic,
enable the 'Generate a panic event to all BMCs on a panic' option.  If
you want the whole panic string put into the event log using OEM
events, enable the 'Generate OEM events containing the panic string'
option.
option.  You can also enable these dynamically by setting the module
parameter named "panic_op" in the ipmi_msghandler module to "event"
or "string".  Setting that parameter to "none" disables this function.

Basic Design
------------
+17 −10
Original line number Diff line number Diff line
@@ -25,21 +25,28 @@ if IPMI_HANDLER
config IPMI_PANIC_EVENT
       bool 'Generate a panic event to all BMCs on a panic'
       help
         When a panic occurs, this will cause the IPMI message handler to
	 generate an IPMI event describing the panic to each interface
	 registered with the message handler.
	 When a panic occurs, this will cause the IPMI message handler to,
	 by default, generate an IPMI event describing the panic to each
	 interface registered with the message handler.  This is always
	 available, the module parameter for ipmi_msghandler named
	 panic_op can be set to "event" to chose this value, this config
	 simply causes the default value to be set to "event".

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.
	  When a panic occurs, this will cause the IPMI message handler to,
	  by default, 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.  This config
	  parameter sets the default value to generate these events,
	  the module parameter for ipmi_msghandler named panic_op can
	  be set to "string" to chose this value, this config simply
	  causes the default value to be set to "string".

config IPMI_DEVICE_INTERFACE
       tristate 'Device interface for IPMI'
+78 −13
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
#include <linux/proc_fs.h>
#include <linux/rcupdate.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>

#define PFX "IPMI message handler: "

@@ -61,6 +62,74 @@ static int handle_one_recv_msg(ipmi_smi_t intf,

static int initialized;

enum ipmi_panic_event_op {
	IPMI_SEND_PANIC_EVENT_NONE,
	IPMI_SEND_PANIC_EVENT,
	IPMI_SEND_PANIC_EVENT_STRING
};
#ifdef CONFIG_IPMI_PANIC_STRING
#define IPMI_PANIC_DEFAULT IPMI_SEND_PANIC_EVENT_STRING
#elif defined(CONFIG_IPMI_PANIC_EVENT)
#define IPMI_PANIC_DEFAULT IPMI_SEND_PANIC_EVENT
#else
#define IPMI_PANIC_DEFAULT IPMI_SEND_PANIC_EVENT_NONE
#endif
static enum ipmi_panic_event_op ipmi_send_panic_event = IPMI_PANIC_DEFAULT;

static int panic_op_write_handler(const char *val,
				  const struct kernel_param *kp)
{
	char valcp[16];
	char *s;

	strncpy(valcp, val, 16);
	valcp[15] = '\0';

	s = strstrip(valcp);

	if (strcmp(s, "none") == 0)
		ipmi_send_panic_event = IPMI_SEND_PANIC_EVENT_NONE;
	else if (strcmp(s, "event") == 0)
		ipmi_send_panic_event = IPMI_SEND_PANIC_EVENT;
	else if (strcmp(s, "string") == 0)
		ipmi_send_panic_event = IPMI_SEND_PANIC_EVENT_STRING;
	else
		return -EINVAL;

	return 0;
}

static int panic_op_read_handler(char *buffer, const struct kernel_param *kp)
{
	switch (ipmi_send_panic_event) {
	case IPMI_SEND_PANIC_EVENT_NONE:
		strcpy(buffer, "none");
		break;

	case IPMI_SEND_PANIC_EVENT:
		strcpy(buffer, "event");
		break;

	case IPMI_SEND_PANIC_EVENT_STRING:
		strcpy(buffer, "string");
		break;

	default:
		strcpy(buffer, "???");
		break;
	}

	return strlen(buffer);
}

static const struct kernel_param_ops panic_op_ops = {
	.set = panic_op_write_handler,
	.get = panic_op_read_handler
};
module_param_cb(panic_op, &panic_op_ops, NULL, 0600);
MODULE_PARM_DESC(panic_op, "Sets if the IPMI driver will attempt to store panic information in the event log in the event of a panic.  Set to 'none' for no, 'event' for a single event, or 'string' for a generic event and the panic string in IPMI OEM events.");


#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_ipmi_root;
#endif /* CONFIG_PROC_FS */
@@ -4271,8 +4340,6 @@ void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
}
EXPORT_SYMBOL(ipmi_free_recv_msg);

#ifdef CONFIG_IPMI_PANIC_EVENT

static atomic_t panic_done_count = ATOMIC_INIT(0);

static void dummy_smi_done_handler(struct ipmi_smi_msg *msg)
@@ -4320,7 +4387,6 @@ static void ipmi_panic_request_and_wait(ipmi_smi_t intf,
		ipmi_poll(intf);
}

#ifdef CONFIG_IPMI_PANIC_STRING
static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{
	if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
@@ -4347,7 +4413,6 @@ static void device_id_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
		intf->local_event_generator = (msg->msg.data[6] >> 5) & 1;
	}
}
#endif

static void send_panic_events(char *str)
{
@@ -4357,6 +4422,9 @@ static void send_panic_events(char *str)
	struct ipmi_system_interface_addr *si;
	struct ipmi_addr                  addr;

	if (ipmi_send_panic_event == IPMI_SEND_PANIC_EVENT_NONE)
		return;

	si = (struct ipmi_system_interface_addr *) &addr;
	si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
	si->channel = IPMI_BMC_CHANNEL;
@@ -4385,20 +4453,19 @@ static void send_panic_events(char *str)

	/* For every registered interface, send the event. */
	list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
		if (!intf->handlers)
			/* Interface is not ready. */
		if (!intf->handlers || !intf->handlers->poll)
			/* Interface is not ready or can't run at panic time. */
			continue;

		/* Send the event announcing the panic. */
		ipmi_panic_request_and_wait(intf, &addr, &msg);
	}

#ifdef CONFIG_IPMI_PANIC_STRING
	/*
	 * On every interface, dump a bunch of OEM event holding the
	 * string.
	 */
	if (!str)
	if (ipmi_send_panic_event != IPMI_SEND_PANIC_EVENT_STRING || !str)
		return;

	/* For every registered interface, send the event. */
@@ -4507,9 +4574,7 @@ static void send_panic_events(char *str)
			ipmi_panic_request_and_wait(intf, &addr, &msg);
		}
	}
#endif /* CONFIG_IPMI_PANIC_STRING */
}
#endif /* CONFIG_IPMI_PANIC_EVENT */

static int has_panicked;

@@ -4547,12 +4612,12 @@ static int panic_event(struct notifier_block *this,
			spin_unlock(&intf->waiting_rcv_msgs_lock);

		intf->run_to_completion = 1;
		intf->handlers->set_run_to_completion(intf->send_info, 1);
		if (intf->handlers->set_run_to_completion)
			intf->handlers->set_run_to_completion(intf->send_info,
							      1);
	}

#ifdef CONFIG_IPMI_PANIC_EVENT
	send_panic_events(ptr);
#endif

	return NOTIFY_DONE;
}