mmc: block: replace __blk_end_request() with blk_end_request()
[pandora-kernel.git] / drivers / mmc / card / block.c
index 74793af..bbbb91e 100644 (file)
@@ -119,6 +119,7 @@ enum mmc_blk_status {
        MMC_BLK_ABORT,
        MMC_BLK_DATA_ERR,
        MMC_BLK_ECC_ERR,
+       MMC_BLK_NOMEDIUM,
 };
 
 module_param(perdev_minors, int, 0444);
@@ -318,7 +319,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
        md = mmc_blk_get(bdev->bd_disk);
        if (!md) {
                err = -EINVAL;
-               goto cmd_done;
+               goto cmd_err;
        }
 
        card = md->queue.card;
@@ -417,6 +418,7 @@ cmd_rel_host:
 
 cmd_done:
        mmc_blk_put(md);
+cmd_err:
        kfree(idata->buf);
        kfree(idata);
        return err;
@@ -487,7 +489,6 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
        struct mmc_request mrq = {NULL};
        struct mmc_command cmd = {0};
        struct mmc_data data = {0};
-       unsigned int timeout_us;
 
        struct scatterlist sg;
 
@@ -507,23 +508,12 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
        cmd.arg = 0;
        cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
 
-       data.timeout_ns = card->csd.tacc_ns * 100;
-       data.timeout_clks = card->csd.tacc_clks * 100;
-
-       timeout_us = data.timeout_ns / 1000;
-       timeout_us += data.timeout_clks * 1000 /
-               (card->host->ios.clock / 1000);
-
-       if (timeout_us > 100000) {
-               data.timeout_ns = 100000000;
-               data.timeout_clks = 0;
-       }
-
        data.blksz = 4;
        data.blocks = 1;
        data.flags = MMC_DATA_READ;
        data.sg = &sg;
        data.sg_len = 1;
+       mmc_set_data_timeout(&data, card);
 
        mrq.cmd = &cmd;
        mrq.data = &data;
@@ -573,6 +563,7 @@ static int get_card_status(struct mmc_card *card, u32 *status, int retries)
        return err;
 }
 
+#define ERR_NOMEDIUM   3
 #define ERR_RETRY      2
 #define ERR_ABORT      1
 #define ERR_CONTINUE   0
@@ -634,12 +625,15 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
  * Otherwise we don't understand what happened, so abort.
  */
 static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
-       struct mmc_blk_request *brq, int *ecc_err)
+       struct mmc_blk_request *brq, int *ecc_err, int *gen_err)
 {
        bool prev_cmd_status_valid = true;
        u32 status, stop_status = 0;
        int err, retry;
 
+       if (mmc_card_removed(card))
+               return ERR_NOMEDIUM;
+
        /*
         * Try to get card status which indicates both the card state
         * and why there was no response.  If the first attempt fails,
@@ -656,8 +650,12 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
        }
 
        /* We couldn't get a response from the card.  Give up. */
-       if (err)
+       if (err) {
+               /* Check if the card is removed */
+               if (mmc_detect_card_removed(card->host))
+                       return ERR_NOMEDIUM;
                return ERR_ABORT;
+       }
 
        /* Flag ECC errors */
        if ((status & R1_CARD_ECC_FAILED) ||
@@ -665,6 +663,16 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
            (brq->cmd.resp[0] & R1_CARD_ECC_FAILED))
                *ecc_err = 1;
 
+       /* Flag General errors */
+       if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
+               if ((status & R1_ERROR) ||
+                       (brq->stop.resp[0] & R1_ERROR)) {
+                       pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
+                              req->rq_disk->disk_name, __func__,
+                              brq->stop.resp[0], status);
+                       *gen_err = 1;
+               }
+
        /*
         * Check the current card state.  If it is in some data transfer
         * mode, tell it to stop (and hopefully transition back to TRAN.)
@@ -684,6 +692,13 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
                        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 */
@@ -787,9 +802,7 @@ out:
                goto retry;
        if (!err)
                mmc_blk_reset_success(md, type);
-       spin_lock_irq(&md->lock);
-       __blk_end_request(req, err, blk_rq_bytes(req));
-       spin_unlock_irq(&md->lock);
+       blk_end_request(req, err, blk_rq_bytes(req));
 
        return err ? 0 : 1;
 }
@@ -871,9 +884,7 @@ out_retry:
        if (!err)
                mmc_blk_reset_success(md, type);
 out:
-       spin_lock_irq(&md->lock);
-       __blk_end_request(req, err, blk_rq_bytes(req));
-       spin_unlock_irq(&md->lock);
+       blk_end_request(req, err, blk_rq_bytes(req));
 
        return err ? 0 : 1;
 }
@@ -888,9 +899,7 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
        if (ret)
                ret = -EIO;
 
