Dear Sir, Any comments on this. Regards, Mahadev 2009/9/16 Mahadev Cholachagudda <mgudda@xxxxxxxxx>: > 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 -- 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