diff options
| author | Bjorn Helgaas <bhelgaas@google.com> | 2016-10-05 15:00:21 -0400 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-10-05 15:00:21 -0400 |
| commit | bdf530984d10b6b88b10a6d03057409a3f1c6897 (patch) | |
| tree | 9ae670861f37cd57c21d92bf6fb1b50c4cacd2f6 | |
| parent | 69a06e49843b29b296689fa2a7fc320d81aa7c64 (diff) | |
| parent | 181ffd19cc9898f795646bf9a897072a419a51ed (diff) | |
Merge branch 'pci/host-vmd' into next
* pci/host-vmd:
x86/PCI: VMD: Move VMD driver to drivers/pci/host
x86/PCI: VMD: Synchronize with RCU freeing MSI IRQ descs
x86/PCI: VMD: Eliminate index member from IRQ list
x86/PCI: VMD: Eliminate vmd_vector member from list type
x86/PCI: VMD: Convert to use pci_alloc_irq_vectors() API
x86/PCI: VMD: Allocate IRQ lists with correct MSI-X count
PCI: Use positive flags in pci_alloc_irq_vectors()
PCI: Update "pci=resource_alignment" documentation
Conflicts:
drivers/pci/host/Kconfig
drivers/pci/host/Makefile
| -rw-r--r-- | Documentation/PCI/MSI-HOWTO.txt | 24 | ||||
| -rw-r--r-- | Documentation/kernel-parameters.txt | 4 | ||||
| -rw-r--r-- | arch/x86/Kconfig | 13 | ||||
| -rw-r--r-- | arch/x86/pci/Makefile | 2 | ||||
| -rw-r--r-- | drivers/pci/host/Kconfig | 16 | ||||
| -rw-r--r-- | drivers/pci/host/Makefile | 1 | ||||
| -rw-r--r-- | drivers/pci/host/vmd.c (renamed from arch/x86/pci/vmd.c) | 48 | ||||
| -rw-r--r-- | drivers/pci/msi.c | 15 | ||||
| -rw-r--r-- | include/linux/pci.h | 10 |
9 files changed, 66 insertions, 67 deletions
diff --git a/Documentation/PCI/MSI-HOWTO.txt b/Documentation/PCI/MSI-HOWTO.txt index c55df2911136..cd9c9f6a7cd9 100644 --- a/Documentation/PCI/MSI-HOWTO.txt +++ b/Documentation/PCI/MSI-HOWTO.txt | |||
| @@ -94,14 +94,11 @@ has a requirements for a minimum number of vectors the driver can pass a | |||
| 94 | min_vecs argument set to this limit, and the PCI core will return -ENOSPC | 94 | min_vecs argument set to this limit, and the PCI core will return -ENOSPC |
| 95 | if it can't meet the minimum number of vectors. | 95 | if it can't meet the minimum number of vectors. |
| 96 | 96 | ||
| 97 | The flags argument should normally be set to 0, but can be used to pass the | 97 | The flags argument is used to specify which type of interrupt can be used |
| 98 | PCI_IRQ_NOMSI and PCI_IRQ_NOMSIX flag in case a device claims to support | 98 | by the device and the driver (PCI_IRQ_LEGACY, PCI_IRQ_MSI, PCI_IRQ_MSIX). |
| 99 | MSI or MSI-X, but the support is broken, or to pass PCI_IRQ_NOLEGACY in | 99 | A convenient short-hand (PCI_IRQ_ALL_TYPES) is also available to ask for |
| 100 | case the device does not support legacy interrupt lines. | 100 | any possible kind of interrupt. If the PCI_IRQ_AFFINITY flag is set, |
| 101 | 101 | pci_alloc_irq_vectors() will spread the interrupts around the available CPUs. | |
| 102 | By default this function will spread the interrupts around the available | ||
| 103 | CPUs, but this feature can be disabled by passing the PCI_IRQ_NOAFFINITY | ||
| 104 | flag. | ||
| 105 | 102 | ||
| 106 | To get the Linux IRQ numbers passed to request_irq() and free_irq() and the | 103 | To get the Linux IRQ numbers passed to request_irq() and free_irq() and the |
| 107 | vectors, use the following function: | 104 | vectors, use the following function: |
| @@ -131,7 +128,7 @@ larger than the number supported by the device it will automatically be | |||
| 131 | capped to the supported limit, so there is no need to query the number of | 128 | capped to the supported limit, so there is no need to query the number of |
| 132 | vectors supported beforehand: | 129 | vectors supported beforehand: |
| 133 | 130 | ||
| 134 | nvec = pci_alloc_irq_vectors(pdev, 1, nvec, 0); | 131 | nvec = pci_alloc_irq_vectors(pdev, 1, nvec, PCI_IRQ_ALL_TYPES) |
| 135 | if (nvec < 0) | 132 | if (nvec < 0) |
| 136 | goto out_err; | 133 | goto out_err; |
| 137 | 134 | ||
| @@ -140,7 +137,7 @@ interrupts it can request a particular number of interrupts by passing that | |||
| 140 | number to pci_alloc_irq_vectors() function as both 'min_vecs' and | 137 | number to pci_alloc_irq_vectors() function as both 'min_vecs' and |
| 141 | 'max_vecs' parameters: | 138 | 'max_vecs' parameters: |
| 142 | 139 | ||
| 143 | ret = pci_alloc_irq_vectors(pdev, nvec, nvec, 0); | 140 | ret = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_ALL_TYPES); |
| 144 | if (ret < 0) | 141 | if (ret < 0) |
| 145 | goto out_err; | 142 | goto out_err; |
| 146 | 143 | ||
| @@ -148,15 +145,14 @@ The most notorious example of the request type described above is enabling | |||
| 148 | the single MSI mode for a device. It could be done by passing two 1s as | 145 | the single MSI mode for a device. It could be done by passing two 1s as |
| 149 | 'min_vecs' and 'max_vecs': | 146 | 'min_vecs' and 'max_vecs': |
| 150 | 147 | ||
| 151 | ret = pci_alloc_irq_vectors(pdev, 1, 1, 0); | 148 | ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); |
| 152 | if (ret < 0) | 149 | if (ret < 0) |
| 153 | goto out_err; | 150 | goto out_err; |
| 154 | 151 | ||
| 155 | Some devices might not support using legacy line interrupts, in which case | 152 | Some devices might not support using legacy line interrupts, in which case |
| 156 | the PCI_IRQ_NOLEGACY flag can be used to fail the request if the platform | 153 | the driver can specify that only MSI or MSI-X is acceptable: |
| 157 | can't provide MSI or MSI-X interrupts: | ||
| 158 | 154 | ||
| 159 | nvec = pci_alloc_irq_vectors(pdev, 1, nvec, PCI_IRQ_NOLEGACY); | 155 | nvec = pci_alloc_irq_vectors(pdev, 1, nvec, PCI_IRQ_MSI | PCI_IRQ_MSIX); |
| 160 | if (nvec < 0) | 156 | if (nvec < 0) |
| 161 | goto out_err; | 157 | goto out_err; |
| 162 | 158 | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 46c030a49186..a4f4d693e2c1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -3032,6 +3032,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 3032 | PAGE_SIZE is used as alignment. | 3032 | PAGE_SIZE is used as alignment. |
| 3033 | PCI-PCI bridge can be specified, if resource | 3033 | PCI-PCI bridge can be specified, if resource |
| 3034 | windows need to be expanded. | 3034 | windows need to be expanded. |
| 3035 | To specify the alignment for several | ||
| 3036 | instances of a device, the PCI vendor, | ||
| 3037 | device, subvendor, and subdevice may be | ||
| 3038 | specified, e.g., 4096@pci:8086:9c22:103c:198f | ||
| 3035 | ecrc= Enable/disable PCIe ECRC (transaction layer | 3039 | ecrc= Enable/disable PCIe ECRC (transaction layer |
| 3036 | end-to-end CRC checking). | 3040 | end-to-end CRC checking). |
| 3037 | bios: Use BIOS/firmware settings. This is the | 3041 | bios: Use BIOS/firmware settings. This is the |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5c6e7471b732..c32083808f27 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -2744,19 +2744,6 @@ config PMC_ATOM | |||
| 2744 | def_bool y | 2744 | def_bool y |
| 2745 | depends on PCI | 2745 | depends on PCI |
| 2746 | 2746 | ||
| 2747 | config VMD | ||
| 2748 | depends on PCI_MSI | ||
| 2749 | tristate "Volume Management Device Driver" | ||
| 2750 | default N | ||
| 2751 | ---help--- | ||
| 2752 | Adds support for the Intel Volume Management Device (VMD). VMD is a | ||
| 2753 | secondary PCI host bridge that allows PCI Express root ports, | ||
| 2754 | and devices attached to them, to be removed from the default | ||
| 2755 | PCI domain and placed within the VMD domain. This provides | ||
| 2756 | more bus resources than are otherwise possible with a | ||
| 2757 | single domain. If you know your system provides one of these and | ||
| 2758 | has devices attached to it, say Y; if you are not sure, say N. | ||
| 2759 | |||
| 2760 | source "net/Kconfig" | 2747 | source "net/Kconfig" |
| 2761 | 2748 | ||
| 2762 | source "drivers/Kconfig" | 2749 | source "drivers/Kconfig" |
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile index 97062a635b77..5c6fc3577a49 100644 --- a/arch/x86/pci/Makefile +++ b/arch/x86/pci/Makefile | |||
| @@ -23,8 +23,6 @@ obj-y += bus_numa.o | |||
| 23 | obj-$(CONFIG_AMD_NB) += amd_bus.o | 23 | obj-$(CONFIG_AMD_NB) += amd_bus.o |
| 24 | obj-$(CONFIG_PCI_CNB20LE_QUIRK) += broadcom_bus.o | 24 | obj-$(CONFIG_PCI_CNB20LE_QUIRK) += broadcom_bus.o |
| 25 | 25 | ||
| 26 | obj-$(CONFIG_VMD) += vmd.o | ||
| 27 | |||
| 28 | ifeq ($(CONFIG_PCI_DEBUG),y) | 26 | ifeq ($(CONFIG_PCI_DEBUG),y) |
| 29 | EXTRA_CFLAGS += -DDEBUG | 27 | EXTRA_CFLAGS += -DDEBUG |
| 30 | endif | 28 | endif |
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 90f5e89854be..d7e7c0a827c3 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
| @@ -285,4 +285,20 @@ config PCIE_ROCKCHIP | |||
| 285 | There is 1 internal PCIe port available to support GEN2 with | 285 | There is 1 internal PCIe port available to support GEN2 with |
| 286 | 4 slots. | 286 | 4 slots. |
| 287 | 287 | ||
| 288 | config VMD | ||
| 289 | depends on PCI_MSI && X86_64 | ||
| 290 | tristate "Intel Volume Management Device Driver" | ||
| 291 | default N | ||
| 292 | ---help--- | ||
| 293 | Adds support for the Intel Volume Management Device (VMD). VMD is a | ||
| 294 | secondary PCI host bridge that allows PCI Express root ports, | ||
| 295 | and devices attached to them, to be removed from the default | ||
| 296 | PCI domain and placed within the VMD domain. This provides | ||
| 297 | more bus resources than are otherwise possible with a | ||
| 298 | single domain. If you know your system provides one of these and | ||
| 299 | has devices attached to it, say Y; if you are not sure, say N. | ||
| 300 | |||
| 301 | To compile this driver as a module, choose M here: the | ||
| 302 | module will be called vmd. | ||
| 303 | |||
| 288 | endmenu | 304 | endmenu |
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index a8afc16b0299..084cb4983645 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile | |||
| @@ -32,3 +32,4 @@ obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o | |||
| 32 | obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o | 32 | obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o |
| 33 | obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o | 33 | obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o |
| 34 | obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o | 34 | obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o |
| 35 | obj-$(CONFIG_VMD) += vmd.o | ||
diff --git a/arch/x86/pci/vmd.c b/drivers/pci/host/vmd.c index a021b7b0eb69..ca99fb4f7292 100644 --- a/arch/x86/pci/vmd.c +++ b/drivers/pci/host/vmd.c | |||
| @@ -56,16 +56,11 @@ struct vmd_irq { | |||
| 56 | /** | 56 | /** |
| 57 | * struct vmd_irq_list - list of driver requested IRQs mapping to a VMD vector | 57 | * struct vmd_irq_list - list of driver requested IRQs mapping to a VMD vector |
| 58 | * @irq_list: the list of irq's the VMD one demuxes to. | 58 | * @irq_list: the list of irq's the VMD one demuxes to. |
| 59 | * @vmd_vector: the h/w IRQ assigned to the VMD. | ||
| 60 | * @index: index into the VMD MSI-X table; used for message routing. | ||
| 61 | * @count: number of child IRQs assigned to this vector; used to track | 59 | * @count: number of child IRQs assigned to this vector; used to track |
| 62 | * sharing. | 60 | * sharing. |
| 63 | */ | 61 | */ |
| 64 | struct vmd_irq_list { | 62 | struct vmd_irq_list { |
| 65 | struct list_head irq_list; | 63 | struct list_head irq_list; |
| 66 | struct vmd_dev *vmd; | ||
| 67 | unsigned int vmd_vector; | ||
| 68 | unsigned int index; | ||
| 69 | unsigned int count; | 64 | unsigned int count; |
| 70 | }; | 65 | }; |
| 71 | 66 | ||
| @@ -76,7 +71,6 @@ struct vmd_dev { | |||
| 76 | char __iomem *cfgbar; | 71 | char __iomem *cfgbar; |
| 77 | 72 | ||
| 78 | int msix_count; | 73 | int msix_count; |
| 79 | struct msix_entry *msix_entries; | ||
| 80 | struct vmd_irq_list *irqs; | 74 | struct vmd_irq_list *irqs; |
| 81 | 75 | ||
| 82 | struct pci_sysdata sysdata; | 76 | struct pci_sysdata sysdata; |
| @@ -95,6 +89,12 @@ static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus) | |||
| 95 | return container_of(bus->sysdata, struct vmd_dev, sysdata); | 89 | return container_of(bus->sysdata, struct vmd_dev, sysdata); |
| 96 | } | 90 | } |
| 97 | 91 | ||
| 92 | static inline unsigned int index_from_irqs(struct vmd_dev *vmd, | ||
| 93 | struct vmd_irq_list *irqs) | ||
| 94 | { | ||
| 95 | return irqs - vmd->irqs; | ||
| 96 | } | ||
| 97 | |||
| 98 | /* | 98 | /* |
| 99 | * Drivers managing a device in a VMD domain allocate their own IRQs as before, | 99 | * Drivers managing a device in a VMD domain allocate their own IRQs as before, |
| 100 | * but the MSI entry for the hardware it's driving will be programmed with a | 100 | * but the MSI entry for the hardware it's driving will be programmed with a |
| @@ -107,9 +107,11 @@ static void vmd_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | |||
| 107 | { | 107 | { |
| 108 | struct vmd_irq *vmdirq = data->chip_data; | 108 | struct vmd_irq *vmdirq = data->chip_data; |
| 109 | struct vmd_irq_list *irq = vmdirq->irq; | 109 | struct vmd_irq_list *irq = vmdirq->irq; |
| 110 | struct vmd_dev *vmd = irq_data_get_irq_handler_data(data); | ||
| 110 | 111 | ||
| 111 | msg->address_hi = MSI_ADDR_BASE_HI; | 112 | msg->address_hi = MSI_ADDR_BASE_HI; |
| 112 | msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_DEST_ID(irq->index); | 113 | msg->address_lo = MSI_ADDR_BASE_LO | |
| 114 | MSI_ADDR_DEST_ID(index_from_irqs(vmd, irq)); | ||
| 113 | msg->data = 0; | 115 | msg->data = 0; |
| 114 | } | 116 | } |
| 115 | 117 | ||
| @@ -194,6 +196,7 @@ static int vmd_msi_init(struct irq_domain *domain, struct msi_domain_info *info, | |||
| 194 | struct msi_desc *desc = arg->desc; | 196 | struct msi_desc *desc = arg->desc; |
| 195 | struct vmd_dev *vmd = vmd_from_bus(msi_desc_to_pci_dev(desc)->bus); | 197 | struct vmd_dev *vmd = vmd_from_bus(msi_desc_to_pci_dev(desc)->bus); |
| 196 | struct vmd_irq *vmdirq = kzalloc(sizeof(*vmdirq), GFP_KERNEL); | 198 | struct vmd_irq *vmdirq = kzalloc(sizeof(*vmdirq), GFP_KERNEL); |
| 199 | unsigned int index, vector; | ||
| 197 | 200 | ||
| 198 | if (!vmdirq) | 201 | if (!vmdirq) |
| 199 | return -ENOMEM; | 202 | return -ENOMEM; |
| @@ -201,9 +204,11 @@ static int vmd_msi_init(struct irq_domain *domain, struct msi_domain_info *info, | |||
| 201 | INIT_LIST_HEAD(&vmdirq->node); | 204 | INIT_LIST_HEAD(&vmdirq->node); |
| 202 | vmdirq->irq = vmd_next_irq(vmd, desc); | 205 | vmdirq->irq = vmd_next_irq(vmd, desc); |
| 203 | vmdirq->virq = virq; | 206 | vmdirq->virq = virq; |
| 207 | index = index_from_irqs(vmd, vmdirq->irq); | ||
| 208 | vector = pci_irq_vector(vmd->dev, index); | ||
| 204 | 209 | ||
| 205 | irq_domain_set_info(domain, virq, vmdirq->irq->vmd_vector, info->chip, | 210 | irq_domain_set_info(domain, virq, vector, info->chip, vmdirq, |
| 206 | vmdirq, handle_untracked_irq, vmd, NULL); | 211 | handle_untracked_irq, vmd, NULL); |
| 207 | return 0; | 212 | return 0; |
| 208 | } | 213 | } |
| 209 | 214 | ||
| @@ -213,6 +218,8 @@ static void vmd_msi_free(struct irq_domain *domain, | |||
| 213 | struct vmd_irq *vmdirq = irq_get_chip_data(virq); | 218 | struct vmd_irq *vmdirq = irq_get_chip_data(virq); |
| 214 | unsigned long flags; | 219 | unsigned long flags; |
| 215 | 220 | ||
| 221 | synchronize_rcu(); | ||
| 222 | |||
| 216 | /* XXX: Potential optimization to rebalance */ | 223 | /* XXX: Potential optimization to rebalance */ |
| 217 | raw_spin_lock_irqsave(&list_lock, flags); | 224 | raw_spin_lock_irqsave(&list_lock, flags); |
| 218 | vmdirq->irq->count--; | 225 | vmdirq->irq->count--; |
| @@ -672,30 +679,19 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 672 | if (vmd->msix_count < 0) | 679 | if (vmd->msix_count < 0) |
| 673 | return -ENODEV; | 680 | return -ENODEV; |
| 674 | 681 | ||
| 682 | vmd->msix_count = pci_alloc_irq_vectors(dev, 1, vmd->msix_count, | ||
| 683 | PCI_IRQ_MSIX | PCI_IRQ_AFFINITY); | ||
| 684 | if (vmd->msix_count < 0) | ||
| 685 | return vmd->msix_count; | ||
| 686 | |||
| 675 | vmd->irqs = devm_kcalloc(&dev->dev, vmd->msix_count, sizeof(*vmd->irqs), | 687 | vmd->irqs = devm_kcalloc(&dev->dev, vmd->msix_count, sizeof(*vmd->irqs), |
| 676 | GFP_KERNEL); | 688 | GFP_KERNEL); |
| 677 | if (!vmd->irqs) | 689 | if (!vmd->irqs) |
| 678 | return -ENOMEM; | 690 | return -ENOMEM; |
| 679 | 691 | ||
| 680 | vmd->msix_entries = devm_kcalloc(&dev->dev, vmd->msix_count, | ||
| 681 | sizeof(*vmd->msix_entries), | ||
| 682 | GFP_KERNEL); | ||
| 683 | if (!vmd->msix_entries) | ||
| 684 | return -ENOMEM; | ||
| 685 | for (i = 0; i < vmd->msix_count; i++) | ||
| 686 | vmd->msix_entries[i].entry = i; | ||
| 687 | |||
| 688 | vmd->msix_count = pci_enable_msix_range(vmd->dev, vmd->msix_entries, 1, | ||
| 689 | vmd->msix_count); | ||
| 690 | if (vmd->msix_count < 0) | ||
| 691 | return vmd->msix_count; | ||
| 692 | |||
| 693 | for (i = 0; i < vmd->msix_count; i++) { | 692 | for (i = 0; i < vmd->msix_count; i++) { |
| 694 | INIT_LIST_HEAD(&vmd->irqs[i].irq_list); | 693 | INIT_LIST_HEAD(&vmd->irqs[i].irq_list); |
| 695 | vmd->irqs[i].vmd_vector = vmd->msix_entries[i].vector; | 694 | err = devm_request_irq(&dev->dev, pci_irq_vector(dev, i), |
| 696 | vmd->irqs[i].index = i; | ||
| 697 | |||
| 698 | err = devm_request_irq(&dev->dev, vmd->irqs[i].vmd_vector, | ||
| 699 | vmd_irq, 0, "vmd", &vmd->irqs[i]); | 695 | vmd_irq, 0, "vmd", &vmd->irqs[i]); |
| 700 | if (err) | 696 | if (err) |
| 701 | return err; | 697 | return err; |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index a02981efdad5..9233e7f62f47 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
| @@ -1069,7 +1069,7 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, | |||
| 1069 | nvec = maxvec; | 1069 | nvec = maxvec; |
| 1070 | 1070 | ||
| 1071 | for (;;) { | 1071 | for (;;) { |
| 1072 | if (!(flags & PCI_IRQ_NOAFFINITY)) { | 1072 | if (flags & PCI_IRQ_AFFINITY) { |
| 1073 | dev->irq_affinity = irq_create_affinity_mask(&nvec); | 1073 | dev->irq_affinity = irq_create_affinity_mask(&nvec); |
| 1074 | if (nvec < minvec) | 1074 | if (nvec < minvec) |
| 1075 | return -ENOSPC; | 1075 | return -ENOSPC; |
| @@ -1105,7 +1105,7 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec, | |||
| 1105 | **/ | 1105 | **/ |
| 1106 | int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) | 1106 | int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) |
| 1107 | { | 1107 | { |
| 1108 | return __pci_enable_msi_range(dev, minvec, maxvec, PCI_IRQ_NOAFFINITY); | 1108 | return __pci_enable_msi_range(dev, minvec, maxvec, 0); |
| 1109 | } | 1109 | } |
| 1110 | EXPORT_SYMBOL(pci_enable_msi_range); | 1110 | EXPORT_SYMBOL(pci_enable_msi_range); |
| 1111 | 1111 | ||
| @@ -1120,7 +1120,7 @@ static int __pci_enable_msix_range(struct pci_dev *dev, | |||
| 1120 | return -ERANGE; | 1120 | return -ERANGE; |
| 1121 | 1121 | ||
| 1122 | for (;;) { | 1122 | for (;;) { |
| 1123 | if (!(flags & PCI_IRQ_NOAFFINITY)) { | 1123 | if (flags & PCI_IRQ_AFFINITY) { |
| 1124 | dev->irq_affinity = irq_create_affinity_mask(&nvec); | 1124 | dev->irq_affinity = irq_create_affinity_mask(&nvec); |
| 1125 | if (nvec < minvec) | 1125 | if (nvec < minvec) |
| 1126 | return -ENOSPC; | 1126 | return -ENOSPC; |
| @@ -1160,8 +1160,7 @@ static int __pci_enable_msix_range(struct pci_dev *dev, | |||
| 1160 | int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, | 1160 | int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, |
| 1161 | int minvec, int maxvec) | 1161 | int minvec, int maxvec) |
| 1162 | { | 1162 | { |
| 1163 | return __pci_enable_msix_range(dev, entries, minvec, maxvec, | 1163 | return __pci_enable_msix_range(dev, entries, minvec, maxvec, 0); |
| 1164 | PCI_IRQ_NOAFFINITY); | ||
| 1165 | } | 1164 | } |
| 1166 | EXPORT_SYMBOL(pci_enable_msix_range); | 1165 | EXPORT_SYMBOL(pci_enable_msix_range); |
| 1167 | 1166 | ||
| @@ -1187,21 +1186,21 @@ int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, | |||
| 1187 | { | 1186 | { |
| 1188 | int vecs = -ENOSPC; | 1187 | int vecs = -ENOSPC; |
| 1189 | 1188 | ||
| 1190 | if (!(flags & PCI_IRQ_NOMSIX)) { | 1189 | if (flags & PCI_IRQ_MSIX) { |
| 1191 | vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs, | 1190 | vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs, |
| 1192 | flags); | 1191 | flags); |
| 1193 | if (vecs > 0) | 1192 | if (vecs > 0) |
| 1194 | return vecs; | 1193 | return vecs; |
| 1195 | } | 1194 | } |
| 1196 | 1195 | ||
| 1197 | if (!(flags & PCI_IRQ_NOMSI)) { | 1196 | if (flags & PCI_IRQ_MSI) { |
| 1198 | vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, flags); | 1197 | vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, flags); |
| 1199 | if (vecs > 0) | 1198 | if (vecs > 0) |
| 1200 | return vecs; | 1199 | return vecs; |
| 1201 | } | 1200 | } |
| 1202 | 1201 | ||
| 1203 | /* use legacy irq if allowed */ | 1202 | /* use legacy irq if allowed */ |
| 1204 | if (!(flags & PCI_IRQ_NOLEGACY) && min_vecs == 1) | 1203 | if ((flags & PCI_IRQ_LEGACY) && min_vecs == 1) |
| 1205 | return 1; | 1204 | return 1; |
| 1206 | return vecs; | 1205 | return vecs; |
| 1207 | } | 1206 | } |
diff --git a/include/linux/pci.h b/include/linux/pci.h index b0e4ed19b315..bcde6d4a04ce 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -1264,10 +1264,12 @@ resource_size_t pcibios_iov_resource_alignment(struct pci_dev *dev, int resno); | |||
| 1264 | int pci_set_vga_state(struct pci_dev *pdev, bool decode, | 1264 | int pci_set_vga_state(struct pci_dev *pdev, bool decode, |
| 1265 | unsigned int command_bits, u32 flags); | 1265 | unsigned int command_bits, u32 flags); |
| 1266 | 1266 | ||
| 1267 | #define PCI_IRQ_NOLEGACY (1 << 0) /* don't use legacy interrupts */ | 1267 | #define PCI_IRQ_LEGACY (1 << 0) /* allow legacy interrupts */ |
| 1268 | #define PCI_IRQ_NOMSI (1 << 1) /* don't use MSI interrupts */ | 1268 | #define PCI_IRQ_MSI (1 << 1) /* allow MSI interrupts */ |
| 1269 | #define PCI_IRQ_NOMSIX (1 << 2) /* don't use MSI-X interrupts */ | 1269 | #define PCI_IRQ_MSIX (1 << 2) /* allow MSI-X interrupts */ |
| 1270 | #define PCI_IRQ_NOAFFINITY (1 << 3) /* don't auto-assign affinity */ | 1270 | #define PCI_IRQ_AFFINITY (1 << 3) /* auto-assign affinity */ |
| 1271 | #define PCI_IRQ_ALL_TYPES \ | ||
| 1272 | (PCI_IRQ_LEGACY | PCI_IRQ_MSI | PCI_IRQ_MSIX) | ||
| 1271 | 1273 | ||
| 1272 | /* kmem_cache style wrapper around pci_alloc_consistent() */ | 1274 | /* kmem_cache style wrapper around pci_alloc_consistent() */ |
| 1273 | 1275 | ||
