1
0
Fork 0

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: Corey Minyard <cminyard@mvista.com>
hifive-unleashed-5.1
Corey Minyard 2017-08-18 17:32:03 -05:00
parent b72fce52a1
commit 1c9f98d1bf
3 changed files with 98 additions and 24 deletions

View File

@ -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 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 you want the whole panic string put into the event log using OEM
events, enable the 'Generate OEM events containing the panic string' 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 Basic Design
------------ ------------

View File

@ -25,21 +25,28 @@ if IPMI_HANDLER
config IPMI_PANIC_EVENT config IPMI_PANIC_EVENT
bool 'Generate a panic event to all BMCs on a panic' bool 'Generate a panic event to all BMCs on a panic'
help help
When a panic occurs, this will cause the IPMI message handler to When a panic occurs, this will cause the IPMI message handler to,
generate an IPMI event describing the panic to each interface by default, generate an IPMI event describing the panic to each
registered with the message handler. 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 config IPMI_PANIC_STRING
bool 'Generate OEM events containing the panic string' bool 'Generate OEM events containing the panic string'
depends on IPMI_PANIC_EVENT depends on IPMI_PANIC_EVENT
help help
When a panic occurs, this will cause the IPMI message handler to When a panic occurs, this will cause the IPMI message handler to,
generate IPMI OEM type f0 events holding the IPMB address of the by default, generate IPMI OEM type f0 events holding the IPMB
panic generator (byte 4 of the event), a sequence number for the address of the panic generator (byte 4 of the event), a sequence
string (byte 5 of the event) and part of the string (the rest of the number for the string (byte 5 of the event) and part of the
event). Bytes 1, 2, and 3 are the normal usage for an OEM event. string (the rest of the event). Bytes 1, 2, and 3 are the normal
You can fetch these events and use the sequence numbers to piece the usage for an OEM event. You can fetch these events and use the
string together. 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 config IPMI_DEVICE_INTERFACE
tristate 'Device interface for IPMI' tristate 'Device interface for IPMI'

View File

@ -46,6 +46,7 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/moduleparam.h>
#define PFX "IPMI message handler: " #define PFX "IPMI message handler: "
@ -61,6 +62,74 @@ static int handle_one_recv_msg(ipmi_smi_t intf,
static int initialized; 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 #ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_ipmi_root; static struct proc_dir_entry *proc_ipmi_root;
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
@ -4271,8 +4340,6 @@ void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
} }
EXPORT_SYMBOL(ipmi_free_recv_msg); EXPORT_SYMBOL(ipmi_free_recv_msg);
#ifdef CONFIG_IPMI_PANIC_EVENT
static atomic_t panic_done_count = ATOMIC_INIT(0); static atomic_t panic_done_count = ATOMIC_INIT(0);
static void dummy_smi_done_handler(struct ipmi_smi_msg *msg) 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); ipmi_poll(intf);
} }
#ifdef CONFIG_IPMI_PANIC_STRING
static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg) static void event_receiver_fetcher(ipmi_smi_t intf, struct ipmi_recv_msg *msg)
{ {
if ((msg->addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE) 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; intf->local_event_generator = (msg->msg.data[6] >> 5) & 1;
} }
} }
#endif
static void send_panic_events(char *str) 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_system_interface_addr *si;
struct ipmi_addr addr; struct ipmi_addr addr;
if (ipmi_send_panic_event == IPMI_SEND_PANIC_EVENT_NONE)
return;
si = (struct ipmi_system_interface_addr *) &addr; si = (struct ipmi_system_interface_addr *) &addr;
si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
si->channel = IPMI_BMC_CHANNEL; si->channel = IPMI_BMC_CHANNEL;
@ -4385,20 +4453,19 @@ static void send_panic_events(char *str)
/* For every registered interface, send the event. */ /* For every registered interface, send the event. */
list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { list_for_each_entry_rcu(intf, &ipmi_interfaces, link) {
if (!intf->handlers) if (!intf->handlers || !intf->handlers->poll)
/* Interface is not ready. */ /* Interface is not ready or can't run at panic time. */
continue; continue;
/* Send the event announcing the panic. */ /* Send the event announcing the panic. */
ipmi_panic_request_and_wait(intf, &addr, &msg); ipmi_panic_request_and_wait(intf, &addr, &msg);
} }
#ifdef CONFIG_IPMI_PANIC_STRING
/* /*
* On every interface, dump a bunch of OEM event holding the * On every interface, dump a bunch of OEM event holding the
* string. * string.
*/ */
if (!str) if (ipmi_send_panic_event != IPMI_SEND_PANIC_EVENT_STRING || !str)
return; return;
/* For every registered interface, send the event. */ /* 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); ipmi_panic_request_and_wait(intf, &addr, &msg);
} }
} }
#endif /* CONFIG_IPMI_PANIC_STRING */
} }
#endif /* CONFIG_IPMI_PANIC_EVENT */
static int has_panicked; static int has_panicked;
@ -4547,12 +4612,12 @@ static int panic_event(struct notifier_block *this,
spin_unlock(&intf->waiting_rcv_msgs_lock); spin_unlock(&intf->waiting_rcv_msgs_lock);
intf->run_to_completion = 1; 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); send_panic_events(ptr);
#endif
return NOTIFY_DONE; return NOTIFY_DONE;
} }