summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
authorPhilipp Stanner <pstanner@redhat.com>2024-06-13 14:50:25 +0300
committerBjorn Helgaas <bhelgaas@google.com>2024-07-12 00:20:15 +0300
commitad78e05d654567e0a96f91d5db198469ddc2d4fb (patch)
tree1948929339f7bbd8b00631031c3ad2da9de5131a /drivers/pci
parentf748a07a0b6430b3ed638e5df7ae5007a28eaf11 (diff)
downloadlinux-ad78e05d654567e0a96f91d5db198469ddc2d4fb.tar.xz
PCI: Add managed pcim_iomap_range()
The only managed mapping function currently is pcim_iomap() which doesn't allow for mapping an area starting at a certain offset, which many drivers want. Add pcim_iomap_range() as an exported function. Link: https://lore.kernel.org/r/20240613115032.29098-13-pstanner@redhat.com Signed-off-by: Philipp Stanner <pstanner@redhat.com> Signed-off-by: Krzysztof WilczyƄski <kwilczynski@kernel.org> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/devres.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c
index f4a0af2c4d79..3780a9f9ec00 100644
--- a/drivers/pci/devres.c
+++ b/drivers/pci/devres.c
@@ -1027,3 +1027,47 @@ void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
}
}
EXPORT_SYMBOL(pcim_iounmap_regions);
+
+/**
+ * pcim_iomap_range - Create a ranged __iomap mapping within a PCI BAR
+ * @pdev: PCI device to map IO resources for
+ * @bar: Index of the BAR
+ * @offset: Offset from the begin of the BAR
+ * @len: Length in bytes for the mapping
+ *
+ * Returns: __iomem pointer on success, an IOMEM_ERR_PTR on failure.
+ *
+ * Creates a new IO-Mapping within the specified @bar, ranging from @offset to
+ * @offset + @len.
+ *
+ * The mapping will automatically get unmapped on driver detach. If desired,
+ * release manually only with pcim_iounmap().
+ */
+void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar,
+ unsigned long offset, unsigned long len)
+{
+ void __iomem *mapping;
+ struct pcim_addr_devres *res;
+
+ res = pcim_addr_devres_alloc(pdev);
+ if (!res)
+ return IOMEM_ERR_PTR(-ENOMEM);
+
+ mapping = pci_iomap_range(pdev, bar, offset, len);
+ if (!mapping) {
+ pcim_addr_devres_free(res);
+ return IOMEM_ERR_PTR(-EINVAL);
+ }
+
+ res->type = PCIM_ADDR_DEVRES_TYPE_MAPPING;
+ res->baseaddr = mapping;
+
+ /*
+ * Ranged mappings don't get added to the legacy-table, since the table
+ * only ever keeps track of whole BARs.
+ */
+
+ devres_add(&pdev->dev, res);
+ return mapping;
+}
+EXPORT_SYMBOL(pcim_iomap_range);