[PATCH 1/1] irqchip: irq-gic: forward SGI to itself for cortex-a7 single core
Peter Chen
peter.chen at nxp.com
Mon Aug 8 05:00:35 PDT 2016
>
>On Mon, Aug 08, 2016 at 03:49:54PM +0800, Peter Chen wrote:
>> According to Cortex-A7 MPCore TRM, ch8.3.1, Distributor register
>> summary,
>> GICD_ITARGETSRn:
>>
>> The register that contains the SGI and PPI interrupts is
>> read-only and the value is implementation defined. For
>> Cortex-A7 configurations with only one processor, these
>> registers are RAZ/WI.
>>
>> So, the GICD_ITARGETSR[0..7] is read-only, and the value is 0 for
>> cortex-a7 single core platform if the SoC is cortex-a7 mpcore version.
>> So the cupmask from gic_get_cpumask is 0.
>>
>> At ARM Generic Interrupt Controller Architecture version 2.0,
>> ch4.3.15 Software Generated Interrupt Register, GICD_SGIR, The
>> distributor will process the requested SGI according to register
>> TargetListFilter and CPUTargetList. At current gic code, it takes
>> TargetListFilter as 0b00, and forward the interrupt to cpumask
>> (variable map at gic_raise_softirq) getting from gic_get_cpumask.
>> but cpumask is 0 according to above explanation for cortex-a7 single
>> core platform, so, both TargetListFilter and CPUTargetList are 0, and
>> the distributor does not forward the interrupt to any CPU interface
>> according to gic documentation, then the SGI can't be occurred.
>>
>> We have found this problem at nxp imx6ul platform, which is a
>> cortex-a7 single core platform, the irq work (triggered by SGI at ARM)
>> can't be occurred which is needed for cpufreq, then the system has
>> failed to boot and reboot [1].
>>
>> In this commit, we set TargetListFilter as 0b10 to fix this problem,
>> it forwards the interrupt only to CPU0 and only cortex-a7 single core
>> platform uses this setting currently.
>
>This is a generic property of the GIC architecture in UP systems, and is not specific
>to Cortex-A7. So checking for Cortex-A7 specifically doesn't solve the problem.
>
It is a SMP system, the is_smp returns true due to MPIDR is 0x80000000. This
platform is MPcore, just the cpu number is one.
Current kernel considers the hardware is IPI capable if is_smp is true, see
arch_irq_work_has_interrupt(). I think I should add additional condition
is_smp == true.
>As Russell pointed out in [2], this is a generic infrastructure problem, and there are
>other systems where HW might not have a self-IPI.
If the HW is UP, it is no problem. The irq work will not trigger IPI.
> I note that core code already
>handles that in some cases, e.g. in generic_exec_single where we just disable
>interrupts and run the work locally rather than sending a self-IPI.
>
>How/where exactly is this self-IPI raised? Can we follow the example of
>generic_exec_single there?
In my case, the cpufreq uses irq work, irq work tries to trigger IPI. See
sugov_update_commit-> irq_work_queue.
imx6ul is MPcore system, just single core. If ARM considers MPcore
system has IPI capabilities, and documentation is correct, then it is
probably gic code's issue.
Peter
>[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-May/430545.html
>[2] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-May/430849.html
>
>> Cc: Russell King <linux at armlinux.org.uk>
>> Cc: Shawn Guo <shawnguo at kernel.org>
>> Cc: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
>> Cc: Jason Liu <jason.hui.liu at nxp.com>
>> Cc: Anson Huang <anson.huang at nxp.com>
>> Cc: Frank Li <frank.li at nxp.com>
>> Cc: Fabio Estevam <fabio.estevam at nxp.com>
>> Cc: Ping Bai <ping.bai at nxp.com>
>>
>> Signed-off-by: Peter Chen <peter.chen at nxp.com>
>> ---
>> drivers/irqchip/irq-gic.c | 39
>> ++++++++++++++++++++++++++++++++++++---
>> 1 file changed, 36 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
>> index c2cab57..625ae6d 100644
>> --- a/drivers/irqchip/irq-gic.c
>> +++ b/drivers/irqchip/irq-gic.c
>> @@ -764,6 +764,23 @@ static int gic_pm_init(struct gic_chip_data *gic)
>> #endif
>>
>> #ifdef CONFIG_SMP
>> +static void gic_raise_softirq_itself(const struct cpumask *mask,
>> + unsigned int irq)
>> +{
>> + unsigned long flags;
>> +
>> + raw_spin_lock_irqsave(&irq_controller_lock, flags);
>> +
>> + /*
>> + * Forward the interrupt only to the CPU interface of the processor
>> + * that requested the interrupt.
>> + */
>> + writel_relaxed(0x2000000 | irq, gic_data_dist_base(&gic_data[0])
>> + + GIC_DIST_SOFTINT);
>> +
>> + raw_spin_unlock_irqrestore(&irq_controller_lock, flags); }
>> +
>> static void gic_raise_softirq(const struct cpumask *mask, unsigned
>> int irq) {
>> int cpu;
>> @@ -1162,9 +1179,6 @@ 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,
>> "AP_IRQ_GIC_STARTING",
>> gic_starting_cpu, NULL);
>> @@ -1336,6 +1350,16 @@ static void __init gic_of_setup_kvm_info(struct
>device_node *node)
>> gic_set_kvm_info(&gic_v2_kvm_info);
>> }
>>
>> +static bool __init gic_is_a7_singlecore(struct gic_chip_data *gic,
>> + struct device_node *node)
>> +{
>> + if (!of_device_is_compatible(node, "arm,cortex-a7-gic"))
>> + return false;
>> +
>> + return !(readl_relaxed(gic_data_dist_base(gic) + GIC_DIST_CTR) &
>> +0xe0);
>> +
>> +}
>> +
>> int __init
>> gic_of_init(struct device_node *node, struct device_node *parent) {
>> @@ -1367,6 +1391,15 @@ gic_of_init(struct device_node *node, struct
>device_node *parent)
>> return ret;
>> }
>>
>> + if (gic == &gic_data[0]) {
>> +#ifdef CONFIG_SMP
>> + if (gic_is_a7_singlecore(gic, node))
>> + set_smp_cross_call(gic_raise_softirq_itself);
>> + else
>> + set_smp_cross_call(gic_raise_softirq);
>> +#endif
>> + }
>> +
>> if (!gic_cnt) {
>> gic_init_physaddr(node);
>> gic_of_setup_kvm_info(node);
>> --
>> 1.9.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
More information about the linux-arm-kernel
mailing list