diff options
author | Kishon Vijay Abraham I <kishon@ti.com> | 2017-10-11 10:44:38 +0200 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-10-31 21:33:46 +0100 |
commit | b7636e816adcb52bc96b6fb7bc9d141cbfd17ddb (patch) | |
tree | 1ea4fa1ff02a2df79fd46682f7dc46d3eb16fabb /drivers/misc | |
parent | misc: pci_endpoint_test: Fix pci_endpoint_test not releasing resources on remove (diff) | |
download | linux-b7636e816adcb52bc96b6fb7bc9d141cbfd17ddb.tar.xz linux-b7636e816adcb52bc96b6fb7bc9d141cbfd17ddb.zip |
misc: pci_endpoint_test: Fix BUG_ON error during pci_disable_msi()
pci_disable_msi() throws a Kernel BUG if the driver has successfully
requested an IRQ and not released it. Fix it here by freeing IRQs before
invoking pci_disable_msi().
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/pci_endpoint_test.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index bf64d150ec41..320276f42653 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -92,6 +92,7 @@ struct pci_endpoint_test { void __iomem *bar[6]; struct completion irq_raised; int last_irq; + int num_irqs; /* mutex to protect the ioctls */ struct mutex mutex; struct miscdevice miscdev; @@ -513,6 +514,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); if (irq < 0) dev_err(dev, "failed to get MSI interrupts\n"); + test->num_irqs = irq; } err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, @@ -587,6 +589,9 @@ err_iounmap: pci_iounmap(pdev, test->bar[bar]); } + for (i = 0; i < irq; i++) + devm_free_irq(dev, pdev->irq + i, test); + err_disable_msi: pci_disable_msi(pdev); pci_release_regions(pdev); @@ -600,6 +605,7 @@ err_disable_pdev: static void pci_endpoint_test_remove(struct pci_dev *pdev) { int id; + int i; enum pci_barno bar; struct pci_endpoint_test *test = pci_get_drvdata(pdev); struct miscdevice *misc_device = &test->miscdev; @@ -616,6 +622,8 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) if (test->bar[bar]) pci_iounmap(pdev, test->bar[bar]); } + for (i = 0; i < test->num_irqs; i++) + devm_free_irq(&pdev->dev, pdev->irq + i, test); pci_disable_msi(pdev); pci_release_regions(pdev); pci_disable_device(pdev); |