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

Commit 7f6c69dc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq:
  [CPUFREQ] Make acpi-cpufreq more robust against BIOS freq changes behind our back.
  [CPUFREQ] change cpu freq tables to per_cpu variables
  [CPUFREQ] fix show_trans_table
  [CPUFREQ] Warn when cpufreq_register_notifier called before pure initcalls
  [CPUFREQ] Refactor locking in cpufreq_add_dev
  [CPUFREQ] more CodingStyle
  [CPUFREQ] CodingStyle
  [CPUFREQ] Slightly shorten the error paths of cpufreq_suspend/cpufreq_resume
parents 1e5ad9a3 e56a727b
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -339,6 +339,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
{
{
	struct acpi_cpufreq_data *data = per_cpu(drv_data, cpu);
	struct acpi_cpufreq_data *data = per_cpu(drv_data, cpu);
	unsigned int freq;
	unsigned int freq;
	unsigned int cached_freq;


	dprintk("get_cur_freq_on_cpu (%d)\n", cpu);
	dprintk("get_cur_freq_on_cpu (%d)\n", cpu);


@@ -347,7 +348,16 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
		return 0;
		return 0;
	}
	}


	cached_freq = data->freq_table[data->acpi_data->state].frequency;
	freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
	freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data);
	if (freq != cached_freq) {
		/*
		 * The dreaded BIOS frequency change behind our back.
		 * Force set the frequency on next target call.
		 */
		data->resume = 1;
	}

	dprintk("cur freq = %u\n", freq);
	dprintk("cur freq = %u\n", freq);


	return freq;
	return freq;
+16 −14
Original line number Original line Diff line number Diff line
@@ -97,7 +97,7 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr)
#define CPUFREQ_THERMAL_MIN_STEP 0
#define CPUFREQ_THERMAL_MIN_STEP 0
#define CPUFREQ_THERMAL_MAX_STEP 3
#define CPUFREQ_THERMAL_MAX_STEP 3


static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS];
static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg);
static unsigned int acpi_thermal_cpufreq_is_init = 0;
static unsigned int acpi_thermal_cpufreq_is_init = 0;


static int cpu_has_cpufreq(unsigned int cpu)
static int cpu_has_cpufreq(unsigned int cpu)
@@ -113,9 +113,9 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu)
	if (!cpu_has_cpufreq(cpu))
	if (!cpu_has_cpufreq(cpu))
		return -ENODEV;
		return -ENODEV;


	if (cpufreq_thermal_reduction_pctg[cpu] <
	if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) <
		CPUFREQ_THERMAL_MAX_STEP) {
		CPUFREQ_THERMAL_MAX_STEP) {
		cpufreq_thermal_reduction_pctg[cpu]++;
		per_cpu(cpufreq_thermal_reduction_pctg, cpu)++;
		cpufreq_update_policy(cpu);
		cpufreq_update_policy(cpu);
		return 0;
		return 0;
	}
	}
@@ -128,14 +128,14 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
	if (!cpu_has_cpufreq(cpu))
	if (!cpu_has_cpufreq(cpu))
		return -ENODEV;
		return -ENODEV;


	if (cpufreq_thermal_reduction_pctg[cpu] >
	if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) >
		(CPUFREQ_THERMAL_MIN_STEP + 1))
		(CPUFREQ_THERMAL_MIN_STEP + 1))
		cpufreq_thermal_reduction_pctg[cpu]--;
		per_cpu(cpufreq_thermal_reduction_pctg, cpu)--;
	else
	else
		cpufreq_thermal_reduction_pctg[cpu] = 0;
		per_cpu(cpufreq_thermal_reduction_pctg, cpu) = 0;
	cpufreq_update_policy(cpu);
	cpufreq_update_policy(cpu);
	/* We reached max freq again and can leave passive mode */
	/* We reached max freq again and can leave passive mode */
	return !cpufreq_thermal_reduction_pctg[cpu];
	return !per_cpu(cpufreq_thermal_reduction_pctg, cpu);
}
}


static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
@@ -147,9 +147,10 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
	if (event != CPUFREQ_ADJUST)
	if (event != CPUFREQ_ADJUST)
		goto out;
		goto out;


	max_freq =
	max_freq = (
	    (policy->cpuinfo.max_freq *
	    policy->cpuinfo.max_freq *
	     (100 - cpufreq_thermal_reduction_pctg[policy->cpu] * 20)) / 100;
	    (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20)
	) / 100;


	cpufreq_verify_within_limits(policy, 0, max_freq);
	cpufreq_verify_within_limits(policy, 0, max_freq);


