Merge tag 'lsk-v3.10-15.05-android' into develop-3.10
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / card / block.c
old mode 100644 (file)
new mode 100755 (executable)
index d813cb9..355c18f
@@ -34,9 +34,8 @@
 #include <linux/delay.h>
 #include <linux/capability.h>
 #include <linux/compat.h>
+#include <linux/pm_runtime.h>
 
-#define CREATE_TRACE_POINTS
-#include <trace/events/mmc.h>
 
 #include <linux/mmc/ioctl.h>
 #include <linux/mmc/card.h>
@@ -61,6 +60,8 @@ MODULE_ALIAS("mmc:block");
 #define INAND_CMD38_ARG_SECTRIM1 0x81
 #define INAND_CMD38_ARG_SECTRIM2 0x88
 #define MMC_BLK_TIMEOUT_MS  (10 * 60 * 1000)        /* 10 minute timeout */
+#define MMC_SANITIZE_REQ_TIMEOUT 240000
+#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
 
 #define mmc_req_rel_wr(req)    (((req->cmd_flags & REQ_FUA) || \
                                  (req->cmd_flags & REQ_META)) && \
@@ -221,7 +222,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
        md = mmc_blk_get(dev_to_disk(dev));
        card = md->queue.card;
 
-       mmc_claim_host(card->host);
+       mmc_get_card(card);
 
        ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
                                card->ext_csd.boot_ro_lock |
@@ -232,7 +233,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
        else
                card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
 
-       mmc_release_host(card->host);
+       mmc_put_card(card);
 
        if (!ret) {
                pr_info("%s: Locking boot partition ro until next power on\n",
@@ -407,6 +408,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
        return err;
 }
 
+static int ioctl_do_sanitize(struct mmc_card *card)
+{
+       int err;
+
+       if (!(mmc_can_sanitize(card) &&
+             (card->host->caps2 & MMC_CAP2_SANITIZE))) {
+                       pr_warn("%s: %s - SANITIZE is not supported\n",
+                               mmc_hostname(card->host), __func__);
+                       err = -EOPNOTSUPP;
+                       goto out;
+       }
+
+       pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
+               mmc_hostname(card->host), __func__);
+
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                                       EXT_CSD_SANITIZE_START, 1,
+                                       MMC_SANITIZE_REQ_TIMEOUT);
+
+       if (err)
+               pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n",
+                      mmc_hostname(card->host), __func__, err);
+
+       pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host),
+                                            __func__);
+out:
+       return err;
+}
+
 static int mmc_blk_ioctl_cmd(struct block_device *bdev,
        struct mmc_ioc_cmd __user *ic_ptr)
 {
@@ -490,7 +520,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 
        mrq.cmd = &cmd;
 
-       mmc_claim_host(card->host);
+       mmc_get_card(card);
 
        err = mmc_blk_part_switch(card, md);
        if (err)
@@ -509,6 +539,17 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
                        goto cmd_rel_host;
        }
 
+       if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
+           (cmd.opcode == MMC_SWITCH)) {
+               err = ioctl_do_sanitize(card);
+
+               if (err)
+                       pr_err("%s: ioctl_do_sanitize() failed. err = %d",
+                              __func__, err);
+
+               goto cmd_rel_host;
+       }
+
        mmc_wait_for_req(card->host, &mrq);
 
        if (cmd.error) {
@@ -557,7 +598,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
        }
 
 cmd_rel_host:
-       mmc_release_host(card->host);
+       mmc_put_card(card);
 
 cmd_done:
        mmc_blk_put(md);
@@ -971,10 +1012,10 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
 {
        struct mmc_blk_data *md = mq->data;
        struct mmc_card *card = md->queue.card;
-       unsigned int from, nr, arg, trim_arg, erase_arg;
+       unsigned int from, nr, arg;
        int err = 0, type = MMC_BLK_SECDISCARD;
 
-       if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
+       if (!(mmc_can_secure_erase_trim(card))) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -982,23 +1023,11 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
        from = blk_rq_pos(req);
        nr = blk_rq_sectors(req);
 
-       /* The sanitize operation is supported at v4.5 only */
-       if (mmc_can_sanitize(card)) {
-               erase_arg = MMC_ERASE_ARG;
-               trim_arg = MMC_TRIM_ARG;
-       } else {
-               erase_arg = MMC_SECURE_ERASE_ARG;
-               trim_arg = MMC_SECURE_TRIM1_ARG;
-       }
+       if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
+               arg = MMC_SECURE_TRIM1_ARG;
+       else
+               arg = MMC_SECURE_ERASE_ARG;
 
-       if (mmc_erase_group_aligned(card, from, nr))
-               arg = erase_arg;
-       else if (mmc_can_trim(card))
-               arg = trim_arg;
-       else {
-               err = -EINVAL;
-               goto out;
-       }
 retry:
        if (card->quirks & MMC_QUIRK_INAND_CMD38) {
                err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1034,12 +1063,6 @@ retry:
                        goto out;
        }
 
-       if (mmc_can_sanitize(card)) {
-               trace_mmc_blk_erase_start(EXT_CSD_SANITIZE_START, 0, 0);
-               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-                                EXT_CSD_SANITIZE_START, 1, 0);
-               trace_mmc_blk_erase_end(EXT_CSD_SANITIZE_START, 0, 0);
-       }
 out_retry:
        if (err && !mmc_blk_reset(md, card->host, type))
                goto retry;
@@ -1958,7 +1981,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
 
        if (req && !mq->mqrq_prev->req)
                /* claim host only for the first request */
