diff options
Diffstat (limited to 'drivers/irqchip/irq-armada-370-xp.c')
-rw-r--r-- | drivers/irqchip/irq-armada-370-xp.c | 54 |
1 files changed, 20 insertions, 34 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); |