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

Commit 46e1d5e9 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branches 'pm-cpufreq-fixes' and 'pm-cpuidle-fixes'

* pm-cpufreq-fixes:
  cpufreq: Fix creation of symbolic links to policy directories

* pm-cpuidle-fixes:
  cpuidle: powernv: Pass correct drv->cpumask for registration
Loading
Loading
Loading
Loading
+21 −17
Original line number Diff line number Diff line
@@ -918,11 +918,19 @@ static struct kobj_type ktype_cpufreq = {
	.release	= cpufreq_sysfs_release,
};

static int add_cpu_dev_symlink(struct cpufreq_policy *policy,
			       struct device *dev)
static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu)
{
	struct device *dev = get_cpu_device(cpu);

	if (!dev)
		return;

	if (cpumask_test_and_set_cpu(cpu, policy->real_cpus))
		return;

	dev_dbg(dev, "%s: Adding symlink\n", __func__);
	return sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq");
	if (sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"))
		dev_err(dev, "cpufreq symlink creation failed\n");
}

static void remove_cpu_dev_symlink(struct cpufreq_policy *policy,
@@ -1180,10 +1188,10 @@ static int cpufreq_online(unsigned int cpu)
		policy->user_policy.min = policy->min;
		policy->user_policy.max = policy->max;

		write_lock_irqsave(&cpufreq_driver_lock, flags);
		for_each_cpu(j, policy->related_cpus)
		for_each_cpu(j, policy->related_cpus) {
			per_cpu(cpufreq_cpu_data, j) = policy;
		write_unlock_irqrestore(&cpufreq_driver_lock, flags);
			add_cpu_dev_symlink(policy, j);
		}
	} else {
		policy->min = policy->user_policy.min;
		policy->max = policy->user_policy.max;
@@ -1275,13 +1283,15 @@ static int cpufreq_online(unsigned int cpu)

	if (cpufreq_driver->exit)
		cpufreq_driver->exit(policy);

	for_each_cpu(j, policy->real_cpus)
		remove_cpu_dev_symlink(policy, get_cpu_device(j));

out_free_policy:
	cpufreq_policy_free(policy);
	return ret;
}

static int cpufreq_offline(unsigned int cpu);

/**
 * cpufreq_add_dev - the cpufreq interface for a CPU device.
 * @dev: CPU device.
@@ -1303,16 +1313,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)

	/* Create sysfs link on CPU registration */
	policy = per_cpu(cpufreq_cpu_data, cpu);
	if (!policy || cpumask_test_and_set_cpu(cpu, policy->real_cpus))
		return 0;

	ret = add_cpu_dev_symlink(policy, dev);
	if (ret) {
		cpumask_clear_cpu(cpu, policy->real_cpus);
		cpufreq_offline(cpu);
	}
	if (policy)
		add_cpu_dev_symlink(policy, cpu);

	return ret;
	return 0;
}

static int cpufreq_offline(unsigned int cpu)
+18 −0
Original line number Diff line number Diff line
@@ -175,6 +175,24 @@ static int powernv_cpuidle_driver_init(void)
		drv->state_count += 1;
	}

	/*
	 * On the PowerNV platform cpu_present may be less than cpu_possible in
	 * cases when firmware detects the CPU, but it is not available to the
	 * OS.  If CONFIG_HOTPLUG_CPU=n, then such CPUs are not hotplugable at
	 * run time and hence cpu_devices are not created for those CPUs by the
	 * generic topology_init().
	 *
	 * drv->cpumask defaults to cpu_possible_mask in
	 * __cpuidle_driver_init().  This breaks cpuidle on PowerNV where
	 * cpu_devices are not created for CPUs in cpu_possible_mask that
	 * cannot be hot-added later at run time.
	 *
	 * Trying cpuidle_register_device() on a CPU without a cpu_device is
	 * incorrect, so pass a correct CPU mask to the generic cpuidle driver.
	 */

	drv->cpumask = (struct cpumask *)cpu_present_mask;

	return 0;
}