Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 371deb95 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-cpufreq'

* pm-cpufreq:
  cpufreq: Revert incorrect commit 5800043b
parents 885f925e 1c3d85dd
Loading
Loading
Loading
Loading
+69 −214
Original line number Diff line number Diff line
@@ -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 */
@@ -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);
@@ -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;
}
@@ -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)
@@ -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);

@@ -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"
@@ -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;
@@ -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);
@@ -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);
}

/**
@@ -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))
@@ -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);
	}
@@ -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;
@@ -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) {
@@ -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);
@@ -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);

@@ -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;
@@ -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)
@@ -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;
@@ -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;
@@ -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;
}
@@ -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);

@@ -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);
@@ -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);
@@ -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);
	}
@@ -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) {
@@ -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)) {
@@ -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();
@@ -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);
@@ -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;
@@ -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);
@@ -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);

@@ -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;
@@ -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;
}
@@ -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;
@@ -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);
@@ -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;

@@ -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;

@@ -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 */
@@ -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) {
@@ -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);
		}
@@ -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;

@@ -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);
@@ -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);

@@ -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;
}