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); |