Przeglądaj źródła

Merge back earlier 'pm-cpufreq' material.

Rafael J. Wysocki 11 lat temu
rodzic
commit
15afee3aea
46 zmienionych plików z 298 dodań i 514 usunięć
  1. 1 0
      arch/arm/mach-spear/spear1310.c
  2. 1 0
      arch/arm/mach-spear/spear1340.c
  3. 8 0
      arch/arm64/Kconfig
  4. 5 0
      drivers/base/power/main.c
  5. 1 1
      drivers/cpufreq/Kconfig
  6. 0 1
      drivers/cpufreq/acpi-cpufreq.c
  7. 0 1
      drivers/cpufreq/arm_big_little.c
  8. 0 1
      drivers/cpufreq/blackfin-cpufreq.c
  9. 0 1
      drivers/cpufreq/cpufreq-cpu0.c
  10. 209 206
      drivers/cpufreq/cpufreq.c
  11. 13 25
      drivers/cpufreq/cpufreq_stats.c
  12. 0 1
      drivers/cpufreq/cris-artpec3-cpufreq.c
  13. 0 1
      drivers/cpufreq/cris-etraxfs-cpufreq.c
  14. 0 1
      drivers/cpufreq/davinci-cpufreq.c
  15. 0 1
      drivers/cpufreq/e_powersaver.c
  16. 0 1
      drivers/cpufreq/elanfreq.c
  17. 7 90
      drivers/cpufreq/exynos-cpufreq.c
  18. 0 1
      drivers/cpufreq/exynos5440-cpufreq.c
  19. 8 38
      drivers/cpufreq/freq_table.c
  20. 0 1
      drivers/cpufreq/ia64-acpi-cpufreq.c
  21. 0 1
      drivers/cpufreq/imx6q-cpufreq.c
  22. 12 14
      drivers/cpufreq/intel_pstate.c
  23. 0 1
      drivers/cpufreq/kirkwood-cpufreq.c
  24. 0 1
      drivers/cpufreq/longhaul.c
  25. 0 1
      drivers/cpufreq/loongson2_cpufreq.c
  26. 0 1
      drivers/cpufreq/omap-cpufreq.c
  27. 0 1
      drivers/cpufreq/p4-clockmod.c
  28. 0 1
      drivers/cpufreq/pasemi-cpufreq.c
  29. 0 1
      drivers/cpufreq/powernow-k6.c
  30. 0 2
      drivers/cpufreq/powernow-k7.c
  31. 0 2
      drivers/cpufreq/powernow-k8.c
  32. 0 1
      drivers/cpufreq/ppc-corenet-cpufreq.c
  33. 0 1
      drivers/cpufreq/ppc_cbe_cpufreq.c
  34. 0 1
      drivers/cpufreq/pxa2xx-cpufreq.c
  35. 0 1
      drivers/cpufreq/pxa3xx-cpufreq.c
  36. 3 46
      drivers/cpufreq/s5pv210-cpufreq.c
  37. 0 1
      drivers/cpufreq/sc520_freq.c
  38. 0 1
      drivers/cpufreq/sh-cpufreq.c
  39. 1 3
      drivers/cpufreq/sparc-us2e-cpufreq.c
  40. 1 3
      drivers/cpufreq/sparc-us3-cpufreq.c
  41. 11 3
      drivers/cpufreq/spear-cpufreq.c
  42. 0 2
      drivers/cpufreq/speedstep-centrino.c
  43. 0 1
      drivers/cpufreq/speedstep-ich.c
  44. 0 1
      drivers/cpufreq/speedstep-smi.c
  45. 5 42
      drivers/cpufreq/tegra-cpufreq.c
  46. 12 10
      include/linux/cpufreq.h

+ 1 - 0
arch/arm/mach-spear/spear1310.c

@@ -28,6 +28,7 @@
 static void __init spear1310_dt_init(void)
 static void __init spear1310_dt_init(void)
 {
 {
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
 }
 }
 
 
 static const char * const spear1310_dt_board_compat[] = {
 static const char * const spear1310_dt_board_compat[] = {

+ 1 - 0
arch/arm/mach-spear/spear1340.c

@@ -143,6 +143,7 @@ static void __init spear1340_dt_init(void)
 {
 {
 	of_platform_populate(NULL, of_default_bus_match_table,
 	of_platform_populate(NULL, of_default_bus_match_table,
 			spear1340_auxdata_lookup, NULL);
 			spear1340_auxdata_lookup, NULL);
+	platform_device_register_simple("spear-cpufreq", -1, NULL, 0);
 }
 }
 
 
 static const char * const spear1340_dt_board_compat[] = {
 static const char * const spear1340_dt_board_compat[] = {

+ 8 - 0
arch/arm64/Kconfig

@@ -303,6 +303,14 @@ source "drivers/cpuidle/Kconfig"
 
 
 endmenu
 endmenu
 
 
+menu "Power management options"
+
+source "kernel/power/Kconfig"
+
+source "drivers/cpufreq/Kconfig"
+
+endmenu
+
 source "net/Kconfig"
 source "net/Kconfig"
 
 
 source "drivers/Kconfig"
 source "drivers/Kconfig"

+ 5 - 0
drivers/base/power/main.c

@@ -29,6 +29,7 @@
 #include <linux/async.h>
 #include <linux/async.h>
 #include <linux/suspend.h>
 #include <linux/suspend.h>
 #include <trace/events/power.h>
 #include <trace/events/power.h>
+#include <linux/cpufreq.h>
 #include <linux/cpuidle.h>
 #include <linux/cpuidle.h>
 #include <linux/timer.h>
 #include <linux/timer.h>
 
 
@@ -789,6 +790,8 @@ void dpm_resume(pm_message_t state)
 	mutex_unlock(&dpm_list_mtx);
 	mutex_unlock(&dpm_list_mtx);
 	async_synchronize_full();
 	async_synchronize_full();
 	dpm_show_time(starttime, state, NULL);
 	dpm_show_time(starttime, state, NULL);
+
+	cpufreq_resume();
 }
 }
 
 
 /**
 /**
@@ -1259,6 +1262,8 @@ int dpm_suspend(pm_message_t state)
 
 
 	might_sleep();
 	might_sleep();
 
 
+	cpufreq_suspend();
+
 	mutex_lock(&dpm_list_mtx);
 	mutex_lock(&dpm_list_mtx);
 	pm_transition = state;
 	pm_transition = state;
 	async_error = 0;
 	async_error = 0;

+ 1 - 1
drivers/cpufreq/Kconfig

@@ -200,7 +200,7 @@ source "drivers/cpufreq/Kconfig.x86"
 endmenu
 endmenu
 
 
 menu "ARM CPU frequency scaling drivers"
 menu "ARM CPU frequency scaling drivers"
-depends on ARM
+depends on ARM || ARM64
 source "drivers/cpufreq/Kconfig.arm"
 source "drivers/cpufreq/Kconfig.arm"
 endmenu
 endmenu
 
 

+ 0 - 1
drivers/cpufreq/acpi-cpufreq.c

@@ -855,7 +855,6 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 	pr_debug("acpi_cpufreq_cpu_exit\n");
 	pr_debug("acpi_cpufreq_cpu_exit\n");
 
 
 	if (data) {
 	if (data) {
-		cpufreq_frequency_table_put_attr(policy->cpu);
 		per_cpu(acfreq_data, policy->cpu) = NULL;
 		per_cpu(acfreq_data, policy->cpu) = NULL;
 		acpi_processor_unregister_performance(data->acpi_data,
 		acpi_processor_unregister_performance(data->acpi_data,
 						      policy->cpu);
 						      policy->cpu);

+ 0 - 1
drivers/cpufreq/arm_big_little.c

@@ -478,7 +478,6 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	cpufreq_frequency_table_put_attr(policy->cpu);
 	put_cluster_clk_and_freq_table(cpu_dev);
 	put_cluster_clk_and_freq_table(cpu_dev);
 	dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu);
 	dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu);
 
 

+ 0 - 1
drivers/cpufreq/blackfin-cpufreq.c

@@ -195,7 +195,6 @@ static struct cpufreq_driver bfin_driver = {
 	.target_index = bfin_target,
 	.target_index = bfin_target,
 	.get = bfin_getfreq_khz,
 	.get = bfin_getfreq_khz,
 	.init = __bfin_cpu_init,
 	.init = __bfin_cpu_init,
-	.exit = cpufreq_generic_exit,
 	.name = "bfin cpufreq",
 	.name = "bfin cpufreq",
 	.attr = cpufreq_generic_attr,
 	.attr = cpufreq_generic_attr,
 };
 };

+ 0 - 1
drivers/cpufreq/cpufreq-cpu0.c

@@ -109,7 +109,6 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
 	.target_index = cpu0_set_target,
 	.target_index = cpu0_set_target,
 	.get = cpufreq_generic_get,
 	.get = cpufreq_generic_get,
 	.init = cpu0_cpufreq_init,
 	.init = cpu0_cpufreq_init,
-	.exit = cpufreq_generic_exit,
 	.name = "generic_cpu0",
 	.name = "generic_cpu0",
 	.attr = cpufreq_generic_attr,
 	.attr = cpufreq_generic_attr,
 };
 };

+ 209 - 206
drivers/cpufreq/cpufreq.c

@@ -26,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
-#include <linux/syscore_ops.h>
+#include <linux/suspend.h>
 #include <linux/tick.h>
 #include <linux/tick.h>
 #include <trace/events/power.h>
 #include <trace/events/power.h>
 
 
@@ -42,10 +42,11 @@ static DEFINE_RWLOCK(cpufreq_driver_lock);
 DEFINE_MUTEX(cpufreq_governor_lock);
 DEFINE_MUTEX(cpufreq_governor_lock);
 static LIST_HEAD(cpufreq_policy_list);
 static LIST_HEAD(cpufreq_policy_list);
 
 
-#ifdef CONFIG_HOTPLUG_CPU
 /* This one keeps track of the previously set governor of a removed CPU */
 /* This one keeps track of the previously set governor of a removed CPU */
 static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
 static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
-#endif
+
+/* Flag to suspend/resume CPUFreq governors */
+static bool cpufreq_suspended;
 
 
 static inline bool has_target(void)
 static inline bool has_target(void)
 {
 {
@@ -181,8 +182,8 @@ unsigned int cpufreq_generic_get(unsigned int cpu)
 	struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
 	struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
 
 
 	if (!policy || IS_ERR(policy->clk)) {
 	if (!policy || IS_ERR(policy->clk)) {
-		pr_err("%s: No %s associated to cpu: %d\n", __func__,
-				policy ? "clk" : "policy", cpu);
+		pr_err("%s: No %s associated to cpu: %d\n",
+		       __func__, policy ? "clk" : "policy", cpu);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -190,6 +191,12 @@ unsigned int cpufreq_generic_get(unsigned int cpu)
 }
 }
 EXPORT_SYMBOL_GPL(cpufreq_generic_get);
 EXPORT_SYMBOL_GPL(cpufreq_generic_get);
 
 
+/* Only for cpufreq core internal use */
+struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
+{
+	return per_cpu(cpufreq_cpu_data, cpu);
+}
+
 struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
 struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
 {
 {
 	struct cpufreq_policy *policy = NULL;
 	struct cpufreq_policy *policy = NULL;
@@ -254,15 +261,15 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
 	if (!l_p_j_ref_freq) {
 	if (!l_p_j_ref_freq) {
 		l_p_j_ref = loops_per_jiffy;
 		l_p_j_ref = loops_per_jiffy;
 		l_p_j_ref_freq = ci->old;
 		l_p_j_ref_freq = ci->old;
-		pr_debug("saving %lu as reference value for loops_per_jiffy; "
-			"freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
+		pr_debug("saving %lu as reference value for loops_per_jiffy; freq is %u kHz\n",
+			 l_p_j_ref, l_p_j_ref_freq);
 	}
 	}
 	if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) ||
 	if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) ||
 	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
 	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
 		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
 		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
 								ci->new);
 								ci->new);
-		pr_debug("scaling loops_per_jiffy to %lu "
-			"for frequency %u kHz\n", loops_per_jiffy, ci->new);
+		pr_debug("scaling loops_per_jiffy to %lu for frequency %u kHz\n",
+			 loops_per_jiffy, ci->new);
 	}
 	}
 }
 }
 #else
 #else
