[PATCHv2 1/2] ARM: perf_event: allow platform-specific interrupt handler
Rabin Vincent
rabin at rab.in
Wed Feb 16 05:34:27 EST 2011
On Fri, Feb 11, 2011 at 22:03, Will Deacon <will.deacon at arm.com> wrote:
>> Allow a platform-specific IRQ handler to be specified via platform data. This
>> will be used to implement the single-irq workaround for the DB8500.
>>
>> Signed-off-by: Rabin Vincent <rabin.vincent at stericsson.com>
>> ---
>> arch/arm/include/asm/pmu.h | 14 ++++++++++++++
>> arch/arm/kernel/perf_event.c | 17 ++++++++++++++++-
>> 2 files changed, 30 insertions(+), 1 deletions(-)
>
> If you're happy with this as a workaround for your platform, then
> it looks alright to me.
>
> Acked-by: Will Deacon <will.deacon at arm.com>
Thanks.
>
> One thing you could try is using the GIC patch I posted the other day:
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2011-February/041496.html
>
> If you then do:
>
> ARM: gic: allow per-cpu SPIs to be affine to multiple CPUs
>
> The concept of a per-cpu SPI is somewhat a contradiction, but can occur in
> systems where SPIs from different CPUs are ORd together into a single line.
>
> An example of this is the PMU interrupt on the u8500 platform.
>
> This patch allows SPIs with the IRQF_PERCPU flag to be affine to multiple
> CPUs in a CPU mask. This, of course, assumes that the driver knows what it
> is doing and can handle such a configuration.
>
> Signed-off-by: Will Deacon <will.deacon at arm.com>
>
> diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
> index 9def30b..512f55f 100644
> --- a/arch/arm/common/gic.c
> +++ b/arch/arm/common/gic.c
> @@ -145,7 +145,7 @@ gic_set_cpu(struct irq_data *d, const struct cpumask *mask_val, bool force)
> {
> void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
> unsigned int shift = (d->irq % 4) * 8;
> - unsigned int cpu = cpumask_first(mask_val);
> + unsigned int cpu_map, cpu = cpumask_first(mask_val);
> u32 val;
> struct irq_desc *desc;
>
> @@ -155,9 +155,19 @@ gic_set_cpu(struct irq_data *d, const struct cpumask *mask_val, bool force)
> spin_unlock(&irq_controller_lock);
> return -EINVAL;
> }
> +
> d->node = cpu;
> +
> + if (CHECK_IRQ_PER_CPU(desc->status)) {
> + cpu_map = 0;
> + for_each_cpu(cpu, mask_val)
> + cpu_map |= 1 << (cpu + shift);
> + } else {
> + cpu_map = 1 << (cpu + shift);
> + }
> +
> val = readl(reg) & ~(0xff << shift);
> - val |= 1 << (cpu + shift);
> + val |= cpu_map;
> writel(val, reg);
> spin_unlock(&irq_controller_lock);
>
>
> You'll be able to target the PMU IRQ to both CPUs and avoid the need for
> ping-ponging the affinity. This is a bit weird though as usually you'd have
> a PPI for a percpu interrupt so this might be better off staying inside
> platform code and leaving the GIC code alone. I also think this approach
> is more invasive from the perf point of view.
>
> Unless this approach gives markedly better profiling results than your
> proposal, I think we should go with what you've got.
I gave this a try, along with the modifications to enable IRQ_PER_CPU
and have the pmu code use the appropriate flags and set the affinity.
Didn't work though; it always ends up triggering the spurious IRQ check.
More information about the linux-arm-kernel
mailing list