Commit 41f762a1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull more power management updates from Rafael Wysocki:
 "First of all, the adaptive voltage scaling (AVS) drivers go to new
  platform-specific locations as planned (this part was reported to have
  merge conflicts against the new arm-soc updates in linux-next).

  In addition to that, there are some fixes (intel_idle, intel_pstate,
  RAPL, acpi_cpufreq), the addition of on/off notifiers and idle state
  accounting support to the generic power domains (genpd) code and some
  janitorial changes all over.

  Specifics:

   - Move the AVS drivers to new platform-specific locations and get rid
     of the drivers/power/avs directory (Ulf Hansson).

   - Add on/off notifiers and idle state accounting support to the
     generic power domains (genpd) framework (Ulf Hansson, Lina Iyer).

   - Ulf will maintain the PM domain part of cpuidle-psci (Ulf Hansson).

   - Make intel_idle disregard ACPI _CST if it cannot use the data
     returned by that method (Mel Gorman).

   - Modify intel_pstate to avoid leaving useless sysfs directory
     structure behind if it cannot be registered (Chen Yu).

   - Fix domain detection in the RAPL power capping driver and prevent
     it from failing to enumerate the Psys RAPL domain (Zhang Rui).

   - Allow acpi-cpufreq to use ACPI _PSD information with Family 19 and
     later AMD chips (Wei Huang).

   - Update the driver assumptions comment in intel_idle and fix a
     kerneldoc comment in the runtime PM framework (Alexander Monakov,
     Bean Huo).

   - Avoid unnecessary resets of the cached frequency in the schedutil
     cpufreq governor to reduce overhead (Wei Wang).

   - Clean up the cpufreq core a bit (Viresh Kumar).

   - Make assorted minor janitorial changes (Daniel Lezcano, Geert
     Uytterhoeven, Hubert Jasudowicz, Tom Rix).

   - Clean up and optimize the cpupower utility somewhat (Colin Ian
     King, Martin Kaistra)"

* tag 'pm-5.10-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (23 commits)
  PM: sleep: remove unreachable break
  PM: AVS: Drop the avs directory and the corresponding Kconfig
  PM: AVS: qcom-cpr: Move the driver to the qcom specific drivers
  PM: runtime: Fix typo in pm_runtime_set_active() helper comment
  PM: domains: Fix build error for genpd notifiers
  powercap: Fix typo in Kconfig "Plance" -> "Plane"
  cpufreq: schedutil: restore cached freq when next_f is not changed
  acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
  PM: AVS: smartreflex Move driver to soc specific drivers
  PM: AVS: rockchip-io: Move the driver to the rockchip specific drivers
  PM: domains: enable domain idle state accounting
  PM: domains: Add curly braces to delimit comment + statement block
  PM: domains: Add support for PM domain on/off notifiers for genpd
  powercap/intel_rapl: enumerate Psys RAPL domain together with package RAPL domain
  powercap/intel_rapl: Fix domain detection
  intel_idle: Ignore _CST if control cannot be taken from the platform
  cpuidle: Remove pointless stub
  intel_idle: mention assumption that WBINVD is not needed
  MAINTAINERS: Add section for cpuidle-psci PM domain
  cpufreq: intel_pstate: Delete intel_pstate sysfs if failed to register the driver
  ...
parents af995383 41c169d9
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -4585,6 +4585,14 @@ L: linux-arm-kernel@lists.infradead.org
S:	Supported
F:	drivers/cpuidle/cpuidle-psci.c
CPUIDLE DRIVER - ARM PSCI PM DOMAIN
M:	Ulf Hansson <ulf.hansson@linaro.org>
L:	linux-pm@vger.kernel.org
L:	linux-arm-kernel@lists.infradead.org
S:	Supported
F:	drivers/cpuidle/cpuidle-psci.h
F:	drivers/cpuidle/cpuidle-psci-domain.c
CRAMFS FILESYSTEM
M:	Nicolas Pitre <nico@fluxnic.net>
S:	Maintained
@@ -5398,11 +5406,11 @@ F: include/linux/debugfs.h
F:	include/linux/kobj*
F:	lib/kobj*
DRIVERS FOR ADAPTIVE VOLTAGE SCALING (AVS)
DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
M:	Nishanth Menon <nm@ti.com>
L:	linux-pm@vger.kernel.org
S:	Maintained
F:	drivers/power/avs/
F:	drivers/soc/ti/smartreflex.c
F:	include/linux/power/smartreflex.h
DRM DRIVER FOR ALLWINNER DE2 AND DE3 ENGINE
@@ -14459,7 +14467,7 @@ L: linux-pm@vger.kernel.org
L:	linux-arm-msm@vger.kernel.org
S:	Maintained
F:	Documentation/devicetree/bindings/power/avs/qcom,cpr.txt
F:	drivers/power/avs/qcom-cpr.c
F:	drivers/soc/qcom/cpr.c
QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
M:	Ilia Lin <ilia.lin@kernel.org>
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ config OMAP_DEBUG_LEDS

