powerpc/eeh: Rework eeh_ops->probe()
With the EEH early probe now being pseries specific there's no need for eeh_ops->probe() to take a pci_dn. Instead, we can make it take a pci_dev and use the probe function to map a pci_dev to an eeh_dev. This allows the platform to implement it's own method for finding (or creating) an eeh_dev for a given pci_dev which also removes a use of pci_dn in generic EEH code. This patch also renames eeh_device_add_late() to eeh_device_probe(). This better reflects what it does does and removes the last vestiges of the early/late EEH probe split. Reviewed-by: Sam Bobroff <sbobroff@linux.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20200306073904.4737-6-oohall@gmail.com
This commit is contained in:

committed by
Michael Ellerman

parent
b6eebb093c
commit
e86350f70a
@@ -1107,35 +1107,43 @@ static int eeh_init(void)
|
||||
core_initcall_sync(eeh_init);
|
||||
|
||||
/**
|
||||
* eeh_add_device_late - Perform EEH initialization for the indicated pci device
|
||||
* eeh_probe_device() - Perform EEH initialization for the indicated pci device
|
||||
* @dev: pci device for which to set up EEH
|
||||
*
|
||||
* This routine must be used to complete EEH initialization for PCI
|
||||
* devices that were added after system boot (e.g. hotplug, dlpar).
|
||||
*/
|
||||
void eeh_add_device_late(struct pci_dev *dev)
|
||||
void eeh_probe_device(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dn *pdn;
|
||||
struct eeh_dev *edev;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
pr_debug("EEH: Adding device %s\n", pci_name(dev));
|
||||
|
||||
pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn);
|
||||
edev = pdn_to_eeh_dev(pdn);
|
||||
eeh_edev_dbg(edev, "Adding device\n");
|
||||
if (edev->pdev == dev) {
|
||||
eeh_edev_dbg(edev, "Device already referenced!\n");
|
||||
/*
|
||||
* pci_dev_to_eeh_dev() can only work if eeh_probe_dev() was
|
||||
* already called for this device.
|
||||
*/
|
||||
if (WARN_ON_ONCE(pci_dev_to_eeh_dev(dev))) {
|
||||
pci_dbg(dev, "Already bound to an eeh_dev!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
edev = eeh_ops->probe(dev);
|
||||
if (!edev) {
|
||||
pr_debug("EEH: Adding device failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The EEH cache might not be removed correctly because of
|
||||
* unbalanced kref to the device during unplug time, which
|
||||
* relies on pcibios_release_device(). So we have to remove
|
||||
* that here explicitly.
|
||||
* FIXME: We rely on pcibios_release_device() to remove the
|
||||
* existing EEH state. The release function is only called if
|
||||
* the pci_dev's refcount drops to zero so if something is
|
||||
* keeping a ref to a device (e.g. a filesystem) we need to
|
||||
* remove the old EEH state.
|
||||
*
|
||||
* FIXME: HEY MA, LOOK AT ME, NO LOCKING!
|
||||
*/
|
||||
if (edev->pdev) {
|
||||
if (edev->pdev && edev->pdev != dev) {
|
||||
eeh_rmv_from_parent_pe(edev);
|
||||
eeh_addr_cache_rmv_dev(edev->pdev);
|
||||
eeh_sysfs_remove_device(edev->pdev);
|
||||
@@ -1146,17 +1154,11 @@ void eeh_add_device_late(struct pci_dev *dev)
|
||||
* into error handler afterwards.
|
||||
*/
|
||||
edev->mode |= EEH_DEV_NO_HANDLER;
|
||||
|
||||
edev->pdev = NULL;
|
||||
dev->dev.archdata.edev = NULL;
|
||||
}
|
||||
|
||||
if (eeh_has_flag(EEH_PROBE_MODE_DEV))
|
||||
eeh_ops->probe(pdn, NULL);
|
||||
|
||||
/* bind the pdev and the edev together */
|
||||
edev->pdev = dev;
|
||||
dev->dev.archdata.edev = edev;
|
||||
|
||||
eeh_addr_cache_insert_dev(dev);
|
||||
eeh_sysfs_add_device(dev);
|
||||
}
|
||||
|
Reference in New Issue
Block a user