diff options
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 37 | ||||
-rw-r--r-- | include/linux/cpufreq.h | 10 |
2 files changed, 47 insertions, 0 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index d8d6bc9d1815..d57806a85def 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -353,6 +353,41 @@ void cpufreq_notify_post_transition(struct cpufreq_policy *policy, | |||
353 | } | 353 | } |
354 | EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition); | 354 | EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition); |
355 | 355 | ||
356 | void cpufreq_freq_transition_begin(struct cpufreq_policy *policy, | ||
357 | struct cpufreq_freqs *freqs) | ||
358 | { | ||
359 | wait: | ||
360 | wait_event(policy->transition_wait, !policy->transition_ongoing); | ||
361 | |||
362 | spin_lock(&policy->transition_lock); | ||
363 | |||
364 | if (unlikely(policy->transition_ongoing)) { | ||
365 | spin_unlock(&policy->transition_lock); | ||
366 | goto wait; | ||
367 | } | ||
368 | |||
369 | policy->transition_ongoing = true; | ||
370 | |||
371 | spin_unlock(&policy->transition_lock); | ||
372 | |||
373 | cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE); | ||
374 | } | ||
375 | EXPORT_SYMBOL_GPL(cpufreq_freq_transition_begin); | ||
376 | |||
377 | void cpufreq_freq_transition_end(struct cpufreq_policy *policy, | ||
378 | struct cpufreq_freqs *freqs, int transition_failed) | ||
379 | { | ||
380 | if (unlikely(WARN_ON(!policy->transition_ongoing))) | ||
381 | return; | ||
382 | |||
383 | cpufreq_notify_post_transition(policy, freqs, transition_failed); | ||
384 | |||
385 | policy->transition_ongoing = false; | ||
386 | |||
387 | wake_up(&policy->transition_wait); | ||
388 | } | ||
389 | EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end); | ||
390 | |||
356 | 391 | ||
357 | /********************************************************************* | 392 | /********************************************************************* |
358 | * SYSFS INTERFACE * | 393 | * SYSFS INTERFACE * |
@@ -985,6 +1020,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(void) | |||
985 | 1020 | ||
986 | INIT_LIST_HEAD(&policy->policy_list); | 1021 | INIT_LIST_HEAD(&policy->policy_list); |
987 | init_rwsem(&policy->rwsem); | 1022 | init_rwsem(&policy->rwsem); |
1023 | spin_lock_init(&policy->transition_lock); | ||
1024 | init_waitqueue_head(&policy->transition_wait); | ||
988 | 1025 | ||
989 | return policy; | 1026 | return policy; |
990 | 1027 | ||
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 2d2e62c8666a..e33760268a86 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/completion.h> | 16 | #include <linux/completion.h> |
17 | #include <linux/kobject.h> | 17 | #include <linux/kobject.h> |
18 | #include <linux/notifier.h> | 18 | #include <linux/notifier.h> |
19 | #include <linux/spinlock.h> | ||
19 | #include <linux/sysfs.h> | 20 | #include <linux/sysfs.h> |
20 | 21 | ||
21 | /********************************************************************* | 22 | /********************************************************************* |
@@ -104,6 +105,11 @@ struct cpufreq_policy { | |||
104 | * __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); | 105 | * __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); |
105 | */ | 106 | */ |
106 | struct rw_semaphore rwsem; | 107 | struct rw_semaphore rwsem; |
108 | |||
109 | /* Synchronization for frequency transitions */ | ||
110 | bool transition_ongoing; /* Tracks transition status */ | ||
111 | spinlock_t transition_lock; | ||
112 | wait_queue_head_t transition_wait; | ||
107 | }; | 113 | }; |
108 | 114 | ||
109 | /* Only for ACPI */ | 115 | /* Only for ACPI */ |
@@ -337,6 +343,10 @@ void cpufreq_notify_transition(struct cpufreq_policy *policy, | |||
337 | struct cpufreq_freqs *freqs, unsigned int state); | 343 | struct cpufreq_freqs *freqs, unsigned int state); |
338 | void cpufreq_notify_post_transition(struct cpufreq_policy *policy, | 344 | void cpufreq_notify_post_transition(struct cpufreq_policy *policy, |
339 | struct cpufreq_freqs *freqs, int transition_failed); | 345 | struct cpufreq_freqs *freqs, int transition_failed); |
346 | void cpufreq_freq_transition_begin(struct cpufreq_policy *policy, | ||
347 | struct cpufreq_freqs *freqs); | ||
348 | void cpufreq_freq_transition_end(struct cpufreq_policy *policy, | ||
349 | struct cpufreq_freqs *freqs, int transition_failed); | ||
340 | 350 | ||
341 | #else /* CONFIG_CPU_FREQ */ | 351 | #else /* CONFIG_CPU_FREQ */ |
342 | static inline int cpufreq_register_notifier(struct notifier_block *nb, | 352 | static inline int cpufreq_register_notifier(struct notifier_block *nb, |