Commit ded86d8d37736df67ddeec4ae00e2ec1a5a90b3c
Committed by
Greg Kroah-Hartman
1 parent
8fed4b6523
Exists in
master
and in
7 other branches
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>
Showing 2 changed files with 62 additions and 90 deletions Side-by-side Diff
drivers/pci/msi.c
... | ... | @@ -272,28 +272,6 @@ |
272 | 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 | 275 | #ifdef CONFIG_PM |
298 | 276 | static int __pci_save_msi_state(struct pci_dev *dev) |
299 | 277 | { |
300 | 278 | |
... | ... | @@ -364,11 +342,13 @@ |
364 | 342 | static int __pci_save_msix_state(struct pci_dev *dev) |
365 | 343 | { |
366 | 344 | int pos; |
367 | - int temp; | |
368 | 345 | int irq, head, tail = 0; |
369 | 346 | u16 control; |
370 | 347 | struct pci_cap_saved_state *save_state; |
371 | 348 | |
349 | + if (!dev->msix_enabled) | |
350 | + return 0; | |
351 | + | |
372 | 352 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
373 | 353 | if (pos <= 0 || dev->no_msi) |
374 | 354 | return 0; |
... | ... | @@ -386,13 +366,7 @@ |
386 | 366 | *((u16 *)&save_state->data[0]) = control; |
387 | 367 | |
388 | 368 | /* save the table */ |
389 | - temp = dev->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; | |
369 | + irq = head = dev->first_msi_irq; | |
396 | 370 | while (head != tail) { |
397 | 371 | struct msi_desc *entry; |
398 | 372 | |
... | ... | @@ -402,7 +376,6 @@ |
402 | 376 | tail = msi_desc[irq]->link.tail; |
403 | 377 | irq = tail; |
404 | 378 | } |
405 | - dev->irq = temp; | |
406 | 379 | |
407 | 380 | save_state->cap_nr = PCI_CAP_ID_MSIX; |
408 | 381 | pci_add_saved_cap(dev, save_state); |
409 | 382 | |
... | ... | @@ -428,9 +401,11 @@ |
428 | 401 | int pos; |
429 | 402 | int irq, head, tail = 0; |
430 | 403 | struct msi_desc *entry; |
431 | - int temp; | |
432 | 404 | struct pci_cap_saved_state *save_state; |
433 | 405 | |
406 | + if (!dev->msix_enabled) | |
407 | + return; | |
408 | + | |
434 | 409 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_MSIX); |
435 | 410 | if (!save_state) |
436 | 411 | return; |
... | ... | @@ -443,10 +418,7 @@ |
443 | 418 | return; |
444 | 419 | |
445 | 420 | /* route the table */ |
446 | - temp = dev->irq; | |
447 | - if (msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) | |
448 | - return; | |
449 | - irq = head = dev->irq; | |
421 | + irq = head = dev->first_msi_irq; | |
450 | 422 | while (head != tail) { |
451 | 423 | entry = msi_desc[irq]; |
452 | 424 | write_msi_msg(irq, &entry->msg_save); |
... | ... | @@ -454,7 +426,6 @@ |
454 | 426 | tail = msi_desc[irq]->link.tail; |
455 | 427 | irq = tail; |
456 | 428 | } |
457 | - dev->irq = temp; | |
458 | 429 | |
459 | 430 | pci_write_config_word(dev, msi_control_reg(pos), save); |
460 | 431 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
... | ... | @@ -524,6 +495,7 @@ |
524 | 495 | return status; |
525 | 496 | } |
526 | 497 | |
498 | + dev->first_msi_irq = irq; | |
527 | 499 | attach_msi_entry(entry, irq); |
528 | 500 | /* Set MSI enabled bits */ |
529 | 501 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
... | ... | @@ -620,6 +592,7 @@ |
620 | 592 | avail = -EBUSY; |
621 | 593 | return avail; |
622 | 594 | } |
595 | + dev->first_msi_irq = entries[0].vector; | |
623 | 596 | /* Set MSI-X enabled bits */ |
624 | 597 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
625 | 598 | |
626 | 599 | |
... | ... | @@ -667,13 +640,11 @@ |
667 | 640 | **/ |
668 | 641 | int pci_enable_msi(struct pci_dev* dev) |
669 | 642 | { |
670 | - int pos, temp, status; | |
643 | + int pos, status; | |
671 | 644 | |
672 | 645 | if (pci_msi_supported(dev) < 0) |
673 | 646 | return -EINVAL; |
674 | 647 | |
675 | - temp = dev->irq; | |
676 | - | |
677 | 648 | status = msi_init(); |
678 | 649 | if (status < 0) |
679 | 650 | return status; |
680 | 651 | |
681 | 652 | |
682 | 653 | |
... | ... | @@ -682,15 +653,14 @@ |
682 | 653 | if (!pos) |
683 | 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 | 658 | /* Check whether driver already requested for MSI-X irqs */ |
688 | 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 | 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 | 663 | pci_name(dev)); |
693 | - dev->irq = temp; | |
694 | 664 | return -EINVAL; |
695 | 665 | } |
696 | 666 | status = msi_capability_init(dev); |
... | ... | @@ -709,6 +679,9 @@ |
709 | 679 | if (!dev) |
710 | 680 | return; |
711 | 681 | |
682 | + if (!dev->msi_enabled) | |
683 | + return; | |
684 | + | |
712 | 685 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
713 | 686 | if (!pos) |
714 | 687 | return; |
715 | 688 | |
716 | 689 | |
717 | 690 | |
718 | 691 | |
719 | 692 | |
... | ... | @@ -717,28 +690,30 @@ |
717 | 690 | if (!(control & PCI_MSI_FLAGS_ENABLE)) |
718 | 691 | return; |
719 | 692 | |
693 | + | |
720 | 694 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
721 | 695 | |
722 | 696 | spin_lock_irqsave(&msi_lock, flags); |
723 | - entry = msi_desc[dev->irq]; | |
697 | + entry = msi_desc[dev->first_msi_irq]; | |
724 | 698 | if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { |
725 | 699 | spin_unlock_irqrestore(&msi_lock, flags); |
726 | 700 | return; |
727 | 701 | } |
728 | - if (irq_has_action(dev->irq)) { | |
702 | + if (irq_has_action(dev->first_msi_irq)) { | |
729 | 703 | spin_unlock_irqrestore(&msi_lock, flags); |
730 | 704 | printk(KERN_WARNING "PCI: %s: pci_disable_msi() called without " |
731 | 705 | "free_irq() on MSI irq %d\n", |
732 | - pci_name(dev), dev->irq); | |
733 | - BUG_ON(irq_has_action(dev->irq)); | |
706 | + pci_name(dev), dev->first_msi_irq); | |
707 | + BUG_ON(irq_has_action(dev->first_msi_irq)); | |
734 | 708 | } else { |
735 | 709 | default_irq = entry->msi_attrib.default_irq; |
736 | 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 | 713 | /* Restore dev->irq to its default pin-assertion irq */ |
740 | 714 | dev->irq = default_irq; |
741 | 715 | } |
716 | + dev->first_msi_irq = 0; | |
742 | 717 | } |
743 | 718 | |
744 | 719 | static int msi_free_irq(struct pci_dev* dev, int irq) |
... | ... | @@ -797,7 +772,7 @@ |
797 | 772 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) |
798 | 773 | { |
799 | 774 | int status, pos, nr_entries; |
800 | - int i, j, temp; | |
775 | + int i, j; | |
801 | 776 | u16 control; |
802 | 777 | |
803 | 778 | if (!entries || pci_msi_supported(dev) < 0) |
804 | 779 | |
805 | 780 | |
... | ... | @@ -825,16 +800,14 @@ |
825 | 800 | return -EINVAL; /* duplicate entry */ |
826 | 801 | } |
827 | 802 | } |
828 | - temp = dev->irq; | |
829 | - WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)); | |
803 | + WARN_ON(!!dev->msix_enabled); | |
830 | 804 | |
831 | 805 | /* Check whether driver already requested for MSI irq */ |
832 | 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 | 808 | printk(KERN_INFO "PCI: %s: Can't enable MSI-X. " |
835 | 809 | "Device already has an MSI irq assigned\n", |
836 | 810 | pci_name(dev)); |
837 | - dev->irq = temp; | |
838 | 811 | return -EINVAL; |
839 | 812 | } |
840 | 813 | status = msix_capability_init(dev, entries, nvec); |
... | ... | @@ -843,7 +816,9 @@ |
843 | 816 | |
844 | 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 | 822 | u16 control; |
848 | 823 | |
849 | 824 | if (!pci_msi_enable) |
... | ... | @@ -851,6 +826,9 @@ |
851 | 826 | if (!dev) |
852 | 827 | return; |
853 | 828 | |
829 | + if (!dev->msix_enabled) | |
830 | + return; | |
831 | + | |
854 | 832 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
855 | 833 | if (!pos) |
856 | 834 | return; |
857 | 835 | |
... | ... | @@ -861,31 +839,25 @@ |
861 | 839 | |
862 | 840 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); |
863 | 841 | |
864 | - temp = dev->irq; | |
865 | - if (!msi_lookup_irq(dev, PCI_CAP_ID_MSIX)) { | |
866 | - int irq, head, tail = 0, warning = 0; | |
867 | - unsigned long flags; | |
868 | - | |
869 | - irq = head = dev->irq; | |
870 | - dev->irq = temp; /* Restore pin IRQ */ | |
871 | - while (head != tail) { | |
872 | - spin_lock_irqsave(&msi_lock, flags); | |
873 | - tail = msi_desc[irq]->link.tail; | |
874 | - spin_unlock_irqrestore(&msi_lock, flags); | |
875 | - if (irq_has_action(irq)) | |
876 | - warning = 1; | |
877 | - else if (irq != head) /* Release MSI-X irq */ | |
878 | - msi_free_irq(dev, irq); | |
879 | - irq = tail; | |
880 | - } | |
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 | - } | |
842 | + irq = head = dev->first_msi_irq; | |
843 | + while (head != tail) { | |
844 | + spin_lock_irqsave(&msi_lock, flags); | |
845 | + tail = msi_desc[irq]->link.tail; | |
846 | + spin_unlock_irqrestore(&msi_lock, flags); | |
847 | + if (irq_has_action(irq)) | |
848 | + warning = 1; | |
849 | + else if (irq != head) /* Release MSI-X irq */ | |
850 | + msi_free_irq(dev, irq); | |
851 | + irq = tail; | |
888 | 852 | } |
853 | + msi_free_irq(dev, irq); | |
854 | + if (warning) { | |
855 | + printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " | |
856 | + "free_irq() on all MSI-X irqs\n", | |
857 | + pci_name(dev)); | |
858 | + BUG_ON(warning > 0); | |
859 | + } | |
860 | + dev->first_msi_irq = 0; | |
889 | 861 | } |
890 | 862 | |
891 | 863 | /** |
892 | 864 | |
893 | 865 | |
894 | 866 | |
895 | 867 | |
896 | 868 | |
897 | 869 | |
... | ... | @@ -899,30 +871,28 @@ |
899 | 871 | **/ |
900 | 872 | void msi_remove_pci_irq_vectors(struct pci_dev* dev) |
901 | 873 | { |
902 | - int pos, temp; | |
874 | + int pos; | |
903 | 875 | unsigned long flags; |
904 | 876 | |
905 | 877 | if (!pci_msi_enable || !dev) |
906 | 878 | return; |
907 | 879 | |
908 | - temp = dev->irq; /* Save IOAPIC IRQ */ | |
909 | 880 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
910 | - if (pos > 0 && !msi_lookup_irq(dev, PCI_CAP_ID_MSI)) { | |
911 | - if (irq_has_action(dev->irq)) { | |
881 | + if (pos > 0 && dev->msi_enabled) { | |
882 | + if (irq_has_action(dev->first_msi_irq)) { | |
912 | 883 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " |
913 | 884 | "called without free_irq() on MSI irq %d\n", |
914 | - pci_name(dev), dev->irq); | |
915 | - BUG_ON(irq_has_action(dev->irq)); | |
885 | + pci_name(dev), dev->first_msi_irq); | |
886 | + BUG_ON(irq_has_action(dev->first_msi_irq)); | |
916 | 887 | } else /* Release MSI irq assigned to this device */ |
917 | - msi_free_irq(dev, dev->irq); | |
918 | - dev->irq = temp; /* Restore IOAPIC IRQ */ | |
888 | + msi_free_irq(dev, dev->first_msi_irq); | |
919 | 889 | } |
920 | 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 | 892 | int irq, head, tail = 0, warning = 0; |
923 | 893 | void __iomem *base = NULL; |
924 | 894 | |
925 | - irq = head = dev->irq; | |
895 | + irq = head = dev->first_msi_irq; | |
926 | 896 | while (head != tail) { |
927 | 897 | spin_lock_irqsave(&msi_lock, flags); |
928 | 898 | tail = msi_desc[irq]->link.tail; |
... | ... | @@ -942,7 +912,6 @@ |
942 | 912 | pci_name(dev)); |
943 | 913 | BUG_ON(warning > 0); |
944 | 914 | } |
945 | - dev->irq = temp; /* Restore IOAPIC IRQ */ | |
946 | 915 | } |
947 | 916 | } |
948 | 917 |
include/linux/pci.h
... | ... | @@ -174,6 +174,9 @@ |
174 | 174 | struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */ |
175 | 175 | int rom_attr_enabled; /* has display of the rom attribute been enabled? */ |
176 | 176 | struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ |
177 | +#ifdef CONFIG_PCI_MSI | |
178 | + unsigned int first_msi_irq; | |
179 | +#endif | |
177 | 180 | }; |
178 | 181 | |
179 | 182 | #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list) |