diff options
author | Kishon Vijay Abraham I <kishon@ti.com> | 2017-10-11 04:44:38 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-10-31 16:33:46 -0400 |
commit | b7636e816adcb52bc96b6fb7bc9d141cbfd17ddb (patch) | |
tree | 1ea4fa1ff02a2df79fd46682f7dc46d3eb16fabb | |
parent | 139838fffec40296d7235982a1a9b917ba31530f (diff) |
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>
-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 { | |||
92 | void __iomem *bar[6]; | 92 | void __iomem *bar[6]; |
93 | struct completion irq_raised; | 93 | struct completion irq_raised; |
94 | int last_irq; | 94 | int last_irq; |
95 | int num_irqs; | ||
95 | /* mutex to protect the ioctls */ | 96 | /* mutex to protect the ioctls */ |
96 | struct mutex mutex; | 97 | struct mutex mutex; |
97 | struct miscdevice miscdev; | 98 | struct miscdevice miscdev; |
@@ -513,6 +514,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, | |||
513 | irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); | 514 | irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); |
514 | if (irq < 0) | 515 | if (irq < 0) |
515 | dev_err(dev, "failed to get MSI interrupts\n"); | 516 | dev_err(dev, "failed to get MSI interrupts\n"); |
517 | test->num_irqs = irq; | ||
516 | } | 518 | } |
517 | 519 | ||
518 | err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, | 520 | err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, |
@@ -587,6 +589,9 @@ err_iounmap: | |||
587 | pci_iounmap(pdev, test->bar[bar]); | 589 | pci_iounmap(pdev, test->bar[bar]); |
588 | } | 590 | } |
589 | 591 | ||
592 | for (i = 0; i < irq; i++) | ||
593 | devm_free_irq(dev, pdev->irq + i, test); | ||
594 | |||
590 | err_disable_msi: | 595 | err_disable_msi: |
591 | pci_disable_msi(pdev); | 596 | pci_disable_msi(pdev); |
592 | pci_release_regions(pdev); | 597 | pci_release_regions(pdev); |
@@ -600,6 +605,7 @@ err_disable_pdev: | |||
600 | static void pci_endpoint_test_remove(struct pci_dev *pdev) | 605 | static void pci_endpoint_test_remove(struct pci_dev *pdev) |
601 | { | 606 | { |
602 | int id; | 607 | int id; |
608 | int i; | ||
603 | enum pci_barno bar; | 609 | enum pci_barno bar; |
604 | struct pci_endpoint_test *test = pci_get_drvdata(pdev); | 610 | struct pci_endpoint_test *test = pci_get_drvdata(pdev); |
605 | struct miscdevice *misc_device = &test->miscdev; | 611 | struct miscdevice *misc_device = &test->miscdev; |
@@ -616,6 +622,8 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) | |||
616 | if (test->bar[bar]) | 622 | if (test->bar[bar]) |
617 | pci_iounmap(pdev, test->bar[bar]); | 623 | pci_iounmap(pdev, test->bar[bar]); |
618 | } | 624 | } |
625 | for (i = 0; i < test->num_irqs; i++) | ||
626 | devm_free_irq(&pdev->dev, pdev->irq + i, test); | ||
619 | pci_disable_msi(pdev); | 627 | pci_disable_msi(pdev); |
620 | pci_release_regions(pdev); | 628 | pci_release_regions(pdev); |
621 | pci_disable_device(pdev); | 629 | pci_disable_device(pdev); |