Loading drivers/mmc/core/core.c +96 −52 Original line number Diff line number Diff line Loading @@ -258,25 +258,6 @@ out: } EXPORT_SYMBOL(mmc_cmdq_clk_scaling_stop_busy); /** * mmc_disable_devfreq_clk_scaling() - Disable clock scaling * @host: pointer to mmc host structure * * Disables clock scaling aggresively */ void mmc_disable_clk_scaling(struct mmc_host *host) { if (!host) { pr_err("bad host parameter\n"); WARN_ON(1); return; } pr_debug("%s: disabling clock scaling\n", mmc_hostname(host)); mmc_exit_clk_scaling(host); } EXPORT_SYMBOL(mmc_disable_clk_scaling); /** * mmc_can_scale_clk() - Check clock scaling capability * @host: pointer to mmc host structure Loading @@ -289,8 +270,7 @@ bool mmc_can_scale_clk(struct mmc_host *host) return false; } return (host->caps2 & MMC_CAP2_CLK_SCALE) && (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)); return host->caps2 & MMC_CAP2_CLK_SCALE; } EXPORT_SYMBOL(mmc_can_scale_clk); Loading Loading @@ -738,18 +718,20 @@ int mmc_init_clk_scaling(struct mmc_host *host) EXPORT_SYMBOL(mmc_init_clk_scaling); /** * mmc_exit_devfreq_clk_scaling() - Disable clock scaling * mmc_suspend_clk_scaling() - suspend clock scaling * @host: pointer to mmc host structure * * Disable clock scaling permanently. * This API will suspend devfreq feature for the specific host. * The statistics collected by mmc will be cleared. * This function is intended to be called by the pm callbacks * (e.g. runtime_suspend, suspend) of the mmc device */ int mmc_exit_clk_scaling(struct mmc_host *host) int mmc_suspend_clk_scaling(struct mmc_host *host) { int err; if (!host) { pr_err("bad host parameter\n"); WARN_ON(1); WARN(1, "bad host parameter\n"); return -EINVAL; } Loading @@ -757,55 +739,118 @@ int mmc_exit_clk_scaling(struct mmc_host *host) return 0; if (!host->clk_scaling.devfreq) { pr_err("%s: no devfreq is assosiated with this device\n", mmc_hostname(host)); pr_err("%s: %s: no devfreq is assosiated with this device\n", mmc_hostname(host), __func__); return -EPERM; } host->clk_scaling.enable = false; atomic_inc(&host->clk_scaling.devfreq_abort); err = devfreq_suspend_device(host->clk_scaling.devfreq); if (err) { pr_err("%s: failed to suspend devfreq\n", mmc_hostname(host)); pr_err("%s: %s: failed to suspend devfreq\n", mmc_hostname(host), __func__); return err; } host->clk_scaling.enable = false; host->clk_scaling.total_busy_time_us = 0; pr_debug("%s: devfreq suspended\n", mmc_hostname(host)); err = devfreq_remove_device(host->clk_scaling.devfreq); if (err) { pr_err("%s: remove devfreq failed\n", mmc_hostname(host)); return err; return 0; } EXPORT_SYMBOL(mmc_suspend_clk_scaling); host->clk_scaling.devfreq = NULL; atomic_set(&host->clk_scaling.devfreq_abort, 1); mmc_reset_clk_scale_stats(host); pr_debug("%s: devfreq was removed\n", mmc_hostname(host)); /** * mmc_resume_clk_scaling() - resume clock scaling * @host: pointer to mmc host structure * * This API will resume devfreq feature for the specific host. * This API is intended to be called by the pm callbacks * (e.g. runtime_suspend, suspend) of the mmc device */ int mmc_resume_clk_scaling(struct mmc_host *host) { int err = 0; if (!host) { WARN(1, "bad host parameter\n"); return -EINVAL; } if (!mmc_can_scale_clk(host)) return 0; if (!host->clk_scaling.devfreq) { pr_err("%s: %s: no devfreq is assosiated with this device\n", mmc_hostname(host), __func__); return -EPERM; } EXPORT_SYMBOL(mmc_exit_clk_scaling); atomic_set(&host->clk_scaling.devfreq_abort, 0); host->clk_scaling.curr_freq = host->ios.clock; host->clk_scaling.clk_scaling_in_progress = false; host->clk_scaling.need_freq_change = false; err = devfreq_resume_device(host->clk_scaling.devfreq); if (err) { pr_err("%s: %s: failed to resume devfreq (%d)\n", mmc_hostname(host), __func__, err); } else { host->clk_scaling.enable = true; pr_debug("%s: devfreq resumed\n", mmc_hostname(host)); } return err; } EXPORT_SYMBOL(mmc_resume_clk_scaling); /** * mmc_reset_clk_scale_stats() - reset clock scaling statistics * mmc_exit_devfreq_clk_scaling() - Disable clock scaling * @host: pointer to mmc host structure * * Disable clock scaling permanently. */ void mmc_reset_clk_scale_stats(struct mmc_host *host) int mmc_exit_clk_scaling(struct mmc_host *host) { int err; if (!host) { pr_err("bad host parameter\n"); pr_err("%s: bad host parameter\n", __func__); WARN_ON(1); return; return -EINVAL; } if (!host->clk_scaling.enable) return; spin_lock_bh(&host->clk_scaling.lock); host->clk_scaling.total_busy_time_us = 0; spin_unlock_bh(&host->clk_scaling.lock); if (!mmc_can_scale_clk(host)) return 0; if (!host->clk_scaling.devfreq) { pr_err("%s: %s: no devfreq is assosiated with this device\n", mmc_hostname(host), __func__); return -EPERM; } err = mmc_suspend_clk_scaling(host); if (err) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, err); return err; } err = devfreq_remove_device(host->clk_scaling.devfreq); if (err) { pr_err("%s: remove devfreq failed (%d)\n", mmc_hostname(host), err); return err; } host->clk_scaling.devfreq = NULL; atomic_set(&host->clk_scaling.devfreq_abort, 1); pr_debug("%s: devfreq was removed\n", mmc_hostname(host)); return 0; } EXPORT_SYMBOL(mmc_reset_clk_scale_stats); EXPORT_SYMBOL(mmc_exit_clk_scaling); /** * mmc_request_done - finish processing an MMC request Loading Loading @@ -3909,7 +3954,6 @@ int mmc_pm_notify(struct notifier_block *notify_block, spin_unlock_irqrestore(&host->lock, flags); cancel_delayed_work_sync(&host->detect); mmc_disable_clk_scaling(host); if (!host->bus_ops) break; Loading drivers/mmc/core/core.h +2 −2 Original line number Diff line number Diff line Loading @@ -72,11 +72,11 @@ void mmc_remove_card_debugfs(struct mmc_card *card); void mmc_init_context_info(struct mmc_host *host); extern void mmc_disable_clk_scaling(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 void mmc_reset_clk_scale_stats(struct mmc_host *host); extern unsigned long mmc_get_max_frequency(struct mmc_host *host); #endif drivers/mmc/core/host.c +0 −2 Original line number Diff line number Diff line Loading @@ -168,8 +168,6 @@ void mmc_host_clk_hold(struct mmc_host *host) spin_unlock_irqrestore(&host->clk_lock, flags); mmc_ungate_clock(host); /* Reset clock scaling stats as host is out of idle */ mmc_reset_clk_scale_stats(host); spin_lock_irqsave(&host->clk_lock, flags); pr_debug("%s: ungated MCI clock\n", mmc_hostname(host)); } Loading drivers/mmc/core/mmc.c +25 −17 Original line number Diff line number Diff line Loading @@ -2210,12 +2210,12 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) BUG_ON(!host); BUG_ON(!host->card); /* * Disable clock scaling before suspend and enable it after resume so * as to avoid clock scaling decisions kicking in during this window. */ if (mmc_can_scale_clk(host)) mmc_disable_clk_scaling(host); err = mmc_suspend_clk_scaling(host); if (err) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, err); goto out; } mmc_claim_host(host); Loading Loading @@ -2335,12 +2335,10 @@ static int _mmc_resume(struct mmc_host *host) mmc_release_host(host); /* * We have done full initialization of the card, * reset the clk scale stats and current frequency. */ if (mmc_can_scale_clk(host)) mmc_init_clk_scaling(host); err = mmc_resume_clk_scaling(host); if (err) pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, err); out: if (!err) Loading Loading @@ -2416,15 +2414,23 @@ static int mmc_power_restore(struct mmc_host *host) { int ret; /* Disable clk scaling to avoid switching frequencies intermittently */ mmc_disable_clk_scaling(host); /* Suspend clk scaling to avoid switching frequencies intermittently */ ret = mmc_suspend_clk_scaling(host); if (ret) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } mmc_claim_host(host); ret = mmc_init_card(host, host->card->ocr, host->card); mmc_release_host(host); if (mmc_can_scale_clk(host)) mmc_init_clk_scaling(host); ret = mmc_resume_clk_scaling(host); if (ret) pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } Loading Loading @@ -2556,7 +2562,9 @@ int mmc_attach_mmc(struct mmc_host *host) if (err) goto remove_card; mmc_init_clk_scaling(host); err = mmc_init_clk_scaling(host); if (err) goto remove_card; register_reboot_notifier(&host->card->reboot_notify); Loading drivers/mmc/core/sd.c +27 −14 Original line number Diff line number Diff line Loading @@ -1192,12 +1192,12 @@ static int _mmc_sd_suspend(struct mmc_host *host) BUG_ON(!host); BUG_ON(!host->card); /* * Disable clock scaling before suspend and enable it after resume so * as to avoid clock scaling decisions kicking in during this window. */ if (mmc_can_scale_clk(host)) mmc_disable_clk_scaling(host); err = mmc_suspend_clk_scaling(host); if (err) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, err); return err; } mmc_claim_host(host); Loading Loading @@ -1275,8 +1275,12 @@ static int _mmc_sd_resume(struct mmc_host *host) #endif mmc_card_clr_suspended(host->card); if (mmc_can_scale_clk(host)) mmc_init_clk_scaling(host); err = mmc_resume_clk_scaling(host); if (err) { pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, err); goto out; } out: mmc_release_host(host); Loading Loading @@ -1340,15 +1344,22 @@ static int mmc_sd_power_restore(struct mmc_host *host) { int ret; /* Disable clk scaling to avoid switching frequencies intermittently */ mmc_disable_clk_scaling(host); /* Suspend clk scaling to avoid switching frequencies intermittently */ ret = mmc_suspend_clk_scaling(host); if (ret) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } mmc_claim_host(host); ret = mmc_sd_init_card(host, host->card->ocr, host->card); mmc_release_host(host); if (mmc_can_scale_clk(host)) mmc_init_clk_scaling(host); ret = mmc_resume_clk_scaling(host); if (ret) pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } Loading Loading @@ -1443,7 +1454,9 @@ int mmc_attach_sd(struct mmc_host *host) if (err) goto remove_card; mmc_init_clk_scaling(host); err = mmc_init_clk_scaling(host); if (err) goto remove_card; return 0; Loading Loading
drivers/mmc/core/core.c +96 −52 Original line number Diff line number Diff line Loading @@ -258,25 +258,6 @@ out: } EXPORT_SYMBOL(mmc_cmdq_clk_scaling_stop_busy); /** * mmc_disable_devfreq_clk_scaling() - Disable clock scaling * @host: pointer to mmc host structure * * Disables clock scaling aggresively */ void mmc_disable_clk_scaling(struct mmc_host *host) { if (!host) { pr_err("bad host parameter\n"); WARN_ON(1); return; } pr_debug("%s: disabling clock scaling\n", mmc_hostname(host)); mmc_exit_clk_scaling(host); } EXPORT_SYMBOL(mmc_disable_clk_scaling); /** * mmc_can_scale_clk() - Check clock scaling capability * @host: pointer to mmc host structure Loading @@ -289,8 +270,7 @@ bool mmc_can_scale_clk(struct mmc_host *host) return false; } return (host->caps2 & MMC_CAP2_CLK_SCALE) && (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)); return host->caps2 & MMC_CAP2_CLK_SCALE; } EXPORT_SYMBOL(mmc_can_scale_clk); Loading Loading @@ -738,18 +718,20 @@ int mmc_init_clk_scaling(struct mmc_host *host) EXPORT_SYMBOL(mmc_init_clk_scaling); /** * mmc_exit_devfreq_clk_scaling() - Disable clock scaling * mmc_suspend_clk_scaling() - suspend clock scaling * @host: pointer to mmc host structure * * Disable clock scaling permanently. * This API will suspend devfreq feature for the specific host. * The statistics collected by mmc will be cleared. * This function is intended to be called by the pm callbacks * (e.g. runtime_suspend, suspend) of the mmc device */ int mmc_exit_clk_scaling(struct mmc_host *host) int mmc_suspend_clk_scaling(struct mmc_host *host) { int err; if (!host) { pr_err("bad host parameter\n"); WARN_ON(1); WARN(1, "bad host parameter\n"); return -EINVAL; } Loading @@ -757,55 +739,118 @@ int mmc_exit_clk_scaling(struct mmc_host *host) return 0; if (!host->clk_scaling.devfreq) { pr_err("%s: no devfreq is assosiated with this device\n", mmc_hostname(host)); pr_err("%s: %s: no devfreq is assosiated with this device\n", mmc_hostname(host), __func__); return -EPERM; } host->clk_scaling.enable = false; atomic_inc(&host->clk_scaling.devfreq_abort); err = devfreq_suspend_device(host->clk_scaling.devfreq); if (err) { pr_err("%s: failed to suspend devfreq\n", mmc_hostname(host)); pr_err("%s: %s: failed to suspend devfreq\n", mmc_hostname(host), __func__); return err; } host->clk_scaling.enable = false; host->clk_scaling.total_busy_time_us = 0; pr_debug("%s: devfreq suspended\n", mmc_hostname(host)); err = devfreq_remove_device(host->clk_scaling.devfreq); if (err) { pr_err("%s: remove devfreq failed\n", mmc_hostname(host)); return err; return 0; } EXPORT_SYMBOL(mmc_suspend_clk_scaling); host->clk_scaling.devfreq = NULL; atomic_set(&host->clk_scaling.devfreq_abort, 1); mmc_reset_clk_scale_stats(host); pr_debug("%s: devfreq was removed\n", mmc_hostname(host)); /** * mmc_resume_clk_scaling() - resume clock scaling * @host: pointer to mmc host structure * * This API will resume devfreq feature for the specific host. * This API is intended to be called by the pm callbacks * (e.g. runtime_suspend, suspend) of the mmc device */ int mmc_resume_clk_scaling(struct mmc_host *host) { int err = 0; if (!host) { WARN(1, "bad host parameter\n"); return -EINVAL; } if (!mmc_can_scale_clk(host)) return 0; if (!host->clk_scaling.devfreq) { pr_err("%s: %s: no devfreq is assosiated with this device\n", mmc_hostname(host), __func__); return -EPERM; } EXPORT_SYMBOL(mmc_exit_clk_scaling); atomic_set(&host->clk_scaling.devfreq_abort, 0); host->clk_scaling.curr_freq = host->ios.clock; host->clk_scaling.clk_scaling_in_progress = false; host->clk_scaling.need_freq_change = false; err = devfreq_resume_device(host->clk_scaling.devfreq); if (err) { pr_err("%s: %s: failed to resume devfreq (%d)\n", mmc_hostname(host), __func__, err); } else { host->clk_scaling.enable = true; pr_debug("%s: devfreq resumed\n", mmc_hostname(host)); } return err; } EXPORT_SYMBOL(mmc_resume_clk_scaling); /** * mmc_reset_clk_scale_stats() - reset clock scaling statistics * mmc_exit_devfreq_clk_scaling() - Disable clock scaling * @host: pointer to mmc host structure * * Disable clock scaling permanently. */ void mmc_reset_clk_scale_stats(struct mmc_host *host) int mmc_exit_clk_scaling(struct mmc_host *host) { int err; if (!host) { pr_err("bad host parameter\n"); pr_err("%s: bad host parameter\n", __func__); WARN_ON(1); return; return -EINVAL; } if (!host->clk_scaling.enable) return; spin_lock_bh(&host->clk_scaling.lock); host->clk_scaling.total_busy_time_us = 0; spin_unlock_bh(&host->clk_scaling.lock); if (!mmc_can_scale_clk(host)) return 0; if (!host->clk_scaling.devfreq) { pr_err("%s: %s: no devfreq is assosiated with this device\n", mmc_hostname(host), __func__); return -EPERM; } err = mmc_suspend_clk_scaling(host); if (err) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, err); return err; } err = devfreq_remove_device(host->clk_scaling.devfreq); if (err) { pr_err("%s: remove devfreq failed (%d)\n", mmc_hostname(host), err); return err; } host->clk_scaling.devfreq = NULL; atomic_set(&host->clk_scaling.devfreq_abort, 1); pr_debug("%s: devfreq was removed\n", mmc_hostname(host)); return 0; } EXPORT_SYMBOL(mmc_reset_clk_scale_stats); EXPORT_SYMBOL(mmc_exit_clk_scaling); /** * mmc_request_done - finish processing an MMC request Loading Loading @@ -3909,7 +3954,6 @@ int mmc_pm_notify(struct notifier_block *notify_block, spin_unlock_irqrestore(&host->lock, flags); cancel_delayed_work_sync(&host->detect); mmc_disable_clk_scaling(host); if (!host->bus_ops) break; Loading
drivers/mmc/core/core.h +2 −2 Original line number Diff line number Diff line Loading @@ -72,11 +72,11 @@ void mmc_remove_card_debugfs(struct mmc_card *card); void mmc_init_context_info(struct mmc_host *host); extern void mmc_disable_clk_scaling(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 void mmc_reset_clk_scale_stats(struct mmc_host *host); extern unsigned long mmc_get_max_frequency(struct mmc_host *host); #endif
drivers/mmc/core/host.c +0 −2 Original line number Diff line number Diff line Loading @@ -168,8 +168,6 @@ void mmc_host_clk_hold(struct mmc_host *host) spin_unlock_irqrestore(&host->clk_lock, flags); mmc_ungate_clock(host); /* Reset clock scaling stats as host is out of idle */ mmc_reset_clk_scale_stats(host); spin_lock_irqsave(&host->clk_lock, flags); pr_debug("%s: ungated MCI clock\n", mmc_hostname(host)); } Loading
drivers/mmc/core/mmc.c +25 −17 Original line number Diff line number Diff line Loading @@ -2210,12 +2210,12 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) BUG_ON(!host); BUG_ON(!host->card); /* * Disable clock scaling before suspend and enable it after resume so * as to avoid clock scaling decisions kicking in during this window. */ if (mmc_can_scale_clk(host)) mmc_disable_clk_scaling(host); err = mmc_suspend_clk_scaling(host); if (err) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, err); goto out; } mmc_claim_host(host); Loading Loading @@ -2335,12 +2335,10 @@ static int _mmc_resume(struct mmc_host *host) mmc_release_host(host); /* * We have done full initialization of the card, * reset the clk scale stats and current frequency. */ if (mmc_can_scale_clk(host)) mmc_init_clk_scaling(host); err = mmc_resume_clk_scaling(host); if (err) pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, err); out: if (!err) Loading Loading @@ -2416,15 +2414,23 @@ static int mmc_power_restore(struct mmc_host *host) { int ret; /* Disable clk scaling to avoid switching frequencies intermittently */ mmc_disable_clk_scaling(host); /* Suspend clk scaling to avoid switching frequencies intermittently */ ret = mmc_suspend_clk_scaling(host); if (ret) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } mmc_claim_host(host); ret = mmc_init_card(host, host->card->ocr, host->card); mmc_release_host(host); if (mmc_can_scale_clk(host)) mmc_init_clk_scaling(host); ret = mmc_resume_clk_scaling(host); if (ret) pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } Loading Loading @@ -2556,7 +2562,9 @@ int mmc_attach_mmc(struct mmc_host *host) if (err) goto remove_card; mmc_init_clk_scaling(host); err = mmc_init_clk_scaling(host); if (err) goto remove_card; register_reboot_notifier(&host->card->reboot_notify); Loading
drivers/mmc/core/sd.c +27 −14 Original line number Diff line number Diff line Loading @@ -1192,12 +1192,12 @@ static int _mmc_sd_suspend(struct mmc_host *host) BUG_ON(!host); BUG_ON(!host->card); /* * Disable clock scaling before suspend and enable it after resume so * as to avoid clock scaling decisions kicking in during this window. */ if (mmc_can_scale_clk(host)) mmc_disable_clk_scaling(host); err = mmc_suspend_clk_scaling(host); if (err) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, err); return err; } mmc_claim_host(host); Loading Loading @@ -1275,8 +1275,12 @@ static int _mmc_sd_resume(struct mmc_host *host) #endif mmc_card_clr_suspended(host->card); if (mmc_can_scale_clk(host)) mmc_init_clk_scaling(host); err = mmc_resume_clk_scaling(host); if (err) { pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, err); goto out; } out: mmc_release_host(host); Loading Loading @@ -1340,15 +1344,22 @@ static int mmc_sd_power_restore(struct mmc_host *host) { int ret; /* Disable clk scaling to avoid switching frequencies intermittently */ mmc_disable_clk_scaling(host); /* Suspend clk scaling to avoid switching frequencies intermittently */ ret = mmc_suspend_clk_scaling(host); if (ret) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } mmc_claim_host(host); ret = mmc_sd_init_card(host, host->card->ocr, host->card); mmc_release_host(host); if (mmc_can_scale_clk(host)) mmc_init_clk_scaling(host); ret = mmc_resume_clk_scaling(host); if (ret) pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } Loading Loading @@ -1443,7 +1454,9 @@ int mmc_attach_sd(struct mmc_host *host) if (err) goto remove_card; mmc_init_clk_scaling(host); err = mmc_init_clk_scaling(host); if (err) goto remove_card; return 0; Loading