Page MenuHomeFreeBSD

D38222.diff
No OneTemporary

D38222.diff

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
@@ -333,11 +333,7 @@
bool msix_enabled;
phys_addr_t rom;
size_t romlen;
- /*
- * msi_desc should be an array one day? For as long as we only support
- * 1 MSI vector this is fine.
- */
- struct msi_desc *msi_desc;
+ struct msi_desc **msi_desc;
TAILQ_HEAD(, pci_mmio_region) mmio;
};
@@ -889,28 +885,44 @@
linux_pci_enable_msi(pdev)
static inline int
-pci_enable_msi(struct pci_dev *pdev)
+_lkpi_pci_enable_msi_range(struct pci_dev *pdev, int minvec, int maxvec)
{
struct resource_list_entry *rle;
int error;
- int avail;
+ int nvec;
- avail = pci_msi_count(pdev->dev.bsddev);
- if (avail < 1)
- return -EINVAL;
+ if (maxvec < minvec)
+ return (-EINVAL);
- avail = 1; /* this function only enable one MSI IRQ */
- if ((error = -pci_alloc_msi(pdev->dev.bsddev, &avail)) != 0)
+ 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 + avail;
+ 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)
+{
+
+ return (_lkpi_pci_enable_msi_range(pdev, 1, 1));
+}
+
static inline int
pci_channel_offline(struct pci_dev *pdev)
{
@@ -1611,7 +1623,7 @@
/*
* We cannot simply re-define pci_get_device() as we would normally do
* and then hide it in linux_pci.c as too many semi-native drivers still
- * inlucde linux/pci.h and run into the conflict with native PCI. Linux drivers
+ * include linux/pci.h and run into the conflict with native PCI. Linux drivers
* using pci_get_device() need to be changed to call linuxkpi_pci_get_device().
*/
static inline struct pci_dev *
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
@@ -320,6 +320,11 @@
pdev->dev.parent = &linux_root_device;
pdev->dev.release = lkpi_pci_dev_release;
INIT_LIST_HEAD(&pdev->dev.irqents);
+
+ if (pci_msi_count(dev) > 0)
+ pdev->msi_desc = malloc(pci_msi_count(dev) *
+ sizeof(*pdev->msi_desc), M_DEVBUF, M_WAITOK | M_ZERO);
+
kobject_init(&pdev->dev.kobj, &linux_dev_ktype);
kobject_set_name(&pdev->dev.kobj, device_get_nameunit(dev));
kobject_add(&pdev->dev.kobj, &linux_root_device.kobj,
@@ -332,6 +337,7 @@
lkpinew_pci_dev_release(struct device *dev)
{
struct pci_dev *pdev;
+ int i;
pdev = to_pci_dev(dev);
if (pdev->root != NULL)
@@ -339,8 +345,11 @@
if (pdev->bus->self != pdev)
pci_dev_put(pdev->bus->self);
free(pdev->bus, M_DEVBUF);
- if (pdev->msi_desc != NULL)
+ if (pdev->msi_desc != NULL) {
+ for (i = pci_msi_count(pdev->dev.bsddev) - 1; i >= 0; i--)
+ free(pdev->msi_desc[i], M_DEVBUF);
free(pdev->msi_desc, M_DEVBUF);
+ }
free(pdev, M_DEVBUF);
}
@@ -952,10 +961,7 @@
if (flags & PCI_IRQ_MSI) {
if (pci_msi_count(pdev->dev.bsddev) < minv)
return (-ENOSPC);
- /* We only support 1 vector in pci_enable_msi() */
- if (minv != 1)
- return (-ENOSPC);
- error = pci_enable_msi(pdev);
+ error = _lkpi_pci_enable_msi_range(pdev, minv, maxv);
if (error == 0 && pdev->msi_enabled)
return (pdev->dev.irq_end - pdev->dev.irq_start);
}
@@ -975,14 +981,24 @@
struct msi_desc *desc;
struct pci_devinfo *dinfo;
struct pcicfg_msi *msi;
+ int vec;
dev = linux_pci_find_irq_dev(irq);
if (dev == NULL)
return (NULL);
pdev = to_pci_dev(dev);
- if (pdev->msi_desc != NULL)
- return (pdev->msi_desc);
+
+ if (pdev->msi_desc == NULL)
+ return (NULL);
+
+ if (irq < pdev->dev.irq_start || irq >= pdev->dev.irq_end)
+ return (NULL);
+
+ vec = pdev->dev.irq_start - irq;
+
+ if (pdev->msi_desc[vec] != NULL)
+ return (pdev->msi_desc[vec]);
dinfo = device_get_ivars(dev->bsddev);
msi = &dinfo->cfg.msi;
@@ -993,6 +1009,8 @@
(msi->msi_ctrl & PCIM_MSICTRL_64BIT) ? true : false;
desc->msg.data = msi->msi_data;
+ pdev->msi_desc[vec] = desc;
+
return (desc);
}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 9, 7:46 PM (18 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14565084
Default Alt Text
D38222.diff (4 KB)

Event Timeline