1
0
mirror of https://github.com/DigitalDevices/dddvb.git synced 2023-10-10 13:37:43 +02:00

add MSI-X support

This commit is contained in:
Ralph Metzler 2017-10-22 19:55:07 +02:00
parent 0f05b1988a
commit 3a2e87eefe

View File

@ -33,6 +33,34 @@ MODULE_PARM_DESC(msi,
extern struct workqueue_struct *ddb_wq; extern struct workqueue_struct *ddb_wq;
#if (KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE)
int pci_irq_vector(struct pci_dev *dev, unsigned int nr)
{
if (dev->msix_enabled) {
struct msi_desc *entry;
int i = 0;
for_each_pci_msi_entry(entry, dev) {
if (i == nr)
return entry->irq;
i++;
}
WARN_ON_ONCE(1);
return -EINVAL;
}
if (dev->msi_enabled) {
struct msi_desc *entry = first_pci_msi_entry(dev);
if (WARN_ON_ONCE(nr >= entry->nvec_used))
return -EINVAL;
} else {
if (WARN_ON_ONCE(nr > 0))
return -EINVAL;
}
return dev->irq + nr;
}
#endif
/****************************************************************************/ /****************************************************************************/
/****************************************************************************/ /****************************************************************************/
/****************************************************************************/ /****************************************************************************/
@ -58,11 +86,13 @@ static void __devexit ddb_irq_exit(struct ddb *dev)
{ {
ddb_irq_disable(dev); ddb_irq_disable(dev);
if (dev->msi == 2) if (dev->msi == 2)
free_irq(dev->pdev->irq + 1, dev); free_irq(pci_irq_vector(dev->pdev, 1), dev);
free_irq(dev->pdev->irq, dev); free_irq(pci_irq_vector(dev->pdev, 0), dev);
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
if (dev->msi) if (dev->msi) {
pci_free_irq_vectors(dev->pdev);
pci_disable_msi(dev->pdev); pci_disable_msi(dev->pdev);
}
#endif #endif
} }
@ -98,8 +128,9 @@ static int __devinit ddb_irq_msi(struct ddb *dev, int nr)
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
if (msi && pci_msi_enabled()) { if (msi && pci_msi_enabled()) {
#if (KERNEL_VERSION(3, 15, 0) <= LINUX_VERSION_CODE) #if (KERNEL_VERSION(3, 15, 0) <= LINUX_VERSION_CODE)
#if (KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE) #if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
stat = pci_alloc_irq_vectors(dev->pdev, 1, nr, PCI_IRQ_MSI); stat = pci_alloc_irq_vectors(dev->pdev, 1, nr,
PCI_IRQ_MSI | PCI_IRQ_MSIX);
#else #else
stat = pci_enable_msi_range(dev->pdev, 1, nr); stat = pci_enable_msi_range(dev->pdev, 1, nr);
#endif #endif
@ -147,7 +178,7 @@ static int __devinit ddb_irq_init2(struct ddb *dev)
if (dev->msi) if (dev->msi)
irq_flag = 0; irq_flag = 0;
stat = request_irq(dev->pdev->irq, ddb_irq_handler_v2, stat = request_irq(pci_irq_vector(dev->pdev, 0), ddb_irq_handler_v2,
irq_flag, "ddbridge", (void *)dev); irq_flag, "ddbridge", (void *)dev);
if (stat < 0) if (stat < 0)
return stat; return stat;
@ -185,24 +216,26 @@ static int __devinit ddb_irq_init(struct ddb *dev)
if (dev->msi) if (dev->msi)
irq_flag = 0; irq_flag = 0;
if (dev->msi == 2) { if (dev->msi == 2) {
stat = request_irq(dev->pdev->irq, ddb_irq_handler0, stat = request_irq(pci_irq_vector(dev->pdev, 0), ddb_irq_handler0,
irq_flag, "ddbridge", (void *)dev); irq_flag, "ddbridge", (void *)dev);
if (stat < 0) if (stat < 0)
return stat; return stat;
stat = request_irq(dev->pdev->irq + 1, ddb_irq_handler1, stat = request_irq(pci_irq_vector(dev->pdev, 1), ddb_irq_handler1,
irq_flag, "ddbridge", (void *)dev); irq_flag, "ddbridge", (void *)dev);
if (stat < 0) { if (stat < 0) {
free_irq(dev->pdev->irq, dev); free_irq(pci_irq_vector(dev->pdev, 0), dev);
return stat; return stat;
} }
} else { } else {
#ifdef DDB_TEST_THREADED #ifdef DDB_TEST_THREADED
stat = request_threaded_irq(dev->pdev->irq, ddb_irq_handler, stat = request_threaded_irq(pci_irq_vector(dev->pdev, 0),
dev->pdev->irq, ddb_irq_handler,
irq_thread, irq_thread,
irq_flag, irq_flag,
"ddbridge", (void *)dev); "ddbridge", (void *)dev);
#else #else
stat = request_irq(dev->pdev->irq, ddb_irq_handler, stat = request_irq(pci_irq_vector(dev->pdev, 0),
ddb_irq_handler,
irq_flag, "ddbridge", (void *)dev); irq_flag, "ddbridge", (void *)dev);
#endif #endif
if (stat < 0) if (stat < 0)