Commit 3b4d4c98 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branches 'pm-runtime' and 'pm-powercap'

Merge runtime PM updates and power capping updates for 6.17-rc1:

 - Document return values of suspend-related API functions in the
   runtime PM framework (Sakari Ailus)

 - Mark last busy stamp in multiple autosuspend-related functions in the
   runtime PM framework and update its documentation (Sakari Ailus)

 - Take active children into account in pm_runtime_get_if_in_use() for
   consistency (Rafael Wysocki)

 - Fix NULL pointer dereference in get_pd_power_uw() in the dtpm_cpu
   power capping driver (Sivan Zohar-Kotzer)

 - Add support for the Bartlett Lake platform to the Intel RAPL power
   capping driver (Qiao Wei)

 - Add PL4 support for Panther Lake to the intel_rapl_msr power capping
   driver (Zhang Rui)

* pm-runtime:
  PM: runtime: Take active children into account in pm_runtime_get_if_in_use()
  Documentation: PM: *_autosuspend() functions update last busy time
  PM: runtime: Mark last busy stamp in pm_request_autosuspend()
  PM: runtime: Mark last busy stamp in pm_runtime_autosuspend()
  PM: runtime: Mark last busy stamp in pm_runtime_put_sync_autosuspend()
  PM: runtime: Mark last busy stamp in pm_runtime_put_autosuspend()
  PM: runtime: Document return values of suspend-related API functions

* pm-powercap:
  powercap: dtpm_cpu: Fix NULL pointer dereference in get_pd_power_uw()
  powercap: intel_rapl: Add support for Bartlett Lake platform
  powercap: intel_rapl_msr: Add PL4 support for Panther Lake
Loading
Loading
Loading
Loading
+23 −27
Original line number Diff line number Diff line
@@ -154,11 +154,9 @@ suspending the device are satisfied) and to queue up a suspend request for the
device in that case.  If there is no idle callback, or if the callback returns
0, then the PM core will attempt to carry out a runtime suspend of the device,
also respecting devices configured for autosuspend.  In essence this means a
call to pm_runtime_autosuspend() (do note that drivers needs to update the
device last busy mark, pm_runtime_mark_last_busy(), to control the delay under
this circumstance).  To prevent this (for example, if the callback routine has
started a delayed suspend), the routine must return a non-zero value.  Negative
error return codes are ignored by the PM core.
call to pm_runtime_autosuspend(). To prevent this (for example, if the callback
routine has started a delayed suspend), the routine must return a non-zero
value.  Negative error return codes are ignored by the PM core.

The helper functions provided by the PM core, described in Section 4, guarantee
that the following constraints are met with respect to runtime PM callbacks for
@@ -330,10 +328,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
      'power.disable_depth' is different from 0

  `int pm_runtime_autosuspend(struct device *dev);`
    - same as pm_runtime_suspend() except that the autosuspend delay is taken
      `into account;` if pm_runtime_autosuspend_expiration() says the delay has
      not yet expired then an autosuspend is scheduled for the appropriate time
      and 0 is returned
    - same as pm_runtime_suspend() except that a call to
      pm_runtime_mark_last_busy() is made and an autosuspend is scheduled for
      the appropriate time and 0 is returned

  `int pm_runtime_resume(struct device *dev);`
    - execute the subsystem-level resume callback for the device; returns 0 on
@@ -357,9 +354,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
      success or error code if the request has not been queued up

  `int pm_request_autosuspend(struct device *dev);`
    - schedule the execution of the subsystem-level suspend callback for the
      device when the autosuspend delay has expired; if the delay has already
      expired then the work item is queued up immediately
    - Call pm_runtime_mark_last_busy() and schedule the execution of the
      subsystem-level suspend callback for the device when the autosuspend delay
      expires

  `int pm_schedule_suspend(struct device *dev, unsigned int delay);`
    - schedule the execution of the subsystem-level suspend callback for the
@@ -411,8 +408,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
      pm_request_idle(dev) and return its result

  `int pm_runtime_put_autosuspend(struct device *dev);`
    - does the same as __pm_runtime_put_autosuspend() for now, but in the
      future, will also call pm_runtime_mark_last_busy() as well, DO NOT USE!
    - set the power.last_busy field to the current time and decrement the
      device's usage counter; if the result is 0 then run
      pm_request_autosuspend(dev) and return its result

  `int __pm_runtime_put_autosuspend(struct device *dev);`
    - decrement the device's usage counter; if the result is 0 then run
@@ -427,7 +425,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
      pm_runtime_suspend(dev) and return its result

  `int pm_runtime_put_sync_autosuspend(struct device *dev);`
    - decrement the device's usage counter; if the result is 0 then run
    - set the power.last_busy field to the current time and decrement the
      device's usage counter; if the result is 0 then run
      pm_runtime_autosuspend(dev) and return its result

  `void pm_runtime_enable(struct device *dev);`
@@ -870,11 +869,9 @@ device is automatically suspended (the subsystem or driver still has to call
the appropriate PM routines); rather it means that runtime suspends will
automatically be delayed until the desired period of inactivity has elapsed.

Inactivity is determined based on the power.last_busy field.  Drivers should
call pm_runtime_mark_last_busy() to update this field after carrying out I/O,
typically just before calling __pm_runtime_put_autosuspend().  The desired
length of the inactivity period is a matter of policy.  Subsystems can set this
length initially by calling pm_runtime_set_autosuspend_delay(), but after device
Inactivity is determined based on the power.last_busy field. The desired length
of the inactivity period is a matter of policy.  Subsystems can set this length
initially by calling pm_runtime_set_autosuspend_delay(), but after device
registration the length should be controlled by user space, using the
/sys/devices/.../power/autosuspend_delay_ms attribute.

