|
@@ -28,6 +28,7 @@
|
|
|
#include <linux/cpu.h>
|
|
|
#include <linux/completion.h>
|
|
|
#include <linux/mutex.h>
|
|
|
+#include <linux/syscore_ops.h>
|
|
|
|
|
|
#include <trace/events/power.h>
|
|
|
|
|
@@ -1340,35 +1341,31 @@ out:
|
|
|
}
|
|
|
EXPORT_SYMBOL(cpufreq_get);
|
|
|
|
|
|
+static struct sysdev_driver cpufreq_sysdev_driver = {
|
|
|
+ .add = cpufreq_add_dev,
|
|
|
+ .remove = cpufreq_remove_dev,
|
|
|
+};
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
- * cpufreq_suspend - let the low level driver prepare for suspend
|
|
|
+ * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
|
|
|
+ *
|
|
|
+ * This function is only executed for the boot processor. The other CPUs
|
|
|
+ * have been put offline by means of CPU hotplug.
|
|
|
*/
|
|
|
-
|
|
|
-static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
|
|
|
+static int cpufreq_bp_suspend(void)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
|
|
|
- int cpu = sysdev->id;
|
|
|
+ int cpu = smp_processor_id();
|
|
|
struct cpufreq_policy *cpu_policy;
|
|
|
|
|
|
dprintk("suspending cpu %u\n", cpu);
|
|
|
|
|
|
- if (!cpu_online(cpu))
|
|
|
- return 0;
|
|
|
-
|
|
|
- /* we may be lax here as interrupts are off. Nonetheless
|
|
|
- * we need to grab the correct cpu policy, as to check
|
|
|
- * whether we really run on this CPU.
|
|
|
- */
|
|
|
-
|
|
|
+ /* If there's no policy for the boot CPU, we have nothing to do. */
|
|
|
cpu_policy = cpufreq_cpu_get(cpu);
|
|
|
if (!cpu_policy)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- /* only handle each CPU group once */
|
|
|
- if (unlikely(cpu_policy->cpu != cpu))
|
|
|
- goto out;
|
|
|
+ return 0;
|
|
|
|
|
|
if (cpufreq_driver->suspend) {
|
|
|
ret = cpufreq_driver->suspend(cpu_policy);
|
|
@@ -1377,13 +1374,12 @@ static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
|
|
|
"step on CPU %u\n", cpu_policy->cpu);
|
|
|
}
|
|
|
|
|
|
-out:
|
|
|
cpufreq_cpu_put(cpu_policy);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * cpufreq_resume - restore proper CPU frequency handling after resume
|
|
|
+ * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
|
|
|
*
|
|
|
* 1.) resume CPUfreq hardware support (cpufreq_driver->resume())
|
|
|
* 2.) schedule call cpufreq_update_policy() ASAP as interrupts are
|
|
@@ -1391,31 +1387,23 @@ out:
|
|
|
* 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.
|
|
|
*/
|
|
|
-static int cpufreq_resume(struct sys_device *sysdev)
|
|
|
+static void cpufreq_bp_resume(void)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
|
|
|
- int cpu = sysdev->id;
|
|
|
+ int cpu = smp_processor_id();
|
|
|
struct cpufreq_policy *cpu_policy;
|
|
|
|
|
|
dprintk("resuming cpu %u\n", cpu);
|
|
|
|
|
|
- if (!cpu_online(cpu))
|
|
|
- return 0;
|
|
|
-
|
|
|
- /* we may be lax here as interrupts are off. Nonetheless
|
|
|
- * we need to grab the correct cpu policy, as to check
|
|
|
- * whether we really run on this CPU.
|
|
|
- */
|
|
|
-
|
|
|
+ /* If there's no policy for the boot CPU, we have nothing to do. */
|
|
|
cpu_policy = cpufreq_cpu_get(cpu);
|
|
|
if (!cpu_policy)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- /* only handle each CPU group once */
|
|
|
- if (unlikely(cpu_policy->cpu != cpu))
|
|
|
- goto fail;
|
|
|
+ return;
|
|
|
|
|
|
if (cpufreq_driver->resume) {
|
|
|
ret = cpufreq_driver->resume(cpu_policy);
|
|
@@ -1430,14 +1418,11 @@ static int cpufreq_resume(struct sys_device *sysdev)
|
|
|
|
|
|
fail:
|
|
|
cpufreq_cpu_put(cpu_policy);
|
|
|
- return ret;
|
|
|
}
|
|
|
|
|
|
-static struct sysdev_driver cpufreq_sysdev_driver = {
|
|
|
- .add = cpufreq_add_dev,
|
|
|
- .remove = cpufreq_remove_dev,
|
|
|
- .suspend = cpufreq_suspend,
|
|
|
- .resume = cpufreq_resume,
|
|
|
+static struct syscore_ops cpufreq_syscore_ops = {
|
|
|
+ .suspend = cpufreq_bp_suspend,
|
|
|
+ .resume = cpufreq_bp_resume,
|
|
|
};
|
|
|
|
|
|
|
|
@@ -2002,6 +1987,7 @@ static int __init cpufreq_core_init(void)
|
|
|
cpufreq_global_kobject = kobject_create_and_add("cpufreq",
|
|
|
&cpu_sysdev_class.kset.kobj);
|
|
|
BUG_ON(!cpufreq_global_kobject);
|
|
|
+ register_syscore_ops(&cpufreq_syscore_ops);
|
|
|
|
|
|
return 0;
|
|
|
}
|