Re: [PATCH v3] mmc: core: Fix the HPI execution sequence

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jun 21, 2012 at 4:38 PM, Subhash Jadavani
<subhashj@xxxxxxxxxxxxxx> wrote:
>
>
>> -----Original Message-----
>> From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc-
>> owner@xxxxxxxxxxxxxxx] On Behalf Of S, Venkatraman
>> Sent: Thursday, June 21, 2012 12:55 PM
>> To: Subhash Jadavani
>> Cc: cjb@xxxxxxxxxx; linux-mmc@xxxxxxxxxxxxxxx; linkinjeon@xxxxxxxxx;
>> jh80.chung@xxxxxxxxxxx; alex.lemberg@xxxxxxxxxxx; Kostya
>> Subject: Re: [PATCH v3] mmc: core: Fix the HPI execution sequence
>>
>> On Wed, Jun 20, 2012 at 11:29 PM, Subhash Jadavani
>> <subhashj@xxxxxxxxxxxxxx> wrote:
>> > Hi Venkatraman,
>> >
>> >> -----Original Message-----
>> >> From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc-
>> >> owner@xxxxxxxxxxxxxxx] On Behalf Of Venkatraman S
>> >> Sent: Wednesday, June 20, 2012 3:04 PM
>> >> To: cjb@xxxxxxxxxx
>> >> Cc: linux-mmc@xxxxxxxxxxxxxxx; linkinjeon@xxxxxxxxx;
>> >> jh80.chung@xxxxxxxxxxx; alex.lemberg@xxxxxxxxxxx; Venkatraman S;
>> >> Kostya
>> >> Subject: [PATCH v3] mmc: core: Fix the HPI execution sequence
>> >>
>> >> mmc_execute_hpi should send the HPI command only once, and only if
>> >> the card is in PRG state.
>> >>
>> >> According to eMMC spec, the command's completion time is not
>> >> dependent on OUT_OF_INTERRUPT_TIME. Only the transition out of PRG
>> >> STATE is guarded by OUT_OF_INTERRUPT_TIME - which is defined to begin
>> >> at the end of sending the command itself.
>> >>
>> >> Specify the default timeout for the actual sending of HPI command,
>> >> and
>> > then
>> >> use OUT_OF_INTERRUPT_TIME to wait for the transition out of PRG state.
>> >
>> > I guess this is not the correct interpretation. cmd.cmd_timeout_ms
>> > should specify for how much time host driver should wait for command +
>> > busy line deassertion. So why are you keeping the timeout calculation
>> > after the command is completed?
>> >
>> If what you stay is correct, the card should be in PRG state after
>> mmc_send_hpi_cmd()
>> returns.
>
>>
>> I understood and observed it as opposite. HPI cmd returns immediately, and
> the
>> device takes OUT_OF_INTERRUPT_TIME time to come out of PRG state.
>>
>> My experiments / tests confirm that behavior. It takes a few ms (and
> several
>> SEND_STATUS messages later), after HPI, for the card to be out of PRG
> state.
>
> What is the HPI command in your case? CMD12 or CMD13? For command CMD12, we
> set the R1B flag which would tell the host driver to wait for the DAT0 line
> to be deasserted (if host controller support the automatic detection of DAT0
> de assertion).
> But HPI command is CMD13 then yes, driver will not wait for DAT0 line de
> assertion.
>
Yes, it has CMD13 - and it makes sense.

> Yes, so to support both CMD12 and CMD13 as HPI command, we can have 2
> options:
> 1.
>        - Set the R1B flag for CMD13 as well so controller waits for the
> PROG_DONE.
>        - Once mmc_send_hpi_cmd() returns, you can poll (without any
> timeout) until the card is out of programming state.
>
> 2.
>        - don't set the R1B flag for CMD13
>        - Once mmc_send_hpi_cmd() returns, if HPI command is CMD12, you can
> poll (without any timeout) until the card is out of programming state. But
> if HPI command is CMD13, poll until card is out of programming state with
> timeout.
>
> But in both of the above case, if host driver do not support automatic
> detection of DAT0 de assertion, we will have to send multiple CMD13
> (send_status) before card comes out of programming state but yes, in case

I think that's the case with OMAP, and I assumed it to be common.

> card gets stuck in programming state forever then we will end up sending
> CMD13 forever. In this case timeout based wait is fine. So if you want to
> take of case where card is stuck in programming state forever, your
> implementation is fine. Is this your intention here? I have few comments on
> your code below.
>
Yes - that was atleast the intention. I didn't assume DAT0 de assertation was
auto detectable, and even otherwise, PRG state was to be polled later
anyway.

