The branch stable/14 has been updated by wulf:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=914a0c5e1b0f4d8650f01c44acee387056880d22

commit 914a0c5e1b0f4d8650f01c44acee387056880d22
Author:     Vladimir Kondratyev <w...@freebsd.org>
AuthorDate: 2023-12-24 08:19:57 +0000
Commit:     Vladimir Kondratyev <w...@freebsd.org>
CommitDate: 2024-02-17 20:58:36 +0000

    LinuxKPI: Remove sys/rman.h include from LKPI headers.
    
    sys/rman.h defines `resource` structure which conflicts with the Linux
    structure of the same name. To fix that remove reference to sys/rman.h
    from linux/pci.h and move resource management code to linux_pci.c.
    Update consumers which were depending on linux/pci.h pollution.
    
    No functional changes intended.
    
    Sponsored by:   Serenity Cyber Security, LLC
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D42792
    
    (cherry picked from commit 96ab16ebab6319dce9b3041961b0ab6e20a4fecc)
---
 .../linuxkpi/common/include/linux/interrupt.h      |   2 +-
 sys/compat/linuxkpi/common/include/linux/pci.h     | 361 ++----------------
 sys/compat/linuxkpi/common/src/linux_interrupt.c   |  19 +-
 sys/compat/linuxkpi/common/src/linux_pci.c         | 411 ++++++++++++++++++---
 sys/contrib/dev/iwlwifi/pcie/trans.c               |   1 +
 sys/contrib/dev/rtw88/pci.c                        |   1 +
 sys/dev/irdma/irdma_main.h                         |   1 +
 7 files changed, 413 insertions(+), 383 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/linux/interrupt.h 
b/sys/compat/linuxkpi/common/include/linux/interrupt.h
index 1ae9f48c7ddd..d5f9a0ae7a47 100644
--- a/sys/compat/linuxkpi/common/include/linux/interrupt.h
+++ b/sys/compat/linuxkpi/common/include/linux/interrupt.h
@@ -40,7 +40,7 @@
 
 typedef        irqreturn_t     (*irq_handler_t)(int, void *);
 
-#define        IRQF_SHARED     RF_SHAREABLE
+#define        IRQF_SHARED             0x0004  /* Historically */
 #define        IRQF_NOBALANCING        0
 
 #define        IRQ_DISABLE_UNLAZY      0
diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h 
b/sys/compat/linuxkpi/common/include/linux/pci.h
index 4406e47d3d63..aa99b050ffd9 100644
--- a/sys/compat/linuxkpi/common/include/linux/pci.h
+++ b/sys/compat/linuxkpi/common/include/linux/pci.h
@@ -42,7 +42,6 @@
 #include <sys/module.h>
 #include <sys/nv.h>
 #include <sys/pciio.h>
-#include <sys/rman.h>
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
 #include <dev/pci/pci_private.h>
@@ -306,10 +305,16 @@ struct msi_desc {
        struct pci_msi_desc             pci;
 };
 
+struct msix_entry {
+       int entry;
+       int vector;
+};
+
 /*
  * If we find drivers accessing this from multiple KPIs we may have to
  * refcount objects of this structure.
  */
+struct resource;
 struct pci_mmio_region {
        TAILQ_ENTRY(pci_mmio_region)    next;
        struct resource                 *res;
@@ -346,32 +351,30 @@ struct pci_dev {
        TAILQ_HEAD(, pci_mmio_region)   mmio;
 };
 
-/* We need some meta-struct to keep track of these for devres. */
-struct pci_devres {
-       bool            enable_io;
-       /* PCIR_MAX_BAR_0 + 1 = 6 => BIT(0..5). */
-       uint8_t         region_mask;
-       struct resource *region_table[PCIR_MAX_BAR_0 + 1]; /* Not needed. */
-};
-struct pcim_iomap_devres {
-       void            *mmio_table[PCIR_MAX_BAR_0 + 1];
-       struct resource *res_table[PCIR_MAX_BAR_0 + 1];
-};
-
 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);
 
+int linuxkpi_pcim_enable_device(struct pci_dev *pdev);
+void __iomem **linuxkpi_pcim_iomap_table(struct pci_dev *pdev);
+void *linuxkpi_pci_iomap(struct pci_dev *pdev, int mmio_bar, int mmio_size);
+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_regions(struct pci_dev *pdev, const char *res_name);
+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,
+    int nreq);
+
 /* Internal helper function(s). */
 struct pci_dev *lkpinew_pci_dev(device_t);
