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

pci: add pci_iomap_range

Virtio drivers should map the part of the BAR they need, not necessarily
all of it.

Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-pci@vger.kernel.org
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

authored by

Michael S. Tsirkin and committed by
Rusty Russell
eb29d8d2 54cfe08b

+53 -18
+10
include/asm-generic/pci_iomap.h
··· 15 15 #ifdef CONFIG_PCI 16 16 /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ 17 17 extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); 18 + extern void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, 19 + unsigned long offset, 20 + unsigned long maxlen); 18 21 /* Create a virtual mapping cookie for a port on a given PCI device. 19 22 * Do not call this directly, it exists to make it easier for architectures 20 23 * to override */ ··· 30 27 31 28 #elif defined(CONFIG_GENERIC_PCI_IOMAP) 32 29 static inline void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) 30 + { 31 + return NULL; 32 + } 33 + 34 + static inline void __iomem *pci_iomap_range(struct pci_dev *dev, int bar, 35 + unsigned long offset, 36 + unsigned long maxlen) 33 37 { 34 38 return NULL; 35 39 }
+43 -18
lib/pci_iomap.c
··· 10 10 11 11 #ifdef CONFIG_PCI 12 12 /** 13 + * pci_iomap_range - create a virtual mapping cookie for a PCI BAR 14 + * @dev: PCI device that owns the BAR 15 + * @bar: BAR number 16 + * @offset: map memory at the given offset in BAR 17 + * @maxlen: max length of the memory to map 18 + * 19 + * Using this function you will get a __iomem address to your device BAR. 20 + * You can access it using ioread*() and iowrite*(). These functions hide 21 + * the details if this is a MMIO or PIO address space and will just do what 22 + * you expect from them in the correct way. 23 + * 24 + * @maxlen specifies the maximum length to map. If you want to get access to 25 + * the complete BAR from offset to the end, pass %0 here. 26 + * */ 27 + void __iomem *pci_iomap_range(struct pci_dev *dev, 28 + int bar, 29 + unsigned long offset, 30 + unsigned long maxlen) 31 + { 32 + resource_size_t start = pci_resource_start(dev, bar); 33 + resource_size_t len = pci_resource_len(dev, bar); 34 + unsigned long flags = pci_resource_flags(dev, bar); 35 + 36 + if (len <= offset || !start) 37 + return NULL; 38 + len -= offset; 39 + start += offset; 40 + if (maxlen && len > maxlen) 41 + len = maxlen; 42 + if (flags & IORESOURCE_IO) 43 + return __pci_ioport_map(dev, start, len); 44 + if (flags & IORESOURCE_MEM) { 45 + if (flags & IORESOURCE_CACHEABLE) 46 + return ioremap(start, len); 47 + return ioremap_nocache(start, len); 48 + } 49 + /* What? */ 50 + return NULL; 51 + } 52 + EXPORT_SYMBOL(pci_iomap_range); 53 + 54 + /** 13 55 * pci_iomap - create a virtual mapping cookie for a PCI BAR 14 56 * @dev: PCI device that owns the BAR 15 57 * @bar: BAR number ··· 67 25 * */ 68 26 void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) 69 27 { 70 - resource_size_t start = pci_resource_start(dev, bar); 71 - resource_size_t len = pci_resource_len(dev, bar); 72 - unsigned long flags = pci_resource_flags(dev, bar); 73 - 74 - if (!len || !start) 75 - return NULL; 76 - if (maxlen && len > maxlen) 77 - len = maxlen; 78 - if (flags & IORESOURCE_IO) 79 - return __pci_ioport_map(dev, start, len); 80 - if (flags & IORESOURCE_MEM) { 81 - if (flags & IORESOURCE_CACHEABLE) 82 - return ioremap(start, len); 83 - return ioremap_nocache(start, len); 84 - } 85 - /* What? */ 86 - return NULL; 28 + return pci_iomap_range(dev, bar, 0, maxlen); 87 29 } 88 - 89 30 EXPORT_SYMBOL(pci_iomap); 90 31 #endif /* CONFIG_PCI */