diff options
author | Gavin Shan <shangw@linux.vnet.ibm.com> | 2014-03-05 10:51:02 +0800 |
---|---|---|
committer | Eli Qiao <taget@linux.vnet.ibm.com> | 2014-03-05 10:56:34 +0800 |
commit | 35c294c8cedb1ad99c49994d23b1814a3b4ec536 (patch) | |
tree | 78ebd651000c90a6314ba5ca884ebd42bf48433f | |
parent | 27778ff64de44b24732a24f490ab5b4a0aa164d8 (diff) | |
download | powerkvm-35c294c8cedb1ad99c49994d23b1814a3b4ec536.tar.gz |
powerpc/eeh: Disable EEH on reboot
We possiblly detect EEH errors during reboot, particularly in kexec
path, but it's impossible for device drivers and EEH core to handle
or recover them properly.
The patch registers one reboot notifier for EEH and disable EEH
subsystem during reboot. That means the EEH errors is going to be
cleared by hardware reset or second kernel during early stage of
PCI probe.
It's backporting commit 66f9af83e56bfa12964d251df9d60fb571579913
("powerpc/eeh: Disable EEH on reboot") from 3.14 upstream for
bug#103590
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/kernel/eeh.c | 20 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/eeh-ioda.c | 3 |
2 files changed, 22 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 2e36a012cf638..8c4733592cff9 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -28,6 +28,7 @@ #include <linux/pci.h> #include <linux/proc_fs.h> #include <linux/rbtree.h> +#include <linux/reboot.h> #include <linux/seq_file.h> #include <linux/spinlock.h> #include <linux/export.h> @@ -740,6 +741,17 @@ int __exit eeh_ops_unregister(const char *name) return -EEXIST; } +static int eeh_reboot_notifier(struct notifier_block *nb, + unsigned long action, void *unused) +{ + eeh_set_enable(false); + return NOTIFY_DONE; +} + +static struct notifier_block eeh_reboot_nb = { + .notifier_call = eeh_reboot_notifier, +}; + /** * eeh_init - EEH initialization * @@ -771,6 +783,14 @@ int eeh_init(void) if (machine_is(powernv) && cnt++ <= 0) return ret; + /* Register reboot notifier */ + ret = register_reboot_notifier(&eeh_reboot_nb); + if (ret) { + pr_warn("%s: Failed to register notifier (%d)\n", + __func__, ret); + return ret; + } + /* call platform initialization function */ if (!eeh_ops) { pr_warning("%s: Platform EEH operation not found\n", diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index aa14cb4302515..5660c549bf600 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c @@ -45,7 +45,8 @@ static int ioda_eeh_event(struct notifier_block *nb, /* We simply send special EEH event */ if ((changed_evts & OPAL_EVENT_PCI_ERROR) && - (events & OPAL_EVENT_PCI_ERROR)) + (events & OPAL_EVENT_PCI_ERROR) && + eeh_enabled()) eeh_send_failure_event(NULL); return 0; |