public inbox for linux-mmc@vger.kernel.org
 help / color / mirror / Atom feed
From: Adrian Hunter <adrian.hunter@intel.com>
To: Ulf Hansson <ulf.hansson@linaro.org>
Cc: Chris Ball <chris@printf.net>,
	linux-mmc <linux-mmc@vger.kernel.org>,
	Aaron Lu <aaron.lu@intel.com>, Philip Rakity <prakity@nvidia.com>,
	Girish K S <girish.shivananjappa@linaro.org>,
	Al Cooper <alcooperx@gmail.com>,
	Arend van Spriel <arend@broadcom.com>
Subject: Re: [PATCH V2 11/15] mmc: sdhci: Change to new way of doing re-tuning
Date: Mon, 09 Mar 2015 10:37:49 +0200	[thread overview]
Message-ID: <54FD5BDD.9060004@intel.com> (raw)
In-Reply-To: <CAPDyKFpTuttvhP91qNF_g_2sWV3NZmYMCnqFVGYEnb1L8kXVeg@mail.gmail.com>

On 06/03/15 14:51, Ulf Hansson wrote:
> On 29 January 2015 at 10:00, Adrian Hunter <adrian.hunter@intel.com> wrote:
>> Make use of mmc core support for re-tuning instead
>> of doing it all in the sdhci driver.
>>
>> This patch also changes to flag the need for re-tuning
>> always after runtime suspend when tuning has been used
>> at initialization. Previously it was only done if
>> the re-tuning timer was in use.
>>
>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
>> ---
>>  drivers/mmc/host/sdhci.c  | 113 ++++++----------------------------------------
>>  include/linux/mmc/sdhci.h |   3 --
>>  2 files changed, 14 insertions(+), 102 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index c9881ca..dd0be76 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -51,7 +51,6 @@ static void sdhci_finish_data(struct sdhci_host *);
>>
>>  static void sdhci_finish_command(struct sdhci_host *);
>>  static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
>> -static void sdhci_tuning_timer(unsigned long data);
>>  static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
>>  static int sdhci_pre_dma_transfer(struct sdhci_host *host,
>>                                         struct mmc_data *data,
>> @@ -252,17 +251,6 @@ static void sdhci_init(struct sdhci_host *host, int soft)
>>  static void sdhci_reinit(struct sdhci_host *host)
>>  {
>>         sdhci_init(host, 0);
>> -       /*
>> -        * Retuning stuffs are affected by different cards inserted and only
>> -        * applicable to UHS-I cards. So reset these fields to their initial
>> -        * value when card is removed.
>> -        */
>> -       if (host->flags & SDHCI_USING_RETUNING_TIMER) {
>> -               host->flags &= ~SDHCI_USING_RETUNING_TIMER;
>> -
>> -               del_timer_sync(&host->tuning_timer);
>> -               host->flags &= ~SDHCI_NEEDS_RETUNING;
>> -       }
>>         sdhci_enable_card_detection(host);
>>  }
>>
>> @@ -1350,7 +1338,6 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
>>         struct sdhci_host *host;
>>         int present;
>>         unsigned long flags;
>> -       u32 tuning_opcode;
>>
>>         host = mmc_priv(mmc);
>>
>> @@ -1399,39 +1386,6 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
>>                 host->mrq->cmd->error = -ENOMEDIUM;
>>                 tasklet_schedule(&host->finish_tasklet);
>>         } else {
>> -               u32 present_state;
>> -
>> -               present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
>> -               /*
>> -                * Check if the re-tuning timer has already expired and there
>> -                * is no on-going data transfer and DAT0 is not busy. If so,
>> -                * we need to execute tuning procedure before sending command.
>> -                */
>> -               if ((host->flags & SDHCI_NEEDS_RETUNING) &&
>> -                   !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ)) &&
>> -                   (present_state & SDHCI_DATA_0_LVL_MASK)) {
>> -                       if (mmc->card) {
>> -                               /* eMMC uses cmd21 but sd and sdio use cmd19 */
>> -                               tuning_opcode =
>> -                                       mmc->card->type == MMC_TYPE_MMC ?
>> -                                       MMC_SEND_TUNING_BLOCK_HS200 :
>> -                                       MMC_SEND_TUNING_BLOCK;
>> -
>> -                               /* Here we need to set the host->mrq to NULL,
>> -                                * in case the pending finish_tasklet
>> -                                * finishes it incorrectly.
>> -                                */
>> -                               host->mrq = NULL;
>> -
>> -                               spin_unlock_irqrestore(&host->lock, flags);
>> -                               sdhci_execute_tuning(mmc, tuning_opcode);
>> -                               spin_lock_irqsave(&host->lock, flags);
>> -
>> -                               /* Restore original mmc_request structure */
>> -                               host->mrq = mrq;
>> -                       }
>> -               }
>> -
>>                 if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
>>                         sdhci_send_command(host, mrq->sbc);
>>                 else
>> @@ -2077,23 +2031,19 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
>>         }
>>
>>  out:
>> -       host->flags &= ~SDHCI_NEEDS_RETUNING;
>> -
>>         if (tuning_count) {
>> -               host->flags |= SDHCI_USING_RETUNING_TIMER;
>> -               mod_timer(&host->tuning_timer, jiffies + tuning_count * HZ);
>> +               /*
>> +                * In case tuning fails, host controllers which support
>> +                * re-tuning can try tuning again at a later time, when the
>> +                * re-tuning timer expires.  So for these controllers, we
>> +                * return 0. Since there might be other controllers who do not
>> +                * have this capability, we return error for them.
>> +                */
>> +               err = 0;
>>         }
>>
>> -       /*
>> -        * In case tuning fails, host controllers which support re-tuning can
>> -        * try tuning again at a later time, when the re-tuning timer expires.
>> -        * So for these controllers, we return 0. Since there might be other
>> -        * controllers who do not have this capability, we return error for
>> -        * them. SDHCI_USING_RETUNING_TIMER means the host is currently using
>> -        * a retuning timer to do the retuning for the card.
>> -        */
>> -       if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
>> -               err = 0;
>> +       if (!err)
>> +               mmc_retune_enable(host->mmc, tuning_count);
>>
>>         sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
>>         sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
>> @@ -2349,20 +2299,6 @@ static void sdhci_timeout_timer(unsigned long data)
>>         spin_unlock_irqrestore(&host->lock, flags);
>>  }
>>
>> -static void sdhci_tuning_timer(unsigned long data)
>> -{
>> -       struct sdhci_host *host;
>> -       unsigned long flags;
>> -
>> -       host = (struct sdhci_host *)data;
>> -
>> -       spin_lock_irqsave(&host->lock, flags);
>> -
>> -       host->flags |= SDHCI_NEEDS_RETUNING;
>> -
>> -       spin_unlock_irqrestore(&host->lock, flags);
>> -}
>> -
>>  /*****************************************************************************\
>>   *                                                                           *
>>   * Interrupt handling                                                        *
>> @@ -2740,11 +2676,8 @@ int sdhci_suspend_host(struct sdhci_host *host)
>>  {
>>         sdhci_disable_card_detection(host);
>>
>> -       /* Disable tuning since we are suspending */
>> -       if (host->flags & SDHCI_USING_RETUNING_TIMER) {
>> -               del_timer_sync(&host->tuning_timer);
>> -               host->flags &= ~SDHCI_NEEDS_RETUNING;
>> -       }
>> +       mmc_retune_timer_stop(host->mmc);
>> +       mmc_retune_needed(host->mmc);
>>
>>         if (!device_may_wakeup(mmc_dev(host->mmc))) {
>>                 host->ier = 0;
>> @@ -2794,10 +2727,6 @@ int sdhci_resume_host(struct sdhci_host *host)
>>
>>         sdhci_enable_card_detection(host);
>>
>> -       /* Set the re-tuning expiration flag */
>> -       if (host->flags & SDHCI_USING_RETUNING_TIMER)
>> -               host->flags |= SDHCI_NEEDS_RETUNING;
>> -
>>         return ret;
>>  }
>>
>> @@ -2834,11 +2763,8 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
>>  {
>>         unsigned long flags;
>>
>> -       /* Disable tuning since we are suspending */
>> -       if (host->flags & SDHCI_USING_RETUNING_TIMER) {
>> -               del_timer_sync(&host->tuning_timer);
>> -               host->flags &= ~SDHCI_NEEDS_RETUNING;
>> -       }
>> +       mmc_retune_timer_stop(host->mmc);
> 
> I think this could give a deadlock.
> 
> What if the retuning is just about to start and thus sdhci's
> ->execute_tuning() callback has been invoked, which is waiting for the
> pm_runtime_get_sync() to return.

The re-tune timer is mmc_retune_timer() and it does not take any locks
so it can't deadlock.

> 
>> +       mmc_retune_needed(host->mmc);
> 
> This seems racy.
> 
> What if a new request has already been started from the mmc core
> (waiting for sdhci's ->request() callback to return). That would mean
> the mmc core won't detect that a retune was needed.

That is a good point. The host controller must not runtime suspend after
re-tuning until retuning is released. I can think of a couple of options:
	- move the retuning call into the ->request function
	- add extra host ops for the host to runtime resume/suspend


  reply	other threads:[~2015-03-09  8:39 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-29  9:00 [PATCH V2 00/15] mmc: host: Add facility to support re-tuning Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 01/15] " Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 02/15] mmc: core: Disable re-tuning when card is no longer initialized Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 03/15] mmc: core: Add support for re-tuning before each request Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 04/15] mmc: core: Check re-tuning before retrying Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 05/15] mmc: core: Hold re-tuning during switch commands Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 06/15] mmc: core: Hold re-tuning during erase commands Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 07/15] mmc: core: Hold re-tuning while bkops ongoing Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 08/15] mmc: mmc: Comment that callers need to hold re-tuning if the card is put to sleep Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 09/15] mmc: core: Separate out the mmc_switch status check so it can be re-used Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 10/15] mmc: core: Add support for HS400 re-tuning Adrian Hunter
2015-02-04 13:35   ` [PATCH V3 " Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 11/15] mmc: sdhci: Change to new way of doing re-tuning Adrian Hunter
2015-03-06 12:51   ` Ulf Hansson
2015-03-09  8:37     ` Adrian Hunter [this message]
2015-03-10 13:55       ` Ulf Hansson
2015-03-10 14:20         ` Adrian Hunter
2015-03-23 12:54           ` Ulf Hansson
2015-03-23 14:26             ` Adrian Hunter
2015-03-23 15:02               ` Ulf Hansson
2015-03-23 21:11                 ` Adrian Hunter
2015-03-24 21:12                   ` Ulf Hansson
2015-03-25 13:48                     ` Adrian Hunter
2015-03-26 16:06                       ` Ulf Hansson
2015-03-27  9:54                         ` Adrian Hunter
2015-03-27 12:04                           ` Adrian Hunter
2015-03-24  2:49               ` NeilBrown
2015-03-24  9:40                 ` Ulf Hansson
2015-01-29  9:00 ` [PATCH V2 12/15] mmc: sdhci: Flag re-tuning is needed on CRC or End-Bit errors Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 13/15] mmc: block: Check re-tuning in the recovery path Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 14/15] mmc: block: Retry data requests when re-tuning is needed Adrian Hunter
2015-02-27 12:55   ` [PATCH V3 14/15] mmc: block: Retry errored " Adrian Hunter
2015-01-29  9:00 ` [PATCH V2 15/15] mmc: core: Don't print reset warning if reset is not supported Adrian Hunter
2015-02-09  9:33   ` Arend van Spriel
2015-02-09  9:47     ` Adrian Hunter
2015-02-09 16:05       ` Johan Rudholm
2015-02-09  8:43 ` [PATCH V2 00/15] mmc: host: Add facility to support re-tuning Adrian Hunter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54FD5BDD.9060004@intel.com \
    --to=adrian.hunter@intel.com \
    --cc=aaron.lu@intel.com \
    --cc=alcooperx@gmail.com \
    --cc=arend@broadcom.com \
    --cc=chris@printf.net \
    --cc=girish.shivananjappa@linaro.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=prakity@nvidia.com \
    --cc=ulf.hansson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox