diff options
| author | Bjoern A. Zeeb <bz@FreeBSD.org> | 2025-07-31 17:45:26 +0000 |
|---|---|---|
| committer | Bjoern A. Zeeb <bz@FreeBSD.org> | 2025-09-05 23:24:13 +0000 |
| commit | 2f9064a5d2b50f292cc8699d2be5c66c317f1dc7 (patch) | |
| tree | 3adf7abd0b75ea3f30029cc945dce342fe6cb66c | |
| parent | 910cf345d0ee9a5d72856a1ba35382eb4f0db951 (diff) | |
LinuxKPI: pci: implement pcim_iomap()
Like pci_iomap() add the devres version pcim_iomap() using the former
to get the resource.
Add a helper function to validate that the bar is within a valid range
and sprinkle that check also to other related functions.
Sponsored by: The FreeBSD Foundation (intially)
MFC after: 3 days
Reviewed by: dumbbell
Differential Revision: https://reviews.freebsd.org/D52067
| -rw-r--r-- | sys/compat/linuxkpi/common/include/linux/pci.h | 3 | ||||
| -rw-r--r-- | sys/compat/linuxkpi/common/src/linux_pci.c | 58 |
2 files changed, 59 insertions, 2 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h index df29af87f160..49d2cd79d474 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci.h +++ b/sys/compat/linuxkpi/common/include/linux/pci.h @@ -365,6 +365,7 @@ void __iomem **linuxkpi_pcim_iomap_table(struct pci_dev *pdev); void *linuxkpi_pci_iomap_range(struct pci_dev *, int, unsigned long, unsigned long); void *linuxkpi_pci_iomap(struct pci_dev *, int, unsigned long); +void *linuxkpi_pcim_iomap(struct pci_dev *, int, unsigned long); void linuxkpi_pci_iounmap(struct pci_dev *pdev, void *res); int linuxkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask, const char *name); @@ -803,6 +804,8 @@ static inline void pci_disable_sriov(struct pci_dev *dev) linuxkpi_pci_iomap_range(pdev, mmio_bar, mmio_off, mmio_size) #define pci_iomap(pdev, mmio_bar, mmio_size) \ linuxkpi_pci_iomap(pdev, mmio_bar, mmio_size) +#define pcim_iomap(pdev, bar, maxlen) \ + linuxkpi_pcim_iomap(pdev, bar, maxlen) #define pci_iounmap(pdev, res) \ linuxkpi_pci_iounmap(pdev, res) diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c index 00d4a25e86ed..44024e495bb2 100644 --- a/sys/compat/linuxkpi/common/src/linux_pci.c +++ b/sys/compat/linuxkpi/common/src/linux_pci.c @@ -145,6 +145,23 @@ struct linux_dma_priv { #define DMA_PRIV_LOCK(priv) mtx_lock(&(priv)->lock) #define DMA_PRIV_UNLOCK(priv) mtx_unlock(&(priv)->lock) +static void +lkpi_set_pcim_iomap_devres(struct pcim_iomap_devres *dr, int bar, + void *res) +{ + dr->mmio_table[bar] = (void *)rman_get_bushandle(res); + dr->res_table[bar] = res; +} + +static bool +lkpi_pci_bar_id_valid(int bar) +{ + if (bar < 0 || bar > PCIR_MAX_BAR_0) + return (false); + + return (true); +} + static int linux_pdev_dma_uninit(struct pci_dev *pdev) { @@ -763,6 +780,9 @@ _lkpi_pci_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen __unused) struct pci_mmio_region *mmio, *p; int type; + if (!lkpi_pci_bar_id_valid(bar)) + return (NULL); + type = pci_resource_type(pdev, bar); if (type < 0) { device_printf(pdev->dev.bsddev, "%s: bar %d type %d\n", @@ -803,6 +823,9 @@ linuxkpi_pci_iomap_range(struct pci_dev *pdev, int bar, { struct resource *res; + if (!lkpi_pci_bar_id_valid(bar)) + return (NULL); + res = _lkpi_pci_iomap(pdev, bar, maxlen); if (res == NULL) return (NULL); @@ -816,9 +839,41 @@ linuxkpi_pci_iomap_range(struct pci_dev *pdev, int bar, void * linuxkpi_pci_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen) { + if (!lkpi_pci_bar_id_valid(bar)) + return (NULL); + return (linuxkpi_pci_iomap_range(pdev, bar, 0, maxlen)); } +void * +linuxkpi_pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen) +{ + struct pcim_iomap_devres *dr; + void *res; + + if (!lkpi_pci_bar_id_valid(bar)) + return (NULL); + + dr = lkpi_pcim_iomap_devres_find(pdev); + if (dr == NULL) + return (NULL); + + if (dr->res_table[bar] != NULL) + return (dr->res_table[bar]); + + res = linuxkpi_pci_iomap(pdev, bar, maxlen); + if (res == NULL) { + /* + * Do not free the devres in case there were + * other valid mappings before already. + */ + return (NULL); + } + lkpi_set_pcim_iomap_devres(dr, bar, res); + + return (res); +} + void linuxkpi_pci_iounmap(struct pci_dev *pdev, void *res) { @@ -870,8 +925,7 @@ linuxkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask, const char *nam res = _lkpi_pci_iomap(pdev, bar, 0); if (res == NULL) goto err; - dr->mmio_table[bar] = (void *)rman_get_bushandle(res); - dr->res_table[bar] = res; + lkpi_set_pcim_iomap_devres(dr, bar, res); mappings |= (1 << bar); } |
