From 9c48f1c629ecfa114850c03f875c6691003214de Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Fri, 30 Sep 2011 15:06:21 -0400 Subject: x86, nmi: Wire up NMI handlers to new routines Just convert all the files that have an nmi handler to the new routines. Most of it is straight forward conversion. A couple of places needed some tweaking like kgdb which separates the debug notifier from the nmi handler and mce removes a call to notify_die. [Thanks to Ying for finding out the history behind that mce call https://lkml.org/lkml/2010/5/27/114 And Boris responding that he would like to remove that call because of it https://lkml.org/lkml/2011/9/21/163] The things that get converted are the registeration/unregistration routines and the nmi handler itself has its args changed along with code removal to check which list it is on (most are on one NMI list except for kgdb which has both an NMI routine and an NMI Unknown routine). Signed-off-by: Don Zickus Signed-off-by: Peter Zijlstra Acked-by: Corey Minyard Cc: Jason Wessel Cc: Andi Kleen Cc: Robert Richter Cc: Huang Ying Cc: Corey Minyard Cc: Jack Steiner Link: http://lkml.kernel.org/r/1317409584-23662-4-git-send-email-dzickus@redhat.com Signed-off-by: Ingo Molnar --- drivers/acpi/apei/ghes.c | 22 ++++++++-------------- drivers/char/ipmi/ipmi_watchdog.c | 33 +++++++++++---------------------- drivers/watchdog/hpwdt.c | 24 ++++++------------------ 3 files changed, 25 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 0784f99a4665..b8e08cb67a18 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -50,6 +50,7 @@ #include #include #include +#include #include "apei-internal.h" @@ -749,15 +750,11 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) } } -static int ghes_notify_nmi(struct notifier_block *this, - unsigned long cmd, void *data) +static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs) { struct ghes *ghes, *ghes_global = NULL; int sev, sev_global = -1; - int ret = NOTIFY_DONE; - - if (cmd != DIE_NMI) - return ret; + int ret = NMI_DONE; raw_spin_lock(&ghes_nmi_lock); list_for_each_entry_rcu(ghes, &ghes_nmi, list) { @@ -770,10 +767,10 @@ static int ghes_notify_nmi(struct notifier_block *this, sev_global = sev; ghes_global = ghes; } - ret = NOTIFY_STOP; + ret = NMI_HANDLED; } - if (ret == NOTIFY_DONE) + if (ret == NMI_DONE) goto out; if (sev_global >= GHES_SEV_PANIC) { @@ -825,10 +822,6 @@ static struct notifier_block ghes_notifier_sci = { .notifier_call = ghes_notify_sci, }; -static struct notifier_block ghes_notifier_nmi = { - .notifier_call = ghes_notify_nmi, -}; - static unsigned long ghes_esource_prealloc_size( const struct acpi_hest_generic *generic) { @@ -918,7 +911,8 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev) ghes_estatus_pool_expand(len); mutex_lock(&ghes_list_mutex); if (list_empty(&ghes_nmi)) - register_die_notifier(&ghes_notifier_nmi); + register_nmi_handler(NMI_LOCAL, ghes_notify_nmi, 0, + "ghes"); list_add_rcu(&ghes->list, &ghes_nmi); mutex_unlock(&ghes_list_mutex); break; @@ -964,7 +958,7 @@ static int __devexit ghes_remove(struct platform_device *ghes_dev) mutex_lock(&ghes_list_mutex); list_del_rcu(&ghes->list); if (list_empty(&ghes_nmi)) - unregister_die_notifier(&ghes_notifier_nmi); + unregister_nmi_handler(NMI_LOCAL, "ghes"); mutex_unlock(&ghes_list_mutex); /* * To synchronize with NMI handler, ghes can only be diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 3302586655c4..c2917ffad2c2 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -65,6 +65,7 @@ * mechanism for it at that time. */ #include +#include #define HAVE_DIE_NMI #endif @@ -1077,17 +1078,8 @@ static void ipmi_unregister_watchdog(int ipmi_intf) #ifdef HAVE_DIE_NMI static int -ipmi_nmi(struct notifier_block *self, unsigned long val, void *data) +ipmi_nmi(unsigned int val, struct pt_regs *regs) { - struct die_args *args = data; - - if (val != DIE_NMIUNKNOWN) - return NOTIFY_OK; - - /* Hack, if it's a memory or I/O error, ignore it. */ - if (args->err & 0xc0) - return NOTIFY_OK; - /* * If we get here, it's an NMI that's not a memory or I/O * error. We can't truly tell if it's from IPMI or not @@ -1097,15 +1089,15 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data) if (testing_nmi) { testing_nmi = 2; - return NOTIFY_STOP; + return NMI_HANDLED; } /* If we are not expecting a timeout, ignore it. */ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) - return NOTIFY_OK; + return NMI_DONE; if (preaction_val != WDOG_PRETIMEOUT_NMI) - return NOTIFY_OK; + return NMI_DONE; /* * If no one else handled the NMI, we assume it was the IPMI @@ -1120,12 +1112,8 @@ ipmi_nmi(struct notifier_block *self, unsigned long val, void *data) panic(PFX "pre-timeout"); } - return NOTIFY_STOP; + return NMI_HANDLED; } - -static struct notifier_block ipmi_nmi_handler = { - .notifier_call = ipmi_nmi -}; #endif static int wdog_reboot_handler(struct notifier_block *this, @@ -1290,7 +1278,8 @@ static void check_parms(void) } } if (do_nmi && !nmi_handler_registered) { - rv = register_die_notifier(&ipmi_nmi_handler); + rv = register_nmi_handler(NMI_UNKNOWN, ipmi_nmi, 0, + "ipmi"); if (rv) { printk(KERN_WARNING PFX "Can't register nmi handler\n"); @@ -1298,7 +1287,7 @@ static void check_parms(void) } else nmi_handler_registered = 1; } else if (!do_nmi && nmi_handler_registered) { - unregister_die_notifier(&ipmi_nmi_handler); + unregister_nmi_handler(NMI_UNKNOWN, "ipmi"); nmi_handler_registered = 0; } #endif @@ -1336,7 +1325,7 @@ static int __init ipmi_wdog_init(void) if (rv) { #ifdef HAVE_DIE_NMI if (nmi_handler_registered) - unregister_die_notifier(&ipmi_nmi_handler); + unregister_nmi_handler(NMI_UNKNOWN, "ipmi"); #endif atomic_notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier); @@ -1357,7 +1346,7 @@ static void __exit ipmi_wdog_exit(void) #ifdef HAVE_DIE_NMI if (nmi_handler_registered) - unregister_die_notifier(&ipmi_nmi_handler); + unregister_nmi_handler(NMI_UNKNOWN, "ipmi"); #endif atomic_notifier_chain_unregister(&panic_notifier_list, diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 809cbda03d7a..7e7feac05221 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -477,15 +477,11 @@ static int hpwdt_time_left(void) /* * NMI Handler */ -static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, - void *data) +static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs) { unsigned long rom_pl; static int die_nmi_called; - if (ulReason != DIE_NMIUNKNOWN) - goto out; - if (!hpwdt_nmi_decoding) goto out; @@ -508,7 +504,7 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, "Management Log for details.\n"); out: - return NOTIFY_OK; + return NMI_DONE; } #endif /* CONFIG_HPWDT_NMI_DECODING */ @@ -648,13 +644,6 @@ static struct miscdevice hpwdt_miscdev = { .fops = &hpwdt_fops, }; -#ifdef CONFIG_HPWDT_NMI_DECODING -static struct notifier_block die_notifier = { - .notifier_call = hpwdt_pretimeout, - .priority = 0, -}; -#endif /* CONFIG_HPWDT_NMI_DECODING */ - /* * Init & Exit */ @@ -740,10 +729,9 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) * die notify list to handle a critical NMI. The default is to * be last so other users of the NMI signal can function. */ - if (priority) - die_notifier.priority = 0x7FFFFFFF; - - retval = register_die_notifier(&die_notifier); + retval = register_nmi_handler(NMI_UNKNOWN, hpwdt_pretimeout, + (priority) ? NMI_FLAG_FIRST : 0, + "hpwdt"); if (retval != 0) { dev_warn(&dev->dev, "Unable to register a die notifier (err=%d).\n", @@ -763,7 +751,7 @@ static int __devinit hpwdt_init_nmi_decoding(struct pci_dev *dev) static void hpwdt_exit_nmi_decoding(void) { - unregister_die_notifier(&die_notifier); + unregister_nmi_handler(NMI_UNKNOWN, "hpwdt"); if (cru_rom_addr) iounmap(cru_rom_addr); } -- cgit v1.2.3