@@ -282,7 +289,7 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
 
 
 	freqs->flags = cpufreq_driver->flags;
 	freqs->flags = cpufreq_driver->flags;
 	pr_debug("notification %u of frequency transition to %u kHz\n",
 	pr_debug("notification %u of frequency transition to %u kHz\n",
-		state, freqs->new);
+		 state, freqs->new);
 
 
 	switch (state) {
 	switch (state) {
 
 
@@ -294,9 +301,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
 		if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
 		if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
 			if ((policy) && (policy->cpu == freqs->cpu) &&
 			if ((policy) && (policy->cpu == freqs->cpu) &&
 			    (policy->cur) && (policy->cur != freqs->old)) {
 			    (policy->cur) && (policy->cur != freqs->old)) {
-				pr_debug("Warning: CPU frequency is"
-					" %u, cpufreq assumed %u kHz.\n",
-					freqs->old, policy->cur);
+				pr_debug("Warning: CPU frequency is %u, cpufreq assumed %u kHz\n",
+					 freqs->old, policy->cur);
 				freqs->old = policy->cur;
 				freqs->old = policy->cur;
 			}
 			}
 		}
 		}
@@ -307,8 +313,8 @@ static void __cpufreq_notify_transition(struct cpufreq_policy *policy,
 
 
 	case CPUFREQ_POSTCHANGE:
 	case CPUFREQ_POSTCHANGE:
 		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
 		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
-		pr_debug("FREQ: %lu - CPU: %lu", (unsigned long)freqs->new,
-			(unsigned long)freqs->cpu);
+		pr_debug("FREQ: %lu - CPU: %lu\n",
+			 (unsigned long)freqs->new, (unsigned long)freqs->cpu);
 		trace_cpu_frequency(freqs->new, freqs->cpu);
 		trace_cpu_frequency(freqs->new, freqs->cpu);
 		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
 		srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
 				CPUFREQ_POSTCHANGE, freqs);
 				CPUFREQ_POSTCHANGE, freqs);
@@ -352,7 +358,7 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition);
 /*********************************************************************
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
  *                          SYSFS INTERFACE                          *
  *********************************************************************/
  *********************************************************************/
-ssize_t show_boost(struct kobject *kobj,
+static ssize_t show_boost(struct kobject *kobj,
 				 struct attribute *attr, char *buf)
 				 struct attribute *attr, char *buf)
 {
 {
 	return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled);
 	return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled);
@@ -368,13 +374,13 @@ static ssize_t store_boost(struct kobject *kobj, struct attribute *attr,
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (cpufreq_boost_trigger_state(enable)) {
 	if (cpufreq_boost_trigger_state(enable)) {
-		pr_err("%s: Cannot %s BOOST!\n", __func__,
-		       enable ? "enable" : "disable");
+		pr_err("%s: Cannot %s BOOST!\n",
+		       __func__, enable ? "enable" : "disable");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	pr_debug("%s: cpufreq BOOST %s\n", __func__,
-		 enable ? "enabled" : "disabled");
+	pr_debug("%s: cpufreq BOOST %s\n",
+		 __func__, enable ? "enabled" : "disabled");
 
 
 	return count;
 	return count;
 }
 }
@@ -879,18 +885,25 @@ err_out_kobj_put:
 
 
 static void cpufreq_init_policy(struct cpufreq_policy *policy)
 static void cpufreq_init_policy(struct cpufreq_policy *policy)
 {
 {
+	struct cpufreq_governor *gov = NULL;
 	struct cpufreq_policy new_policy;
 	struct cpufreq_policy new_policy;
 	int ret = 0;
 	int ret = 0;
 
 
 	memcpy(&new_policy, policy, sizeof(*policy));
 	memcpy(&new_policy, policy, sizeof(*policy));
 
 
+	/* Update governor of new_policy to the governor used before hotplug */
+	gov = __find_governor(per_cpu(cpufreq_cpu_governor, policy->cpu));
+	if (gov)
+		pr_debug("Restoring governor %s for cpu %d\n",
+				policy->governor->name, policy->cpu);
+	else
+		gov = CPUFREQ_DEFAULT_GOVERNOR;
+
+	new_policy.governor = gov;
+
 	/* Use the default policy if its valid. */
 	/* Use the default policy if its valid. */
 	if (cpufreq_driver->setpolicy)
 	if (cpufreq_driver->setpolicy)
-		cpufreq_parse_governor(policy->governor->name,
-					&new_policy.policy, NULL);
-
-	/* assure that the starting sequence is run in cpufreq_set_policy */
-	policy->governor = NULL;
+		cpufreq_parse_governor(gov->name, &new_policy.policy, NULL);
 
 
 	/* set default policy */
 	/* set default policy */
 	ret = cpufreq_set_policy(policy, &new_policy);
 	ret = cpufreq_set_policy(policy, &new_policy);
@@ -949,6 +962,8 @@ static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
 
 
 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 	read_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 
+	policy->governor = NULL;
+
 	return policy;
 	return policy;
 }
 }
 
 
@@ -1022,21 +1037,19 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
 
 
 	up_write(&policy->rwsem);
 	up_write(&policy->rwsem);
 
 
-	cpufreq_frequency_table_update_policy_cpu(policy);
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
 			CPUFREQ_UPDATE_POLICY_CPU, policy);
 			CPUFREQ_UPDATE_POLICY_CPU, policy);
 }
 }
 
 