-struct pci_devres *lkpi_pci_devres_get_alloc(struct pci_dev *pdev);
 void lkpi_pci_devres_release(struct device *, void *);
-struct resource *_lkpi_pci_iomap(struct pci_dev *pdev, int bar, int mmio_size);
-struct pcim_iomap_devres *lkpi_pcim_iomap_devres_find(struct pci_dev *pdev);
-void lkpi_pcim_iomap_table_release(struct device *, void *);
 struct pci_dev *lkpi_pci_get_device(uint16_t, uint16_t, struct pci_dev *);
 struct msi_desc *lkpi_pci_msi_desc_alloc(int);
+struct device *lkpi_pci_find_irq_dev(unsigned int irq);
+int _lkpi_pci_enable_msi_range(struct pci_dev *pdev, int minvec, int maxvec);
 
 static inline bool
 dev_is_pci(struct device *dev)
@@ -395,56 +398,6 @@ pci_resource_type(struct pci_dev *pdev, int bar)
                return (SYS_RES_MEMORY);
 }
 
-struct resource_list_entry *linux_pci_reserve_bar(struct pci_dev *pdev,
-                   struct resource_list *rl, int type, int rid);
-
-static inline struct resource_list_entry *
-linux_pci_get_rle(struct pci_dev *pdev, int type, int rid, bool reserve_bar)
-{
-       struct pci_devinfo *dinfo;
-       struct resource_list *rl;
-       struct resource_list_entry *rle;
-
-       dinfo = device_get_ivars(pdev->dev.bsddev);
-       rl = &dinfo->resources;
-       rle = resource_list_find(rl, type, rid);
-       /* Reserve resources for this BAR if needed. */
-       if (rle == NULL && reserve_bar)
-               rle = linux_pci_reserve_bar(pdev, rl, type, rid);
-       return (rle);
-}
-
-static inline struct resource_list_entry *
-linux_pci_get_bar(struct pci_dev *pdev, int bar, bool reserve)
-{
-       int type;
-
-       type = pci_resource_type(pdev, bar);
-       if (type < 0)
-               return (NULL);
-       bar = PCIR_BAR(bar);
-       return (linux_pci_get_rle(pdev, type, bar, reserve));
-}
-
-static inline struct device *
-linux_pci_find_irq_dev(unsigned int irq)
-{
-       struct pci_dev *pdev;
-       struct device *found;
-
-       found = NULL;
-       spin_lock(&pci_lock);
-       list_for_each_entry(pdev, &pci_devices, links) {
-               if (irq == pdev->dev.irq ||
-                   (irq >= pdev->dev.irq_start && irq < pdev->dev.irq_end)) {
-                       found = &pdev->dev;
-                       break;
-               }
-       }
-       spin_unlock(&pci_lock);
-       return (found);
-}
-
 /*
  * All drivers just seem to want to inspect the type not flags.
  */
@@ -578,73 +531,10 @@ done:
        return (pdev->bus->self);
 }
 
-static inline struct pci_devres *
-lkpi_pci_devres_find(struct pci_dev *pdev)
-{
-
-       if (!pdev->managed)
-               return (NULL);
-
-       return (lkpi_pci_devres_get_alloc(pdev));
-}
-
-static inline void
-pci_release_region(struct pci_dev *pdev, int bar)
-{
-       struct resource_list_entry *rle;
-       struct pci_devres *dr;
-       struct pci_mmio_region *mmio, *p;
-
-       if ((rle = linux_pci_get_bar(pdev, bar, false)) == NULL)
-               return;
-
-       /*
-        * As we implicitly track the requests we also need to clear them on
-        * release.  Do clear before resource release.
-        */
-       dr = lkpi_pci_devres_find(pdev);
-       if (dr != NULL) {
-               KASSERT(dr->region_table[bar] == rle->res, ("%s: pdev %p bar %d"
-                   " region_table res %p != rel->res %p\n", __func__, pdev,
-                   bar, dr->region_table[bar], rle->res));
-               dr->region_table[bar] = NULL;
-               dr->region_mask &= ~(1 << bar);
-       }
-
-       TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) {
-               if (rle->res != (void *)rman_get_bushandle(mmio->res))
-                       continue;
-               TAILQ_REMOVE(&pdev->mmio, mmio, next);
-               free(mmio, M_DEVBUF);
-       }
-
-       bus_release_resource(pdev->dev.bsddev, rle->type, rle->rid, rle->res);
-}
-
-static inline void
-pci_release_regions(struct pci_dev *pdev)
-{
-       int i;
-
-       for (i = 0; i <= PCIR_MAX_BAR_0; i++)
-               pci_release_region(pdev, i);
-}
-
-static inline int
-pci_request_regions(struct pci_dev *pdev, const char *res_name)
-{
-       int error;
-       int i;
-
-       for (i = 0; i <= PCIR_MAX_BAR_0; i++) {
-               error = pci_request_region(pdev, i, res_name);
-               if (error && error != -ENODEV) {
-                       pci_release_regions(pdev);
-                       return (error);
-               }
-       }
-       return (0);
-}
+#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)
 
 static inline void
 lkpi_pci_disable_msix(struct pci_dev *pdev)
