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)
 {

Reply via email to