diff options
| -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 | } |
