aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGavin Shan <shangw@linux.vnet.ibm.com>2013-06-20 06:13:24 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-06-21 02:01:51 -0400
commit7cb9d93dc6d4f717218b6fa791be9bcf4e417379 (patch)
tree239427b8fb85d805d73ad5b2b3f5a17b9f74f611
parente8e71fa426d72914c500e98afa2076628076f511 (diff)
powerpc/eeh: Register OPAL notifier for PCI error
The patch registers OPAL event notifier and process the PCI errors from firmware. If we have pending PCI errors, special EEH event (without binding PE) will be sent to EEH core for processing. Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/platforms/powernv/eeh-ioda.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index a3eebd193dfe..2b7689ed5d18 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -18,6 +18,7 @@
18#include <linux/irq.h> 18#include <linux/irq.h>
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/msi.h> 20#include <linux/msi.h>
21#include <linux/notifier.h>
21#include <linux/pci.h> 22#include <linux/pci.h>
22#include <linux/string.h> 23#include <linux/string.h>
23 24
@@ -42,6 +43,26 @@
42#endif 43#endif
43 44
44static char *hub_diag = NULL; 45static char *hub_diag = NULL;
46static int ioda_eeh_nb_init = 0;
47
48static int ioda_eeh_event(struct notifier_block *nb,
49 unsigned long events, void *change)
50{
51 uint64_t changed_evts = (uint64_t)change;
52
53 /* We simply send special EEH event */
54 if ((changed_evts & OPAL_EVENT_PCI_ERROR) &&
55 (events & OPAL_EVENT_PCI_ERROR))
56 eeh_send_failure_event(NULL);
57
58 return 0;
59}
60
61static struct notifier_block ioda_eeh_nb = {
62 .notifier_call = ioda_eeh_event,
63 .next = NULL,
64 .priority = 0
65};
45 66
46/** 67/**
47 * ioda_eeh_post_init - Chip dependent post initialization 68 * ioda_eeh_post_init - Chip dependent post initialization
@@ -54,6 +75,19 @@ static char *hub_diag = NULL;
54static int ioda_eeh_post_init(struct pci_controller *hose) 75static int ioda_eeh_post_init(struct pci_controller *hose)
55{ 76{
56 struct pnv_phb *phb = hose->private_data; 77 struct pnv_phb *phb = hose->private_data;
78 int ret;
79
80 /* Register OPAL event notifier */
81 if (!ioda_eeh_nb_init) {
82 ret = opal_notifier_register(&ioda_eeh_nb);
83 if (ret) {
84 pr_err("%s: Can't register OPAL event notifier (%d)\n",
85 __func__, ret);
86 return ret;
87 }
88
89 ioda_eeh_nb_init = 1;
90 }
57 91
58 /* FIXME: Enable it for PHB3 later */ 92 /* FIXME: Enable it for PHB3 later */
59 if (phb->type == PNV_PHB_IODA1) { 93 if (phb->type == PNV_PHB_IODA1) {
@@ -736,8 +770,13 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
736 long rc; 770 long rc;
737 int ret = 1; 771 int ret = 1;
738 772
739 /* While running here, it's safe to purge the event queue */ 773 /*
774 * While running here, it's safe to purge the event queue.
775 * And we should keep the cached OPAL notifier event sychronized
776 * between the kernel and firmware.
777 */
740 eeh_remove_event(NULL); 778 eeh_remove_event(NULL);
779 opal_notifier_update_evt(OPAL_EVENT_PCI_ERROR, 0x0ul);
741 780
742 list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { 781 list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
743 /* 782 /*