Commit cf3c8f84 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull more power manadement updates from Rafael Wysocki:
 "Prevent cpufreq from creating excessively large stack frames and fix
  the handling of devices deleted during system-wide resume in the PM
  core (Rafael Wysocki), revert a problematic commit affecting the
  cpupower utility and correct its man page (Thomas Renninger,
  Brahadambal Srinivasan), and improve the intel_pstate_tracer utility
  (Doug Smythies)"

* tag 'pm-5.6-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  tools/power/x86/intel_pstate_tracer: change several graphs to autoscale y-axis
  tools/power/x86/intel_pstate_tracer: changes for python 3 compatibility
  Correction to manpage of cpupower
  cpufreq: Avoid creating excessively large stack frames
  PM: core: Fix handling of devices deleted during system-wide resume
  cpupower: Revert library ABI changes from commit ae291709
parents a62aa6f7 82b2c6ff
Loading
Loading
Loading
Loading
+37 −5
Original line number Diff line number Diff line
@@ -273,10 +273,38 @@ static void dpm_wait_for_suppliers(struct device *dev, bool async)
	device_links_read_unlock(idx);
}

static void dpm_wait_for_superior(struct device *dev, bool async)
static bool dpm_wait_for_superior(struct device *dev, bool async)
{
	dpm_wait(dev->parent, async);
	struct device *parent;

	/*
	 * If the device is resumed asynchronously and the parent's callback
	 * deletes both the device and the parent itself, the parent object may
	 * be freed while this function is running, so avoid that by reference
	 * counting the parent once more unless the device has been deleted
	 * already (in which case return right away).
	 */
	mutex_lock(&dpm_list_mtx);

	if (!device_pm_initialized(dev)) {
		mutex_unlock(&dpm_list_mtx);
		return false;
	}

	parent = get_device(dev->parent);

	mutex_unlock(&dpm_list_mtx);

	dpm_wait(parent, async);
	put_device(parent);

	dpm_wait_for_suppliers(dev, async);

	/*
	 * If the parent's callback has deleted the device, attempting to resume
	 * it would be invalid, so avoid doing that then.
	 */
	return device_pm_initialized(dev);
}

static void dpm_wait_for_consumers(struct device *dev, bool async)
@@ -621,7 +649,8 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn
	if (!dev->power.is_noirq_suspended)
		goto Out;

	dpm_wait_for_superior(dev, async);
	if (!dpm_wait_for_superior(dev, async))
		goto Out;

	skip_resume = dev_pm_may_skip_resume(dev);

@@ -829,7 +858,8 @@ static int device_resume_early(struct device *dev, pm_message_t state, bool asyn
	if (!dev->power.is_late_suspended)
		goto Out;

	dpm_wait_for_superior(dev, async);
	if (!dpm_wait_for_superior(dev, async))
		goto Out;

	callback = dpm_subsys_resume_early_cb(dev, state, &info);

@@ -944,7 +974,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
		goto Complete;
	}

	dpm_wait_for_superior(dev, async);
	if (!dpm_wait_for_superior(dev, async))
		goto Complete;

	dpm_watchdog_set(&wd, dev);
	device_lock(dev);

+1 −1
Original line number Diff line number Diff line
@@ -221,7 +221,7 @@ static int cppc_cpufreq_set_target(struct cpufreq_policy *policy,
	return ret;
}