@@ -174,7 +175,7 @@ static int cpufreq_get_cur_state(unsigned int cpu)
	if (!cpu_has_cpufreq(cpu))
	if (!cpu_has_cpufreq(cpu))
		return 0;
		return 0;


	return cpufreq_thermal_reduction_pctg[cpu];
	return per_cpu(cpufreq_thermal_reduction_pctg, cpu);
}
}


static int cpufreq_set_cur_state(unsigned int cpu, int state)
static int cpufreq_set_cur_state(unsigned int cpu, int state)
@@ -182,7 +183,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state)
	if (!cpu_has_cpufreq(cpu))
	if (!cpu_has_cpufreq(cpu))
		return 0;
		return 0;


	cpufreq_thermal_reduction_pctg[cpu] = state;
	per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state;
	cpufreq_update_policy(cpu);
	cpufreq_update_policy(cpu);
	return 0;
	return 0;
}
}
@@ -191,8 +192,9 @@ void acpi_thermal_cpufreq_init(void)
{
{
	int i;
	int i;


	for (i = 0; i < NR_CPUS; i++)
	for (i = 0; i < nr_cpu_ids; i++)
		cpufreq_thermal_reduction_pctg[i] = 0;
		if (cpu_present(i))
			per_cpu(cpufreq_thermal_reduction_pctg, i) = 0;


	i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
	i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
				      CPUFREQ_POLICY_NOTIFIER);
				      CPUFREQ_POLICY_NOTIFIER);
+57 −72
Original line number Original line Diff line number Diff line
@@ -118,9 +118,11 @@ static void handle_update(struct work_struct *work);
static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list);
static struct srcu_notifier_head cpufreq_transition_notifier_list;
static struct srcu_notifier_head cpufreq_transition_notifier_list;


static bool init_cpufreq_transition_notifier_list_called;
static int __init init_cpufreq_transition_notifier_list(void)
static int __init init_cpufreq_transition_notifier_list(void)
{
{
	srcu_init_notifier_head(&cpufreq_transition_notifier_list);
	srcu_init_notifier_head(&cpufreq_transition_notifier_list);
	init_cpufreq_transition_notifier_list_called = true;
	return 0;
	return 0;
}
}
pure_initcall(init_cpufreq_transition_notifier_list);
pure_initcall(init_cpufreq_transition_notifier_list);
@@ -503,8 +505,7 @@ static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy,
/**
/**
 * show_scaling_governor - show the current policy for the specified CPU
 * show_scaling_governor - show the current policy for the specified CPU
 */
 */
static ssize_t show_scaling_governor (struct cpufreq_policy * policy,
static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
							char *buf)
{
{
	if(policy->policy == CPUFREQ_POLICY_POWERSAVE)
	if(policy->policy == CPUFREQ_POLICY_POWERSAVE)
		return sprintf(buf, "powersave\n");
		return sprintf(buf, "powersave\n");
@@ -800,7 +801,6 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
	ret = cpufreq_driver->init(policy);
	ret = cpufreq_driver->init(policy);
	if (ret) {
	if (ret) {
		dprintk("initialization failed\n");
		dprintk("initialization failed\n");
		unlock_policy_rwsem_write(cpu);
		goto err_out;
		goto err_out;
	}
	}
	policy->user_policy.min = policy->cpuinfo.min_freq;
	policy->user_policy.min = policy->cpuinfo.min_freq;
@@ -823,7 +823,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
		/* check for existing affected CPUs.  They may not be aware
		/* check for existing affected CPUs.  They may not be aware
		 * of it due to CPU Hotplug.
		 * of it due to CPU Hotplug.
		 */
		 */
		managed_policy = cpufreq_cpu_get(j);
		managed_policy = cpufreq_cpu_get(j);		// FIXME: Where is this released?  What about error paths?
		if (unlikely(managed_policy)) {
		if (unlikely(managed_policy)) {


			/* Set proper policy_cpu */
			/* Set proper policy_cpu */
@@ -842,14 +842,11 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
			ret = sysfs_create_link(&sys_dev->kobj,
			ret = sysfs_create_link(&sys_dev->kobj,
						&managed_policy->kobj,
						&managed_policy->kobj,
						"cpufreq");
						"cpufreq");
			if (ret) {
			if (ret)
				unlock_policy_rwsem_write(cpu);
				goto err_out_driver_exit;
				goto err_out_driver_exit;
			}


			cpufreq_debug_enable_ratelimit();
			cpufreq_debug_enable_ratelimit();
			ret = 0;
			ret = 0;
			unlock_policy_rwsem_write(cpu);
			goto err_out_driver_exit; /* call driver->exit() */
			goto err_out_driver_exit; /* call driver->exit() */
		}
		}
	}
	}
