summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/thermal/devfreq_cooling.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c
index 659c0143c9f0..afcebadbad24 100644
--- a/drivers/thermal/devfreq_cooling.c
+++ b/drivers/thermal/devfreq_cooling.c
@@ -227,20 +227,39 @@ static inline unsigned long get_total_power(struct devfreq_cooling_device *dfc,
voltage);
}
+static void _normalize_load(struct devfreq_dev_status *status)
+{
+ if (status->total_time > 0xfffff) {
+ status->total_time >>= 10;
+ status->busy_time >>= 10;
+ }
+
+ status->busy_time <<= 10;
+ status->busy_time /= status->total_time ? : 1;
+
+ status->busy_time = status->busy_time ? : 1;
+ status->total_time = 1024;
+}
static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev,
u32 *power)
{
struct devfreq_cooling_device *dfc = cdev->devdata;
struct devfreq *df = dfc->devfreq;
- struct devfreq_dev_status *status = &df->last_status;
+ struct devfreq_dev_status status;
unsigned long state;
- unsigned long freq = status->current_frequency;
+ unsigned long freq;
unsigned long voltage;
u32 dyn_power = 0;
u32 static_power = 0;
int res;
+ mutex_lock(&df->lock);
+ status = df->last_status;
+ mutex_unlock(&df->lock);
+
+ freq = status.current_frequency;
+
state = freq_get_state(dfc, freq);
if (state == THERMAL_CSTATE_INVALID) {
res = -EAGAIN;
@@ -268,16 +287,18 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd
} else {
dyn_power = dfc->power_table[state];
+ _normalize_load(&status);
+
/* Scale dynamic power for utilization */
- dyn_power *= status->busy_time;
- dyn_power /= status->total_time;
+ dyn_power *= status.busy_time;
+ dyn_power >>= 10;
/* Get static power */
static_power = get_static_power(dfc, freq);
*power = dyn_power + static_power;
}
- trace_thermal_power_devfreq_get_power(cdev, status, freq, *power);
+ trace_thermal_power_devfreq_get_power(cdev, &status, freq, *power);
return 0;
fail:
@@ -309,14 +330,19 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
{
struct devfreq_cooling_device *dfc = cdev->devdata;
struct devfreq *df = dfc->devfreq;
- struct devfreq_dev_status *status = &df->last_status;
- unsigned long freq = status->current_frequency;
- unsigned long busy_time;
+ struct devfreq_dev_status status;
+ unsigned long freq;
s32 dyn_power;
u32 static_power;
s32 est_power;
int i;
+ mutex_lock(&df->lock);
+ status = df->last_status;
+ mutex_unlock(&df->lock);
+
+ freq = status.current_frequency;
+
if (dfc->power_ops->get_real_power) {
/* Scale for resource utilization */
est_power = power * dfc->res_util;
@@ -328,8 +354,9 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
dyn_power = dyn_power > 0 ? dyn_power : 0;
/* Scale dynamic power for utilization */
- busy_time = status->busy_time ?: 1;
- est_power = (dyn_power * status->total_time) / busy_time;
+ _normalize_load(&status);
+ dyn_power <<= 10;
+ est_power = dyn_power / status.busy_time;
}
/*