Loading drivers/cpufreq/cpufreq.c +69 −214 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ * level driver of CPUFreq support, and its spinlock. This lock * also protects the cpufreq_cpu_data array. */ static struct cpufreq_driver __rcu *cpufreq_driver; static struct cpufreq_driver *cpufreq_driver; static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); #ifdef CONFIG_HOTPLUG_CPU /* This one keeps track of the previously set governor of a removed CPU */ Loading Loading @@ -130,34 +130,26 @@ static DEFINE_MUTEX(cpufreq_governor_mutex); bool have_governor_per_policy(void) { bool have_governor_per_policy; rcu_read_lock(); have_governor_per_policy = rcu_dereference(cpufreq_driver)->have_governor_per_policy; rcu_read_unlock(); return have_governor_per_policy; return cpufreq_driver->have_governor_per_policy; } static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) { struct cpufreq_policy *data; struct cpufreq_driver *driver; unsigned long flags; if (cpu >= nr_cpu_ids) goto err_out; /* get the cpufreq driver */ rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); read_lock_irqsave(&cpufreq_driver_lock, flags); if (!driver) if (!cpufreq_driver) goto err_out_unlock; if (!try_module_get(driver->owner)) if (!try_module_get(cpufreq_driver->owner)) goto err_out_unlock; read_lock_irqsave(&cpufreq_driver_lock, flags); /* get the CPU */ data = per_cpu(cpufreq_cpu_data, cpu); Loading @@ -169,14 +161,12 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) goto err_out_put_module; read_unlock_irqrestore(&cpufreq_driver_lock, flags); rcu_read_unlock(); return data; err_out_put_module: module_put(driver->owner); read_unlock_irqrestore(&cpufreq_driver_lock, flags); module_put(cpufreq_driver->owner); err_out_unlock: rcu_read_unlock(); read_unlock_irqrestore(&cpufreq_driver_lock, flags); err_out: return NULL; } Loading @@ -199,9 +189,7 @@ static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs) { if (!sysfs) kobject_put(&data->kobj); rcu_read_lock(); module_put(rcu_dereference(cpufreq_driver)->owner); rcu_read_unlock(); module_put(cpufreq_driver->owner); } void cpufreq_cpu_put(struct cpufreq_policy *data) Loading Loading @@ -269,9 +257,7 @@ void __cpufreq_notify_transition(struct cpufreq_policy *policy, if (cpufreq_disabled()) return; rcu_read_lock(); freqs->flags = rcu_dereference(cpufreq_driver)->flags; rcu_read_unlock(); freqs->flags = cpufreq_driver->flags; pr_debug("notification %u of frequency transition to %u kHz\n", state, freqs->new); Loading @@ -282,7 +268,7 @@ void __cpufreq_notify_transition(struct cpufreq_policy *policy, * which is not equal to what the cpufreq core thinks is * "old frequency". */ if (!(freqs->flags & CPUFREQ_CONST_LOOPS)) { if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { if ((policy) && (policy->cpu == freqs->cpu) && (policy->cur) && (policy->cur != freqs->old)) { pr_debug("Warning: CPU frequency is" Loading Loading @@ -348,21 +334,11 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) { int err = -EINVAL; struct cpufreq_driver *driver; bool has_setpolicy; bool has_target; rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (!driver) { rcu_read_unlock(); if (!cpufreq_driver) goto out; } has_setpolicy = driver->setpolicy ? true : false; has_target = driver->target ? true : false; rcu_read_unlock(); if (has_setpolicy) { if (cpufreq_driver->setpolicy) { if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_PERFORMANCE; err = 0; Loading @@ -371,7 +347,7 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, *policy = CPUFREQ_POLICY_POWERSAVE; err = 0; } } else if (has_target) { } else if (cpufreq_driver->target) { struct cpufreq_governor *t; mutex_lock(&cpufreq_governor_mutex); Loading Loading @@ -522,12 +498,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy, */ static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf) { ssize_t size; rcu_read_lock(); size = scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", rcu_dereference(cpufreq_driver)->name); rcu_read_unlock(); return size; return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name); } /** Loading @@ -539,13 +510,10 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, ssize_t i = 0; struct cpufreq_governor *t; rcu_read_lock(); if (!rcu_dereference(cpufreq_driver)->target) { rcu_read_unlock(); if (!cpufreq_driver->target) { i += sprintf(buf, "performance powersave"); goto out; } rcu_read_unlock(); list_for_each_entry(t, &cpufreq_governor_list, governor_list) { if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) Loading Loading @@ -623,15 +591,9 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) { unsigned int limit; int (*bios_limit)(int cpu, unsigned int *limit); int ret; rcu_read_lock(); bios_limit = rcu_dereference(cpufreq_driver)->bios_limit; rcu_read_unlock(); if (bios_limit) { ret = bios_limit(policy->cpu, &limit); if (cpufreq_driver->bios_limit) { ret = cpufreq_driver->bios_limit(policy->cpu, &limit); if (!ret) return sprintf(buf, "%u\n", limit); } Loading Loading @@ -774,7 +736,6 @@ static int cpufreq_add_dev_interface(unsigned int cpu, { struct cpufreq_policy new_policy; struct freq_attr **drv_attr; struct cpufreq_driver *driver; unsigned long flags; int ret = 0; unsigned int j; Loading @@ -786,31 +747,28 @@ static int cpufreq_add_dev_interface(unsigned int cpu, return ret; /* set up files for this cpu device */ rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); drv_attr = driver->attr; drv_attr = cpufreq_driver->attr; while ((drv_attr) && (*drv_attr)) { ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); if (ret) goto err_out_unlock; goto err_out_kobj_put; drv_attr++; } if (driver->get) { if (cpufreq_driver->get) { ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); if (ret) goto err_out_unlock; goto err_out_kobj_put; } if (driver->target) { if (cpufreq_driver->target) { ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); if (ret) goto err_out_unlock; goto err_out_kobj_put; } if (driver->bios_limit) { if (cpufreq_driver->bios_limit) { ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); if (ret) goto err_out_unlock; goto err_out_kobj_put; } rcu_read_unlock(); write_lock_irqsave(&cpufreq_driver_lock, flags); for_each_cpu(j, policy->cpus) { Loading @@ -833,20 +791,12 @@ static int cpufreq_add_dev_interface(unsigned int cpu, policy->user_policy.governor = policy->governor; if (ret) { int (*exit)(struct cpufreq_policy *policy); pr_debug("setting policy failed\n"); rcu_read_lock(); exit = rcu_dereference(cpufreq_driver)->exit; rcu_read_unlock(); if (exit) exit(policy); if (cpufreq_driver->exit) cpufreq_driver->exit(policy); } return ret; err_out_unlock: rcu_read_unlock(); err_out_kobj_put: kobject_put(&policy->kobj); wait_for_completion(&policy->kobj_unregister); Loading @@ -858,16 +808,12 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, struct device *dev) { struct cpufreq_policy *policy; int ret = 0, has_target = 0; int ret = 0, has_target = !!cpufreq_driver->target; unsigned long flags; policy = cpufreq_cpu_get(sibling); WARN_ON(!policy); rcu_read_lock(); has_target = !!rcu_dereference(cpufreq_driver)->target; rcu_read_unlock(); if (has_target) __cpufreq_governor(policy, CPUFREQ_GOV_STOP); Loading Loading @@ -911,8 +857,6 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) unsigned int j, cpu = dev->id; int ret = -ENOMEM; struct cpufreq_policy *policy; struct cpufreq_driver *driver; int (*init)(struct cpufreq_policy *policy); unsigned long flags; #ifdef CONFIG_HOTPLUG_CPU struct cpufreq_governor *gov; Loading Loading @@ -947,15 +891,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) #endif #endif rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (!try_module_get(driver->owner)) { rcu_read_unlock(); if (!try_module_get(cpufreq_driver->owner)) { ret = -EINVAL; goto module_out; } init = driver->init; rcu_read_unlock(); policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); if (!policy) Loading @@ -980,7 +919,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) /* call driver. From then on the cpufreq must be able * to accept all calls to ->verify and ->setpolicy for this CPU */ ret = init(policy); ret = cpufreq_driver->init(policy); if (ret) { pr_debug("initialization failed\n"); goto err_set_policy_cpu; Loading Loading @@ -1015,9 +954,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) goto err_out_unregister; kobject_uevent(&policy->kobj, KOBJ_ADD); rcu_read_lock(); module_put(rcu_dereference(cpufreq_driver)->owner); rcu_read_unlock(); module_put(cpufreq_driver->owner); pr_debug("initialization complete\n"); return 0; Loading @@ -1039,9 +976,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) err_free_policy: kfree(policy); nomem_out: rcu_read_lock(); module_put(rcu_dereference(cpufreq_driver)->owner); rcu_read_unlock(); module_put(cpufreq_driver->owner); module_out: return ret; } Loading Loading @@ -1075,12 +1010,9 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif unsigned int cpu = dev->id, ret, cpus; unsigned long flags; struct cpufreq_policy *data; struct cpufreq_driver *driver; struct kobject *kobj; struct completion *cmp; struct device *cpu_dev; bool has_target; int (*exit)(struct cpufreq_policy *policy); pr_debug("%s: unregistering CPU %u\n", __func__, cpu); Loading @@ -1096,19 +1028,14 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif return -EINVAL; } rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); has_target = driver->target ? true : false; exit = driver->exit; if (has_target) if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_STOP); #ifdef CONFIG_HOTPLUG_CPU if (!driver->setpolicy) if (!cpufreq_driver->setpolicy) strncpy(per_cpu(cpufreq_cpu_governor, cpu), data->governor->name, CPUFREQ_NAME_LEN); #endif rcu_read_unlock(); WARN_ON(lock_policy_rwsem_write(cpu)); cpus = cpumask_weight(data->cpus); Loading Loading @@ -1153,7 +1080,7 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif /* If cpu is last user of policy, free policy */ if (cpus == 1) { if (has_target) if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); lock_policy_rwsem_read(cpu); Loading @@ -1170,13 +1097,13 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif wait_for_completion(cmp); pr_debug("wait complete\n"); if (exit) exit(data); if (cpufreq_driver->exit) cpufreq_driver->exit(data); free_cpumask_var(data->related_cpus); free_cpumask_var(data->cpus); kfree(data); } else if (has_target) { } else if (cpufreq_driver->target) { __cpufreq_governor(data, CPUFREQ_GOV_START); __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); } Loading Loading @@ -1250,18 +1177,10 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigned int cpufreq_quick_get(unsigned int cpu) { struct cpufreq_policy *policy; struct cpufreq_driver *driver; unsigned int (*get)(unsigned int cpu); unsigned int ret_freq = 0; rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (driver && driver->setpolicy && driver->get) { get = driver->get; rcu_read_unlock(); return get(cpu); } rcu_read_unlock(); if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) return cpufreq_driver->get(cpu); policy = cpufreq_cpu_get(cpu); if (policy) { Loading Loading @@ -1297,26 +1216,15 @@ EXPORT_SYMBOL(cpufreq_quick_get_max); static unsigned int __cpufreq_get(unsigned int cpu) { struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); struct cpufreq_driver *driver; unsigned int (*get)(unsigned int cpu); unsigned int ret_freq = 0; u8 flags; rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (!driver->get) { rcu_read_unlock(); if (!cpufreq_driver->get) return ret_freq; } flags = driver->flags; get = driver->get; rcu_read_unlock(); ret_freq = get(cpu); ret_freq = cpufreq_driver->get(cpu); if (ret_freq && policy->cur && !(flags & CPUFREQ_CONST_LOOPS)) { !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { /* verify no discrepancy between actual and saved value exists */ if (unlikely(ret_freq != policy->cur)) { Loading Loading @@ -1372,7 +1280,6 @@ static struct subsys_interface cpufreq_interface = { */ static int cpufreq_bp_suspend(void) { int (*suspend)(struct cpufreq_policy *policy); int ret = 0; int cpu = smp_processor_id(); Loading @@ -1385,11 +1292,8 @@ static int cpufreq_bp_suspend(void) if (!cpu_policy) return 0; rcu_read_lock(); suspend = rcu_dereference(cpufreq_driver)->suspend; rcu_read_unlock(); if (suspend) { ret = suspend(cpu_policy); if (cpufreq_driver->suspend) { ret = cpufreq_driver->suspend(cpu_policy); if (ret) printk(KERN_ERR "cpufreq: suspend failed in ->suspend " "step on CPU %u\n", cpu_policy->cpu); Loading @@ -1415,7 +1319,6 @@ static int cpufreq_bp_suspend(void) static void cpufreq_bp_resume(void) { int ret = 0; int (*resume)(struct cpufreq_policy *policy); int cpu = smp_processor_id(); struct cpufreq_policy *cpu_policy; Loading @@ -1427,12 +1330,8 @@ static void cpufreq_bp_resume(void) if (!cpu_policy) return; rcu_read_lock(); resume = rcu_dereference(cpufreq_driver)->resume; rcu_read_unlock(); if (resume) { ret = resume(cpu_policy); if (cpufreq_driver->resume) { ret = cpufreq_driver->resume(cpu_policy); if (ret) { printk(KERN_ERR "cpufreq: resume failed in ->resume " "step on CPU %u\n", cpu_policy->cpu); Loading @@ -1459,14 +1358,10 @@ static struct syscore_ops cpufreq_syscore_ops = { */ const char *cpufreq_get_current_driver(void) { struct cpufreq_driver *driver; const char *name = NULL; rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (driver) name = driver->name; rcu_read_unlock(); return name; if (cpufreq_driver) return cpufreq_driver->name; return NULL; } EXPORT_SYMBOL_GPL(cpufreq_get_current_driver); Loading Loading @@ -1560,9 +1455,6 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, { int retval = -EINVAL; unsigned int old_target_freq = target_freq; int (*target)(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); if (cpufreq_disabled()) return -ENODEV; Loading @@ -1579,11 +1471,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, if (target_freq == policy->cur) return 0; rcu_read_lock(); target = rcu_dereference(cpufreq_driver)->target; rcu_read_unlock(); if (target) retval = target(policy, target_freq, relation); if (cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); return retval; } Loading Loading @@ -1616,24 +1505,18 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target); int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu) { int ret = 0; unsigned int (*getavg)(struct cpufreq_policy *policy, unsigned int cpu); if (cpufreq_disabled()) return ret; rcu_read_lock(); getavg = rcu_dereference(cpufreq_driver)->getavg; rcu_read_unlock(); if (!getavg) if (!cpufreq_driver->getavg) return 0; policy = cpufreq_cpu_get(policy->cpu); if (!policy) return -EINVAL; ret = getavg(policy, cpu); ret = cpufreq_driver->getavg(policy, cpu); cpufreq_cpu_put(policy); return ret; Loading Loading @@ -1791,9 +1674,6 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy) { int ret = 0, failed = 1; struct cpufreq_driver *driver; int (*verify)(struct cpufreq_policy *policy); int (*setpolicy)(struct cpufreq_policy *policy); pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, policy->min, policy->max); Loading @@ -1807,13 +1687,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, } /* verify the cpu speed can be set within this limit */ rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); verify = driver->verify; setpolicy = driver->setpolicy; rcu_read_unlock(); ret = verify(policy); ret = cpufreq_driver->verify(policy); if (ret) goto error_out; Loading @@ -1827,7 +1701,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, /* verify the cpu speed can be set within this limit, which might be different to the first one */ ret = verify(policy); ret = cpufreq_driver->verify(policy); if (ret) goto error_out; Loading @@ -1841,10 +1715,10 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, pr_debug("new min and max freqs are %u - %u kHz\n", data->min, data->max); if (setpolicy) { if (cpufreq_driver->setpolicy) { data->policy = policy->policy; pr_debug("setting range\n"); ret = setpolicy(policy); ret = cpufreq_driver->setpolicy(policy); } else { if (policy->governor != data->governor) { /* save old, working values */ Loading Loading @@ -1904,11 +1778,6 @@ int cpufreq_update_policy(unsigned int cpu) { struct cpufreq_policy *data = cpufreq_cpu_get(cpu); struct cpufreq_policy policy; struct cpufreq_driver *driver; unsigned int (*get)(unsigned int cpu); int (*target)(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); int ret; if (!data) { Loading @@ -1930,18 +1799,13 @@ int cpufreq_update_policy(unsigned int cpu) /* BIOS might change freq behind our back -> ask driver for current freq and notify governors about a change */ rcu_read_lock(); driver = rcu_access_pointer(cpufreq_driver); get = driver->get; target = driver->target; rcu_read_unlock(); if (get) { policy.cur = get(cpu); if (cpufreq_driver->get) { policy.cur = cpufreq_driver->get(cpu); if (!data->cur) { pr_debug("Driver did not initialize current freq"); data->cur = policy.cur; } else { if (data->cur != policy.cur && target) if (data->cur != policy.cur && cpufreq_driver->target) cpufreq_out_of_sync(cpu, data->cur, policy.cur); } Loading Loading @@ -2020,19 +1884,18 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) driver_data->flags |= CPUFREQ_CONST_LOOPS; write_lock_irqsave(&cpufreq_driver_lock, flags); if (rcu_access_pointer(cpufreq_driver)) { if (cpufreq_driver) { write_unlock_irqrestore(&cpufreq_driver_lock, flags); return -EBUSY; } rcu_assign_pointer(cpufreq_driver, driver_data); cpufreq_driver = driver_data; write_unlock_irqrestore(&cpufreq_driver_lock, flags); synchronize_rcu(); ret = subsys_interface_register(&cpufreq_interface); if (ret) goto err_null_driver; if (!(driver_data->flags & CPUFREQ_STICKY)) { if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) { int i; ret = -ENODEV; Loading @@ -2059,9 +1922,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) subsys_interface_unregister(&cpufreq_interface); err_null_driver: write_lock_irqsave(&cpufreq_driver_lock, flags); rcu_assign_pointer(cpufreq_driver, NULL); cpufreq_driver = NULL; write_unlock_irqrestore(&cpufreq_driver_lock, flags); synchronize_rcu(); return ret; } EXPORT_SYMBOL_GPL(cpufreq_register_driver); Loading @@ -2078,15 +1940,9 @@ EXPORT_SYMBOL_GPL(cpufreq_register_driver); int cpufreq_unregister_driver(struct cpufreq_driver *driver) { unsigned long flags; struct cpufreq_driver *old_driver; rcu_read_lock(); old_driver = rcu_access_pointer(cpufreq_driver); if (!old_driver || (driver != old_driver)) { rcu_read_unlock(); if (!cpufreq_driver || (driver != cpufreq_driver)) return -EINVAL; } rcu_read_unlock(); pr_debug("unregistering driver %s\n", driver->name); Loading @@ -2094,9 +1950,8 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) unregister_hotcpu_notifier(&cpufreq_cpu_notifier); write_lock_irqsave(&cpufreq_driver_lock, flags); rcu_assign_pointer(cpufreq_driver, NULL); cpufreq_driver = NULL; write_unlock_irqrestore(&cpufreq_driver_lock, flags); synchronize_rcu(); return 0; } Loading Loading
drivers/cpufreq/cpufreq.c +69 −214 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ * level driver of CPUFreq support, and its spinlock. This lock * also protects the cpufreq_cpu_data array. */ static struct cpufreq_driver __rcu *cpufreq_driver; static struct cpufreq_driver *cpufreq_driver; static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); #ifdef CONFIG_HOTPLUG_CPU /* This one keeps track of the previously set governor of a removed CPU */ Loading Loading @@ -130,34 +130,26 @@ static DEFINE_MUTEX(cpufreq_governor_mutex); bool have_governor_per_policy(void) { bool have_governor_per_policy; rcu_read_lock(); have_governor_per_policy = rcu_dereference(cpufreq_driver)->have_governor_per_policy; rcu_read_unlock(); return have_governor_per_policy; return cpufreq_driver->have_governor_per_policy; } static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) { struct cpufreq_policy *data; struct cpufreq_driver *driver; unsigned long flags; if (cpu >= nr_cpu_ids) goto err_out; /* get the cpufreq driver */ rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); read_lock_irqsave(&cpufreq_driver_lock, flags); if (!driver) if (!cpufreq_driver) goto err_out_unlock; if (!try_module_get(driver->owner)) if (!try_module_get(cpufreq_driver->owner)) goto err_out_unlock; read_lock_irqsave(&cpufreq_driver_lock, flags); /* get the CPU */ data = per_cpu(cpufreq_cpu_data, cpu); Loading @@ -169,14 +161,12 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) goto err_out_put_module; read_unlock_irqrestore(&cpufreq_driver_lock, flags); rcu_read_unlock(); return data; err_out_put_module: module_put(driver->owner); read_unlock_irqrestore(&cpufreq_driver_lock, flags); module_put(cpufreq_driver->owner); err_out_unlock: rcu_read_unlock(); read_unlock_irqrestore(&cpufreq_driver_lock, flags); err_out: return NULL; } Loading @@ -199,9 +189,7 @@ static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs) { if (!sysfs) kobject_put(&data->kobj); rcu_read_lock(); module_put(rcu_dereference(cpufreq_driver)->owner); rcu_read_unlock(); module_put(cpufreq_driver->owner); } void cpufreq_cpu_put(struct cpufreq_policy *data) Loading Loading @@ -269,9 +257,7 @@ void __cpufreq_notify_transition(struct cpufreq_policy *policy, if (cpufreq_disabled()) return; rcu_read_lock(); freqs->flags = rcu_dereference(cpufreq_driver)->flags; rcu_read_unlock(); freqs->flags = cpufreq_driver->flags; pr_debug("notification %u of frequency transition to %u kHz\n", state, freqs->new); Loading @@ -282,7 +268,7 @@ void __cpufreq_notify_transition(struct cpufreq_policy *policy, * which is not equal to what the cpufreq core thinks is * "old frequency". */ if (!(freqs->flags & CPUFREQ_CONST_LOOPS)) { if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { if ((policy) && (policy->cpu == freqs->cpu) && (policy->cur) && (policy->cur != freqs->old)) { pr_debug("Warning: CPU frequency is" Loading Loading @@ -348,21 +334,11 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) { int err = -EINVAL; struct cpufreq_driver *driver; bool has_setpolicy; bool has_target; rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (!driver) { rcu_read_unlock(); if (!cpufreq_driver) goto out; } has_setpolicy = driver->setpolicy ? true : false; has_target = driver->target ? true : false; rcu_read_unlock(); if (has_setpolicy) { if (cpufreq_driver->setpolicy) { if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_PERFORMANCE; err = 0; Loading @@ -371,7 +347,7 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, *policy = CPUFREQ_POLICY_POWERSAVE; err = 0; } } else if (has_target) { } else if (cpufreq_driver->target) { struct cpufreq_governor *t; mutex_lock(&cpufreq_governor_mutex); Loading Loading @@ -522,12 +498,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy, */ static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf) { ssize_t size; rcu_read_lock(); size = scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", rcu_dereference(cpufreq_driver)->name); rcu_read_unlock(); return size; return scnprintf(buf, CPUFREQ_NAME_PLEN, "%s\n", cpufreq_driver->name); } /** Loading @@ -539,13 +510,10 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, ssize_t i = 0; struct cpufreq_governor *t; rcu_read_lock(); if (!rcu_dereference(cpufreq_driver)->target) { rcu_read_unlock(); if (!cpufreq_driver->target) { i += sprintf(buf, "performance powersave"); goto out; } rcu_read_unlock(); list_for_each_entry(t, &cpufreq_governor_list, governor_list) { if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) Loading Loading @@ -623,15 +591,9 @@ static ssize_t show_scaling_setspeed(struct cpufreq_policy *policy, char *buf) static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) { unsigned int limit; int (*bios_limit)(int cpu, unsigned int *limit); int ret; rcu_read_lock(); bios_limit = rcu_dereference(cpufreq_driver)->bios_limit; rcu_read_unlock(); if (bios_limit) { ret = bios_limit(policy->cpu, &limit); if (cpufreq_driver->bios_limit) { ret = cpufreq_driver->bios_limit(policy->cpu, &limit); if (!ret) return sprintf(buf, "%u\n", limit); } Loading Loading @@ -774,7 +736,6 @@ static int cpufreq_add_dev_interface(unsigned int cpu, { struct cpufreq_policy new_policy; struct freq_attr **drv_attr; struct cpufreq_driver *driver; unsigned long flags; int ret = 0; unsigned int j; Loading @@ -786,31 +747,28 @@ static int cpufreq_add_dev_interface(unsigned int cpu, return ret; /* set up files for this cpu device */ rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); drv_attr = driver->attr; drv_attr = cpufreq_driver->attr; while ((drv_attr) && (*drv_attr)) { ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); if (ret) goto err_out_unlock; goto err_out_kobj_put; drv_attr++; } if (driver->get) { if (cpufreq_driver->get) { ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); if (ret) goto err_out_unlock; goto err_out_kobj_put; } if (driver->target) { if (cpufreq_driver->target) { ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); if (ret) goto err_out_unlock; goto err_out_kobj_put; } if (driver->bios_limit) { if (cpufreq_driver->bios_limit) { ret = sysfs_create_file(&policy->kobj, &bios_limit.attr); if (ret) goto err_out_unlock; goto err_out_kobj_put; } rcu_read_unlock(); write_lock_irqsave(&cpufreq_driver_lock, flags); for_each_cpu(j, policy->cpus) { Loading @@ -833,20 +791,12 @@ static int cpufreq_add_dev_interface(unsigned int cpu, policy->user_policy.governor = policy->governor; if (ret) { int (*exit)(struct cpufreq_policy *policy); pr_debug("setting policy failed\n"); rcu_read_lock(); exit = rcu_dereference(cpufreq_driver)->exit; rcu_read_unlock(); if (exit) exit(policy); if (cpufreq_driver->exit) cpufreq_driver->exit(policy); } return ret; err_out_unlock: rcu_read_unlock(); err_out_kobj_put: kobject_put(&policy->kobj); wait_for_completion(&policy->kobj_unregister); Loading @@ -858,16 +808,12 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, struct device *dev) { struct cpufreq_policy *policy; int ret = 0, has_target = 0; int ret = 0, has_target = !!cpufreq_driver->target; unsigned long flags; policy = cpufreq_cpu_get(sibling); WARN_ON(!policy); rcu_read_lock(); has_target = !!rcu_dereference(cpufreq_driver)->target; rcu_read_unlock(); if (has_target) __cpufreq_governor(policy, CPUFREQ_GOV_STOP); Loading Loading @@ -911,8 +857,6 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) unsigned int j, cpu = dev->id; int ret = -ENOMEM; struct cpufreq_policy *policy; struct cpufreq_driver *driver; int (*init)(struct cpufreq_policy *policy); unsigned long flags; #ifdef CONFIG_HOTPLUG_CPU struct cpufreq_governor *gov; Loading Loading @@ -947,15 +891,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) #endif #endif rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (!try_module_get(driver->owner)) { rcu_read_unlock(); if (!try_module_get(cpufreq_driver->owner)) { ret = -EINVAL; goto module_out; } init = driver->init; rcu_read_unlock(); policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); if (!policy) Loading @@ -980,7 +919,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) /* call driver. From then on the cpufreq must be able * to accept all calls to ->verify and ->setpolicy for this CPU */ ret = init(policy); ret = cpufreq_driver->init(policy); if (ret) { pr_debug("initialization failed\n"); goto err_set_policy_cpu; Loading Loading @@ -1015,9 +954,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) goto err_out_unregister; kobject_uevent(&policy->kobj, KOBJ_ADD); rcu_read_lock(); module_put(rcu_dereference(cpufreq_driver)->owner); rcu_read_unlock(); module_put(cpufreq_driver->owner); pr_debug("initialization complete\n"); return 0; Loading @@ -1039,9 +976,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) err_free_policy: kfree(policy); nomem_out: rcu_read_lock(); module_put(rcu_dereference(cpufreq_driver)->owner); rcu_read_unlock(); module_put(cpufreq_driver->owner); module_out: return ret; } Loading Loading @@ -1075,12 +1010,9 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif unsigned int cpu = dev->id, ret, cpus; unsigned long flags; struct cpufreq_policy *data; struct cpufreq_driver *driver; struct kobject *kobj; struct completion *cmp; struct device *cpu_dev; bool has_target; int (*exit)(struct cpufreq_policy *policy); pr_debug("%s: unregistering CPU %u\n", __func__, cpu); Loading @@ -1096,19 +1028,14 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif return -EINVAL; } rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); has_target = driver->target ? true : false; exit = driver->exit; if (has_target) if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_STOP); #ifdef CONFIG_HOTPLUG_CPU if (!driver->setpolicy) if (!cpufreq_driver->setpolicy) strncpy(per_cpu(cpufreq_cpu_governor, cpu), data->governor->name, CPUFREQ_NAME_LEN); #endif rcu_read_unlock(); WARN_ON(lock_policy_rwsem_write(cpu)); cpus = cpumask_weight(data->cpus); Loading Loading @@ -1153,7 +1080,7 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif /* If cpu is last user of policy, free policy */ if (cpus == 1) { if (has_target) if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); lock_policy_rwsem_read(cpu); Loading @@ -1170,13 +1097,13 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif wait_for_completion(cmp); pr_debug("wait complete\n"); if (exit) exit(data); if (cpufreq_driver->exit) cpufreq_driver->exit(data); free_cpumask_var(data->related_cpus); free_cpumask_var(data->cpus); kfree(data); } else if (has_target) { } else if (cpufreq_driver->target) { __cpufreq_governor(data, CPUFREQ_GOV_START); __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); } Loading Loading @@ -1250,18 +1177,10 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigned int cpufreq_quick_get(unsigned int cpu) { struct cpufreq_policy *policy; struct cpufreq_driver *driver; unsigned int (*get)(unsigned int cpu); unsigned int ret_freq = 0; rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (driver && driver->setpolicy && driver->get) { get = driver->get; rcu_read_unlock(); return get(cpu); } rcu_read_unlock(); if (cpufreq_driver && cpufreq_driver->setpolicy && cpufreq_driver->get) return cpufreq_driver->get(cpu); policy = cpufreq_cpu_get(cpu); if (policy) { Loading Loading @@ -1297,26 +1216,15 @@ EXPORT_SYMBOL(cpufreq_quick_get_max); static unsigned int __cpufreq_get(unsigned int cpu) { struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); struct cpufreq_driver *driver; unsigned int (*get)(unsigned int cpu); unsigned int ret_freq = 0; u8 flags; rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (!driver->get) { rcu_read_unlock(); if (!cpufreq_driver->get) return ret_freq; } flags = driver->flags; get = driver->get; rcu_read_unlock(); ret_freq = get(cpu); ret_freq = cpufreq_driver->get(cpu); if (ret_freq && policy->cur && !(flags & CPUFREQ_CONST_LOOPS)) { !(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { /* verify no discrepancy between actual and saved value exists */ if (unlikely(ret_freq != policy->cur)) { Loading Loading @@ -1372,7 +1280,6 @@ static struct subsys_interface cpufreq_interface = { */ static int cpufreq_bp_suspend(void) { int (*suspend)(struct cpufreq_policy *policy); int ret = 0; int cpu = smp_processor_id(); Loading @@ -1385,11 +1292,8 @@ static int cpufreq_bp_suspend(void) if (!cpu_policy) return 0; rcu_read_lock(); suspend = rcu_dereference(cpufreq_driver)->suspend; rcu_read_unlock(); if (suspend) { ret = suspend(cpu_policy); if (cpufreq_driver->suspend) { ret = cpufreq_driver->suspend(cpu_policy); if (ret) printk(KERN_ERR "cpufreq: suspend failed in ->suspend " "step on CPU %u\n", cpu_policy->cpu); Loading @@ -1415,7 +1319,6 @@ static int cpufreq_bp_suspend(void) static void cpufreq_bp_resume(void) { int ret = 0; int (*resume)(struct cpufreq_policy *policy); int cpu = smp_processor_id(); struct cpufreq_policy *cpu_policy; Loading @@ -1427,12 +1330,8 @@ static void cpufreq_bp_resume(void) if (!cpu_policy) return; rcu_read_lock(); resume = rcu_dereference(cpufreq_driver)->resume; rcu_read_unlock(); if (resume) { ret = resume(cpu_policy); if (cpufreq_driver->resume) { ret = cpufreq_driver->resume(cpu_policy); if (ret) { printk(KERN_ERR "cpufreq: resume failed in ->resume " "step on CPU %u\n", cpu_policy->cpu); Loading @@ -1459,14 +1358,10 @@ static struct syscore_ops cpufreq_syscore_ops = { */ const char *cpufreq_get_current_driver(void) { struct cpufreq_driver *driver; const char *name = NULL; rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); if (driver) name = driver->name; rcu_read_unlock(); return name; if (cpufreq_driver) return cpufreq_driver->name; return NULL; } EXPORT_SYMBOL_GPL(cpufreq_get_current_driver); Loading Loading @@ -1560,9 +1455,6 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, { int retval = -EINVAL; unsigned int old_target_freq = target_freq; int (*target)(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); if (cpufreq_disabled()) return -ENODEV; Loading @@ -1579,11 +1471,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, if (target_freq == policy->cur) return 0; rcu_read_lock(); target = rcu_dereference(cpufreq_driver)->target; rcu_read_unlock(); if (target) retval = target(policy, target_freq, relation); if (cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); return retval; } Loading Loading @@ -1616,24 +1505,18 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target); int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu) { int ret = 0; unsigned int (*getavg)(struct cpufreq_policy *policy, unsigned int cpu); if (cpufreq_disabled()) return ret; rcu_read_lock(); getavg = rcu_dereference(cpufreq_driver)->getavg; rcu_read_unlock(); if (!getavg) if (!cpufreq_driver->getavg) return 0; policy = cpufreq_cpu_get(policy->cpu); if (!policy) return -EINVAL; ret = getavg(policy, cpu); ret = cpufreq_driver->getavg(policy, cpu); cpufreq_cpu_put(policy); return ret; Loading Loading @@ -1791,9 +1674,6 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy) { int ret = 0, failed = 1; struct cpufreq_driver *driver; int (*verify)(struct cpufreq_policy *policy); int (*setpolicy)(struct cpufreq_policy *policy); pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, policy->min, policy->max); Loading @@ -1807,13 +1687,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, } /* verify the cpu speed can be set within this limit */ rcu_read_lock(); driver = rcu_dereference(cpufreq_driver); verify = driver->verify; setpolicy = driver->setpolicy; rcu_read_unlock(); ret = verify(policy); ret = cpufreq_driver->verify(policy); if (ret) goto error_out; Loading @@ -1827,7 +1701,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, /* verify the cpu speed can be set within this limit, which might be different to the first one */ ret = verify(policy); ret = cpufreq_driver->verify(policy); if (ret) goto error_out; Loading @@ -1841,10 +1715,10 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, pr_debug("new min and max freqs are %u - %u kHz\n", data->min, data->max); if (setpolicy) { if (cpufreq_driver->setpolicy) { data->policy = policy->policy; pr_debug("setting range\n"); ret = setpolicy(policy); ret = cpufreq_driver->setpolicy(policy); } else { if (policy->governor != data->governor) { /* save old, working values */ Loading Loading @@ -1904,11 +1778,6 @@ int cpufreq_update_policy(unsigned int cpu) { struct cpufreq_policy *data = cpufreq_cpu_get(cpu); struct cpufreq_policy policy; struct cpufreq_driver *driver; unsigned int (*get)(unsigned int cpu); int (*target)(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); int ret; if (!data) { Loading @@ -1930,18 +1799,13 @@ int cpufreq_update_policy(unsigned int cpu) /* BIOS might change freq behind our back -> ask driver for current freq and notify governors about a change */ rcu_read_lock(); driver = rcu_access_pointer(cpufreq_driver); get = driver->get; target = driver->target; rcu_read_unlock(); if (get) { policy.cur = get(cpu); if (cpufreq_driver->get) { policy.cur = cpufreq_driver->get(cpu); if (!data->cur) { pr_debug("Driver did not initialize current freq"); data->cur = policy.cur; } else { if (data->cur != policy.cur && target) if (data->cur != policy.cur && cpufreq_driver->target) cpufreq_out_of_sync(cpu, data->cur, policy.cur); } Loading Loading @@ -2020,19 +1884,18 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) driver_data->flags |= CPUFREQ_CONST_LOOPS; write_lock_irqsave(&cpufreq_driver_lock, flags); if (rcu_access_pointer(cpufreq_driver)) { if (cpufreq_driver) { write_unlock_irqrestore(&cpufreq_driver_lock, flags); return -EBUSY; } rcu_assign_pointer(cpufreq_driver, driver_data); cpufreq_driver = driver_data; write_unlock_irqrestore(&cpufreq_driver_lock, flags); synchronize_rcu(); ret = subsys_interface_register(&cpufreq_interface); if (ret) goto err_null_driver; if (!(driver_data->flags & CPUFREQ_STICKY)) { if (!(cpufreq_driver->flags & CPUFREQ_STICKY)) { int i; ret = -ENODEV; Loading @@ -2059,9 +1922,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) subsys_interface_unregister(&cpufreq_interface); err_null_driver: write_lock_irqsave(&cpufreq_driver_lock, flags); rcu_assign_pointer(cpufreq_driver, NULL); cpufreq_driver = NULL; write_unlock_irqrestore(&cpufreq_driver_lock, flags); synchronize_rcu(); return ret; } EXPORT_SYMBOL_GPL(cpufreq_register_driver); Loading @@ -2078,15 +1940,9 @@ EXPORT_SYMBOL_GPL(cpufreq_register_driver); int cpufreq_unregister_driver(struct cpufreq_driver *driver) { unsigned long flags; struct cpufreq_driver *old_driver; rcu_read_lock(); old_driver = rcu_access_pointer(cpufreq_driver); if (!old_driver || (driver != old_driver)) { rcu_read_unlock(); if (!cpufreq_driver || (driver != cpufreq_driver)) return -EINVAL; } rcu_read_unlock(); pr_debug("unregistering driver %s\n", driver->name); Loading @@ -2094,9 +1950,8 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) unregister_hotcpu_notifier(&cpufreq_cpu_notifier); write_lock_irqsave(&cpufreq_driver_lock, flags); rcu_assign_pointer(cpufreq_driver, NULL); cpufreq_driver = NULL; write_unlock_irqrestore(&cpufreq_driver_lock, flags); synchronize_rcu(); return 0; } Loading