aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/intr_remapping.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/intr_remapping.c')
-rw-r--r--drivers/pci/intr_remapping.c77
1 files changed, 75 insertions, 2 deletions
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 2de5a3238c94..f78371b22529 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -5,6 +5,7 @@
5#include <linux/pci.h> 5#include <linux/pci.h>
6#include <linux/irq.h> 6#include <linux/irq.h>
7#include <asm/io_apic.h> 7#include <asm/io_apic.h>
8#include <asm/smp.h>
8#include <linux/intel-iommu.h> 9#include <linux/intel-iommu.h>
9#include "intr_remapping.h" 10#include "intr_remapping.h"
10 11
@@ -19,17 +20,75 @@ struct irq_2_iommu {
19 u8 irte_mask; 20 u8 irte_mask;
20}; 21};
21 22
22static struct irq_2_iommu irq_2_iommuX[NR_IRQS]; 23#ifdef CONFIG_SPARSE_IRQ
24static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu)
25{
26 struct irq_2_iommu *iommu;
27 int node;
28
29 node = cpu_to_node(cpu);
30
31 iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
32 printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node);
33
34 return iommu;
35}
23 36
24static struct irq_2_iommu *irq_2_iommu(unsigned int irq) 37static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
25{ 38{
26 return (irq < nr_irqs) ? irq_2_iommuX + irq : NULL; 39 struct irq_desc *desc;
40
41 desc = irq_to_desc(irq);
42
43 if (WARN_ON_ONCE(!desc))
44 return NULL;
45
46 return desc->irq_2_iommu;
47}
48
49static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
50{
51 struct irq_desc *desc;
52 struct irq_2_iommu *irq_iommu;
53
54 /*
55 * alloc irq desc if not allocated already.
56 */
57 desc = irq_to_desc_alloc_cpu(irq, cpu);
58 if (!desc) {
59 printk(KERN_INFO "can not get irq_desc for %d\n", irq);
60 return NULL;
61 }
62
63 irq_iommu = desc->irq_2_iommu;
64
65 if (!irq_iommu)
66 desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu);
67
68 return desc->irq_2_iommu;
27} 69}
28 70
29static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) 71static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
30{ 72{
73 return irq_2_iommu_alloc_cpu(irq, boot_cpu_id);
74}
75
76#else /* !CONFIG_SPARSE_IRQ */
77
78static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
79
80static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
81{
82 if (irq < nr_irqs)
83 return &irq_2_iommuX[irq];
84
85 return NULL;
86}
87static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
88{
31 return irq_2_iommu(irq); 89 return irq_2_iommu(irq);
32} 90}
91#endif
33 92
34static DEFINE_SPINLOCK(irq_2_ir_lock); 93static DEFINE_SPINLOCK(irq_2_ir_lock);
35 94
@@ -86,9 +145,11 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
86 if (!count) 145 if (!count)
87 return -1; 146 return -1;
88 147
148#ifndef CONFIG_SPARSE_IRQ
89 /* protect irq_2_iommu_alloc later */ 149 /* protect irq_2_iommu_alloc later */
90 if (irq >= nr_irqs) 150 if (irq >= nr_irqs)
91 return -1; 151 return -1;
152#endif
92 153
93 /* 154 /*
94 * start the IRTE search from index 0. 155 * start the IRTE search from index 0.
@@ -130,6 +191,12 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
130 table->base[i].present = 1; 191 table->base[i].present = 1;
131 192
132 irq_iommu = irq_2_iommu_alloc(irq); 193 irq_iommu = irq_2_iommu_alloc(irq);
194 if (!irq_iommu) {
195 spin_unlock(&irq_2_ir_lock);
196 printk(KERN_ERR "can't allocate irq_2_iommu\n");
197 return -1;
198 }
199
133 irq_iommu->iommu = iommu; 200 irq_iommu->iommu = iommu;
134 irq_iommu->irte_index = index; 201 irq_iommu->irte_index = index;
135 irq_iommu->sub_handle = 0; 202 irq_iommu->sub_handle = 0;
@@ -177,6 +244,12 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
177 244
178 irq_iommu = irq_2_iommu_alloc(irq); 245 irq_iommu = irq_2_iommu_alloc(irq);
179 246
247 if (!irq_iommu) {
248 spin_unlock(&irq_2_ir_lock);
249 printk(KERN_ERR "can't allocate irq_2_iommu\n");
250 return -1;
251 }
252
180 irq_iommu->iommu = iommu; 253 irq_iommu->iommu = iommu;
181 irq_iommu->irte_index = index; 254 irq_iommu->irte_index = index;
182 irq_iommu->sub_handle = subhandle; 255 irq_iommu->sub_handle = subhandle;