Commit 7cede21e authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branches 'pm-qos' and 'pm-tools'

Merge PM QoS updates and a cpupower utility update for 6.19-rc1:

 - Introduce and document a QoS limit on CPU exit latency during wakeup
   from suspend-to-idle (Ulf Hansson)

 - Add support for building libcpupower statically (Zuo An)

* pm-qos:
  Documentation: power/cpuidle: Document the CPU system wakeup latency QoS
  cpuidle: Respect the CPU system wakeup QoS limit for cpuidle
  sched: idle: Respect the CPU system wakeup QoS limit for s2idle
  pmdomain: Respect the CPU system wakeup QoS limit for cpuidle
  pmdomain: Respect the CPU system wakeup QoS limit for s2idle
  PM: QoS: Introduce a CPU system wakeup QoS limit

* pm-tools:
  tools/power/cpupower: Support building libcpupower statically
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -580,6 +580,15 @@ the given CPU as the upper limit for the exit latency of the idle states that
they are allowed to select for that CPU.  They should never select any idle
states with exit latency beyond that limit.

While the above CPU QoS constraints apply to CPU idle time management, user
space may also request a CPU system wakeup latency QoS limit, via the
`cpu_wakeup_latency` file.  This QoS constraint is respected when selecting a
suitable idle state for the CPUs, while entering the system-wide suspend-to-idle
sleep state, but also to the regular CPU idle time management.

Note that, the management of the `cpu_wakeup_latency` file works according to
the 'cpu_dma_latency' file from user space point of view.  Moreover, the unit
is also microseconds.

Idle States Control Via Kernel Command Line
===========================================
+5 −4
Original line number Diff line number Diff line
@@ -55,7 +55,8 @@ int cpu_latency_qos_request_active(handle):

From user space:

The infrastructure exposes one device node, /dev/cpu_dma_latency, for the CPU
The infrastructure exposes two separate device nodes, /dev/cpu_dma_latency for
the CPU latency QoS and /dev/cpu_wakeup_latency for the CPU system wakeup
latency QoS.

Only processes can register a PM QoS request.  To provide for automatic
@@ -63,15 +64,15 @@ cleanup of a process, the interface requires the process to register its
parameter requests as follows.

To register the default PM QoS target for the CPU latency QoS, the process must
open /dev/cpu_dma_latency.
open /dev/cpu_dma_latency.  To register a CPU system wakeup QoS limit, the
process must open /dev/cpu_wakeup_latency.

As long as the device node is held open that process has a registered
request on the parameter.

To change the requested target value, the process needs to write an s32 value to
the open device node.  Alternatively, it can write a hex string for the value
using the 10 char long format e.g. "0x12345678".  This translates to a
cpu_latency_qos_update_request() call.
using the 10 char long format e.g. "0x12345678".

To remove the user mode request for a target value simply close the device
node.
+7 −5
Original line number Diff line number Diff line
@@ -184,20 +184,22 @@ static noinstr void enter_s2idle_proper(struct cpuidle_driver *drv,
 * cpuidle_enter_s2idle - Enter an idle state suitable for suspend-to-idle.
 * @drv: cpuidle driver for the given CPU.
 * @dev: cpuidle device for the given CPU.
 * @latency_limit_ns: Idle state exit latency limit
 *
 * If there are states with the ->enter_s2idle callback, find the deepest of
 * them and enter it with frozen tick.
 */
int cpuidle_enter_s2idle(struct cpuidle_driver *drv, struct cpuidle_device *dev)
int cpuidle_enter_s2idle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
			 u64 latency_limit_ns)
{
	int index;

	/*
	 * Find the deepest state with ->enter_s2idle present, which guarantees
	 * that interrupts won't be enabled when it exits and allows the tick to
	 * be frozen safely.
	 * Find the deepest state with ->enter_s2idle present that meets the
	 * specified latency limit, which guarantees that interrupts won't be
	 * enabled when it exits and allows the tick to be frozen safely.
	 */
	index = find_deepest_state(drv, dev, U64_MAX, 0, true);
	index = find_deepest_state(drv, dev, latency_limit_ns, 0, true);
	if (index > 0) {
		enter_s2idle_proper(drv, dev, index);
		local_irq_enable();
+4 −0
Original line number Diff line number Diff line
@@ -111,6 +111,10 @@ s64 cpuidle_governor_latency_req(unsigned int cpu)
	struct device *device = get_cpu_device(cpu);
	int device_req = dev_pm_qos_raw_resume_latency(device);
	int global_req = cpu_latency_qos_limit();
	int global_wake_req = cpu_wakeup_latency_qos_limit();

	if (global_req > global_wake_req)
		global_req = global_wake_req;

	if (device_req > global_req)
		device_req = global_req;
+8 −2
Original line number Diff line number Diff line
@@ -1425,8 +1425,14 @@ static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock,
			return;
	}

	/* Choose the deepest state when suspending */
	if (genpd->gov && genpd->gov->system_power_down_ok) {
		if (!genpd->gov->system_power_down_ok(&genpd->domain))
			return;
	} else {
		/* Default to the deepest state. */
		genpd->state_idx = genpd->state_count - 1;
	}

	if (_genpd_power_off(genpd, false)) {
		genpd->states[genpd->state_idx].rejected++;
		return;
Loading