-static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
-			     bool frozen)
+static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 {
 {
 	unsigned int j, cpu = dev->id;
 	unsigned int j, cpu = dev->id;
 	int ret = -ENOMEM;
 	int ret = -ENOMEM;
 	struct cpufreq_policy *policy;
 	struct cpufreq_policy *policy;
 	unsigned long flags;
 	unsigned long flags;
+	bool recover_policy = cpufreq_suspended;
 #ifdef CONFIG_HOTPLUG_CPU
 #ifdef CONFIG_HOTPLUG_CPU
 	struct cpufreq_policy *tpolicy;
 	struct cpufreq_policy *tpolicy;
-	struct cpufreq_governor *gov;
 #endif
 #endif
 
 
 	if (cpu_is_offline(cpu))
 	if (cpu_is_offline(cpu))
@@ -1075,9 +1088,9 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
 	 * Restore the saved policy when doing light-weight init and fall back
 	 * Restore the saved policy when doing light-weight init and fall back
 	 * to the full init if that fails.
 	 * to the full init if that fails.
 	 */
 	 */
-	policy = frozen ? cpufreq_policy_restore(cpu) : NULL;
+	policy = recover_policy ? cpufreq_policy_restore(cpu) : NULL;
 	if (!policy) {
 	if (!policy) {
-		frozen = false;
+		recover_policy = false;
 		policy = cpufreq_policy_alloc();
 		policy = cpufreq_policy_alloc();
 		if (!policy)
 		if (!policy)
 			goto nomem_out;
 			goto nomem_out;
@@ -1089,12 +1102,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
 	 * the creation of a brand new one. So we need to perform this update
 	 * the creation of a brand new one. So we need to perform this update
 	 * by invoking update_policy_cpu().
 	 * by invoking update_policy_cpu().
 	 */
 	 */
-	if (frozen && cpu != policy->cpu)
+	if (recover_policy && cpu != policy->cpu)
 		update_policy_cpu(policy, cpu);
 		update_policy_cpu(policy, cpu);
 	else
 	else
 		policy->cpu = cpu;
 		policy->cpu = cpu;
 
 
-	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 	cpumask_copy(policy->cpus, cpumask_of(cpu));
 	cpumask_copy(policy->cpus, cpumask_of(cpu));
 
 
 	init_completion(&policy->kobj_unregister);
 	init_completion(&policy->kobj_unregister);
@@ -1118,7 +1130,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
 	 */
 	 */
 	cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
 	cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
 
 
-	if (!frozen) {
+	if (!recover_policy) {
 		policy->user_policy.min = policy->min;
 		policy->user_policy.min = policy->min;
 		policy->user_policy.max = policy->max;
 		policy->user_policy.max = policy->max;
 	}
 	}
@@ -1180,16 +1192,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
 				     CPUFREQ_START, policy);
 				     CPUFREQ_START, policy);
 
 
-#ifdef CONFIG_HOTPLUG_CPU
-	gov = __find_governor(per_cpu(cpufreq_cpu_governor, cpu));
-	if (gov) {
-		policy->governor = gov;
-		pr_debug("Restoring governor %s for cpu %d\n",
-		       policy->governor->name, cpu);
-	}
-#endif
-
-	if (!frozen) {
+	if (!recover_policy) {
 		ret = cpufreq_add_dev_interface(policy, dev);
 		ret = cpufreq_add_dev_interface(policy, dev);
 		if (ret)
 		if (ret)
 			goto err_out_unregister;
 			goto err_out_unregister;
@@ -1203,7 +1206,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
 
 
 	cpufreq_init_policy(policy);
 	cpufreq_init_policy(policy);
 
 
-	if (!frozen) {
+	if (!recover_policy) {
 		policy->user_policy.policy = policy->policy;
 		policy->user_policy.policy = policy->policy;
 		policy->user_policy.governor = policy->governor;
 		policy->user_policy.governor = policy->governor;
 	}
 	}
@@ -1226,7 +1229,7 @@ err_get_freq:
 	if (cpufreq_driver->exit)
 	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(policy);
 		cpufreq_driver->exit(policy);
 err_set_policy_cpu:
 err_set_policy_cpu:
-	if (frozen) {
+	if (recover_policy) {
 		/* Do not leave stale fallback data behind. */
 		/* Do not leave stale fallback data behind. */
 		per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL;
 		per_cpu(cpufreq_cpu_data_fallback, cpu) = NULL;
 		cpufreq_policy_put_kobj(policy);
 		cpufreq_policy_put_kobj(policy);
@@ -1250,7 +1253,7 @@ nomem_out:
  */
  */
 static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 {
 {
-	return __cpufreq_add_dev(dev, sif, false);
+	return __cpufreq_add_dev(dev, sif);
 }
 }
 
 
 static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
 static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
@@ -1265,7 +1268,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
 	sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
 	sysfs_remove_link(&cpu_dev->kobj, "cpufreq");
 	ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
 	ret = kobject_move(&policy->kobj, &cpu_dev->kobj);
 	if (ret) {
 	if (ret) {
-		pr_err("%s: Failed to move kobj: %d", __func__, ret);
+		pr_err("%s: Failed to move kobj: %d\n", __func__, ret);
 
 
 		down_write(&policy->rwsem);
 		down_write(&policy->rwsem);
 		cpumask_set_cpu(old_cpu, policy->cpus);
 		cpumask_set_cpu(old_cpu, policy->cpus);
@@ -1281,8 +1284,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
 }
 }
 
 
 static int __cpufreq_remove_dev_prepare(struct device *dev,
 static int __cpufreq_remove_dev_prepare(struct device *dev,
-					struct subsys_interface *sif,
-					bool frozen)
+					struct subsys_interface *sif)
 {
 {
 	unsigned int cpu = dev->id, cpus;
 	unsigned int cpu = dev->id, cpus;
 	int new_cpu, ret;
 	int new_cpu, ret;
@@ -1296,7 +1298,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
 	policy = per_cpu(cpufreq_cpu_data, cpu);
 	policy = per_cpu(cpufreq_cpu_data, cpu);
 
 
 	/* Save the policy somewhere when doing a light-weight tear-down */
 	/* Save the policy somewhere when doing a light-weight tear-down */
-	if (frozen)
+	if (cpufreq_suspended)
 		per_cpu(cpufreq_cpu_data_fallback, cpu) = policy;
 		per_cpu(cpufreq_cpu_data_fallback, cpu) = policy;
 
 
 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -1314,11 +1316,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
 		}
 		}
 	}
 	}
 
 
-#ifdef CONFIG_HOTPLUG_CPU
 	if (!cpufreq_driver->setpolicy)
 	if (!cpufreq_driver->setpolicy)
 		strncpy(per_cpu(cpufreq_cpu_governor, cpu),
 		strncpy(per_cpu(cpufreq_cpu_governor, cpu),
 			policy->governor->name, CPUFREQ_NAME_LEN);
 			policy->governor->name, CPUFREQ_NAME_LEN);
-#endif
 
 
 	down_read(&policy->rwsem);
 	down_read(&policy->rwsem);
 	cpus = cpumask_weight(policy->cpus);
 	cpus = cpumask_weight(policy->cpus);
@@ -1331,9 +1331,9 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
 		if (new_cpu >= 0) {
 		if (new_cpu >= 0) {
 			update_policy_cpu(policy, new_cpu);
 			update_policy_cpu(policy, new_cpu);
 
 
-			if (!frozen) {
+			if (!cpufreq_suspended) {
 				pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
 				pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
-						__func__, new_cpu, cpu);
+					 __func__, new_cpu, cpu);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -1342,8 +1342,7 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
 }
 }
 
 
 static int __cpufreq_remove_dev_finish(struct device *dev,
 static int __cpufreq_remove_dev_finish(struct device *dev,
-				       struct subsys_interface *sif,
-				       bool frozen)
+				       struct subsys_interface *sif)
 {
 {
 	unsigned int cpu = dev->id, cpus;
 	unsigned int cpu = dev->id, cpus;
 	int ret;
 	int ret;
@@ -1373,12 +1372,12 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
 					CPUFREQ_GOV_POLICY_EXIT);
 					CPUFREQ_GOV_POLICY_EXIT);
 			if (ret) {
 			if (ret) {
 				pr_err("%s: Failed to exit governor\n",
 				pr_err("%s: Failed to exit governor\n",
-						__func__);
+				       __func__);
 				return ret;
 				return ret;
 			}
 			}
 		}
 		}
 
 
-		if (!frozen)
+		if (!cpufreq_suspended)
 			cpufreq_policy_put_kobj(policy);
 			cpufreq_policy_put_kobj(policy);
 
 
 		/*
 		/*
@@ -1394,14 +1393,14 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
 		list_del(&policy->policy_list);
 		list_del(&policy->policy_list);
 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 
-		if (!frozen)
+		if (!cpufreq_suspended)
 			cpufreq_policy_free(policy);
 			cpufreq_policy_free(policy);
 	} else {
 	} else {
 		if (has_target()) {
 		if (has_target()) {
 			if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
 			if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) ||
 					(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
 					(ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) {
 				pr_err("%s: Failed to start governor\n",
 				pr_err("%s: Failed to start governor\n",
-						__func__);
+				       __func__);
 				return ret;
 				return ret;
 			}
 			}
 		}
 		}
@@ -1424,10 +1423,10 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
 	if (cpu_is_offline(cpu))
 	if (cpu_is_offline(cpu))
 		return 0;
 		return 0;
 
 
-	ret = __cpufreq_remove_dev_prepare(dev, sif, false);
+	ret = __cpufreq_remove_dev_prepare(dev, sif);
 
 
 	if (!ret)
 	if (!ret)
-		ret = __cpufreq_remove_dev_finish(dev, sif, false);
+		ret = __cpufreq_remove_dev_finish(dev, sif);
 
 
 	return ret;
 	return ret;
 }
 }
@@ -1458,8 +1457,8 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq,
 	struct cpufreq_freqs freqs;
 	struct cpufreq_freqs freqs;
 	unsigned long flags;
 	unsigned long flags;
 
 
-	pr_debug("Warning: CPU frequency out of sync: cpufreq and timing "
-	       "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
+	pr_debug("Warning: CPU frequency out of sync: cpufreq and timing core thinks of %u, is %u kHz\n",
+		 old_freq, new_freq);
 
 
 	freqs.old = old_freq;
 	freqs.old = old_freq;
 	freqs.new = new_freq;
 	freqs.new = new_freq;
@@ -1570,83 +1569,104 @@ static struct subsys_interface cpufreq_interface = {
 	.remove_dev	= cpufreq_remove_dev,
 	.remove_dev	= cpufreq_remove_dev,
 };
 };
 
 
+/*
+ * In case platform wants some specific frequency to be configured
+ * during suspend..
+ */
+int cpufreq_generic_suspend(struct cpufreq_policy *policy)
+{
+	int ret;
+
+	if (!policy->suspend_freq) {
+		pr_err("%s: suspend_freq can't be zero\n", __func__);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: Setting suspend-freq: %u\n", __func__,
+			policy->suspend_freq);
+
+	ret = __cpufreq_driver_target(policy, policy->suspend_freq,
+			CPUFREQ_RELATION_H);
+	if (ret)
+		pr_err("%s: unable to set suspend-freq: %u. err: %d\n",
+				__func__, policy->suspend_freq, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL(cpufreq_generic_suspend);
+
 /**
 /**
- * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
+ * cpufreq_suspend() - Suspend CPUFreq governors
  *
  *
- * This function is only executed for the boot processor.  The other CPUs
- * have been put offline by means of CPU hotplug.
+ * Called during system wide Suspend/Hibernate cycles for suspending governors
+ * as some platforms can't change frequency after this point in suspend cycle.
+ * Because some of the devices (like: i2c, regulators, etc) they use for
+ * changing frequency are suspended quickly after this point.
  */
  */
-static int cpufreq_bp_suspend(void)
+void cpufreq_suspend(void)
 {
 {
-	int ret = 0;
-
-	int cpu = smp_processor_id();
 	struct cpufreq_policy *policy;
 	struct cpufreq_policy *policy;
 
 
-	pr_debug("suspending cpu %u\n", cpu);
+	if (!cpufreq_driver)
+		return;
 
 
-	/* If there's no policy for the boot CPU, we have nothing to do. */
-	policy = cpufreq_cpu_get(cpu);
-	if (!policy)
-		return 0;
+	if (!has_target())
+		return;
 
 
-	if (cpufreq_driver->suspend) {
-		ret = cpufreq_driver->suspend(policy);
-		if (ret)
-			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
-					"step on CPU %u\n", policy->cpu);
+	pr_debug("%s: Suspending Governors\n", __func__);
+
+	list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
+		if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
+			pr_err("%s: Failed to stop governor for policy: %p\n",
+				__func__, policy);
+		else if (cpufreq_driver->suspend
+		    && cpufreq_driver->suspend(policy))
+			pr_err("%s: Failed to suspend driver: %p\n", __func__,
+				policy);
 	}
 	}
 
 
-	cpufreq_cpu_put(policy);
-	return ret;
+	cpufreq_suspended = true;
 }
 }
 
 
 /**
 /**
- * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
+ * cpufreq_resume() - Resume CPUFreq governors
  *
  *
- *	1.) resume CPUfreq hardware support (cpufreq_driver->resume())
- *	2.) schedule call cpufreq_update_policy() ASAP as interrupts are
- *	    restored. It will verify that the current freq is in sync with
- *	    what we believe it to be. This is a bit later than when it
- *	    should be, but nonethteless it's better than calling
- *	    cpufreq_driver->get() here which might re-enable interrupts...
- *
- * This function is only executed for the boot CPU.  The other CPUs have not
- * been turned on yet.
+ * Called during system wide Suspend/Hibernate cycle for resuming governors that
+ * are suspended with cpufreq_suspend().
  */
  */
-static void cpufreq_bp_resume(void)
+void cpufreq_resume(void)
 {
 {
-	int ret = 0;
-
-	int cpu = smp_processor_id();
 	struct cpufreq_policy *policy;
 	struct cpufreq_policy *policy;
 
 
-	pr_debug("resuming cpu %u\n", cpu);
+	if (!cpufreq_driver)
+		return;
 
 
-	/* If there's no policy for the boot CPU, we have nothing to do. */
-	policy = cpufreq_cpu_get(cpu);
-	if (!policy)
+	if (!has_target())
 		return;
 		return;
 
 
-	if (cpufreq_driver->resume) {
-		ret = cpufreq_driver->resume(policy);
-		if (ret) {
-			printk(KERN_ERR "cpufreq: resume failed in ->resume "
-					"step on CPU %u\n", policy->cpu);
-			goto fail;
-		}
-	}
+	pr_debug("%s: Resuming Governors\n", __func__);
 
 
-	schedule_work(&policy->update);
+	cpufreq_suspended = false;
 
 
-fail:
-	cpufreq_cpu_put(policy);
-}
+	list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
+		if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
+		    || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
+			pr_err("%s: Failed to start governor for policy: %p\n",
+				__func__, policy);
+		else if (cpufreq_driver->resume
+		    && cpufreq_driver->resume(policy))
+			pr_err("%s: Failed to resume driver: %p\n", __func__,
+				policy);
 
 
-static struct syscore_ops cpufreq_syscore_ops = {
-	.suspend	= cpufreq_bp_suspend,
-	.resume		= cpufreq_bp_resume,
-};
+		/*
+		 * schedule call cpufreq_update_policy() for boot CPU, i.e. last
+		 * policy in list. It will verify that the current freq is in
+		 * sync with what we believe it to be.
+		 */
+		if (list_is_last(&policy->policy_list, &cpufreq_policy_list))
+			schedule_work(&policy->update);
+	}
+}
 
 
 /**
 /**
  *	cpufreq_get_current_driver - return current driver's name
  *	cpufreq_get_current_driver - return current driver's name
@@ -1762,7 +1782,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
 		target_freq = policy->min;
 		target_freq = policy->min;
 
 
 	pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
 	pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
-			policy->cpu, target_freq, relation, old_target_freq);
+		 policy->cpu, target_freq, relation, old_target_freq);
 
 
 	/*
 	/*
 	 * This might look like a redundant call as we are checking it again
 	 * This might look like a redundant call as we are checking it again
@@ -1807,8 +1827,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
 			freqs.flags = 0;
 			freqs.flags = 0;
 
 
 			pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
 			pr_debug("%s: cpu: %d, oldfreq: %u, new freq: %u\n",
-					__func__, policy->cpu, freqs.old,
-					freqs.new);
+				 __func__, policy->cpu, freqs.old, freqs.new);
 
 
 			cpufreq_notify_transition(policy, &freqs,
 			cpufreq_notify_transition(policy, &freqs,
 					CPUFREQ_PRECHANGE);
 					CPUFREQ_PRECHANGE);
@@ -1817,7 +1836,7 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
 		retval = cpufreq_driver->target_index(policy, index);
 		retval = cpufreq_driver->target_index(policy, index);
 		if (retval)
 		if (retval)
 			pr_err("%s: Failed to change cpu frequency: %d\n",
 			pr_err("%s: Failed to change cpu frequency: %d\n",
-					__func__, retval);
+			       __func__, retval);
 
 
 		if (notify)
 		if (notify)
 			cpufreq_notify_post_transition(policy, &freqs, retval);
 			cpufreq_notify_post_transition(policy, &freqs, retval);
@@ -1863,17 +1882,18 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
 	struct cpufreq_governor *gov = NULL;
 	struct cpufreq_governor *gov = NULL;
 #endif
 #endif
 
 
+	/* Don't start any governor operations if we are entering suspend */
+	if (cpufreq_suspended)
+		return 0;
+
 	if (policy->governor->max_transition_latency &&
 	if (policy->governor->max_transition_latency &&
 	    policy->cpuinfo.transition_latency >
 	    policy->cpuinfo.transition_latency >
 	    policy->governor->max_transition_latency) {
 	    policy->governor->max_transition_latency) {
 		if (!gov)
 		if (!gov)
 			return -EINVAL;
 			return -EINVAL;
 		else {
 		else {
-			printk(KERN_WARNING "%s governor failed, too long"
-			       " transition latency of HW, fallback"
-			       " to %s governor\n",
-			       policy->governor->name,
-			       gov->name);
+			pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n",
+				policy->governor->name, gov->name);
 			policy->governor = gov;
 			policy->governor = gov;
 		}
 		}
 	}
 	}
