aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/apic/io_apic.c5
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c54
-rw-r--r--drivers/irqchip/irq-crossbar.c2
-rw-r--r--include/linux/interrupt.h4
-rw-r--r--include/linux/irq.h2
-rw-r--r--kernel/irq/irqdesc.c7
-rw-r--r--kernel/softirq.c5
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
3428unsigned int arch_dynirq_lower_bound(unsigned int from)
3429{
3430 return from < nr_irqs_gsi ? nr_irqs_gsi : from;
3431}
3432
3428int __init arch_probe_nr_irqs(void) 3433int __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
168static 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
166static struct irq_chip armada_370_xp_msi_irq_chip = { 177static 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);
244static int armada_xp_set_affinity(struct irq_data *d, 256static 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
606unsigned int arch_dynirq_lower_bound(unsigned int from);
607
606int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, 608int __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
783unsigned int __weak arch_dynirq_lower_bound(unsigned int from)
784{
785 return from;
786}