aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2013-05-28 22:22:21 -0400
committerRusty Russell <rusty@rustcorp.com.au>2015-01-21 00:58:49 -0500
commit8cfc99b58366ea9f391fe0da7d16940ca6a1d9c0 (patch)
tree8e9941de0e82da7d4f49856c6134d50173a05bab
parenteb29d8d2aad70636ea23810b4868693673d630d5 (diff)
s390: add pci_iomap_range
Virtio drivers should map the part of the range they need, not necessarily all of it. To this end, support mapping ranges within BAR on s390. Since multiple ranges can now be mapped within a BAR, we keep track of the number of mappings created, and only clear out the mapping for a BAR when this number reaches 0. Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: linux-pci@vger.kernel.org Tested-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--arch/s390/include/asm/pci_io.h1
-rw-r--r--arch/s390/pci/pci.c34
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 @@
16struct zpci_iomap_entry { 16struct zpci_iomap_entry {
17 u32 fh; 17 u32 fh;
18 u8 bar; 18 u8 bar;
19 u16 count;
19}; 20};
20 21
21extern struct zpci_iomap_entry *zpci_iomap_start; 22extern 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 */
262void __iomem *pci_iomap(struct pci_dev *pdev, int bar, unsigned long max) 262void __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}
280EXPORT_SYMBOL_GPL(pci_iomap); 290EXPORT_SYMBOL_GPL(pci_iomap_range);
291
292void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
293{
294 return pci_iomap_range(dev, bar, 0, maxlen);
295}
296EXPORT_SYMBOL(pci_iomap);
281 297
282void pci_iounmap(struct pci_dev *pdev, void __iomem *addr) 298void 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}
292EXPORT_SYMBOL_GPL(pci_iounmap); 312EXPORT_SYMBOL_GPL(pci_iounmap);