diff options
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r-- | arch/s390/pci/pci.c | 34 |
1 files changed, 27 insertions, 7 deletions
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); |