Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F138984834
D42792.id130675.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
D42792.id130675.diff
View Options
diff --git a/sys/compat/linuxkpi/common/include/linux/interrupt.h b/sys/compat/linuxkpi/common/include/linux/interrupt.h
--- 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 /* RF_SHAREABLE */
#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
--- 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>
@@ -310,6 +309,7 @@
* 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,18 +346,6 @@
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);
@@ -365,10 +353,7 @@
/* 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);
@@ -395,55 +380,7 @@
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);
-}
+struct device *linux_pci_find_irq_dev(unsigned int irq);
/*
* All drivers just seem to want to inspect the type not flags.
@@ -578,73 +515,14 @@
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;
+void lkpi_pci_release_region(struct pci_dev *pdev, int bar);
+void lkpi_pci_release_regions(struct pci_dev *pdev);
+int lkpi_pci_request_regions(struct pci_dev *pdev, const char *res_name);
- 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) lkpi_pci_release_region(pdev, bar)
+#define pci_release_regions(pdev) lkpi_pci_release_regions(pdev)
+#define pci_request_regions(pdev, res_name) \
+ lkpi_pci_request_regions(pdev, res_name)
static inline void
lkpi_pci_disable_msix(struct pci_dev *pdev)
@@ -825,42 +703,10 @@
* 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__)
+#define pci_enable_msix(...) lkpi_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);
-}
+int lkpi_pci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries,
+ int nreq);
#define pci_enable_msix_range(...) \
linux_pci_enable_msix_range(__VA_ARGS__)
@@ -891,37 +737,7 @@
#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);
-}
+int _lkpi_pci_enable_msi_range(struct pci_dev *pdev, int minvec, int maxvec);
static inline int
pci_enable_msi(struct pci_dev *pdev)
@@ -946,35 +762,12 @@
{
}
-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;
+void *lkpi_pci_iomap(struct pci_dev *pdev, int mmio_bar, int mmio_size);
+void lkpi_pci_iounmap(struct pci_dev *pdev, void *res);
- 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) \
+ lkpi_pci_iomap(pdev, mmio_bar, mmio_size)
+#define pci_iounmap(pdev, res) lkpi_pci_iounmap(pdev, res)
static inline void
lkpi_pci_save_state(struct pci_dev *pdev)
@@ -1534,97 +1327,16 @@
/* -------------------------------------------------------------------------- */
-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;
+int lkpi_pcim_enable_device(struct pci_dev *pdev);
+#define pcim_enable_device(pdev) lkpi_pcim_enable_device(pdev)
- /* This device is not managed. */
- pdev->managed = true;
+void __iomem **lkpi_pcim_iomap_table(struct pci_dev *pdev);
+#define pcim_iomap_table(pdev) lkpi_pcim_iomap_table(pdev)
- 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);
-}
+int lkpi_pcim_iomap_regions(struct pci_dev *pdev, uint32_t mask,
+ const char *name);
+#define pcim_iomap_regions(pdev, mask, name) \
+ lkpi_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_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -41,11 +41,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>
@@ -118,6 +121,18 @@
"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;
@@ -434,6 +449,41 @@
return (linux_pci_attach_device(dev, pdrv, id, pdev));
}
+static inline 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 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);
+}
+
int
linux_pci_attach_device(device_t dev, struct pci_driver *pdrv,
const struct pci_device_id *id, struct pci_dev *pdev)
@@ -542,7 +592,7 @@
return (0);
}
-struct pci_devres *
+static struct pci_devres *
lkpi_pci_devres_get_alloc(struct pci_dev *pdev)
{
struct pci_devres *dr;
@@ -558,6 +608,15 @@
return (dr);
}
+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));
+}
+
void
lkpi_pci_devres_release(struct device *dev, void *p)
{
@@ -586,7 +645,32 @@
}
}
-struct pcim_iomap_devres *
+int
+lkpi_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;
@@ -606,6 +690,143 @@
return (dr);
}
+void __iomem **
+lkpi_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 *
+lkpi_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
+lkpi_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
+lkpi_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;
+ lkpi_pci_iounmap(pdev, res);
+ }
+ }
+
+ return (-EINVAL);
+}
+
void
lkpi_pcim_iomap_table_release(struct device *dev, void *p)
{
@@ -756,23 +977,36 @@
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 inline struct resource_list_entry *
+linux_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));
+}
+
+//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);
}
unsigned long
@@ -851,44 +1085,62 @@
return (0);
}
-struct resource *
-_lkpi_pci_iomap(struct pci_dev *pdev, int bar, int mmio_size __unused)
+int
+lkpi_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
+lkpi_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;
/*
- * 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);
+ 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);
}
- 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));
+ 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);
- return (NULL);
}
- TAILQ_INSERT_TAIL(&pdev->mmio, mmio, next);
- return (mmio->res);
+ bus_release_resource(pdev->dev.bsddev, rle->type, rle->rid, rle->res);
+}
+
+void
+lkpi_pci_release_regions(struct pci_dev *pdev)
+{
+ int i;
+
+ for (i = 0; i <= PCIR_MAX_BAR_0; i++)
+ pci_release_region(pdev, i);
}
int
@@ -936,6 +1188,72 @@
bus_topo_unlock();
}
+int
+lkpi_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);
+}
+
+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);
+}
+
int
pci_alloc_irq_vectors(struct pci_dev *pdev, int minv, int maxv,
unsigned int flags)
diff --git a/sys/contrib/dev/iwlwifi/pcie/trans.c b/sys/contrib/dev/iwlwifi/pcie/trans.c
--- a/sys/contrib/dev/iwlwifi/pcie/trans.c
+++ b/sys/contrib/dev/iwlwifi/pcie/trans.c
@@ -15,6 +15,7 @@
#include <linux/wait.h>
#include <linux/seq_file.h>
#if defined(__FreeBSD__)
+#include <sys/rman.h>
#include <linux/delay.h>
#endif
diff --git a/sys/contrib/dev/rtw88/pci.c b/sys/contrib/dev/rtw88/pci.c
--- a/sys/contrib/dev/rtw88/pci.c
+++ b/sys/contrib/dev/rtw88/pci.c
@@ -17,6 +17,7 @@
#include "ps.h"
#include "debug.h"
#if defined(__FreeBSD__)
+#include <sys/rman.h>
#include <linux/pm.h>
#endif
diff --git a/sys/dev/irdma/irdma_main.h b/sys/dev/irdma/irdma_main.h
--- a/sys/dev/irdma/irdma_main.h
+++ b/sys/dev/irdma/irdma_main.h
@@ -39,6 +39,7 @@
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
+#include <sys/rman.h>
#include <sys/socket.h>
#include <netinet/if_ether.h>
#include <linux/slab.h>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 7, 4:30 AM (16 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26791170
Default Alt Text
D42792.id130675.diff (24 KB)
Attached To
Mode
D42792: LinuxKPI: Remove sys/rman.h include from LKPI headers.
Attached
Detach File
Event Timeline
Log In to Comment