summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Donnellan <andrew.donnellan@au1.ibm.com>2016-08-18 17:35:14 +1000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-10-16 17:50:36 +0200
commit3e08bc37a172aed688ddb45d0d5c54c65464a079 (patch)
tree519e455b16b3ec2908e35f991ba55c7d65c97847
parent83573addff2b4e16df9fad9a561a0d77d554b370 (diff)
downloadlinux-stable-3e08bc37a172aed688ddb45d0d5c54c65464a079.tar.gz
linux-stable-3e08bc37a172aed688ddb45d0d5c54c65464a079.tar.bz2
linux-stable-3e08bc37a172aed688ddb45d0d5c54c65464a079.zip
cxl: use pcibios_free_controller_deferred() when removing vPHBs
commit 6f38a8b9a45833495dc878c335c5431cd98a16ed upstream. When cxl removes a vPHB, it's possible that the pci_controller may be freed before all references to the devices on the vPHB have been released. This in turn causes an invalid memory access when the devices are eventually released, as pcibios_release_device() attempts to call the phb's release_device hook. In cxl_pci_vphb_remove(), remove the existing call to pcibios_free_controller(). Instead, use pcibios_free_controller_deferred() to free the pci_controller after all devices have been released. Export pci_set_host_bridge_release() so we can do this. Signed-off-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Reviewed-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Acked-by: Ian Munsie <imunsie@au1.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/misc/cxl/vphb.c10
-rw-r--r--drivers/pci/host-bridge.c1
2 files changed, 10 insertions, 1 deletions
diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c
index cdc7723b845d..bec6c2260a11 100644
--- a/drivers/misc/cxl/vphb.c
+++ b/drivers/misc/cxl/vphb.c
@@ -243,6 +243,11 @@ int cxl_pci_vphb_add(struct cxl_afu *afu)
if (phb->bus == NULL)
return -ENXIO;
+ /* Set release hook on root bus */
+ pci_set_host_bridge_release(to_pci_host_bridge(phb->bus->bridge),
+ pcibios_free_controller_deferred,
+ (void *) phb);
+
/* Claim resources. This might need some rework as well depending
* whether we are doing probe-only or not, like assigning unassigned
* resources etc...
@@ -269,7 +274,10 @@ void cxl_pci_vphb_remove(struct cxl_afu *afu)
afu->phb = NULL;
pci_remove_root_bus(phb->bus);
- pcibios_free_controller(phb);
+ /*
+ * We don't free phb here - that's handled by
+ * pcibios_free_controller_deferred()
+ */
}
bool cxl_pci_is_vphb_device(struct pci_dev *dev)
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 5f4a2e04c8d7..add66236215c 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -44,6 +44,7 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
bridge->release_fn = release_fn;
bridge->release_data = release_data;
}
+EXPORT_SYMBOL_GPL(pci_set_host_bridge_release);
void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,
struct resource *res)