diff options
Diffstat (limited to 'drivers/cpufreq/cpufreq_conservative.c')
-rw-r--r-- | drivers/cpufreq/cpufreq_conservative.c | 43 |
1 files changed, 18 insertions, 25 deletions
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 7fc58af748b4..bdea7e2f94ba 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 | }; |
68 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); | 74 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); |
69 | 75 | ||
70 | static unsigned int dbs_enable; /* number of CPUs using this policy */ | 76 | static 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 | */ |
83 | static DEFINE_MUTEX(dbs_mutex); | 82 | static 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 | ||
505 | static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) | 498 | static 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 | } |