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);
struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe);
void eeh_show_enabled(void);
int __init eeh_ops_register(struct eeh_ops *ops);
int __exit eeh_ops_unregister(const char *name);
int __init eeh_init(struct eeh_ops *ops);
int eeh_check_failure(const volatile void __iomem *token);
int eeh_dev_check_failure(struct eeh_dev *edev);
void eeh_addr_cache_init(void);
......
......@@ -929,56 +929,6 @@ void eeh_save_bars(struct eeh_dev *edev)
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,
unsigned long action, void *unused)
{
......@@ -991,25 +941,22 @@ static struct notifier_block eeh_reboot_nb = {
};
/**
* eeh_init - 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.
* eeh_init - System wide EEH initialization
*
* The eeh-force-off option disables EEH checking globally, for all slots.
* Even if force-off is set, the EEH hardware is still enabled, so that
* newer systems can boot.
* It's the platform's job to call this from an arch_initcall().
*/
static int eeh_init(void)
int eeh_init(struct eeh_ops *ops)
{
struct pci_controller *hose, *tmp;
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 */
ret = register_reboot_notifier(&eeh_reboot_nb);
if (ret) {
......@@ -1018,13 +965,13 @@ static int eeh_init(void)
return ret;
}
/* call platform initialization function */
if (!eeh_ops) {
pr_warn("%s: Platform EEH operation not found\n",
__func__);
return -EEXIST;
} else if ((ret = eeh_ops->init()))
if (eeh_ops->init)
ret = eeh_ops->init();
if (ret) {
pr_warn("%s: platform EEH init failed (%d)\n",
__func__, ret);
return ret;
}
/* Initialize PHB PEs */
list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
......@@ -1036,8 +983,6 @@ static int eeh_init(void)
return eeh_event_init();
}
core_initcall_sync(eeh_init);
static int eeh_device_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
......
......@@ -1717,7 +1717,7 @@ static int __init eeh_powernv_init(void)
{
int ret = -EINVAL;
ret = eeh_ops_register(&pnv_eeh_ops);
ret = eeh_init(&pnv_eeh_ops);
if (!ret)
pr_info("EEH: PowerNV platform initialized\n");
else
......@@ -1725,4 +1725,4 @@ static int __init eeh_powernv_init(void)
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)
{
int ret;
ret = eeh_ops_register(&pseries_eeh_ops);
ret = eeh_init(&pseries_eeh_ops);
if (!ret)
pr_info("EEH: pSeries platform initialized\n");
else
pr_info("EEH: pSeries platform initialization failure (%d)\n",
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