diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-28 18:08:16 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-04-28 18:08:16 -0400 |
commit | 1c3d85dd4e21a405e8de54131a5f759f9a0115b7 (patch) | |
tree | 5f99d5cb69d50c5f46d1ee3fa7c3dfec705e20d5 /drivers/cpufreq/cpufreq.c | |
parent | 45c009a9a447655aecbdb06c86126f05d0272171 (diff) |
cpufreq: Revert incorrect commit 5800043
Commit 5800043 (cpufreq: convert cpufreq_driver to using RCU) causes
the following call trace to be spit on boot:
BUG: sleeping function called from invalid context at /scratch/rafael/work/linux-pm/mm/slab.c:3179
in_atomic(): 0, irqs_disabled(): 0, pid: 292, name: systemd-udevd
2 locks held by systemd-udevd/292:
#0: (subsys mutex){+.+.+.}, at: [<ffffffff8146851a>] subsys_interface_register+0x4a/0xe0
#1: (rcu_read_lock){.+.+.+}, at: [<ffffffff81538210>] cpufreq_add_dev_interface+0x60/0x5e0
Pid: 292, comm: systemd-udevd Not tainted 3.9.0-rc8+ #323
Call Trace:
[<ffffffff81072c90>] __might_sleep+0x140/0x1f0
[<ffffffff811581c2>] kmem_cache_alloc+0x42/0x2b0
[<ffffffff811e7179>] sysfs_new_dirent+0x59/0x130
[<ffffffff811e63cb>] sysfs_add_file_mode+0x6b/0x110
[<ffffffff81538210>] ? cpufreq_add_dev_interface+0x60/0x5e0
[<ffffffff810a3254>] ? __lock_is_held+0x54/0x80
[<ffffffff811e647d>] sysfs_add_file+0xd/0x10
[<ffffffff811e6541>] sysfs_create_file+0x21/0x30
[<ffffffff81538280>] cpufreq_add_dev_interface+0xd0/0x5e0
[<ffffffff81538210>] ? cpufreq_add_dev_interface+0x60/0x5e0
[<ffffffffa000337f>] ? acpi_processor_get_platform_limit+0x32/0xbb [processor]
[<ffffffffa022f540>] ? do_drv_write+0x70/0x70 [acpi_cpufreq]
[<ffffffff810a3254>] ? __lock_is_held+0x54/0x80
[<ffffffff8106c97e>] ? up_read+0x1e/0x40
[<ffffffff8106e632>] ? __blocking_notifier_call_chain+0x72/0xc0
[<ffffffff81538dbd>] cpufreq_add_dev+0x62d/0xae0
[<ffffffff815389b8>] ? cpufreq_add_dev+0x228/0xae0
[<ffffffff81468569>] subsys_interface_register+0x99/0xe0
[<ffffffffa014d000>] ? 0xffffffffa014cfff
[<ffffffff81535d5d>] cpufreq_register_driver+0x9d/0x200
[<ffffffffa014d000>] ? 0xffffffffa014cfff
[<ffffffffa014d0e9>] acpi_cpufreq_init+0xe9/0x1000 [acpi_cpufreq]
[<ffffffff810002fa>] do_one_initcall+0x11a/0x170
[<ffffffff810b4b87>] load_module+0x1cf7/0x2920
[<ffffffff81322580>] ? ddebug_proc_open+0xb0/0xb0
[<ffffffff816baee0>] ? retint_restore_args+0xe/0xe
[<ffffffff810b5887>] sys_init_module+0xd7/0x120
[<ffffffff816bb6d2>] system_call_fastpath+0x16/0x1b
which is quite obvious, because that commit put (multiple instances
of) sysfs_create_file() under rcu_read_lock()/rcu_read_unlock(),
although sysfs_create_file() may cause memory to be allocated with
GFP_KERNEL and that may sleep, which is not permitted in RCU read
critical section.
Revert the buggy commit altogether along with some changes on top
of it.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/cpufreq/cpufreq.c')
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 283 |
1 files changed, 69 insertions, 214 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a6f65954b0ab..1b8a48eaf90f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -39,7 +39,7 @@ | |||
39 | * level driver of CPUFreq support, and its spinlock. This lock | 39 | * level driver of CPUFreq support, and its spinlock. This lock |
40 | * also protects the cpufreq_cpu_data array. | 40 | * also protects the cpufreq_cpu_data array. |
41 | */ | 41 | */ |
42 | static struct cpufreq_driver __rcu *cpufreq_driver; | 42 | static struct cpufreq_driver *cpufreq_driver; |
43 | static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); | 43 | static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); |
44 | #ifdef CONFIG_HOTPLUG_CPU | 44 | #ifdef CONFIG_HOTPLUG_CPU |
45 | /* This one keeps track of the previously set governor of a removed CPU */ | 45 | /* This one keeps track of the previously set governor of a removed CPU */ |
@@ -130,34 +130,26 @@ static DEFINE_MUTEX(cpufreq_governor_mutex); | |||
130 | 130 | ||
131 | bool have_governor_per_policy(void) | 131 | bool have_governor_per_policy(void) |
132 | { | 132 | { |
133 | bool have_governor_per_policy; | 133 | return cpufreq_driver->have_governor_per_policy; |
134 | rcu_read_lock(); | ||
135 | have_governor_per_policy = | ||
136 | rcu_dereference(cpufreq_driver)->have_governor_per_policy; | ||
137 | rcu_read_unlock(); | ||
138 | return have_governor_per_policy; | ||
139 | } | 134 | } |
140 | 135 | ||
141 | static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) | 136 | static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) |
142 | { | 137 | { |
143 | struct cpufreq_policy *data; | 138 | struct cpufreq_policy *data; |
144 | struct cpufreq_driver *driver; | ||
145 | unsigned long flags; | 139 | unsigned long flags; |
146 | 140 | ||
147 | if (cpu >= nr_cpu_ids) | 141 | if (cpu >= nr_cpu_ids) |
148 | goto err_out; | 142 | goto err_out; |
149 | 143 | ||
150 | /* get the cpufreq driver */ | 144 | /* get the cpufreq driver */ |
151 | rcu_read_lock(); | 145 | read_lock_irqsave(&cpufreq_driver_lock, flags); |
152 | driver = rcu_dereference(cpufreq_driver); | ||
153 | 146 | ||
154 | if (!driver) | 147 | if (!cpufreq_driver) |
155 | goto err_out_unlock; | 148 | goto err_out_unlock; |
156 | 149 | ||
157 | if (!try_module_get(driver->owner)) | 150 | if (!try_module_get(cpufreq_driver->owner)) |
158 | goto err_out_unlock; | 151 | goto err_out_unlock; |
159 | 152 | ||
160 | read_lock_irqsave(&cpufreq_driver_lock, flags); | ||
161 | 153 | ||
162 | /* get the CPU */ | 154 | /* get the CPU */ |
163 | data = per_cpu(cpufreq_cpu_data, cpu); | 155 | data = per_cpu(cpufreq_cpu_data, cpu); |
@@ -169,14 +161,12 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) | |||
169 | goto err_out_put_module; | 161 | goto err_out_put_module; |
170 | 162 | ||
171 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | 163 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
172 | rcu_read_unlock(); | ||
173 | return data; | 164 | return data; |
174 | 165 | ||
175 | err_out_put_module: | 166 | err_out_put_module: |
176 | module_put(driver->owner); | 167 | module_put(cpufreq_driver->owner); |
177 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); | ||
178 | err_out_unlock: | 168 | err_out_unlock: |
179 | rcu_read_unlock(); | 169 | read_unlock_irqrestore(&cpufreq_driver_lock, flags); |
180 | err_out: | 170 | err_out: |
181 | return NULL; | 171 | return NULL; |
182 | } | 172 | } |
@@ -199,9 +189,7 @@ static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs) | |||
199 | { | 189 | { |
200 | if (!sysfs) | 190 | if (!sysfs) |
201 | kobject_put(&data->kobj); | 191 | kobject_put(&data->kobj); |
202 | rcu_read_lock(); | 192 | module_put(cpufreq_driver->owner); |
203 | module_put(rcu_dereference(cpufreq_driver)->owner); | ||
204 | rcu_read_unlock(); | ||
205 | } | 193 | } |
206 | 194 | ||
207 | void cpufreq_cpu_put(struct cpufreq_policy *data) | 195 | void cpufreq_cpu_put(struct cpufreq_policy *data) |
@@ -269,9 +257,7 @@ void __cpufreq_notify_transition(struct cpufreq_policy *policy, | |||
269 | if (cpufreq_disabled()) | 257 | if (cpufreq_disabled()) |
270 | return; | 258 | return; |
271 | 259 | ||
272 | rcu_read_lock(); | 260 | freqs->flags = cpufreq_driver->flags; |
273 | freqs->flags = rcu_dereference(cpufreq_driver)->flags; | ||
274 | rcu_read_unlock(); | ||
275 | pr_debug("notification %u of frequency transition to %u kHz\n", | 261 | pr_debug("notification %u of frequency transition to %u kHz\n", |
276 | state, freqs->new); | 262 | state, freqs->new); |
277 | 263 | ||
@@ -282,7 +268,7 @@ void __cpufreq_notify_transition(struct cpufreq_policy *policy, | |||
282 | * which is not equal to what the cpufreq core thinks is | 268 | * which is not equal to what the cpufreq core thinks is |
283 | * "old frequency". | 269 | * "old frequency". |
284 | */ | 270 | */ |
285 | if (!(freqs->flags & CPUFREQ_CONST_LOOPS)) { | 271 | if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { |
286 | if ((policy) && (policy->cpu == freqs->cpu) && | 272 | if ((policy) && (policy->cpu == freqs->cpu) && |
287 | (policy->cur) && (policy->cur != freqs->old)) { | 273 | (policy->cur) && (policy->cur != freqs->old)) { |
288 | pr_debug("Warning: CPU frequency is" | 274 | pr_debug("Warning: CPU frequency is" |
@@ -348,21 +334,11 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, | |||
348 | struct cpufreq_governor **governor) | 334 | struct cpufreq_governor **governor) |
349 | { | 335 | { |
350 | int err = -EINVAL; | 336 | int err = -EINVAL; |
351 | struct cpufreq_driver *driver; | 337 | |
352 | bool has_setpolicy; | 338 | if (!cpufreq_driver) |
353 | bool has_target; | ||
354 | |||
355 | rcu_read_lock(); | ||
356 | driver = rcu_dereference(cpufreq_driver); | ||
357 | if (!driver) { | ||
358 | rcu_read_unlock(); | ||
359 | goto out; | 339 | goto out; |
360 | } | ||
361 | has_setpolicy = driver->setpolicy ? true : false; | ||
362 | has_target = driver->target ? true : false; | ||
363 | rcu_read_unlock(); | ||
364 | 340 | ||
365 | if (has_setpolicy) { | 341 | if (cpufreq_driver->setpolicy) { |
366 | if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { | 342 | if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { |
367 | *policy = CPUFREQ_POLICY_PERFORMANCE; | 343 | *policy = CPUFREQ_POLICY_PERFORMANCE; |
368 | err = 0; | 344 | err = 0; |
@@ -371,7 +347,7 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, | |||
371 | *policy = CPUFREQ_POLICY_POWERSAVE; | 347 | *policy = CPUFREQ_POLICY_POWERSAVE; |
372 | err = 0; | 348 | err = 0; |
373 | } | 349 | } |
374 | } else if (has_target) { | 350 | } else if (cpufreq_driver->target) { |
375 | struct cpufreq_governor *t; | 351 | struct cpufreq_governor *t; |
376 | 352 | ||
377 | mutex_lock(&cpufreq_governor_mutex); | 353 | mutex_lock(&cpufreq_governor_mutex); |
@@ -522,12 +498,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy, | |||
522 | */ | 498 | */ |
523 | static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf) | 499 | static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf) |
524 | { | 500 | { |
525 | ssize_t size; | 501 | return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name); |
526 | rcu_read_lock(); | ||
527 | size = scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", | ||
528 | rcu_dereference(cpufreq_driver)->name); | ||
529 | rcu_read_unlock(); | ||
530 | return size; | ||
531 | } | 502 | } |
532 | 503 | ||
533 | /** | 504 | /** |
@@ -539,13 +510,10 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, | |||
539 | ssize_t i = 0; | 510 | ssize_t i = 0; |
540 | struct cpufreq_governor *t; | 511 | struct cpufreq_governor *t; |
541 | 512 | ||
542 | rcu_read_lock(); | 513 | if (!cpufreq_driver->target) { |
543 | if (!rcu_dereference(cpufreq_driver)->target) { | ||
544 | rcu_read_unlock(); | ||
545 | i += sprintf(buf, "performance powersave"); | 514 | i += sprintf(buf, "performance powersave"); |
546 | goto out; | 515 | goto out; |
547 | } | 516 | } |
548 | rcu_read_unlock(); | ||
549 | 517 | ||
550 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { | 518 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { |
551 | if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) | 519 | if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) |
@@ -623,15 +591,9 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) | |||
623 | static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) | 591 | static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) |
624 | { | 592 | { |
625 | unsigned int limit; | 593 | unsigned int limit; |
626 | int (*bios_limit)(int cpu, unsigned int *limit); | ||
627 | int ret; | 594 | int ret; |
628 | 595 | if (cpufreq_driver->bios_limit) { | |
629 | rcu_read_lock(); | 596 | ret = cpufreq_driver->bios_limit(policy->cpu, &limit); |
630 | bios_limit = rcu_dereference(cpufreq_driver)->bios_limit; | ||
631 | rcu_read_unlock(); | ||
632 | |||
633 | if (bios_limit) { | ||
634 | ret = bios_limit(policy->cpu, &limit); | ||
635 | if (!ret) | 597 | if (!ret) |
636 | return sprintf(buf, "%u\n", limit); | 598 | return sprintf(buf, "%u\n", limit); |
637 | } | 599 | } |
@@ -774,7 +736,6 @@ static int cpufreq_add_dev_interface(unsigned int cpu, | |||
774 | { | 736 | { |
775 | struct cpufreq_policy new_policy; | 737 | struct cpufreq_policy new_policy; |
776 | struct freq_attr **drv_attr; | 738 | struct freq_attr **drv_attr; |
777 | struct cpufreq_driver *driver; | ||
778 | unsigned long flags; | 739 | unsigned long flags; |
779 | int ret = 0; | 740 | int ret = 0; |
780 | unsigned int j; | 741 | unsigned int j; |
@@ -786,31 +747,28 @@ static int cpufreq_add_dev_interface(unsigned int cpu, | |||
786 | return ret; | 747 | return ret; |
787 | 748 | ||
788 | /* set up files for this cpu device */ | 749 | /* set up files for this cpu device */ |
789 | rcu_read_lock(); | 750 | drv_attr = cpufreq_driver->attr; |
790 | driver = rcu_dereference(cpufreq_driver); | ||
791 | drv_attr = driver->attr; | ||
792 | while ((drv_attr) && (*drv_attr)) { | 751 | while ((drv_attr) && (*drv_attr)) { |
793 | ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); | 752 | ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); |
794 | if (ret) | 753 | if (ret) |
795 | goto err_out_unlock; | 754 | goto err_out_kobj_put; |
796 | drv_attr++; | 755 | drv_attr++; |
797 | } | 756 | } |
798 | if (driver->get) { | 757 | if (cpufreq_driver->get) { |
799 | ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); | 758 | ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); |
800 | if (ret) | 759 | if (ret) |
801 | goto err_out_unlock; | 760 | goto err_out_kobj_put; |
802 | } | 761 | } |
803 | if (driver->target) { | 762 | if (cpufreq_driver->target) { |
804 | ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); | 763 | ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); |
805 | if (ret) | 764 | if (ret) |
806 | goto err_out_unlock; | 765 | goto err_out_kobj_put; |
807 | } | 766 | } |
808 | if (driver->bios_limit) { | 767 | if (cpufreq_driver->bios_limit) { |
809 | ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); | 768 | ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); |
810 | if (ret) | 769 | if (ret) |
811 | goto err_out_unlock; | 770 | goto err_out_kobj_put; |
812 | } | 771 | } |
813 | rcu_read_unlock(); | ||
814 | 772 | ||
815 | write_lock_irqsave(&cpufreq_driver_lock, flags); | 773 | write_lock_irqsave(&cpufreq_driver_lock, flags); |
816 | for_each_cpu(j, policy->cpus) { | 774 | for_each_cpu(j, policy->cpus) { |
@@ -833,20 +791,12 @@ static int cpufreq_add_dev_interface(unsigned int cpu, | |||
833 | policy->user_policy.governor = policy->governor; | 791 | policy->user_policy.governor = policy->governor; |
834 | 792 | ||
835 | if (ret) { | 793 | if (ret) { |
836 | int (*exit)(struct cpufreq_policy *policy); | ||
837 | |||
838 | pr_debug("setting policy failed\n"); | 794 | pr_debug("setting policy failed\n"); |
839 | rcu_read_lock(); | 795 | if (cpufreq_driver->exit) |
840 | exit = rcu_dereference(cpufreq_driver)->exit; | 796 | cpufreq_driver->exit(policy); |
841 | rcu_read_unlock(); | ||
842 | if (exit) | ||
843 | exit(policy); | ||
844 | |||
845 | } | 797 | } |
846 | return ret; | 798 | return ret; |
847 | 799 | ||
848 | err_out_unlock: | ||
849 | rcu_read_unlock(); | ||
850 | err_out_kobj_put: | 800 | err_out_kobj_put: |
851 | kobject_put(&policy->kobj); | 801 | kobject_put(&policy->kobj); |
852 | wait_for_completion(&policy->kobj_unregister); | 802 | wait_for_completion(&policy->kobj_unregister); |
@@ -858,16 +808,12 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, | |||
858 | struct device *dev) | 808 | struct device *dev) |
859 | { | 809 | { |
860 | struct cpufreq_policy *policy; | 810 | struct cpufreq_policy *policy; |
861 | int ret = 0, has_target = 0; | 811 | int ret = 0, has_target = !!cpufreq_driver->target; |
862 | unsigned long flags; | 812 | unsigned long flags; |
863 | 813 | ||
864 | policy = cpufreq_cpu_get(sibling); | 814 | policy = cpufreq_cpu_get(sibling); |
865 | WARN_ON(!policy); | 815 | WARN_ON(!policy); |
866 | 816 | ||
867 | rcu_read_lock(); | ||
868 | has_target = !!rcu_dereference(cpufreq_driver)->target; | ||
869 | rcu_read_unlock(); | ||
870 | |||
871 | if (has_target) | 817 | if (has_target) |
872 | __cpufreq_governor(policy, CPUFREQ_GOV_STOP); | 818 | __cpufreq_governor(policy, CPUFREQ_GOV_STOP); |
873 | 819 | ||
@@ -911,8 +857,6 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | |||
911 | unsigned int j, cpu = dev->id; | 857 | unsigned int j, cpu = dev->id; |
912 | int ret = -ENOMEM; | 858 | int ret = -ENOMEM; |
913 | struct cpufreq_policy *policy; | 859 | struct cpufreq_policy *policy; |
914 | struct cpufreq_driver *driver; | ||
915 | int (*init)(struct cpufreq_policy *policy); | ||
916 | unsigned long flags; | 860 | unsigned long flags; |
917 | #ifdef CONFIG_HOTPLUG_CPU | 861 | #ifdef CONFIG_HOTPLUG_CPU |
918 | struct cpufreq_governor *gov; | 862 | struct cpufreq_governor *gov; |
@@ -947,15 +891,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | |||
947 | #endif | 891 | #endif |
948 | #endif | 892 | #endif |
949 | 893 | ||
950 | rcu_read_lock(); | 894 | if (!try_module_get(cpufreq_driver->owner)) { |
951 | driver = rcu_dereference(cpufreq_driver); | ||
952 | if (!try_module_get(driver->owner)) { | ||
953 | rcu_read_unlock(); | ||
954 | ret = -EINVAL; | 895 | ret = -EINVAL; |
955 | goto module_out; | 896 | goto module_out; |
956 | } | 897 | } |
957 | init = driver->init; | ||
958 | rcu_read_unlock(); | ||
959 | 898 | ||
960 | policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); | 899 | policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); |
961 | if (!policy) | 900 | if (!policy) |
@@ -980,7 +919,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | |||
980 | /* call driver. From then on the cpufreq must be able | 919 | /* call driver. From then on the cpufreq must be able |
981 | * to accept all calls to ->verify and ->setpolicy for this CPU | 920 | * to accept all calls to ->verify and ->setpolicy for this CPU |
982 | */ | 921 | */ |
983 | ret = init(policy); | 922 | ret = cpufreq_driver->init(policy); |
984 | if (ret) { | 923 | if (ret) { |
985 | pr_debug("initialization failed\n"); | 924 | pr_debug("initialization failed\n"); |
986 | goto err_set_policy_cpu; | 925 | goto err_set_policy_cpu; |
@@ -1015,9 +954,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) | |||
1015 | goto err_out_unregister; | 954 | goto err_out_unregister; |
1016 | 955 | ||
1017 | kobject_uevent(&policy->kobj, KOBJ_ADD); | 956 | kobject_uevent(&policy->kobj, KOBJ_ADD); |
1018 | rcu_read_lock(); | 957 | module_put(cpufreq_driver->owner); |
1019 | module_put(rcu_dereference(cpufreq_driver)->owner); | ||
1020 | rcu_read_unlock(); | ||
1021 | pr_debug("initialization complete\n"); | 958 | pr_debug("initialization complete\n"); |
1022 | 959 | ||
1023 | return 0; | 960 | return 0; |
@@ -1039,9 +976,7 @@ err_free_cpumask: | |||
1039 | err_free_policy: | 976 | err_free_policy: |
1040 | kfree(policy); | 977 | kfree(policy); |
1041 | nomem_out: | 978 | nomem_out: |
1042 | rcu_read_lock(); | 979 | module_put(cpufreq_driver->owner); |
1043 | module_put(rcu_dereference(cpufreq_driver)->owner); | ||
1044 | rcu_read_unlock(); | ||
1045 | module_out: | 980 | module_out: |
1046 | return ret; | 981 | return ret; |
1047 | } | 982 | } |
@@ -1075,12 +1010,9 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif | |||
1075 | unsigned int cpu = dev->id, ret, cpus; | 1010 | unsigned int cpu = dev->id, ret, cpus; |
1076 | unsigned long flags; | 1011 | unsigned long flags; |
1077 | struct cpufreq_policy *data; | 1012 | struct cpufreq_policy *data; |
1078 | struct cpufreq_driver *driver; | ||
1079 | struct kobject *kobj; | 1013 | struct kobject *kobj; |
1080 | struct completion *cmp; | 1014 | struct completion *cmp; |
1081 | struct device *cpu_dev; | 1015 | struct device *cpu_dev; |
1082 | bool has_target; | ||
1083 | int (*exit)(struct cpufreq_policy *policy); | ||
1084 | 1016 | ||
1085 | pr_debug("%s: unregistering CPU %u\n", __func__, cpu); | 1017 | pr_debug("%s: unregistering CPU %u\n", __func__, cpu); |
1086 | 1018 | ||
@@ -1096,19 +1028,14 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif | |||
1096 | return -EINVAL; | 1028 | return -EINVAL; |
1097 | } | 1029 | } |
1098 | 1030 | ||
1099 | rcu_read_lock(); | 1031 | if (cpufreq_driver->target) |
1100 | driver = rcu_dereference(cpufreq_driver); | ||
1101 | has_target = driver->target ? true : false; | ||
1102 | exit = driver->exit; | ||
1103 | if (has_target) | ||
1104 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); | 1032 | __cpufreq_governor(data, CPUFREQ_GOV_STOP); |
1105 | 1033 | ||
1106 | #ifdef CONFIG_HOTPLUG_CPU | 1034 | #ifdef CONFIG_HOTPLUG_CPU |
1107 | if (!driver->setpolicy) | 1035 | if (!cpufreq_driver->setpolicy) |
1108 | strncpy(per_cpu(cpufreq_cpu_governor, cpu), | 1036 | strncpy(per_cpu(cpufreq_cpu_governor, cpu), |
1109 | data->governor->name, CPUFREQ_NAME_LEN); | 1037 | data->governor->name, CPUFREQ_NAME_LEN); |
1110 | #endif | 1038 | #endif |
1111 | rcu_read_unlock(); | ||
1112 | 1039 | ||
1113 | WARN_ON(lock_policy_rwsem_write(cpu)); | 1040 | WARN_ON(lock_policy_rwsem_write(cpu)); |
1114 | cpus = cpumask_weight(data->cpus); | 1041 | cpus = cpumask_weight(data->cpus); |
@@ -1153,7 +1080,7 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif | |||
1153 | 1080 | ||
1154 | /* If cpu is last user of policy, free policy */ | 1081 | /* If cpu is last user of policy, free policy */ |
1155 | if (cpus == 1) { | 1082 | if (cpus == 1) { |
1156 | if (has_target) | 1083 | if (cpufreq_driver->target) |
1157 | __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); | 1084 | __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); |
1158 | 1085 | ||
1159 | lock_policy_rwsem_read(cpu); | 1086 | lock_policy_rwsem_read(cpu); |
@@ -1170,13 +1097,13 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif | |||
1170 | wait_for_completion(cmp); | 1097 | wait_for_completion(cmp); |
1171 | pr_debug("wait complete\n"); | 1098 | pr_debug("wait complete\n"); |
1172 | 1099 | ||
1173 | if (exit) | 1100 | if (cpufreq_driver->exit) |
1174 | exit(data); | 1101 | cpufreq_driver->exit(data); |
1175 | 1102 | ||
1176 | free_cpumask_var(data->related_cpus); | 1103 | free_cpumask_var(data->related_cpus); |
1177 | free_cpumask_var(data->cpus); | 1104 | free_cpumask_var(data->cpus); |
1178 | kfree(data); | 1105 | kfree(data); |
1179 | } else if (has_target) { | 1106 | } else if (cpufreq_driver->target) { |
1180 | __cpufreq_governor(data, CPUFREQ_GOV_START); | 1107 | __cpufreq_governor(data, CPUFREQ_GOV_START); |
1181 | __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); | 1108 | __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); |
1182 | } | 1109 | } |
@@ -1250,18 +1177,10 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, | |||
1250 | unsigned int cpufreq_quick_get(unsigned int cpu) | 1177 | unsigned int cpufreq_quick_get(unsigned int cpu) |
1251 | { | 1178 | { |
1252 | struct cpufreq_policy *policy; | 1179 | struct cpufreq_policy *policy; |
1253 | struct cpufreq_driver *driver; | ||
1254 | unsigned int (*get)(unsigned int cpu); | ||
1255 | unsigned int ret_freq = 0; | 1180 | unsigned int ret_freq = 0; |
1256 | 1181 | ||
1257 | rcu_read_lock(); | 1182 | if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) |
1258 | driver = rcu_dereference(cpufreq_driver); | 1183 | return cpufreq_driver->get(cpu); |
1259 | if (driver && driver->setpolicy && driver->get) { | ||
1260 | get = driver->get; | ||
1261 | rcu_read_unlock(); | ||
1262 | return get(cpu); | ||
1263 | } | ||
1264 | rcu_read_unlock(); | ||
1265 | 1184 | ||
1266 | policy = cpufreq_cpu_get(cpu); | 1185 | policy = cpufreq_cpu_get(cpu); |
1267 | if (policy) { | 1186 | if (policy) { |
@@ -1297,26 +1216,15 @@ EXPORT_SYMBOL(cpufreq_quick_get_max); | |||
1297 | static unsigned int __cpufreq_get(unsigned int cpu) | 1216 | static unsigned int __cpufreq_get(unsigned int cpu) |
1298 | { | 1217 | { |
1299 | struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); | 1218 | struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); |
1300 | struct cpufreq_driver *driver; | ||
1301 | unsigned int (*get)(unsigned int cpu); | ||
1302 | unsigned int ret_freq = 0; | 1219 | unsigned int ret_freq = 0; |
1303 | u8 flags; | ||
1304 | 1220 | ||
1305 | 1221 | if (!cpufreq_driver->get) | |
1306 | rcu_read_lock(); | ||
1307 | driver = rcu_dereference(cpufreq_driver); | ||
1308 | if (!driver->get) { | ||
1309 | rcu_read_unlock(); | ||
1310 | return ret_freq; | 1222 | return ret_freq; |
1311 | } | ||
1312 | flags = driver->flags; | ||
1313 | get = driver->get; | ||
1314 | rcu_read_unlock(); | ||
1315 | 1223 | ||
1316 | ret_freq = get(cpu); | 1224 | ret_freq = cpufreq_driver->get(cpu); |
1317 | 1225 | ||
1318 | if (ret_freq && policy->cur && | 1226 | if (ret_freq && policy->cur && |
1319 | !(flags & CPUFREQ_CONST_LOOPS)) { | 1227 | !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { |
1320 | /* verify no discrepancy between actual and | 1228 | /* verify no discrepancy between actual and |
1321 | saved value exists */ | 1229 | saved value exists */ |
1322 | if (unlikely(ret_freq != policy->cur)) { | 1230 | if (unlikely(ret_freq != policy->cur)) { |
@@ -1372,7 +1280,6 @@ static struct subsys_interface cpufreq_interface = { | |||
1372 | */ | 1280 | */ |
1373 | static int cpufreq_bp_suspend(void) | 1281 | static int cpufreq_bp_suspend(void) |
1374 | { | 1282 | { |
1375 | int (*suspend)(struct cpufreq_policy *policy); | ||
1376 | int ret = 0; | 1283 | int ret = 0; |
1377 | 1284 | ||
1378 | int cpu = smp_processor_id(); | 1285 | int cpu = smp_processor_id(); |
@@ -1385,11 +1292,8 @@ static int cpufreq_bp_suspend(void) | |||
1385 | if (!cpu_policy) | 1292 | if (!cpu_policy) |
1386 | return 0; | 1293 | return 0; |
1387 | 1294 | ||
1388 | rcu_read_lock(); | 1295 | if (cpufreq_driver->suspend) { |
1389 | suspend = rcu_dereference(cpufreq_driver)->suspend; | 1296 | ret = cpufreq_driver->suspend(cpu_policy); |
1390 | rcu_read_unlock(); | ||
1391 | if (suspend) { | ||
1392 | ret = suspend(cpu_policy); | ||
1393 | if (ret) | 1297 | if (ret) |
1394 | printk(KERN_ERR "cpufreq: suspend failed in ->suspend " | 1298 | printk(KERN_ERR "cpufreq: suspend failed in ->suspend " |
1395 | "step on CPU %u\n", cpu_policy->cpu); | 1299 | "step on CPU %u\n", cpu_policy->cpu); |
@@ -1415,7 +1319,6 @@ static int cpufreq_bp_suspend(void) | |||
1415 | static void cpufreq_bp_resume(void) | 1319 | static void cpufreq_bp_resume(void) |
1416 | { | 1320 | { |
1417 | int ret = 0; | 1321 | int ret = 0; |
1418 | int (*resume)(struct cpufreq_policy *policy); | ||
1419 | 1322 | ||
1420 | int cpu = smp_processor_id(); | 1323 | int cpu = smp_processor_id(); |
1421 | struct cpufreq_policy *cpu_policy; | 1324 | struct cpufreq_policy *cpu_policy; |
@@ -1427,12 +1330,8 @@ static void cpufreq_bp_resume(void) | |||
1427 | if (!cpu_policy) | 1330 | if (!cpu_policy) |
1428 | return; | 1331 | return; |
1429 | 1332 | ||
1430 | rcu_read_lock(); | 1333 | if (cpufreq_driver->resume) { |
1431 | resume = rcu_dereference(cpufreq_driver)->resume; | 1334 | ret = cpufreq_driver->resume(cpu_policy); |
1432 | rcu_read_unlock(); | ||
1433 | |||
1434 | if (resume) { | ||
1435 | ret = resume(cpu_policy); | ||
1436 | if (ret) { | 1335 | if (ret) { |
1437 | printk(KERN_ERR "cpufreq: resume failed in ->resume " | 1336 | printk(KERN_ERR "cpufreq: resume failed in ->resume " |
1438 | "step on CPU %u\n", cpu_policy->cpu); | 1337 | "step on CPU %u\n", cpu_policy->cpu); |
@@ -1459,14 +1358,10 @@ static struct syscore_ops cpufreq_syscore_ops = { | |||
1459 | */ | 1358 | */ |
1460 | const char *cpufreq_get_current_driver(void) | 1359 | const char *cpufreq_get_current_driver(void) |
1461 | { | 1360 | { |
1462 | struct cpufreq_driver *driver; | 1361 | if (cpufreq_driver) |
1463 | const char *name = NULL; | 1362 | return cpufreq_driver->name; |
1464 | rcu_read_lock(); | 1363 | |
1465 | driver = rcu_dereference(cpufreq_driver); | 1364 | return NULL; |
1466 | if (driver) | ||
1467 | name = driver->name; | ||
1468 | rcu_read_unlock(); | ||
1469 | return name; | ||
1470 | } | 1365 | } |
1471 | EXPORT_SYMBOL_GPL(cpufreq_get_current_driver); | 1366 | EXPORT_SYMBOL_GPL(cpufreq_get_current_driver); |
1472 | 1367 | ||
@@ -1560,9 +1455,6 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, | |||
1560 | { | 1455 | { |
1561 | int retval = -EINVAL; | 1456 | int retval = -EINVAL; |
1562 | unsigned int old_target_freq = target_freq; | 1457 | unsigned int old_target_freq = target_freq; |
1563 | int (*target)(struct cpufreq_policy *policy, | ||
1564 | unsigned int target_freq, | ||
1565 | unsigned int relation); | ||
1566 | 1458 | ||
1567 | if (cpufreq_disabled()) | 1459 | if (cpufreq_disabled()) |
1568 | return -ENODEV; | 1460 | return -ENODEV; |
@@ -1579,11 +1471,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, | |||
1579 | if (target_freq == policy->cur) | 1471 | if (target_freq == policy->cur) |
1580 | return 0; | 1472 | return 0; |
1581 | 1473 | ||
1582 | rcu_read_lock(); | 1474 | if (cpufreq_driver->target) |
1583 | target = rcu_dereference(cpufreq_driver)->target; | 1475 | retval = cpufreq_driver->target(policy, target_freq, relation); |
1584 | rcu_read_unlock(); | ||
1585 | if (target) | ||
1586 | retval = target(policy, target_freq, relation); | ||
1587 | 1476 | ||
1588 | return retval; | 1477 | return retval; |
1589 | } | 1478 | } |
@@ -1616,24 +1505,18 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target); | |||
1616 | int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu) | 1505 | int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu) |
1617 | { | 1506 | { |
1618 | int ret = 0; | 1507 | int ret = 0; |
1619 | unsigned int (*getavg)(struct cpufreq_policy *policy, | ||
1620 | unsigned int cpu); | ||
1621 | 1508 | ||
1622 | if (cpufreq_disabled()) | 1509 | if (cpufreq_disabled()) |
1623 | return ret; | 1510 | return ret; |
1624 | 1511 | ||
1625 | rcu_read_lock(); | 1512 | if (!cpufreq_driver->getavg) |
1626 | getavg = rcu_dereference(cpufreq_driver)->getavg; | ||
1627 | rcu_read_unlock(); | ||
1628 | |||
1629 | if (!getavg) | ||
1630 | return 0; | 1513 | return 0; |
1631 | 1514 | ||
1632 | policy = cpufreq_cpu_get(policy->cpu); | 1515 | policy = cpufreq_cpu_get(policy->cpu); |
1633 | if (!policy) | 1516 | if (!policy) |
1634 | return -EINVAL; | 1517 | return -EINVAL; |
1635 | 1518 | ||
1636 | ret = getavg(policy, cpu); | 1519 | ret = cpufreq_driver->getavg(policy, cpu); |
1637 | 1520 | ||
1638 | cpufreq_cpu_put(policy); | 1521 | cpufreq_cpu_put(policy); |
1639 | return ret; | 1522 | return ret; |
@@ -1791,9 +1674,6 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, | |||
1791 | struct cpufreq_policy *policy) | 1674 | struct cpufreq_policy *policy) |
1792 | { | 1675 | { |
1793 | int ret = 0, failed = 1; | 1676 | int ret = 0, failed = 1; |
1794 | struct cpufreq_driver *driver; | ||
1795 | int (*verify)(struct cpufreq_policy *policy); | ||
1796 | int (*setpolicy)(struct cpufreq_policy *policy); | ||
1797 | 1677 | ||
1798 | pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, | 1678 | pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, |
1799 | policy->min, policy->max); | 1679 | policy->min, policy->max); |
@@ -1807,13 +1687,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, | |||
1807 | } | 1687 | } |
1808 | 1688 | ||
1809 | /* verify the cpu speed can be set within this limit */ | 1689 | /* verify the cpu speed can be set within this limit */ |
1810 | rcu_read_lock(); | 1690 | ret = cpufreq_driver->verify(policy); |
1811 | driver = rcu_dereference(cpufreq_driver); | ||
1812 | verify = driver->verify; | ||
1813 | setpolicy = driver->setpolicy; | ||
1814 | rcu_read_unlock(); | ||
1815 | |||
1816 | ret = verify(policy); | ||
1817 | if (ret) | 1691 | if (ret) |
1818 | goto error_out; | 1692 | goto error_out; |
1819 | 1693 | ||
@@ -1827,7 +1701,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, | |||
1827 | 1701 | ||
1828 | /* verify the cpu speed can be set within this limit, | 1702 | /* verify the cpu speed can be set within this limit, |
1829 | which might be different to the first one */ | 1703 | which might be different to the first one */ |
1830 | ret = verify(policy); | 1704 | ret = cpufreq_driver->verify(policy); |
1831 | if (ret) | 1705 | if (ret) |
1832 | goto error_out; | 1706 | goto error_out; |
1833 | 1707 | ||
@@ -1841,10 +1715,10 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, | |||
1841 | pr_debug("new min and max freqs are %u - %u kHz\n", | 1715 | pr_debug("new min and max freqs are %u - %u kHz\n", |
1842 | data->min, data->max); | 1716 | data->min, data->max); |
1843 | 1717 | ||
1844 | if (setpolicy) { | 1718 | if (cpufreq_driver->setpolicy) { |
1845 | data->policy = policy->policy; | 1719 | data->policy = policy->policy; |
1846 | pr_debug("setting range\n"); | 1720 | pr_debug("setting range\n"); |
1847 | ret = setpolicy(policy); | 1721 | ret = cpufreq_driver->setpolicy(policy); |
1848 | } else { | 1722 | } else { |
1849 | if (policy->governor != data->governor) { | 1723 | if (policy->governor != data->governor) { |
1850 | /* save old, working values */ | 1724 | /* save old, working values */ |
@@ -1904,11 +1778,6 @@ int cpufreq_update_policy(unsigned int cpu) | |||
1904 | { | 1778 | { |
1905 | struct cpufreq_policy *data = cpufreq_cpu_get(cpu); | 1779 | struct cpufreq_policy *data = cpufreq_cpu_get(cpu); |
1906 | struct cpufreq_policy policy; | 1780 | struct cpufreq_policy policy; |
1907 | struct cpufreq_driver *driver; | ||
1908 | unsigned int (*get)(unsigned int cpu); | ||
1909 | int (*target)(struct cpufreq_policy *policy, | ||
1910 | unsigned int target_freq, | ||
1911 | unsigned int relation); | ||
1912 | int ret; | 1781 | int ret; |
1913 | 1782 | ||
1914 | if (!data) { | 1783 | if (!data) { |
@@ -1930,18 +1799,13 @@ int cpufreq_update_policy(unsigned int cpu) | |||
1930 | 1799 | ||
1931 | /* BIOS might change freq behind our back | 1800 | /* BIOS might change freq behind our back |
1932 | -> ask driver for current freq and notify governors about a change */ | 1801 | -> ask driver for current freq and notify governors about a change */ |
1933 | rcu_read_lock(); | 1802 | if (cpufreq_driver->get) { |
1934 | driver = rcu_access_pointer(cpufreq_driver); | 1803 | policy.cur = cpufreq_driver->get(cpu); |
1935 | get = driver->get; | ||
1936 | target = driver->target; | ||
1937 | rcu_read_unlock(); | ||
1938 | if (get) { | ||
1939 | policy.cur = get(cpu); | ||
1940 | if (!data->cur) { | 1804 | if (!data->cur) { |
1941 | pr_debug("Driver did not initialize current freq"); | 1805 | pr_debug("Driver did not initialize current freq"); |
1942 | data->cur = policy.cur; | 1806 | data->cur = policy.cur; |
1943 | } else { | 1807 | } else { |
1944 | if (data->cur != policy.cur && target) | 1808 | if (data->cur != policy.cur && cpufreq_driver->target) |
1945 | cpufreq_out_of_sync(cpu, data->cur, | 1809 | cpufreq_out_of_sync(cpu, data->cur, |
1946 | policy.cur); | 1810 | policy.cur); |
1947 | } | 1811 | } |
@@ -2020,19 +1884,18 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) | |||
2020 | driver_data->flags |= CPUFREQ_CONST_LOOPS; | 1884 | driver_data->flags |= CPUFREQ_CONST_LOOPS; |
2021 | 1885 | ||
2022 | write_lock_irqsave(&cpufreq_driver_lock, flags); | 1886 | write_lock_irqsave(&cpufreq_driver_lock, flags); |
2023 | if (rcu_access_pointer(cpufreq_driver)) { | 1887 | if (cpufreq_driver) { |
2024 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1888 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); |
2025 | return -EBUSY; | 1889 | return -EBUSY; |
2026 | } | 1890 | } |
2027 | rcu_assign_pointer(cpufreq_driver, driver_data); | 1891 | cpufreq_driver = driver_data; |
2028 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1892 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); |
2029 | synchronize_rcu(); | ||
2030 | 1893 | ||
2031 | ret = subsys_interface_register(&cpufreq_interface); | 1894 | ret = subsys_interface_register(&cpufreq_interface); |
2032 | if (ret) | 1895 | if (ret) |
2033 | goto err_null_driver; | 1896 | goto err_null_driver; |
2034 | 1897 | ||
2035 | if (!(driver_data->flags & CPUFREQ_STICKY)) { | 1898 | if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) { |
2036 | int i; | 1899 | int i; |
2037 | ret = -ENODEV; | 1900 | ret = -ENODEV; |
2038 | 1901 | ||
@@ -2059,9 +1922,8 @@ err_if_unreg: | |||
2059 | subsys_interface_unregister(&cpufreq_interface); | 1922 | subsys_interface_unregister(&cpufreq_interface); |
2060 | err_null_driver: | 1923 | err_null_driver: |
2061 | write_lock_irqsave(&cpufreq_driver_lock, flags); | 1924 | write_lock_irqsave(&cpufreq_driver_lock, flags); |
2062 | rcu_assign_pointer(cpufreq_driver, NULL); | 1925 | cpufreq_driver = NULL; |
2063 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1926 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); |
2064 | synchronize_rcu(); | ||
2065 | return ret; | 1927 | return ret; |
2066 | } | 1928 | } |
2067 | EXPORT_SYMBOL_GPL(cpufreq_register_driver); | 1929 | EXPORT_SYMBOL_GPL(cpufreq_register_driver); |
@@ -2078,15 +1940,9 @@ EXPORT_SYMBOL_GPL(cpufreq_register_driver); | |||
2078 | int cpufreq_unregister_driver(struct cpufreq_driver *driver) | 1940 | int cpufreq_unregister_driver(struct cpufreq_driver *driver) |
2079 | { | 1941 | { |
2080 | unsigned long flags; | 1942 | unsigned long flags; |
2081 | struct cpufreq_driver *old_driver; | ||
2082 | 1943 | ||
2083 | rcu_read_lock(); | 1944 | if (!cpufreq_driver || (driver != cpufreq_driver)) |
2084 | old_driver = rcu_access_pointer(cpufreq_driver); | ||
2085 | if (!old_driver || (driver != old_driver)) { | ||
2086 | rcu_read_unlock(); | ||
2087 | return -EINVAL; | 1945 | return -EINVAL; |
2088 | } | ||
2089 | rcu_read_unlock(); | ||
2090 | 1946 | ||
2091 | pr_debug("unregistering driver %s\n", driver->name); | 1947 | pr_debug("unregistering driver %s\n", driver->name); |
2092 | 1948 | ||
@@ -2094,9 +1950,8 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) | |||
2094 | unregister_hotcpu_notifier(&cpufreq_cpu_notifier); | 1950 | unregister_hotcpu_notifier(&cpufreq_cpu_notifier); |
2095 | 1951 | ||
2096 | write_lock_irqsave(&cpufreq_driver_lock, flags); | 1952 | write_lock_irqsave(&cpufreq_driver_lock, flags); |
2097 | rcu_assign_pointer(cpufreq_driver, NULL); | 1953 | cpufreq_driver = NULL; |
2098 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); | 1954 | write_unlock_irqrestore(&cpufreq_driver_lock, flags); |
2099 | synchronize_rcu(); | ||
2100 | 1955 | ||
2101 | return 0; | 1956 | return 0; |
2102 | } | 1957 | } |