lkml.org 
[lkml]   [2018]   [Apr]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.16 080/196] irqchip/gic: Take lock when updating irq type
    Date
    4.16-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Aniruddha Banerjee <aniruddhab@nvidia.com>

    commit aa08192a254d362a4d5317647a81de6996961aef upstream.

    Most MMIO GIC register accesses use a 1-hot bit scheme that
    avoids requiring any form of locking. This isn't true for the
    GICD_ICFGRn registers, which require a RMW sequence.

    Unfortunately, we seem to be missing a lock for these particular
    accesses, which could result in a race condition if changing the
    trigger type on any two interrupts within the same set of 16
    interrupts (and thus controlled by the same CFGR register).

    Introduce a private lock in the GIC common comde for this
    particular case, making it cover both GIC implementations
    in one go.

    Cc: stable@vger.kernel.org
    Signed-off-by: Aniruddha Banerjee <aniruddhab@nvidia.com>
    [maz: updated changelog]
    Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/irqchip/irq-gic-common.c | 9 ++++++++-
    1 file changed, 8 insertions(+), 1 deletion(-)

    --- a/drivers/irqchip/irq-gic-common.c
    +++ b/drivers/irqchip/irq-gic-common.c
    @@ -21,6 +21,8 @@

    #include "irq-gic-common.h"

    +static DEFINE_RAW_SPINLOCK(irq_controller_lock);
    +
    static const struct gic_kvm_info *gic_kvm_info;

    const struct gic_kvm_info *gic_get_kvm_info(void)
    @@ -53,11 +55,13 @@ int gic_configure_irq(unsigned int irq,
    u32 confoff = (irq / 16) * 4;
    u32 val, oldval;
    int ret = 0;
    + unsigned long flags;

    /*
    * Read current configuration register, and insert the config
    * for "irq", depending on "type".
    */
    + raw_spin_lock_irqsave(&irq_controller_lock, flags);
    val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
    if (type & IRQ_TYPE_LEVEL_MASK)
    val &= ~confmask;
    @@ -65,8 +69,10 @@ int gic_configure_irq(unsigned int irq,
    val |= confmask;

    /* If the current configuration is the same, then we are done */
    - if (val == oldval)
    + if (val == oldval) {
    + raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
    return 0;
    + }

    /*
    * Write back the new configuration, and possibly re-enable
    @@ -84,6 +90,7 @@ int gic_configure_irq(unsigned int irq,
    pr_warn("GIC: PPI%d is secure or misconfigured\n",
    irq - 16);
    }
    + raw_spin_unlock_irqrestore(&irq_controller_lock, flags);

    if (sync_access)
    sync_access();

    \
     
     \ /
      Last update: 2018-04-22 18:03    [W:4.132 / U:0.120 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site