diff options
author | Philipp Stanner <pstanner@redhat.com> | 2024-06-13 14:50:25 +0300 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2024-07-12 00:20:15 +0300 |
commit | ad78e05d654567e0a96f91d5db198469ddc2d4fb (patch) | |
tree | 1948929339f7bbd8b00631031c3ad2da9de5131a /drivers/pci | |
parent | f748a07a0b6430b3ed638e5df7ae5007a28eaf11 (diff) | |
download | linux-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.c | 44 |
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); |