> Regards,
> Subhash
>
>>
>> > mmc_send_hpi_cmd() returns means the host controller driver have
>> > ensured that BUSY indication is removed so after mmc_send_hpi_cmd(),
>> > if you want to check if the card is still in PROGRAMMING state, it
>> > should be unconditional check in loop (rather than timeout based)
>> > until card is out of programming state.
>> >
>> > To me, mmc_send_hpi_cmd() implementation should not be anything
>> > different than mmc_switch(). In mmc_switch() also, after
>> > mmc_wait_for_cmd() returns it continuously keeps checking if card is
>> programming or not.
>> >
>> > Regards,
>> > Subhash
>> >
>> >>
>> >> Reported-by: Alex Lemberg <Alex.Lemberg@xxxxxxxxxxx>
>> >> Signed-off-by: Venkatraman S <svenkatr@xxxxxx>
>> >> Reviewed-by: Namjae Jeon <linkinjeon@xxxxxxxxx>
>> >> Acked-by: Jaehoon Chung <jh80.chung@xxxxxxxxxxx>
>> >> CC: Kostya <kdorfman@xxxxxxxxxxxxxx>
>> >> ---
>> >> v2 discussions: http://marc.info/?l=linux-mmc&m=133657255616390&w=2
>> >>
>> >> v2->v3:
>> >>       Return gracefully for card idle states (suggested by kdorfman)
>> >>
>> >>  drivers/mmc/core/core.c    |   57
>> > ++++++++++++++++++++++++++-----------------
>> >> -
>> >>  drivers/mmc/core/mmc_ops.c |    1 -
>> >>  2 files changed, 34 insertions(+), 24 deletions(-)
>> >>
>> >> diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index
>> >> 80ec427..08ed144 100644
>> >> --- a/drivers/mmc/core/core.c
>> >> +++ b/drivers/mmc/core/core.c
>> >> @@ -404,6 +404,7 @@ int mmc_interrupt_hpi(struct mmc_card *card)  {
>> >>       int err;
>> >>       u32 status;
>> >> +     unsigned long starttime;
>> >>
>> >>       BUG_ON(!card);
>> >>
>> >> @@ -419,30 +420,40 @@ int mmc_interrupt_hpi(struct mmc_card *card)
>> >>               goto out;
>> >>       }
>> >>
>> >> -     /*
>> >> -      * If the card status is in PRG-state, we can send the HPI
> command.
>> >> -      */
>> >> -     if (R1_CURRENT_STATE(status) == R1_STATE_PRG) {
>> >> -             do {
>> >> -                     /*
>> >> -                      * We don't know when the HPI command will
>> >> finish
>> >> -                      * processing, so we need to resend HPI until
>> >> out
>> >> -                      * of prg-state, and keep checking the card
>> >> status
>> >> -                      * with SEND_STATUS.  If a timeout error occurs
>> >> when
>> >> -                      * sending the HPI command, we are already out
>> >> of
>> >> -                      * prg-state.
>> >> -                      */
>> >> -                     err = mmc_send_hpi_cmd(card, &status);
>> >> -                     if (err)
>> >> -                             pr_debug("%s: abort HPI (%d error)\n",
>> >> -                                      mmc_hostname(card->host),
>> >> err);
>> >> +     switch (R1_CURRENT_STATE(status)) {
>> >>
>> >> -                     err = mmc_send_status(card, &status);
>> >> -                     if (err)
>> >> -                             break;
>> >> -             } while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
>> >> -     } else
>> >> -             pr_debug("%s: Left prg-state\n",
>> >> mmc_hostname(card->host));
>> >> +     case R1_STATE_IDLE:
>> >> +     case R1_STATE_READY:
>> >> +     case R1_STATE_STBY: /* intentional fall through */
>> >> +             /* In idle states, HPI is not needed and the caller
>> >> +              can issue the next intended command immediately */
>> >> +             goto out;
>> >> +             break;
>> >> +     case R1_STATE_PRG:
>> >> +             break;
>> >> +     default:
>> >> +             /* In all other states, it's illegal to issue HPI */
>> >> +             pr_debug("%s: HPI cannot be sent. Card state=%d\n",
>> >> +                     mmc_hostname(card->host),
>> >> R1_CURRENT_STATE(status));
>> >> +             err = -EINVAL;
>> >> +             goto out;
>> >> +             break;
>> >> +     }
>> >> +
>> >> +     starttime = jiffies;
>> >> +     err = mmc_send_hpi_cmd(card, &status);
>> >> +     if (err)
>> >> +             goto out;
>> >> +
>> >> +     do {
>> >> +             err = mmc_send_status(card, &status);
>> >> +
>> >> +             if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN)
>> >> +                     break;
>> >> +             if (jiffies_to_msecs(jiffies - starttime) >=
>> >> +                     card->ext_csd.out_of_int_time)
>
> When you are comparing snapshot of 2 different jiffies, you should be using
> time_after() or time_before() macros others this will not take case of
> jiffies wraparound.

Ok- I'll send out an updated version.
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux