Skip to content

Commit 8e7de6d

Browse files
storulfrafaeljw
authored andcommitted
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: Dhruva Gole <d-gole@ti.com> Reviewed-by: Kevin Hilman (TI) <khilman@baylibre.com> Tested-by: Kevin Hilman (TI) <khilman@baylibre.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Link: https://patch.msgid.link/20251125112650.329269-3-ulf.hansson@linaro.org Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent a4e6512 commit 8e7de6d

3 files changed

Lines changed: 36 additions & 2 deletions

File tree

drivers/pmdomain/core.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,8 +1425,14 @@ static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock,
14251425
return;
14261426
}
14271427

1428-
/* Choose the deepest state when suspending */
1429-
genpd->state_idx = genpd->state_count - 1;
1428+
if (genpd->gov && genpd->gov->system_power_down_ok) {
1429+
if (!genpd->gov->system_power_down_ok(&genpd->domain))
1430+
return;
1431+
} else {
1432+
/* Default to the deepest state. */
1433+
genpd->state_idx = genpd->state_count - 1;
1434+
}
1435+
14301436
if (_genpd_power_off(genpd, false)) {
14311437
genpd->states[genpd->state_idx].rejected++;
14321438
return;

drivers/pmdomain/governor.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,36 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
415415
return false;
416416
}
417417

418+
static bool cpu_system_power_down_ok(struct dev_pm_domain *pd)
419+
{
420+
s64 constraint_ns = cpu_wakeup_latency_qos_limit() * NSEC_PER_USEC;
421+
struct generic_pm_domain *genpd = pd_to_genpd(pd);
422+
int state_idx = genpd->state_count - 1;
423+
424+
if (!(genpd->flags & GENPD_FLAG_CPU_DOMAIN)) {
425+
genpd->state_idx = state_idx;
426+
return true;
427+
}
428+
429+
/* Find the deepest state for the latency constraint. */
430+
while (state_idx >= 0) {
431+
s64 latency_ns = genpd->states[state_idx].power_off_latency_ns +
432+
genpd->states[state_idx].power_on_latency_ns;
433+
434+
if (latency_ns <= constraint_ns) {
435+
genpd->state_idx = state_idx;
436+
return true;
437+
}
438+
state_idx--;
439+
}
440+
441+
return false;
442+
}
443+
418444
struct dev_power_governor pm_domain_cpu_gov = {
419445
.suspend_ok = default_suspend_ok,
420446
.power_down_ok = cpu_power_down_ok,
447+
.system_power_down_ok = cpu_system_power_down_ok,
421448
};
422449
#endif
423450

include/linux/pm_domain.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ enum genpd_sync_state {
153153
};
154154

155155
struct dev_power_governor {
156+
bool (*system_power_down_ok)(struct dev_pm_domain *domain);
156157
bool (*power_down_ok)(struct dev_pm_domain *domain);
157158
bool (*suspend_ok)(struct device *dev);
158159
};

0 commit comments

Comments
 (0)