diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2007-01-28 14:42:52 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-07 18:50:07 -0500 |
commit | ded86d8d37736df67ddeec4ae00e2ec1a5a90b3c (patch) | |
tree | 6a1c175992692ca2db80b34b0df3cb44b1541253 /drivers/pci/msi.c | |
parent | 8fed4b65236c44d090bd62f2d14938ae791e0260 (diff) |
msi: Kill msi_lookup_irq
The function msi_lookup_irq was horrible. As a side effect of running
it changed dev->irq, and then the callers would need to change it
back. In addition it does a global scan through all of the irqs,
which seems to be the sole justification of the msi_lock.
To remove the neede for msi_lookup_irq I added first_msi_irq to struct
pci_dev. Then depending on the context I replaced msi_lookup_irq with
dev->first_msi_irq, dev->msi_enabled, or dev->msix_enabled.
msi_enabled and msix_enabled were already present in pci_dev for other
reasons.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r-- | drivers/pci/msi.c | 149 |
1 files changed, 59 insertions, 90 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 067ae9917fd6..b945470bef18 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -272,28 +272,6 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type) | |||
272 | pci_intx(dev, 1); /* enable intx */ | 272 | pci_intx(dev, 1); /* enable intx */ |
273 | } | 273 | } |
274 | 274 | ||
275 | static int msi_lookup_irq(struct pci_dev *dev, int type) | ||
276 | { | ||
277 | int irq; | ||
278 | unsigned long flags; | ||
279 | |||
280 | spin_lock_irqsave(&msi_lock, flags); | ||
281 | for (irq = 0; irq < NR_IRQS; irq++) { | ||
282 | if (!msi_desc[irq] || msi_desc[irq]->dev != dev || | ||
283 | msi_desc[irq]->msi_attrib.type != type || | ||
284 | msi_desc[irq]->msi_attrib.default_irq != dev->irq) | ||
285 | continue; | ||
286 | spin_unlock_irqrestore(&msi_lock, flags); | ||
287 | /* This pre-assigned MSI irq for this device | ||
288 | already exists. Override dev->irq with this irq */ | ||
289 | dev->irq = irq; | ||
290 | return 0; | ||
291 | } | ||
292 | spin_unlock_irqrestore(&msi_lock, flags); | ||
293 | |||
294 | return -EACCES; | ||
295 | } | ||
296 | |||
297 | #ifdef CONFIG_PM | 275 | #ifdef CONFIG_PM |
298 | static int __pci_save_msi_state(struct pci_dev *dev) | 276 | static int __pci_save_msi_state(struct pci_dev *dev) |
299 | { | 277 | { |
@@ -364,11 +342,13 @@ static void __pci_restore_msi_state(struct pci_dev *dev) | |||
364 | static int __pci_save_msix_state(struct pci_dev *dev) | 342 | static int __pci_save_msix_state(struct pci_dev *dev) |
365 | { | 343 | { |
366 | int pos; | 344 | int pos; |
367 | int temp; | ||
368 | int irq, head, tail = 0; | 345 | int irq, head, tail = 0; |
369 | u16 control; | 346 | u16 control; |
370 | struct pci_cap_saved_state *save_state; | 347 | struct pci_cap_saved_state *save_state; |
371 | 348 | ||
349 | if (!dev->msix_enabled) | ||
350 | return 0; | ||
351 | |||
372 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 352 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
373 | if (pos <= 0 || dev->no_msi) | 353 | if (pos <= 0 || dev->no_msi) |
374 | return 0; | 354 | return 0; |
@@ -386,13 +366,7 @@ static int __pci_save_msix_state(struct pci_dev *dev) | |||
386 | *((u16 *)&save_state->data[0]) = control; | 366 | *((u16 *)&save_state->data[0]) = control; |
387 | 367 | ||
388 | /* save the table */ | 368 | /* save the table */ |
389 | temp = dev->irq; | 369 | irq = head = dev->first_msi_irq; |
390 | if (msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { | ||
391 | kfree(save_state); | ||
392 | return -EINVAL; | ||
393 | } | ||
394 | |||
395 | irq = head = dev->irq; | ||
396 | while (head != tail) { | 370 | while (head != tail) { |
397 | struct msi_desc *entry; | 371 | struct msi_desc *entry; |
398 | 372 | ||
@@ -402,7 +376,6 @@ static int __pci_save_msix_state(struct pci_dev *dev) | |||
402 | tail = msi_desc[irq]->link.tail; | 376 | tail = msi_desc[irq]->link.tail; |
403 | irq = tail; | 377 | irq = tail; |
404 | } | 378 | } |
405 | dev->irq = temp; | ||
406 | 379 | ||
407 | save_state->cap_nr = PCI_CAP_ID_MSIX; | 380 | save_state->cap_nr = PCI_CAP_ID_MSIX; |
408 | pci_add_saved_cap(dev, save_state); | 381 | pci_add_saved_cap(dev, save_state); |
@@ -428,9 +401,11 @@ static void __pci_restore_msix_state(struct pci_dev *dev) | |||
428 | int pos; | 401 | int pos; |
429 | int irq, head, tail = 0; | 402 | int irq, head, tail = 0; |
430 | struct msi_desc *entry; | 403 | struct msi_desc *entry; |
431 | int temp; | ||
432 | struct pci_cap_saved_state *save_state; | 404 | struct pci_cap_saved_state *save_state; |
433 | 405 | ||
406 | if (!dev->msix_enabled) | ||
407 | return; | ||
408 | |||
434 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); | 409 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); |
435 | if (!save_state) | 410 | if (!save_state) |
436 | return; | 411 | return; |
@@ -443,10 +418,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev) | |||
443 | return; | 418 | return; |
444 | 419 | ||
445 | /* route the table */ | 420 | /* route the table */ |
446 | temp = dev->irq; | 421 | irq = head = dev->first_msi_irq; |
447 | if (msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) | ||
448 | return; | ||
449 | irq = head = dev->irq; | ||
450 | while (head != tail) { | 422 | while (head != tail) { |
451 | entry = msi_desc[irq]; | 423 | entry = msi_desc[irq]; |
452 | write_msi_msg(irq, &entry->msg_save); | 424 | write_msi_msg(irq, &entry->msg_save); |
@@ -454,7 +426,6 @@ static void __pci_restore_msix_state(struct pci_dev *dev) | |||
454 | tail = msi_desc[irq]->link.tail; | 426 | tail = msi_desc[irq]->link.tail; |
455 | irq = tail; | 427 | irq = tail; |
456 | } | 428 | } |
457 | dev->irq = temp; | ||
458 | 429 | ||
459 | pci_write_config_word(dev, msi_control_reg(pos), save); | 430 | pci_write_config_word(dev, msi_control_reg(pos), save); |
460 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | 431 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
@@ -524,6 +495,7 @@ static int msi_capability_init(struct pci_dev *dev) | |||
524 | return status; | 495 | return status; |
525 | } | 496 | } |
526 | 497 | ||
498 | dev->first_msi_irq = irq; | ||
527 | attach_msi_entry(entry, irq); | 499 | attach_msi_entry(entry, irq); |
528 | /* Set MSI enabled bits */ | 500 | /* Set MSI enabled bits */ |
529 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 501 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
@@ -620,6 +592,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
620 | avail = -EBUSY; | 592 | avail = -EBUSY; |
621 | return avail; | 593 | return avail; |
622 | } | 594 | } |
595 | dev->first_msi_irq = entries[0].vector; | ||
623 | /* Set MSI-X enabled bits */ | 596 | /* Set MSI-X enabled bits */ |
624 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | 597 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
625 | 598 | ||
@@ -667,13 +640,11 @@ int pci_msi_supported(struct pci_dev * dev) | |||
667 | **/ | 640 | **/ |
668 | int pci_enable_msi(struct pci_dev* dev) | 641 | int pci_enable_msi(struct pci_dev* dev) |
669 | { | 642 | { |
670 | int pos, temp, status; | 643 | int pos, status; |
671 | 644 | ||
672 | if (pci_msi_supported(dev) < 0) | 645 | if (pci_msi_supported(dev) < 0) |
673 | return -EINVAL; | 646 | return -EINVAL; |
674 | 647 | ||
675 | temp = dev->irq; | ||
676 | |||
677 | status = msi_init(); | 648 | status = msi_init(); |
678 | if (status < 0) | 649 | if (status < 0) |
679 | return status; | 650 | return status; |
@@ -682,15 +653,14 @@ int pci_enable_msi(struct pci_dev* dev) | |||
682 | if (!pos) | 653 | if (!pos) |
683 | return -EINVAL; | 654 | return -EINVAL; |
684 | 655 | ||
685 | WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSI)); | 656 | WARN_ON(!!dev->msi_enabled); |
686 | 657 | ||
687 | /* Check whether driver already requested for MSI-X irqs */ | 658 | /* Check whether driver already requested for MSI-X irqs */ |
688 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 659 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
689 | if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { | 660 | if (pos > 0 && dev->msix_enabled) { |
690 | printk(KERN_INFO "PCI: %s: Can't enable MSI. " | 661 | printk(KERN_INFO "PCI: %s: Can't enable MSI. " |
691 | "Device already has MSI-X irq assigned\n", | 662 | "Device already has MSI-X enabled\n", |
692 | pci_name(dev)); | 663 | pci_name(dev)); |
693 | dev->irq = temp; | ||
694 | return -EINVAL; | 664 | return -EINVAL; |
695 | } | 665 | } |
696 | status = msi_capability_init(dev); | 666 | status = msi_capability_init(dev); |
@@ -709,6 +679,9 @@ void pci_disable_msi(struct pci_dev* dev) | |||
709 | if (!dev) | 679 | if (!dev) |
710 | return; | 680 | return; |
711 | 681 | ||
682 | if (!dev->msi_enabled) | ||
683 | return; | ||
684 | |||
712 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 685 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
713 | if (!pos) | 686 | if (!pos) |
714 | return; | 687 | return; |
@@ -717,28 +690,30 @@ void pci_disable_msi(struct pci_dev* dev) | |||
717 | if (!(control & PCI_MSI_FLAGS_ENABLE)) | 690 | if (!(control & PCI_MSI_FLAGS_ENABLE)) |
718 | return; | 691 | return; |
719 | 692 | ||
693 | |||
720 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 694 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
721 | 695 | ||
722 | spin_lock_irqsave(&msi_lock, flags); | 696 | spin_lock_irqsave(&msi_lock, flags); |
723 | entry = msi_desc[dev->irq]; | 697 | entry = msi_desc[dev->first_msi_irq]; |
724 | if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { | 698 | if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { |
725 | spin_unlock_irqrestore(&msi_lock, flags); | 699 | spin_unlock_irqrestore(&msi_lock, flags); |
726 | return; | 700 | return; |
727 | } | 701 | } |
728 | if (irq_has_action(dev->irq)) { | 702 | if (irq_has_action(dev->first_msi_irq)) { |
729 | spin_unlock_irqrestore(&msi_lock, flags); | 703 | spin_unlock_irqrestore(&msi_lock, flags); |
730 | printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without " | 704 | printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without " |
731 | "free_irq() on MSI irq %d\n", | 705 | "free_irq() on MSI irq %d\n", |
732 | pci_name(dev), dev->irq); | 706 | pci_name(dev), dev->first_msi_irq); |
733 | BUG_ON(irq_has_action(dev->irq)); | 707 | BUG_ON(irq_has_action(dev->first_msi_irq)); |
734 | } else { | 708 | } else { |
735 | default_irq = entry->msi_attrib.default_irq; | 709 | default_irq = entry->msi_attrib.default_irq; |
736 | spin_unlock_irqrestore(&msi_lock, flags); | 710 | spin_unlock_irqrestore(&msi_lock, flags); |
737 | msi_free_irq(dev, dev->irq); | 711 | msi_free_irq(dev, dev->first_msi_irq); |
738 | 712 | ||
739 | /* Restore dev->irq to its default pin-assertion irq */ | 713 | /* Restore dev->irq to its default pin-assertion irq */ |
740 | dev->irq = default_irq; | 714 | dev->irq = default_irq; |
741 | } | 715 | } |
716 | dev->first_msi_irq = 0; | ||
742 | } | 717 | } |
743 | 718 | ||
744 | static int msi_free_irq(struct pci_dev* dev, int irq) | 719 | static int msi_free_irq(struct pci_dev* dev, int irq) |
@@ -797,7 +772,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq) | |||
797 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | 772 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) |
798 | { | 773 | { |
799 | int status, pos, nr_entries; | 774 | int status, pos, nr_entries; |
800 | int i, j, temp; | 775 | int i, j; |
801 | u16 control; | 776 | u16 control; |
802 | 777 | ||
803 | if (!entries || pci_msi_supported(dev) < 0) | 778 | if (!entries || pci_msi_supported(dev) < 0) |
@@ -825,16 +800,14 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
825 | return -EINVAL; /* duplicate entry */ | 800 | return -EINVAL; /* duplicate entry */ |
826 | } | 801 | } |
827 | } | 802 | } |
828 | temp = dev->irq; | 803 | WARN_ON(!!dev->msix_enabled); |
829 | WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)); | ||
830 | 804 | ||
831 | /* Check whether driver already requested for MSI irq */ | 805 | /* Check whether driver already requested for MSI irq */ |
832 | if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 && | 806 | if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 && |
833 | !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) { | 807 | dev->msi_enabled) { |
834 | printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " | 808 | printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " |
835 | "Device already has an MSI irq assigned\n", | 809 | "Device already has an MSI irq assigned\n", |
836 | pci_name(dev)); | 810 | pci_name(dev)); |
837 | dev->irq = temp; | ||
838 | return -EINVAL; | 811 | return -EINVAL; |
839 | } | 812 | } |
840 | status = msix_capability_init(dev, entries, nvec); | 813 | status = msix_capability_init(dev, entries, nvec); |
@@ -843,7 +816,9 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
843 | 816 | ||
844 | void pci_disable_msix(struct pci_dev* dev) | 817 | void pci_disable_msix(struct pci_dev* dev) |
845 | { | 818 | { |
846 | int pos, temp; | 819 | int irq, head, tail = 0, warning = 0; |
820 | unsigned long flags; | ||
821 | int pos; | ||
847 | u16 control; | 822 | u16 control; |
848 | 823 | ||
849 | if (!pci_msi_enable) | 824 | if (!pci_msi_enable) |
@@ -851,6 +826,9 @@ void pci_disable_msix(struct pci_dev* dev) | |||
851 | if (!dev) | 826 | if (!dev) |
852 | return; | 827 | return; |
853 | 828 | ||
829 | if (!dev->msix_enabled) | ||
830 | return; | ||
831 | |||
854 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 832 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
855 | if (!pos) | 833 | if (!pos) |
856 | return; | 834 | return; |
@@ -861,31 +839,25 @@ void pci_disable_msix(struct pci_dev* dev) | |||
861 | 839 | ||
862 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | 840 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
863 | 841 | ||
864 | temp = dev->irq; | 842 | irq = head = dev->first_msi_irq; |
865 | if (!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { | 843 | while (head != tail) { |
866 | int irq, head, tail = 0, warning = 0; | 844 | spin_lock_irqsave(&msi_lock, flags); |
867 | unsigned long flags; | 845 | tail = msi_desc[irq]->link.tail; |
868 | 846 | spin_unlock_irqrestore(&msi_lock, flags); | |
869 | irq = head = dev->irq; | 847 | if (irq_has_action(irq)) |
870 | dev->irq = temp; /* Restore pin IRQ */ | 848 | warning = 1; |
871 | while (head != tail) { | 849 | else if (irq != head) /* Release MSI-X irq */ |
872 | spin_lock_irqsave(&msi_lock, flags); | 850 | msi_free_irq(dev, irq); |
873 | tail = msi_desc[irq]->link.tail; | 851 | irq = tail; |
874 | spin_unlock_irqrestore(&msi_lock, flags); | 852 | } |
875 | if (irq_has_action(irq)) | 853 | msi_free_irq(dev, irq); |
876 | warning = 1; | 854 | if (warning) { |
877 | else if (irq != head) /* Release MSI-X irq */ | 855 | printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " |
878 | msi_free_irq(dev, irq); | 856 | "free_irq() on all MSI-X irqs\n", |
879 | irq = tail; | 857 | pci_name(dev)); |
880 | } | 858 | BUG_ON(warning > 0); |
881 | msi_free_irq(dev, irq); | ||
882 | if (warning) { | ||
883 | printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " | ||
884 | "free_irq() on all MSI-X irqs\n", | ||
885 | pci_name(dev)); | ||
886 | BUG_ON(warning > 0); | ||
887 | } | ||
888 | } | 859 | } |
860 | dev->first_msi_irq = 0; | ||
889 | } | 861 | } |
890 | 862 | ||
891 | /** | 863 | /** |
@@ -899,30 +871,28 @@ void pci_disable_msix(struct pci_dev* dev) | |||
899 | **/ | 871 | **/ |
900 | void msi_remove_pci_irq_vectors(struct pci_dev* dev) | 872 | void msi_remove_pci_irq_vectors(struct pci_dev* dev) |
901 | { | 873 | { |
902 | int pos, temp; | 874 | int pos; |
903 | unsigned long flags; | 875 | unsigned long flags; |
904 | 876 | ||
905 | if (!pci_msi_enable || !dev) | 877 | if (!pci_msi_enable || !dev) |
906 | return; | 878 | return; |
907 | 879 | ||
908 | temp = dev->irq; /* Save IOAPIC IRQ */ | ||
909 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 880 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
910 | if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) { | 881 | if (pos > 0 && dev->msi_enabled) { |
911 | if (irq_has_action(dev->irq)) { | 882 | if (irq_has_action(dev->first_msi_irq)) { |
912 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " | 883 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " |
913 | "called without free_irq() on MSI irq %d\n", | 884 | "called without free_irq() on MSI irq %d\n", |
914 | pci_name(dev), dev->irq); | 885 | pci_name(dev), dev->first_msi_irq); |
915 | BUG_ON(irq_has_action(dev->irq)); | 886 | BUG_ON(irq_has_action(dev->first_msi_irq)); |
916 | } else /* Release MSI irq assigned to this device */ | 887 | } else /* Release MSI irq assigned to this device */ |
917 | msi_free_irq(dev, dev->irq); | 888 | msi_free_irq(dev, dev->first_msi_irq); |
918 | dev->irq = temp; /* Restore IOAPIC IRQ */ | ||
919 | } | 889 | } |
920 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 890 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
921 | if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { | 891 | if (pos > 0 && dev->msix_enabled) { |
922 | int irq, head, tail = 0, warning = 0; | 892 | int irq, head, tail = 0, warning = 0; |
923 | void __iomem *base = NULL; | 893 | void __iomem *base = NULL; |
924 | 894 | ||
925 | irq = head = dev->irq; | 895 | irq = head = dev->first_msi_irq; |
926 | while (head != tail) { | 896 | while (head != tail) { |
927 | spin_lock_irqsave(&msi_lock, flags); | 897 | spin_lock_irqsave(&msi_lock, flags); |
928 | tail = msi_desc[irq]->link.tail; | 898 | tail = msi_desc[irq]->link.tail; |
@@ -942,7 +912,6 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
942 | pci_name(dev)); | 912 | pci_name(dev)); |
943 | BUG_ON(warning > 0); | 913 | BUG_ON(warning > 0); |
944 | } | 914 | } |
945 | dev->irq = temp; /* Restore IOAPIC IRQ */ | ||
946 | } | 915 | } |
947 | } | 916 | } |
948 | 917 | ||