aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/msi.c122
1 files changed, 16 insertions, 106 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 27a057409eca..75d1c0dacffa 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -933,7 +933,6 @@ int pci_msi_supported(struct pci_dev * dev)
933int pci_enable_msi(struct pci_dev* dev) 933int pci_enable_msi(struct pci_dev* dev)
934{ 934{
935 int pos, temp, status; 935 int pos, temp, status;
936 u16 control;
937 936
938 if (pci_msi_supported(dev) < 0) 937 if (pci_msi_supported(dev) < 0)
939 return -EINVAL; 938 return -EINVAL;
@@ -948,27 +947,8 @@ int pci_enable_msi(struct pci_dev* dev)
948 if (!pos) 947 if (!pos)
949 return -EINVAL; 948 return -EINVAL;
950 949
951 if (!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { 950 WARN_ON(!msi_lookup_vector(dev, PCI_CAP_ID_MSI));
952 /* Lookup Sucess */
953 unsigned long flags;
954 951
955 pci_read_config_word(dev, msi_control_reg(pos), &control);
956 if (control & PCI_MSI_FLAGS_ENABLE)
957 return 0; /* Already in MSI mode */
958 spin_lock_irqsave(&msi_lock, flags);
959 if (!vector_irq[dev->irq]) {
960 msi_desc[dev->irq]->msi_attrib.state = 0;
961 vector_irq[dev->irq] = -1;
962 nr_released_vectors--;
963 spin_unlock_irqrestore(&msi_lock, flags);
964 status = msi_register_init(dev, msi_desc[dev->irq]);
965 if (status == 0)
966 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
967 return status;
968 }
969 spin_unlock_irqrestore(&msi_lock, flags);
970 dev->irq = temp;
971 }
972 /* Check whether driver already requested for MSI-X vectors */ 952 /* Check whether driver already requested for MSI-X vectors */
973 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); 953 pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
974 if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { 954 if (pos > 0 && !msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
@@ -1010,6 +990,8 @@ void pci_disable_msi(struct pci_dev* dev)
1010 if (!(control & PCI_MSI_FLAGS_ENABLE)) 990 if (!(control & PCI_MSI_FLAGS_ENABLE))
1011 return; 991 return;
1012 992
993 disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
994
1013 spin_lock_irqsave(&msi_lock, flags); 995 spin_lock_irqsave(&msi_lock, flags);
1014 entry = msi_desc[dev->irq]; 996 entry = msi_desc[dev->irq];
1015 if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) { 997 if (!entry || !entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
@@ -1023,14 +1005,12 @@ void pci_disable_msi(struct pci_dev* dev)
1023 pci_name(dev), dev->irq); 1005 pci_name(dev), dev->irq);
1024 BUG_ON(entry->msi_attrib.state > 0); 1006 BUG_ON(entry->msi_attrib.state > 0);
1025 } else { 1007 } else {
1026 vector_irq[dev->irq] = 0; /* free it */
1027 nr_released_vectors++;
1028 default_vector = entry->msi_attrib.default_vector; 1008 default_vector = entry->msi_attrib.default_vector;
1029 spin_unlock_irqrestore(&msi_lock, flags); 1009 spin_unlock_irqrestore(&msi_lock, flags);
1010 msi_free_vector(dev, dev->irq, 0);
1011
1030 /* Restore dev->irq to its default pin-assertion vector */ 1012 /* Restore dev->irq to its default pin-assertion vector */
1031 dev->irq = default_vector; 1013 dev->irq = default_vector;
1032 disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
1033 PCI_CAP_ID_MSI);
1034 } 1014 }
1035} 1015}
1036 1016
@@ -1078,57 +1058,6 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)
1078 return 0; 1058 return 0;
1079} 1059}
1080 1060
1081static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
1082{
1083 int vector = head, tail = 0;
1084 int i, j = 0, nr_entries = 0;
1085 void __iomem *base;
1086 unsigned long flags;
1087
1088 spin_lock_irqsave(&msi_lock, flags);
1089 while (head != tail) {
1090 nr_entries++;
1091 tail = msi_desc[vector]->link.tail;
1092 if (entries[0].entry == msi_desc[vector]->msi_attrib.entry_nr)
1093 j = vector;
1094 vector = tail;
1095 }
1096 if (*nvec > nr_entries) {
1097 spin_unlock_irqrestore(&msi_lock, flags);
1098 *nvec = nr_entries;
1099 return -EINVAL;
1100 }
1101 vector = ((j > 0) ? j : head);
1102 for (i = 0; i < *nvec; i++) {
1103 j = msi_desc[vector]->msi_attrib.entry_nr;
1104 msi_desc[vector]->msi_attrib.state = 0; /* Mark it not active */
1105 vector_irq[vector] = -1; /* Mark it busy */
1106 nr_released_vectors--;
1107 entries[i].vector = vector;
1108 if (j != (entries + i)->entry) {
1109 base = msi_desc[vector]->mask_base;
1110 msi_desc[vector]->msi_attrib.entry_nr =
1111 (entries + i)->entry;
1112 writel( readl(base + j * PCI_MSIX_ENTRY_SIZE +
1113 PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET), base +
1114 (entries + i)->entry * PCI_MSIX_ENTRY_SIZE +
1115 PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
1116 writel( readl(base + j * PCI_MSIX_ENTRY_SIZE +
1117 PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET), base +
1118 (entries + i)->entry * PCI_MSIX_ENTRY_SIZE +
1119 PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
1120 writel( (readl(base + j * PCI_MSIX_ENTRY_SIZE +
1121 PCI_MSIX_ENTRY_DATA_OFFSET) & 0xff00) | vector,
1122 base + (entries+i)->entry*PCI_MSIX_ENTRY_SIZE +
1123 PCI_MSIX_ENTRY_DATA_OFFSET);
1124 }
1125 vector = msi_desc[vector]->link.tail;
1126 }
1127 spin_unlock_irqrestore(&msi_lock, flags);
1128
1129 return 0;
1130}
1131
1132/** 1061/**
1133 * pci_enable_msix - configure device's MSI-X capability structure 1062 * pci_enable_msix - configure device's MSI-X capability structure
1134 * @dev: pointer to the pci_dev data structure of MSI-X device function 1063 * @dev: pointer to the pci_dev data structure of MSI-X device function
@@ -1163,9 +1092,6 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
1163 return -EINVAL; 1092 return -EINVAL;
1164 1093
1165 pci_read_config_word(dev, msi_control_reg(pos), &control); 1094 pci_read_config_word(dev, msi_control_reg(pos), &control);
1166 if (control & PCI_MSIX_FLAGS_ENABLE)
1167 return -EINVAL; /* Already in MSI-X mode */
1168
1169 nr_entries = multi_msix_capable(control); 1095 nr_entries = multi_msix_capable(control);
1170 if (nvec > nr_entries) 1096 if (nvec > nr_entries)
1171 return -EINVAL; 1097 return -EINVAL;
@@ -1180,19 +1106,8 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
1180 } 1106 }
1181 } 1107 }
1182 temp = dev->irq; 1108 temp = dev->irq;
1183 if (!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { 1109 WARN_ON(!msi_lookup_vector(dev, PCI_CAP_ID_MSIX));
1184 /* Lookup Sucess */ 1110
1185 nr_entries = nvec;
1186 /* Reroute MSI-X table */
1187 if (reroute_msix_table(dev->irq, entries, &nr_entries)) {
1188 /* #requested > #previous-assigned */
1189 dev->irq = temp;
1190 return nr_entries;
1191 }
1192 dev->irq = temp;
1193 enable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
1194 return 0;
1195 }
1196 /* Check whether driver already requested for MSI vector */ 1111 /* Check whether driver already requested for MSI vector */
1197 if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 && 1112 if (pci_find_capability(dev, PCI_CAP_ID_MSI) > 0 &&
1198 !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { 1113 !msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
@@ -1251,37 +1166,32 @@ void pci_disable_msix(struct pci_dev* dev)
1251 if (!(control & PCI_MSIX_FLAGS_ENABLE)) 1166 if (!(control & PCI_MSIX_FLAGS_ENABLE))
1252 return; 1167 return;
1253 1168
1169 disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
1170
1254 temp = dev->irq; 1171 temp = dev->irq;
1255 if (!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { 1172 if (!msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
1256 int state, vector, head, tail = 0, warning = 0; 1173 int state, vector, head, tail = 0, warning = 0;
1257 unsigned long flags; 1174 unsigned long flags;
1258 1175
1259 vector = head = dev->irq; 1176 vector = head = dev->irq;
1260 spin_lock_irqsave(&msi_lock, flags); 1177 dev->irq = temp; /* Restore pin IRQ */
1261 while (head != tail) { 1178 while (head != tail) {
1179 spin_lock_irqsave(&msi_lock, flags);
1262 state = msi_desc[vector]->msi_attrib.state; 1180 state = msi_desc[vector]->msi_attrib.state;
1181 tail = msi_desc[vector]->link.tail;
1182 spin_unlock_irqrestore(&msi_lock, flags);
1263 if (state) 1183 if (state)
1264 warning = 1; 1184 warning = 1;
1265 else { 1185 else if (vector != head) /* Release MSI-X vector */
1266 vector_irq[vector] = 0; /* free it */ 1186 msi_free_vector(dev, vector, 0);
1267 nr_released_vectors++;
1268 }
1269 tail = msi_desc[vector]->link.tail;
1270 vector = tail; 1187 vector = tail;
1271 } 1188 }
1272 spin_unlock_irqrestore(&msi_lock, flags); 1189 msi_free_vector(dev, vector, 0);
1273 if (warning) { 1190 if (warning) {
1274 dev->irq = temp;
1275 printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without " 1191 printk(KERN_WARNING "PCI: %s: pci_disable_msix() called without "
1276 "free_irq() on all MSI-X vectors\n", 1192 "free_irq() on all MSI-X vectors\n",
1277 pci_name(dev)); 1193 pci_name(dev));
1278 BUG_ON(warning > 0); 1194 BUG_ON(warning > 0);
1279 } else {
1280 dev->irq = temp;
1281 disable_msi_mode(dev,
1282 pci_find_capability(dev, PCI_CAP_ID_MSIX),
1283 PCI_CAP_ID_MSIX);
1284
1285 } 1195 }
1286 } 1196 }
1287} 1197}