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>
This commit is contained in:
Philipp Stanner 2024-06-13 13:50:25 +02:00 committed by Bjorn Helgaas
parent f748a07a0b
commit ad78e05d65
2 changed files with 46 additions and 0 deletions

View File

@ -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);

View File

@ -2303,6 +2303,8 @@ int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name);
int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
const char *name);
void pcim_iounmap_regions(struct pci_dev *pdev, int mask);
void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar,
unsigned long offset, unsigned long len);
extern int pci_pci_problems;
#define PCIPCI_FAIL 1 /* No PCI PCI DMA */