@@ -1883,7 +1903,7 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
 			return -EINVAL;
 			return -EINVAL;
 
 
 	pr_debug("__cpufreq_governor for CPU %u, event %u\n",
 	pr_debug("__cpufreq_governor for CPU %u, event %u\n",
-						policy->cpu, event);
+		 policy->cpu, event);
 
 
 	mutex_lock(&cpufreq_governor_lock);
 	mutex_lock(&cpufreq_governor_lock);
 	if ((policy->governor_enabled && event == CPUFREQ_GOV_START)
 	if ((policy->governor_enabled && event == CPUFREQ_GOV_START)
@@ -1950,9 +1970,7 @@ EXPORT_SYMBOL_GPL(cpufreq_register_governor);
 
 
 void cpufreq_unregister_governor(struct cpufreq_governor *governor)
 void cpufreq_unregister_governor(struct cpufreq_governor *governor)
 {
 {
-#ifdef CONFIG_HOTPLUG_CPU
 	int cpu;
 	int cpu;
-#endif
 
 
 	if (!governor)
 	if (!governor)
 		return;
 		return;
@@ -1960,14 +1978,12 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor)
 	if (cpufreq_disabled())
 	if (cpufreq_disabled())
 		return;
 		return;
 
 
-#ifdef CONFIG_HOTPLUG_CPU
 	for_each_present_cpu(cpu) {
 	for_each_present_cpu(cpu) {
 		if (cpu_online(cpu))
 		if (cpu_online(cpu))
 			continue;
 			continue;
 		if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name))
 		if (!strcmp(per_cpu(cpufreq_cpu_governor, cpu), governor->name))
 			strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0");
 			strcpy(per_cpu(cpufreq_cpu_governor, cpu), "\0");
 	}
 	}
-#endif
 
 
 	mutex_lock(&cpufreq_governor_mutex);
 	mutex_lock(&cpufreq_governor_mutex);
 	list_del(&governor->governor_list);
 	list_del(&governor->governor_list);
@@ -2012,22 +2028,21 @@ EXPORT_SYMBOL(cpufreq_get_policy);
 static int cpufreq_set_policy(struct cpufreq_policy *policy,
 static int cpufreq_set_policy(struct cpufreq_policy *policy,
 				struct cpufreq_policy *new_policy)
 				struct cpufreq_policy *new_policy)
 {
 {
-	int ret = 0, failed = 1;
+	struct cpufreq_governor *old_gov;
+	int ret;
 
 
-	pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu,
-		new_policy->min, new_policy->max);
+	pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
+		 new_policy->cpu, new_policy->min, new_policy->max);
 
 
 	memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
 	memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
 
 
-	if (new_policy->min > policy->max || new_policy->max < policy->min) {
-		ret = -EINVAL;
-		goto error_out;
-	}
+	if (new_policy->min > policy->max || new_policy->max < policy->min)
+		return -EINVAL;
 
 
 	/* verify the cpu speed can be set within this limit */
 	/* verify the cpu speed can be set within this limit */
 	ret = cpufreq_driver->verify(new_policy);
 	ret = cpufreq_driver->verify(new_policy);
 	if (ret)
 	if (ret)
-		goto error_out;
+		return ret;
 
 
 	/* adjust if necessary - all reasons */
 	/* adjust if necessary - all reasons */
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
@@ -2043,7 +2058,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
 	 */
 	 */
 	ret = cpufreq_driver->verify(new_policy);
 	ret = cpufreq_driver->verify(new_policy);
 	if (ret)
 	if (ret)
-		goto error_out;
+		return ret;
 
 
 	/* notification of the new policy */
 	/* notification of the new policy */
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
 	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
@@ -2053,63 +2068,53 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
 	policy->max = new_policy->max;
 	policy->max = new_policy->max;
 
 
 	pr_debug("new min and max freqs are %u - %u kHz\n",
 	pr_debug("new min and max freqs are %u - %u kHz\n",
-					policy->min, policy->max);
+		 policy->min, policy->max);
 
 
 	if (cpufreq_driver->setpolicy) {
 	if (cpufreq_driver->setpolicy) {
 		policy->policy = new_policy->policy;
 		policy->policy = new_policy->policy;
 		pr_debug("setting range\n");
 		pr_debug("setting range\n");
-		ret = cpufreq_driver->setpolicy(new_policy);
-	} else {
-		if (new_policy->governor != policy->governor) {
-			/* save old, working values */
-			struct cpufreq_governor *old_gov = policy->governor;
-
-			pr_debug("governor switch\n");
-
-			/* end old governor */
-			if (policy->governor) {
-				__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
-				up_write(&policy->rwsem);
-				__cpufreq_governor(policy,
-						CPUFREQ_GOV_POLICY_EXIT);
-				down_write(&policy->rwsem);
-			}
+		return cpufreq_driver->setpolicy(new_policy);
+	}
 
 
-			/* start new governor */
-			policy->governor = new_policy->governor;
-			if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
-				if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) {
-					failed = 0;
-				} else {
-					up_write(&policy->rwsem);
-					__cpufreq_governor(policy,
-							CPUFREQ_GOV_POLICY_EXIT);
-					down_write(&policy->rwsem);
-				}
-			}
+	if (new_policy->governor == policy->governor)
+		goto out;
 
 
-			if (failed) {
-				/* new governor failed, so re-start old one */
-				pr_debug("starting governor %s failed\n",
-							policy->governor->name);
-				if (old_gov) {
-					policy->governor = old_gov;
-					__cpufreq_governor(policy,
-							CPUFREQ_GOV_POLICY_INIT);
-					__cpufreq_governor(policy,
-							   CPUFREQ_GOV_START);
-				}
-				ret = -EINVAL;
-				goto error_out;
-			}
-			/* might be a policy change, too, so fall through */
-		}
-		pr_debug("governor: change or update limits\n");
-		ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+	pr_debug("governor switch\n");
+
+	/* save old, working values */
+	old_gov = policy->governor;
+	/* end old governor */
+	if (old_gov) {
+		__cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+		up_write(&policy->rwsem);
+		__cpufreq_governor(policy,CPUFREQ_GOV_POLICY_EXIT);
+		down_write(&policy->rwsem);
 	}
 	}
 
 
-error_out:
-	return ret;
+	/* start new governor */
+	policy->governor = new_policy->governor;
+	if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) {
+		if (!__cpufreq_governor(policy, CPUFREQ_GOV_START))
+			goto out;
+
+		up_write(&policy->rwsem);
+		__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
+		down_write(&policy->rwsem);
+	}
+
+	/* new governor failed, so re-start old one */
+	pr_debug("starting governor %s failed\n", policy->governor->name);
+	if (old_gov) {
+		policy->governor = old_gov;
+		__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
+		__cpufreq_governor(policy, CPUFREQ_GOV_START);
+	}
+
+	return -EINVAL;
+
+ out:
+	pr_debug("governor: change or update limits\n");
+	return __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
 }
 }
 
 
 /**
 /**
@@ -2145,8 +2150,13 @@ int cpufreq_update_policy(unsigned int cpu)
 	 */
 	 */
 	if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
 	if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
 		new_policy.cur = cpufreq_driver->get(cpu);
 		new_policy.cur = cpufreq_driver->get(cpu);
+		if (WARN_ON(!new_policy.cur)) {
+			ret = -EIO;
+			goto no_policy;
+		}
+
 		if (!policy->cur) {
 		if (!policy->cur) {
-			pr_debug("Driver did not initialize current freq");
+			pr_debug("Driver did not initialize current freq\n");
 			policy->cur = new_policy.cur;
 			policy->cur = new_policy.cur;
 		} else {
 		} else {
 			if (policy->cur != new_policy.cur && has_target())
 			if (policy->cur != new_policy.cur && has_target())
@@ -2170,30 +2180,24 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
 {
 {
 	unsigned int cpu = (unsigned long)hcpu;
 	unsigned int cpu = (unsigned long)hcpu;
 	struct device *dev;
 	struct device *dev;
-	bool frozen = false;
 
 
 	dev = get_cpu_device(cpu);
 	dev = get_cpu_device(cpu);
 	if (dev) {
 	if (dev) {
-
-		if (action & CPU_TASKS_FROZEN)
-			frozen = true;
-
 		switch (action & ~CPU_TASKS_FROZEN) {
 		switch (action & ~CPU_TASKS_FROZEN) {
 		case CPU_ONLINE:
 		case CPU_ONLINE:
-			__cpufreq_add_dev(dev, NULL, frozen);
-			cpufreq_update_policy(cpu);
+			__cpufreq_add_dev(dev, NULL);
 			break;
 			break;
 
 
 		case CPU_DOWN_PREPARE:
 		case CPU_DOWN_PREPARE:
-			__cpufreq_remove_dev_prepare(dev, NULL, frozen);
+			__cpufreq_remove_dev_prepare(dev, NULL);
 			break;
 			break;
 
 
 		case CPU_POST_DEAD:
 		case CPU_POST_DEAD:
-			__cpufreq_remove_dev_finish(dev, NULL, frozen);
+			__cpufreq_remove_dev_finish(dev, NULL);
 			break;
 			break;
 
 
 		case CPU_DOWN_FAILED:
 		case CPU_DOWN_FAILED:
-			__cpufreq_add_dev(dev, NULL, frozen);
+			__cpufreq_add_dev(dev, NULL);
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -2249,8 +2253,8 @@ int cpufreq_boost_trigger_state(int state)
 		cpufreq_driver->boost_enabled = !state;
 		cpufreq_driver->boost_enabled = !state;
 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
 
-		pr_err("%s: Cannot %s BOOST\n", __func__,
-		       state ? "enable" : "disable");
+		pr_err("%s: Cannot %s BOOST\n",
+		       __func__, state ? "enable" : "disable");
 	}
 	}
 
 
 	return ret;
 	return ret;
@@ -2322,7 +2326,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 		ret = cpufreq_sysfs_create_file(&boost.attr);
 		ret = cpufreq_sysfs_create_file(&boost.attr);
 		if (ret) {
 		if (ret) {
 			pr_err("%s: cannot register global BOOST sysfs file\n",
 			pr_err("%s: cannot register global BOOST sysfs file\n",
-				__func__);
+			       __func__);
 			goto err_null_driver;
 			goto err_null_driver;
 		}
 		}
 	}
 	}
@@ -2345,7 +2349,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 		/* if all ->init() calls failed, unregister */
 		/* if all ->init() calls failed, unregister */
 		if (ret) {
 		if (ret) {
 			pr_debug("no CPU initialized for driver %s\n",
 			pr_debug("no CPU initialized for driver %s\n",
-							driver_data->name);
+				 driver_data->name);
 			goto err_if_unreg;
 			goto err_if_unreg;
 		}
 		}
 	}
 	}
@@ -2409,7 +2413,6 @@ static int __init cpufreq_core_init(void)
 
 
 	cpufreq_global_kobject = kobject_create();
 	cpufreq_global_kobject = kobject_create();
 	BUG_ON(!cpufreq_global_kobject);
 	BUG_ON(!cpufreq_global_kobject);
-	register_syscore_ops(&cpufreq_syscore_ops);
 
 
 	return 0;
 	return 0;
 }
 }