config POWER_AVS_OMAP
	bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2"
	depends on POWER_AVS && (ARCH_OMAP3 || ARCH_OMAP4) && PM
	depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
	select POWER_SUPPLY
	help
	  Say Y to enable AVS(Adaptive Voltage Scaling)
+153 −14
Original line number Diff line number Diff line
@@ -415,26 +415,45 @@ static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
	s64 elapsed_ns;
	int ret;

	/* Notify consumers that we are about to power on. */
	ret = raw_notifier_call_chain_robust(&genpd->power_notifiers,
					     GENPD_NOTIFY_PRE_ON,
					     GENPD_NOTIFY_OFF, NULL);
	ret = notifier_to_errno(ret);
	if (ret)
		return ret;

	if (!genpd->power_on)
		return 0;
		goto out;

	if (!timed) {
		ret = genpd->power_on(genpd);
		if (ret)
			goto err;

	if (!timed)
		return genpd->power_on(genpd);
		goto out;
	}

	time_start = ktime_get();
	ret = genpd->power_on(genpd);
	if (ret)
		return ret;
		goto err;

	elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
	if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns)
		return ret;
		goto out;

	genpd->states[state_idx].power_on_latency_ns = elapsed_ns;
	genpd->max_off_time_changed = true;
	pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
		 genpd->name, "on", elapsed_ns);

out:
	raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
	return 0;
err:
	raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
				NULL);
	return ret;
}

@@ -445,27 +464,46 @@ static int _genpd_power_off(struct generic_pm_domain *genpd, bool timed)
	s64 elapsed_ns;
	int ret;

	/* Notify consumers that we are about to power off. */
	ret = raw_notifier_call_chain_robust(&genpd->power_notifiers,
					     GENPD_NOTIFY_PRE_OFF,
					     GENPD_NOTIFY_ON, NULL);
	ret = notifier_to_errno(ret);
	if (ret)
		return ret;

	if (!genpd->power_off)
		return 0;
		goto out;

	if (!timed)
		return genpd->power_off(genpd);
	if (!timed) {
		ret = genpd->power_off(genpd);
		if (ret)
			goto busy;

		goto out;
	}

	time_start = ktime_get();
	ret = genpd->power_off(genpd);
	if (ret)
		return ret;
		goto busy;

	elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
	if (elapsed_ns <= genpd->states[state_idx].power_off_latency_ns)
		return 0;
		goto out;

	genpd->states[state_idx].power_off_latency_ns = elapsed_ns;
	genpd->max_off_time_changed = true;
	pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
		 genpd->name, "off", elapsed_ns);

out:
	raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF,
				NULL);
	return 0;
busy:
	raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL);
	return ret;
}

/**
@@ -550,11 +588,14 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
		return -EBUSY;

	ret = _genpd_power_off(genpd, true);
	if (ret)
	if (ret) {
		genpd->states[genpd->state_idx].rejected++;
		return ret;
	}

	genpd->status = GENPD_STATE_OFF;
	genpd_update_accounting(genpd);
	genpd->states[genpd->state_idx].usage++;

	list_for_each_entry(link, &genpd->child_links, child_node) {
		genpd_sd_counter_dec(link->parent);
@@ -1270,13 +1311,14 @@ static int genpd_restore_noirq(struct device *dev)
	 * first time for the given domain in the present cycle.
	 */
	genpd_lock(genpd);
	if (genpd->suspended_count++ == 0)
	if (genpd->suspended_count++ == 0) {
		/*
		 * The boot kernel might put the domain into arbitrary state,
		 * so make it appear as powered off to genpd_sync_power_on(),
		 * so that it tries to power it on in case it was really off.
		 */
		genpd->status = GENPD_STATE_OFF;
	}

	genpd_sync_power_on(genpd, true, 0);
	genpd_unlock(genpd);
@@ -1592,6 +1634,101 @@ int pm_genpd_remove_device(struct device *dev)
}
EXPORT_SYMBOL_GPL(pm_genpd_remove_device);

/**
 * dev_pm_genpd_add_notifier - Add a genpd power on/off notifier for @dev
 *
 * @dev: Device that should be associated with the notifier
 * @nb: The notifier block to register
 *
 * Users may call this function to add a genpd power on/off notifier for an
 * attached @dev. Only one notifier per device is allowed. The notifier is
 * sent when genpd is powering on/off the PM domain.
 *
 * It is assumed that the user guarantee that the genpd wouldn't be detached
 * while this routine is getting called.
 *
 * Returns 0 on success and negative error values on failures.
 */
