| @@ -41,6 +41,7 @@ · 40 unmodified lines |
| 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, · 85 unmodified lines |
| 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, · 19 unmodified lines |
| 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, · 34 unmodified lines |
| 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); · 37 unmodified lines |
| 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, · 215 unmodified lines |
| 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); |