+ 13 - 25
drivers/cpufreq/cpufreq_stats.c

@@ -180,27 +180,25 @@ static void cpufreq_stats_free_table(unsigned int cpu)
 	cpufreq_cpu_put(policy);
 	cpufreq_cpu_put(policy);
 }
 }
 
 
-static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
-		struct cpufreq_frequency_table *table)
+static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
 {
 {
 	unsigned int i, j, count = 0, ret = 0;
 	unsigned int i, j, count = 0, ret = 0;
 	struct cpufreq_stats *stat;
 	struct cpufreq_stats *stat;
-	struct cpufreq_policy *current_policy;
 	unsigned int alloc_size;
 	unsigned int alloc_size;
 	unsigned int cpu = policy->cpu;
 	unsigned int cpu = policy->cpu;
+	struct cpufreq_frequency_table *table;
+
+	table = cpufreq_frequency_get_table(cpu);
+	if (unlikely(!table))
+		return 0;
+
 	if (per_cpu(cpufreq_stats_table, cpu))
 	if (per_cpu(cpufreq_stats_table, cpu))
 		return -EBUSY;
 		return -EBUSY;
 	stat = kzalloc(sizeof(*stat), GFP_KERNEL);
 	stat = kzalloc(sizeof(*stat), GFP_KERNEL);
 	if ((stat) == NULL)
 	if ((stat) == NULL)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	current_policy = cpufreq_cpu_get(cpu);
-	if (current_policy == NULL) {
-		ret = -EINVAL;
-		goto error_get_fail;
-	}
-
-	ret = sysfs_create_group(&current_policy->kobj, &stats_attr_group);
+	ret = sysfs_create_group(&policy->kobj, &stats_attr_group);
 	if (ret)
 	if (ret)
 		goto error_out;
 		goto error_out;
 
 
@@ -223,7 +221,7 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
 	stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
 	stat->time_in_state = kzalloc(alloc_size, GFP_KERNEL);
 	if (!stat->time_in_state) {
 	if (!stat->time_in_state) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
-		goto error_out;
+		goto error_alloc;
 	}
 	}
 	stat->freq_table = (unsigned int *)(stat->time_in_state + count);
 	stat->freq_table = (unsigned int *)(stat->time_in_state + count);
 
 
@@ -243,11 +241,10 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy,
 	stat->last_time = get_jiffies_64();
 	stat->last_time = get_jiffies_64();
 	stat->last_index = freq_table_get_index(stat, policy->cur);
 	stat->last_index = freq_table_get_index(stat, policy->cur);
 	spin_unlock(&cpufreq_stats_lock);
 	spin_unlock(&cpufreq_stats_lock);
-	cpufreq_cpu_put(current_policy);
 	return 0;
 	return 0;
+error_alloc:
+	sysfs_remove_group(&policy->kobj, &stats_attr_group);
 error_out:
 error_out:
-	cpufreq_cpu_put(current_policy);
-error_get_fail:
 	kfree(stat);
 	kfree(stat);
 	per_cpu(cpufreq_stats_table, cpu) = NULL;
 	per_cpu(cpufreq_stats_table, cpu) = NULL;
 	return ret;
 	return ret;
@@ -256,7 +253,6 @@ error_get_fail:
 static void cpufreq_stats_create_table(unsigned int cpu)
 static void cpufreq_stats_create_table(unsigned int cpu)
 {
 {
 	struct cpufreq_policy *policy;
 	struct cpufreq_policy *policy;
-	struct cpufreq_frequency_table *table;
 
 
 	/*
 	/*
 	 * "likely(!policy)" because normally cpufreq_stats will be registered
 	 * "likely(!policy)" because normally cpufreq_stats will be registered
@@ -266,9 +262,7 @@ static void cpufreq_stats_create_table(unsigned int cpu)
 	if (likely(!policy))
 	if (likely(!policy))
 		return;
 		return;
 
 
-	table = cpufreq_frequency_get_table(policy->cpu);
-	if (likely(table))
-		__cpufreq_stats_create_table(policy, table);
+	__cpufreq_stats_create_table(policy);
 
 
 	cpufreq_cpu_put(policy);
 	cpufreq_cpu_put(policy);
 }
 }
@@ -291,20 +285,14 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb,
 {
 {
 	int ret = 0;
 	int ret = 0;
 	struct cpufreq_policy *policy = data;
 	struct cpufreq_policy *policy = data;
-	struct cpufreq_frequency_table *table;
-	unsigned int cpu = policy->cpu;
 
 
 	if (val == CPUFREQ_UPDATE_POLICY_CPU) {
 	if (val == CPUFREQ_UPDATE_POLICY_CPU) {
 		cpufreq_stats_update_policy_cpu(policy);
 		cpufreq_stats_update_policy_cpu(policy);
 		return 0;
 		return 0;
 	}
 	}
 
 
-	table = cpufreq_frequency_get_table(cpu);
-	if (!table)
-		return 0;
-
 	if (val == CPUFREQ_CREATE_POLICY)
 	if (val == CPUFREQ_CREATE_POLICY)
-		ret = __cpufreq_stats_create_table(policy, table);
+		ret = __cpufreq_stats_create_table(policy);
 	else if (val == CPUFREQ_REMOVE_POLICY)
 	else if (val == CPUFREQ_REMOVE_POLICY)
 		__cpufreq_stats_free_table(policy);
 		__cpufreq_stats_free_table(policy);
 
 

+ 0 - 1
drivers/cpufreq/cris-artpec3-cpufreq.c

@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = {
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.target_index = cris_freq_target,
 	.target_index = cris_freq_target,
 	.init	= cris_freq_cpu_init,
 	.init	= cris_freq_cpu_init,
-	.exit	= cpufreq_generic_exit,
 	.name	= "cris_freq",
 	.name	= "cris_freq",
 	.attr	= cpufreq_generic_attr,
 	.attr	= cpufreq_generic_attr,
 };
 };

+ 0 - 1
drivers/cpufreq/cris-etraxfs-cpufreq.c

@@ -57,7 +57,6 @@ static struct cpufreq_driver cris_freq_driver = {
 	.verify = cpufreq_generic_frequency_table_verify,
 	.verify = cpufreq_generic_frequency_table_verify,
 	.target_index = cris_freq_target,
 	.target_index = cris_freq_target,
 	.init = cris_freq_cpu_init,
 	.init = cris_freq_cpu_init,
-	.exit = cpufreq_generic_exit,
 	.name = "cris_freq",
 	.name = "cris_freq",
 	.attr = cpufreq_generic_attr,
 	.attr = cpufreq_generic_attr,
 };
 };

+ 0 - 1
drivers/cpufreq/davinci-cpufreq.c

@@ -125,7 +125,6 @@ static struct cpufreq_driver davinci_driver = {
 	.target_index	= davinci_target,
 	.target_index	= davinci_target,
 	.get		= cpufreq_generic_get,
 	.get		= cpufreq_generic_get,
 	.init		= davinci_cpu_init,
 	.init		= davinci_cpu_init,
-	.exit		= cpufreq_generic_exit,
 	.name		= "davinci",
 	.name		= "davinci",
 	.attr		= cpufreq_generic_attr,
 	.attr		= cpufreq_generic_attr,
 };
 };

+ 0 - 1
drivers/cpufreq/e_powersaver.c

@@ -382,7 +382,6 @@ static int eps_cpu_exit(struct cpufreq_policy *policy)
 	unsigned int cpu = policy->cpu;
 	unsigned int cpu = policy->cpu;
 
 
 	/* Bye */
 	/* Bye */
-	cpufreq_frequency_table_put_attr(policy->cpu);
 	kfree(eps_cpu[cpu]);
 	kfree(eps_cpu[cpu]);
 	eps_cpu[cpu] = NULL;
 	eps_cpu[cpu] = NULL;
 	return 0;
 	return 0;

+ 0 - 1
drivers/cpufreq/elanfreq.c

@@ -198,7 +198,6 @@ static struct cpufreq_driver elanfreq_driver = {
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.target_index	= elanfreq_target,
 	.target_index	= elanfreq_target,
 	.init		= elanfreq_cpu_init,
 	.init		= elanfreq_cpu_init,
-	.exit		= cpufreq_generic_exit,
 	.name		= "elanfreq",
 	.name		= "elanfreq",
 	.attr		= cpufreq_generic_attr,
 	.attr		= cpufreq_generic_attr,
 };
 };

+ 7 - 90
drivers/cpufreq/exynos-cpufreq.c

@@ -16,7 +16,6 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/consumer.h>
 #include <linux/cpufreq.h>
 #include <linux/cpufreq.h>
-#include <linux/suspend.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 
 
 #include <plat/cpu.h>
 #include <plat/cpu.h>
@@ -24,12 +23,8 @@
 #include "exynos-cpufreq.h"
 #include "exynos-cpufreq.h"
 
 
 static struct exynos_dvfs_info *exynos_info;
 static struct exynos_dvfs_info *exynos_info;
-
 static struct regulator *arm_regulator;
 static struct regulator *arm_regulator;
-
 static unsigned int locking_frequency;
 static unsigned int locking_frequency;
-static bool frequency_locked;
-static DEFINE_MUTEX(cpufreq_lock);
 
 
 static int exynos_cpufreq_get_index(unsigned int freq)
 static int exynos_cpufreq_get_index(unsigned int freq)
 {
 {
@@ -134,83 +129,13 @@ out:
 
 
 static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
 static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
 {
 {
-	struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
-	int ret = 0;
-
-	mutex_lock(&cpufreq_lock);
-
-	if (frequency_locked)
-		goto out;
-
-	ret = exynos_cpufreq_scale(freq_table[index].frequency);
-
-out:
-	mutex_unlock(&cpufreq_lock);
-
-	return ret;
-}
-
-#ifdef CONFIG_PM
-static int exynos_cpufreq_suspend(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-
-static int exynos_cpufreq_resume(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-#endif
-
-/**
- * exynos_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
- *			context
- * @notifier
- * @pm_event
- * @v
- *
- * While frequency_locked == true, target() ignores every frequency but
- * locking_frequency. The locking_frequency value is the initial frequency,
- * which is set by the bootloader. In order to eliminate possible
- * inconsistency in clock values, we save and restore frequencies during
- * suspend and resume and block CPUFREQ activities. Note that the standard
- * suspend/resume cannot be used as they are too deep (syscore_ops) for
- * regulator actions.
- */
-static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier,
-				       unsigned long pm_event, void *v)
-{
-	int ret;
-
-	switch (pm_event) {
-	case PM_SUSPEND_PREPARE:
-		mutex_lock(&cpufreq_lock);
-		frequency_locked = true;
-		mutex_unlock(&cpufreq_lock);
-
-		ret = exynos_cpufreq_scale(locking_frequency);
-		if (ret < 0)
-			return NOTIFY_BAD;
-
-		break;
-
-	case PM_POST_SUSPEND:
-		mutex_lock(&cpufreq_lock);
-		frequency_locked = false;
-		mutex_unlock(&cpufreq_lock);
-		break;
-	}
-
-	return NOTIFY_OK;
+	return exynos_cpufreq_scale(exynos_info->freq_table[index].frequency);
 }
 }
 
 
-static struct notifier_block exynos_cpufreq_nb = {
-	.notifier_call = exynos_cpufreq_pm_notifier,
-};
-
 static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
 {
 	policy->clk = exynos_info->cpu_clk;
 	policy->clk = exynos_info->cpu_clk;
+	policy->suspend_freq = locking_frequency;
 	return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
 	return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
 }
 }
 
 
@@ -220,15 +145,13 @@ static struct cpufreq_driver exynos_driver = {
 	.target_index	= exynos_target,
 	.target_index	= exynos_target,
 	.get		= cpufreq_generic_get,
 	.get		= cpufreq_generic_get,
 	.init		= exynos_cpufreq_cpu_init,
 	.init		= exynos_cpufreq_cpu_init,
-	.exit		= cpufreq_generic_exit,
 	.name		= "exynos_cpufreq",
 	.name		= "exynos_cpufreq",
 	.attr		= cpufreq_generic_attr,
 	.attr		= cpufreq_generic_attr,
 #ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW
 #ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW
 	.boost_supported = true,
 	.boost_supported = true,
 #endif
 #endif
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
-	.suspend	= exynos_cpufreq_suspend,
-	.resume		= exynos_cpufreq_resume,
+	.suspend	= cpufreq_generic_suspend,
 #endif
 #endif
 };
 };
 
 
@@ -263,19 +186,13 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
 		goto err_vdd_arm;
 		goto err_vdd_arm;
 	}
 	}
 
 
+	/* Done here as we want to capture boot frequency */
 	locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;
 	locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;
 
 
-	register_pm_notifier(&exynos_cpufreq_nb);
-
-	if (cpufreq_register_driver(&exynos_driver)) {
-		pr_err("%s: failed to register cpufreq driver\n", __func__);
-		goto err_cpufreq;
-	}
-
-	return 0;
-err_cpufreq:
-	unregister_pm_notifier(&exynos_cpufreq_nb);
+	if (!cpufreq_register_driver(&exynos_driver))
+		return 0;
 
 
+	pr_err("%s: failed to register cpufreq driver\n", __func__);
 	regulator_put(arm_regulator);
 	regulator_put(arm_regulator);
 err_vdd_arm:
 err_vdd_arm:
 	kfree(exynos_info);
 	kfree(exynos_info);

+ 0 - 1
drivers/cpufreq/exynos5440-cpufreq.c

@@ -312,7 +312,6 @@ static struct cpufreq_driver exynos_driver = {
 	.target_index	= exynos_target,
 	.target_index	= exynos_target,
 	.get		= cpufreq_generic_get,
 	.get		= cpufreq_generic_get,
 	.init		= exynos_cpufreq_cpu_init,
 	.init		= exynos_cpufreq_cpu_init,
-	.exit		= cpufreq_generic_exit,
 	.name		= CPUFREQ_NAME,
 	.name		= CPUFREQ_NAME,
 	.attr		= cpufreq_generic_attr,
 	.attr		= cpufreq_generic_attr,
 };
 };

