aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index f8e9ee9f713..74f56093d2f 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -21,7 +21,7 @@
#include <linux/cpufreq.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/mutex.h>
+#include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/sched/rt.h>
#include <linux/tick.h>
@@ -29,7 +29,6 @@
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/kthread.h>
-#include <linux/mutex.h>
#include <linux/slab.h>
#include <asm/cputime.h>
@@ -52,6 +51,7 @@ struct cpufreq_interactive_cpuinfo {
unsigned int floor_freq;
u64 floor_validate_time;
u64 hispeed_validate_time;
+ struct rw_semaphore enable_sem;
int governor_enabled;
};
@@ -279,8 +279,8 @@ static void cpufreq_interactive_timer(unsigned long data)
unsigned long flags;
bool boosted;
- smp_rmb();
-
+ if (!down_read_trylock(&pcpu->enable_sem))
+ return;
if (!pcpu->governor_enabled)
goto exit;
@@ -387,6 +387,7 @@ rearm:
cpufreq_interactive_timer_resched(pcpu);
exit:
+ up_read(&pcpu->enable_sem);
return;
}
@@ -396,8 +397,12 @@ static void cpufreq_interactive_idle_start(void)
&per_cpu(cpuinfo, smp_processor_id());
int pending;
- if (!pcpu->governor_enabled)
+ if (!down_read_trylock(&pcpu->enable_sem))
+ return;
+ if (!pcpu->governor_enabled) {
+ up_read(&pcpu->enable_sem);
return;
+ }
pending = timer_pending(&pcpu->cpu_timer);
@@ -414,6 +419,7 @@ static void cpufreq_interactive_idle_start(void)
cpufreq_interactive_timer_resched(pcpu);
}
+ up_read(&pcpu->enable_sem);
}
static void cpufreq_interactive_idle_end(void)
@@ -421,8 +427,12 @@ static void cpufreq_interactive_idle_end(void)
struct cpufreq_interactive_cpuinfo *pcpu =
&per_cpu(cpuinfo, smp_processor_id());
- if (!pcpu->governor_enabled)
+ if (!down_read_trylock(&pcpu->enable_sem))
+ return;
+ if (!pcpu->governor_enabled) {
+ up_read(&pcpu->enable_sem);
return;
+ }
/* Arm the timer for 1-2 ticks later if not already. */
if (!timer_pending(&pcpu->cpu_timer)) {
@@ -432,6 +442,8 @@ static void cpufreq_interactive_idle_end(void)
del_timer(&pcpu->cpu_slack_timer);
cpufreq_interactive_timer(smp_processor_id());
}
+
+ up_read(&pcpu->enable_sem);
}
static int cpufreq_interactive_speedchange_task(void *data)
@@ -466,10 +478,12 @@ static int cpufreq_interactive_speedchange_task(void *data)
unsigned int max_freq = 0;
pcpu = &per_cpu(cpuinfo, cpu);
- smp_rmb();
-
- if (!pcpu->governor_enabled)
+ if (!down_read_trylock(&pcpu->enable_sem))
+ continue;
+ if (!pcpu->governor_enabled) {
+ up_read(&pcpu->enable_sem);
continue;
+ }
for_each_cpu(j, pcpu->policy->cpus) {
struct cpufreq_interactive_cpuinfo *pjcpu =
@@ -486,6 +500,8 @@ static int cpufreq_interactive_speedchange_task(void *data)
trace_cpufreq_interactive_setspeed(cpu,
pcpu->target_freq,
pcpu->policy->cur);
+
+ up_read(&pcpu->enable_sem);
}
}
@@ -936,10 +952,11 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
case CPUFREQ_GOV_STOP:
for_each_cpu(j, policy->cpus) {
pcpu = &per_cpu(cpuinfo, j);
+ down_write(&pcpu->enable_sem);
pcpu->governor_enabled = 0;
- smp_wmb();
del_timer_sync(&pcpu->cpu_timer);
del_timer_sync(&pcpu->cpu_slack_timer);
+ up_write(&pcpu->enable_sem);
}
if (atomic_dec_return(&active_count) > 0)
@@ -989,6 +1006,7 @@ static int __init cpufreq_interactive_init(void)
init_timer(&pcpu->cpu_slack_timer);
pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer;
spin_lock_init(&pcpu->load_lock);
+ init_rwsem(&pcpu->enable_sem);
}
spin_lock_init(&target_loads_lock);