emmc: pre-alloc cali blk_test memory to fix suspend/resume failed
authorNan Li <nan.li@amlogic.com>
Wed, 6 Sep 2017 02:25:10 +0000 (10:25 +0800)
committerVictor Wan <victor.wan@amlogic.com>
Fri, 8 Sep 2017 03:28:45 +0000 (20:28 -0700)
PD#150194: modify suspend & resume fail.
1. fixed alloc blk_test memory on probe,
pre-allocated memory allows suspend/resume
without dynamic allocation.
2. do not flush cache while resume.

Change-Id: If4a310da82f053359f89599fd187ad51a24f16ba
Signed-off-by: Nan Li <nan.li@amlogic.com>
drivers/amlogic/mmc/aml_sd_emmc.c
drivers/mmc/core/mmc.c
include/linux/amlogic/sd.h

index 8d72ef2..2845bda 100644 (file)
@@ -168,13 +168,8 @@ static int aml_cali_auto(struct mmc_host *mmc, struct cali_data *c_data)
        u8 bus_width = 8;
        struct sd_emmc_adjust *gadjust = (struct sd_emmc_adjust *)&adjust;
        u32 blksz = 512;
-       u8 *blk_test;
        int ret = 0;
 
-       blk_test = kmalloc(blksz * CALI_BLK_CNT, GFP_KERNEL);
-       if (!blk_test)
-               return -ENOMEM;
-
        if (mmc->ios.bus_width == 0)
                bus_width = 1;
        else if (mmc->ios.bus_width == 2)
@@ -199,7 +194,7 @@ static int aml_cali_auto(struct mmc_host *mmc, struct cali_data *c_data)
                        pdata->caling = 1;
                        aml_sd_emmc_cali_transfer(mmc,
                                        MMC_READ_MULTIPLE_BLOCK,
-                                       blk_test, blksz);
+                                       host->blk_test, blksz);
                        for (i = 0; i < 4; i++) {
                                cali_tmp[i]     = readl(host->base
                                                + SD_EMMC_CALOUT + i*4);
@@ -253,8 +248,6 @@ static int aml_cali_auto(struct mmc_host *mmc, struct cali_data *c_data)
                pr_info("\n");
 #endif
        }
-       kfree(blk_test);
-       blk_test = NULL;
        return ret;
 }
 
@@ -274,13 +267,8 @@ static int aml_cali_index(struct mmc_host *mmc, struct cali_data *c_data)
        u8 cal_per_line_num = 8;
        struct sd_emmc_adjust *gadjust = (struct sd_emmc_adjust *)&adjust;
        u32 blksz = 512;
-       u8 *blk_test;
        int ret = 0;
 
-       blk_test = kmalloc(blksz * CALI_BLK_CNT, GFP_KERNEL);
-       if (!blk_test)
-               return -ENOMEM;
-
        if (mmc->ios.bus_width == 0)
                bus_width = 1;
        else if (mmc->ios.bus_width == 2)
@@ -312,7 +300,7 @@ static int aml_cali_index(struct mmc_host *mmc, struct cali_data *c_data)
                                pdata->caling = 1;
                                aml_sd_emmc_cali_transfer(mmc,
                                        MMC_READ_MULTIPLE_BLOCK,
-                                       blk_test, blksz);
+                                       host->blk_test, blksz);
                                pdata->calout[dly_tmp][cal_time]
                                        = readl(host->base + SD_EMMC_CALOUT)
                                        & 0x3f;
@@ -371,8 +359,6 @@ static int aml_cali_index(struct mmc_host *mmc, struct cali_data *c_data)
                }
 #endif
        }
-       kfree(blk_test);
-       blk_test = NULL;
        return ret;
 }
 
