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 132/196] mmc: jz4740: Fix race condition in IRQ mask update
    Date
    4.16-stable review patch.  If anyone has any objections, please let me know.

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

    From: Alex Smith <alex.smith@imgtec.com>

    commit a04f0017c22453613d5f423326b190c61e3b4f98 upstream.

    A spinlock is held while updating the internal copy of the IRQ mask,
    but not while writing it to the actual IMASK register. After the lock
    is released, an IRQ can occur before the IMASK register is written.
    If handling this IRQ causes the mask to be changed, when the handler
    returns back to the middle of the first mask update, a stale value
    will be written to the mask register.

    If this causes an IRQ to become unmasked that cannot have its status
    cleared by writing a 1 to it in the IREG register, e.g. the SDIO IRQ,
    then we can end up stuck with the same IRQ repeatedly being fired but
    not handled. Normally the MMC IRQ handler attempts to clear any
    unexpected IRQs by writing IREG, but for those that cannot be cleared
    in this way then the IRQ will just repeatedly fire.

    This was resulting in lockups after a while of using Wi-Fi on the
    CI20 (GitHub issue #19).

    Resolve by holding the spinlock until after the IMASK register has
    been updated.

    Cc: stable@vger.kernel.org
    Link: https://github.com/MIPS/CI20_linux/issues/19
    Fixes: 61bfbdb85687 ("MMC: Add support for the controller on JZ4740 SoCs.")
    Tested-by: Mathieu Malaterre <malat@debian.org>
    Signed-off-by: Alex Smith <alex.smith@imgtec.com>
    Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/mmc/host/jz4740_mmc.c | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)

    --- a/drivers/mmc/host/jz4740_mmc.c
    +++ b/drivers/mmc/host/jz4740_mmc.c
    @@ -362,9 +362,9 @@ static void jz4740_mmc_set_irq_enabled(s
    host->irq_mask &= ~irq;
    else
    host->irq_mask |= irq;
    - spin_unlock_irqrestore(&host->lock, flags);

    writew(host->irq_mask, host->base + JZ_REG_MMC_IMASK);
    + spin_unlock_irqrestore(&host->lock, flags);
    }

    static void jz4740_mmc_clock_enable(struct jz4740_mmc_host *host,

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