diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2016-08-18 12:04:56 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-08-18 12:04:56 -0700 |
commit | 042da313a7c4e7cf45dd1441e88eb9493e88b068 (patch) | |
tree | bfc477a3f94d3941b20a90e19ceea873666cd00b | |
parent | 275e32870564c118e19105e9aba7a055bb23e1e4 (diff) | |
parent | 64e8b93b0ac2e27a0bbf907e8f39e06a76f8973d (diff) |
Merge "scsi: ufs: kick start clock scaling only after device detection"
-rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 84 |
1 files changed, 45 insertions, 39 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index ab602d2ef392..84b8425c8965 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -372,6 +372,28 @@ static void __ufshcd_suspend_clkscaling(struct ufs_hba *hba); static void ufshcd_release_all(struct ufs_hba *hba); static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba); static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba); +static int ufshcd_devfreq_target(struct device *dev, + unsigned long *freq, u32 flags); +static int ufshcd_devfreq_get_dev_status(struct device *dev, + struct devfreq_dev_status *stat); + +#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) +static struct devfreq_simple_ondemand_data ufshcd_ondemand_data = { + .upthreshold = 35, + .downdifferential = 30, + .simple_scaling = 1, +}; + +static void *gov_data = &ufshcd_ondemand_data; +#else +static void *gov_data; +#endif + +static struct devfreq_dev_profile ufs_devfreq_profile = { + .polling_ms = 40, + .target = ufshcd_devfreq_target, + .get_dev_status = ufshcd_devfreq_get_dev_status, +}; static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) { @@ -6877,20 +6899,31 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) if (ufshcd_scsi_add_wlus(hba)) goto out; + /* Initialize devfreq after UFS device is detected */ + if (ufshcd_is_clkscaling_supported(hba)) { + memcpy(&hba->clk_scaling.saved_pwr_info.info, + &hba->pwr_info, sizeof(struct ufs_pa_layer_attr)); + hba->clk_scaling.saved_pwr_info.is_valid = true; + hba->clk_scaling.is_scaled_up = true; + if (!hba->devfreq) { + hba->devfreq = devfreq_add_device(hba->dev, + &ufs_devfreq_profile, + "simple_ondemand", + gov_data); + if (IS_ERR(hba->devfreq)) { + ret = PTR_ERR(hba->devfreq); + dev_err(hba->dev, "Unable to register with devfreq %d\n", + ret); + goto out; + } + } + hba->clk_scaling.is_allowed = true; + } + scsi_scan_host(hba->host); pm_runtime_put_sync(hba->dev); } - /* Resume devfreq after UFS device is detected */ - if (ufshcd_is_clkscaling_supported(hba)) { - memcpy(&hba->clk_scaling.saved_pwr_info.info, &hba->pwr_info, - sizeof(struct ufs_pa_layer_attr)); - hba->clk_scaling.saved_pwr_info.is_valid = true; - hba->clk_scaling.is_scaled_up = true; - ufshcd_resume_clkscaling(hba); - hba->clk_scaling.is_allowed = true; - } - if (!hba->is_init_prefetch) hba->is_init_prefetch = true; @@ -7700,7 +7733,8 @@ static void ufshcd_hba_exit(struct ufs_hba *hba) ufshcd_variant_hba_exit(hba); ufshcd_setup_vreg(hba, false); if (ufshcd_is_clkscaling_supported(hba)) { - ufshcd_suspend_clkscaling(hba); + if (hba->devfreq) + ufshcd_suspend_clkscaling(hba); destroy_workqueue(hba->clk_scaling.workq); } ufshcd_disable_clocks(hba, false); @@ -9001,23 +9035,6 @@ start_window: return 0; } -#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) -static struct devfreq_simple_ondemand_data ufshcd_ondemand_data = { - .upthreshold = 35, - .downdifferential = 30, - .simple_scaling = 1, -}; - -static void *gov_data = &ufshcd_ondemand_data; -#else -static void *gov_data; -#endif - -static struct devfreq_dev_profile ufs_devfreq_profile = { - .polling_ms = 40, - .target = ufshcd_devfreq_target, - .get_dev_status = ufshcd_devfreq_get_dev_status, -}; static void ufshcd_clkscaling_init_sysfs(struct ufs_hba *hba) { hba->clk_scaling.enable_attr.show = ufshcd_clkscale_enable_show; @@ -9182,15 +9199,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) if (ufshcd_is_clkscaling_supported(hba)) { char wq_name[sizeof("ufs_clkscaling_00")]; - hba->devfreq = devfreq_add_device(dev, &ufs_devfreq_profile, - "simple_ondemand", gov_data); - if (IS_ERR(hba->devfreq)) { - dev_err(hba->dev, "Unable to register with devfreq %ld\n", - PTR_ERR(hba->devfreq)); - goto out_remove_scsi_host; - } - hba->clk_scaling.is_suspended = false; - INIT_WORK(&hba->clk_scaling.suspend_work, ufshcd_clk_scaling_suspend_work); INIT_WORK(&hba->clk_scaling.resume_work, @@ -9200,8 +9208,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) host->host_no); hba->clk_scaling.workq = create_singlethread_workqueue(wq_name); - /* Suspend devfreq until the UFS device is detected */ - ufshcd_suspend_clkscaling(hba); ufshcd_clkscaling_init_sysfs(hba); } |