@@ -655,7 +545,7 @@ lkpi_pci_disable_msix(struct pci_dev *pdev)
        /*
         * The MSIX IRQ numbers associated with this PCI device are no
         * longer valid and might be re-assigned. Make sure
-        * linux_pci_find_irq_dev() does no longer see them by
+        * lkpi_pci_find_irq_dev() does no longer see them by
         * resetting their references to zero:
         */
        pdev->dev.irq_start = 0;
@@ -813,11 +703,6 @@ void       linux_pci_unregister_drm_driver(struct 
pci_driver *pdrv);
 #define        pci_register_driver(pdrv)       linux_pci_register_driver(pdrv)
 #define        pci_unregister_driver(pdrv)     
linux_pci_unregister_driver(pdrv)
 
-struct msix_entry {
-       int entry;
-       int vector;
-};
-
 /*
  * Enable msix, positive errors indicate actual number of available
  * vectors.  Negative errors are failures.
@@ -825,42 +710,7 @@ struct msix_entry {
  * NB: define added to prevent this definition of pci_enable_msix from
  * clashing with the native FreeBSD version.
  */
-#define        pci_enable_msix(...) \
-  linux_pci_enable_msix(__VA_ARGS__)
-
-static inline int
-pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int nreq)
-{
-       struct resource_list_entry *rle;
-       int error;
-       int avail;
-       int i;
-
-       avail = pci_msix_count(pdev->dev.bsddev);
-       if (avail < nreq) {
-               if (avail == 0)
-                       return -EINVAL;
-               return avail;
-       }
-       avail = nreq;
-       if ((error = -pci_alloc_msix(pdev->dev.bsddev, &avail)) != 0)
-               return error;
-       /*
-        * Handle case where "pci_alloc_msix()" may allocate less
-        * interrupts than available and return with no error:
-        */
-       if (avail < nreq) {
-               pci_release_msi(pdev->dev.bsddev);
-               return avail;
-       }
-       rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false);
-       pdev->dev.irq_start = rle->start;
-       pdev->dev.irq_end = rle->start + avail;
-       for (i = 0; i < nreq; i++)
-               entries[i].vector = pdev->dev.irq_start + i;
-       pdev->msix_enabled = true;
-       return (0);
-}
+#define        pci_enable_msix(...)    linuxkpi_pci_enable_msix(__VA_ARGS__)
 
 #define        pci_enable_msix_range(...) \
   linux_pci_enable_msix_range(__VA_ARGS__)
