| @@ -192,6 +192,9 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) · 191 unmodified lines |
| 192 | 192 | |
| 193 | 193 | static void __iomem *pci_msix_desc_addr(struct msi_desc *desc) |
| 194 | 194 | { |
| 195 | + if (desc->msi_attrib.is_virtual) |
| 196 | + return NULL; |
| 197 | + |
| 195 | 198 | return desc->mask_base + |
| 196 | 199 | desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
| 197 | 200 | } |
| @@ -206,14 +209,19 @@ static void __iomem *pci_msix_desc_addr(struct msi_desc *desc) · 8 unmodified lines |
| 206 | 209 | u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag) |
| 207 | 210 | { |
| 208 | 211 | u32 mask_bits = desc->masked; |
| 212 | + void __iomem *desc_addr; |
| 209 | 213 | |
| 210 | 214 | if (pci_msi_ignore_mask) |
| 211 | 215 | return 0; |
| 216 | + desc_addr = pci_msix_desc_addr(desc); |
| 217 | + if (!desc_addr) |
| 218 | + return 0; |
| 212 | 219 | |
| 213 | 220 | mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT; |
| 214 | 221 | if (flag) |
| 215 | 222 | mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT; |
| 216 | | − writel(mask_bits, pci_msix_desc_addr(desc) + PCI_MSIX_ENTRY_VECTOR_CTRL); |
| 223 | + |
| 224 | + writel(mask_bits, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL); |
| 217 | 225 | |
| 218 | 226 | return mask_bits; |
| 219 | 227 | } |
| @@ -273,6 +281,11 @@ void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) · 53 unmodified lines |
| 273 | 281 | if (entry->msi_attrib.is_msix) { |
| 274 | 282 | void __iomem *base = pci_msix_desc_addr(entry); |
| 275 | 283 | |
| 284 | + if (!base) { |
| 285 | + WARN_ON(1); |
| 286 | + return; |
| 287 | + } |
| 288 | + |
| 276 | 289 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR); |
| 277 | 290 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR); |
| 278 | 291 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA); |
| @@ -303,6 +316,9 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) · 24 unmodified lines |
| 303 | 316 | } else if (entry->msi_attrib.is_msix) { |
| 304 | 317 | void __iomem *base = pci_msix_desc_addr(entry); |
| 305 | 318 | |
| 319 | + if (!base) |
| 320 | + goto skip; |
| 321 | + |
| 306 | 322 | writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR); |
| 307 | 323 | writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR); |
| 308 | 324 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA); |
| @@ -327,7 +343,13 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) · 18 unmodified lines |
| 327 | 343 | msg->data); |
| 328 | 344 | } |
| 329 | 345 | } |
| 346 | + |
| 347 | +skip: |
| 330 | 348 | entry->msg = *msg; |
| 349 | + |
| 350 | + if (entry->write_msi_msg) |
| 351 | + entry->write_msi_msg(entry, entry->write_msi_msg_data); |
| 352 | + |
| 331 | 353 | } |
| 332 | 354 | |
| 333 | 355 | void pci_write_msi_msg(unsigned int irq, struct msi_msg *msg) |
| @@ -550,6 +572,7 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd) · 216 unmodified lines |
| 550 | 572 | |
| 551 | 573 | entry->msi_attrib.is_msix = 0; |
| 552 | 574 | entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT); |
| 575 | + entry->msi_attrib.is_virtual = 0; |
| 553 | 576 | entry->msi_attrib.entry_nr = 0; |
| 554 | 577 | entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT); |
| 555 | 578 | entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ |
| @@ -674,6 +697,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, · 118 unmodified lines |
| 674 | 697 | struct irq_affinity_desc *curmsk, *masks = NULL; |
| 675 | 698 | struct msi_desc *entry; |
| 676 | 699 | int ret, i; |
| 700 | + int vec_count = pci_msix_vec_count(dev); |
| 677 | 701 | |
| 678 | 702 | if (affd) |
| 679 | 703 | masks = irq_create_affinity_masks(nvec, affd); |
| @@ -696,6 +720,10 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, · 16 unmodified lines |
| 696 | 720 | entry->msi_attrib.entry_nr = entries[i].entry; |
| 697 | 721 | else |
| 698 | 722 | entry->msi_attrib.entry_nr = i; |
| 723 | + |
| 724 | + entry->msi_attrib.is_virtual = |
| 725 | + entry->msi_attrib.entry_nr >= vec_count; |
| 726 | + |
| 699 | 727 | entry->msi_attrib.default_irq = dev->irq; |
| 700 | 728 | entry->mask_base = base; |
| 701 | 729 | |
| @@ -714,12 +742,19 @@ static void msix_program_entries(struct pci_dev *dev, · 12 unmodified lines |
| 714 | 742 | { |
| 715 | 743 | struct msi_desc *entry; |
| 716 | 744 | int i = 0; |
| 745 | + void __iomem *desc_addr; |
| 717 | 746 | |
| 718 | 747 | for_each_pci_msi_entry(entry, dev) { |
| 719 | 748 | if (entries) |
| 720 | 749 | entries[i++].vector = entry->irq; |
| 721 | | − entry->masked = readl(pci_msix_desc_addr(entry) + |
| 722 | | − PCI_MSIX_ENTRY_VECTOR_CTRL); |
| 750 | + |
| 751 | + desc_addr = pci_msix_desc_addr(entry); |
| 752 | + if (desc_addr) |
| 753 | + entry->masked = readl(desc_addr + |
| 754 | + PCI_MSIX_ENTRY_VECTOR_CTRL); |
| 755 | + else |
| 756 | + entry->masked = 0; |
| 757 | + |
| 723 | 758 | msix_mask_irq(entry, 1); |
| 724 | 759 | } |
| 725 | 760 | } |
| @@ -932,7 +967,7 @@ int pci_msix_vec_count(struct pci_dev *dev) · 206 unmodified lines |
| 932 | 967 | EXPORT_SYMBOL(pci_msix_vec_count); |
| 933 | 968 | |
| 934 | 969 | static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, |
| 935 | | − int nvec, struct irq_affinity *affd) |
| 970 | + int nvec, struct irq_affinity *affd, int flags) |
| 936 | 971 | { |
| 937 | 972 | int nr_entries; |
| 938 | 973 | int i, j; |
| @@ -943,7 +978,7 @@ static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, · 4 unmodified lines |
| 943 | 978 | nr_entries = pci_msix_vec_count(dev); |
| 944 | 979 | if (nr_entries < 0) |
| 945 | 980 | return nr_entries; |
| 946 | | − if (nvec > nr_entries) |
| 981 | + if (nvec > nr_entries && !(flags & PCI_IRQ_VIRTUAL)) |
| 947 | 982 | return nr_entries; |
| 948 | 983 | |
| 949 | 984 | if (entries) { |
| @@ -1079,7 +1114,8 @@ EXPORT_SYMBOL(pci_enable_msi); · 129 unmodified lines |
| 1079 | 1114 | |
| 1080 | 1115 | static int __pci_enable_msix_range(struct pci_dev *dev, |
| 1081 | 1116 | struct msix_entry *entries, int minvec, |
| 1082 | | − int maxvec, struct irq_affinity *affd) |
| 1117 | + int maxvec, struct irq_affinity *affd, |
| 1118 | + int flags) |
| 1083 | 1119 | { |
| 1084 | 1120 | int rc, nvec = maxvec; |
| 1085 | 1121 | |
| @@ -1096,7 +1132,7 @@ static int __pci_enable_msix_range(struct pci_dev *dev, · 10 unmodified lines |
| 1096 | 1132 | return -ENOSPC; |
| 1097 | 1133 | } |
| 1098 | 1134 | |
| 1099 | | − rc = __pci_enable_msix(dev, entries, nvec, affd); |
| 1135 | + rc = __pci_enable_msix(dev, entries, nvec, affd, flags); |
| 1100 | 1136 | if (rc == 0) |
| 1101 | 1137 | return nvec; |
| 1102 | 1138 | |
| @@ -1127,7 +1163,7 @@ static int __pci_enable_msix_range(struct pci_dev *dev, · 24 unmodified lines |
| 1127 | 1163 | int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, |
| 1128 | 1164 | int minvec, int maxvec) |
| 1129 | 1165 | { |
| 1130 | | − return __pci_enable_msix_range(dev, entries, minvec, maxvec, NULL); |
| 1166 | + return __pci_enable_msix_range(dev, entries, minvec, maxvec, NULL, 0); |
| 1131 | 1167 | } |
| 1132 | 1168 | EXPORT_SYMBOL(pci_enable_msix_range); |
| 1133 | 1169 | |
| @@ -1167,7 +1203,7 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs, · 33 unmodified lines |
| 1167 | 1203 | |
| 1168 | 1204 | if (flags & PCI_IRQ_MSIX) { |
| 1169 | 1205 | msix_vecs = __pci_enable_msix_range(dev, NULL, min_vecs, |
| 1170 | | − max_vecs, affd); |
| 1206 | + max_vecs, affd, flags); |
| 1171 | 1207 | if (msix_vecs > 0) |
| 1172 | 1208 | return msix_vecs; |
| 1173 | 1209 | } |