Loading drivers/mmc/card/block.c +57 −1 Original line number Diff line number Diff line Loading @@ -2200,6 +2200,17 @@ static int mmc_blk_err_check(struct mmc_card *card, int need_retune = card->host->need_retune; int ecc_err = 0, gen_err = 0; if (card->host->sdr104_wa && mmc_card_sd(card) && (card->host->ios.timing == MMC_TIMING_UHS_SDR104) && !card->sdr104_blocked && (brq->data.error == -EILSEQ || brq->data.error == -EIO || brq->data.error == -ETIMEDOUT || brq->cmd.error == -EILSEQ || brq->cmd.error == -EIO || brq->cmd.error == -ETIMEDOUT)) card->err_in_sdr104 = true; /* * sbc.error indicates a problem with the set block count * command. No data will have been transferred. Loading Loading @@ -3640,6 +3651,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) struct mmc_async_req *areq; const u8 packed_nr = 2; u8 reqs = 0; bool reset = false; #ifdef CONFIG_MMC_SIMULATE_MAX_SPEED unsigned long waitfor = jiffies; #endif Loading Loading @@ -3685,6 +3697,26 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; mmc_queue_bounce_post(mq_rq); if (card->err_in_sdr104) { /* * Data CRC/timeout errors will manifest as CMD/DATA * ERR. But we'd like to retry these too. * Moreover, no harm done if this fails too for multiple * times, we anyway reduce the bus-speed and retry the * same request. * If that fails too, we don't override this status. */ if (status == MMC_BLK_ABORT || status == MMC_BLK_CMD_ERR || status == MMC_BLK_DATA_ERR || status == MMC_BLK_RETRY) /* reset on all of these errors and retry */ reset = true; status = MMC_BLK_RETRY; card->err_in_sdr104 = false; } switch (status) { case MMC_BLK_SUCCESS: case MMC_BLK_PARTIAL: Loading Loading @@ -3725,8 +3757,32 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) break; case MMC_BLK_RETRY: retune_retry_done = brq->retune_retry_done; if (retry++ < MMC_BLK_MAX_RETRIES) if (retry++ < MMC_BLK_MAX_RETRIES) { break; } else if (reset) { reset = false; /* * If we exhaust all the retries due to * CRC/timeout errors in SDR140 mode with UHS SD * cards, re-configure the card in SDR50 * bus-speed mode. * All subsequent re-init of this card will be * in SDR50 mode, unless it is removed and * re-inserted. When new UHS SD cards are * inserted, it may start at SDR104 mode if * supported by the card. */ pr_err("%s: blocked SDR104, lower the bus-speed (SDR50 / DDR50)\n", req->rq_disk->disk_name); mmc_host_clear_sdr104(card->host); mmc_suspend_clk_scaling(card->host); mmc_blk_reset(md, card->host, type); /* SDR104 mode is blocked from now on */ card->sdr104_blocked = true; /* retry 5 times again */ retry = 0; break; } /* Fall through */ case MMC_BLK_ABORT: if (!mmc_blk_reset(md, card->host, type) && Loading drivers/mmc/core/core.c +4 −0 Original line number Diff line number Diff line Loading @@ -4175,6 +4175,10 @@ int _mmc_detect_card_removed(struct mmc_host *host) if (ret) { mmc_card_set_removed(host->card); if (host->card->sdr104_blocked) { mmc_host_set_sdr104(host); host->card->sdr104_blocked = false; } pr_debug("%s: card remove detected\n", mmc_hostname(host)); } Loading drivers/mmc/core/core.h +0 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,6 @@ void mmc_init_context_info(struct mmc_host *host); extern bool mmc_can_scale_clk(struct mmc_host *host); extern int mmc_init_clk_scaling(struct mmc_host *host); extern int mmc_suspend_clk_scaling(struct mmc_host *host); extern int mmc_resume_clk_scaling(struct mmc_host *host); extern int mmc_exit_clk_scaling(struct mmc_host *host); extern unsigned long mmc_get_max_frequency(struct mmc_host *host); Loading drivers/mmc/core/sd.c +2 −0 Original line number Diff line number Diff line Loading @@ -1313,6 +1313,8 @@ static int _mmc_sd_resume(struct mmc_host *host) #endif mmc_card_clr_suspended(host->card); if (host->card->sdr104_blocked) goto out; err = mmc_resume_clk_scaling(host); if (err) { pr_err("%s: %s: fail to resume clock scaling (%d)\n", Loading include/linux/mmc/card.h +2 −0 Original line number Diff line number Diff line Loading @@ -439,6 +439,8 @@ struct mmc_card { u8 *cached_ext_csd; bool cmdq_init; struct mmc_bkops_info bkops; bool err_in_sdr104; bool sdr104_blocked; }; /* Loading Loading
drivers/mmc/card/block.c +57 −1 Original line number Diff line number Diff line Loading @@ -2200,6 +2200,17 @@ static int mmc_blk_err_check(struct mmc_card *card, int need_retune = card->host->need_retune; int ecc_err = 0, gen_err = 0; if (card->host->sdr104_wa && mmc_card_sd(card) && (card->host->ios.timing == MMC_TIMING_UHS_SDR104) && !card->sdr104_blocked && (brq->data.error == -EILSEQ || brq->data.error == -EIO || brq->data.error == -ETIMEDOUT || brq->cmd.error == -EILSEQ || brq->cmd.error == -EIO || brq->cmd.error == -ETIMEDOUT)) card->err_in_sdr104 = true; /* * sbc.error indicates a problem with the set block count * command. No data will have been transferred. Loading Loading @@ -3640,6 +3651,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) struct mmc_async_req *areq; const u8 packed_nr = 2; u8 reqs = 0; bool reset = false; #ifdef CONFIG_MMC_SIMULATE_MAX_SPEED unsigned long waitfor = jiffies; #endif Loading Loading @@ -3685,6 +3697,26 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) type = rq_data_dir(req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; mmc_queue_bounce_post(mq_rq); if (card->err_in_sdr104) { /* * Data CRC/timeout errors will manifest as CMD/DATA * ERR. But we'd like to retry these too. * Moreover, no harm done if this fails too for multiple * times, we anyway reduce the bus-speed and retry the * same request. * If that fails too, we don't override this status. */ if (status == MMC_BLK_ABORT || status == MMC_BLK_CMD_ERR || status == MMC_BLK_DATA_ERR || status == MMC_BLK_RETRY) /* reset on all of these errors and retry */ reset = true; status = MMC_BLK_RETRY; card->err_in_sdr104 = false; } switch (status) { case MMC_BLK_SUCCESS: case MMC_BLK_PARTIAL: Loading Loading @@ -3725,8 +3757,32 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) break; case MMC_BLK_RETRY: retune_retry_done = brq->retune_retry_done; if (retry++ < MMC_BLK_MAX_RETRIES) if (retry++ < MMC_BLK_MAX_RETRIES) { break; } else if (reset) { reset = false; /* * If we exhaust all the retries due to * CRC/timeout errors in SDR140 mode with UHS SD * cards, re-configure the card in SDR50 * bus-speed mode. * All subsequent re-init of this card will be * in SDR50 mode, unless it is removed and * re-inserted. When new UHS SD cards are * inserted, it may start at SDR104 mode if * supported by the card. */ pr_err("%s: blocked SDR104, lower the bus-speed (SDR50 / DDR50)\n", req->rq_disk->disk_name); mmc_host_clear_sdr104(card->host); mmc_suspend_clk_scaling(card->host); mmc_blk_reset(md, card->host, type); /* SDR104 mode is blocked from now on */ card->sdr104_blocked = true; /* retry 5 times again */ retry = 0; break; } /* Fall through */ case MMC_BLK_ABORT: if (!mmc_blk_reset(md, card->host, type) && Loading
drivers/mmc/core/core.c +4 −0 Original line number Diff line number Diff line Loading @@ -4175,6 +4175,10 @@ int _mmc_detect_card_removed(struct mmc_host *host) if (ret) { mmc_card_set_removed(host->card); if (host->card->sdr104_blocked) { mmc_host_set_sdr104(host); host->card->sdr104_blocked = false; } pr_debug("%s: card remove detected\n", mmc_hostname(host)); } Loading
drivers/mmc/core/core.h +0 −1 Original line number Diff line number Diff line Loading @@ -80,7 +80,6 @@ void mmc_init_context_info(struct mmc_host *host); extern bool mmc_can_scale_clk(struct mmc_host *host); extern int mmc_init_clk_scaling(struct mmc_host *host); extern int mmc_suspend_clk_scaling(struct mmc_host *host); extern int mmc_resume_clk_scaling(struct mmc_host *host); extern int mmc_exit_clk_scaling(struct mmc_host *host); extern unsigned long mmc_get_max_frequency(struct mmc_host *host); Loading
drivers/mmc/core/sd.c +2 −0 Original line number Diff line number Diff line Loading @@ -1313,6 +1313,8 @@ static int _mmc_sd_resume(struct mmc_host *host) #endif mmc_card_clr_suspended(host->card); if (host->card->sdr104_blocked) goto out; err = mmc_resume_clk_scaling(host); if (err) { pr_err("%s: %s: fail to resume clock scaling (%d)\n", Loading
include/linux/mmc/card.h +2 −0 Original line number Diff line number Diff line Loading @@ -439,6 +439,8 @@ struct mmc_card { u8 *cached_ext_csd; bool cmdq_init; struct mmc_bkops_info bkops; bool err_in_sdr104; bool sdr104_blocked; }; /* Loading