@@ -891,38 +741,6 @@ pci_enable_msix_range(struct pci_dev *dev, struct 
msix_entry *entries,
 #define        pci_enable_msi(pdev) \
   linux_pci_enable_msi(pdev)
 
-static inline int
-_lkpi_pci_enable_msi_range(struct pci_dev *pdev, int minvec, int maxvec)
-{
-       struct resource_list_entry *rle;
-       int error;
-       int nvec;
-
-       if (maxvec < minvec)
-               return (-EINVAL);
-
-       nvec = pci_msi_count(pdev->dev.bsddev);
-       if (nvec < 1 || nvec < minvec)
-               return (-ENOSPC);
-
-       nvec = min(nvec, maxvec);
-       if ((error = -pci_alloc_msi(pdev->dev.bsddev, &nvec)) != 0)
-               return error;
-
-       /* Native PCI might only ever ask for 32 vectors. */
-       if (nvec < minvec) {
-               pci_release_msi(pdev->dev.bsddev);
-               return (-ENOSPC);
-       }
-
-       rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1, false);
-       pdev->dev.irq_start = rle->start;
-       pdev->dev.irq_end = rle->start + nvec;
-       pdev->irq = rle->start;
-       pdev->msi_enabled = true;
-       return (0);
-}
-
 static inline int
 pci_enable_msi(struct pci_dev *pdev)
 {
@@ -946,35 +764,9 @@ static inline void pci_disable_sriov(struct pci_dev *dev)
 {
 }
 
-static inline void *
-pci_iomap(struct pci_dev *pdev, int mmio_bar, int mmio_size)
-{
-       struct resource *res;
-
-       res = _lkpi_pci_iomap(pdev, mmio_bar, mmio_size);
-       if (res == NULL)
-               return (NULL);
-       /* This is a FreeBSD extension so we can use bus_*(). */
-       if (pdev->want_iomap_res)
-               return (res);
-       return ((void *)rman_get_bushandle(res));
-}
-
-static inline void
-pci_iounmap(struct pci_dev *pdev, void *res)
-{
-       struct pci_mmio_region *mmio, *p;
-
-       TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) {
-               if (res != (void *)rman_get_bushandle(mmio->res))
-                       continue;
-               bus_release_resource(pdev->dev.bsddev,
-                   mmio->type, mmio->rid, mmio->res);
-               TAILQ_REMOVE(&pdev->mmio, mmio, next);
-               free(mmio, M_DEVBUF);
-               return;
-       }
-}
+#define        pci_iomap(pdev, mmio_bar, mmio_size) \
+       linuxkpi_pci_iomap(pdev, mmio_bar, mmio_size)
+#define        pci_iounmap(pdev, res)  linuxkpi_pci_iounmap(pdev, res)
 
 static inline void
 lkpi_pci_save_state(struct pci_dev *pdev)
@@ -1534,97 +1326,10 @@ struct pci_dev *lkpi_pci_get_class(unsigned int class, 
struct pci_dev *from);
 
 /* -------------------------------------------------------------------------- 
*/
 
-static inline int
-pcim_enable_device(struct pci_dev *pdev)
-{
-       struct pci_devres *dr;
-       int error;
-
-       /* Here we cannot run through the pdev->managed check. */
-       dr = lkpi_pci_devres_get_alloc(pdev);
-       if (dr == NULL)
-               return (-ENOMEM);
-
-       /* If resources were enabled before do not do it again. */
-       if (dr->enable_io)
-               return (0);
-
-       error = pci_enable_device(pdev);
-       if (error == 0)
-               dr->enable_io = true;
-
-       /* This device is not managed. */
-       pdev->managed = true;
-
-       return (error);
-}
-
-static inline void __iomem **
-pcim_iomap_table(struct pci_dev *pdev)
-{
-       struct pcim_iomap_devres *dr;
-
-       dr = lkpi_pcim_iomap_devres_find(pdev);
-       if (dr == NULL)
-               return (NULL);
-
-       /*
-        * If the driver has manually set a flag to be able to request the
-        * resource to use bus_read/write_<n>, return the shadow table.
-        */
-       if (pdev->want_iomap_res)
-               return ((void **)dr->res_table);
-
-       /* This is the Linux default. */
-       return (dr->mmio_table);
-}
-
-static inline int
-pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask, const char *name)
-{
-       struct pcim_iomap_devres *dr;
-       void *res;
-       uint32_t mappings;
-       int bar;
-
-       dr = lkpi_pcim_iomap_devres_find(pdev);
-       if (dr == NULL)
-               return (-ENOMEM);
-
-       /* Now iomap all the requested (by "mask") ones. */
-       for (bar = mappings = 0; mappings != mask; bar++) {
-               if ((mask & (1 << bar)) == 0)
-                       continue;
-
-               /* Request double is not allowed. */
-               if (dr->mmio_table[bar] != NULL) {
-                       device_printf(pdev->dev.bsddev, "%s: bar %d %p\n",
-                            __func__, bar, dr->mmio_table[bar]);
-                       goto err;
-               }
-
-               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;
-
-               mappings |= (1 << bar);
-       }
-
-       return (0);
-err:
-       for (bar = PCIR_MAX_BAR_0; bar >= 0; bar--) {
-               if ((mappings & (1 << bar)) != 0) {
-                       res = dr->mmio_table[bar];
-                       if (res == NULL)
-                               continue;
-                       pci_iounmap(pdev, res);
-               }
-       }
-
-       return (-EINVAL);
-}
+#define        pcim_enable_device(pdev)        
linuxkpi_pcim_enable_device(pdev)
+#define        pcim_iomap_table(pdev)   linuxkpi_pcim_iomap_table(pdev)
+#define        pcim_iomap_regions(pdev, mask, name) \
+       linuxkpi_pcim_iomap_regions(pdev,  mask, name)
 
 static inline int
 pcim_iomap_regions_request_all(struct pci_dev *pdev, uint32_t mask, char *name)
