mmc: block: Disable Command Queue while RPMB is used
authorAdrian Hunter <adrian.hunter@intel.com>
Mon, 13 Mar 2017 12:36:39 +0000 (14:36 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 24 Apr 2017 19:42:03 +0000 (21:42 +0200)
RPMB does not allow Command Queue commands. Disable and re-enable the
Command Queue when switching.

Note that the driver only switches partitions when the queue is empty.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Harjani Ritesh <riteshh@codeaurora.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/core/block.c

index 018488e7f194bdf80e5c5c8d2fa4eb16dbe1b613..d189e8c4436e2f96bf0b6c9302bed1a6a952f76f 100644 (file)
@@ -728,10 +728,41 @@ static const struct block_device_operations mmc_bdops = {
 #endif
 };
 
+static int mmc_blk_part_switch_pre(struct mmc_card *card,
+                                  unsigned int part_type)
+{
+       int ret = 0;
+
+       if (part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
+               if (card->ext_csd.cmdq_en) {
+                       ret = mmc_cmdq_disable(card);
+                       if (ret)
+                               return ret;
+               }
+               mmc_retune_pause(card->host);
+       }
+
+       return ret;
+}
+
+static int mmc_blk_part_switch_post(struct mmc_card *card,
+                                   unsigned int part_type)
+{
+       int ret = 0;
+
+       if (part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
+               mmc_retune_unpause(card->host);
+               if (card->reenable_cmdq && !card->ext_csd.cmdq_en)
+                       ret = mmc_cmdq_enable(card);
+       }
+
+       return ret;
+}
+
 static inline int mmc_blk_part_switch(struct mmc_card *card,
                                      struct mmc_blk_data *md)
 {
-       int ret;
+       int ret = 0;
        struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
 
        if (main_md->part_curr == md->part_type)
@@ -740,8 +771,9 @@ 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);
+               ret = mmc_blk_part_switch_pre(card, md->part_type);
+               if (ret)
+                       return ret;
 
                part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
                part_config |= md->part_type;
@@ -750,19 +782,17 @@ static inline int mmc_blk_part_switch(struct mmc_card *card,
                                 EXT_CSD_PART_CONFIG, part_config,
                                 card->ext_csd.part_time);
                if (ret) {
-                       if (md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
-                               mmc_retune_unpause(card->host);
+                       mmc_blk_part_switch_post(card, md->part_type);
                        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);
+               ret = mmc_blk_part_switch_post(card, main_md->part_curr);
        }
 
        main_md->part_curr = md->part_type;
-       return 0;
+       return ret;
 }
 
 static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks)