Skip to content

Commit ad78e05

Browse files
Philipp Stannerbjorn-helgaas
authored andcommitted
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/[email protected] Signed-off-by: Philipp Stanner <[email protected]> Signed-off-by: Krzysztof Wilczyński <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]>
1 parent f748a07 commit ad78e05

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

drivers/pci/devres.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,3 +1027,47 @@ void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
10271027
}
10281028
}
10291029
EXPORT_SYMBOL(pcim_iounmap_regions);
1030+
1031+
/**
1032+
* pcim_iomap_range - Create a ranged __iomap mapping within a PCI BAR
1033+
* @pdev: PCI device to map IO resources for
1034+
* @bar: Index of the BAR
1035+
* @offset: Offset from the begin of the BAR
1036+
* @len: Length in bytes for the mapping
1037+
*
1038+
* Returns: __iomem pointer on success, an IOMEM_ERR_PTR on failure.
1039+
*
1040+
* Creates a new IO-Mapping within the specified @bar, ranging from @offset to
1041+
* @offset + @len.
1042+
*
1043+
* The mapping will automatically get unmapped on driver detach. If desired,
1044+
* release manually only with pcim_iounmap().
1045+
*/
1046+
void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar,
1047+
unsigned long offset, unsigned long len)
1048+
{
1049+
void __iomem *mapping;
1050+
struct pcim_addr_devres *res;
1051+
1052+
res = pcim_addr_devres_alloc(pdev);
1053+
if (!res)
1054+
return IOMEM_ERR_PTR(-ENOMEM);
1055+
1056+
mapping = pci_iomap_range(pdev, bar, offset, len);
1057+
if (!mapping) {
1058+
pcim_addr_devres_free(res);
1059+
return IOMEM_ERR_PTR(-EINVAL);
1060+
}
1061+
1062+
res->type = PCIM_ADDR_DEVRES_TYPE_MAPPING;
1063+
res->baseaddr = mapping;
1064+
1065+
/*
1066+
* Ranged mappings don't get added to the legacy-table, since the table
1067+
* only ever keeps track of whole BARs.
1068+
*/
1069+
1070+
devres_add(&pdev->dev, res);
1071+
return mapping;
1072+
}
1073+
EXPORT_SYMBOL(pcim_iomap_range);

include/linux/pci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,6 +2303,8 @@ int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name);
23032303
int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
23042304
const char *name);
23052305
void pcim_iounmap_regions(struct pci_dev *pdev, int mask);
2306+
void __iomem *pcim_iomap_range(struct pci_dev *pdev, int bar,
2307+
unsigned long offset, unsigned long len);
23062308

23072309
extern int pci_pci_problems;
23082310
#define PCIPCI_FAIL 1 /* No PCI PCI DMA */

0 commit comments

Comments
 (0)