@@ -859,34 +856,27 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
	/* prepare interface data */
	/* prepare interface data */
	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
				   "cpufreq");
				   "cpufreq");
	if (ret) {
	if (ret)
		unlock_policy_rwsem_write(cpu);
		goto err_out_driver_exit;
		goto err_out_driver_exit;
	}

	/* set up files for this cpu device */
	/* set up files for this cpu device */
	drv_attr = cpufreq_driver->attr;
	drv_attr = cpufreq_driver->attr;
	while ((drv_attr) && (*drv_attr)) {
	while ((drv_attr) && (*drv_attr)) {
		ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
		ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
		if (ret) {
		if (ret)
			unlock_policy_rwsem_write(cpu);
			goto err_out_driver_exit;
			goto err_out_driver_exit;
		}
		drv_attr++;
		drv_attr++;
	}
	}
	if (cpufreq_driver->get) {
	if (cpufreq_driver->get) {
		ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
		ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
		if (ret) {
		if (ret)
			unlock_policy_rwsem_write(cpu);
			goto err_out_driver_exit;
			goto err_out_driver_exit;
	}
	}
	}
	if (cpufreq_driver->target) {
	if (cpufreq_driver->target) {
		ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
		ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
		if (ret) {
		if (ret)
			unlock_policy_rwsem_write(cpu);
			goto err_out_driver_exit;
			goto err_out_driver_exit;
	}
	}
	}


	spin_lock_irqsave(&cpufreq_driver_lock, flags);
	spin_lock_irqsave(&cpufreq_driver_lock, flags);
	for_each_cpu_mask(j, policy->cpus) {
	for_each_cpu_mask(j, policy->cpus) {
@@ -907,11 +897,9 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
		cpu_sys_dev = get_cpu_sysdev(j);
		cpu_sys_dev = get_cpu_sysdev(j);
		ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
		ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
					"cpufreq");
					"cpufreq");
		if (ret) {
		if (ret)
			unlock_policy_rwsem_write(cpu);
			goto err_out_unregister;
			goto err_out_unregister;
	}
	}
	}


	policy->governor = NULL; /* to assure that the starting sequence is
	policy->governor = NULL; /* to assure that the starting sequence is
				  * run in cpufreq_set_policy */
				  * run in cpufreq_set_policy */
@@ -950,6 +938,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
		cpufreq_driver->exit(policy);
		cpufreq_driver->exit(policy);


err_out:
err_out:
	unlock_policy_rwsem_write(cpu);
	kfree(policy);
	kfree(policy);


nomem_out:
nomem_out:
@@ -1138,7 +1127,7 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
		cpufreq_cpu_put(policy);
		cpufreq_cpu_put(policy);
	}
	}


	return (ret_freq);
	return ret_freq;
}
}
EXPORT_SYMBOL(cpufreq_quick_get);
EXPORT_SYMBOL(cpufreq_quick_get);


@@ -1149,7 +1138,7 @@ static unsigned int __cpufreq_get(unsigned int cpu)
	unsigned int ret_freq = 0;
	unsigned int ret_freq = 0;


	if (!cpufreq_driver->get)
	if (!cpufreq_driver->get)
		return (ret_freq);
		return ret_freq;


	ret_freq = cpufreq_driver->get(cpu);
	ret_freq = cpufreq_driver->get(cpu);


@@ -1163,7 +1152,7 @@ static unsigned int __cpufreq_get(unsigned int cpu)
		}
		}
	}
	}


	return (ret_freq);
	return ret_freq;
}
}


