Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102196378
D38222.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D38222.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D38222: LinuxKPI: PCI: implement support for more than 1 MSI vector
Attached
Detach File
Event Timeline
Log In to Comment