diff options
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-armada-370-xp.c | 54 | ||||
-rw-r--r-- | drivers/irqchip/irq-crossbar.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic.c | 8 | ||||
-rw-r--r-- | drivers/irqchip/irq-vic.c | 6 | ||||
-rw-r--r-- | drivers/irqchip/spear-shirq.c | 2 |
5 files changed, 34 insertions, 38 deletions
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/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 4300b6606f5e..57d165e026f4 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -246,10 +246,14 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, | |||
246 | bool force) | 246 | bool force) |
247 | { | 247 | { |
248 | void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); | 248 | void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); |
249 | unsigned int shift = (gic_irq(d) % 4) * 8; | 249 | unsigned int cpu, shift = (gic_irq(d) % 4) * 8; |
250 | unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask); | ||
251 | u32 val, mask, bit; | 250 | u32 val, mask, bit; |
252 | 251 | ||
252 | if (!force) | ||
253 | cpu = cpumask_any_and(mask_val, cpu_online_mask); | ||
254 | else | ||
255 | cpu = cpumask_first(mask_val); | ||
256 | |||
253 | if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) | 257 | if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) |
254 | return -EINVAL; | 258 | return -EINVAL; |
255 | 259 | ||
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c index 37dab0b472cd..7d35287f9e90 100644 --- a/drivers/irqchip/irq-vic.c +++ b/drivers/irqchip/irq-vic.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/irq.h> | 26 | #include <linux/irq.h> |
27 | #include <linux/irqchip/chained_irq.h> | ||
27 | #include <linux/irqdomain.h> | 28 | #include <linux/irqdomain.h> |
28 | #include <linux/of.h> | 29 | #include <linux/of.h> |
29 | #include <linux/of_address.h> | 30 | #include <linux/of_address.h> |
@@ -228,12 +229,17 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs) | |||
228 | static void vic_handle_irq_cascaded(unsigned int irq, struct irq_desc *desc) | 229 | static void vic_handle_irq_cascaded(unsigned int irq, struct irq_desc *desc) |
229 | { | 230 | { |
230 | u32 stat, hwirq; | 231 | u32 stat, hwirq; |
232 | struct irq_chip *host_chip = irq_desc_get_chip(desc); | ||
231 | struct vic_device *vic = irq_desc_get_handler_data(desc); | 233 | struct vic_device *vic = irq_desc_get_handler_data(desc); |
232 | 234 | ||
235 | chained_irq_enter(host_chip, desc); | ||
236 | |||
233 | while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { | 237 | while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) { |
234 | hwirq = ffs(stat) - 1; | 238 | hwirq = ffs(stat) - 1; |
235 | generic_handle_irq(irq_find_mapping(vic->domain, hwirq)); | 239 | generic_handle_irq(irq_find_mapping(vic->domain, hwirq)); |
236 | } | 240 | } |
241 | |||
242 | chained_irq_exit(host_chip, desc); | ||
237 | } | 243 | } |
238 | 244 | ||
239 | /* | 245 | /* |
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c index 8527743b5cef..3fdda3a40269 100644 --- a/drivers/irqchip/spear-shirq.c +++ b/drivers/irqchip/spear-shirq.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Viresh Kumar <viresh.linux@gmail.com> | 5 | * Viresh Kumar <viresh.linux@gmail.com> |
6 | * | 6 | * |
7 | * Copyright (C) 2012 ST Microelectronics | 7 | * Copyright (C) 2012 ST Microelectronics |
8 | * Shiraz Hashim <shiraz.hashim@st.com> | 8 | * Shiraz Hashim <shiraz.linux.kernel@gmail.com> |
9 | * | 9 | * |
10 | * This file is licensed under the terms of the GNU General Public | 10 | * This file is licensed under the terms of the GNU General Public |
11 | * License version 2. This program is licensed "as is" without any | 11 | * License version 2. This program is licensed "as is" without any |