diff options
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r-- | drivers/pci/msi.c | 105 |
1 files changed, 72 insertions, 33 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 48723d6fa60f..a77e79c8c82e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -103,9 +103,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
103 | switch (entry->msi_attrib.type) { | 103 | switch (entry->msi_attrib.type) { |
104 | case PCI_CAP_ID_MSI: | 104 | case PCI_CAP_ID_MSI: |
105 | { | 105 | { |
106 | int pos; | 106 | int pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI); |
107 | 107 | ||
108 | if (!(pos = pci_find_capability(entry->dev, PCI_CAP_ID_MSI))) | 108 | if (!pos) |
109 | return; | 109 | return; |
110 | 110 | ||
111 | pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), | 111 | pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), |
@@ -347,9 +347,9 @@ static int assign_msi_vector(void) | |||
347 | 347 | ||
348 | static int get_new_vector(void) | 348 | static int get_new_vector(void) |
349 | { | 349 | { |
350 | int vector; | 350 | int vector = assign_msi_vector(); |
351 | 351 | ||
352 | if ((vector = assign_msi_vector()) > 0) | 352 | if (vector > 0) |
353 | set_intr_gate(vector, interrupt[vector]); | 353 | set_intr_gate(vector, interrupt[vector]); |
354 | 354 | ||
355 | return vector; | 355 | return vector; |
@@ -369,7 +369,8 @@ static int msi_init(void) | |||
369 | return status; | 369 | return status; |
370 | } | 370 | } |
371 | 371 | ||
372 | if ((status = msi_cache_init()) < 0) { | 372 | status = msi_cache_init(); |
373 | if (status < 0) { | ||
373 | pci_msi_enable = 0; | 374 | pci_msi_enable = 0; |
374 | printk(KERN_WARNING "PCI: MSI cache init failed\n"); | 375 | printk(KERN_WARNING "PCI: MSI cache init failed\n"); |
375 | return status; | 376 | return status; |
@@ -523,10 +524,12 @@ static int msi_capability_init(struct pci_dev *dev) | |||
523 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 524 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
524 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 525 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
525 | /* MSI Entry Initialization */ | 526 | /* MSI Entry Initialization */ |
526 | if (!(entry = alloc_msi_entry())) | 527 | entry = alloc_msi_entry(); |
528 | if (!entry) | ||
527 | return -ENOMEM; | 529 | return -ENOMEM; |
528 | 530 | ||
529 | if ((vector = get_msi_vector(dev)) < 0) { | 531 | vector = get_msi_vector(dev); |
532 | if (vector < 0) { | ||
530 | kmem_cache_free(msi_cachep, entry); | 533 | kmem_cache_free(msi_cachep, entry); |
531 | return -EBUSY; | 534 | return -EBUSY; |
532 | } | 535 | } |
@@ -597,7 +600,8 @@ static int msix_capability_init(struct pci_dev *dev, | |||
597 | struct msg_address address; | 600 | struct msg_address address; |
598 | struct msg_data data; | 601 | struct msg_data data; |
599 | int vector, pos, i, j, nr_entries, temp = 0; | 602 | int vector, pos, i, j, nr_entries, temp = 0; |
600 | u32 phys_addr, table_offset; | 603 | unsigned long phys_addr; |
604 | u32 table_offset; | ||
601 | u16 control; | 605 | u16 control; |
602 | u8 bir; | 606 | u8 bir; |
603 | void __iomem *base; | 607 | void __iomem *base; |
@@ -606,11 +610,11 @@ static int msix_capability_init(struct pci_dev *dev, | |||
606 | /* Request & Map MSI-X table region */ | 610 | /* Request & Map MSI-X table region */ |
607 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 611 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
608 | nr_entries = multi_msix_capable(control); | 612 | nr_entries = multi_msix_capable(control); |
609 | pci_read_config_dword(dev, msix_table_offset_reg(pos), | 613 | |
610 | &table_offset); | 614 | pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); |
611 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | 615 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); |
612 | phys_addr = pci_resource_start (dev, bir); | 616 | table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; |
613 | phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK); | 617 | phys_addr = pci_resource_start (dev, bir) + table_offset; |
614 | base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); | 618 | base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); |
615 | if (base == NULL) | 619 | if (base == NULL) |
616 | return -ENOMEM; | 620 | return -ENOMEM; |
@@ -620,7 +624,8 @@ static int msix_capability_init(struct pci_dev *dev, | |||
620 | entry = alloc_msi_entry(); | 624 | entry = alloc_msi_entry(); |
621 | if (!entry) | 625 | if (!entry) |
622 | break; | 626 | break; |
623 | if ((vector = get_msi_vector(dev)) < 0) | 627 | vector = get_msi_vector(dev); |
628 | if (vector < 0) | ||
624 | break; | 629 | break; |
625 | 630 | ||
626 | j = entries[i].entry; | 631 | j = entries[i].entry; |
@@ -699,12 +704,17 @@ int pci_enable_msi(struct pci_dev* dev) | |||
699 | if (dev->no_msi) | 704 | if (dev->no_msi) |
700 | return status; | 705 | return status; |
701 | 706 | ||
707 | if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) | ||
708 | return -EINVAL; | ||
709 | |||
702 | temp = dev->irq; | 710 | temp = dev->irq; |
703 | 711 | ||
704 | if ((status = msi_init()) < 0) | 712 | status = msi_init(); |
713 | if (status < 0) | ||
705 | return status; | 714 | return status; |
706 | 715 | ||
707 | if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSI))) | 716 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
717 | if (!pos) | ||
708 | return -EINVAL; | 718 | return -EINVAL; |
709 | 719 | ||
710 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 720 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
@@ -728,8 +738,8 @@ int pci_enable_msi(struct pci_dev* dev) | |||
728 | dev->irq = temp; | 738 | dev->irq = temp; |
729 | } | 739 | } |
730 | /* Check whether driver already requested for MSI-X vectors */ | 740 | /* Check whether driver already requested for MSI-X vectors */ |
731 | if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 && | 741 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
732 | !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { | 742 | if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { |
733 | printk(KERN_INFO "PCI: %s: Can't enable MSI. " | 743 | printk(KERN_INFO "PCI: %s: Can't enable MSI. " |
734 | "Device already has MSI-X vectors assigned\n", | 744 | "Device already has MSI-X vectors assigned\n", |
735 | pci_name(dev)); | 745 | pci_name(dev)); |
@@ -755,7 +765,13 @@ void pci_disable_msi(struct pci_dev* dev) | |||
755 | u16 control; | 765 | u16 control; |
756 | unsigned long flags; | 766 | unsigned long flags; |
757 | 767 | ||
758 | if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSI))) | 768 | if (!pci_msi_enable) |
769 | return; | ||
770 | if (!dev) | ||
771 | return; | ||
772 | |||
773 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | ||
774 | if (!pos) | ||
759 | return; | 775 | return; |
760 | 776 | ||
761 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 777 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
@@ -826,8 +842,10 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) | |||
826 | * Detect last MSI-X vector to be released. | 842 | * Detect last MSI-X vector to be released. |
827 | * Release the MSI-X memory-mapped table. | 843 | * Release the MSI-X memory-mapped table. |
828 | */ | 844 | */ |
845 | #if 0 | ||
829 | int pos, nr_entries; | 846 | int pos, nr_entries; |
830 | u32 phys_addr, table_offset; | 847 | unsigned long phys_addr; |
848 | u32 table_offset; | ||
831 | u16 control; | 849 | u16 control; |
832 | u8 bir; | 850 | u8 bir; |
833 | 851 | ||
@@ -838,9 +856,12 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) | |||
838 | pci_read_config_dword(dev, msix_table_offset_reg(pos), | 856 | pci_read_config_dword(dev, msix_table_offset_reg(pos), |
839 | &table_offset); | 857 | &table_offset); |
840 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | 858 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); |
841 | phys_addr = pci_resource_start (dev, bir); | 859 | table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; |
842 | phys_addr += (u32)(table_offset & | 860 | phys_addr = pci_resource_start(dev, bir) + table_offset; |
843 | ~PCI_MSIX_FLAGS_BIRMASK); | 861 | /* |
862 | * FIXME! and what did you want to do with phys_addr? | ||
863 | */ | ||
864 | #endif | ||
844 | iounmap(base); | 865 | iounmap(base); |
845 | } | 866 | } |
846 | } | 867 | } |
@@ -924,10 +945,12 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
924 | if (!pci_msi_enable || !dev || !entries) | 945 | if (!pci_msi_enable || !dev || !entries) |
925 | return -EINVAL; | 946 | return -EINVAL; |
926 | 947 | ||
927 | if ((status = msi_init()) < 0) | 948 | status = msi_init(); |
949 | if (status < 0) | ||
928 | return status; | 950 | return status; |
929 | 951 | ||
930 | if (!(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX))) | 952 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
953 | if (!pos) | ||
931 | return -EINVAL; | 954 | return -EINVAL; |
932 | 955 | ||
933 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 956 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
@@ -1006,7 +1029,13 @@ void pci_disable_msix(struct pci_dev* dev) | |||
1006 | int pos, temp; | 1029 | int pos, temp; |
1007 | u16 control; | 1030 | u16 control; |
1008 | 1031 | ||
1009 | if (!dev || !(pos = pci_find_capability(dev, PCI_CAP_ID_MSIX))) | 1032 | if (!pci_msi_enable) |
1033 | return; | ||
1034 | if (!dev) | ||
1035 | return; | ||
1036 | |||
1037 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
1038 | if (!pos) | ||
1010 | return; | 1039 | return; |
1011 | 1040 | ||
1012 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 1041 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
@@ -1066,8 +1095,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
1066 | return; | 1095 | return; |
1067 | 1096 | ||
1068 | temp = dev->irq; /* Save IOAPIC IRQ */ | 1097 | temp = dev->irq; /* Save IOAPIC IRQ */ |
1069 | if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) > 0 && | 1098 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
1070 | !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { | 1099 | if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { |
1071 | spin_lock_irqsave(&msi_lock, flags); | 1100 | spin_lock_irqsave(&msi_lock, flags); |
1072 | state = msi_desc[dev->irq]->msi_attrib.state; | 1101 | state = msi_desc[dev->irq]->msi_attrib.state; |
1073 | spin_unlock_irqrestore(&msi_lock, flags); | 1102 | spin_unlock_irqrestore(&msi_lock, flags); |
@@ -1080,8 +1109,8 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
1080 | msi_free_vector(dev, dev->irq, 0); | 1109 | msi_free_vector(dev, dev->irq, 0); |
1081 | dev->irq = temp; /* Restore IOAPIC IRQ */ | 1110 | dev->irq = temp; /* Restore IOAPIC IRQ */ |
1082 | } | 1111 | } |
1083 | if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSIX)) > 0 && | 1112 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); |
1084 | !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { | 1113 | if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { |
1085 | int vector, head, tail = 0, warning = 0; | 1114 | int vector, head, tail = 0, warning = 0; |
1086 | void __iomem *base = NULL; | 1115 | void __iomem *base = NULL; |
1087 | 1116 | ||
@@ -1101,7 +1130,9 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
1101 | msi_free_vector(dev, vector, 0); | 1130 | msi_free_vector(dev, vector, 0); |
1102 | if (warning) { | 1131 | if (warning) { |
1103 | /* Force to release the MSI-X memory-mapped table */ | 1132 | /* Force to release the MSI-X memory-mapped table */ |
1104 | u32 phys_addr, table_offset; | 1133 | #if 0 |
1134 | unsigned long phys_addr; | ||
1135 | u32 table_offset; | ||
1105 | u16 control; | 1136 | u16 control; |
1106 | u8 bir; | 1137 | u8 bir; |
1107 | 1138 | ||
@@ -1110,9 +1141,12 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
1110 | pci_read_config_dword(dev, msix_table_offset_reg(pos), | 1141 | pci_read_config_dword(dev, msix_table_offset_reg(pos), |
1111 | &table_offset); | 1142 | &table_offset); |
1112 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | 1143 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); |
1113 | phys_addr = pci_resource_start (dev, bir); | 1144 | table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; |
1114 | phys_addr += (u32)(table_offset & | 1145 | phys_addr = pci_resource_start(dev, bir) + table_offset; |
1115 | ~PCI_MSIX_FLAGS_BIRMASK); | 1146 | /* |
1147 | * FIXME! and what did you want to do with phys_addr? | ||
1148 | */ | ||
1149 | #endif | ||
1116 | iounmap(base); | 1150 | iounmap(base); |
1117 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " | 1151 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " |
1118 | "called without free_irq() on all MSI-X vectors\n", | 1152 | "called without free_irq() on all MSI-X vectors\n", |
@@ -1123,6 +1157,11 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
1123 | } | 1157 | } |
1124 | } | 1158 | } |
1125 | 1159 | ||
1160 | void pci_no_msi(void) | ||
1161 | { | ||
1162 | pci_msi_enable = 0; | ||
1163 | } | ||
1164 | |||
1126 | EXPORT_SYMBOL(pci_enable_msi); | 1165 | EXPORT_SYMBOL(pci_enable_msi); |
1127 | EXPORT_SYMBOL(pci_disable_msi); | 1166 | EXPORT_SYMBOL(pci_disable_msi); |
1128 | EXPORT_SYMBOL(pci_enable_msix); | 1167 | EXPORT_SYMBOL(pci_enable_msix); |