static int cppc_verify_policy(struct cpufreq_policy *policy)
static int cppc_verify_policy(struct cpufreq_policy_data *policy)
{
	cpufreq_verify_within_cpu_limits(policy);
	return 0;
+1 −1
Original line number Diff line number Diff line
@@ -291,7 +291,7 @@ static int nforce2_target(struct cpufreq_policy *policy,
 * nforce2_verify - verifies a new CPUFreq policy
 * @policy: new policy
 */
static int nforce2_verify(struct cpufreq_policy *policy)
static int nforce2_verify(struct cpufreq_policy_data *policy)
{
	unsigned int fsb_pol_max;

+70 −77
Original line number Diff line number Diff line
@@ -74,6 +74,9 @@ static void cpufreq_exit_governor(struct cpufreq_policy *policy);
static int cpufreq_start_governor(struct cpufreq_policy *policy);
static void cpufreq_stop_governor(struct cpufreq_policy *policy);
static void cpufreq_governor_limits(struct cpufreq_policy *policy);
static int cpufreq_set_policy(struct cpufreq_policy *policy,
			      struct cpufreq_governor *new_gov,
			      unsigned int new_pol);

/**
 * Two notifier lists: the "policy" list is involved in the
@@ -616,25 +619,22 @@ static struct cpufreq_governor *find_governor(const char *str_governor)
	return NULL;
}

static int cpufreq_parse_policy(char *str_governor,
				struct cpufreq_policy *policy)
static unsigned int cpufreq_parse_policy(char *str_governor)
{
	if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
		policy->policy = CPUFREQ_POLICY_PERFORMANCE;
		return 0;
	}
	if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
		policy->policy = CPUFREQ_POLICY_POWERSAVE;
		return 0;
	}
	return -EINVAL;
	if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN))
		return CPUFREQ_POLICY_PERFORMANCE;

	if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN))
		return CPUFREQ_POLICY_POWERSAVE;

	return CPUFREQ_POLICY_UNKNOWN;
}

/**
 * cpufreq_parse_governor - parse a governor string only for has_target()
 * @str_governor: Governor name.
 */
static int cpufreq_parse_governor(char *str_governor,
				  struct cpufreq_policy *policy)
static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor)
{
	struct cpufreq_governor *t;

@@ -648,7 +648,7 @@ static int cpufreq_parse_governor(char *str_governor,

		ret = request_module("cpufreq_%s", str_governor);
		if (ret)
			return -EINVAL;
			return NULL;

		mutex_lock(&cpufreq_governor_mutex);

@@ -659,12 +659,7 @@ static int cpufreq_parse_governor(char *str_governor,

	mutex_unlock(&cpufreq_governor_mutex);

	if (t) {
		policy->governor = t;
		return 0;
	}

	return -EINVAL;
	return t;
}

/**
@@ -765,28 +760,33 @@ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
					const char *buf, size_t count)
{
	int ret;
	char str_governor[16];
	struct cpufreq_policy new_policy;

	memcpy(&new_policy, policy, sizeof(*policy));
	int ret;

	ret = sscanf(buf, "%15s", str_governor);
	if (ret != 1)
		return -EINVAL;

	if (cpufreq_driver->setpolicy) {
		if (cpufreq_parse_policy(str_governor, &new_policy))
		unsigned int new_pol;

		new_pol = cpufreq_parse_policy(str_governor);
		if (!new_pol)
			return -EINVAL;

		ret = cpufreq_set_policy(policy, NULL, new_pol);
	} else {
		if (cpufreq_parse_governor(str_governor, &new_policy))
		struct cpufreq_governor *new_gov;

		new_gov = cpufreq_parse_governor(str_governor);
		if (!new_gov)
			return -EINVAL;
	}

	ret = cpufreq_set_policy(policy, &new_policy);
		ret = cpufreq_set_policy(policy, new_gov,
					 CPUFREQ_POLICY_UNKNOWN);

	if (new_policy.governor)
		module_put(new_policy.governor->owner);
		module_put(new_gov->owner);
	}

	return ret ? ret : count;
}
@@ -1053,40 +1053,33 @@ __weak struct cpufreq_governor *cpufreq_default_governor(void)

static int cpufreq_init_policy(struct cpufreq_policy *policy)
{
	struct cpufreq_governor *gov = NULL, *def_gov = NULL;
	struct cpufreq_policy new_policy;

	memcpy(&new_policy, policy, sizeof(*policy));

	def_gov = cpufreq_default_governor();
	struct cpufreq_governor *def_gov = cpufreq_default_governor();
	struct cpufreq_governor *gov = NULL;
	unsigned int pol = CPUFREQ_POLICY_UNKNOWN;

	if (has_target()) {
		/*
		 * Update governor of new_policy to the governor used before
		 * hotplug
		 */
		/* Update policy governor to the one used before hotplug. */
		gov = find_governor(policy->last_governor);
		if (gov) {
			pr_debug("Restoring governor %s for cpu %d\n",
				 policy->governor->name, policy->cpu);
		} else if (def_gov) {
			gov = def_gov;
		} else {
			if (!def_gov)
			return -ENODATA;
			gov = def_gov;
		}
		new_policy.governor = gov;
	} else {
		/* Use the default policy if there is no last_policy. */
		if (policy->last_policy) {
			new_policy.policy = policy->last_policy;
			pol = policy->last_policy;
		} else if (def_gov) {
			pol = cpufreq_parse_policy(def_gov->name);
		} else {
			if (!def_gov)
			return -ENODATA;
			cpufreq_parse_policy(def_gov->name, &new_policy);
		}
	}

	return cpufreq_set_policy(policy, &new_policy);
	return cpufreq_set_policy(policy, gov, pol);
}

static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
@@ -1114,13 +1107,10 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp

void refresh_frequency_limits(struct cpufreq_policy *policy)
{
	struct cpufreq_policy new_policy;

	if (!policy_is_inactive(policy)) {
		new_policy = *policy;
		pr_debug("updating policy for CPU %u\n", policy->cpu);

		cpufreq_set_policy(policy, &new_policy);
		cpufreq_set_policy(policy, policy->governor, policy->policy);
	}
}
EXPORT_SYMBOL(refresh_frequency_limits);
@@ -2364,46 +2354,49 @@ EXPORT_SYMBOL(cpufreq_get_policy);
/**
 * cpufreq_set_policy - Modify cpufreq policy parameters.
 * @policy: Policy object to modify.
 * @new_policy: New policy data.
 * @new_gov: Policy governor pointer.
 * @new_pol: Policy value (for drivers with built-in governors).
 *
 * Pass @new_policy to the cpufreq driver's ->verify() callback. Next, copy the
 * min and max parameters of @new_policy to @policy and either invoke the
 * driver's ->setpolicy() callback (if present) or carry out a governor update
 * for @policy.  That is, run the current governor's ->limits() callback (if the
 * governor field in @new_policy points to the same object as the one in
 * @policy) or replace the governor for @policy with the new one stored in
 * @new_policy.
 * Invoke the cpufreq driver's ->verify() callback to sanity-check the frequency
 * limits to be set for the policy, update @policy with the verified limits
 * values and either invoke the driver's ->setpolicy() callback (if present) or
 * carry out a governor update for @policy.  That is, run the current governor's
 * ->limits() callback (if @new_gov points to the same object as the one in
 * @policy) or replace the governor for @policy with @new_gov.
 *
 * The cpuinfo part of @policy is not updated by this function.
 */
int cpufreq_set_policy(struct cpufreq_policy *policy,
		       struct cpufreq_policy *new_policy)
static int cpufreq_set_policy(struct cpufreq_policy *policy,
			      struct cpufreq_governor *new_gov,
			      unsigned int new_pol)
{
	struct cpufreq_policy_data new_data;
	struct cpufreq_governor *old_gov;
	int ret;

	pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
		 new_policy->cpu, new_policy->min, new_policy->max);

	memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));

	memcpy(&new_data.cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
	new_data.freq_table = policy->freq_table;
	new_data.cpu = policy->cpu;
	/*
	 * PM QoS framework collects all the requests from users and provide us
	 * the final aggregated value here.
	 */
	new_policy->min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN);
	new_policy->max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX);
	new_data.min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN);
	new_data.max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX);

	pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
		 new_data.cpu, new_data.min, new_data.max);

	/*
	 * Verify that the CPU speed can be set within these limits and make sure
	 * that min <= max.
	 */
	ret = cpufreq_driver->verify(new_policy);
	ret = cpufreq_driver->verify(&new_data);
	if (ret)
		return ret;

	policy->min = new_policy->min;
	policy->max = new_policy->max;
	policy->min = new_data.min;
	policy->max = new_data.max;
	trace_cpu_frequency_limits(policy);

	policy->cached_target_freq = UINT_MAX;
@@ -2412,12 +2405,12 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
		 policy->min, policy->max);

	if (cpufreq_driver->setpolicy) {
		policy->policy = new_policy->policy;
		policy->policy = new_pol;
		pr_debug("setting range\n");
		return cpufreq_driver->setpolicy(policy);
	}

	if (new_policy->governor == policy->governor) {
	if (new_gov == policy->governor) {
		pr_debug("governor limits update\n");
		cpufreq_governor_limits(policy);
		return 0;
@@ -2434,7 +2427,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
	}

	/* start new governor */
	policy->governor = new_policy->governor;
	policy->governor = new_gov;
	ret = cpufreq_init_governor(policy);
	if (!ret) {
		ret = cpufreq_start_governor(policy);
+2 −2
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
		return 0;
}

int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy,
				   struct cpufreq_frequency_table *table)
{
	struct cpufreq_frequency_table *pos;
@@ -100,7 +100,7 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
 * Generic routine to verify policy & frequency table, requires driver to set
 * policy->freq_table prior to it.
 */
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy)
{
	if (!policy->freq_table)
		return -ENODEV;
Loading