-       spin_lock_irq(&md->lock);
-       __blk_end_request_all(req, ret);
-       spin_unlock_irq(&md->lock);
+       blk_end_request_all(req, ret);
 
        return ret ? 0 : 1;
 }
@@ -933,7 +942,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
                                                    mmc_active);
        struct mmc_blk_request *brq = &mq_mrq->brq;
        struct request *req = mq_mrq->req;
-       int ecc_err = 0;
+       int ecc_err = 0, gen_err = 0;
 
        /*
         * sbc.error indicates a problem with the set block count
@@ -947,11 +956,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
         */
        if (brq->sbc.error || brq->cmd.error || brq->stop.error ||
            brq->data.error) {
-               switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) {
+               switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
                case ERR_RETRY:
                        return MMC_BLK_RETRY;
                case ERR_ABORT:
                        return MMC_BLK_ABORT;
+               case ERR_NOMEDIUM:
+                       return MMC_BLK_NOMEDIUM;
                case ERR_CONTINUE:
                        break;
                }
@@ -975,6 +986,15 @@ static int mmc_blk_err_check(struct mmc_card *card,
         */
        if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
                u32 status;
+
+               /* Check stop command response */
+               if (brq->stop.resp[0] & R1_ERROR) {
+                       pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
+                              req->rq_disk->disk_name, __func__,
+                              brq->stop.resp[0]);
+                       gen_err = 1;
+               }
+
                do {
                        int err = get_card_status(card, &status, 5);
                        if (err) {
@@ -982,6 +1002,14 @@ static int mmc_blk_err_check(struct mmc_card *card,
                                       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;
+                       }
+
                        /*
                         * Some cards mishandle the status bits,
                         * so make sure to check both the busy
@@ -991,6 +1019,13 @@ static int mmc_blk_err_check(struct mmc_card *card,
                         (R1_CURRENT_STATE(status) == R1_STATE_PRG));
        }
 
+       /* if general error occurs, retry the write operation. */
+       if (gen_err) {
+               pr_warning("%s: retrying write for general error\n",
+                               req->rq_disk->disk_name);
+               return MMC_BLK_RETRY;
+       }
+
        if (brq->data.error) {
                pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
                       req->rq_disk->disk_name, brq->data.error,
@@ -1176,14 +1211,10 @@ static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
 
                blocks = mmc_sd_num_wr_blocks(card);
                if (blocks != (u32)-1) {
-                       spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, 0, blocks << 9);
-                       spin_unlock_irq(&md->lock);
+                       ret = blk_end_request(req, 0, blocks << 9);
                }
        } else {
-               spin_lock_irq(&md->lock);
-               ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
-               spin_unlock_irq(&md->lock);
+               ret = blk_end_request(req, 0, brq->data.bytes_xfered);
        }
        return ret;
 }
@@ -1225,10 +1256,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
                         * A block was successfully transferred.
                         */
                        mmc_blk_reset_success(md, type);
-                       spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, 0,
+                       ret = blk_end_request(req, 0,
                                                brq->data.bytes_xfered);
-                       spin_unlock_irq(&md->lock);
                        /*
                         * If the blk_end_request function returns non-zero even
                         * though all data has been transferred and no errors
@@ -1278,13 +1307,13 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
                         * time, so we only reach here after trying to
                         * read a single sector.
                         */
-                       spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, -EIO,
+                       ret = blk_end_request(req, -EIO,
                                                brq->data.blksz);
-                       spin_unlock_irq(&md->lock);
                        if (!ret)
                                goto start_new_req;
                        break;
+               case MMC_BLK_NOMEDIUM:
+                       goto cmd_abort;
                }
 
                if (ret) {
@@ -1300,10 +1329,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
        return 1;
 
  cmd_abort:
-       spin_lock_irq(&md->lock);
+       if (mmc_card_removed(card))
+               req->cmd_flags |= REQ_QUIET;
        while (ret)
-               ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
-       spin_unlock_irq(&md->lock);
+               ret = blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
 
  start_new_req:
        if (rqc) {
@@ -1327,9 +1356,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        ret = mmc_blk_part_switch(card, md);
        if (ret) {
                if (req) {
-                       spin_lock_irq(&md->lock);
-                       __blk_end_request_all(req, -EIO);
-                       spin_unlock_irq(&md->lock);
+                       blk_end_request_all(req, -EIO);
                }
                ret = 0;
                goto out;
@@ -1732,7 +1759,7 @@ static void mmc_blk_remove(struct mmc_card *card)
 }
 
 #ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
+static int mmc_blk_suspend(struct mmc_card *card)
 {
        struct mmc_blk_data *part_md;
        struct mmc_blk_data *md = mmc_get_drvdata(card);