diff --git a/sys/compat/linuxkpi/common/src/linux_interrupt.c 
b/sys/compat/linuxkpi/common/src/linux_interrupt.c
index 5602b09c8fb8..378088246f21 100644
--- a/sys/compat/linuxkpi/common/src/linux_interrupt.c
+++ b/sys/compat/linuxkpi/common/src/linux_interrupt.c
@@ -117,17 +117,20 @@ lkpi_request_irq(struct device *xdev, unsigned int irq,
        struct resource *res;
        struct irq_ent *irqe;
        struct device *dev;
+       unsigned resflags;
        int error;
        int rid;
 
-       dev = linux_pci_find_irq_dev(irq);
+       dev = lkpi_pci_find_irq_dev(irq);
        if (dev == NULL)
                return -ENXIO;
        if (xdev != NULL && xdev != dev)
                return -ENXIO;
        rid = lkpi_irq_rid(dev, irq);
-       res = bus_alloc_resource_any(dev->bsddev, SYS_RES_IRQ, &rid,
-           flags | RF_ACTIVE);
+       resflags = RF_ACTIVE;
+       if ((flags & IRQF_SHARED) != 0)
+               resflags |= RF_SHAREABLE;
+       res = bus_alloc_resource_any(dev->bsddev, SYS_RES_IRQ, &rid, resflags);
        if (res == NULL)
                return (-ENXIO);
        if (xdev != NULL)
@@ -167,7 +170,7 @@ lkpi_enable_irq(unsigned int irq)
        struct irq_ent *irqe;
        struct device *dev;
 
-       dev = linux_pci_find_irq_dev(irq);
+       dev = lkpi_pci_find_irq_dev(irq);
        if (dev == NULL)
                return -EINVAL;
        irqe = lkpi_irq_ent(dev, irq);
@@ -183,7 +186,7 @@ lkpi_disable_irq(unsigned int irq)
        struct irq_ent *irqe;
        struct device *dev;
 
-       dev = linux_pci_find_irq_dev(irq);
+       dev = lkpi_pci_find_irq_dev(irq);
        if (dev == NULL)
                return;
        irqe = lkpi_irq_ent(dev, irq);
@@ -200,7 +203,7 @@ lkpi_bind_irq_to_cpu(unsigned int irq, int cpu_id)
        struct irq_ent *irqe;
        struct device *dev;
 
-       dev = linux_pci_find_irq_dev(irq);
+       dev = lkpi_pci_find_irq_dev(irq);
        if (dev == NULL)
                return (-ENOENT);
 
@@ -217,7 +220,7 @@ lkpi_free_irq(unsigned int irq, void *device __unused)
        struct irq_ent *irqe;
        struct device *dev;
 
-       dev = linux_pci_find_irq_dev(irq);
+       dev = lkpi_pci_find_irq_dev(irq);
        if (dev == NULL)
                return;
        irqe = lkpi_irq_ent(dev, irq);
@@ -233,7 +236,7 @@ lkpi_devm_free_irq(struct device *xdev, unsigned int irq, 
void *p __unused)
        struct device *dev;
        struct irq_ent *irqe;
 
-       dev = linux_pci_find_irq_dev(irq);
+       dev = lkpi_pci_find_irq_dev(irq);
        if (dev == NULL)
                return;
        if (xdev != dev)
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c 
b/sys/compat/linuxkpi/common/src/linux_pci.c
index 8386552dcd51..4e6cc92f3615 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -42,11 +42,14 @@
 #include <sys/filio.h>
 #include <sys/pciio.h>
 #include <sys/pctrie.h>
+#include <sys/rman.h>
 #include <sys/rwlock.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
 
+#include <machine/bus.h>
+#include <machine/resource.h>
 #include <machine/stdarg.h>
 
 #include <dev/pci/pcivar.h>
@@ -96,6 +99,7 @@ static pci_iov_add_vf_t linux_pci_iov_add_vf;
 static int linux_backlight_get_status(device_t dev, struct backlight_props 
*props);
 static int linux_backlight_update_status(device_t dev, struct backlight_props 
*props);
 static int linux_backlight_get_info(device_t dev, struct backlight_info *info);
+static void lkpi_pcim_iomap_table_release(struct device *, void *);
 
 static device_method_t pci_methods[] = {
        DEVMETHOD(device_probe, linux_pci_probe),
@@ -119,6 +123,18 @@ const char *pci_power_names[] = {
        "UNKNOWN", "D0", "D1", "D2", "D3hot", "D3cold"
 };
 
+/* We need some meta-struct to keep track of these for devres. */
+struct pci_devres {
+       bool            enable_io;
+       /* PCIR_MAX_BAR_0 + 1 = 6 => BIT(0..5). */
+       uint8_t         region_mask;
+       struct resource *region_table[PCIR_MAX_BAR_0 + 1]; /* Not needed. */
+};
+struct pcim_iomap_devres {
+       void            *mmio_table[PCIR_MAX_BAR_0 + 1];
+       struct resource *res_table[PCIR_MAX_BAR_0 + 1];
+};
+
 struct linux_dma_priv {
        uint64_t        dma_mask;
        bus_dma_tag_t   dmat;
@@ -435,6 +451,41 @@ linux_pci_attach(device_t dev)
        return (linux_pci_attach_device(dev, pdrv, id, pdev));
 }
 
+static struct resource_list_entry *
+linux_pci_reserve_bar(struct pci_dev *pdev, struct resource_list *rl,
+    int type, int rid)
+{
+       device_t dev;
+       struct resource *res;
+
+       KASSERT(type == SYS_RES_IOPORT || type == SYS_RES_MEMORY,
+           ("trying to reserve non-BAR type %d", type));
+
+       dev = pdev->pdrv != NULL && pdev->pdrv->isdrm ?
+           device_get_parent(pdev->dev.bsddev) : pdev->dev.bsddev;
+       res = pci_reserve_map(device_get_parent(dev), dev, type, &rid, 0, ~0,
+           1, 1, 0);
+       if (res == NULL)
+               return (NULL);
+       return (resource_list_find(rl, type, rid));
+}
+
+static struct resource_list_entry *
+linux_pci_get_rle(struct pci_dev *pdev, int type, int rid, bool reserve_bar)
+{
+       struct pci_devinfo *dinfo;
+       struct resource_list *rl;
+       struct resource_list_entry *rle;
+
+       dinfo = device_get_ivars(pdev->dev.bsddev);
+       rl = &dinfo->resources;
+       rle = resource_list_find(rl, type, rid);
+       /* Reserve resources for this BAR if needed. */
+       if (rle == NULL && reserve_bar)
+               rle = linux_pci_reserve_bar(pdev, rl, type, rid);
+       return (rle);
+}
+
 int
 linux_pci_attach_device(device_t dev, struct pci_driver *pdrv,
     const struct pci_device_id *id, struct pci_dev *pdev)
@@ -543,7 +594,7 @@ lkpi_pci_disable_dev(struct device *dev)
        return (0);
 }
 
-struct pci_devres *
+static struct pci_devres *
 lkpi_pci_devres_get_alloc(struct pci_dev *pdev)
 {
        struct pci_devres *dr;
@@ -559,6 +610,15 @@ lkpi_pci_devres_get_alloc(struct pci_dev *pdev)
        return (dr);
 }
 
+static struct pci_devres *
+lkpi_pci_devres_find(struct pci_dev *pdev)
+{
+       if (!pdev->managed)
+               return (NULL);
+
+       return (lkpi_pci_devres_get_alloc(pdev));
+}
+
 void
 lkpi_pci_devres_release(struct device *dev, void *p)
 {
@@ -587,7 +647,32 @@ lkpi_pci_devres_release(struct device *dev, void *p)
        }
 }
 
