|
@@ -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. */
|