@@ -885,12 +882,13 @@ instead of the non-autosuspend counterparts::

	Instead of: pm_runtime_suspend    use: pm_runtime_autosuspend;
	Instead of: pm_schedule_suspend   use: pm_request_autosuspend;
	Instead of: pm_runtime_put        use: __pm_runtime_put_autosuspend;
	Instead of: pm_runtime_put        use: pm_runtime_put_autosuspend;
	Instead of: pm_runtime_put_sync   use: pm_runtime_put_sync_autosuspend.

Drivers may also continue to use the non-autosuspend helper functions; they
will behave normally, which means sometimes taking the autosuspend delay into
account (see pm_runtime_idle).
account (see pm_runtime_idle). The autosuspend variants of the functions also
call pm_runtime_mark_last_busy().

Under some circumstances a driver or subsystem may want to prevent a device
from autosuspending immediately, even though the usage counter is zero and the
@@ -922,12 +920,10 @@ Here is a schematic pseudo-code example::
	foo_io_completion(struct foo_priv *foo, void *req)
	{
		lock(&foo->private_lock);
		if (--foo->num_pending_requests == 0) {
			pm_runtime_mark_last_busy(&foo->dev);
			__pm_runtime_put_autosuspend(&foo->dev);
		} else {
		if (--foo->num_pending_requests == 0)
			pm_runtime_put_autosuspend(&foo->dev);
		else
			foo_process_next_request(foo);
		}
		unlock(&foo->private_lock);
		/* Send req result back to the user ... */
	}
+18 −9
Original line number Diff line number Diff line
@@ -1203,10 +1203,12 @@ EXPORT_SYMBOL_GPL(__pm_runtime_resume);
 *
 * Return -EINVAL if runtime PM is disabled for @dev.
 *
 * Otherwise, if the runtime PM status of @dev is %RPM_ACTIVE and either
 * @ign_usage_count is %true or the runtime PM usage counter of @dev is not
 * zero, increment the usage counter of @dev and return 1. Otherwise, return 0
 * without changing the usage counter.
 * Otherwise, if its runtime PM status is %RPM_ACTIVE and (1) @ign_usage_count
 * is set, or (2) @dev is not ignoring children and its active child count is
 * nonero, or (3) the runtime PM usage counter of @dev is not zero, increment
 * the usage counter of @dev and return 1.
 *
 * Otherwise, return 0 without changing the usage counter.
 *
 * If @ign_usage_count is %true, this function can be used to prevent suspending
 * the device when its runtime PM status is %RPM_ACTIVE.
@@ -1228,7 +1230,8 @@ static int pm_runtime_get_conditional(struct device *dev, bool ign_usage_count)
		retval = -EINVAL;
	} else if (dev->power.runtime_status != RPM_ACTIVE) {
		retval = 0;
	} else if (ign_usage_count) {
	} else if (ign_usage_count || (!dev->power.ignore_children &&
		   atomic_read(&dev->power.child_count) > 0)) {
		retval = 1;
		atomic_inc(&dev->power.usage_count);
	} else {
@@ -1261,10 +1264,16 @@ EXPORT_SYMBOL_GPL(pm_runtime_get_if_active);
 * @dev: Target device.
 *
 * Increment the runtime PM usage counter of @dev if its runtime PM status is
 * %RPM_ACTIVE and its runtime PM usage counter is greater than 0, in which case
 * it returns 1. If the device is in a different state or its usage_count is 0,
 * 0 is returned. -EINVAL is returned if runtime PM is disabled for the device,
 * in which case also the usage_count will remain unmodified.
 * %RPM_ACTIVE and its runtime PM usage counter is greater than 0 or it is not
 * ignoring children and its active child count is nonzero.  1 is returned in
 * this case.
 *
 * If @dev is in a different state or it is not in use (that is, its usage
 * counter is 0, or it is ignoring children, or its active child count is 0),
 * 0 is returned.
 *
 * -EINVAL is returned if runtime PM is disabled for the device, in which case
 * also the usage counter of @dev is not updated.
 */
int pm_runtime_get_if_in_use(struct device *dev)
{
+2 −0
Original line number Diff line number Diff line
@@ -96,6 +96,8 @@ static u64 get_pd_power_uw(struct dtpm *dtpm)
	int i;

	pd = em_cpu_get(dtpm_cpu->cpu);
	if (!pd)
		return 0;

	pd_mask = em_span_cpus(pd);

+1 −0
Original line number Diff line number Diff line
@@ -1277,6 +1277,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
	X86_MATCH_VFM(INTEL_RAPTORLAKE,		&rapl_defaults_core),
	X86_MATCH_VFM(INTEL_RAPTORLAKE_P,        &rapl_defaults_core),
	X86_MATCH_VFM(INTEL_RAPTORLAKE_S,	&rapl_defaults_core),
	X86_MATCH_VFM(INTEL_BARTLETTLAKE,	&rapl_defaults_core),
	X86_MATCH_VFM(INTEL_METEORLAKE,		&rapl_defaults_core),
	X86_MATCH_VFM(INTEL_METEORLAKE_L,	&rapl_defaults_core),
	X86_MATCH_VFM(INTEL_SAPPHIRERAPIDS_X,	&rapl_defaults_spr_server),
+1 −0
Original line number Diff line number Diff line
@@ -150,6 +150,7 @@ static const struct x86_cpu_id pl4_support_ids[] = {
	X86_MATCH_VFM(INTEL_METEORLAKE_L, NULL),
	X86_MATCH_VFM(INTEL_ARROWLAKE_U, NULL),
	X86_MATCH_VFM(INTEL_ARROWLAKE_H, NULL),
	X86_MATCH_VFM(INTEL_PANTHERLAKE_L, NULL),
	{}
};

Loading