-struct pcim_iomap_devres *
+int
+linuxkpi_pcim_enable_device(struct pci_dev *pdev)
+{
+       struct pci_devres *dr;
+       int error;
+
+       /* Here we cannot run through the pdev->managed check. */
+       dr = lkpi_pci_devres_get_alloc(pdev);
+       if (dr == NULL)
+               return (-ENOMEM);
+
+       /* If resources were enabled before do not do it again. */
+       if (dr->enable_io)
+               return (0);
+
+       error = pci_enable_device(pdev);
+       if (error == 0)
+               dr->enable_io = true;
+
+       /* This device is not managed. */
+       pdev->managed = true;
+
+       return (error);
+}
+
+static struct pcim_iomap_devres *
 lkpi_pcim_iomap_devres_find(struct pci_dev *pdev)
 {
        struct pcim_iomap_devres *dr;
@@ -607,7 +692,144 @@ lkpi_pcim_iomap_devres_find(struct pci_dev *pdev)
        return (dr);
 }
 
+void __iomem **
+linuxkpi_pcim_iomap_table(struct pci_dev *pdev)
+{
+       struct pcim_iomap_devres *dr;
+
+       dr = lkpi_pcim_iomap_devres_find(pdev);
+       if (dr == NULL)
+               return (NULL);
+
+       /*
+        * If the driver has manually set a flag to be able to request the
+        * resource to use bus_read/write_<n>, return the shadow table.
+        */
+       if (pdev->want_iomap_res)
+               return ((void **)dr->res_table);
+
+       /* This is the Linux default. */
+       return (dr->mmio_table);
+}
+
+static struct resource *
+_lkpi_pci_iomap(struct pci_dev *pdev, int bar, int mmio_size __unused)
+{
+       struct pci_mmio_region *mmio, *p;
+       int type;
+
+       type = pci_resource_type(pdev, bar);
+       if (type < 0) {
+               device_printf(pdev->dev.bsddev, "%s: bar %d type %d\n",
+                    __func__, bar, type);
+               return (NULL);
+       }
+
+       /*
+        * Check for duplicate mappings.
+        * This can happen if a driver calls pci_request_region() first.
+        */
+       TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) {
+               if (mmio->type == type && mmio->rid == PCIR_BAR(bar)) {
+                       return (mmio->res);
+               }
+       }
+
+       mmio = malloc(sizeof(*mmio), M_DEVBUF, M_WAITOK | M_ZERO);
+       mmio->rid = PCIR_BAR(bar);
+       mmio->type = type;
+       mmio->res = bus_alloc_resource_any(pdev->dev.bsddev, mmio->type,
+           &mmio->rid, RF_ACTIVE|RF_SHAREABLE);
+       if (mmio->res == NULL) {
+               device_printf(pdev->dev.bsddev, "%s: failed to alloc "
+                   "bar %d type %d rid %d\n",
+                   __func__, bar, type, PCIR_BAR(bar));
+               free(mmio, M_DEVBUF);
+               return (NULL);
+       }
+       TAILQ_INSERT_TAIL(&pdev->mmio, mmio, next);
+
+       return (mmio->res);
+}
+
+void *
+linuxkpi_pci_iomap(struct pci_dev *pdev, int mmio_bar, int mmio_size)
+{
+       struct resource *res;
+
+       res = _lkpi_pci_iomap(pdev, mmio_bar, mmio_size);
+       if (res == NULL)
+               return (NULL);
+       /* This is a FreeBSD extension so we can use bus_*(). */
+       if (pdev->want_iomap_res)
+               return (res);
+       return ((void *)rman_get_bushandle(res));
+}
+
 void
