Loading drivers/mmc/card/block.c +1 −1 Original line number Diff line number Diff line Loading @@ -2957,7 +2957,7 @@ unhalt: out: pm_runtime_mark_last_busy(&card->dev); pm_runtime_put_autosuspend(&card->dev); __mmc_put_card(card); if (test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mrq->req->q); Loading drivers/mmc/core/core.c +2 −1 Original line number Diff line number Diff line Loading @@ -1973,7 +1973,7 @@ EXPORT_SYMBOL(mmc_get_card); * This is a helper function, which drops the runtime * pm reference for the card device. */ static void __mmc_put_card(struct mmc_card *card) void __mmc_put_card(struct mmc_card *card) { /* In case of runtime_idle, it will handle the suspend */ if (card->host->bus_ops->runtime_idle) Loading @@ -1981,6 +1981,7 @@ static void __mmc_put_card(struct mmc_card *card) else pm_runtime_put_autosuspend(&card->dev); } EXPORT_SYMBOL(__mmc_put_card); /* * This is a helper function, which releases the host and drops the runtime Loading drivers/mmc/core/mmc.c +42 −3 Original line number Diff line number Diff line Loading @@ -2424,21 +2424,60 @@ static int mmc_power_restore(struct mmc_host *host) #define NO_AUTOSUSPEND (-1) static int mmc_runtime_idle(struct mmc_host *host) { int err = 0; bool halt_cmdq; BUG_ON(!host->card); halt_cmdq = mmc_card_cmdq(host->card) && (host->card->bkops.needs_check || host->card->bkops.needs_manual); /* * If there are active requests, can't check for bkops. Postpone * until the next time that runtime_idle is scheduled. */ if (host->cmdq_ctx.active_reqs) goto no_suspend; if (halt_cmdq) { err = mmc_cmdq_halt(host, true); if (err) { pr_err("%s: %s failed to halt cmdq (%d)\n", mmc_hostname(host), __func__, err); goto out; } } if (host->card->bkops.needs_manual) host->card->bkops.needs_check = false; if (host->card->bkops.needs_check) { mmc_claim_host(host); mmc_check_bkops(host->card); host->card->bkops.needs_check = false; mmc_release_host(host); } if (host->card->bkops.needs_manual) mmc_start_manual_bkops(host->card); pm_runtime_mark_last_busy(&host->card->dev); if (halt_cmdq) { err = mmc_cmdq_halt(host, false); if (err) pr_err("%s: %s failed to unhalt cmdq (%d)\n", mmc_hostname(host), __func__, err); } out: /* * TODO: consider prolonging suspend when bkops * is running in order to allow a longer time for * bkops to complete * */ pm_schedule_suspend(&host->card->dev, MMC_AUTOSUSPEND_DELAY_MS); no_suspend: pm_runtime_mark_last_busy(&host->card->dev); /* return negative value in order to avoid autosuspend */ return NO_AUTOSUSPEND; return (err) ? err : NO_AUTOSUSPEND; } static const struct mmc_bus_ops mmc_ops = { Loading drivers/mmc/host/cmdq_hci.c +15 −1 Original line number Diff line number Diff line Loading @@ -342,6 +342,11 @@ static int cmdq_enable(struct mmc_host *mmc) cmdq_writel(cq_host, cmdq_readl(cq_host, CQSSC1) | SEND_QSR_INTERVAL, CQSSC1); /* enable bkops exception indication */ if (mmc_card_configured_manual_bkops(mmc->card)) cmdq_writel(cq_host, cmdq_readl(cq_host, CQRMEM) | CQ_EXCEPTION, CQRMEM); /* ensure the writes are done before enabling CQE */ mb(); Loading Loading @@ -675,6 +680,15 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) * In most cases, this would require a reset. */ if (status & CQIS_RED) { /* * will check if the RED error is due to a bkops * exception once the queue is empty */ BUG_ON(!mmc->card); if (mmc_card_configured_manual_bkops(mmc->card) && !mmc_card_configured_auto_bkops(mmc->card)) mmc->card->bkops.needs_check = true; mrq->cmdq_req->resp_err = true; pr_err("%s: Response error (0x%08x) from card !!!", mmc_hostname(mmc), status); Loading drivers/mmc/host/cmdq_hci.h +1 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ /* response mode error mask */ #define CQRMEM 0x50 #define CQ_EXCEPTION (1 << 6) /* task error info */ #define CQTERRI 0x54 Loading Loading
drivers/mmc/card/block.c +1 −1 Original line number Diff line number Diff line Loading @@ -2957,7 +2957,7 @@ unhalt: out: pm_runtime_mark_last_busy(&card->dev); pm_runtime_put_autosuspend(&card->dev); __mmc_put_card(card); if (test_and_clear_bit(0, &ctx_info->req_starved)) blk_run_queue(mrq->req->q); Loading
drivers/mmc/core/core.c +2 −1 Original line number Diff line number Diff line Loading @@ -1973,7 +1973,7 @@ EXPORT_SYMBOL(mmc_get_card); * This is a helper function, which drops the runtime * pm reference for the card device. */ static void __mmc_put_card(struct mmc_card *card) void __mmc_put_card(struct mmc_card *card) { /* In case of runtime_idle, it will handle the suspend */ if (card->host->bus_ops->runtime_idle) Loading @@ -1981,6 +1981,7 @@ static void __mmc_put_card(struct mmc_card *card) else pm_runtime_put_autosuspend(&card->dev); } EXPORT_SYMBOL(__mmc_put_card); /* * This is a helper function, which releases the host and drops the runtime Loading
drivers/mmc/core/mmc.c +42 −3 Original line number Diff line number Diff line Loading @@ -2424,21 +2424,60 @@ static int mmc_power_restore(struct mmc_host *host) #define NO_AUTOSUSPEND (-1) static int mmc_runtime_idle(struct mmc_host *host) { int err = 0; bool halt_cmdq; BUG_ON(!host->card); halt_cmdq = mmc_card_cmdq(host->card) && (host->card->bkops.needs_check || host->card->bkops.needs_manual); /* * If there are active requests, can't check for bkops. Postpone * until the next time that runtime_idle is scheduled. */ if (host->cmdq_ctx.active_reqs) goto no_suspend; if (halt_cmdq) { err = mmc_cmdq_halt(host, true); if (err) { pr_err("%s: %s failed to halt cmdq (%d)\n", mmc_hostname(host), __func__, err); goto out; } } if (host->card->bkops.needs_manual) host->card->bkops.needs_check = false; if (host->card->bkops.needs_check) { mmc_claim_host(host); mmc_check_bkops(host->card); host->card->bkops.needs_check = false; mmc_release_host(host); } if (host->card->bkops.needs_manual) mmc_start_manual_bkops(host->card); pm_runtime_mark_last_busy(&host->card->dev); if (halt_cmdq) { err = mmc_cmdq_halt(host, false); if (err) pr_err("%s: %s failed to unhalt cmdq (%d)\n", mmc_hostname(host), __func__, err); } out: /* * TODO: consider prolonging suspend when bkops * is running in order to allow a longer time for * bkops to complete * */ pm_schedule_suspend(&host->card->dev, MMC_AUTOSUSPEND_DELAY_MS); no_suspend: pm_runtime_mark_last_busy(&host->card->dev); /* return negative value in order to avoid autosuspend */ return NO_AUTOSUSPEND; return (err) ? err : NO_AUTOSUSPEND; } static const struct mmc_bus_ops mmc_ops = { Loading
drivers/mmc/host/cmdq_hci.c +15 −1 Original line number Diff line number Diff line Loading @@ -342,6 +342,11 @@ static int cmdq_enable(struct mmc_host *mmc) cmdq_writel(cq_host, cmdq_readl(cq_host, CQSSC1) | SEND_QSR_INTERVAL, CQSSC1); /* enable bkops exception indication */ if (mmc_card_configured_manual_bkops(mmc->card)) cmdq_writel(cq_host, cmdq_readl(cq_host, CQRMEM) | CQ_EXCEPTION, CQRMEM); /* ensure the writes are done before enabling CQE */ mb(); Loading Loading @@ -675,6 +680,15 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) * In most cases, this would require a reset. */ if (status & CQIS_RED) { /* * will check if the RED error is due to a bkops * exception once the queue is empty */ BUG_ON(!mmc->card); if (mmc_card_configured_manual_bkops(mmc->card) && !mmc_card_configured_auto_bkops(mmc->card)) mmc->card->bkops.needs_check = true; mrq->cmdq_req->resp_err = true; pr_err("%s: Response error (0x%08x) from card !!!", mmc_hostname(mmc), status); Loading
drivers/mmc/host/cmdq_hci.h +1 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ /* response mode error mask */ #define CQRMEM 0x50 #define CQ_EXCEPTION (1 << 6) /* task error info */ #define CQTERRI 0x54 Loading