+ 8 - 38
drivers/cpufreq/freq_table.c

@@ -91,8 +91,8 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
 
 
 /*
 /*
- * Generic routine to verify policy & frequency table, requires driver to call
- * cpufreq_frequency_table_get_attr() prior to it.
+ * Generic routine to verify policy & frequency table, requires driver to set
+ * policy->freq_table prior to it.
  */
  */
 int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
 int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
 {
 {
@@ -203,8 +203,6 @@ int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
 }
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index);
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_index);
 
 
-static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
-
 /**
 /**
  * show_available_freqs - show available frequencies for the specified CPU
  * show_available_freqs - show available frequencies for the specified CPU
  */
  */
@@ -212,15 +210,12 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
 				    bool show_boost)
 				    bool show_boost)
 {
 {
 	unsigned int i = 0;
 	unsigned int i = 0;
-	unsigned int cpu = policy->cpu;
 	ssize_t count = 0;
 	ssize_t count = 0;
-	struct cpufreq_frequency_table *table;
+	struct cpufreq_frequency_table *table = policy->freq_table;
 
 
-	if (!per_cpu(cpufreq_show_table, cpu))
+	if (!table)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	table = per_cpu(cpufreq_show_table, cpu);
-
 	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 	for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
 		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
 			continue;
 			continue;
@@ -283,49 +278,24 @@ struct freq_attr *cpufreq_generic_attr[] = {
 };
 };
 EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
 EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
 
 
-/*
- * if you use these, you must assure that the frequency table is valid
- * all the time between get_attr and put_attr!
- */
-void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
-				      unsigned int cpu)
-{
-	pr_debug("setting show_table for cpu %u to %p\n", cpu, table);
-	per_cpu(cpufreq_show_table, cpu) = table;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
-
-void cpufreq_frequency_table_put_attr(unsigned int cpu)
-{
-	pr_debug("clearing show_table for cpu %u\n", cpu);
-	per_cpu(cpufreq_show_table, cpu) = NULL;
-}
-EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
-
 int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
 int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
 				      struct cpufreq_frequency_table *table)
 				      struct cpufreq_frequency_table *table)
 {
 {
 	int ret = cpufreq_frequency_table_cpuinfo(policy, table);
 	int ret = cpufreq_frequency_table_cpuinfo(policy, table);
 
 
 	if (!ret)
 	if (!ret)
-		cpufreq_frequency_table_get_attr(table, policy->cpu);
+		policy->freq_table = table;
 
 
 	return ret;
 	return ret;
 }
 }
 EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
 EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
 
 
-void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy)
-{
-	pr_debug("Updating show_table for new_cpu %u from last_cpu %u\n",
-			policy->cpu, policy->last_cpu);
-	per_cpu(cpufreq_show_table, policy->cpu) = per_cpu(cpufreq_show_table,
-			policy->last_cpu);
-	per_cpu(cpufreq_show_table, policy->last_cpu) = NULL;
-}
+struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
 
 
 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
 struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
 {
 {
-	return per_cpu(cpufreq_show_table, cpu);
+	struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
+	return policy ? policy->freq_table : NULL;
 }
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
 EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);
 
 

+ 0 - 1
drivers/cpufreq/ia64-acpi-cpufreq.c

@@ -332,7 +332,6 @@ acpi_cpufreq_cpu_exit (
 	pr_debug("acpi_cpufreq_cpu_exit\n");
 	pr_debug("acpi_cpufreq_cpu_exit\n");
 
 
 	if (data) {
 	if (data) {
-		cpufreq_frequency_table_put_attr(policy->cpu);
 		acpi_io_data[policy->cpu] = NULL;
 		acpi_io_data[policy->cpu] = NULL;
 		acpi_processor_unregister_performance(&data->acpi_data,
 		acpi_processor_unregister_performance(&data->acpi_data,
 		                                      policy->cpu);
 		                                      policy->cpu);

+ 0 - 1
drivers/cpufreq/imx6q-cpufreq.c

@@ -144,7 +144,6 @@ static struct cpufreq_driver imx6q_cpufreq_driver = {
 	.target_index = imx6q_set_target,
 	.target_index = imx6q_set_target,
 	.get = cpufreq_generic_get,
 	.get = cpufreq_generic_get,
 	.init = imx6q_cpufreq_init,
 	.init = imx6q_cpufreq_init,
-	.exit = cpufreq_generic_exit,
 	.name = "imx6q-cpufreq",
 	.name = "imx6q-cpufreq",
 	.attr = cpufreq_generic_attr,
 	.attr = cpufreq_generic_attr,
 };
 };

+ 12 - 14
drivers/cpufreq/intel_pstate.c

@@ -99,8 +99,7 @@ struct cpudata {
 	u64	prev_aperf;
 	u64	prev_aperf;
 	u64	prev_mperf;
 	u64	prev_mperf;
 	unsigned long long prev_tsc;
 	unsigned long long prev_tsc;
-	int	sample_ptr;
-	struct sample samples[SAMPLE_COUNT];
+	struct sample sample;
 };
 };
 
 
 static struct cpudata **all_cpu_data;
 static struct cpudata **all_cpu_data;
@@ -154,7 +153,7 @@ static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
 	pid->setpoint = setpoint;
 	pid->setpoint = setpoint;
 	pid->deadband  = deadband;
 	pid->deadband  = deadband;
 	pid->integral  = int_tofp(integral);
 	pid->integral  = int_tofp(integral);
-	pid->last_err  = setpoint - busy;
+	pid->last_err  = int_tofp(setpoint) - int_tofp(busy);
 }
 }
 
 
 static inline void pid_p_gain_set(struct _pid *pid, int percent)
 static inline void pid_p_gain_set(struct _pid *pid, int percent)
@@ -586,15 +585,14 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
 	mperf = mperf >> FRAC_BITS;
 	mperf = mperf >> FRAC_BITS;
 	tsc = tsc >> FRAC_BITS;
 	tsc = tsc >> FRAC_BITS;
 
 
-	cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
-	cpu->samples[cpu->sample_ptr].aperf = aperf;
-	cpu->samples[cpu->sample_ptr].mperf = mperf;
-	cpu->samples[cpu->sample_ptr].tsc = tsc;
-	cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf;
-	cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf;
-	cpu->samples[cpu->sample_ptr].tsc -= cpu->prev_tsc;
+	cpu->sample.aperf = aperf;
+	cpu->sample.mperf = mperf;
+	cpu->sample.tsc = tsc;
+	cpu->sample.aperf -= cpu->prev_aperf;
+	cpu->sample.mperf -= cpu->prev_mperf;
+	cpu->sample.tsc -= cpu->prev_tsc;
 
 
-	intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]);
+	intel_pstate_calc_busy(cpu, &cpu->sample);
 
 
 	cpu->prev_aperf = aperf;
 	cpu->prev_aperf = aperf;
 	cpu->prev_mperf = mperf;
 	cpu->prev_mperf = mperf;
@@ -614,7 +612,7 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
 {
 {
 	int32_t core_busy, max_pstate, current_pstate;
 	int32_t core_busy, max_pstate, current_pstate;
 
 
-	core_busy = cpu->samples[cpu->sample_ptr].core_pct_busy;
+	core_busy = cpu->sample.core_pct_busy;
 	max_pstate = int_tofp(cpu->pstate.max_pstate);
 	max_pstate = int_tofp(cpu->pstate.max_pstate);
 	current_pstate = int_tofp(cpu->pstate.current_pstate);
 	current_pstate = int_tofp(cpu->pstate.current_pstate);
 	core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
 	core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
@@ -648,7 +646,7 @@ static void intel_pstate_timer_func(unsigned long __data)
 
 
 	intel_pstate_sample(cpu);
 	intel_pstate_sample(cpu);
 
 
-	sample = &cpu->samples[cpu->sample_ptr];
+	sample = &cpu->sample;
 
 
 	intel_pstate_adjust_busy_pstate(cpu);
 	intel_pstate_adjust_busy_pstate(cpu);
 
 
@@ -729,7 +727,7 @@ static unsigned int intel_pstate_get(unsigned int cpu_num)
 	cpu = all_cpu_data[cpu_num];
 	cpu = all_cpu_data[cpu_num];
 	if (!cpu)
 	if (!cpu)
 		return 0;
 		return 0;
-	sample = &cpu->samples[cpu->sample_ptr];
+	sample = &cpu->sample;
 	return sample->freq;
 	return sample->freq;
 }
 }
 
 

+ 0 - 1
drivers/cpufreq/kirkwood-cpufreq.c

