Commit d125aedb authored by Oliver O'Halloran's avatar Oliver O'Halloran Committed by Michael Ellerman

powerpc/eeh: Rework EEH initialisation

Drop the EEH register / unregister ops thing and have the platform pass the
ops structure into eeh_init() directly. This takes one initcall out of the
EEH setup path and it means we're only doing EEH setup on the platforms
which actually support it. It's also less code and generally easier to
follow.

No functional changes.
Signed-off-by: default avatarOliver O'Halloran <oohall@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200918093050.37344-1-oohall@gmail.com
parent 874dc62f
...@@ -295,8 +295,7 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe); ...@@ -295,8 +295,7 @@ const char *eeh_pe_loc_get(struct eeh_pe *pe);
struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe);
void eeh_show_enabled(void); void eeh_show_enabled(void);
int __init eeh_ops_register(struct eeh_ops *ops); int __init eeh_init(struct eeh_ops *ops);
int __exit eeh_ops_unregister(const char *name);
int eeh_check_failure(const volatile void __iomem *token); int eeh_check_failure(const volatile void __iomem *token);
int eeh_dev_check_failure(struct eeh_dev *edev); int eeh_dev_check_failure(struct eeh_dev *edev);
void eeh_addr_cache_init(void); void eeh_addr_cache_init(void);
......
...@@ -929,56 +929,6 @@ void eeh_save_bars(struct eeh_dev *edev) ...@@ -929,56 +929,6 @@ void eeh_save_bars(struct eeh_dev *edev)
edev->config_space[1] |= PCI_COMMAND_MASTER; edev->config_space[1] |= PCI_COMMAND_MASTER;
} }
/**
* eeh_ops_register - Register platform dependent EEH operations
* @ops: platform dependent EEH operations
*
* Register the platform dependent EEH operation callback
* functions. The platform should call this function before
* any other EEH operations.
*/
int __init eeh_ops_register(struct eeh_ops *ops)
{
if (!ops->name) {
pr_warn("%s: Invalid EEH ops name for %p\n",
__func__, ops);
return -EINVAL;
}
if (eeh_ops && eeh_ops != ops) {
pr_warn("%s: EEH ops of platform %s already existing (%s)\n",
__func__, eeh_ops->name, ops->name);
return -EEXIST;
}
eeh_ops = ops;
return 0;
}
/**
* eeh_ops_unregister - Unreigster platform dependent EEH operations
* @name: name of EEH platform operations
*
* Unregister the platform dependent EEH operation callback
* functions.
*/
int __exit eeh_ops_unregister(const char *name)
{
if (!name || !strlen(name)) {
pr_warn("%s: Invalid EEH ops name\n",
__func__);
return -EINVAL;
}
if (eeh_ops && !strcmp(eeh_ops->name, name)) {
eeh_ops = NULL;
return 0;
}
return -EEXIST;
}
static int eeh_reboot_notifier(struct notifier_block *nb, static int eeh_reboot_notifier(struct notifier_block *nb,
unsigned long action, void *unused) unsigned long action, void *unused)
{ {
...@@ -991,25 +941,22 @@ static struct notifier_block eeh_reboot_nb = { ...@@ -991,25 +941,22 @@ static struct notifier_block eeh_reboot_nb = {
}; };
/** /**
* eeh_init - EEH initialization * eeh_init - System wide EEH initialization
*
* Initialize EEH by trying to enable it for all of the adapters in the system.
* As a side effect we can determine here if eeh is supported at all.
* Note that we leave EEH on so failed config cycles won't cause a machine
* check. If a user turns off EEH for a particular adapter they are really
* telling Linux to ignore errors. Some hardware (e.g. POWER5) won't
* grant access to a slot if EEH isn't enabled, and so we always enable
* EEH for all slots/all devices.
* *
* The eeh-force-off option disables EEH checking globally, for all slots. * It's the platform's job to call this from an arch_initcall().
* Even if force-off is set, the EEH hardware is still enabled, so that
* newer systems can boot.
*/ */
static int eeh_init(void) int eeh_init(struct eeh_ops *ops)
{ {
struct pci_controller *hose, *tmp; struct pci_controller *hose, *tmp;
int ret = 0; int ret = 0;
/* the platform should only initialise EEH once */
if (WARN_ON(eeh_ops))
return -EEXIST;
if (WARN_ON(!ops))
return -ENOENT;
eeh_ops = ops;
/* Register reboot notifier */ /* Register reboot notifier */
ret = register_reboot_notifier(&eeh_reboot_nb); ret = register_reboot_notifier(&eeh_reboot_nb);
if (ret) { if (ret) {
...@@ -1018,13 +965,13 @@ static int eeh_init(void) ...@@ -1018,13 +965,13 @@ static int eeh_init(void)
return ret; return ret;
} }
/* call platform initialization function */ if (eeh_ops->init)
if (!eeh_ops) { ret = eeh_ops->init();
pr_warn("%s: Platform EEH operation not found\n", if (ret) {
__func__); pr_warn("%s: platform EEH init failed (%d)\n",
return -EEXIST; __func__, ret);
} else if ((ret = eeh_ops->init()))
return ret; return ret;
}
/* Initialize PHB PEs */ /* Initialize PHB PEs */
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
...@@ -1036,8 +983,6 @@ static int eeh_init(void) ...@@ -1036,8 +983,6 @@ static int eeh_init(void)
return eeh_event_init(); return eeh_event_init();
} }
core_initcall_sync(eeh_init);
static int eeh_device_notifier(struct notifier_block *nb, static int eeh_device_notifier(struct notifier_block *nb,
unsigned long action, void *data) unsigned long action, void *data)
{ {
......
...@@ -1717,7 +1717,7 @@ static int __init eeh_powernv_init(void) ...@@ -1717,7 +1717,7 @@ static int __init eeh_powernv_init(void)
{ {
int ret = -EINVAL; int ret = -EINVAL;
ret = eeh_ops_register(&pnv_eeh_ops); ret = eeh_init(&pnv_eeh_ops);
if (!ret) if (!ret)
pr_info("EEH: PowerNV platform initialized\n"); pr_info("EEH: PowerNV platform initialized\n");
else else
...@@ -1725,4 +1725,4 @@ static int __init eeh_powernv_init(void) ...@@ -1725,4 +1725,4 @@ static int __init eeh_powernv_init(void)
return ret; return ret;
} }
machine_early_initcall(powernv, eeh_powernv_init); machine_core_initcall_sync(powernv, eeh_powernv_init);
...@@ -990,13 +990,12 @@ static int __init eeh_pseries_init(void) ...@@ -990,13 +990,12 @@ static int __init eeh_pseries_init(void)
{ {
int ret; int ret;
ret = eeh_ops_register(&pseries_eeh_ops); ret = eeh_init(&pseries_eeh_ops);
if (!ret) if (!ret)
pr_info("EEH: pSeries platform initialized\n"); pr_info("EEH: pSeries platform initialized\n");
else else
pr_info("EEH: pSeries platform initialization failure (%d)\n", pr_info("EEH: pSeries platform initialization failure (%d)\n",
ret); ret);
return ret; return ret;
} }
machine_early_initcall(pseries, eeh_pseries_init); machine_core_initcall_sync(pseries, eeh_pseries_init);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment