mmc: block: Implement card_busy_detect() for busy detection
To complete a data write request we poll for the card's status register by sending CMD13. The are other scenarios when this polling method are needed, which is why we here moves this code to it's own function. No functional change. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Chris Ball <chris@printf.net>
This commit is contained in:
parent
bcc3e1726d
commit
c49433fb66
1 changed files with 47 additions and 35 deletions
|
@ -749,6 +749,49 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
|
||||
struct request *req, int *gen_err)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
|
||||
int err = 0;
|
||||
u32 status;
|
||||
|
||||
do {
|
||||
err = get_card_status(card, &status, 5);
|
||||
if (err) {
|
||||
pr_err("%s: error %d requesting status\n",
|
||||
req->rq_disk->disk_name, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (status & R1_ERROR) {
|
||||
pr_err("%s: %s: error sending status cmd, status %#x\n",
|
||||
req->rq_disk->disk_name, __func__, status);
|
||||
*gen_err = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timeout if the device never becomes ready for data and never
|
||||
* leaves the program state.
|
||||
*/
|
||||
if (time_after(jiffies, timeout)) {
|
||||
pr_err("%s: Card stuck in programming state! %s %s\n",
|
||||
mmc_hostname(card->host),
|
||||
req->rq_disk->disk_name, __func__);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some cards mishandle the status bits,
|
||||
* so make sure to check both the busy
|
||||
* indication and the card state.
|
||||
*/
|
||||
} while (!(status & R1_READY_FOR_DATA) ||
|
||||
(R1_CURRENT_STATE(status) == R1_STATE_PRG));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#define ERR_NOMEDIUM 3
|
||||
#define ERR_RETRY 2
|
||||
#define ERR_ABORT 1
|
||||
|
@ -1156,8 +1199,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|||
* program mode, which we have to wait for it to complete.
|
||||
*/
|
||||
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
|
||||
u32 status;
|
||||
unsigned long timeout;
|
||||
int err;
|
||||
|
||||
/* Check stop command response */
|
||||
if (brq->stop.resp[0] & R1_ERROR) {
|
||||
|
@ -1167,41 +1209,11 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
|||
gen_err = 1;
|
||||
}
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
|
||||
do {
|
||||
int err = get_card_status(card, &status, 5);
|
||||
if (err) {
|
||||
pr_err("%s: error %d requesting status\n",
|
||||
req->rq_disk->disk_name, err);
|
||||
err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &gen_err);
|
||||
if (err)
|
||||
return MMC_BLK_CMD_ERR;
|
||||
}
|
||||
|
||||
if (status & R1_ERROR) {
|
||||
pr_err("%s: %s: general error sending status command, card status %#x\n",
|
||||
req->rq_disk->disk_name, __func__,
|
||||
status);
|
||||
gen_err = 1;
|
||||
}
|
||||
|
||||
/* Timeout if the device never becomes ready for data
|
||||
* and never leaves the program state.
|
||||
*/
|
||||
if (time_after(jiffies, timeout)) {
|
||||
pr_err("%s: Card stuck in programming state!"\
|
||||
" %s %s\n", mmc_hostname(card->host),
|
||||
req->rq_disk->disk_name, __func__);
|
||||
|
||||
return MMC_BLK_CMD_ERR;
|
||||
}
|
||||
/*
|
||||
* Some cards mishandle the status bits,
|
||||
* so make sure to check both the busy
|
||||
* indication and the card state.
|
||||
*/
|
||||
} while (!(status & R1_READY_FOR_DATA) ||
|
||||
(R1_CURRENT_STATE(status) == R1_STATE_PRG));
|
||||
}
|
||||
|
||||
/* if general error occurs, retry the write operation. */
|
||||
if (gen_err) {
|
||||
pr_warn("%s: retrying write for general error\n",
|
||||
|
|
Loading…
Reference in a new issue