@@ -102,7 +102,6 @@ static struct cpufreq_driver kirkwood_cpufreq_driver = {
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.target_index = kirkwood_cpufreq_target,
 	.target_index = kirkwood_cpufreq_target,
 	.init	= kirkwood_cpufreq_cpu_init,
 	.init	= kirkwood_cpufreq_cpu_init,
-	.exit	= cpufreq_generic_exit,
 	.name	= "kirkwood-cpufreq",
 	.name	= "kirkwood-cpufreq",
 	.attr	= cpufreq_generic_attr,
 	.attr	= cpufreq_generic_attr,
 };
 };

+ 0 - 1
drivers/cpufreq/longhaul.c

@@ -913,7 +913,6 @@ static struct cpufreq_driver longhaul_driver = {
 	.target_index = longhaul_target,
 	.target_index = longhaul_target,
 	.get	= longhaul_get,
 	.get	= longhaul_get,
 	.init	= longhaul_cpu_init,
 	.init	= longhaul_cpu_init,
-	.exit	= cpufreq_generic_exit,
 	.name	= "longhaul",
 	.name	= "longhaul",
 	.attr	= cpufreq_generic_attr,
 	.attr	= cpufreq_generic_attr,
 };
 };

+ 0 - 1
drivers/cpufreq/loongson2_cpufreq.c

@@ -104,7 +104,6 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
 
 static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
 static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
 {
 {
-	cpufreq_frequency_table_put_attr(policy->cpu);
 	clk_put(policy->clk);
 	clk_put(policy->clk);
 	return 0;
 	return 0;
 }
 }

+ 0 - 1
drivers/cpufreq/omap-cpufreq.c

@@ -143,7 +143,6 @@ fail:
 
 
 static int omap_cpu_exit(struct cpufreq_policy *policy)
 static int omap_cpu_exit(struct cpufreq_policy *policy)
 {
 {
-	cpufreq_frequency_table_put_attr(policy->cpu);
 	freq_table_free();
 	freq_table_free();
 	clk_put(policy->clk);
 	clk_put(policy->clk);
 	return 0;
 	return 0;

+ 0 - 1
drivers/cpufreq/p4-clockmod.c

@@ -237,7 +237,6 @@ static struct cpufreq_driver p4clockmod_driver = {
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.target_index	= cpufreq_p4_target,
 	.target_index	= cpufreq_p4_target,
 	.init		= cpufreq_p4_cpu_init,
 	.init		= cpufreq_p4_cpu_init,
-	.exit		= cpufreq_generic_exit,
 	.get		= cpufreq_p4_get,
 	.get		= cpufreq_p4_get,
 	.name		= "p4-clockmod",
 	.name		= "p4-clockmod",
 	.attr		= cpufreq_generic_attr,
 	.attr		= cpufreq_generic_attr,

+ 0 - 1
drivers/cpufreq/pasemi-cpufreq.c

@@ -234,7 +234,6 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 	if (sdcpwr_mapbase)
 	if (sdcpwr_mapbase)
 		iounmap(sdcpwr_mapbase);
 		iounmap(sdcpwr_mapbase);
 
 
-	cpufreq_frequency_table_put_attr(policy->cpu);
 	return 0;
 	return 0;
 }
 }
 
 

+ 0 - 1
drivers/cpufreq/powernow-k6.c

@@ -231,7 +231,6 @@ static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
 		if (i == max_multiplier)
 		if (i == max_multiplier)
 			powernow_k6_target(policy, i);
 			powernow_k6_target(policy, i);
 	}
 	}
-	cpufreq_frequency_table_put_attr(policy->cpu);
 	return 0;
 	return 0;
 }
 }
 
 

+ 0 - 2
drivers/cpufreq/powernow-k7.c

@@ -664,8 +664,6 @@ static int powernow_cpu_init(struct cpufreq_policy *policy)
 
 
 static int powernow_cpu_exit(struct cpufreq_policy *policy)
 static int powernow_cpu_exit(struct cpufreq_policy *policy)
 {
 {
-	cpufreq_frequency_table_put_attr(policy->cpu);
-
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
 	if (acpi_processor_perf) {
 	if (acpi_processor_perf) {
 		acpi_processor_unregister_performance(acpi_processor_perf, 0);
 		acpi_processor_unregister_performance(acpi_processor_perf, 0);

+ 0 - 2
drivers/cpufreq/powernow-k8.c

@@ -1164,8 +1164,6 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
 
 
 	powernow_k8_cpu_exit_acpi(data);
 	powernow_k8_cpu_exit_acpi(data);
 
 
-	cpufreq_frequency_table_put_attr(pol->cpu);
-
 	kfree(data->powernow_table);
 	kfree(data->powernow_table);
 	kfree(data);
 	kfree(data);
 	for_each_cpu(cpu, pol->cpus)
 	for_each_cpu(cpu, pol->cpus)

+ 0 - 1
drivers/cpufreq/ppc-corenet-cpufreq.c

@@ -228,7 +228,6 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 	struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
 	struct cpu_data *data = per_cpu(cpu_data, policy->cpu);
 	unsigned int cpu;
 	unsigned int cpu;
 
 
-	cpufreq_frequency_table_put_attr(policy->cpu);
 	of_node_put(data->parent);
 	of_node_put(data->parent);
 	kfree(data->table);
 	kfree(data->table);
 	kfree(data);
 	kfree(data);

+ 0 - 1
drivers/cpufreq/ppc_cbe_cpufreq.c

@@ -141,7 +141,6 @@ static struct cpufreq_driver cbe_cpufreq_driver = {
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.target_index	= cbe_cpufreq_target,
 	.target_index	= cbe_cpufreq_target,
 	.init		= cbe_cpufreq_cpu_init,
 	.init		= cbe_cpufreq_cpu_init,
-	.exit		= cpufreq_generic_exit,
 	.name		= "cbe-cpufreq",
 	.name		= "cbe-cpufreq",
 	.flags		= CPUFREQ_CONST_LOOPS,
 	.flags		= CPUFREQ_CONST_LOOPS,
 };
 };

+ 0 - 1
drivers/cpufreq/pxa2xx-cpufreq.c

@@ -427,7 +427,6 @@ static struct cpufreq_driver pxa_cpufreq_driver = {
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.target_index = pxa_set_target,
 	.target_index = pxa_set_target,
 	.init	= pxa_cpufreq_init,
 	.init	= pxa_cpufreq_init,
-	.exit	= cpufreq_generic_exit,
 	.get	= pxa_cpufreq_get,
 	.get	= pxa_cpufreq_get,
 	.name	= "PXA2xx",
 	.name	= "PXA2xx",
 };
 };

+ 0 - 1
drivers/cpufreq/pxa3xx-cpufreq.c

@@ -205,7 +205,6 @@ static struct cpufreq_driver pxa3xx_cpufreq_driver = {
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.target_index	= pxa3xx_cpufreq_set,
 	.target_index	= pxa3xx_cpufreq_set,
 	.init		= pxa3xx_cpufreq_init,
 	.init		= pxa3xx_cpufreq_init,
-	.exit		= cpufreq_generic_exit,
 	.get		= pxa3xx_cpufreq_get,
 	.get		= pxa3xx_cpufreq_get,
 	.name		= "pxa3xx-cpufreq",
 	.name		= "pxa3xx-cpufreq",
 };
 };

+ 3 - 46
drivers/cpufreq/s5pv210-cpufreq.c

@@ -18,7 +18,6 @@
 #include <linux/cpufreq.h>
 #include <linux/cpufreq.h>
 #include <linux/reboot.h>
 #include <linux/reboot.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/consumer.h>
-#include <linux/suspend.h>
 
 
 #include <mach/map.h>
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-clock.h>
@@ -435,18 +434,6 @@ exit:
 	return ret;
 	return ret;
 }
 }
 
 
-#ifdef CONFIG_PM
-static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-
-static int s5pv210_cpufreq_resume(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-#endif
-
 static int check_mem_type(void __iomem *dmc_reg)
 static int check_mem_type(void __iomem *dmc_reg)
 {
 {
 	unsigned long val;
 	unsigned long val;
@@ -502,6 +489,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
 	s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
 	s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
 	s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
 	s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
 
 
+	policy->suspend_freq = SLEEP_FREQ;
 	return cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
 	return cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
 
 
 out_dmc1:
 out_dmc1:
@@ -511,32 +499,6 @@ out_dmc0:
 	return ret;
 	return ret;
 }
 }
 
 
-static int s5pv210_cpufreq_notifier_event(struct notifier_block *this,
-					  unsigned long event, void *ptr)
-{
-	int ret;
-
-	switch (event) {
-	case PM_SUSPEND_PREPARE:
-		ret = cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
-		if (ret < 0)
-			return NOTIFY_BAD;
-
-		/* Disable updation of cpu frequency */
-		no_cpufreq_access = true;
-		return NOTIFY_OK;
-	case PM_POST_RESTORE:
-	case PM_POST_SUSPEND:
-		/* Enable updation of cpu frequency */
-		no_cpufreq_access = false;
-		cpufreq_driver_target(cpufreq_cpu_get(0), SLEEP_FREQ, 0);
-
-		return NOTIFY_OK;
-	}
-
-	return NOTIFY_DONE;
-}
-
 static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
 static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
 						 unsigned long event, void *ptr)
 						 unsigned long event, void *ptr)
 {
 {
@@ -558,15 +520,11 @@ static struct cpufreq_driver s5pv210_driver = {
 	.init		= s5pv210_cpu_init,
 	.init		= s5pv210_cpu_init,
 	.name		= "s5pv210",
 	.name		= "s5pv210",
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
-	.suspend	= s5pv210_cpufreq_suspend,
-	.resume		= s5pv210_cpufreq_resume,
+	.suspend	= cpufreq_generic_suspend,
+	.resume		= cpufreq_generic_suspend, /* We need to set SLEEP FREQ again */
 #endif
 #endif
 };
 };
 
 
-static struct notifier_block s5pv210_cpufreq_notifier = {
-	.notifier_call = s5pv210_cpufreq_notifier_event,
-};
-
 static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
 static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
 	.notifier_call = s5pv210_cpufreq_reboot_notifier_event,
 	.notifier_call = s5pv210_cpufreq_reboot_notifier_event,
 };
 };
@@ -586,7 +544,6 @@ static int __init s5pv210_cpufreq_init(void)
 		return PTR_ERR(int_regulator);
 		return PTR_ERR(int_regulator);
 	}
 	}
 
 
-	register_pm_notifier(&s5pv210_cpufreq_notifier);
 	register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier);
 	register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier);
 
 
 	return cpufreq_register_driver(&s5pv210_driver);
 	return cpufreq_register_driver(&s5pv210_driver);

+ 0 - 1
drivers/cpufreq/sc520_freq.c

@@ -93,7 +93,6 @@ static struct cpufreq_driver sc520_freq_driver = {
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.target_index = sc520_freq_target,
 	.target_index = sc520_freq_target,
 	.init	= sc520_freq_cpu_init,
 	.init	= sc520_freq_cpu_init,
-	.exit	= cpufreq_generic_exit,
 	.name	= "sc520_freq",
 	.name	= "sc520_freq",
 	.attr	= cpufreq_generic_attr,
 	.attr	= cpufreq_generic_attr,
 };
 };

+ 0 - 1
drivers/cpufreq/sh-cpufreq.c

@@ -143,7 +143,6 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 	unsigned int cpu = policy->cpu;
 	unsigned int cpu = policy->cpu;
 	struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu);
 	struct clk *cpuclk = &per_cpu(sh_cpuclk, cpu);
 
 
-	cpufreq_frequency_table_put_attr(cpu);
 	clk_put(cpuclk);
 	clk_put(cpuclk);
 
 
 	return 0;
 	return 0;

