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:
parent
0f05b1988a
commit
3a2e87eefe
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user