]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/mmc/card/block.c
drivers: use req op accessor
[karo-tx-linux.git] / drivers / mmc / card / block.c
index 8a0147dfed27d864d419de730499960c54bc202c..201a8719f6c417473b3e9ee70752d8e6fb58645a 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/capability.h>
 #include <linux/compat.h>
 #include <linux/pm_runtime.h>
+#include <linux/idr.h>
 
 #include <linux/mmc/ioctl.h>
 #include <linux/mmc/card.h>
@@ -78,14 +79,14 @@ static int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
 /*
  * We've only got one major, so number of mmcblk devices is
  * limited to (1 << 20) / number of minors per device.  It is also
- * currently limited by the size of the static bitmaps below.
+ * limited by the MAX_DEVICES below.
  */
 static int max_devices;
 
 #define MAX_DEVICES 256
 
-/* TODO: Replace these with struct ida */
-static DECLARE_BITMAP(dev_use, MAX_DEVICES);
+static DEFINE_IDA(mmc_blk_ida);
+static DEFINE_SPINLOCK(mmc_blk_lock);
 
 /*
  * There is one mmc_blk_data per slot.
@@ -178,7 +179,9 @@ static void mmc_blk_put(struct mmc_blk_data *md)
                int devidx = mmc_get_devidx(md->disk);
                blk_cleanup_queue(md->queue.queue);
 
-               __clear_bit(devidx, dev_use);
+               spin_lock(&mmc_blk_lock);
+               ida_remove(&mmc_blk_ida, devidx);
+               spin_unlock(&mmc_blk_lock);
 
                put_disk(md->disk);
                kfree(md);
@@ -615,6 +618,10 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 
        ioc_err = __mmc_blk_ioctl_cmd(card, md, idata);
 
+       /* Always switch back to main area after RPMB access */
+       if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+               mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
+
        mmc_put_card(card);
 
        err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
@@ -682,6 +689,10 @@ static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
        for (i = 0; i < num_of_cmds && !ioc_err; i++)
                ioc_err = __mmc_blk_ioctl_cmd(card, md, idata[i]);
 
+       /* Always switch back to main area after RPMB access */
+       if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+               mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
+
        mmc_put_card(card);
 
        /* copy to user if data and response */
@@ -745,16 +756,25 @@ static inline int mmc_blk_part_switch(struct mmc_card *card,
        if (mmc_card_mmc(card)) {
                u8 part_config = card->ext_csd.part_config;
 
+               if (md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
+                       mmc_retune_pause(card->host);
+
                part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
                part_config |= md->part_type;
 
                ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                                 EXT_CSD_PART_CONFIG, part_config,
                                 card->ext_csd.part_time);
-               if (ret)
+               if (ret) {
+                       if (md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
+                               mmc_retune_unpause(card->host);
                        return ret;
+               }
 
                card->ext_csd.part_config = part_config;
+
+               if (main_md->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB)
+                       mmc_retune_unpause(card->host);
        }
 
        main_md->part_curr = md->part_type;
@@ -945,16 +965,22 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
                        req->rq_disk->disk_name, "timed out", name, status);
 
                /* If the status cmd initially failed, retry the r/w cmd */
-               if (!status_valid)
+               if (!status_valid) {
+                       pr_err("%s: status not valid, retrying timeout\n",
+                               req->rq_disk->disk_name);
                        return ERR_RETRY;
+               }
 
                /*
                 * If it was a r/w cmd crc error, or illegal command
                 * (eg, issued in wrong state) then retry - we should
                 * have corrected the state problem above.
                 */
-               if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND))
+               if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND)) {
+                       pr_err("%s: command error, retrying timeout\n",
+                               req->rq_disk->disk_name);
                        return ERR_RETRY;
+               }
 
                /* Otherwise abort the command */
                return ERR_ABORT;
@@ -1696,8 +1722,7 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
                    !IS_ALIGNED(blk_rq_sectors(next), 8))
                        break;
 
-               if (next->cmd_flags & REQ_DISCARD ||
-                   next->cmd_flags & REQ_FLUSH)
+               if (req_op(next) == REQ_OP_DISCARD || next->cmd_flags & REQ_FLUSH)
                        break;
 
                if (rq_data_dir(cur) != rq_data_dir(next))
@@ -2138,7 +2163,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        }
 
        mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
-       if (cmd_flags & REQ_DISCARD) {
+       if (req && req_op(req) == REQ_OP_DISCARD) {
                /* complete ongoing async transfer before issuing discard */
                if (card->host->areq)
                        mmc_blk_issue_rw_rq(mq, NULL);
@@ -2162,7 +2187,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
 out:
        if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
-            (cmd_flags & MMC_REQ_SPECIAL_MASK))
+           mmc_req_is_special(req))
                /*
                 * Release host when there are no more requests
                 * and after special request(discard, flush) is done.
@@ -2189,10 +2214,23 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
        struct mmc_blk_data *md;
        int devidx, ret;
 
-       devidx = find_first_zero_bit(dev_use, max_devices);
-       if (devidx >= max_devices)
-               return ERR_PTR(-ENOSPC);
-       __set_bit(devidx, dev_use);
+again:
+       if (!ida_pre_get(&mmc_blk_ida, GFP_KERNEL))
+               return ERR_PTR(-ENOMEM);
+
+       spin_lock(&mmc_blk_lock);
+       ret = ida_get_new(&mmc_blk_ida, &devidx);
+       spin_unlock(&mmc_blk_lock);
+
+       if (ret == -EAGAIN)
+               goto again;
+       else if (ret)
+               return ERR_PTR(ret);
+
+       if (devidx >= max_devices) {
+               ret = -ENOSPC;
+               goto out;
+       }
 
        md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
        if (!md) {
@@ -2271,7 +2309,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
            ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
             card->ext_csd.rel_sectors)) {
                md->flags |= MMC_BLK_REL_WR;
-               blk_queue_flush(md->queue.queue, REQ_FLUSH | REQ_FUA);
+               blk_queue_write_cache(md->queue.queue, true, true);
        }
 
        if (mmc_card_mmc(card) &&
@@ -2289,6 +2327,9 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
  err_kfree:
        kfree(md);
  out:
+       spin_lock(&mmc_blk_lock);
+       ida_remove(&mmc_blk_ida, devidx);
+       spin_unlock(&mmc_blk_lock);
        return ERR_PTR(ret);
 }
 
@@ -2494,11 +2535,12 @@ static const struct mmc_fixup blk_fixups[] =
                  MMC_QUIRK_BLK_NO_CMD23),
 
        /*
-        * Some Micron MMC cards needs longer data read timeout than
-        * indicated in CSD.
+        * Some MMC cards need longer data read timeout than indicated in CSD.
         */
        MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
                  MMC_QUIRK_LONG_READ_TIME),
+       MMC_FIXUP("008GE0", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_LONG_READ_TIME),
 
        /*
         * On these Samsung MoviNAND parts, performing secure erase or