+ 1 - 3
drivers/cpufreq/sparc-us2e-cpufreq.c

@@ -301,10 +301,8 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
 
 
 static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
 static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
 {
 {
-	if (cpufreq_us2e_driver) {
-		cpufreq_frequency_table_put_attr(policy->cpu);
+	if (cpufreq_us2e_driver)
 		us2e_freq_target(policy, 0);
 		us2e_freq_target(policy, 0);
-	}
 
 
 	return 0;
 	return 0;
 }
 }

+ 1 - 3
drivers/cpufreq/sparc-us3-cpufreq.c

@@ -156,10 +156,8 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
 
 
 static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
 static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
 {
 {
-	if (cpufreq_us3_driver) {
-		cpufreq_frequency_table_put_attr(policy->cpu);
+	if (cpufreq_us3_driver)
 		us3_freq_target(policy, 0);
 		us3_freq_target(policy, 0);
-	}
 
 
 	return 0;
 	return 0;
 }
 }

+ 11 - 3
drivers/cpufreq/spear-cpufreq.c

@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/types.h>
 
 
@@ -163,11 +164,10 @@ static struct cpufreq_driver spear_cpufreq_driver = {
 	.target_index	= spear_cpufreq_target,
 	.target_index	= spear_cpufreq_target,
 	.get		= cpufreq_generic_get,
 	.get		= cpufreq_generic_get,
 	.init		= spear_cpufreq_init,
 	.init		= spear_cpufreq_init,
-	.exit		= cpufreq_generic_exit,
 	.attr		= cpufreq_generic_attr,
 	.attr		= cpufreq_generic_attr,
 };
 };
 
 
-static int spear_cpufreq_driver_init(void)
+static int spear_cpufreq_probe(struct platform_device *pdev)
 {
 {
 	struct device_node *np;
 	struct device_node *np;
 	const struct property *prop;
 	const struct property *prop;
@@ -235,7 +235,15 @@ out_put_node:
 	of_node_put(np);
 	of_node_put(np);
 	return ret;
 	return ret;
 }
 }
-late_initcall(spear_cpufreq_driver_init);
+
+static struct platform_driver spear_cpufreq_platdrv = {
+	.driver = {
+		.name	= "spear-cpufreq",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= spear_cpufreq_probe,
+};
+module_platform_driver(spear_cpufreq_platdrv);
 
 
 MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>");
 MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>");
 MODULE_DESCRIPTION("SPEAr CPUFreq driver");
 MODULE_DESCRIPTION("SPEAr CPUFreq driver");

+ 0 - 2
drivers/cpufreq/speedstep-centrino.c

@@ -406,8 +406,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
 	if (!per_cpu(centrino_model, cpu))
 	if (!per_cpu(centrino_model, cpu))
 		return -ENODEV;
 		return -ENODEV;
 
 
-	cpufreq_frequency_table_put_attr(cpu);
-
 	per_cpu(centrino_model, cpu) = NULL;
 	per_cpu(centrino_model, cpu) = NULL;
 
 
 	return 0;
 	return 0;

+ 0 - 1
drivers/cpufreq/speedstep-ich.c

@@ -311,7 +311,6 @@ static struct cpufreq_driver speedstep_driver = {
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.verify	= cpufreq_generic_frequency_table_verify,
 	.target_index = speedstep_target,
 	.target_index = speedstep_target,
 	.init	= speedstep_cpu_init,
 	.init	= speedstep_cpu_init,
-	.exit	= cpufreq_generic_exit,
 	.get	= speedstep_get,
 	.get	= speedstep_get,
 	.attr	= cpufreq_generic_attr,
 	.attr	= cpufreq_generic_attr,
 };
 };

+ 0 - 1
drivers/cpufreq/speedstep-smi.c

@@ -280,7 +280,6 @@ static struct cpufreq_driver speedstep_driver = {
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.target_index	= speedstep_target,
 	.target_index	= speedstep_target,
 	.init		= speedstep_cpu_init,
 	.init		= speedstep_cpu_init,
-	.exit		= cpufreq_generic_exit,
 	.get		= speedstep_get,
 	.get		= speedstep_get,
 	.resume		= speedstep_resume,
 	.resume		= speedstep_resume,
 	.attr		= cpufreq_generic_attr,
 	.attr		= cpufreq_generic_attr,

+ 5 - 42
drivers/cpufreq/tegra-cpufreq.c

@@ -26,7 +26,6 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/io.h>
-#include <linux/suspend.h>
 
 
 static struct cpufreq_frequency_table freq_table[] = {
 static struct cpufreq_frequency_table freq_table[] = {
 	{ .frequency = 216000 },
 	{ .frequency = 216000 },
@@ -47,9 +46,6 @@ static struct clk *pll_x_clk;
 static struct clk *pll_p_clk;
 static struct clk *pll_p_clk;
 static struct clk *emc_clk;
 static struct clk *emc_clk;
 
 
-static DEFINE_MUTEX(tegra_cpu_lock);
-static bool is_suspended;
-
 static int tegra_cpu_clk_set_rate(unsigned long rate)
 static int tegra_cpu_clk_set_rate(unsigned long rate)
 {
 {
 	int ret;
 	int ret;
@@ -112,42 +108,9 @@ static int tegra_update_cpu_speed(struct cpufreq_policy *policy,
 
 
 static int tegra_target(struct cpufreq_policy *policy, unsigned int index)
 static int tegra_target(struct cpufreq_policy *policy, unsigned int index)
 {
 {
-	int ret = -EBUSY;
-
-	mutex_lock(&tegra_cpu_lock);
-
-	if (!is_suspended)
-		ret = tegra_update_cpu_speed(policy,
-				freq_table[index].frequency);
-
-	mutex_unlock(&tegra_cpu_lock);
-	return ret;
+	return tegra_update_cpu_speed(policy, freq_table[index].frequency);
 }
 }
 
 
-static int tegra_pm_notify(struct notifier_block *nb, unsigned long event,
-	void *dummy)
-{
-	mutex_lock(&tegra_cpu_lock);
-	if (event == PM_SUSPEND_PREPARE) {
-		struct cpufreq_policy *policy = cpufreq_cpu_get(0);
-		is_suspended = true;
-		pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n",
-			freq_table[0].frequency);
-		if (clk_get_rate(cpu_clk) / 1000 != freq_table[0].frequency)
-			tegra_update_cpu_speed(policy, freq_table[0].frequency);
-		cpufreq_cpu_put(policy);
-	} else if (event == PM_POST_SUSPEND) {
-		is_suspended = false;
-	}
-	mutex_unlock(&tegra_cpu_lock);
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block tegra_cpu_pm_notifier = {
-	.notifier_call = tegra_pm_notify,
-};
-
 static int tegra_cpu_init(struct cpufreq_policy *policy)
 static int tegra_cpu_init(struct cpufreq_policy *policy)
 {
 {
 	int ret;
 	int ret;
@@ -166,16 +129,13 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
 		return ret;
 		return ret;
 	}
 	}
 
 
-	if (policy->cpu == 0)
-		register_pm_notifier(&tegra_cpu_pm_notifier);
-
 	policy->clk = cpu_clk;
 	policy->clk = cpu_clk;
+	policy->suspend_freq = freq_table[0].frequency;
 	return 0;
 	return 0;
 }
 }
 
 
 static int tegra_cpu_exit(struct cpufreq_policy *policy)
 static int tegra_cpu_exit(struct cpufreq_policy *policy)
 {
 {
-	cpufreq_frequency_table_put_attr(policy->cpu);
 	clk_disable_unprepare(cpu_clk);
 	clk_disable_unprepare(cpu_clk);
 	clk_disable_unprepare(emc_clk);
 	clk_disable_unprepare(emc_clk);
 	return 0;
 	return 0;
@@ -190,6 +150,9 @@ static struct cpufreq_driver tegra_cpufreq_driver = {
 	.exit		= tegra_cpu_exit,
 	.exit		= tegra_cpu_exit,
 	.name		= "tegra",
 	.name		= "tegra",
 	.attr		= cpufreq_generic_attr,
 	.attr		= cpufreq_generic_attr,
+#ifdef CONFIG_PM
+	.suspend	= cpufreq_generic_suspend,
+#endif
 };
 };
 
 
 static int __init tegra_cpufreq_init(void)
 static int __init tegra_cpufreq_init(void)

+ 12 - 10
include/linux/cpufreq.h

@@ -74,6 +74,8 @@ struct cpufreq_policy {
 	unsigned int		max;    /* in kHz */
 	unsigned int		max;    /* in kHz */
 	unsigned int		cur;    /* in kHz, only needed if cpufreq
 	unsigned int		cur;    /* in kHz, only needed if cpufreq
 					 * governors are used */
 					 * governors are used */
+	unsigned int		suspend_freq; /* freq to set during suspend */
+
 	unsigned int		policy; /* see above */
 	unsigned int		policy; /* see above */
 	struct cpufreq_governor	*governor; /* see below */
 	struct cpufreq_governor	*governor; /* see below */
 	void			*governor_data;
 	void			*governor_data;
@@ -83,6 +85,7 @@ struct cpufreq_policy {
 					 * called, but you're in IRQ context */
 					 * called, but you're in IRQ context */
 
 
 	struct cpufreq_real_policy	user_policy;
 	struct cpufreq_real_policy	user_policy;
+	struct cpufreq_frequency_table	*freq_table;
 
 
 	struct list_head        policy_list;
 	struct list_head        policy_list;
 	struct kobject		kobj;
 	struct kobject		kobj;
@@ -296,6 +299,15 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
 			policy->cpuinfo.max_freq);
 			policy->cpuinfo.max_freq);
 }
 }
 
 
+#ifdef CONFIG_CPU_FREQ
+void cpufreq_suspend(void);
+void cpufreq_resume(void);
+int cpufreq_generic_suspend(struct cpufreq_policy *policy);
+#else
+static inline void cpufreq_suspend(void) {}
+static inline void cpufreq_resume(void) {}
+#endif
+
 /*********************************************************************
 /*********************************************************************
  *                     CPUFREQ NOTIFIER INTERFACE                    *
  *                     CPUFREQ NOTIFIER INTERFACE                    *
  *********************************************************************/
  *********************************************************************/
@@ -463,7 +475,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
 int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
 int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy,
 		unsigned int freq);
 		unsigned int freq);
 
 
-void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy);
 ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
 ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf);
 
 
 #ifdef CONFIG_CPU_FREQ
 #ifdef CONFIG_CPU_FREQ
@@ -490,9 +501,6 @@ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
 /* the following are really really optional */
 /* the following are really really optional */
 extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
 extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
 extern struct freq_attr *cpufreq_generic_attr[];
 extern struct freq_attr *cpufreq_generic_attr[];
-void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
-				      unsigned int cpu);
-void cpufreq_frequency_table_put_attr(unsigned int cpu);
 int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
 int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
 				      struct cpufreq_frequency_table *table);
 				      struct cpufreq_frequency_table *table);
 
 
@@ -500,10 +508,4 @@ unsigned int cpufreq_generic_get(unsigned int cpu);
 int cpufreq_generic_init(struct cpufreq_policy *policy,
 int cpufreq_generic_init(struct cpufreq_policy *policy,
 		struct cpufreq_frequency_table *table,
 		struct cpufreq_frequency_table *table,
 		unsigned int transition_latency);
 		unsigned int transition_latency);
-static inline int cpufreq_generic_exit(struct cpufreq_policy *policy)
-{
-	cpufreq_frequency_table_put_attr(policy->cpu);
-	return 0;
-}
-
 #endif /* _LINUX_CPUFREQ_H */
 #endif /* _LINUX_CPUFREQ_H */