diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index a3eebd193dfe085f3e880b936f28577b3667f4b4..2b7689ed5d1875b75b912ce298e88881059fd2eb 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,26 @@ #endif static char *hub_diag = NULL; +static int ioda_eeh_nb_init = 0; + +static int ioda_eeh_event(struct notifier_block *nb, + unsigned long events, void *change) +{ + uint64_t changed_evts = (uint64_t)change; + + /* We simply send special EEH event */ + if ((changed_evts & OPAL_EVENT_PCI_ERROR) && + (events & OPAL_EVENT_PCI_ERROR)) + eeh_send_failure_event(NULL); + + return 0; +} + +static struct notifier_block ioda_eeh_nb = { + .notifier_call = ioda_eeh_event, + .next = NULL, + .priority = 0 +}; /** * ioda_eeh_post_init - Chip dependent post initialization @@ -54,6 +75,19 @@ static char *hub_diag = NULL; static int ioda_eeh_post_init(struct pci_controller *hose) { struct pnv_phb *phb = hose->private_data; + int ret; + + /* Register OPAL event notifier */ + if (!ioda_eeh_nb_init) { + ret = opal_notifier_register(&ioda_eeh_nb); + if (ret) { + pr_err("%s: Can't register OPAL event notifier (%d)\n", + __func__, ret); + return ret; + } + + ioda_eeh_nb_init = 1; + } /* FIXME: Enable it for PHB3 later */ if (phb->type == PNV_PHB_IODA1) { @@ -736,8 +770,13 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) long rc; int ret = 1; - /* While running here, it's safe to purge the event queue */ + /* + * While running here, it's safe to purge the event queue. + * And we should keep the cached OPAL notifier event sychronized + * between the kernel and firmware. + */ eeh_remove_event(NULL); + opal_notifier_update_evt(OPAL_EVENT_PCI_ERROR, 0x0ul); list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { /*