diff options
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 5 | ||||
-rw-r--r-- | drivers/irqchip/irq-armada-370-xp.c | 54 | ||||
-rw-r--r-- | drivers/irqchip/irq-crossbar.c | 2 | ||||
-rw-r--r-- | include/linux/interrupt.h | 4 | ||||
-rw-r--r-- | include/linux/irq.h | 2 | ||||
-rw-r--r-- | kernel/irq/irqdesc.c | 7 | ||||
-rw-r--r-- | kernel/softirq.c | 5 |
7 files changed, 42 insertions, 37 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 6ad4658de705..d23aa82e7a7b 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -3425,6 +3425,11 @@ int get_nr_irqs_gsi(void) | |||
3425 | return nr_irqs_gsi; | 3425 | return nr_irqs_gsi; |
3426 | } | 3426 | } |
3427 | 3427 | ||
3428 | unsigned int arch_dynirq_lower_bound(unsigned int from) | ||
3429 | { | ||
3430 | return from < nr_irqs_gsi ? nr_irqs_gsi : from; | ||
3431 | } | ||
3432 | |||
3428 | int __init arch_probe_nr_irqs(void) | 3433 | int __init arch_probe_nr_irqs(void) |
3429 | { | 3434 | { |
3430 | int nr; | 3435 | int nr; |
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 41be897df8d5..3899ba7821c5 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) | 41 | #define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) |
42 | #define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) | 42 | #define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) |
43 | #define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) | 43 | #define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) |
44 | #define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF | ||
44 | 45 | ||
45 | #define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) | 46 | #define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) |
46 | #define ARMADA_375_PPI_CAUSE (0x10) | 47 | #define ARMADA_375_PPI_CAUSE (0x10) |
@@ -132,8 +133,7 @@ static int armada_370_xp_setup_msi_irq(struct msi_chip *chip, | |||
132 | struct msi_desc *desc) | 133 | struct msi_desc *desc) |
133 | { | 134 | { |
134 | struct msi_msg msg; | 135 | struct msi_msg msg; |
135 | irq_hw_number_t hwirq; | 136 | int virq, hwirq; |
136 | int virq; | ||
137 | 137 | ||
138 | hwirq = armada_370_xp_alloc_msi(); | 138 | hwirq = armada_370_xp_alloc_msi(); |
139 | if (hwirq < 0) | 139 | if (hwirq < 0) |
@@ -159,8 +159,19 @@ static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip, | |||
159 | unsigned int irq) | 159 | unsigned int irq) |
160 | { | 160 | { |
161 | struct irq_data *d = irq_get_irq_data(irq); | 161 | struct irq_data *d = irq_get_irq_data(irq); |
162 | unsigned long hwirq = d->hwirq; | ||
163 | |||
162 | irq_dispose_mapping(irq); | 164 | irq_dispose_mapping(irq); |
163 | armada_370_xp_free_msi(d->hwirq); | 165 | armada_370_xp_free_msi(hwirq); |
166 | } | ||
167 | |||
168 | static int armada_370_xp_check_msi_device(struct msi_chip *chip, struct pci_dev *dev, | ||
169 | int nvec, int type) | ||
170 | { | ||
171 | /* We support MSI, but not MSI-X */ | ||
172 | if (type == PCI_CAP_ID_MSI) | ||
173 | return 0; | ||
174 | return -EINVAL; | ||
164 | } | 175 | } |
165 | 176 | ||
166 | static struct irq_chip armada_370_xp_msi_irq_chip = { | 177 | static struct irq_chip armada_370_xp_msi_irq_chip = { |
@@ -201,6 +212,7 @@ static int armada_370_xp_msi_init(struct device_node *node, | |||
201 | 212 | ||
202 | msi_chip->setup_irq = armada_370_xp_setup_msi_irq; | 213 | msi_chip->setup_irq = armada_370_xp_setup_msi_irq; |
203 | msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq; | 214 | msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq; |
215 | msi_chip->check_device = armada_370_xp_check_msi_device; | ||
204 | msi_chip->of_node = node; | 216 | msi_chip->of_node = node; |
205 | 217 | ||
206 | armada_370_xp_msi_domain = | 218 | armada_370_xp_msi_domain = |
@@ -244,35 +256,18 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock); | |||
244 | static int armada_xp_set_affinity(struct irq_data *d, | 256 | static int armada_xp_set_affinity(struct irq_data *d, |
245 | const struct cpumask *mask_val, bool force) | 257 | const struct cpumask *mask_val, bool force) |
246 | { | 258 | { |
247 | unsigned long reg; | ||
248 | unsigned long new_mask = 0; | ||
249 | unsigned long online_mask = 0; | ||
250 | unsigned long count = 0; | ||
251 | irq_hw_number_t hwirq = irqd_to_hwirq(d); | 259 | irq_hw_number_t hwirq = irqd_to_hwirq(d); |
260 | unsigned long reg, mask; | ||
252 | int cpu; | 261 | int cpu; |
253 | 262 | ||
254 | for_each_cpu(cpu, mask_val) { | 263 | /* Select a single core from the affinity mask which is online */ |
255 | new_mask |= 1 << cpu_logical_map(cpu); | 264 | cpu = cpumask_any_and(mask_val, cpu_online_mask); |
256 | count++; | 265 | mask = 1UL << cpu_logical_map(cpu); |
257 | } | ||
258 | |||
259 | /* | ||
260 | * Forbid mutlicore interrupt affinity | ||
261 | * This is required since the MPIC HW doesn't limit | ||
262 | * several CPUs from acknowledging the same interrupt. | ||
263 | */ | ||
264 | if (count > 1) | ||
265 | return -EINVAL; | ||
266 | |||
267 | for_each_cpu(cpu, cpu_online_mask) | ||
268 | online_mask |= 1 << cpu_logical_map(cpu); | ||
269 | 266 | ||
270 | raw_spin_lock(&irq_controller_lock); | 267 | raw_spin_lock(&irq_controller_lock); |
271 | |||
272 | reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); | 268 | reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); |
273 | reg = (reg & (~online_mask)) | new_mask; | 269 | reg = (reg & (~ARMADA_370_XP_INT_SOURCE_CPU_MASK)) | mask; |
274 | writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); | 270 | writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); |
275 | |||
276 | raw_spin_unlock(&irq_controller_lock); | 271 | raw_spin_unlock(&irq_controller_lock); |
277 | 272 | ||
278 | return 0; | 273 | return 0; |
@@ -494,15 +489,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, | |||
494 | 489 | ||
495 | #ifdef CONFIG_SMP | 490 | #ifdef CONFIG_SMP |
496 | armada_xp_mpic_smp_cpu_init(); | 491 | armada_xp_mpic_smp_cpu_init(); |
497 | |||
498 | /* | ||
499 | * Set the default affinity from all CPUs to the boot cpu. | ||
500 | * This is required since the MPIC doesn't limit several CPUs | ||
501 | * from acknowledging the same interrupt. | ||
502 | */ | ||
503 | cpumask_clear(irq_default_affinity); | ||
504 | cpumask_set_cpu(smp_processor_id(), irq_default_affinity); | ||
505 | |||
506 | #endif | 492 | #endif |
507 | 493 | ||
508 | armada_370_xp_msi_init(node, main_int_res.start); | 494 | armada_370_xp_msi_init(node, main_int_res.start); |
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c index fc817d28d1fe..3d15d16a7088 100644 --- a/drivers/irqchip/irq-crossbar.c +++ b/drivers/irqchip/irq-crossbar.c | |||
@@ -107,7 +107,7 @@ static int __init crossbar_of_init(struct device_node *node) | |||
107 | int i, size, max, reserved = 0, entry; | 107 | int i, size, max, reserved = 0, entry; |
108 | const __be32 *irqsr; | 108 | const __be32 *irqsr; |
109 | 109 | ||
110 | cb = kzalloc(sizeof(struct cb_device *), GFP_KERNEL); | 110 | cb = kzalloc(sizeof(*cb), GFP_KERNEL); |
111 | 111 | ||
112 | if (!cb) | 112 | if (!cb) |
113 | return -ENOMEM; | 113 | return -ENOMEM; |
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 8834a7e5b944..97ac926c78a7 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -210,7 +210,7 @@ extern int __irq_set_affinity(unsigned int irq, const struct cpumask *cpumask, | |||
210 | /** | 210 | /** |
211 | * irq_set_affinity - Set the irq affinity of a given irq | 211 | * irq_set_affinity - Set the irq affinity of a given irq |
212 | * @irq: Interrupt to set affinity | 212 | * @irq: Interrupt to set affinity |
213 | * @mask: cpumask | 213 | * @cpumask: cpumask |
214 | * | 214 | * |
215 | * Fails if cpumask does not contain an online CPU | 215 | * Fails if cpumask does not contain an online CPU |
216 | */ | 216 | */ |
@@ -223,7 +223,7 @@ irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
223 | /** | 223 | /** |
224 | * irq_force_affinity - Force the irq affinity of a given irq | 224 | * irq_force_affinity - Force the irq affinity of a given irq |
225 | * @irq: Interrupt to set affinity | 225 | * @irq: Interrupt to set affinity |
226 | * @mask: cpumask | 226 | * @cpumask: cpumask |
227 | * | 227 | * |
228 | * Same as irq_set_affinity, but without checking the mask against | 228 | * Same as irq_set_affinity, but without checking the mask against |
229 | * online cpus. | 229 | * online cpus. |
diff --git a/include/linux/irq.h b/include/linux/irq.h index 10a0b1ac4ea0..5c57efb863d0 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
@@ -603,6 +603,8 @@ static inline u32 irq_get_trigger_type(unsigned int irq) | |||
603 | return d ? irqd_get_trigger_type(d) : 0; | 603 | return d ? irqd_get_trigger_type(d) : 0; |
604 | } | 604 | } |
605 | 605 | ||
606 | unsigned int arch_dynirq_lower_bound(unsigned int from); | ||
607 | |||
606 | int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, | 608 | int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, |
607 | struct module *owner); | 609 | struct module *owner); |
608 | 610 | ||
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index a7174617616b..bb07f2928f4b 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
@@ -363,6 +363,13 @@ __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, | |||
363 | if (from > irq) | 363 | if (from > irq) |
364 | return -EINVAL; | 364 | return -EINVAL; |
365 | from = irq; | 365 | from = irq; |
366 | } else { | ||
367 | /* | ||
368 | * For interrupts which are freely allocated the | ||
369 | * architecture can force a lower bound to the @from | ||
370 | * argument. x86 uses this to exclude the GSI space. | ||
371 | */ | ||
372 | from = arch_dynirq_lower_bound(from); | ||
366 | } | 373 | } |
367 | 374 | ||
368 | mutex_lock(&sparse_irq_lock); | 375 | mutex_lock(&sparse_irq_lock); |
diff --git a/kernel/softirq.c b/kernel/softirq.c index b50990a5bea0..33e4648ae0e7 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -779,3 +779,8 @@ int __init __weak arch_early_irq_init(void) | |||
779 | { | 779 | { |
780 | return 0; | 780 | return 0; |
781 | } | 781 | } |
782 | |||
783 | unsigned int __weak arch_dynirq_lower_bound(unsigned int from) | ||
784 | { | ||
785 | return from; | ||
786 | } | ||