lkml.org 
[lkml]   [2021]   [May]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 017/184] mmc: sdhci: Check for reset prior to DMA address unmap
    Date
    From: Pradeep P V K <pragalla@codeaurora.org>

    commit 21e35e898aa9ef7781632959db8613a5380f2eae upstream.

    For data read commands, SDHC may initiate data transfers even before it
    completely process the command response. In case command itself fails,
    driver un-maps the memory associated with data transfer but this memory
    can still be accessed by SDHC for the already initiated data transfer.
    This scenario can lead to un-mapped memory access error.

    To avoid this scenario, reset SDHC (when command fails) prior to
    un-mapping memory. Resetting SDHC ensures that all in-flight data
    transfers are either aborted or completed. So we don't run into this
    scenario.

    Swap the reset, un-map steps sequence in sdhci_request_done().

    Suggested-by: Veerabhadrarao Badiganti <vbadigan@codeaurora.org>
    Signed-off-by: Pradeep P V K <pragalla@codeaurora.org>
    Acked-by: Adrian Hunter <adrian.hunter@intel.com>
    Link: https://lore.kernel.org/r/1614760331-43499-1-git-send-email-pragalla@qti.qualcomm.com
    Cc: stable@vger.kernel.org # v4.9+
    Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/mmc/host/sdhci.c | 60 ++++++++++++++++++++++++-----------------------
    1 file changed, 31 insertions(+), 29 deletions(-)

    --- a/drivers/mmc/host/sdhci.c
    +++ b/drivers/mmc/host/sdhci.c
    @@ -2648,6 +2648,37 @@ static bool sdhci_request_done(struct sd
    }

    /*
    + * The controller needs a reset of internal state machines
    + * upon error conditions.
    + */
    + if (sdhci_needs_reset(host, mrq)) {
    + /*
    + * Do not finish until command and data lines are available for
    + * reset. Note there can only be one other mrq, so it cannot
    + * also be in mrqs_done, otherwise host->cmd and host->data_cmd
    + * would both be null.
    + */
    + if (host->cmd || host->data_cmd) {
    + spin_unlock_irqrestore(&host->lock, flags);
    + return true;
    + }
    +
    + /* Some controllers need this kick or reset won't work here */
    + if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
    + /* This is to force an update */
    + host->ops->set_clock(host, host->clock);
    +
    + /*
    + * Spec says we should do both at the same time, but Ricoh
    + * controllers do not like that.
    + */
    + sdhci_do_reset(host, SDHCI_RESET_CMD);
    + sdhci_do_reset(host, SDHCI_RESET_DATA);
    +
    + host->pending_reset = false;
    + }
    +
    + /*
    * Always unmap the data buffers if they were mapped by
    * sdhci_prepare_data() whenever we finish with a request.
    * This avoids leaking DMA mappings on error.
    @@ -2699,35 +2730,6 @@ static bool sdhci_request_done(struct sd
    }
    }

    - /*
    - * The controller needs a reset of internal state machines
    - * upon error conditions.
    - */
    - if (sdhci_needs_reset(host, mrq)) {
    - /*
    - * Do not finish until command and data lines are available for
    - * reset. Note there can only be one other mrq, so it cannot
    - * also be in mrqs_done, otherwise host->cmd and host->data_cmd
    - * would both be null.
    - */
    - if (host->cmd || host->data_cmd) {
    - spin_unlock_irqrestore(&host->lock, flags);
    - return true;
    - }
    -
    - /* Some controllers need this kick or reset won't work here */
    - if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
    - /* This is to force an update */
    - host->ops->set_clock(host, host->clock);
    -
    - /* Spec says we should do both at the same time, but Ricoh
    - controllers do not like that. */
    - sdhci_do_reset(host, SDHCI_RESET_CMD);
    - sdhci_do_reset(host, SDHCI_RESET_DATA);
    -
    - host->pending_reset = false;
    - }
    -
    host->mrqs_done[i] = NULL;

    spin_unlock_irqrestore(&host->lock, flags);

    \
     
     \ /
      Last update: 2021-05-10 12:28    [W:6.417 / U:0.548 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site