Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sebastian Ott and committed by
Martin Schwidefsky
9a99649f 1b17cb79

+33 -23
+1 -2
arch/s390/include/asm/pci.h
··· 66 66 67 67 /* Private data per function */ 68 68 struct zpci_dev { 69 - struct pci_dev *pdev; 70 69 struct pci_bus *bus; 71 70 struct list_head entry; /* list of all zpci_devices, needed for hotplug, etc. */ 72 71 ··· 191 192 /* Debug */ 192 193 int zpci_debug_init(void); 193 194 void zpci_debug_exit(void); 194 - void zpci_debug_init_device(struct zpci_dev *); 195 + void zpci_debug_init_device(struct zpci_dev *, const char *); 195 196 void zpci_debug_exit_device(struct zpci_dev *); 196 197 void zpci_debug_info(struct zpci_dev *, struct seq_file *); 197 198
+1 -5
arch/s390/pci/pci.c
··· 637 637 638 638 int pcibios_add_device(struct pci_dev *pdev) 639 639 { 640 - struct zpci_dev *zdev = to_zpci(pdev); 641 640 struct resource *res; 642 641 int i; 643 642 644 - zdev->pdev = pdev; 645 643 pdev->dev.groups = zpci_attr_groups; 646 644 zpci_map_resources(pdev); 647 645 ··· 662 664 { 663 665 struct zpci_dev *zdev = to_zpci(pdev); 664 666 665 - zdev->pdev = pdev; 666 - zpci_debug_init_device(zdev); 667 + zpci_debug_init_device(zdev, dev_name(&pdev->dev)); 667 668 zpci_fmb_enable_device(zdev); 668 669 669 670 return pci_enable_resources(pdev, mask); ··· 674 677 675 678 zpci_fmb_disable_device(zdev); 676 679 zpci_debug_exit_device(zdev); 677 - zdev->pdev = NULL; 678 680 } 679 681 680 682 #ifdef CONFIG_HIBERNATE_CALLBACKS
+2 -3
arch/s390/pci/pci_debug.c
··· 128 128 .release = single_release, 129 129 }; 130 130 131 - void zpci_debug_init_device(struct zpci_dev *zdev) 131 + void zpci_debug_init_device(struct zpci_dev *zdev, const char *name) 132 132 { 133 - zdev->debugfs_dev = debugfs_create_dir(dev_name(&zdev->pdev->dev), 134 - debugfs_root); 133 + zdev->debugfs_dev = debugfs_create_dir(name, debugfs_root); 135 134 if (IS_ERR(zdev->debugfs_dev)) 136 135 zdev->debugfs_dev = NULL; 137 136
+12 -9
arch/s390/pci/pci_dma.c
··· 217 217 dma_free_cpu_table(table); 218 218 } 219 219 220 - static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev, 220 + static unsigned long __dma_alloc_iommu(struct device *dev, 221 221 unsigned long start, int size) 222 222 { 223 + struct zpci_dev *zdev = to_zpci(to_pci_dev(dev)); 223 224 unsigned long boundary_size; 224 225 225 - boundary_size = ALIGN(dma_get_seg_boundary(&zdev->pdev->dev) + 1, 226 + boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, 226 227 PAGE_SIZE) >> PAGE_SHIFT; 227 228 return iommu_area_alloc(zdev->iommu_bitmap, zdev->iommu_pages, 228 229 start, size, 0, boundary_size, 0); 229 230 } 230 231 231 - static unsigned long dma_alloc_iommu(struct zpci_dev *zdev, int size) 232 + static unsigned long dma_alloc_iommu(struct device *dev, int size) 232 233 { 234 + struct zpci_dev *zdev = to_zpci(to_pci_dev(dev)); 233 235 unsigned long offset, flags; 234 236 int wrap = 0; 235 237 236 238 spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags); 237 - offset = __dma_alloc_iommu(zdev, zdev->next_bit, size); 239 + offset = __dma_alloc_iommu(dev, zdev->next_bit, size); 238 240 if (offset == -1) { 239 241 /* wrap-around */ 240 - offset = __dma_alloc_iommu(zdev, 0, size); 242 + offset = __dma_alloc_iommu(dev, 0, size); 241 243 wrap = 1; 242 244 } 243 245 ··· 253 251 return offset; 254 252 } 255 253 256 - static void dma_free_iommu(struct zpci_dev *zdev, unsigned long offset, int size) 254 + static void dma_free_iommu(struct device *dev, unsigned long offset, int size) 257 255 { 256 + struct zpci_dev *zdev = to_zpci(to_pci_dev(dev)); 258 257 unsigned long flags; 259 258 260 259 spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags); ··· 296 293 297 294 /* This rounds up number of pages based on size and offset */ 298 295 nr_pages = iommu_num_pages(pa, size, PAGE_SIZE); 299 - iommu_page_index = dma_alloc_iommu(zdev, nr_pages); 296 + iommu_page_index = dma_alloc_iommu(dev, nr_pages); 300 297 if (iommu_page_index == -1) { 301 298 ret = -ENOSPC; 302 299 goto out_err; ··· 322 319 return dma_addr + (offset & ~PAGE_MASK); 323 320 324 321 out_free: 325 - dma_free_iommu(zdev, iommu_page_index, nr_pages); 322 + dma_free_iommu(dev, iommu_page_index, nr_pages); 326 323 out_err: 327 324 zpci_err("map error:\n"); 328 325 zpci_err_dma(ret, pa); ··· 349 346 350 347 atomic64_add(npages, &zdev->unmapped_pages); 351 348 iommu_page_index = (dma_addr - zdev->start_dma) >> PAGE_SHIFT; 352 - dma_free_iommu(zdev, iommu_page_index, npages); 349 + dma_free_iommu(dev, iommu_page_index, npages); 353 350 } 354 351 355 352 static void *s390_dma_alloc(struct device *dev, size_t size,
+11 -2
arch/s390/pci/pci_event.c
··· 46 46 static void __zpci_event_error(struct zpci_ccdf_err *ccdf) 47 47 { 48 48 struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); 49 - struct pci_dev *pdev = zdev ? zdev->pdev : NULL; 49 + struct pci_dev *pdev = NULL; 50 50 51 51 zpci_err("error CCDF:\n"); 52 52 zpci_err_hex(ccdf, sizeof(*ccdf)); 53 + 54 + if (zdev) 55 + pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN); 53 56 54 57 pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n", 55 58 pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid); ··· 61 58 return; 62 59 63 60 pdev->error_state = pci_channel_io_perm_failure; 61 + pci_dev_put(pdev); 64 62 } 65 63 66 64 void zpci_event_error(void *data) ··· 73 69 static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf) 74 70 { 75 71 struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); 76 - struct pci_dev *pdev = zdev ? zdev->pdev : NULL; 72 + struct pci_dev *pdev = NULL; 77 73 int ret; 74 + 75 + if (zdev) 76 + pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN); 78 77 79 78 pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n", 80 79 pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid); ··· 145 138 default: 146 139 break; 147 140 } 141 + if (pdev) 142 + pci_dev_put(pdev); 148 143 } 149 144 150 145 void zpci_event_availability(void *data)
+6 -2
drivers/pci/hotplug/s390_pci_hpc.c
··· 93 93 static int disable_slot(struct hotplug_slot *hotplug_slot) 94 94 { 95 95 struct slot *slot = hotplug_slot->private; 96 + struct pci_dev *pdev; 96 97 int rc; 97 98 98 99 if (!zpci_fn_configured(slot->zdev->state)) 99 100 return -EIO; 100 101 101 - if (slot->zdev->pdev) 102 - pci_stop_and_remove_bus_device_locked(slot->zdev->pdev); 102 + pdev = pci_get_slot(slot->zdev->bus, ZPCI_DEVFN); 103 + if (pdev) { 104 + pci_stop_and_remove_bus_device_locked(pdev); 105 + pci_dev_put(pdev); 106 + } 103 107 104 108 rc = zpci_disable_device(slot->zdev); 105 109 if (rc)