diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-26 18:19:19 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-26 18:19:19 -0500 |
commit | ecfc555c7485b64906f9713ef5eaafe6550b72b8 (patch) | |
tree | 1d428e68b54aa21ed019cc0a70a9d965030868f1 | |
parent | e66c176837462928a05a135bbe16cdce70536d6e (diff) | |
parent | 1c0ca90207d61e4868043b5bbbbd7cc0bb1ac974 (diff) |
Merge back earlier 'pm-cpufreq' material.
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 100 |
1 files changed, 44 insertions, 56 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index cb003a6b72c8..c755b5fe317c 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -2017,22 +2017,21 @@ EXPORT_SYMBOL(cpufreq_get_policy); | |||
2017 | static int cpufreq_set_policy(struct cpufreq_policy *policy, | 2017 | static int cpufreq_set_policy(struct cpufreq_policy *policy, |
2018 | struct cpufreq_policy *new_policy) | 2018 | struct cpufreq_policy *new_policy) |
2019 | { | 2019 | { |
2020 | int ret = 0, failed = 1; | 2020 | struct cpufreq_governor *old_gov; |
2021 | int ret; | ||
2021 | 2022 | ||
2022 | pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu, | 2023 | pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu, |
2023 | new_policy->min, new_policy->max); | 2024 | new_policy->min, new_policy->max); |
2024 | 2025 | ||
2025 | memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo)); | 2026 | memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo)); |
2026 | 2027 | ||
2027 | if (new_policy->min > policy->max || new_policy->max < policy->min) { | 2028 | if (new_policy->min > policy->max || new_policy->max < policy->min) |
2028 | ret = -EINVAL; | 2029 | return -EINVAL; |
2029 | goto error_out; | ||
2030 | } | ||
2031 | 2030 | ||
2032 | /* verify the cpu speed can be set within this limit */ | 2031 | /* verify the cpu speed can be set within this limit */ |
2033 | ret = cpufreq_driver->verify(new_policy); | 2032 | ret = cpufreq_driver->verify(new_policy); |
2034 | if (ret) | 2033 | if (ret) |
2035 | goto error_out; | 2034 | return ret; |
2036 | 2035 | ||
2037 | /* adjust if necessary - all reasons */ | 2036 | /* adjust if necessary - all reasons */ |
2038 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, | 2037 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
@@ -2048,7 +2047,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, | |||
2048 | */ | 2047 | */ |
2049 | ret = cpufreq_driver->verify(new_policy); | 2048 | ret = cpufreq_driver->verify(new_policy); |
2050 | if (ret) | 2049 | if (ret) |
2051 | goto error_out; | 2050 | return ret; |
2052 | 2051 | ||
2053 | /* notification of the new policy */ | 2052 | /* notification of the new policy */ |
2054 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, | 2053 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
@@ -2063,58 +2062,48 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, | |||
2063 | if (cpufreq_driver->setpolicy) { | 2062 | if (cpufreq_driver->setpolicy) { |
2064 | policy->policy = new_policy->policy; | 2063 | policy->policy = new_policy->policy; |
2065 | pr_debug("setting range\n"); | 2064 | pr_debug("setting range\n"); |
2066 | ret = cpufreq_driver->setpolicy(new_policy); | 2065 | return cpufreq_driver->setpolicy(new_policy); |
2067 | } else { | 2066 | } |
2068 | if (new_policy->governor != policy->governor) { | ||
2069 | /* save old, working values */ | ||
2070 | struct cpufreq_governor *old_gov = policy->governor; | ||
2071 | |||
2072 | pr_debug("governor switch\n"); | ||
2073 | |||
2074 | /* end old governor */ | ||
2075 | if (policy->governor) { | ||
2076 | __cpufreq_governor(policy, CPUFREQ_GOV_STOP); | ||
2077 | up_write(&policy->rwsem); | ||
2078 | __cpufreq_governor(policy, | ||
2079 | CPUFREQ_GOV_POLICY_EXIT); | ||
2080 | down_write(&policy->rwsem); | ||
2081 | } | ||
2082 | 2067 | ||
2083 | /* start new governor */ | 2068 | if (new_policy->governor == policy->governor) |
2084 | policy->governor = new_policy->governor; | 2069 | goto out; |
2085 | if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) { | ||
2086 | if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) { | ||
2087 | failed = 0; | ||
2088 | } else { | ||
2089 | up_write(&policy->rwsem); | ||
2090 | __cpufreq_governor(policy, | ||
2091 | CPUFREQ_GOV_POLICY_EXIT); | ||
2092 | down_write(&policy->rwsem); | ||
2093 | } | ||
2094 | } | ||
2095 | 2070 | ||
2096 | if (failed) { | 2071 | pr_debug("governor switch\n"); |
2097 | /* new governor failed, so re-start old one */ | 2072 | |
2098 | pr_debug("starting governor %s failed\n", | 2073 | /* save old, working values */ |
2099 | policy->governor->name); | 2074 | old_gov = policy->governor; |
2100 | if (old_gov) { | 2075 | /* end old governor */ |
2101 | policy->governor = old_gov; | 2076 | if (old_gov) { |
2102 | __cpufreq_governor(policy, | 2077 | __cpufreq_governor(policy, CPUFREQ_GOV_STOP); |
2103 | CPUFREQ_GOV_POLICY_INIT); | 2078 | up_write(&policy->rwsem); |
2104 | __cpufreq_governor(policy, | 2079 | __cpufreq_governor(policy,CPUFREQ_GOV_POLICY_EXIT); |
2105 | CPUFREQ_GOV_START); | 2080 | down_write(&policy->rwsem); |
2106 | } | ||
2107 | ret = -EINVAL; | ||
2108 | goto error_out; | ||
2109 | } | ||
2110 | /* might be a policy change, too, so fall through */ | ||
2111 | } | ||
2112 | pr_debug("governor: change or update limits\n"); | ||
2113 | ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); | ||
2114 | } | 2081 | } |
2115 | 2082 | ||
2116 | error_out: | 2083 | /* start new governor */ |
2117 | return ret; | 2084 | policy->governor = new_policy->governor; |
2085 | if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) { | ||
2086 | if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) | ||
2087 | goto out; | ||
2088 | |||
2089 | up_write(&policy->rwsem); | ||
2090 | __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); | ||
2091 | down_write(&policy->rwsem); | ||
2092 | } | ||
2093 | |||
2094 | /* new governor failed, so re-start old one */ | ||
2095 | pr_debug("starting governor %s failed\n", policy->governor->name); | ||
2096 | if (old_gov) { | ||
2097 | policy->governor = old_gov; | ||
2098 | __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT); | ||
2099 | __cpufreq_governor(policy, CPUFREQ_GOV_START); | ||
2100 | } | ||
2101 | |||
2102 | return -EINVAL; | ||
2103 | |||
2104 | out: | ||
2105 | pr_debug("governor: change or update limits\n"); | ||
2106 | return __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); | ||
2118 | } | 2107 | } |
2119 | 2108 | ||
2120 | /** | 2109 | /** |
@@ -2186,7 +2175,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, | |||
2186 | switch (action & ~CPU_TASKS_FROZEN) { | 2175 | switch (action & ~CPU_TASKS_FROZEN) { |
2187 | case CPU_ONLINE: | 2176 | case CPU_ONLINE: |
2188 | __cpufreq_add_dev(dev, NULL, frozen); | 2177 | __cpufreq_add_dev(dev, NULL, frozen); |
2189 | cpufreq_update_policy(cpu); | ||
2190 | break; | 2178 | break; |
2191 | 2179 | ||
2192 | case CPU_DOWN_PREPARE: | 2180 | case CPU_DOWN_PREPARE: |