From: Hosung Kim Date: Sun, 9 Apr 2017 11:49:29 +0000 (+0900) Subject: [COMMON] irqchip: gic: implement multiple cpu targeted interrupt X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=6ae58e5e004d38438416801cb5883809c0e2346a;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] irqchip: gic: implement multiple cpu targeted interrupt Current gic driver only supports single cpu targeted interrupt though GIC HW supports multiple cpu targeted interrupt. This patch implements this multiple cpu targeted interrupt by controlling interrupt processor target registers in GIC HW. Because use of multiple cpu targeted interrupt can cause unnecessary wakeups of targeted cpus, use this feature only when minimal interrupt latency is required Change-Id: Iefb8625564e790eede677190aa2190290f7aee00 Signed-off-by: Hosung Kim --- diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 651d726e8b12..04cb3c0a4c6f 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -329,17 +329,32 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, u32 val, mask, bit; unsigned long flags; - if (!force) - cpu = cpumask_any_and(mask_val, cpu_online_mask); - else - cpu = cpumask_first(mask_val); + gic_lock_irqsave(flags); + if (unlikely(d->common->state_use_accessors & IRQD_GIC_MULTI_TARGET)) { + struct cpumask temp_mask; - if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) - return -EINVAL; + bit = 0; + if (!cpumask_and(&temp_mask, mask_val, cpu_online_mask)) + goto err_out; - gic_lock_irqsave(flags); + for_each_cpu(cpu, &temp_mask) { + if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids) + goto err_out; + bit |= gic_cpu_map[cpu]; + } + bit <<= shift; + } else { + 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) + goto err_out; + + bit = gic_cpu_map[cpu] << shift; + } mask = 0xff << shift; - bit = gic_cpu_map[cpu] << shift; val = readl_relaxed(reg) & ~mask; writel_relaxed(val | bit, reg); gic_unlock_irqrestore(flags); @@ -347,6 +362,9 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, irq_data_update_effective_affinity(d, cpumask_of(cpu)); return IRQ_SET_MASK_OK_DONE; +err_out: + gic_unlock_irqrestore(flags); + return -EINVAL; } #endif