THERMALD: update (and fix) thermald daemon
/drivers/thermal/msm_thermal.c
blob:944e6a3bcff0d1996bb7de1ba82ad197e83d010e -> blob:de69ebac30d545c60ed7bc2d5ad0257785739c53
--- drivers/thermal/msm_thermal.c
+++ drivers/thermal/msm_thermal.c
@@ -19,75 +19,23 @@
#include <linux/msm_tsens.h>
#include <linux/workqueue.h>
#include <linux/cpu.h>
-#include <linux/reboot.h>
-#define DEF_TEMP_SENSOR0 0
-#define DEF_TEMP_SENSOR1 1
-
-//shutdown temp
-#define DEF_SHUTDOWNTEMP 80
-
-//max thermal limit
-#define DEF_ALLOWED_MAX_HIGH 75
-#define DEF_ALLOWED_MAX_FREQ 384000
-
-//mid thermal limit
-#define DEF_ALLOWED_MID_HIGH 72
-#define DEF_ALLOWED_MID_FREQ 810000
-
-//low thermal limit
-#define DEF_ALLOWED_LOW_HIGH 70
-#define DEF_ALLOWED_LOW_FREQ 1350000
-
-//Sampling interval
-#define DEF_THERMAL_CHECK_MS 100
-
-static DEFINE_MUTEX(emergency_shutdown_mutex);
+#define DEF_TEMP_SENSOR 0
+#define DEF_THERMAL_CHECK_MS 1000
+#define DEF_ALLOWED_MAX_HIGH 60
+#define DEF_ALLOWED_MAX_FREQ 918000
static int enabled;
-
-//Throttling indicator, 0=not throttled, 1=low, 2=mid, 3=max
-static int thermal_throttled = 0;
-
-//Save the cpu max freq before throttling
-static int pre_throttled_max = 0;
+static int allowed_max_high = DEF_ALLOWED_MAX_HIGH;
+static int allowed_max_low = (DEF_ALLOWED_MAX_HIGH - 10);
+static int allowed_max_freq = DEF_ALLOWED_MAX_FREQ;
+static int check_interval_ms = DEF_THERMAL_CHECK_MS;
+
+module_param(allowed_max_high, int, 0);
+module_param(allowed_max_freq, int, 0);
+module_param(check_interval_ms, int, 0);
static struct delayed_work check_temp_work;
-static struct workqueue_struct *check_temp_workq;
-
-static struct msm_thermal_tuners {
- unsigned int shutdown_temp;
-
- unsigned int allowed_max_high;
- unsigned int allowed_max_low;
- unsigned int allowed_max_freq;
-
- unsigned int allowed_mid_high;
- unsigned int allowed_mid_low;
- unsigned int allowed_mid_freq;
-
- unsigned int allowed_low_high;
- unsigned int allowed_low_low;
- unsigned int allowed_low_freq;
-
- unsigned int check_interval_ms;
-} msm_thermal_tuners_ins = {
- .shutdown_temp = DEF_SHUTDOWNTEMP,
-
- .allowed_max_high = DEF_ALLOWED_MAX_HIGH,
- .allowed_max_low = (DEF_ALLOWED_MAX_HIGH - 4),
- .allowed_max_freq = DEF_ALLOWED_MAX_FREQ,
-
- .allowed_mid_high = DEF_ALLOWED_MID_HIGH,
- .allowed_mid_low = (DEF_ALLOWED_MID_HIGH - 5),
- .allowed_mid_freq = DEF_ALLOWED_MID_FREQ,
-
- .allowed_low_high = DEF_ALLOWED_LOW_HIGH,
- .allowed_low_low = (DEF_ALLOWED_LOW_HIGH - 6),
- .allowed_low_freq = DEF_ALLOWED_LOW_FREQ,
-
- .check_interval_ms = DEF_THERMAL_CHECK_MS,
-};
static int update_cpu_max_freq(struct cpufreq_policy *cpu_policy,
int cpu, int max_freq)
@@ -99,6 +47,7 @@ static int update_cpu_max_freq(struct cp
cpufreq_verify_within_limits(cpu_policy,
cpu_policy->min, max_freq);
+ if (max_freq > 1512000) max_freq = 1512000;
cpu_policy->user_policy.max = max_freq;
ret = cpufreq_update_policy(cpu);
@@ -112,127 +61,54 @@ static int update_cpu_max_freq(struct cp
static void check_temp(struct work_struct *work)
{
struct cpufreq_policy *cpu_policy = NULL;
- struct tsens_device tsens_dev0;
- struct tsens_device tsens_dev1;
- unsigned long temp0 = 0, temp1 = 0;
+ struct tsens_device tsens_dev;
+ unsigned long temp = 0;
unsigned int max_freq = 0;
- bool update_policy = false;
- int i = 0, cpu = 0;
- int ret0 = 0, ret1 = 0;
-
- tsens_dev0.sensor_num = DEF_TEMP_SENSOR0;
- ret0 = tsens_get_temp(&tsens_dev0, &temp0);
- tsens_dev1.sensor_num = DEF_TEMP_SENSOR1;
- ret1 = tsens_get_temp(&tsens_dev1, &temp1);
- if (ret0 && ret1) {
- pr_err("msm_thermal: FATAL: Unable to read TSENS sensor %d & %d\n",
- tsens_dev0.sensor_num, tsens_dev1.sensor_num);
- goto reschedule;
- }
+ int update_policy = 0;
+ int cpu = 0;
+ int ret = 0;
- if ((max(temp0, temp1)) >= (msm_thermal_tuners_ins.shutdown_temp)) {
- mutex_lock(&emergency_shutdown_mutex);
- pr_warn("################################\n");
- pr_warn("################################\n");
- pr_warn("- %u OVERTEMP! SHUTTING DOWN! -\n", msm_thermal_tuners_ins.shutdown_temp);
- pr_warn("################################\n");
- pr_warn("################################\n");
- /* orderly poweroff tries to power down gracefully
- if it fails it will force it. */
- orderly_poweroff(true);
- for_each_possible_cpu(cpu) {
- update_policy = true;
- max_freq = msm_thermal_tuners_ins.allowed_max_freq;
- thermal_throttled = 3;
- pr_warn("msm_thermal: Emergency throttled CPU%i to %u! temp:%lu\n",
- cpu, msm_thermal_tuners_ins.allowed_max_freq, (max(temp0, temp1)));
- }
- mutex_unlock(&emergency_shutdown_mutex);
+ tsens_dev.sensor_num = DEF_TEMP_SENSOR;
+ ret = tsens_get_temp(&tsens_dev, &temp);
+ if (ret) {
+ pr_debug("msm_thermal: Unable to read TSENS sensor %d\n",
+ tsens_dev.sensor_num);
+ goto reschedule;
}
for_each_possible_cpu(cpu) {
- update_policy = false;
+ update_policy = 0;
cpu_policy = cpufreq_cpu_get(cpu);
if (!cpu_policy) {
pr_debug("msm_thermal: NULL policy on cpu %d\n", cpu);
continue;
}
-
- /* save pre-throttled max freq value */
- if ((thermal_throttled == 0) && (cpu == 0))
- pre_throttled_max = cpu_policy->max;
-
- //low trip point
- if (((max(temp0, temp1)) >= msm_thermal_tuners_ins.allowed_low_high) &&
- ((max(temp0, temp1)) < msm_thermal_tuners_ins.allowed_mid_high) &&
- (thermal_throttled < 1)) {
- update_policy = true;
- max_freq = msm_thermal_tuners_ins.allowed_low_freq;
- if (cpu == (CONFIG_NR_CPUS-1)) {
- thermal_throttled = 1;
- pr_warn("msm_thermal: Thermal Throttled (low)! temp:%lu by:%s\n",
- (max(temp0, temp1)), (temp0>temp1) ? "0" : "1");
- }
- //low clr point
- } else if (((max(temp0, temp1)) < msm_thermal_tuners_ins.allowed_low_low) &&
- (thermal_throttled > 0)) {
- if (pre_throttled_max != 0)
- max_freq = pre_throttled_max;
- else {
- max_freq = 1728000;
- pr_warn("msm_thermal: ERROR! pre_throttled_max=0, falling back to %u\n", max_freq);
- }
- update_policy = true;
- for (i = 1; i < CONFIG_NR_CPUS; i++) {
- if (cpu_online(i))
- continue;
- cpu_up(i);
- }
- if (cpu == (CONFIG_NR_CPUS-1)) {
- thermal_throttled = 0;
- pr_warn("msm_thermal: Low thermal throttle ended! temp:%lu by:%s\n",
- (max(temp0, temp1)), (temp0>temp1) ? "0" : "1");
- }
- //mid trip point
- } else if (((max(temp0, temp1)) >= msm_thermal_tuners_ins.allowed_mid_high) &&
- ((max(temp0, temp1)) < msm_thermal_tuners_ins.allowed_max_high) &&
- (thermal_throttled < 2)) {
- update_policy = true;
- max_freq = msm_thermal_tuners_ins.allowed_mid_freq;
- if (cpu == (CONFIG_NR_CPUS-1)) {
- thermal_throttled = 2;
- pr_warn("msm_thermal: Thermal Throttled (mid)! temp:%lu by:%s\n",
- (max(temp0, temp1)), (temp0>temp1) ? "0" : "1");
- }
- //mid clr point
- } else if (((max(temp0, temp1)) < msm_thermal_tuners_ins.allowed_mid_low) &&
- (thermal_throttled > 1)) {
- max_freq = msm_thermal_tuners_ins.allowed_low_freq;
- update_policy = true;
- if (cpu == (CONFIG_NR_CPUS-1)) {
- thermal_throttled = 1;
- pr_warn("msm_thermal: Mid thermal throttle ended! temp:%lu by:%s\n",
- (max(temp0, temp1)), (temp0>temp1) ? "0" : "1");
- }
- //max trip point
- } else if ((max(temp0, temp1)) >= msm_thermal_tuners_ins.allowed_max_high) {
- update_policy = true;
- max_freq = msm_thermal_tuners_ins.allowed_max_freq;
- if (cpu == (CONFIG_NR_CPUS-1)) {
- thermal_throttled = 3;
- pr_warn("msm_thermal: Thermal Throttled (max)! temp:%lu by:%s\n",
- (max(temp0, temp1)), (temp0>temp1) ? "0" : "1");
- }
- //max clr point
- } else if (((max(temp0, temp1)) < msm_thermal_tuners_ins.allowed_max_low) &&
- (thermal_throttled > 2)) {
- max_freq = msm_thermal_tuners_ins.allowed_mid_freq;
- update_policy = true;
- if (cpu == (CONFIG_NR_CPUS-1)) {
- thermal_throttled = 2;
- pr_warn("msm_thermal: Max thermal throttle ended! temp:%lu by:%s\n",
- (max(temp0, temp1)), (temp0>temp1) ? "0" : "1");
+ if (temp >= allowed_max_high) {
+ if (cpu_policy->max > allowed_max_freq) {
+ update_policy = 1;
+ max_freq = allowed_max_freq;
+ } else {
+ pr_debug("msm_thermal: policy max for cpu %d "
+ "already < allowed_max_freq\n", cpu);
+ }
+ } else if (temp < allowed_max_low) {
+#ifdef CONFIG_SEC_DVFS
+ if (cpufreq_get_dvfs_state() != 1) {
+ if (cpu_policy->max < 1512000) {
+ max_freq = 1512000;
+ update_policy = 1;
+ }
+ } else
+ update_policy = 0;
+#else
+ if (cpu_policy->max < cpu_policy->cpuinfo.max_freq) {
+ max_freq = cpu_policy->cpuinfo.max_freq;
+ update_policy = 1;
+ } else {
+ pr_debug("msm_thermal: policy max for cpu %d "
+ "already at max allowed\n", cpu);
}
+#endif
}
if (update_policy)
@@ -243,9 +119,8 @@ static void check_temp(struct work_struc
reschedule:
if (enabled)
- queue_delayed_work(check_temp_workq, &check_temp_work,
- msecs_to_jiffies(msm_thermal_tuners_ins.check_interval_ms));
- return;
+ schedule_delayed_work(&check_temp_work,
+ msecs_to_jiffies(check_interval_ms));
}
static void disable_msm_thermal(void)
@@ -253,10 +128,6 @@ static void disable_msm_thermal(void)
int cpu = 0;
struct cpufreq_policy *cpu_policy = NULL;
- /* make sure check_temp is no longer running */
- cancel_delayed_work_sync(&check_temp_work);
- flush_scheduled_work();
-
for_each_possible_cpu(cpu) {
cpu_policy = cpufreq_cpu_get(cpu);
if (cpu_policy) {
@@ -292,237 +163,14 @@ static struct kernel_param_ops module_op
module_param_cb(enabled, &module_ops, &enabled, 0644);
MODULE_PARM_DESC(enabled, "enforce thermal limit on cpu");
-/**************************** SYSFS START ****************************/
-struct kobject *msm_thermal_kobject;
-
-#define show_one(file_name, object) \
-static ssize_t show_##file_name \
-(struct kobject *kobj, struct attribute *attr, char *buf) \
-{ \
- return sprintf(buf, "%u\n", msm_thermal_tuners_ins.object); \
-}
-
-show_one(shutdown_temp, shutdown_temp);
-show_one(allowed_max_high, allowed_max_high);
-show_one(allowed_max_low, allowed_max_low);
-show_one(allowed_max_freq, allowed_max_freq);
-show_one(allowed_mid_high, allowed_mid_high);
-show_one(allowed_mid_low, allowed_mid_low);
-show_one(allowed_mid_freq, allowed_mid_freq);
-show_one(allowed_low_high, allowed_low_high);
-show_one(allowed_low_low, allowed_low_low);
-show_one(allowed_low_freq, allowed_low_freq);
-show_one(check_interval_ms, check_interval_ms);
-
-static ssize_t store_shutdown_temp(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.shutdown_temp = input;
-
- return count;
-}
-
-static ssize_t store_allowed_max_high(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.allowed_max_high = input;
-
- return count;
-}
-
-static ssize_t store_allowed_max_low(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.allowed_max_low = input;
-
- return count;
-}
-
-static ssize_t store_allowed_max_freq(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.allowed_max_freq = input;
-
- return count;
-}
-
-static ssize_t store_allowed_mid_high(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.allowed_mid_high = input;
-
- return count;
-}
-
-static ssize_t store_allowed_mid_low(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.allowed_mid_low = input;
-
- return count;
-}
-
-static ssize_t store_allowed_mid_freq(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.allowed_mid_freq = input;
-
- return count;
-}
-
-static ssize_t store_allowed_low_high(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.allowed_low_high = input;
-
- return count;
-}
-
-static ssize_t store_allowed_low_low(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.allowed_low_low = input;
-
- return count;
-}
-
-static ssize_t store_allowed_low_freq(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.allowed_low_freq = input;
-
- return count;
-}
-
-static ssize_t store_check_interval_ms(struct kobject *a, struct attribute *b,
- const char *buf, size_t count)
-{
- unsigned int input;
- int ret;
- ret = sscanf(buf, "%u", &input);
- if (ret != 1)
- return -EINVAL;
-
- msm_thermal_tuners_ins.check_interval_ms = input;
-
- return count;
-}
-
-define_one_global_rw(shutdown_temp);
-define_one_global_rw(allowed_max_high);
-define_one_global_rw(allowed_max_low);
-define_one_global_rw(allowed_max_freq);
-define_one_global_rw(allowed_mid_high);
-define_one_global_rw(allowed_mid_low);
-define_one_global_rw(allowed_mid_freq);
-define_one_global_rw(allowed_low_high);
-define_one_global_rw(allowed_low_low);
-define_one_global_rw(allowed_low_freq);
-define_one_global_rw(check_interval_ms);
-
-static struct attribute *msm_thermal_attributes[] = {
- &shutdown_temp.attr,
- &allowed_max_high.attr,
- &allowed_max_low.attr,
- &allowed_max_freq.attr,
- &allowed_mid_high.attr,
- &allowed_mid_low.attr,
- &allowed_mid_freq.attr,
- &allowed_low_high.attr,
- &allowed_low_low.attr,
- &allowed_low_freq.attr,
- &check_interval_ms.attr,
- NULL
-};
-
-
-static struct attribute_group msm_thermal_attr_group = {
- .attrs = msm_thermal_attributes,
- .name = "conf",
-};
-/**************************** SYSFS END ****************************/
-
static int __init msm_thermal_init(void)
{
- int rc, ret = 0;
+ int ret = 0;
enabled = 1;
- check_temp_workq = alloc_workqueue(
- "msm_thermal", WQ_UNBOUND | WQ_RESCUER, 1);
- if (!check_temp_workq)
- BUG_ON(ENOMEM);
- INIT_DELAYED_WORK(&check_temp_work, check_temp);
- queue_delayed_work(check_temp_workq, &check_temp_work, 0);
-
- msm_thermal_kobject = kobject_create_and_add("msm_thermal", kernel_kobj);
- if (msm_thermal_kobject) {
- rc = sysfs_create_group(msm_thermal_kobject,
- &msm_thermal_attr_group);
- if (rc) {
- pr_warn("msm_thermal: sysfs: ERROR, could not create sysfs group");
- }
- } else
- pr_warn("msm_thermal: sysfs: ERROR, could not create sysfs kobj");
+ INIT_DELAYED_WORK(&check_temp_work, check_temp);
+
+ schedule_delayed_work(&check_temp_work, 0);
return ret;
}