+linuxkpi_pci_iounmap(struct pci_dev *pdev, void *res)
+{
+       struct pci_mmio_region *mmio, *p;
+
+       TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) {
+               if (res != (void *)rman_get_bushandle(mmio->res))
+                       continue;
+               bus_release_resource(pdev->dev.bsddev,
+                   mmio->type, mmio->rid, mmio->res);
+               TAILQ_REMOVE(&pdev->mmio, mmio, next);
+               free(mmio, M_DEVBUF);
+               return;
+       }
+}
+
+int
+linuxkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask, const char 
*name)
+{
+       struct pcim_iomap_devres *dr;
+       void *res;
+       uint32_t mappings;
+       int bar;
+
+       dr = lkpi_pcim_iomap_devres_find(pdev);
+       if (dr == NULL)
+               return (-ENOMEM);
+
+       /* Now iomap all the requested (by "mask") ones. */
+       for (bar = mappings = 0; mappings != mask; bar++) {
+               if ((mask & (1 << bar)) == 0)
+                       continue;
+
+               /* Request double is not allowed. */
+               if (dr->mmio_table[bar] != NULL) {
+                       device_printf(pdev->dev.bsddev, "%s: bar %d %p\n",
+                           __func__, bar, dr->mmio_table[bar]);
+                       goto err;
+               }
+
+               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;
+
+               mappings |= (1 << bar);
+       }
+
+       return (0);
+err:
+       for (bar = PCIR_MAX_BAR_0; bar >= 0; bar--) {
+               if ((mappings & (1 << bar)) != 0) {
+                       res = dr->mmio_table[bar];
+                       if (res == NULL)
+                               continue;
+                       pci_iounmap(pdev, res);
+               }
+       }
+
+       return (-EINVAL);
+}
+
+static void
 lkpi_pcim_iomap_table_release(struct device *dev, void *p)
 {
        struct pcim_iomap_devres *dr;
@@ -757,23 +979,35 @@ linux_pci_register_driver(struct pci_driver *pdrv)
        return (_linux_pci_register_driver(pdrv, dc));
 }
 
