Loading drivers/mmc/core/bus.c +14 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,20 @@ static int mmc_bus_suspend(struct device *dev) if (mmc_bus_needs_resume(host)) return 0; ret = host->bus_ops->suspend(host); /* * bus_ops->suspend may fail due to some reason * In such cases if we return error to PM framework * from here without calling drv->resume then mmc * request may get stuck since PM framework will assume * that mmc bus is not suspended (because of error) and * it won't call resume again. * * So in case of error call drv->resume. */ if (ret && dev->driver && drv->resume) drv->resume(card); return ret; } Loading drivers/mmc/core/mmc.c +31 −7 Original line number Diff line number Diff line Loading @@ -2370,7 +2370,7 @@ static int mmc_test_awake_ext_csd(struct mmc_host *host) static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { int err = 0; int err = 0, ret; BUG_ON(!host); BUG_ON(!host->card); Loading @@ -2379,7 +2379,9 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (err) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, err); goto out; if (host->card->cmdq_init) wake_up(&host->cmdq_ctx.wait); return err; } mmc_claim_host(host); Loading @@ -2403,12 +2405,12 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_card_doing_bkops(host->card)) { err = mmc_stop_bkops(host->card); if (err) goto out; goto out_err; } err = mmc_flush_cache(host->card); if (err) goto out; goto out_err; if (mmc_can_sleepawake(host)) { /* Loading @@ -2425,16 +2427,38 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) err = mmc_deselect_cards(host); } if (!err) { if (err) goto out_err; mmc_power_off(host); mmc_card_set_suspended(host->card); goto out; out_err: /* * In case of err let's put controller back in cmdq mode and unhalt * the controller. * We expect cmdq_enable and unhalt won't return any error * since it is anyway enabling few registers. */ if (host->card->cmdq_init) { mmc_host_clk_hold(host); ret = host->cmdq_ops->enable(host); if (ret) pr_err("%s: %s: enabling CMDQ mode failed (%d)\n", mmc_hostname(host), __func__, ret); mmc_host_clk_release(host); mmc_cmdq_halt(host, false); } out: /* Kick CMDQ thread to process any requests came in while suspending */ if (host->card->cmdq_init) wake_up(&host->cmdq_ctx.wait); mmc_release_host(host); if (err) mmc_resume_clk_scaling(host); return err; } Loading Loading
drivers/mmc/core/bus.c +14 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,20 @@ static int mmc_bus_suspend(struct device *dev) if (mmc_bus_needs_resume(host)) return 0; ret = host->bus_ops->suspend(host); /* * bus_ops->suspend may fail due to some reason * In such cases if we return error to PM framework * from here without calling drv->resume then mmc * request may get stuck since PM framework will assume * that mmc bus is not suspended (because of error) and * it won't call resume again. * * So in case of error call drv->resume. */ if (ret && dev->driver && drv->resume) drv->resume(card); return ret; } Loading
drivers/mmc/core/mmc.c +31 −7 Original line number Diff line number Diff line Loading @@ -2370,7 +2370,7 @@ static int mmc_test_awake_ext_csd(struct mmc_host *host) static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { int err = 0; int err = 0, ret; BUG_ON(!host); BUG_ON(!host->card); Loading @@ -2379,7 +2379,9 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (err) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, err); goto out; if (host->card->cmdq_init) wake_up(&host->cmdq_ctx.wait); return err; } mmc_claim_host(host); Loading @@ -2403,12 +2405,12 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_card_doing_bkops(host->card)) { err = mmc_stop_bkops(host->card); if (err) goto out; goto out_err; } err = mmc_flush_cache(host->card); if (err) goto out; goto out_err; if (mmc_can_sleepawake(host)) { /* Loading @@ -2425,16 +2427,38 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) err = mmc_deselect_cards(host); } if (!err) { if (err) goto out_err; mmc_power_off(host); mmc_card_set_suspended(host->card); goto out; out_err: /* * In case of err let's put controller back in cmdq mode and unhalt * the controller. * We expect cmdq_enable and unhalt won't return any error * since it is anyway enabling few registers. */ if (host->card->cmdq_init) { mmc_host_clk_hold(host); ret = host->cmdq_ops->enable(host); if (ret) pr_err("%s: %s: enabling CMDQ mode failed (%d)\n", mmc_hostname(host), __func__, ret); mmc_host_clk_release(host); mmc_cmdq_halt(host, false); } out: /* Kick CMDQ thread to process any requests came in while suspending */ if (host->card->cmdq_init) wake_up(&host->cmdq_ctx.wait); mmc_release_host(host); if (err) mmc_resume_clk_scaling(host); return err; } Loading