/**
/**
@@ -1190,7 +1179,7 @@ unsigned int cpufreq_get(unsigned int cpu)
out_policy:
out_policy:
	cpufreq_cpu_put(policy);
	cpufreq_cpu_put(policy);
out:
out:
	return (ret_freq);
	return ret_freq;
}
}
EXPORT_SYMBOL(cpufreq_get);
EXPORT_SYMBOL(cpufreq_get);


@@ -1221,22 +1210,18 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)
		return -EINVAL;
		return -EINVAL;


	/* only handle each CPU group once */
	/* only handle each CPU group once */
	if (unlikely(cpu_policy->cpu != cpu)) {
	if (unlikely(cpu_policy->cpu != cpu))
		cpufreq_cpu_put(cpu_policy);
		goto out;
		return 0;
	}


	if (cpufreq_driver->suspend) {
	if (cpufreq_driver->suspend) {
		ret = cpufreq_driver->suspend(cpu_policy, pmsg);
		ret = cpufreq_driver->suspend(cpu_policy, pmsg);
		if (ret) {
		if (ret) {
			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
					"step on CPU %u\n", cpu_policy->cpu);
					"step on CPU %u\n", cpu_policy->cpu);
			cpufreq_cpu_put(cpu_policy);
			goto out;
			return ret;
		}
		}
	}
	}



	if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)
	if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)
		goto out;
		goto out;


@@ -1270,7 +1255,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg)


out:
out:
	cpufreq_cpu_put(cpu_policy);
	cpufreq_cpu_put(cpu_policy);
	return 0;
	return ret;
}
}


/**
/**
@@ -1302,18 +1287,15 @@ static int cpufreq_resume(struct sys_device * sysdev)
		return -EINVAL;
		return -EINVAL;


	/* only handle each CPU group once */
	/* only handle each CPU group once */
	if (unlikely(cpu_policy->cpu != cpu)) {
	if (unlikely(cpu_policy->cpu != cpu))
		cpufreq_cpu_put(cpu_policy);
		goto fail;
		return 0;
	}


	if (cpufreq_driver->resume) {
	if (cpufreq_driver->resume) {
		ret = cpufreq_driver->resume(cpu_policy);
		ret = cpufreq_driver->resume(cpu_policy);
		if (ret) {
		if (ret) {
			printk(KERN_ERR "cpufreq: resume failed in ->resume "
			printk(KERN_ERR "cpufreq: resume failed in ->resume "
					"step on CPU %u\n", cpu_policy->cpu);
					"step on CPU %u\n", cpu_policy->cpu);
			cpufreq_cpu_put(cpu_policy);
			goto fail;
			return ret;
		}
		}
	}
	}


@@ -1353,6 +1335,7 @@ static int cpufreq_resume(struct sys_device * sysdev)


out:
out:
	schedule_work(&cpu_policy->update);
	schedule_work(&cpu_policy->update);
fail:
	cpufreq_cpu_put(cpu_policy);
	cpufreq_cpu_put(cpu_policy);
	return ret;
	return ret;
}
}
@@ -1386,6 +1369,8 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
{
{
	int ret;
	int ret;


	WARN_ON(!init_cpufreq_transition_notifier_list_called);

	switch (list) {
	switch (list) {
	case CPUFREQ_TRANSITION_NOTIFIER:
	case CPUFREQ_TRANSITION_NOTIFIER:
		ret = srcu_notifier_chain_register(
		ret = srcu_notifier_chain_register(
@@ -1848,7 +1833,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
		cpufreq_debug_enable_ratelimit();
		cpufreq_debug_enable_ratelimit();
	}
	}


	return (ret);
	return ret;
}
}
EXPORT_SYMBOL_GPL(cpufreq_register_driver);
EXPORT_SYMBOL_GPL(cpufreq_register_driver);


+5 −1
Original line number Original line Diff line number Diff line
@@ -114,7 +114,7 @@ show_trans_table(struct cpufreq_policy *policy, char *buf)
				stat->freq_table[i]);
				stat->freq_table[i]);
	}
	}
	if (len >= PAGE_SIZE)
	if (len >= PAGE_SIZE)
		return len;
		return PAGE_SIZE;


	len += snprintf(buf + len, PAGE_SIZE - len, "\n");
	len += snprintf(buf + len, PAGE_SIZE - len, "\n");


@@ -131,8 +131,12 @@ show_trans_table(struct cpufreq_policy *policy, char *buf)
			len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
			len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
					stat->trans_table[i*stat->max_state+j]);
					stat->trans_table[i*stat->max_state+j]);
		}
		}
		if (len >= PAGE_SIZE)
			break;
		len += snprintf(buf + len, PAGE_SIZE - len, "\n");
		len += snprintf(buf + len, PAGE_SIZE - len, "\n");
	}
	}
	if (len >= PAGE_SIZE)
		return PAGE_SIZE;
	return len;
	return len;
}
}
CPUFREQ_STATDEVICE_ATTR(trans_table,0444,show_trans_table);
CPUFREQ_STATDEVICE_ATTR(trans_table,0444,show_trans_table);