aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq_conservative.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/cpufreq_conservative.c')
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c43
1 files changed, 18 insertions, 25 deletions
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 7fc58af748b..bdea7e2f94b 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -64,21 +64,20 @@ struct cpu_dbs_info_s {
64 unsigned int requested_freq; 64 unsigned int requested_freq;
65 int cpu; 65 int cpu;
66 unsigned int enable:1; 66 unsigned int enable:1;
67 /*
68 * percpu mutex that serializes governor limit change with
69 * do_dbs_timer invocation. We do not want do_dbs_timer to run
70 * when user is changing the governor or limits.
71 */
72 struct mutex timer_mutex;
67}; 73};
68static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); 74static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
69 75
70static unsigned int dbs_enable; /* number of CPUs using this policy */ 76static unsigned int dbs_enable; /* number of CPUs using this policy */
71 77
72/* 78/*
73 * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug 79 * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
74 * lock and dbs_mutex. cpu_hotplug lock should always be held before 80 * different CPUs. It protects dbs_enable in governor start/stop.
75 * dbs_mutex. If any function that can potentially take cpu_hotplug lock
76 * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then
77 * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock
78 * is recursive for the same process. -Venki
79 * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it
80 * would deadlock with cancel_delayed_work_sync(), which is needed for proper
81 * raceless workqueue teardown.
82 */ 81 */
83static DEFINE_MUTEX(dbs_mutex); 82static DEFINE_MUTEX(dbs_mutex);
84 83
@@ -488,18 +487,12 @@ static void do_dbs_timer(struct work_struct *work)
488 487
489 delay -= jiffies % delay; 488 delay -= jiffies % delay;
490 489
491 if (lock_policy_rwsem_write(cpu) < 0) 490 mutex_lock(&dbs_info->timer_mutex);
492 return;
493
494 if (!dbs_info->enable) {
495 unlock_policy_rwsem_write(cpu);
496 return;
497 }
498 491
499 dbs_check_cpu(dbs_info); 492 dbs_check_cpu(dbs_info);
500 493
501 queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay); 494 queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay);
502 unlock_policy_rwsem_write(cpu); 495 mutex_unlock(&dbs_info->timer_mutex);
503} 496}
504 497
505static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) 498static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
@@ -535,9 +528,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
535 if ((!cpu_online(cpu)) || (!policy->cur)) 528 if ((!cpu_online(cpu)) || (!policy->cur))
536 return -EINVAL; 529 return -EINVAL;
537 530
538 if (this_dbs_info->enable) /* Already enabled */
539 break;
540
541 mutex_lock(&dbs_mutex); 531 mutex_lock(&dbs_mutex);
542 532
543 rc = sysfs_create_group(&policy->kobj, &dbs_attr_group); 533 rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
@@ -561,6 +551,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
561 this_dbs_info->down_skip = 0; 551 this_dbs_info->down_skip = 0;
562 this_dbs_info->requested_freq = policy->cur; 552 this_dbs_info->requested_freq = policy->cur;
563 553
554 mutex_init(&this_dbs_info->timer_mutex);
564 dbs_enable++; 555 dbs_enable++;
565 /* 556 /*
566 * Start the timerschedule work, when this governor 557 * Start the timerschedule work, when this governor
@@ -590,17 +581,19 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
590 &dbs_cpufreq_notifier_block, 581 &dbs_cpufreq_notifier_block,
591 CPUFREQ_TRANSITION_NOTIFIER); 582 CPUFREQ_TRANSITION_NOTIFIER);
592 } 583 }
593 dbs_timer_init(this_dbs_info);
594
595 mutex_unlock(&dbs_mutex); 584 mutex_unlock(&dbs_mutex);
596 585
586 dbs_timer_init(this_dbs_info);
587
597 break; 588 break;
598 589
599 case CPUFREQ_GOV_STOP: 590 case CPUFREQ_GOV_STOP:
600 mutex_lock(&dbs_mutex);
601 dbs_timer_exit(this_dbs_info); 591 dbs_timer_exit(this_dbs_info);
592
593 mutex_lock(&dbs_mutex);
602 sysfs_remove_group(&policy->kobj, &dbs_attr_group); 594 sysfs_remove_group(&policy->kobj, &dbs_attr_group);
603 dbs_enable--; 595 dbs_enable--;
596 mutex_destroy(&this_dbs_info->timer_mutex);
604 597
605 /* 598 /*
606 * Stop the timerschedule work, when this governor 599 * Stop the timerschedule work, when this governor
@@ -616,7 +609,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
616 break; 609 break;
617 610
618 case CPUFREQ_GOV_LIMITS: 611 case CPUFREQ_GOV_LIMITS:
619 mutex_lock(&dbs_mutex); 612 mutex_lock(&this_dbs_info->timer_mutex);
620 if (policy->max < this_dbs_info->cur_policy->cur) 613 if (policy->max < this_dbs_info->cur_policy->cur)
621 __cpufreq_driver_target( 614 __cpufreq_driver_target(
622 this_dbs_info->cur_policy, 615 this_dbs_info->cur_policy,
@@ -625,7 +618,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
625 __cpufreq_driver_target( 618 __cpufreq_driver_target(
626 this_dbs_info->cur_policy, 619 this_dbs_info->cur_policy,
627 policy->min, CPUFREQ_RELATION_L); 620 policy->min, CPUFREQ_RELATION_L);
628 mutex_unlock(&dbs_mutex); 621 mutex_unlock(&this_dbs_info->timer_mutex);
629 622
630 break; 623 break;
631 } 624 }