s390/pci: fix [un]map_resources sequence
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Fri, 27 Feb 2015 15:43:21 +0000 (16:43 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 27 Feb 2015 16:50:04 +0000 (17:50 +0100)
Commit 8cfc99b58366 ("s390: add pci_iomap_range") introduced counters
to keep track of the number of mappings created. This revealed that
we don't have our internal mappings in order when using hotunplug or
resume from hibernate. This patch addresses both issues.

Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/pci/pci.c

index 753a567..6500d26 100644 (file)
@@ -483,9 +483,8 @@ void arch_teardown_msi_irqs(struct pci_dev *pdev)
        airq_iv_free_bit(zpci_aisb_iv, zdev->aisb);
 }
 
-static void zpci_map_resources(struct zpci_dev *zdev)
+static void zpci_map_resources(struct pci_dev *pdev)
 {
-       struct pci_dev *pdev = zdev->pdev;
        resource_size_t len;
        int i;
 
@@ -499,9 +498,8 @@ static void zpci_map_resources(struct zpci_dev *zdev)
        }
 }
 
-static void zpci_unmap_resources(struct zpci_dev *zdev)
+static void zpci_unmap_resources(struct pci_dev *pdev)
 {
-       struct pci_dev *pdev = zdev->pdev;
        resource_size_t len;
        int i;
 
@@ -651,7 +649,7 @@ int pcibios_add_device(struct pci_dev *pdev)
 
        zdev->pdev = pdev;
        pdev->dev.groups = zpci_attr_groups;
-       zpci_map_resources(zdev);
+       zpci_map_resources(pdev);
 
        for (i = 0; i < PCI_BAR_COUNT; i++) {
                res = &pdev->resource[i];
@@ -663,6 +661,11 @@ int pcibios_add_device(struct pci_dev *pdev)
        return 0;
 }
 
+void pcibios_release_device(struct pci_dev *pdev)
+{
+       zpci_unmap_resources(pdev);
+}
+
 int pcibios_enable_device(struct pci_dev *pdev, int mask)
 {
        struct zpci_dev *zdev = get_zdev(pdev);
@@ -670,7 +673,6 @@ int pcibios_enable_device(struct pci_dev *pdev, int mask)
        zdev->pdev = pdev;
        zpci_debug_init_device(zdev);
        zpci_fmb_enable_device(zdev);
-       zpci_map_resources(zdev);
 
        return pci_enable_resources(pdev, mask);
 }
@@ -679,7 +681,6 @@ void pcibios_disable_device(struct pci_dev *pdev)
 {
        struct zpci_dev *zdev = get_zdev(pdev);
 
-       zpci_unmap_resources(zdev);
        zpci_fmb_disable_device(zdev);
        zpci_debug_exit_device(zdev);
        zdev->pdev = NULL;
@@ -688,7 +689,8 @@ void pcibios_disable_device(struct pci_dev *pdev)
 #ifdef CONFIG_HIBERNATE_CALLBACKS
 static int zpci_restore(struct device *dev)
 {
-       struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct zpci_dev *zdev = get_zdev(pdev);
        int ret = 0;
 
        if (zdev->state != ZPCI_FN_STATE_ONLINE)
@@ -698,7 +700,7 @@ static int zpci_restore(struct device *dev)
        if (ret)
                goto out;
 
-       zpci_map_resources(zdev);
+       zpci_map_resources(pdev);
        zpci_register_ioat(zdev, 0, zdev->start_dma + PAGE_OFFSET,
                           zdev->start_dma + zdev->iommu_size - 1,
                           (u64) zdev->dma_table);
@@ -709,12 +711,14 @@ out:
 
 static int zpci_freeze(struct device *dev)
 {
-       struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
+       struct pci_dev *pdev = to_pci_dev(dev);
+       struct zpci_dev *zdev = get_zdev(pdev);
 
        if (zdev->state != ZPCI_FN_STATE_ONLINE)
                return 0;
 
        zpci_unregister_ioat(zdev, 0);
+       zpci_unmap_resources(pdev);
        return clp_disable_fh(zdev);
 }