Commit 8e7de6dc authored by Ulf Hansson's avatar Ulf Hansson Committed by Rafael J. Wysocki
Browse files

pmdomain: Respect the CPU system wakeup QoS limit for s2idle



A CPU system wakeup QoS limit may have been requested by user space. To
avoid breaking this constraint when entering a low power state during
s2idle through genpd, let's extend the corresponding genpd governor for
CPUs. More precisely, during s2idle let the genpd governor select a
suitable domain idle state, by taking into account the QoS limit.

Reviewed-by: default avatarDhruva Gole <d-gole@ti.com>
Reviewed-by: default avatarKevin Hilman (TI) <khilman@baylibre.com>
Tested-by: default avatarKevin Hilman (TI) <khilman@baylibre.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Link: https://patch.msgid.link/20251125112650.329269-3-ulf.hansson@linaro.org


Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent a4e6512a
Loading
Loading
Loading
Loading
+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;
+27 −0
Original line number Diff line number Diff line
@@ -415,9 +415,36 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
	return false;
}

static bool cpu_system_power_down_ok(struct dev_pm_domain *pd)
{
	s64 constraint_ns = cpu_wakeup_latency_qos_limit() * NSEC_PER_USEC;
	struct generic_pm_domain *genpd = pd_to_genpd(pd);
	int state_idx = genpd->state_count - 1;

	if (!(genpd->flags & GENPD_FLAG_CPU_DOMAIN)) {
		genpd->state_idx = state_idx;
		return true;
	}

	/* Find the deepest state for the latency constraint. */
	while (state_idx >= 0) {
		s64 latency_ns = genpd->states[state_idx].power_off_latency_ns +
				 genpd->states[state_idx].power_on_latency_ns;

		if (latency_ns <= constraint_ns) {
			genpd->state_idx = state_idx;
			return true;
		}
		state_idx--;
	}

	return false;
}

struct dev_power_governor pm_domain_cpu_gov = {
	.suspend_ok = default_suspend_ok,
	.power_down_ok = cpu_power_down_ok,
	.system_power_down_ok = cpu_system_power_down_ok,
};
#endif

+1 −0
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ enum genpd_sync_state {
};

struct dev_power_governor {
	bool (*system_power_down_ok)(struct dev_pm_domain *domain);
	bool (*power_down_ok)(struct dev_pm_domain *domain);
	bool (*suspend_ok)(struct device *dev);
};