int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb)
{
	struct generic_pm_domain *genpd;
	struct generic_pm_domain_data *gpd_data;
	int ret;

	genpd = dev_to_genpd_safe(dev);
	if (!genpd)
		return -ENODEV;

	if (WARN_ON(!dev->power.subsys_data ||
		     !dev->power.subsys_data->domain_data))
		return -EINVAL;

	gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
	if (gpd_data->power_nb)
		return -EEXIST;

	genpd_lock(genpd);
	ret = raw_notifier_chain_register(&genpd->power_notifiers, nb);
	genpd_unlock(genpd);

	if (ret) {
		dev_warn(dev, "failed to add notifier for PM domain %s\n",
			 genpd->name);
		return ret;
	}

	gpd_data->power_nb = nb;
	return 0;
}
EXPORT_SYMBOL_GPL(dev_pm_genpd_add_notifier);

/**
 * dev_pm_genpd_remove_notifier - Remove a genpd power on/off notifier for @dev
 *
 * @dev: Device that is associated with the notifier
 *
 * Users may call this function to remove a genpd power on/off notifier for an
 * attached @dev.
 *
 * It is assumed that the user guarantee that the genpd wouldn't be detached
 * while this routine is getting called.
 *
 * Returns 0 on success and negative error values on failures.
 */
int dev_pm_genpd_remove_notifier(struct device *dev)
{
	struct generic_pm_domain *genpd;
	struct generic_pm_domain_data *gpd_data;
	int ret;

	genpd = dev_to_genpd_safe(dev);
	if (!genpd)
		return -ENODEV;

	if (WARN_ON(!dev->power.subsys_data ||
		     !dev->power.subsys_data->domain_data))
		return -EINVAL;

	gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
	if (!gpd_data->power_nb)
		return -ENODEV;

	genpd_lock(genpd);
	ret = raw_notifier_chain_unregister(&genpd->power_notifiers,
					    gpd_data->power_nb);
	genpd_unlock(genpd);

	if (ret) {
		dev_warn(dev, "failed to remove notifier for PM domain %s\n",
			 genpd->name);
		return ret;
	}

	gpd_data->power_nb = NULL;
	return 0;
}
EXPORT_SYMBOL_GPL(dev_pm_genpd_remove_notifier);

static int genpd_add_subdomain(struct generic_pm_domain *genpd,
			       struct generic_pm_domain *subdomain)
{
@@ -1762,6 +1899,7 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
	INIT_LIST_HEAD(&genpd->parent_links);
	INIT_LIST_HEAD(&genpd->child_links);
	INIT_LIST_HEAD(&genpd->dev_list);
	RAW_INIT_NOTIFIER_HEAD(&genpd->power_notifiers);
	genpd_lock_init(genpd);
	genpd->gov = gov;
	INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
@@ -2923,7 +3061,7 @@ static int idle_states_show(struct seq_file *s, void *data)
	if (ret)
		return -ERESTARTSYS;

	seq_puts(s, "State          Time Spent(ms)\n");
	seq_puts(s, "State          Time Spent(ms) Usage          Rejected\n");

	for (i = 0; i < genpd->state_count; i++) {
		ktime_t delta = 0;
@@ -2935,7 +3073,8 @@ static int idle_states_show(struct seq_file *s, void *data)

		msecs = ktime_to_ms(
			ktime_add(genpd->states[i].idle_time, delta));
		seq_printf(s, "S%-13i %lld\n", i, msecs);
		seq_printf(s, "S%-13i %-14lld %-14llu %llu\n", i, msecs,
			      genpd->states[i].usage, genpd->states[i].rejected);
	}

	genpd_unlock(genpd);
+0 −1
Original line number Diff line number Diff line
@@ -363,7 +363,6 @@ static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
	case PM_EVENT_THAW:
	case PM_EVENT_RECOVER:
		return ops->thaw;
		break;
	case PM_EVENT_RESTORE:
		return ops->restore;
#endif /* CONFIG_HIBERNATE_CALLBACKS */
+2 −1
Original line number Diff line number Diff line
@@ -691,7 +691,8 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
		cpumask_copy(policy->cpus, topology_core_cpumask(cpu));
	}

	if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
	if (check_amd_hwpstate_cpu(cpu) && boot_cpu_data.x86 < 0x19 &&
	    !acpi_pstate_strict) {
		cpumask_clear(policy->cpus);
		cpumask_set_cpu(cpu, policy->cpus);
		cpumask_copy(data->freqdomain_cpus,
Loading