> Implement a console driver to log messages to SEL when > oops_in_progress is > not zero. The message is logging as OEM event without timestamp.
Why without timestamp? Sometimes time information is significant in a crash. If you log with timestamps, and at least one of the oops texts also prints a timestamp, you're taking a spot measure of the time skew between the BMC and host -- a potentially valuable bit of information. >Bela< > -----Original Message----- > From: Hiroshi Shimamoto [mailto:[email protected]] > Sent: Monday, December 15, 2008 2:15 PM > To: [email protected] > Cc: Bela Lubkin; Corey Minyard > Subject: [RFC v2] ipmi: introduce oops_console > > From: Hiroshi Shimamoto <[email protected]> > > Console messages on oops or panic are very important to > investigate problem. > Logging oops or panic messages to SEL is useful because SEL is a non > volatile memory. > > Implement a console driver to log messages to SEL when > oops_in_progress is > not zero. The message is logging as OEM event without timestamp. > > Enable config IPMI_OOPS_CONSOLE and add console=ttyIPMI to > kernel command > line to log panic or oops messages to IPMI SEL. > > The number of entries for this output is limited by msg_limit > paramter, > and the default value is 100. > > Signed-off-by: Hiroshi Shimamoto <[email protected]> > --- > v1 -> v2: Add msg_limit to limit output size. > > drivers/char/ipmi/Kconfig | 7 + > drivers/char/ipmi/Makefile | 1 + > drivers/char/ipmi/ipmi_oops_console.c | 228 > +++++++++++++++++++++++++++++++++ > 3 files changed, 236 insertions(+), 0 deletions(-) > create mode 100644 drivers/char/ipmi/ipmi_oops_console.c > > diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig > index 0baa8fa..4bca2b3 100644 > --- a/drivers/char/ipmi/Kconfig > +++ b/drivers/char/ipmi/Kconfig > @@ -61,4 +61,11 @@ config IPMI_POWEROFF > This enables a function to power off the system with IPMI if > the IPMI management controller is capable of this. > > +config IPMI_OOPS_CONSOLE > + tristate 'IPMI oops console' > + help > + This enables the IPMI oops console. IPMI oops console > logs oops or > + panic console messsages to SEL. The number of entries > for this usage > + is limited by msg_limit, default is 100 entries. > + > endif # IPMI_HANDLER > diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile > index eb8a1a8..cbbac18 100644 > --- a/drivers/char/ipmi/Makefile > +++ b/drivers/char/ipmi/Makefile > @@ -9,3 +9,4 @@ obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o > obj-$(CONFIG_IPMI_SI) += ipmi_si.o > obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o > obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o > +obj-$(CONFIG_IPMI_OOPS_CONSOLE) += ipmi_oops_console.o > diff --git a/drivers/char/ipmi/ipmi_oops_console.c > b/drivers/char/ipmi/ipmi_oops_console.c > new file mode 100644 > index 0000000..b42de33 > --- /dev/null > +++ b/drivers/char/ipmi/ipmi_oops_console.c > @@ -0,0 +1,228 @@ > +/* > + * ipmi_oops_console.c > + * > + * IPMI Oops Console > + * Logging console message to SEL on oops > + * > + * Author: Hiroshi Shimamoto <[email protected]> > + * > + * Copyright (C) 2008 NEC Corporation > + * > + * This program is free software; you can redistribute it > and/or modify it > + * under the terms of the GNU General Public License as > published by the > + * Free Software Foundation; either version 2 of the > License, or (at your > + * option) any later version. > + * > + * > + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED > + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED > WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > DISCLAIMED. > + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES > (INCLUDING, > + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > SERVICES; LOSS > + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > HOWEVER CAUSED AND > + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > LIABILITY, OR > + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY > WAY OUT OF THE > + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY > OF SUCH DAMAGE. > + * > + * You should have received a copy of the GNU General > Public License along > + * with this program; if not, write to the Free Software > Foundation, Inc., > + * 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > + > +#include <linux/module.h> > +#include <linux/moduleparam.h> > +#include <linux/ipmi.h> > +#include <linux/ipmi_smi.h> > +#include <linux/console.h> > +#include <asm/atomic.h> > + > +#define PFX "IPMI oops_console: " > + > +static ipmi_user_t oops_user; > +static int oops_intf = -1; > + > +static atomic_t oops_counter; > + > +#define OOPS_MSGSIZE (13U) > +#define DEF_LIMIT (100) > + > +static char oops_msg[OOPS_MSGSIZE]; > +static int msg_len, msg_total; > +static int msg_limit = DEF_LIMIT; > + > +module_param(msg_limit, int, 0644); > +MODULE_PARM_DESC(msg_limit, "Message limit. Default: 100 entries."); > + > +static void oops_smi_msg_done(struct ipmi_smi_msg *msg) > +{ > + atomic_dec(&oops_counter); > +} > +static struct ipmi_smi_msg oops_smi_msg = { > + .done = oops_smi_msg_done > +}; > + > +static void oops_recv_msg_done(struct ipmi_recv_msg *msg) > +{ > + atomic_dec(&oops_counter); > +} > +static struct ipmi_recv_msg oops_recv_msg = { > + .done = oops_recv_msg_done > +}; > + > +static void ipmi_oops_console_sync(void) > +{ > + unsigned int len = msg_len; > + struct ipmi_system_interface_addr si; > + struct kernel_ipmi_msg msg; > + unsigned char data[16]; > + unsigned char my_addr; > + > + if (!oops_user || len == 0) > + return; > + > + msg_len = 0; > + > + si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; > + si.channel = IPMI_BMC_CHANNEL; > + si.lun = 0; > + > + msg.netfn = IPMI_NETFN_STORAGE_REQUEST; > + msg.cmd = IPMI_ADD_SEL_ENTRY_CMD; > + msg.data = data; > + msg.data_len = 16; > + > + memset(data, 0, sizeof(data)); > + data[2] = 0xf1; /* OEM event without timestamp */ > + memcpy(data + 3, oops_msg, len); > + > + preempt_disable(); > + > + if (ipmi_get_my_address(oops_user, 0, &my_addr)) > + goto out; > + > + atomic_set(&oops_counter, 2); > + if (ipmi_request_supply_msgs(oops_user, (struct ipmi_addr *)&si, > + 0, &msg, NULL, &oops_smi_msg, > + &oops_recv_msg, 1) < 0) > + goto out; > + while (atomic_read(&oops_counter) > 0) { > + ipmi_poll_interface(oops_user); > + cpu_relax(); > + } > +out: > + preempt_enable(); > +} > + > +static void > +ipmi_oops_console_write(struct console *con, const char *s, > unsigned int count) > +{ > + unsigned int size; > + unsigned int limit; > + > + if (likely(!oops_in_progress)) { > + ipmi_oops_console_sync(); > + return; > + } > + > + if (unlikely(!oops_user)) > + return; > + > + limit = msg_limit * OOPS_MSGSIZE; > + while (count > 0 && msg_total < limit) { > + size = min(OOPS_MSGSIZE - msg_len, count); > + memcpy(oops_msg + msg_len, s, size); > + msg_len += size; > + s += size; > + if (msg_len >= OOPS_MSGSIZE) > + ipmi_oops_console_sync(); > + > + count -= size; > + msg_total += size; > + } > +} > + > +static struct console oops_console = { > + .name = "ttyIPMI", > + .write = ipmi_oops_console_write, > + .unblank = ipmi_oops_console_sync, > + .index = -1, > +}; > + > +static void ipmi_oops_recv(struct ipmi_recv_msg *msg, void *data) > +{ > + ipmi_free_recv_msg(msg); > +} > + > +static struct ipmi_user_hndl ipmi_handler = { > + .ipmi_recv_hndl = ipmi_oops_recv, > +}; > + > +static void ipmi_register_oops_console(int intf) > +{ > + int ret; > + > + ret = ipmi_create_user(intf, &ipmi_handler, NULL, &oops_user); > + if (ret < 0) { > + printk(KERN_ERR PFX "unable to create user\n"); > + return; > + } > + > + oops_intf = intf; > + > + register_console(&oops_console); > + > + printk(KERN_INFO PFX "ready\n"); > +} > + > +static void ipmi_unregister_oops_console(int intf) > +{ > + unregister_console(&oops_console); > + > + ipmi_destroy_user(oops_user); > + oops_user = NULL; > + oops_intf = -1; > +} > + > +static void ipmi_new_smi(int if_num, struct device *dev) > +{ > + ipmi_register_oops_console(if_num); > +} > + > +static void ipmi_smi_gone(int if_num) > +{ > + ipmi_unregister_oops_console(if_num); > +} > + > +static struct ipmi_smi_watcher smi_watcher = { > + .owner = THIS_MODULE, > + .new_smi = ipmi_new_smi, > + .smi_gone = ipmi_smi_gone, > +}; > + > +static int __init ipmi_oops_console_init(void) > +{ > + int ret; > + > + ret = ipmi_smi_watcher_register(&smi_watcher); > + if (ret) { > + printk(KERN_ERR PFX "unable to register smi watcher\n"); > + return ret; > + } > + > + printk(KERN_INFO PFX "driver initialized\n"); > + > + return ret; > +} > +module_init(ipmi_oops_console_init); > + > +static void __exit ipmi_oops_console_exit(void) > +{ > + if (oops_intf >= 0) > + ipmi_unregister_oops_console(oops_intf); > +} > +module_exit(ipmi_oops_console_exit); > + > +MODULE_LICENSE("GPL"); > +MODULE_AUTHOR("Hiroshi Shimamoto <[email protected]>"); > +MODULE_DESCRIPTION("oops console handler based upon the IPMI > interface."); > -- > 1.6.0.4 > > ------------------------------------------------------------------------------ SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada. The future of the web can't happen without you. Join us at MIX09 to help pave the way to the Next Web now. Learn more and register at http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/ _______________________________________________ Openipmi-developer mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openipmi-developer
