Loading drivers/mmc/card/block.c +11 −7 Original line number Diff line number Diff line Loading @@ -1491,7 +1491,7 @@ out: if (test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mq->queue); mmc_release_host(host); mmc_put_card(card); return err ? 1 : 0; } Loading Loading @@ -1607,7 +1607,7 @@ out: if (test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mq->queue); mmc_release_host(host); mmc_put_card(card); return err ? 1 : 0; } Loading Loading @@ -2839,7 +2839,7 @@ static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq) return; } mmc_claim_host(card->host); mmc_get_card(card); /* disable CQ mode in card */ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CMDQ, 0, Loading @@ -2852,7 +2852,7 @@ static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq) host->card->cmdq_init = false; } out: mmc_release_host(card->host); mmc_put_card(card); } static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req) Loading Loading @@ -2887,6 +2887,7 @@ static void mmc_blk_cmdq_err(struct mmc_queue *mq) struct mmc_card *card = mq->card; struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; pm_runtime_get_sync(&card->dev); err = mmc_cmdq_halt(host, true); if (err) { pr_err("halt: failed: %d\n", err); Loading Loading @@ -2948,6 +2949,9 @@ unhalt: mmc_cmdq_halt(host, false); out: pm_runtime_mark_last_busy(&card->dev); pm_runtime_put_autosuspend(&card->dev); if (test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mrq->req->q); } Loading Loading @@ -2999,8 +3003,8 @@ out: if (!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state) && test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mq->queue); mmc_release_host(host); mmc_put_card(host->card); if (blk_queue_stopped(mq->queue) && !ctx_info->active_reqs) complete(&mq->cmdq_shutdown_complete); return; Loading Loading @@ -3269,14 +3273,14 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req) struct mmc_card *card = md->queue.card; unsigned int cmd_flags = req ? req->cmd_flags : 0; mmc_claim_host(card->host); mmc_get_card(card); ret = mmc_blk_cmdq_part_switch(card, md); if (ret) { pr_err("%s: %s: partition switch failed %d\n", md->disk->disk_name, __func__, ret); if (req) blk_end_request_all(req, ret); mmc_release_host(card->host); mmc_put_card(card); goto switch_failure; } Loading drivers/mmc/core/mmc.c +19 −1 Original line number Diff line number Diff line Loading @@ -2138,6 +2138,19 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_card_suspended(host->card)) goto out; if (mmc_card_cmdq(host->card)) { BUG_ON(host->cmdq_ctx.active_reqs); err = mmc_cmdq_halt(host, true); if (err) { pr_err("%s: halt: failed: %d\n", __func__, err); goto out; } mmc_host_clk_hold(host); host->cmdq_ops->disable(host, true); mmc_host_clk_release(host); } if (mmc_card_doing_bkops(host->card)) { err = mmc_stop_bkops(host->card); if (err) Loading Loading @@ -2216,6 +2229,11 @@ static int _mmc_resume(struct mmc_host *host) } break; } if (!err && mmc_card_cmdq(host->card)) { err = mmc_cmdq_halt(host, false); if (err) pr_err("%s: un-halt: failed: %d\n", __func__, err); } mmc_card_clr_suspended(host->card); mmc_release_host(host); Loading Loading @@ -2313,7 +2331,7 @@ static int mmc_runtime_resume(struct mmc_host *host) trace_mmc_runtime_resume(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); return 0; return err; } static int mmc_power_restore(struct mmc_host *host) Loading drivers/mmc/host/cmdq_hci.c +41 −11 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/pm_runtime.h> #include "cmdq_hci.h" Loading @@ -32,6 +33,26 @@ /* 1 sec */ #define HALT_TIMEOUT_MS 1000 #ifdef CONFIG_PM_RUNTIME static int cmdq_runtime_pm_get(struct cmdq_host *host) { return pm_runtime_get_sync(host->mmc->parent); } static int cmdq_runtime_pm_put(struct cmdq_host *host) { pm_runtime_mark_last_busy(host->mmc->parent); return pm_runtime_put_autosuspend(host->mmc->parent); } #else static inline int cmdq_runtime_pm_get(struct cmdq_host *host) { return 0; } static inline int cmdq_runtime_pm_put(struct cmdq_host *host) { return 0; } #endif static inline struct mmc_request *get_req_by_tag(struct cmdq_host *cq_host, unsigned int tag) { Loading Loading @@ -272,6 +293,7 @@ static int cmdq_enable(struct mmc_host *mmc) if (cq_host->enabled) goto out; cmdq_runtime_pm_get(cq_host); cqcfg = cmdq_readl(cq_host, CQCFG); if (cqcfg & 0x1) { pr_info("%s: %s: cq_host is already enabled\n", Loading Loading @@ -335,6 +357,7 @@ static int cmdq_enable(struct mmc_host *mmc) cq_host->ops->clear_set_dumpregs(mmc, 1); out: cmdq_runtime_pm_put(cq_host); return err; } Loading @@ -342,12 +365,13 @@ static void cmdq_disable(struct mmc_host *mmc, bool soft) { struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); cmdq_runtime_pm_get(cq_host); if (soft) { cmdq_writel(cq_host, cmdq_readl( cq_host, CQCFG) & ~(CQ_ENABLE), CQCFG); } cmdq_runtime_pm_put(cq_host); cq_host->enabled = false; } Loading @@ -360,6 +384,7 @@ static void cmdq_reset(struct mmc_host *mmc, bool soft) unsigned int rca; int ret; cmdq_runtime_pm_get(cq_host); cqcfg = cmdq_readl(cq_host, CQCFG); tdlba = cmdq_readl(cq_host, CQTDLBA); tdlbau = cmdq_readl(cq_host, CQTDLBAU); Loading Loading @@ -391,6 +416,7 @@ static void cmdq_reset(struct mmc_host *mmc, bool soft) mb(); cmdq_writel(cq_host, cqcfg, CQCFG); cmdq_runtime_pm_put(cq_host); cq_host->enabled = true; } Loading Loading @@ -536,7 +562,7 @@ static void cmdq_prep_dcmd_desc(struct mmc_host *mmc, static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) { int err; int err = 0; u64 data = 0; u64 *task_desc = NULL; u32 tag = mrq->cmdq_req->tag; Loading @@ -549,11 +575,13 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) goto out; } cmdq_runtime_pm_get(cq_host); if (mrq->cmdq_req->cmdq_req_flags & DCMD) { cmdq_prep_dcmd_desc(mmc, mrq); cq_host->mrq_slot[DCMD_SLOT] = mrq; cmdq_writel(cq_host, 1 << DCMD_SLOT, CQTDBR); return 0; goto out; } if (cq_host->ops->crypto_cfg) { Loading @@ -575,7 +603,7 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) if (err) { pr_err("%s: %s: failed to setup tx desc: %d\n", mmc_hostname(mmc), __func__, err); return err; goto out; } BUG_ON(cmdq_readl(cq_host, CQTDBR) & (1 << tag)); Loading @@ -587,6 +615,7 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) cmdq_writel(cq_host, 1 << tag, CQTDBR); out: cmdq_runtime_pm_put(cq_host); return err; } Loading Loading @@ -689,26 +718,26 @@ EXPORT_SYMBOL(cmdq_irq); static int cmdq_halt(struct mmc_host *mmc, bool halt) { struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); u32 val; u32 ret = 0; cmdq_runtime_pm_get(cq_host); if (halt) { cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) | HALT, CQCTL); val = wait_for_completion_timeout(&cq_host->halt_comp, ret = wait_for_completion_timeout(&cq_host->halt_comp, msecs_to_jiffies(HALT_TIMEOUT_MS)); /* halt done: re-enable legacy interrupts */ if (cq_host->ops->clear_set_irqs) cq_host->ops->clear_set_irqs(mmc, false); return val ? 0 : -ETIMEDOUT; ret = ret ? 0 : -ETIMEDOUT; } else { if (cq_host->ops->clear_set_irqs) cq_host->ops->clear_set_irqs(mmc, true); cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT, CQCTL); } return 0; cmdq_runtime_pm_put(cq_host); return ret; } static void cmdq_post_req(struct mmc_host *host, struct mmc_request *mrq, Loading @@ -731,8 +760,9 @@ static void cmdq_post_req(struct mmc_host *host, struct mmc_request *mrq, static void cmdq_dumpstate(struct mmc_host *mmc) { struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); cmdq_runtime_pm_get(cq_host); cmdq_dumpregs(cq_host); cmdq_runtime_pm_put(cq_host); } static const struct mmc_cmdq_host_ops cmdq_host_ops = { Loading Loading
drivers/mmc/card/block.c +11 −7 Original line number Diff line number Diff line Loading @@ -1491,7 +1491,7 @@ out: if (test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mq->queue); mmc_release_host(host); mmc_put_card(card); return err ? 1 : 0; } Loading Loading @@ -1607,7 +1607,7 @@ out: if (test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mq->queue); mmc_release_host(host); mmc_put_card(card); return err ? 1 : 0; } Loading Loading @@ -2839,7 +2839,7 @@ static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq) return; } mmc_claim_host(card->host); mmc_get_card(card); /* disable CQ mode in card */ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CMDQ, 0, Loading @@ -2852,7 +2852,7 @@ static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq) host->card->cmdq_init = false; } out: mmc_release_host(card->host); mmc_put_card(card); } static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req) Loading Loading @@ -2887,6 +2887,7 @@ static void mmc_blk_cmdq_err(struct mmc_queue *mq) struct mmc_card *card = mq->card; struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; pm_runtime_get_sync(&card->dev); err = mmc_cmdq_halt(host, true); if (err) { pr_err("halt: failed: %d\n", err); Loading Loading @@ -2948,6 +2949,9 @@ unhalt: mmc_cmdq_halt(host, false); out: pm_runtime_mark_last_busy(&card->dev); pm_runtime_put_autosuspend(&card->dev); if (test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mrq->req->q); } Loading Loading @@ -2999,8 +3003,8 @@ out: if (!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state) && test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mq->queue); mmc_release_host(host); mmc_put_card(host->card); if (blk_queue_stopped(mq->queue) && !ctx_info->active_reqs) complete(&mq->cmdq_shutdown_complete); return; Loading Loading @@ -3269,14 +3273,14 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req) struct mmc_card *card = md->queue.card; unsigned int cmd_flags = req ? req->cmd_flags : 0; mmc_claim_host(card->host); mmc_get_card(card); ret = mmc_blk_cmdq_part_switch(card, md); if (ret) { pr_err("%s: %s: partition switch failed %d\n", md->disk->disk_name, __func__, ret); if (req) blk_end_request_all(req, ret); mmc_release_host(card->host); mmc_put_card(card); goto switch_failure; } Loading
drivers/mmc/core/mmc.c +19 −1 Original line number Diff line number Diff line Loading @@ -2138,6 +2138,19 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_card_suspended(host->card)) goto out; if (mmc_card_cmdq(host->card)) { BUG_ON(host->cmdq_ctx.active_reqs); err = mmc_cmdq_halt(host, true); if (err) { pr_err("%s: halt: failed: %d\n", __func__, err); goto out; } mmc_host_clk_hold(host); host->cmdq_ops->disable(host, true); mmc_host_clk_release(host); } if (mmc_card_doing_bkops(host->card)) { err = mmc_stop_bkops(host->card); if (err) Loading Loading @@ -2216,6 +2229,11 @@ static int _mmc_resume(struct mmc_host *host) } break; } if (!err && mmc_card_cmdq(host->card)) { err = mmc_cmdq_halt(host, false); if (err) pr_err("%s: un-halt: failed: %d\n", __func__, err); } mmc_card_clr_suspended(host->card); mmc_release_host(host); Loading Loading @@ -2313,7 +2331,7 @@ static int mmc_runtime_resume(struct mmc_host *host) trace_mmc_runtime_resume(mmc_hostname(host), err, ktime_to_us(ktime_sub(ktime_get(), start))); return 0; return err; } static int mmc_power_restore(struct mmc_host *host) Loading
drivers/mmc/host/cmdq_hci.c +41 −11 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/pm_runtime.h> #include "cmdq_hci.h" Loading @@ -32,6 +33,26 @@ /* 1 sec */ #define HALT_TIMEOUT_MS 1000 #ifdef CONFIG_PM_RUNTIME static int cmdq_runtime_pm_get(struct cmdq_host *host) { return pm_runtime_get_sync(host->mmc->parent); } static int cmdq_runtime_pm_put(struct cmdq_host *host) { pm_runtime_mark_last_busy(host->mmc->parent); return pm_runtime_put_autosuspend(host->mmc->parent); } #else static inline int cmdq_runtime_pm_get(struct cmdq_host *host) { return 0; } static inline int cmdq_runtime_pm_put(struct cmdq_host *host) { return 0; } #endif static inline struct mmc_request *get_req_by_tag(struct cmdq_host *cq_host, unsigned int tag) { Loading Loading @@ -272,6 +293,7 @@ static int cmdq_enable(struct mmc_host *mmc) if (cq_host->enabled) goto out; cmdq_runtime_pm_get(cq_host); cqcfg = cmdq_readl(cq_host, CQCFG); if (cqcfg & 0x1) { pr_info("%s: %s: cq_host is already enabled\n", Loading Loading @@ -335,6 +357,7 @@ static int cmdq_enable(struct mmc_host *mmc) cq_host->ops->clear_set_dumpregs(mmc, 1); out: cmdq_runtime_pm_put(cq_host); return err; } Loading @@ -342,12 +365,13 @@ static void cmdq_disable(struct mmc_host *mmc, bool soft) { struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); cmdq_runtime_pm_get(cq_host); if (soft) { cmdq_writel(cq_host, cmdq_readl( cq_host, CQCFG) & ~(CQ_ENABLE), CQCFG); } cmdq_runtime_pm_put(cq_host); cq_host->enabled = false; } Loading @@ -360,6 +384,7 @@ static void cmdq_reset(struct mmc_host *mmc, bool soft) unsigned int rca; int ret; cmdq_runtime_pm_get(cq_host); cqcfg = cmdq_readl(cq_host, CQCFG); tdlba = cmdq_readl(cq_host, CQTDLBA); tdlbau = cmdq_readl(cq_host, CQTDLBAU); Loading Loading @@ -391,6 +416,7 @@ static void cmdq_reset(struct mmc_host *mmc, bool soft) mb(); cmdq_writel(cq_host, cqcfg, CQCFG); cmdq_runtime_pm_put(cq_host); cq_host->enabled = true; } Loading Loading @@ -536,7 +562,7 @@ static void cmdq_prep_dcmd_desc(struct mmc_host *mmc, static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) { int err; int err = 0; u64 data = 0; u64 *task_desc = NULL; u32 tag = mrq->cmdq_req->tag; Loading @@ -549,11 +575,13 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) goto out; } cmdq_runtime_pm_get(cq_host); if (mrq->cmdq_req->cmdq_req_flags & DCMD) { cmdq_prep_dcmd_desc(mmc, mrq); cq_host->mrq_slot[DCMD_SLOT] = mrq; cmdq_writel(cq_host, 1 << DCMD_SLOT, CQTDBR); return 0; goto out; } if (cq_host->ops->crypto_cfg) { Loading @@ -575,7 +603,7 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) if (err) { pr_err("%s: %s: failed to setup tx desc: %d\n", mmc_hostname(mmc), __func__, err); return err; goto out; } BUG_ON(cmdq_readl(cq_host, CQTDBR) & (1 << tag)); Loading @@ -587,6 +615,7 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) cmdq_writel(cq_host, 1 << tag, CQTDBR); out: cmdq_runtime_pm_put(cq_host); return err; } Loading Loading @@ -689,26 +718,26 @@ EXPORT_SYMBOL(cmdq_irq); static int cmdq_halt(struct mmc_host *mmc, bool halt) { struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); u32 val; u32 ret = 0; cmdq_runtime_pm_get(cq_host); if (halt) { cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) | HALT, CQCTL); val = wait_for_completion_timeout(&cq_host->halt_comp, ret = wait_for_completion_timeout(&cq_host->halt_comp, msecs_to_jiffies(HALT_TIMEOUT_MS)); /* halt done: re-enable legacy interrupts */ if (cq_host->ops->clear_set_irqs) cq_host->ops->clear_set_irqs(mmc, false); return val ? 0 : -ETIMEDOUT; ret = ret ? 0 : -ETIMEDOUT; } else { if (cq_host->ops->clear_set_irqs) cq_host->ops->clear_set_irqs(mmc, true); cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT, CQCTL); } return 0; cmdq_runtime_pm_put(cq_host); return ret; } static void cmdq_post_req(struct mmc_host *host, struct mmc_request *mrq, Loading @@ -731,8 +760,9 @@ static void cmdq_post_req(struct mmc_host *host, struct mmc_request *mrq, static void cmdq_dumpstate(struct mmc_host *mmc) { struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); cmdq_runtime_pm_get(cq_host); cmdq_dumpregs(cq_host); cmdq_runtime_pm_put(cq_host); } static const struct mmc_cmdq_host_ops cmdq_host_ops = { Loading