-struct resource_list_entry *
-linux_pci_reserve_bar(struct pci_dev *pdev, struct resource_list *rl,
-    int type, int rid)
+static struct resource_list_entry *
+lkpi_pci_get_bar(struct pci_dev *pdev, int bar, bool reserve)
 {
-       device_t dev;
-       struct resource *res;
-
-       KASSERT(type == SYS_RES_IOPORT || type == SYS_RES_MEMORY,
-           ("trying to reserve non-BAR type %d", type));
+       int type;
 
-       dev = pdev->pdrv != NULL && pdev->pdrv->isdrm ?
-           device_get_parent(pdev->dev.bsddev) : pdev->dev.bsddev;
-       res = pci_reserve_map(device_get_parent(dev), dev, type, &rid, 0, ~0,
-           1, 1, 0);
-       if (res == NULL)
+       type = pci_resource_type(pdev, bar);
+       if (type < 0)
                return (NULL);
-       return (resource_list_find(rl, type, rid));
+       bar = PCIR_BAR(bar);
+       return (linux_pci_get_rle(pdev, type, bar, reserve));
+}
+
+struct device *
+lkpi_pci_find_irq_dev(unsigned int irq)
+{
+       struct pci_dev *pdev;
+       struct device *found;
+
+       found = NULL;
+       spin_lock(&pci_lock);
+       list_for_each_entry(pdev, &pci_devices, links) {
+               if (irq == pdev->dev.irq ||
+                   (irq >= pdev->dev.irq_start && irq < pdev->dev.irq_end)) {
+                       found = &pdev->dev;
+                       break;
+               }
+       }
+       spin_unlock(&pci_lock);
+       return (found);
 }
 
 unsigned long
@@ -784,7 +1018,7 @@ pci_resource_start(struct pci_dev *pdev, int bar)
        device_t dev;
        int error;
 
-       if ((rle = linux_pci_get_bar(pdev, bar, true)) == NULL)
+       if ((rle = lkpi_pci_get_bar(pdev, bar, true)) == NULL)
                return (0);
        dev = pdev->pdrv != NULL && pdev->pdrv->isdrm ?
            device_get_parent(pdev->dev.bsddev) : pdev->dev.bsddev;
@@ -803,7 +1037,7 @@ pci_resource_len(struct pci_dev *pdev, int bar)
 {
        struct resource_list_entry *rle;
 
-       if ((rle = linux_pci_get_bar(pdev, bar, true)) == NULL)
+       if ((rle = lkpi_pci_get_bar(pdev, bar, true)) == NULL)
                return (0);
        return (rle->count);
 }
@@ -852,44 +1086,62 @@ pci_request_region(struct pci_dev *pdev, int bar, const 
char *res_name)
        return (0);
 }
 
-struct resource *
-_lkpi_pci_iomap(struct pci_dev *pdev, int bar, int mmio_size __unused)
+int
+linuxkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name)
 {
-       struct pci_mmio_region *mmio, *p;
-       int type;
+       int error;
+       int i;
 
-       type = pci_resource_type(pdev, bar);
-       if (type < 0) {
-               device_printf(pdev->dev.bsddev, "%s: bar %d type %d\n",
-                    __func__, bar, type);
-               return (NULL);
+       for (i = 0; i <= PCIR_MAX_BAR_0; i++) {
+               error = pci_request_region(pdev, i, res_name);
+               if (error && error != -ENODEV) {
+                       pci_release_regions(pdev);
+                       return (error);
+               }
        }
+       return (0);
+}
+
+void
+linuxkpi_pci_release_region(struct pci_dev *pdev, int bar)
+{
+       struct resource_list_entry *rle;
+       struct pci_devres *dr;
+       struct pci_mmio_region *mmio, *p;
+
+       if ((rle = lkpi_pci_get_bar(pdev, bar, false)) == NULL)
+               return;
 
        /*
-        * Check for duplicate mappings.
-        * This can happen if a driver calls pci_request_region() first.
+        * As we implicitly track the requests we also need to clear them on
+        * release.  Do clear before resource release.
         */
-       TAILQ_FOREACH_SAFE(mmio, &pdev->mmio, next, p) {
-               if (mmio->type == type && mmio->rid == PCIR_BAR(bar)) {
-                       return (mmio->res);
-               }
+       dr = lkpi_pci_devres_find(pdev);
*** 159 LINES SKIPPED ***

Reply via email to