diff options
| -rw-r--r-- | arch/s390/include/asm/pci_io.h | 1 | ||||
| -rw-r--r-- | arch/s390/pci/pci.c | 34 |
2 files changed, 28 insertions, 7 deletions
diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h index f664e96f48c7..1a9a98de5bde 100644 --- a/arch/s390/include/asm/pci_io.h +++ b/arch/s390/include/asm/pci_io.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | struct zpci_iomap_entry { | 16 | struct zpci_iomap_entry { |
| 17 | u32 fh; | 17 | u32 fh; |
| 18 | u8 bar; | 18 | u8 bar; |
| 19 | u16 count; | ||
| 19 | }; | 20 | }; |
| 20 | 21 | ||
| 21 | extern struct zpci_iomap_entry *zpci_iomap_start; | 22 | extern struct zpci_iomap_entry *zpci_iomap_start; |
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 3290f11ae1d9..753a56731951 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
| @@ -259,7 +259,10 @@ void __iowrite64_copy(void __iomem *to, const void *from, size_t count) | |||
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | /* Create a virtual mapping cookie for a PCI BAR */ | 261 | /* Create a virtual mapping cookie for a PCI BAR */ |
| 262 | void __iomem *pci_iomap(struct pci_dev *pdev, int bar, unsigned long max) | 262 | void __iomem *pci_iomap_range(struct pci_dev *pdev, |
| 263 | int bar, | ||
| 264 | unsigned long offset, | ||
| 265 | unsigned long max) | ||
| 263 | { | 266 | { |
| 264 | struct zpci_dev *zdev = get_zdev(pdev); | 267 | struct zpci_dev *zdev = get_zdev(pdev); |
| 265 | u64 addr; | 268 | u64 addr; |
| @@ -270,14 +273,27 @@ void __iomem *pci_iomap(struct pci_dev *pdev, int bar, unsigned long max) | |||
| 270 | 273 | ||
| 271 | idx = zdev->bars[bar].map_idx; | 274 | idx = zdev->bars[bar].map_idx; |
| 272 | spin_lock(&zpci_iomap_lock); | 275 | spin_lock(&zpci_iomap_lock); |
| 273 | zpci_iomap_start[idx].fh = zdev->fh; | 276 | if (zpci_iomap_start[idx].count++) { |
| 274 | zpci_iomap_start[idx].bar = bar; | 277 | BUG_ON(zpci_iomap_start[idx].fh != zdev->fh || |
| 278 | zpci_iomap_start[idx].bar != bar); | ||
| 279 | } else { | ||
| 280 | zpci_iomap_start[idx].fh = zdev->fh; | ||
| 281 | zpci_iomap_start[idx].bar = bar; | ||
| 282 | } | ||
| 283 | /* Detect overrun */ | ||
| 284 | BUG_ON(!zpci_iomap_start[idx].count); | ||
| 275 | spin_unlock(&zpci_iomap_lock); | 285 | spin_unlock(&zpci_iomap_lock); |
| 276 | 286 | ||
| 277 | addr = ZPCI_IOMAP_ADDR_BASE | ((u64) idx << 48); | 287 | addr = ZPCI_IOMAP_ADDR_BASE | ((u64) idx << 48); |
| 278 | return (void __iomem *) addr; | 288 | return (void __iomem *) addr + offset; |
| 279 | } | 289 | } |
| 280 | EXPORT_SYMBOL_GPL(pci_iomap); | 290 | EXPORT_SYMBOL_GPL(pci_iomap_range); |
| 291 | |||
| 292 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) | ||
| 293 | { | ||
| 294 | return pci_iomap_range(dev, bar, 0, maxlen); | ||
| 295 | } | ||
| 296 | EXPORT_SYMBOL(pci_iomap); | ||
| 281 | 297 | ||
| 282 | void pci_iounmap(struct pci_dev *pdev, void __iomem *addr) | 298 | void pci_iounmap(struct pci_dev *pdev, void __iomem *addr) |
| 283 | { | 299 | { |
| @@ -285,8 +301,12 @@ void pci_iounmap(struct pci_dev *pdev, void __iomem *addr) | |||
| 285 | 301 | ||
| 286 | idx = (((__force u64) addr) & ~ZPCI_IOMAP_ADDR_BASE) >> 48; | 302 | idx = (((__force u64) addr) & ~ZPCI_IOMAP_ADDR_BASE) >> 48; |
| 287 | spin_lock(&zpci_iomap_lock); | 303 | spin_lock(&zpci_iomap_lock); |
| 288 | zpci_iomap_start[idx].fh = 0; | 304 | /* Detect underrun */ |
| 289 | zpci_iomap_start[idx].bar = 0; | 305 | BUG_ON(!zpci_iomap_start[idx].count); |
| 306 | if (!--zpci_iomap_start[idx].count) { | ||
| 307 | zpci_iomap_start[idx].fh = 0; | ||
| 308 | zpci_iomap_start[idx].bar = 0; | ||
| 309 | } | ||
| 290 | spin_unlock(&zpci_iomap_lock); | 310 | spin_unlock(&zpci_iomap_lock); |
| 291 | } | 311 | } |
| 292 | EXPORT_SYMBOL_GPL(pci_iounmap); | 312 | EXPORT_SYMBOL_GPL(pci_iounmap); |
