From a2d1086de6cc3ae2378d9db8b92712911c9e5fef Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 16 Dec 2013 14:37:26 +0100 Subject: mmc: card: Remove host cap MMC_CAP2_SANITIZE There is no need for keeping a host cap for MMC_CAP2_SANITIZE, instead we just make the feature default available. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mmc/card') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 7b5424f398ac..c2187d5e9070 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -415,8 +415,7 @@ static int ioctl_do_sanitize(struct mmc_card *card) { int err; - if (!(mmc_can_sanitize(card) && - (card->host->caps2 & MMC_CAP2_SANITIZE))) { + if (!mmc_can_sanitize(card)) { pr_warn("%s: %s - SANITIZE is not supported\n", mmc_hostname(card->host), __func__); err = -EOPNOTSUPP; -- cgit v1.2.3-59-g8ed1b From bcc3e1726d827c2d6f62f0e0e7bbc99eed7ad925 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 14 Jan 2014 21:24:21 +0100 Subject: mmc: block: Use R1 responses for stop cmds for read requests While using open ended transmission and thus ending the transfer by sending a stop command, we shall use R1B only for writes and R1 shall be used for reads. Previously R1B were used in both cases. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/mmc/card') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c2187d5e9070..156cabfa61c3 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1334,7 +1334,6 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, brq->data.blksz = 512; brq->stop.opcode = MMC_STOP_TRANSMISSION; brq->stop.arg = 0; - brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; brq->data.blocks = blk_rq_sectors(req); /* @@ -1377,9 +1376,15 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, if (rq_data_dir(req) == READ) { brq->cmd.opcode = readcmd; brq->data.flags |= MMC_DATA_READ; + if (brq->mrq.stop) + brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | + MMC_CMD_AC; } else { brq->cmd.opcode = writecmd; brq->data.flags |= MMC_DATA_WRITE; + if (brq->mrq.stop) + brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | + MMC_CMD_AC; } if (do_rel_wr) -- cgit v1.2.3-59-g8ed1b From c49433fb66935bd01930e37c7f47d38b6f8135fc Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 29 Jan 2014 11:01:55 +0100 Subject: 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 Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 82 +++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 35 deletions(-) (limited to 'drivers/mmc/card') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 156cabfa61c3..fffa83359c67 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -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,39 +1209,9 @@ 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); - 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)); + err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &gen_err); + if (err) + return MMC_BLK_CMD_ERR; } /* if general error occurs, retry the write operation. */ -- cgit v1.2.3-59-g8ed1b From 95a91298fc09db0c21193ace96d1934598dd92dd Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 29 Jan 2014 13:11:27 +0100 Subject: mmc: block: Respect hw busy detection in card_busy_detect() Currently for write request we don't trust the hw busy detection to be fully handled by host, thus we also poll the card's status until we see it's gets out of the busy state. Still there are scenarios where it will a benefit to trust the hw busy detection done by the host, since no additional polling is needed. Let's prepare card_busy_detect() to be able to handle this. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/mmc/card') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index fffa83359c67..813ec83b74c9 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -750,7 +750,7 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries) } static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, - struct request *req, int *gen_err) + bool hw_busy_detect, struct request *req, int *gen_err) { unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); int err = 0; @@ -770,6 +770,11 @@ static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, *gen_err = 1; } + /* We may rely on the host hw to handle busy detection.*/ + if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) && + hw_busy_detect) + break; + /* * Timeout if the device never becomes ready for data and never * leaves the program state. @@ -1209,7 +1214,8 @@ static int mmc_blk_err_check(struct mmc_card *card, gen_err = 1; } - err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &gen_err); + err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req, + &gen_err); if (err) return MMC_BLK_CMD_ERR; } -- cgit v1.2.3-59-g8ed1b From bb5cba40dc7f079ea7ee3ae760b7c388b6eb5fc3 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 14 Jan 2014 21:31:35 +0100 Subject: mmc: block: Fixup busy detection while invoking stop cmd at recovery When sending a stop command at the recovery path, use a R1B response when the failing data request are a WRITE. Thus we also care about the busy detection completion in this case. For a failing READ request, we use a R1 response for the stop command, since we don't need to care about busy detection in this case. To align behavior between hosts supporting MMC_CAP_WAIT_WHILE_BUSY and those who are not, we add a CMD13 polling method for the card's status. We also respect whether the host has specified the max_busy_timeout, which means we may fallback to CMD13 polling if the timeout is greater than what the host are able to support. Signed-off-by: Ulf Hansson Signed-off-by: Chris Ball --- drivers/mmc/card/block.c | 83 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 28 deletions(-) (limited to 'drivers/mmc/card') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 813ec83b74c9..452782bffebc 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -721,19 +721,6 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card) return result; } -static int send_stop(struct mmc_card *card, u32 *status) -{ - struct mmc_command cmd = {0}; - int err; - - cmd.opcode = MMC_STOP_TRANSMISSION; - cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; - err = mmc_wait_for_cmd(card->host, &cmd, 5); - if (err == 0) - *status = cmd.resp[0]; - return err; -} - static int get_card_status(struct mmc_card *card, u32 *status, int retries) { struct mmc_command cmd = {0}; @@ -797,6 +784,51 @@ static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms, return err; } +static int send_stop(struct mmc_card *card, unsigned int timeout_ms, + struct request *req, int *gen_err, u32 *stop_status) +{ + struct mmc_host *host = card->host; + struct mmc_command cmd = {0}; + int err; + bool use_r1b_resp = rq_data_dir(req) == WRITE; + + /* + * Normally we use R1B responses for WRITE, but in cases where the host + * has specified a max_busy_timeout we need to validate it. A failure + * means we need to prevent the host from doing hw busy detection, which + * is done by converting to a R1 response instead. + */ + if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) + use_r1b_resp = false; + + cmd.opcode = MMC_STOP_TRANSMISSION; + if (use_r1b_resp) { + cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; + cmd.busy_timeout = timeout_ms; + } else { + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + } + + err = mmc_wait_for_cmd(host, &cmd, 5); + if (err) + return err; + + *stop_status = cmd.resp[0]; + + /* No need to check card status in case of READ. */ + if (rq_data_dir(req) == READ) + return 0; + + if (!mmc_host_is_spi(host) && + (*stop_status & R1_ERROR)) { + pr_err("%s: %s: general error sending stop command, resp %#x\n", + req->rq_disk->disk_name, __func__, *stop_status); + *gen_err = 1; + } + + return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err); +} + #define ERR_NOMEDIUM 3 #define ERR_RETRY 2 #define ERR_ABORT 1 @@ -913,26 +945,21 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, */ if (R1_CURRENT_STATE(status) == R1_STATE_DATA || R1_CURRENT_STATE(status) == R1_STATE_RCV) { - err = send_stop(card, &stop_status); - if (err) + err = send_stop(card, + DIV_ROUND_UP(brq->data.timeout_ns, 1000000), + req, gen_err, &stop_status); + if (err) { pr_err("%s: error %d sending stop command\n", req->rq_disk->disk_name, err); - - /* - * If the stop cmd also timed out, the card is probably - * not present, so abort. Other errors are bad news too. - */ - if (err) + /* + * If the stop cmd also timed out, the card is probably + * not present, so abort. Other errors are bad news too. + */ return ERR_ABORT; + } + if (stop_status & R1_CARD_ECC_FAILED) *ecc_err = 1; - if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) - if (stop_status & R1_ERROR) { - pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", - req->rq_disk->disk_name, __func__, - stop_status); - *gen_err = 1; - } } /* Check for set block count errors */ -- cgit v1.2.3-59-g8ed1b