Merge tag 'lsk-v3.10-android-14.07' into develop-3.10
[firefly-linux-kernel-4.4.55.git] / drivers / acpi / processor_thermal.c
index 79cb6533289456c4f43b92dda5d7059a27345afa..e8e652710e65fd58d3c533281cbf2e10a458cc2f 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
-#include <linux/sysdev.h>
 
 #include <asm/uaccess.h>
 
@@ -58,6 +57,27 @@ ACPI_MODULE_NAME("processor_thermal");
 static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg);
 static unsigned int acpi_thermal_cpufreq_is_init = 0;
 
+#define reduction_pctg(cpu) \
+       per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu))
+
+/*
+ * Emulate "per package data" using per cpu data (which should really be
+ * provided elsewhere)
+ *
+ * Note we can lose a CPU on cpu hotunplug, in this case we forget the state
+ * temporarily. Fortunately that's not a big issue here (I hope)
+ */
+static int phys_package_first_cpu(int cpu)
+{
+       int i;
+       int id = topology_physical_package_id(cpu);
+
+       for_each_online_cpu(i)
+               if (topology_physical_package_id(i) == id)
+                       return i;
+       return 0;
+}
+
 static int cpu_has_cpufreq(unsigned int cpu)
 {
        struct cpufreq_policy policy;
@@ -77,7 +97,7 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
 
        max_freq = (
            policy->cpuinfo.max_freq *
-           (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20)
+           (100 - reduction_pctg(policy->cpu) * 20)
        ) / 100;
 
        cpufreq_verify_within_limits(policy, 0, max_freq);
@@ -103,16 +123,28 @@ static int cpufreq_get_cur_state(unsigned int cpu)
        if (!cpu_has_cpufreq(cpu))
                return 0;
 
-       return per_cpu(cpufreq_thermal_reduction_pctg, cpu);
+       return reduction_pctg(cpu);
 }
 
 static int cpufreq_set_cur_state(unsigned int cpu, int state)
 {
+       int i;
+
        if (!cpu_has_cpufreq(cpu))
                return 0;
 
-       per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state;
-       cpufreq_update_policy(cpu);
+       reduction_pctg(cpu) = state;
+
+       /*
+        * Update all the CPUs in the same package because they all
+        * contribute to the temperature and often share the same
+        * frequency.
+        */
+       for_each_online_cpu(i) {
+               if (topology_physical_package_id(i) ==
+                   topology_physical_package_id(cpu))
+                       cpufreq_update_policy(i);
+       }
        return 0;
 }
 
@@ -120,10 +152,6 @@ void acpi_thermal_cpufreq_init(void)
 {
        int i;
 
-       for (i = 0; i < nr_cpu_ids; i++)
-               if (cpu_present(i))
-                       per_cpu(cpufreq_thermal_reduction_pctg, i) = 0;
-
        i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
                                      CPUFREQ_POLICY_NOTIFIER);
        if (!i)
@@ -190,9 +218,13 @@ processor_get_max_state(struct thermal_cooling_device *cdev,
                        unsigned long *state)
 {
        struct acpi_device *device = cdev->devdata;
-       struct acpi_processor *pr = acpi_driver_data(device);
+       struct acpi_processor *pr;
 
-       if (!device || !pr)
+       if (!device)
+               return -EINVAL;
+
+       pr = acpi_driver_data(device);
+       if (!pr)
                return -EINVAL;
 
        *state = acpi_processor_max_state(pr);
@@ -204,9 +236,13 @@ processor_get_cur_state(struct thermal_cooling_device *cdev,
                        unsigned long *cur_state)
 {
        struct acpi_device *device = cdev->devdata;
-       struct acpi_processor *pr = acpi_driver_data(device);
+       struct acpi_processor *pr;
 
-       if (!device || !pr)
+       if (!device)
+               return -EINVAL;
+
+       pr = acpi_driver_data(device);
+       if (!pr)
                return -EINVAL;
 
        *cur_state = cpufreq_get_cur_state(pr->id);
@@ -220,11 +256,15 @@ processor_set_cur_state(struct thermal_cooling_device *cdev,
                        unsigned long state)
 {
        struct acpi_device *device = cdev->devdata;
-       struct acpi_processor *pr = acpi_driver_data(device);
+       struct acpi_processor *pr;
        int result = 0;
        int max_pstate;
 
-       if (!device || !pr)
+       if (!device)
+               return -EINVAL;
+
+       pr = acpi_driver_data(device);
+       if (!pr)
                return -EINVAL;
 
        max_pstate = cpufreq_get_max_state(pr->id);
@@ -244,7 +284,7 @@ processor_set_cur_state(struct thermal_cooling_device *cdev,
        return result;
 }
 
-struct thermal_cooling_device_ops processor_cooling_ops = {
+const struct thermal_cooling_device_ops processor_cooling_ops = {
        .get_max_state = processor_get_max_state,
        .get_cur_state = processor_get_cur_state,
        .set_cur_state = processor_set_cur_state,