aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/cpufreq.c14
-rw-r--r--include/linux/cpufreq.h1
2 files changed, 15 insertions, 0 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a517da996aaf..bfe82b63875f 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -365,6 +365,18 @@ static void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
365void cpufreq_freq_transition_begin(struct cpufreq_policy *policy, 365void cpufreq_freq_transition_begin(struct cpufreq_policy *policy,
366 struct cpufreq_freqs *freqs) 366 struct cpufreq_freqs *freqs)
367{ 367{
368
369 /*
370 * Catch double invocations of _begin() which lead to self-deadlock.
371 * ASYNC_NOTIFICATION drivers are left out because the cpufreq core
372 * doesn't invoke _begin() on their behalf, and hence the chances of
373 * double invocations are very low. Moreover, there are scenarios
374 * where these checks can emit false-positive warnings in these
375 * drivers; so we avoid that by skipping them altogether.
376 */
377 WARN_ON(!(cpufreq_driver->flags & CPUFREQ_ASYNC_NOTIFICATION)
378 && current == policy->transition_task);
379
368wait: 380wait:
369 wait_event(policy->transition_wait, !policy->transition_ongoing); 381 wait_event(policy->transition_wait, !policy->transition_ongoing);
370 382
@@ -376,6 +388,7 @@ wait:
376 } 388 }
377 389
378 policy->transition_ongoing = true; 390 policy->transition_ongoing = true;
391 policy->transition_task = current;
379 392
380 spin_unlock(&policy->transition_lock); 393 spin_unlock(&policy->transition_lock);
381 394
@@ -392,6 +405,7 @@ void cpufreq_freq_transition_end(struct cpufreq_policy *policy,
392 cpufreq_notify_post_transition(policy, freqs, transition_failed); 405 cpufreq_notify_post_transition(policy, freqs, transition_failed);
393 406
394 policy->transition_ongoing = false; 407 policy->transition_ongoing = false;
408 policy->transition_task = NULL;
395 409
396 wake_up(&policy->transition_wait); 410 wake_up(&policy->transition_wait);
397} 411}
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 77a5fa191502..f3822f836e14 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -110,6 +110,7 @@ struct cpufreq_policy {
110 bool transition_ongoing; /* Tracks transition status */ 110 bool transition_ongoing; /* Tracks transition status */
111 spinlock_t transition_lock; 111 spinlock_t transition_lock;
112 wait_queue_head_t transition_wait; 112 wait_queue_head_t transition_wait;
113 struct task_struct *transition_task; /* Task which is doing the transition */
113}; 114};
114 115
115/* Only for ACPI */ 116/* Only for ACPI */