summaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
authorSebastian Ott2016-01-29 15:13:30 +0100
committerMartin Schwidefsky2016-02-23 08:56:16 +0100
commit9a99649f2a89fdfc9dde5d5401675561567bf99a (patch)
treeb15f95ac2c6a81c3dd85b4ab815406c164979d5f /drivers/pci/hotplug
parents390/fpu: signals vs. floating point control register (diff)
downloadkernel-qcow2-linux-9a99649f2a89fdfc9dde5d5401675561567bf99a.tar.gz
kernel-qcow2-linux-9a99649f2a89fdfc9dde5d5401675561567bf99a.tar.xz
kernel-qcow2-linux-9a99649f2a89fdfc9dde5d5401675561567bf99a.zip
s390/pci: remove pdev pointer from arch data
For each PCI function we need to maintain arch specific data in struct zpci_dev which also contains a pointer to struct pci_dev. When a function is registered or deregistered (which is triggered by PCI common code) we need to adjust that pointer which could interfere with the machine check handler (triggered by FW) using zpci_dev->pdev. Since multiple instances of the same pdev could exist at a time this can't be solved with locking. Fix that by ditching the pdev pointer and use a bus walk to reach struct pci_dev (only one instance of a pdev can be registered at the bus at a time). Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/s390_pci_hpc.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c
index eb5efaef06ea..50b8b7d54416 100644
--- a/drivers/pci/hotplug/s390_pci_hpc.c
+++ b/drivers/pci/hotplug/s390_pci_hpc.c
@@ -93,13 +93,17 @@ out_deconfigure:
static int disable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
+ struct pci_dev *pdev;
int rc;
if (!zpci_fn_configured(slot->zdev->state))
return -EIO;
- if (slot->zdev->pdev)
- pci_stop_and_remove_bus_device_locked(slot->zdev->pdev);
+ pdev = pci_get_slot(slot->zdev->bus, ZPCI_DEVFN);
+ if (pdev) {
+ pci_stop_and_remove_bus_device_locked(pdev);
+ pci_dev_put(pdev);
+ }
rc = zpci_disable_device(slot->zdev);
if (rc)