linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V2] mmc: sdhci: Check for reset prior to DMA address unmap
@ 2021-03-03  8:32 Pradeep P V K
  2021-03-04 13:49 ` Ulf Hansson
  0 siblings, 1 reply; 4+ messages in thread
From: Pradeep P V K @ 2021-03-03  8:32 UTC (permalink / raw)
  To: adrian.hunter, ulf.hansson
  Cc: asutoshd, stummala, rampraka, vbadigan, linux-mmc, linux-kernel,
	Pradeep P V K

From: Pradeep P V K <pragalla@codeaurora.org>

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().

Changes since V1:
- Added an empty line and fixed the comment style.
- Retained the Acked-by signoff.

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>
---
 drivers/mmc/host/sdhci.c | 60 +++++++++++++++++++++++++-----------------------
 1 file changed, 31 insertions(+), 29 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 646823d..130fd2d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2998,6 +2998,37 @@ static bool sdhci_request_done(struct sdhci_host *host)
 	}
 
 	/*
+	 * 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.
@@ -3060,35 +3091,6 @@ static bool sdhci_request_done(struct sdhci_host *host)
 		}
 	}
 
-	/*
-	 * 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);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH V2] mmc: sdhci: Check for reset prior to DMA address unmap
  2021-03-03  8:32 [PATCH V2] mmc: sdhci: Check for reset prior to DMA address unmap Pradeep P V K
@ 2021-03-04 13:49 ` Ulf Hansson
  2021-03-04 15:16   ` pragalla
  0 siblings, 1 reply; 4+ messages in thread
From: Ulf Hansson @ 2021-03-04 13:49 UTC (permalink / raw)
  To: Pradeep P V K
  Cc: Adrian Hunter, Asutosh Das, Sahitya Tummala, Ram Prakash Gupta,
	Veerabhadrarao Badiganti, linux-mmc, Linux Kernel Mailing List,
	Pradeep P V K

On Wed, 3 Mar 2021 at 09:32, Pradeep P V K <pragalla@qti.qualcomm.com> wrote:
>
> From: Pradeep P V K <pragalla@codeaurora.org>
>
> 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().
>
> Changes since V1:
> - Added an empty line and fixed the comment style.
> - Retained the Acked-by signoff.
>
> 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>

Seems like it might be a good idea to tag this for stable? I did that,
but awaiting for your confirmation.

So, applied for next, thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci.c | 60 +++++++++++++++++++++++++-----------------------
>  1 file changed, 31 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 646823d..130fd2d 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -2998,6 +2998,37 @@ static bool sdhci_request_done(struct sdhci_host *host)
>         }
>
>         /*
> +        * 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.
> @@ -3060,35 +3091,6 @@ static bool sdhci_request_done(struct sdhci_host *host)
>                 }
>         }
>
> -       /*
> -        * 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);
> --
> 2.7.4
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH V2] mmc: sdhci: Check for reset prior to DMA address unmap
  2021-03-04 13:49 ` Ulf Hansson
@ 2021-03-04 15:16   ` pragalla
  2021-03-04 18:08     ` Ulf Hansson
  0 siblings, 1 reply; 4+ messages in thread
From: pragalla @ 2021-03-04 15:16 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Pradeep P V K, Adrian Hunter, Asutosh Das, Sahitya Tummala,
	Ram Prakash Gupta, Veerabhadrarao Badiganti, linux-mmc,
	Linux Kernel Mailing List

On 2021-03-04 19:19, Ulf Hansson wrote:
> On Wed, 3 Mar 2021 at 09:32, Pradeep P V K <pragalla@qti.qualcomm.com> 
> wrote:
>> 
>> From: Pradeep P V K <pragalla@codeaurora.org>
>> 
>> 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().
>> 
>> Changes since V1:
>> - Added an empty line and fixed the comment style.
>> - Retained the Acked-by signoff.
>> 
>> 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>

Hi Uffe,
> 
> Seems like it might be a good idea to tag this for stable? I did that,
> but awaiting for your confirmation.
> 
Yes, this fix is applicable for all stable starting from 4.9 (n/a for 
4.4).
Kindly go ahead.

> So, applied for next, thanks!
> 
> Kind regards
> Uffe
> 
Thanks and Regards,
Pradeep

> 
>> ---
>>  drivers/mmc/host/sdhci.c | 60 
>> +++++++++++++++++++++++++-----------------------
>>  1 file changed, 31 insertions(+), 29 deletions(-)
>> 
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 646823d..130fd2d 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -2998,6 +2998,37 @@ static bool sdhci_request_done(struct 
>> sdhci_host *host)
>>         }
>> 
>>         /*
>> +        * 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.
>> @@ -3060,35 +3091,6 @@ static bool sdhci_request_done(struct 
>> sdhci_host *host)
>>                 }
>>         }
>> 
>> -       /*
>> -        * 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);
>> --
>> 2.7.4
>> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH V2] mmc: sdhci: Check for reset prior to DMA address unmap
  2021-03-04 15:16   ` pragalla
@ 2021-03-04 18:08     ` Ulf Hansson
  0 siblings, 0 replies; 4+ messages in thread
From: Ulf Hansson @ 2021-03-04 18:08 UTC (permalink / raw)
  To: Pradeep P V K
  Cc: Pradeep P V K, Adrian Hunter, Asutosh Das, Sahitya Tummala,
	Ram Prakash Gupta, Veerabhadrarao Badiganti, linux-mmc,
	Linux Kernel Mailing List

On Thu, 4 Mar 2021 at 16:16, <pragalla@codeaurora.org> wrote:
>
> On 2021-03-04 19:19, Ulf Hansson wrote:
> > On Wed, 3 Mar 2021 at 09:32, Pradeep P V K <pragalla@qti.qualcomm.com>
> > wrote:
> >>
> >> From: Pradeep P V K <pragalla@codeaurora.org>
> >>
> >> 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().
> >>
> >> Changes since V1:
> >> - Added an empty line and fixed the comment style.
> >> - Retained the Acked-by signoff.
> >>
> >> 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>
>
> Hi Uffe,
> >
> > Seems like it might be a good idea to tag this for stable? I did that,
> > but awaiting for your confirmation.
> >
> Yes, this fix is applicable for all stable starting from 4.9 (n/a for
> 4.4).
> Kindly go ahead.
>
> > So, applied for next, thanks!
> >
> > Kind regards
> > Uffe
> >
> Thanks and Regards,
> Pradeep

Thanks for confirming, I have updated the stable tag.

Kind regards
Uffe

>
> >
> >> ---
> >>  drivers/mmc/host/sdhci.c | 60
> >> +++++++++++++++++++++++++-----------------------
> >>  1 file changed, 31 insertions(+), 29 deletions(-)
> >>
> >> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> >> index 646823d..130fd2d 100644
> >> --- a/drivers/mmc/host/sdhci.c
> >> +++ b/drivers/mmc/host/sdhci.c
> >> @@ -2998,6 +2998,37 @@ static bool sdhci_request_done(struct
> >> sdhci_host *host)
> >>         }
> >>
> >>         /*
> >> +        * 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.
> >> @@ -3060,35 +3091,6 @@ static bool sdhci_request_done(struct
> >> sdhci_host *host)
> >>                 }
> >>         }
> >>
> >> -       /*
> >> -        * 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);
> >> --
> >> 2.7.4
> >>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-03-04 18:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-03  8:32 [PATCH V2] mmc: sdhci: Check for reset prior to DMA address unmap Pradeep P V K
2021-03-04 13:49 ` Ulf Hansson
2021-03-04 15:16   ` pragalla
2021-03-04 18:08     ` Ulf Hansson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).