• Douglas Anderson's avatar
    soc: qcom: geni: More properly switch to DMA mode · 4b6ea87b
    Douglas Anderson authored
    On geni-i2c transfers using DMA, it was seen that if you program the
    command (I2C_READ) before calling geni_se_rx_dma_prep() that it could
    cause interrupts to fire.  If we get unlucky, these interrupts can
    just keep firing (and not be handled) blocking further progress and
    hanging the system.
    
    In commit 02b9aec5 ("i2c: i2c-qcom-geni: Fix DMA transfer race")
    we avoided that by making sure we didn't program the command until
    after geni_se_rx_dma_prep() was called.  While that avoided the
    problems, it also turns out to be invalid.  At least in the TX case we
    started seeing sporadic corrupted transfers.  This is easily seen by
    adding an msleep() between the DMA prep and the writing of the
    command, which makes the problem worse.  That means we need to revert
    that commit and find another way to fix the bogus IRQs.
    
    Specifically, after reverting commit 02b9aec5 ("i2c:
    i2c-qcom-geni: Fix DMA transfer race"), I put some traces in.  I found
    that the when the interrupts were firing like crazy:
    - "m_stat" had bits for M_RX_IRQ_EN, M_RX_FIFO_WATERMARK_EN set.
    - "dma" was set.
    
    Further debugging showed that I could make the problem happen more
    reliably by adding an "msleep(1)" any time after geni_se_setup_m_cmd()
    ran up until geni_se_rx_dma_prep() programmed the length.
    
    A rather simple fix is to change geni_se_select_dma_mode() so it's a
    true inverse of geni_se_select_fifo_mode() and disables all the FIFO
    related interrupts.  Now the problematic interrupts can't fire and we
    can program things in the correct order without worrying.
    
    As part of this, let's also change the writel_relaxed() in the prepare
    function to a writel() so that our DMA is guaranteed to be prepared
    now that we can't rely on geni_se_setup_m_cmd()'s writel().
    
    NOTE: the only current user of GENI_SE_DMA in mainline is i2c.
    
    Fixes: 37692de5 ("i2c: i2c-qcom-geni: Add bus driver for the Qualcomm GENI I2C controller")
    Fixes: 02b9aec5 ("i2c: i2c-qcom-geni: Fix DMA transfer race")
    Signed-off-by: default avatarDouglas Anderson <dianders@chromium.org>
    Reviewed-by: default avatarStephen Boyd <swboyd@chromium.org>
    Reviewed-by: default avatarAkash Asthana <akashast@codeaurora.org>
    Tested-by: default avatarDmitry Baryshkov <dmitry.baryshkov@linaro.org>
    Link: https://lore.kernel.org/r/20201013142448.v2.1.Ifdb1b69fa3367b81118e16e9e4e63299980ca798@changeidSigned-off-by: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
    4b6ea87b
qcom-geni-se.c 27.7 KB