The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=7e21158d44cd46e720395604ca6f00f2fa36b20c
commit 7e21158d44cd46e720395604ca6f00f2fa36b20c Author: Bjoern A. Zeeb <b...@freebsd.org> AuthorDate: 2025-07-31 18:28:22 +0000 Commit: Bjoern A. Zeeb <b...@freebsd.org> CommitDate: 2025-09-05 23:24:13 +0000 LinuxKPI: pci: implement [linuxkpi_]pcim_request_all_regions() Factor out the pci_request_region() implementation into an internal function and make pci_request_region() a simple wrapperaround it. Likewise implement pcim_request_all_regions() as a loop calling pci_request_region() for each entry. In two cases which we returned an error before (bar index is valid but bar is not (no len), and neither IO nor MEM) we now reutrn success (nothing to do for us). Otherwise callers, especially pcim_request_all_regions() would error out for the wrong reasons. This seems to also match the expected behaviour of pci_request_region(). Sponsored by: The FreeBSD Foundation (intially) MFC after: 3 days Reviewed by: dumbbell Differential Revision: https://reviews.freebsd.org/D52068 --- sys/compat/linuxkpi/common/include/linux/pci.h | 11 ++++-- sys/compat/linuxkpi/common/src/linux_pci.c | 55 ++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h index 49d2cd79d474..d891d0df3546 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci.h +++ b/sys/compat/linuxkpi/common/include/linux/pci.h @@ -355,7 +355,6 @@ struct pci_dev { TAILQ_HEAD(, pci_mmio_region) mmio; }; -int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name); int pci_alloc_irq_vectors(struct pci_dev *pdev, int minv, int maxv, unsigned int flags); bool pci_device_is_present(struct pci_dev *pdev); @@ -369,7 +368,9 @@ 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); +int linuxkpi_pci_request_region(struct pci_dev *, int, const char *); int linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name); +int linuxkpi_pcim_request_all_regions(struct pci_dev *, const char *); void linuxkpi_pci_release_region(struct pci_dev *pdev, int bar); void linuxkpi_pci_release_regions(struct pci_dev *pdev); int linuxkpi_pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, @@ -562,12 +563,16 @@ done: return (pdev->bus->self); } +#define pci_request_region(pdev, bar, res_name) \ + linuxkpi_pci_request_region(pdev, bar, res_name) #define pci_release_region(pdev, bar) \ linuxkpi_pci_release_region(pdev, bar) -#define pci_release_regions(pdev) \ - linuxkpi_pci_release_regions(pdev) #define pci_request_regions(pdev, res_name) \ linuxkpi_pci_request_regions(pdev, res_name) +#define pci_release_regions(pdev) \ + linuxkpi_pci_release_regions(pdev) +#define pcim_request_all_regions(pdev, name) \ + linuxkpi_pcim_request_all_regions(pdev, name) static inline void lkpi_pci_disable_msix(struct pci_dev *pdev) diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c index 44024e495bb2..7db8af8e88f9 100644 --- a/sys/compat/linuxkpi/common/src/linux_pci.c +++ b/sys/compat/linuxkpi/common/src/linux_pci.c @@ -1159,8 +1159,9 @@ pci_resource_len(struct pci_dev *pdev, int bar) return (rle->count); } -int -pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) +static int +lkpi_pci_request_region(struct pci_dev *pdev, int bar, const char *res_name, + bool managed) { struct resource *res; struct pci_devres *dr; @@ -1168,9 +1169,20 @@ pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) int rid; int type; + if (!lkpi_pci_bar_id_valid(bar)) + return (-EINVAL); + + /* + * If the bar is not valid, return success without adding the BAR; + * otherwise linuxkpi_pcim_request_all_regions() will error. + */ + if (pci_resource_len(pdev, bar) == 0) + return (0); + /* Likewise if it is neither IO nor MEM, nothing to do for us. */ type = pci_resource_type(pdev, bar); if (type < 0) - return (-ENODEV); + return (0); + rid = PCIR_BAR(bar); res = bus_alloc_resource_any(pdev->dev.bsddev, type, &rid, RF_ACTIVE|RF_SHAREABLE); @@ -1183,11 +1195,16 @@ pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) /* * It seems there is an implicit devres tracking on these if the device - * is managed; otherwise the resources are not automatiaclly freed on - * FreeBSD/LinuxKPI tough they should be/are expected to be by Linux - * drivers. + * is managed (lkpi_pci_devres_find() case); otherwise the resources are + * not automatically freed on FreeBSD/LinuxKPI though they should be/are + * expected to be by Linux drivers. + * Otherwise if we are called from a pcim-function with the managed + * argument set, we need to track devres independent of pdev->managed. */ - dr = lkpi_pci_devres_find(pdev); + if (managed) + dr = lkpi_pci_devres_get_alloc(pdev); + else + dr = lkpi_pci_devres_find(pdev); if (dr != NULL) { dr->region_mask |= (1 << bar); dr->region_table[bar] = res; @@ -1203,6 +1220,12 @@ pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) return (0); } +int +linuxkpi_pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) +{ + return (lkpi_pci_request_region(pdev, bar, res_name, false)); +} + int linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name) { @@ -1219,6 +1242,24 @@ linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name) return (0); } +int +linuxkpi_pcim_request_all_regions(struct pci_dev *pdev, const char *res_name) +{ + int bar, error; + + for (bar = 0; bar <= PCIR_MAX_BAR_0; bar++) { + error = lkpi_pci_request_region(pdev, bar, res_name, true); + if (error != 0) { + device_printf(pdev->dev.bsddev, "%s: bar %d res_name '%s': " + "lkpi_pci_request_region returned %d\n", __func__, + bar, res_name, error); + pci_release_regions(pdev); + return (error); + } + } + return (0); +} + void linuxkpi_pci_release_region(struct pci_dev *pdev, int bar) {