Re: [PATCH 1/1] CMD12 error recovery support for SD cards

Mahadev Cholachagudda
2009-09-23T08:50:15Z

Dear Sir,

Any comments on this.

Regards,
Mahadev

2009/9/16 Mahadev Cholachagudda <mgudda@gmail.com>:
> Dear All,
>
> I've a kernel code base of 2.6.28.9, where in I find that CMD12 error
> recovery is not been implemented. It is a wise idea to implement CMD12
> error recovery, that involves sending CMD13 to get the status of the
> card. If the card is in "trans" state, it means CMD12 error shall be
> treated as successfull. If card state is not in "trans", then we have
> to send CMD12 again to stop the data transfer and then checking of the
> card status through CMD13. This sequence is detailed in the
> "Simplified Host Controller specification" on SDCard website. I
> believe this is the case for any controller, though I may be wrong.
>
> With the modification done to the code which is attached as patch to
> the latest mmc git, it is working at our site. And we do see some
> errors with the SDIO controller (proprietary but meets Standard SD
> host controller specification) that we are using.
>
> Request you to comment on the patch.
>
> diff -urNd linux-orig/drivers/mmc/card/block.c
> linux-current/drivers/mmc/card/block.c
> --- linux-orig/drivers/mmc/card/block.c    2009-09-16 15:43:03.667274139 +0530
> +++ linux-current/drivers/mmc/card/block.c    2009-09-16
> 15:36:24.722272962 +0530
> @@ -335,6 +335,76 @@
>           * until later as we need to wait for the card to leave
>           * programming mode even when things go wrong.
>           */
> +
> +    /* cmd12 error recovery fix */
> +    if( (brq.stop.error) && (brq.data.blocks > 1) &&
> !mmc_host_is_spi(card->host) &&
> +        mmc_card_sd(card) ) {
> +
> +      struct mmc_request my_mrq;
> +      struct mmc_command my_cmd;
> +
> +      /*
> +       * if there is an error for CMD12, get the state of the card by
> +       * sending cmd13 and then check the state of the card.
> +       * If the card state is "tran", consider the cmd12 is successfull
> +       * If not, then send again CMD12 to stop the data transfer. This time,
> +       * any failure to get response, will result in to the card being
> +       * non-recoverable.
> +       */
> +
> +      memset(&my_mrq, 0, sizeof(struct mmc_request));
> +      memset(&my_cmd, 0, sizeof(struct mmc_command));
> +      my_cmd.opcode = MMC_SEND_STATUS;
> +      my_cmd.arg = card->rca << 16;
> +      my_cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
> +      my_mrq.cmd = &my_cmd;
> +      mmc_wait_for_req(card->host, &my_mrq);
> +
> +      if(!my_mrq.cmd->error) {
> +        if(R1_CURRENT_STATE(my_cmd.resp[0]) == 4) {
> +          /* card is in "trans" state, so treat the CMD12 as succesfull */
> +          brq.stop.error = 0;
> +        }
> +        else {
> +          /*
> +           * card is not still in trans state. Now send CMD12 again and repeat
> +           * the process of checking the card status using CMD13
> +           */
> +          memset(&my_cmd, 0, sizeof(struct mmc_command));
> +          my_cmd.opcode = MMC_STOP_TRANSMISSION;
> +          my_cmd.arg = 0;
> +          my_cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
> +          my_mrq.cmd = &my_cmd;
> +          mmc_wait_for_req(card->host, &my_mrq);
> +
> +          /* get the card status */
> +          memset(&my_cmd, 0, sizeof(struct mmc_command));
> +          my_cmd.opcode = MMC_SEND_STATUS;
> +          my_cmd.arg = card->rca << 16;
> +          my_cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
> +          my_mrq.cmd = &my_cmd;
> +          mmc_wait_for_req(card->host, &my_mrq);
> +
> +          if(!my_mrq.cmd->error) {
> +            if(R1_CURRENT_STATE(my_cmd.resp[0]) == 4) {
> +              /* card is in "trans" state, so treat the CMD12 as succesfull */
> +              brq.stop.error = 0;
> +            }
> +            else {
> +              /*
> +               * card is not in "trans" state yet. Just post an error and
> +               * error is not recoverable
> +               */
> +            }
> +          }
> +          else {
> +            /* error for cmd13!!, then something is wrong with the card */
> +          }
> +        }
> +      }
> +    }
> +    /* cmd12 error recovery fix */
> +
>          if (brq.cmd.error || brq.data.error || brq.stop.error) {
>              if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
>                  /* Redo read one sector at a time */
>
> Regards,
> Mahadev Cholachagudda
>

--
Cheers,
Mahadev