-               mmc_claim_host(card->host);
+               mmc_get_card(card);
 
        ret = mmc_blk_part_switch(card, md);
        if (ret) {
@@ -2002,7 +2025,7 @@ out:
                 * In case sepecial request, there is no reentry to
                 * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
                 */
-               mmc_release_host(card->host);
+               mmc_put_card(card);
        return ret;
 }
 
@@ -2222,7 +2245,15 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
        struct mmc_card *card;
 
        if (md) {
+               /*
+                * Flush remaining requests and free queues. It
+                * is freeing the queue that stops new requests
+                * from being accepted.
+                */
                card = md->queue.card;
+               mmc_cleanup_queue(&md->queue);
+               if (md->flags & MMC_BLK_PACKED_CMD)
+                       mmc_packed_clean(&md->queue);
                if (md->disk->flags & GENHD_FL_UP) {
                        device_remove_file(disk_to_dev(md->disk), &md->force_ro);
                        if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
@@ -2230,14 +2261,8 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
                                device_remove_file(disk_to_dev(md->disk),
                                        &md->power_ro_lock);
 
-                       /* Stop new requests from getting into the queue */
                        del_gendisk(md->disk);
                }
-
-               /* Then flush out any already in there */
-               mmc_cleanup_queue(&md->queue);
-               if (md->flags & MMC_BLK_PACKED_CMD)
-                       mmc_packed_clean(&md->queue);
                mmc_blk_put(md);
        }
 }
@@ -2305,6 +2330,7 @@ force_ro_fail:
 #define CID_MANFID_TOSHIBA     0x11
 #define CID_MANFID_MICRON      0x13
 #define CID_MANFID_SAMSUNG     0x15
+#define CID_MANFID_HYNIX        0x90
 
 static const struct mmc_fixup blk_fixups[] =
 {
@@ -2363,9 +2389,17 @@ static const struct mmc_fixup blk_fixups[] =
        MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
                  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
 
+       /* Hynix 4.41 iNAND execute trim will lead boot up failed. */
+       MMC_FIXUP(CID_NAME_ANY, CID_MANFID_HYNIX, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_TRIM_UNSTABLE),
+
        END_FIXUP
 };
 
+#if defined(CONFIG_MMC_DW_ROCKCHIP)
+extern struct mmc_card *this_card;
+#endif
+
 static int mmc_blk_probe(struct mmc_card *card)
 {
        struct mmc_blk_data *md, *part_md;
@@ -2395,6 +2429,14 @@ static int mmc_blk_probe(struct mmc_card *card)
 
 #ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
        mmc_set_bus_resume_policy(card->host, 1);
+#endif
+#if defined(CONFIG_MMC_DW_ROCKCHIP)
+    if(card->host->restrict_caps & RESTRICT_CARD_TYPE_EMMC){
+        this_card = card;
+        md->disk->emmc_disk = 1;
+    }else {
+        md->disk->emmc_disk = 0;
+    }
 #endif
        if (mmc_add_disk(md))
                goto out;
@@ -2403,6 +2445,19 @@ static int mmc_blk_probe(struct mmc_card *card)
                if (mmc_add_disk(part_md))
                        goto out;
        }
+
+       pm_runtime_set_autosuspend_delay(&card->dev, 3000);
+       pm_runtime_use_autosuspend(&card->dev);
+
+       /*
+        * Don't enable runtime PM for SD-combo cards here. Leave that
+        * decision to be taken during the SDIO init sequence instead.
+        */
+       if (card->type != MMC_TYPE_SD_COMBO) {
+               pm_runtime_set_active(&card->dev);
+               pm_runtime_enable(&card->dev);
+       }
+
        return 0;
 
  out:
@@ -2414,11 +2469,19 @@ static int mmc_blk_probe(struct mmc_card *card)
 static void mmc_blk_remove(struct mmc_card *card)
 {
        struct mmc_blk_data *md = mmc_get_drvdata(card);
-
+       
+#if defined(CONFIG_MMC_DW_ROCKCHIP)
+    if(card->host->restrict_caps & RESTRICT_CARD_TYPE_EMMC)
+        this_card = NULL;
+#endif
        mmc_blk_remove_parts(card, md);
+       pm_runtime_get_sync(&card->dev);
        mmc_claim_host(card->host);
        mmc_blk_part_switch(card, md);
        mmc_release_host(card->host);
+       if (card->type != MMC_TYPE_SD_COMBO)
+               pm_runtime_disable(&card->dev);
+       pm_runtime_put_noidle(&card->dev);
        mmc_blk_remove_req(md);
        mmc_set_drvdata(card, NULL);
 #ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
@@ -2426,8 +2489,7 @@ static void mmc_blk_remove(struct mmc_card *card)
 #endif
 }
 
-#ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card)
+static int _mmc_blk_suspend(struct mmc_card *card)
 {
        struct mmc_blk_data *part_md;
        struct mmc_blk_data *md = mmc_get_drvdata(card);
@@ -2441,6 +2503,17 @@ static int mmc_blk_suspend(struct mmc_card *card)
        return 0;
 }
 
+static void mmc_blk_shutdown(struct mmc_card *card)
+{
+       _mmc_blk_suspend(card);
+}
+
+#ifdef CONFIG_PM
+static int mmc_blk_suspend(struct mmc_card *card)
+{
+       return _mmc_blk_suspend(card);
+}
+
 static int mmc_blk_resume(struct mmc_card *card)
 {
        struct mmc_blk_data *part_md;
@@ -2472,6 +2545,7 @@ static struct mmc_driver mmc_driver = {
        .remove         = mmc_blk_remove,
        .suspend        = mmc_blk_suspend,
        .resume         = mmc_blk_resume,
+       .shutdown       = mmc_blk_shutdown,
 };
 
 static int __init mmc_blk_init(void)