@@ -628,7 +614,6 @@ static int aml_tuning_adj(struct mmc_host *mmc, u32 opcode,
        int adj_delay = 0;
        const u8 *blk_pattern = tuning_data->blk_pattern;
        unsigned int blksz = tuning_data->blksz;
-       u8 *blk_test;
        int wrap_win_start = -1, wrap_win_size = 0;
        int best_win_start = -1, best_win_size = 0;
        int curr_win_start = -1, curr_win_size = 0;
@@ -643,9 +628,6 @@ static int aml_tuning_adj(struct mmc_host *mmc, u32 opcode,
                blksz = 512;
                opcode = 17;
        }
-       blk_test = kmalloc(blksz, GFP_KERNEL);
-       if (!blk_test)
-               return -ENOMEM;
 
        pr_info("%s: clk %d %s tuning start\n",
                mmc_hostname(mmc), (ctrl->ddr ? (clock / 2) : clock),
@@ -658,7 +640,7 @@ static int aml_tuning_adj(struct mmc_host *mmc, u32 opcode,
                gadjust->cali_rise = 0;
                writel(adjust, host->base + SD_EMMC_ADJUST);
                nmatch = aml_sd_emmc_tuning_transfer(mmc, opcode,
-                               blk_pattern, blk_test, blksz);
+                               blk_pattern, host->blk_test, blksz);
                /*get a ok adjust point!*/
                if (nmatch == TUNING_NUM_PER_POINT) {
                        if (adj_delay == 0)
@@ -708,7 +690,6 @@ static int aml_tuning_adj(struct mmc_host *mmc, u32 opcode,
        }
        *best_start = best_win_start;
        *best_size = best_win_size;
-       kfree(blk_test);
        return 0;
 }
 
@@ -894,7 +875,6 @@ static int aml_sd_emmc_execute_tuning_rxclk(struct mmc_host *mmc, u32 opcode,
        u8 steps, nmatch;
        u8 rx_phase, rx_delay;
        struct aml_emmc_rxclk *emmc_rxclk = &host->emmc_rxclk;
-       u8 *blk_test;
        u32 clock;
        int rxclk_find;
        u8 rx_tuning_result[25] = {0};
@@ -915,9 +895,6 @@ static int aml_sd_emmc_execute_tuning_rxclk(struct mmc_host *mmc, u32 opcode,
                blksz = 512;
                opcode = 17;
        }
-       blk_test = kmalloc(blksz, GFP_KERNEL);
-       if (!blk_test)
-               return -ENOMEM;
 
        host->is_tunning = 1;
        pr_info("%s: clk %d %s tuning start\n",
@@ -935,7 +912,7 @@ static int aml_sd_emmc_execute_tuning_rxclk(struct mmc_host *mmc, u32 opcode,
                        writel(vclk, host->base + SD_EMMC_CLOCK);
                        pdata->clkc = vclk;
                        nmatch = aml_sd_emmc_tuning_transfer(mmc, opcode,
-                               blk_pattern, blk_test, blksz);
+                               blk_pattern, host->blk_test, blksz);
                        rx_tuning_result[rx_phase * 5 + rx_delay] = nmatch;
                }
        }
@@ -946,7 +923,6 @@ static int aml_sd_emmc_execute_tuning_rxclk(struct mmc_host *mmc, u32 opcode,
 
        if (rxclk_find < 0) {
                pr_info("%s: tuning failed\n", mmc_hostname(host->mmc));
-               kfree(blk_test);
                return -1;
        } else if (rxclk_find < 10) {
                rx_phase = 0;
@@ -971,7 +947,6 @@ static int aml_sd_emmc_execute_tuning_rxclk(struct mmc_host *mmc, u32 opcode,
        emmc_rxclk->rxclk_rx_delay = rx_delay;
        emmc_rxclk->rxclk_point = rxclk_find;
 
-       kfree(blk_test);
        return 0;
 }
 
@@ -2278,9 +2253,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
                        sd_emmc_err("%s: warning... response crc,vstat:0x%x,virqc:%x\n",
                                        mmc_hostname(host->mmc),
                                        vstat, virqc);
-               pr_info("%s %d cmd:%d arg:0x%x ",
-                               __func__, __LINE__,
-                               mrq->cmd->opcode, mrq->cmd->arg);
                host->status = HOST_RSP_CRC_ERR;
                mrq->cmd->error = -EILSEQ;
        } else if (ista->resp_timeout) {
@@ -2300,10 +2272,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
        }
 
        if (err) {
-               if (host->is_tunning == 0)
+               if (host->is_tunning == 0) {
                        aml_host_bus_fsm_show(host, ista->bus_fsm);
-               if (aml_card_type_mmc(pdata))
-                       mmc_cmd_LBA_show(mmc, mrq);
+                       if (aml_card_type_mmc(pdata))
+                               mmc_cmd_LBA_show(mmc, mrq);
+               }
        }
 
        if (host->xfer_step == XFER_IRQ_UNKNOWN_IRQ)
@@ -2768,6 +2741,11 @@ static int meson_mmc_probe(struct platform_device *pdev)
        if (ret)
                goto free_host;
 
+       host->blk_test = kzalloc((512 * CALI_BLK_CNT), GFP_KERNEL);
+       if (host->blk_test == NULL) {
+               ret = -ENOMEM;
+               goto free_host;
+       }
        /* data desc buffer */
        host->desc_buf =
                dma_alloc_coherent(host->dev,
@@ -2777,7 +2755,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        if (host->desc_buf == NULL) {
                dev_err(host->dev, "Unable to map allocate DMA desc buffer.\n");
                ret = -ENOMEM;
-               goto free_host;
+               goto free_cali;
        }
 
        /* data bounce buffer */
@@ -2787,7 +2765,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        if (host->bn_buf == NULL) {
                dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
                ret = -ENOMEM;
-               goto free_host;
+               goto free_cali;
        }
 
        host->pdata = pdata;
@@ -2802,12 +2780,12 @@ static int meson_mmc_probe(struct platform_device *pdev)
        else
                ret = meson_mmc_clk_init(host);
        if (ret)
-               goto free_host;
+               goto free_cali;
 
        ret = mmc_of_parse(mmc);
        if (ret) {
                dev_warn(&pdev->dev, "error parsing DT: %d\n", ret);
-               goto free_host;
+               goto free_cali;
        }
 
        if (amlsd_get_platform_data(pdev, pdata, mmc, 0))
@@ -2880,7 +2858,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        ret = mmc_add_host(mmc);
        if (ret) { /* error */
                sd_emmc_err("Failed to add mmc host.\n");
-               goto free_host;
+               goto free_cali;
        }
        if (aml_card_type_sdio(pdata)) /* if sdio_wifi */
                sdio_host = mmc;
@@ -2897,12 +2875,14 @@ static int meson_mmc_probe(struct platform_device *pdev)
                                "amlsd_cd", host);
                if (ret) {
                        sd_emmc_err("Failed to request SD IN detect\n");
-                       goto free_host;
+                       goto free_cali;
                }
        }
        pr_info("%s() : success!\n", __func__);
        return 0;
 
+free_cali:
+       kfree(host->blk_test);
 free_host:
        mmc_free_host(mmc);
        kfree(pdata);
@@ -2930,6 +2910,7 @@ static int meson_mmc_remove(struct platform_device *pdev)
        if (host->core_clk)
                clk_disable_unprepare(host->core_clk);
 
+       kfree(host->blk_test);
        mmc_free_host(host->mmc);
        kfree(pdata);
        return 0;
index f67201e..9efe47c 100644 (file)
@@ -2174,7 +2174,12 @@ static int mmc_reset(struct mmc_host *host)
         * In the case of recovery, we can't expect flushing the cache to work
         * always, but we have a go and ignore errors.
         */
+#ifdef CONFIG_AMLOGIC_MMC
+       if (!mmc_card_suspended(host->card))
+               mmc_flush_cache(host->card);
+#else
        mmc_flush_cache(host->card);
+#endif
 
        if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset &&
             mmc_can_reset(card)) {
index e475c36..f5cd908 100644 (file)
@@ -357,6 +357,7 @@ struct amlsd_host {
 
        unsigned long           clk_rate;
 
+       u8 *blk_test;
        char *desc_buf;
        dma_addr_t              desc_dma_addr;
        unsigned int dma_sts;