diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/msi.c | 74 |
1 files changed, 31 insertions, 43 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index bdd2ca9df41f..a7f2a014046b 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -272,7 +272,30 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
272 | write_msi_msg_desc(desc, msg); | 272 | write_msi_msg_desc(desc, msg); |
273 | } | 273 | } |
274 | 274 | ||
275 | static int msi_free_irqs(struct pci_dev* dev); | 275 | static void free_msi_irqs(struct pci_dev *dev) |
276 | { | ||
277 | struct msi_desc *entry, *tmp; | ||
278 | |||
279 | list_for_each_entry(entry, &dev->msi_list, list) { | ||
280 | int i, nvec; | ||
281 | if (!entry->irq) | ||
282 | continue; | ||
283 | nvec = 1 << entry->msi_attrib.multiple; | ||
284 | for (i = 0; i < nvec; i++) | ||
285 | BUG_ON(irq_has_action(entry->irq + i)); | ||
286 | } | ||
287 | |||
288 | arch_teardown_msi_irqs(dev); | ||
289 | |||
290 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { | ||
291 | if (entry->msi_attrib.is_msix) { | ||
292 | if (list_is_last(&entry->list, &dev->msi_list)) | ||
293 | iounmap(entry->mask_base); | ||
294 | } | ||
295 | list_del(&entry->list); | ||
296 | kfree(entry); | ||
297 | } | ||
298 | } | ||
276 | 299 | ||
277 | static struct msi_desc *alloc_msi_entry(struct pci_dev *dev) | 300 | static struct msi_desc *alloc_msi_entry(struct pci_dev *dev) |
278 | { | 301 | { |
@@ -396,7 +419,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) | |||
396 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); | 419 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); |
397 | if (ret) { | 420 | if (ret) { |
398 | msi_mask_irq(entry, mask, ~mask); | 421 | msi_mask_irq(entry, mask, ~mask); |
399 | msi_free_irqs(dev); | 422 | free_msi_irqs(dev); |
400 | return ret; | 423 | return ret; |
401 | } | 424 | } |
402 | 425 | ||
@@ -454,7 +477,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
454 | if (!i) | 477 | if (!i) |
455 | iounmap(base); | 478 | iounmap(base); |
456 | else | 479 | else |
457 | msi_free_irqs(dev); | 480 | free_msi_irqs(dev); |
458 | /* No enough memory. Don't try again */ | 481 | /* No enough memory. Don't try again */ |
459 | return -ENOMEM; | 482 | return -ENOMEM; |
460 | } | 483 | } |
@@ -486,7 +509,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
486 | } | 509 | } |
487 | 510 | ||
488 | if (ret) { | 511 | if (ret) { |
489 | msi_free_irqs(dev); | 512 | free_msi_irqs(dev); |
490 | return ret; | 513 | return ret; |
491 | } | 514 | } |
492 | 515 | ||
@@ -644,37 +667,10 @@ void pci_disable_msi(struct pci_dev* dev) | |||
644 | return; | 667 | return; |
645 | 668 | ||
646 | pci_msi_shutdown(dev); | 669 | pci_msi_shutdown(dev); |
647 | msi_free_irqs(dev); | 670 | free_msi_irqs(dev); |
648 | } | 671 | } |
649 | EXPORT_SYMBOL(pci_disable_msi); | 672 | EXPORT_SYMBOL(pci_disable_msi); |
650 | 673 | ||
651 | static int msi_free_irqs(struct pci_dev* dev) | ||
652 | { | ||
653 | struct msi_desc *entry, *tmp; | ||
654 | |||
655 | list_for_each_entry(entry, &dev->msi_list, list) { | ||
656 | int i, nvec; | ||
657 | if (!entry->irq) | ||
658 | continue; | ||
659 | nvec = 1 << entry->msi_attrib.multiple; | ||
660 | for (i = 0; i < nvec; i++) | ||
661 | BUG_ON(irq_has_action(entry->irq + i)); | ||
662 | } | ||
663 | |||
664 | arch_teardown_msi_irqs(dev); | ||
665 | |||
666 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { | ||
667 | if (entry->msi_attrib.is_msix) { | ||
668 | if (list_is_last(&entry->list, &dev->msi_list)) | ||
669 | iounmap(entry->mask_base); | ||
670 | } | ||
671 | list_del(&entry->list); | ||
672 | kfree(entry); | ||
673 | } | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | /** | 674 | /** |
679 | * pci_msix_table_size - return the number of device's MSI-X table entries | 675 | * pci_msix_table_size - return the number of device's MSI-X table entries |
680 | * @dev: pointer to the pci_dev data structure of MSI-X device function | 676 | * @dev: pointer to the pci_dev data structure of MSI-X device function |
@@ -745,11 +741,6 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
745 | } | 741 | } |
746 | EXPORT_SYMBOL(pci_enable_msix); | 742 | EXPORT_SYMBOL(pci_enable_msix); |
747 | 743 | ||
748 | static void msix_free_all_irqs(struct pci_dev *dev) | ||
749 | { | ||
750 | msi_free_irqs(dev); | ||
751 | } | ||
752 | |||
753 | void pci_msix_shutdown(struct pci_dev* dev) | 744 | void pci_msix_shutdown(struct pci_dev* dev) |
754 | { | 745 | { |
755 | struct msi_desc *entry; | 746 | struct msi_desc *entry; |
@@ -774,7 +765,7 @@ void pci_disable_msix(struct pci_dev* dev) | |||
774 | return; | 765 | return; |
775 | 766 | ||
776 | pci_msix_shutdown(dev); | 767 | pci_msix_shutdown(dev); |
777 | msix_free_all_irqs(dev); | 768 | free_msi_irqs(dev); |
778 | } | 769 | } |
779 | EXPORT_SYMBOL(pci_disable_msix); | 770 | EXPORT_SYMBOL(pci_disable_msix); |
780 | 771 | ||
@@ -792,11 +783,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
792 | if (!pci_msi_enable || !dev) | 783 | if (!pci_msi_enable || !dev) |
793 | return; | 784 | return; |
794 | 785 | ||
795 | if (dev->msi_enabled) | 786 | if (dev->msi_enabled || dev->msix_enabled) |
796 | msi_free_irqs(dev); | 787 | free_msi_irqs(dev); |
797 | |||
798 | if (dev->msix_enabled) | ||
799 | msix_free_all_irqs(dev); | ||
800 | } | 788 | } |
801 | 789 | ||
802 | void pci_no_msi(void) | 790 | void pci_no_msi(void) |