diff options
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-gic.c | 76 |
1 files changed, 40 insertions, 36 deletions
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index a27ba2cc1dce..4ffd62af888f 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -325,28 +325,6 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu) return 0; } -#ifdef CONFIG_SMP -static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, - bool force) -{ - void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d); - unsigned int cpu; - - if (!force) - cpu = cpumask_any_and(mask_val, cpu_online_mask); - else - cpu = cpumask_first(mask_val); - - if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) - return -EINVAL; - - writeb_relaxed(gic_cpu_map[cpu], reg); - irq_data_update_effective_affinity(d, cpumask_of(cpu)); - - return IRQ_SET_MASK_OK_DONE; -} -#endif - static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { u32 irqstat, irqnr; @@ -795,6 +773,26 @@ static int gic_pm_init(struct gic_chip_data *gic) #endif #ifdef CONFIG_SMP +static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, + bool force) +{ + void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d); + unsigned int cpu; + + if (!force) + cpu = cpumask_any_and(mask_val, cpu_online_mask); + else + cpu = cpumask_first(mask_val); + + if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) + return -EINVAL; + + writeb_relaxed(gic_cpu_map[cpu], reg); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + + return IRQ_SET_MASK_OK_DONE; +} + static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { int cpu; @@ -824,6 +822,23 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) gic_unlock_irqrestore(flags); } + +static int gic_starting_cpu(unsigned int cpu) +{ + gic_cpu_init(&gic_data[0]); + return 0; +} + +static __init void gic_smp_init(void) +{ + set_smp_cross_call(gic_raise_softirq); + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING, + "irqchip/arm/gic:starting", + gic_starting_cpu, NULL); +} +#else +#define gic_smp_init() do { } while(0) +#define gic_set_affinity NULL #endif #ifdef CONFIG_BL_SWITCHER @@ -1027,12 +1042,6 @@ static int gic_irq_domain_translate(struct irq_domain *d, return -EINVAL; } -static int gic_starting_cpu(unsigned int cpu) -{ - gic_cpu_init(&gic_data[0]); - return 0; -} - static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *arg) { @@ -1079,10 +1088,8 @@ static void gic_init_chip(struct gic_chip_data *gic, struct device *dev, gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity; } -#ifdef CONFIG_SMP if (gic == &gic_data[0]) gic->chip.irq_set_affinity = gic_set_affinity; -#endif } static int gic_init_bases(struct gic_chip_data *gic, @@ -1199,12 +1206,7 @@ static int __init __gic_init_bases(struct gic_chip_data *gic, */ for (i = 0; i < NR_GIC_CPU_IF; i++) gic_cpu_map[i] = 0xff; -#ifdef CONFIG_SMP - set_smp_cross_call(gic_raise_softirq); -#endif - cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING, - "irqchip/arm/gic:starting", - gic_starting_cpu, NULL); + set_handle_irq(gic_handle_irq); if (static_branch_likely(&supports_deactivate_key)) pr_info("GIC: Using split EOI/Deactivate mode\n"); @@ -1221,6 +1223,8 @@ static int __init __gic_init_bases(struct gic_chip_data *gic, ret = gic_init_bases(gic, handle); if (ret) kfree(name); + else if (gic == &gic_data[0]) + gic_smp_init(); return ret; } |