diff --git a/drivers/power/qcom/msm-core.c b/drivers/power/qcom/msm-core.c index 9c6f1fdd88a4..7cab97fa12ee 100644 --- a/drivers/power/qcom/msm-core.c +++ b/drivers/power/qcom/msm-core.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -50,8 +51,6 @@ #define NUM_OF_CORNERS 10 #define DEFAULT_SCALING_FACTOR 1 -#define SAMPLE_MAX_TIMEOUT_MS 1000 - #define ALLOCATE_2D_ARRAY(type)\ static type **allocate_2d_array_##type(int idx)\ {\ @@ -98,10 +97,11 @@ struct cpu_static_info { }; static DEFINE_MUTEX(policy_update_mutex); -static DEFINE_MUTEX(suspend_update_mutex); +static DEFINE_MUTEX(kthread_update_mutex); static DEFINE_SPINLOCK(update_lock); static struct delayed_work sampling_work; -static struct workqueue_struct *msm_core_wq; +static struct completion sampling_completion; +static struct task_struct *sampling_task; static int low_hyst_temp; static int high_hyst_temp; static struct platform_device *msm_core_pdev; @@ -124,8 +124,6 @@ static int max_throttling_temp = 80; /* in C */ module_param_named(throttling_temp, max_throttling_temp, int, S_IRUGO | S_IWUSR | S_IWGRP); -static unsigned long forced_timeout; - /* * Cannot be called from an interrupt context */ @@ -179,23 +177,9 @@ static void set_threshold(struct cpu_activity_info *cpu_node) &cpu_node->low_threshold); } -static inline bool should_run_resampling(void) -{ - if (!mutex_is_locked(&suspend_update_mutex) && !in_suspend) - return true; - else - return false; -} - -static inline void schedule_sampling(void) +static void samplequeue_handle(struct work_struct *work) { - if (should_run_resampling()) { - forced_timeout = jiffies + msecs_to_jiffies(SAMPLE_MAX_TIMEOUT_MS); - if (delayed_work_pending(&sampling_work)) - cancel_delayed_work(&sampling_work); - queue_delayed_work(msm_core_wq, &sampling_work, - msecs_to_jiffies(0)); - } + complete(&sampling_completion); } /* May be called from an interrupt context */ @@ -210,10 +194,7 @@ static void core_temp_notify(enum thermal_trip_type type, cpu_node->temp = temp / scaling_factor; - /* Schedule resampling if the forced timeout is over */ - if (time_after(jiffies, forced_timeout)) { - schedule_sampling(); - } + complete(&sampling_completion); } static void repopulate_stats(int cpu) @@ -243,7 +224,7 @@ static void repopulate_stats(int cpu) void trigger_cpu_pwr_stats_calc(void) { - int cpu, rc; + int cpu; static long prev_temp[NR_CPUS]; struct cpu_activity_info *cpu_node; long temp; @@ -259,12 +240,7 @@ void trigger_cpu_pwr_stats_calc(void) continue; if (cpu_node->temp == prev_temp[cpu]) { - rc = sensor_get_temp(cpu_node->sensor_id, &temp); - if (rc) { - pr_err("msm-core: The sensor reported invalid data!"); - temp = DEFAULT_TEMP; - } - + sensor_get_temp(cpu_node->sensor_id, &temp); cpu_node->temp = temp / scaling_factor; } @@ -324,41 +300,43 @@ static void update_related_freq_table(struct cpufreq_policy *policy) } } -static inline void do_sampling(void) +static __ref int do_sampling(void *data) { int cpu; struct cpu_activity_info *cpu_node; static int prev_temp[NR_CPUS]; - if (!should_run_resampling()) - return; + while (!kthread_should_stop()) { + wait_for_completion_interruptible(&sampling_completion); + cancel_delayed_work(&sampling_work); - mutex_lock(&suspend_update_mutex); - trigger_cpu_pwr_stats_calc(); + mutex_lock(&kthread_update_mutex); + if (in_suspend) + goto unlock; - for_each_online_cpu(cpu) { - cpu_node = &activity[cpu]; - if (prev_temp[cpu] != cpu_node->temp) { - prev_temp[cpu] = cpu_node->temp; - set_threshold(cpu_node); - trace_temp_threshold(cpu, cpu_node->temp, - cpu_node->hi_threshold.temp / - scaling_factor, - cpu_node->low_threshold.temp / - scaling_factor); + trigger_cpu_pwr_stats_calc(); + + for_each_online_cpu(cpu) { + cpu_node = &activity[cpu]; + if (prev_temp[cpu] != cpu_node->temp) { + prev_temp[cpu] = cpu_node->temp; + set_threshold(cpu_node); + trace_temp_threshold(cpu, cpu_node->temp, + cpu_node->hi_threshold.temp / + scaling_factor, + cpu_node->low_threshold.temp / + scaling_factor); + } } - } - mutex_unlock(&suspend_update_mutex); -} + if (!poll_ms) + goto unlock; -static void samplequeue_handle(struct work_struct *work) -{ - /* Prevent race with core_temp notification by using SAMPLE_MAX_TIMEOUT_MS */ - forced_timeout = jiffies + msecs_to_jiffies(SAMPLE_MAX_TIMEOUT_MS); - do_sampling(); - forced_timeout = jiffies + msecs_to_jiffies(poll_ms / 2); - queue_delayed_work(msm_core_wq, &sampling_work, - msecs_to_jiffies(poll_ms)); + schedule_delayed_work(&sampling_work, + msecs_to_jiffies(poll_ms)); +unlock: + mutex_unlock(&kthread_update_mutex); + } + return 0; } static void clear_static_power(struct cpu_static_info *sp) @@ -615,10 +593,13 @@ static int msm_core_stats_init(struct device *dev, int cpu) static int msm_core_task_init(struct device *dev) { - msm_core_wq = alloc_workqueue("msm-core_wq", WQ_HIGHPRI, 0); - if (!msm_core_wq) - return -EFAULT; - + init_completion(&sampling_completion); + sampling_task = kthread_run(do_sampling, NULL, "msm-core:sampling"); + if (IS_ERR(sampling_task)) { + pr_err("Failed to create do_sampling err: %ld\n", + PTR_ERR(sampling_task)); + return PTR_ERR(sampling_task); + } return 0; } @@ -841,22 +822,22 @@ static int system_suspend_handler(struct notifier_block *nb, { int cpu; - mutex_lock(&suspend_update_mutex); + mutex_lock(&kthread_update_mutex); switch (val) { case PM_POST_HIBERNATION: case PM_POST_SUSPEND: case PM_POST_RESTORE: /* - * Schedule resampling to read temperature and repopulate + * Set completion event to read temperature and repopulate * stats */ in_suspend = 0; - schedule_sampling(); + complete(&sampling_completion); break; case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: /* - * cancel work to be able to restart immediately + * cancel delayed work to be able to restart immediately * after system resume */ in_suspend = 1; @@ -879,7 +860,7 @@ static int system_suspend_handler(struct notifier_block *nb, default: break; } - mutex_unlock(&suspend_update_mutex); + mutex_unlock(&kthread_update_mutex); return NOTIFY_OK; } @@ -1090,7 +1071,7 @@ static int msm_core_dev_probe(struct platform_device *pdev) if (ret) goto failed; - INIT_DELAYED_WORK(&sampling_work, samplequeue_handle); + INIT_DEFERRABLE_WORK(&sampling_work, samplequeue_handle); ret = msm_core_task_init(&pdev->dev); if (ret) goto failed; @@ -1098,8 +1079,7 @@ static int msm_core_dev_probe(struct platform_device *pdev) for_each_possible_cpu(cpu) set_threshold(&activity[cpu]); - schedule_sampling(); - + schedule_delayed_work(&sampling_work, msecs_to_jiffies(0)); cpufreq_register_notifier(&cpu_policy, CPUFREQ_POLICY_NOTIFIER); pm_notifier(system_suspend_handler, 0); return 0;