lkml.org 
[lkml]   [2010]   [Nov]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2] [ARM] gic: Unmask private interrupts on all cores during IRQ enable
    Date
    Some multi-core ARM chips designate a unique IRQ number for each core for
    private peripheral interrupts (PPIs). Others designate a common IRQ number
    for all cores. In the latter case, requesting/freeing private peripheral
    interrupts currently unmasks/masks the interrupt for only the
    executing core, respectively.

    With this change, request_irq will unmask a PPI on all cores so a separate
    call to enable_irq on the other cores is not required. Likewise, free_irq
    will mask a PPI on the other cores. Also, shutdown is implemented instead
    of disable to allow for lazy IRQ disabling.

    Signed-off-by: Stephen Caudle <scaudle@codeaurora.org>
    ---
    arch/arm/Kconfig | 5 +++
    arch/arm/common/gic.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++
    2 files changed, 91 insertions(+), 0 deletions(-)

    diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
    index 30ddd06..7f11e31 100644
    --- a/arch/arm/Kconfig
    +++ b/arch/arm/Kconfig
    @@ -1153,6 +1153,11 @@ config SMP

    If you don't know what to do here, say N.

    +config IRQ_PER_CPU
    + bool
    + depends on SMP
    + default n
    +
    config HAVE_ARM_SCU
    bool
    depends on SMP
    diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
    index 886daaf..937a33a 100644
    --- a/arch/arm/common/gic.c
    +++ b/arch/arm/common/gic.c
    @@ -44,12 +44,25 @@ struct gic_chip_data {
    unsigned int wakeup_irqs[32];
    unsigned int enabled_irqs[32];
    #endif
    +#ifdef CONFIG_IRQ_PER_CPU
    + struct call_single_data ppi_data[NR_CPUS];
    +#endif
    };

    #ifndef MAX_GIC_NR
    #define MAX_GIC_NR 1
    #endif

    +#ifdef CONFIG_IRQ_PER_CPU
    +#ifndef GIC_PPI_FIRST
    +#define GIC_PPI_FIRST 16
    +#endif
    +
    +#ifndef GIC_PPI_LAST
    +#define GIC_PPI_LAST 31
    +#endif
    +#endif
    +
    static struct gic_chip_data gic_data[MAX_GIC_NR];

    static inline void __iomem *gic_dist_base(unsigned int irq)
    @@ -272,6 +285,75 @@ static int gic_set_type(unsigned int irq, unsigned int type)
    return 0;
    }

    +#ifdef CONFIG_IRQ_PER_CPU
    +static inline void gic_smp_call_function(struct call_single_data *data)
    +{
    + int cpu;
    +
    + /* Make sure data is visible */
    + smp_mb();
    +
    + /*
    + * Since this function is called with interrupts disabled,
    + * smp_call_function can't be used here because it warns (even
    + * if wait = 0) when interrupts are disabled.
    + *
    + * __smp_call_function_single doesn't warn when interrupts are
    + * disabled and not waiting, so use it instead.
    + */
    + for_each_online_cpu(cpu)
    + if (cpu != smp_processor_id())
    + __smp_call_function_single(cpu, data, 0);
    +}
    +
    +static void gic_mask_ppi(void *info)
    +{
    + struct irq_desc *desc = info;
    + gic_mask_irq(desc->irq);
    +}
    +
    +static void gic_unmask_ppi(void *info)
    +{
    + struct irq_desc *desc = info;
    + gic_unmask_irq(desc->irq);
    +}
    +
    +static void gic_enable_irq(unsigned int irq)
    +{
    + struct irq_desc *desc = irq_to_desc(irq);
    + struct gic_chip_data *gic_data = get_irq_chip_data(irq);
    + int cpu = smp_processor_id();
    +
    + if (irq >= GIC_PPI_FIRST && irq <= GIC_PPI_LAST) {
    + gic_data->ppi_data[cpu].func = gic_unmask_ppi;
    + gic_data->ppi_data[cpu].info = desc;
    +
    + /* Unmask PPIs on all cores during enable. */
    + gic_smp_call_function(&gic_data->ppi_data[cpu]);
    + }
    +
    + desc->chip->unmask(irq);
    + desc->status &= ~IRQ_MASKED;
    +}
    +
    +static void gic_shutdown_irq(unsigned int irq)
    +{
    + struct irq_desc *desc = irq_to_desc(irq);
    + struct gic_chip_data *gic_data = get_irq_chip_data(irq);
    + int cpu = smp_processor_id();
    +
    + if (irq >= GIC_PPI_FIRST && irq <= GIC_PPI_LAST) {
    + gic_data->ppi_data[cpu].func = gic_mask_ppi;
    + gic_data->ppi_data[cpu].info = desc;
    +
    + /* Mask PPIs on all cores during disable. */
    + gic_smp_call_function(&gic_data->ppi_data[cpu]);
    + }
    +
    + desc->chip->mask(irq);
    + desc->status |= IRQ_MASKED;
    +}
    +#endif

    static struct irq_chip gic_chip = {
    .name = "GIC",
    @@ -283,6 +365,10 @@ static struct irq_chip gic_chip = {
    #endif
    .set_type = gic_set_type,
    .set_wake = gic_set_wake,
    +#ifdef CONFIG_IRQ_PER_CPU
    + .enable = gic_enable_irq,
    + .shutdown = gic_shutdown_irq,
    +#endif
    };

    void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
    --
    1.7.3.2
    --
    Sent by an employee of the Qualcomm Innovation Center, Inc.
    The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum



    \
     
     \ /
      Last update: 2010-11-03 22:49    [W:0.025 / U:0.312 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site