Commit 7abc678e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pmdomain / cpuidle-psci fixes from Ulf Hansson:
 "pmdomain core:

   - Respect CPU latency QoS limit in the genpd governor for CPUs

  cpuidle-psci:

   - Fix cpuhotplug support for PREEMPT_RT"

* tag 'pmdomain-v6.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm:
  cpuidle: psci: Fix cpuhotplug routine with PREEMPT_RT=y
  pmdomain: governor: Consider CPU latency tolerance from pm_domain_cpu_gov
parents 16e14971 621a88db
Loading
Loading
Loading
Loading
+12 −11
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ struct psci_cpuidle_domain_state {
static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data);
static DEFINE_PER_CPU(struct psci_cpuidle_domain_state, psci_domain_state);
static bool psci_cpuidle_use_syscore;
static bool psci_cpuidle_use_cpuhp;

void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx,
			   u32 state)
@@ -124,8 +123,12 @@ static int psci_idle_cpuhp_up(unsigned int cpu)
{
	struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev);

	if (pd_dev)
	if (pd_dev) {
		if (!IS_ENABLED(CONFIG_PREEMPT_RT))
			pm_runtime_get_sync(pd_dev);
		else
			dev_pm_genpd_resume(pd_dev);
	}

	return 0;
}
@@ -135,7 +138,11 @@ static int psci_idle_cpuhp_down(unsigned int cpu)
	struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev);

	if (pd_dev) {
		if (!IS_ENABLED(CONFIG_PREEMPT_RT))
			pm_runtime_put_sync(pd_dev);
		else
			dev_pm_genpd_suspend(pd_dev);

		/* Clear domain state to start fresh at next online. */
		psci_clear_domain_state();
	}
@@ -196,9 +203,6 @@ static void psci_idle_init_cpuhp(void)
{
	int err;

	if (!psci_cpuidle_use_cpuhp)
		return;

	err = cpuhp_setup_state_nocalls(CPUHP_AP_CPU_PM_STARTING,
					"cpuidle/psci:online",
					psci_idle_cpuhp_up,
@@ -259,10 +263,8 @@ static int psci_dt_cpu_init_topology(struct cpuidle_driver *drv,
	 * s2ram and s2idle.
	 */
	drv->states[state_count - 1].enter_s2idle = psci_enter_s2idle_domain_idle_state;
	if (!IS_ENABLED(CONFIG_PREEMPT_RT)) {
	if (!IS_ENABLED(CONFIG_PREEMPT_RT))
		drv->states[state_count - 1].enter = psci_enter_domain_idle_state;
		psci_cpuidle_use_cpuhp = true;
	}

	return 0;
}
@@ -339,7 +341,6 @@ static void psci_cpu_deinit_idle(int cpu)

	dt_idle_detach_cpu(data->dev);
	psci_cpuidle_use_syscore = false;
	psci_cpuidle_use_cpuhp = false;
}

static int psci_idle_init_cpu(struct device *dev, int cpu)
+16 −2
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/pm_domain.h>
#include <linux/pm_qos.h>
#include <linux/hrtimer.h>
#include <linux/cpu.h>
#include <linux/cpuidle.h>
#include <linux/cpumask.h>
#include <linux/ktime.h>
@@ -349,6 +350,8 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
	struct cpuidle_device *dev;
	ktime_t domain_wakeup, next_hrtimer;
	ktime_t now = ktime_get();
	struct device *cpu_dev;
	s64 cpu_constraint, global_constraint;
	s64 idle_duration_ns;
	int cpu, i;

@@ -359,6 +362,7 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
	if (!(genpd->flags & GENPD_FLAG_CPU_DOMAIN))
		return true;

	global_constraint = cpu_latency_qos_limit();
	/*
	 * Find the next wakeup for any of the online CPUs within the PM domain
	 * and its subdomains. Note, we only need the genpd->cpus, as it already
@@ -372,8 +376,16 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
			if (ktime_before(next_hrtimer, domain_wakeup))
				domain_wakeup = next_hrtimer;
		}

		cpu_dev = get_cpu_device(cpu);
		if (cpu_dev) {
			cpu_constraint = dev_pm_qos_raw_resume_latency(cpu_dev);
			if (cpu_constraint < global_constraint)
				global_constraint = cpu_constraint;
		}
	}

	global_constraint *= NSEC_PER_USEC;
	/* The minimum idle duration is from now - until the next wakeup. */
	idle_duration_ns = ktime_to_ns(ktime_sub(domain_wakeup, now));
	if (idle_duration_ns <= 0)
@@ -389,8 +401,10 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
	 */
	i = genpd->state_idx;
	do {
		if (idle_duration_ns >= (genpd->states[i].residency_ns +
		    genpd->states[i].power_off_latency_ns)) {
		if ((idle_duration_ns >= (genpd->states[i].residency_ns +
		    genpd->states[i].power_off_latency_ns)) &&
		    (global_constraint >= (genpd->states[i].power_on_latency_ns +
		    genpd->states[i].power_off_latency_ns))) {
			genpd->state_idx = i;
			genpd->gd->last_enter = now;
			genpd->gd->reflect_residency = true;