drivers/pmdomain/governor.c

Source file repositories/reference/linux-study-clean/drivers/pmdomain/governor.c

File Facts

System
Linux kernel
Corpus path
drivers/pmdomain/governor.c
Extension
.c
Size
13643 bytes
Lines
472
Domain
Driver Families
Bucket
drivers/pmdomain
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

while (state_idx >= 0) {
			if (next_wakeup_allows_state(genpd, state_idx, now)) {
				gd->max_off_time_changed = true;
				break;
			}
			state_idx--;
		}

		if (state_idx < 0) {
			state_idx = 0;
			gd->cached_power_down_ok = false;
			goto done;
		}
	}

	if (!gd->max_off_time_changed) {
		genpd->state_idx = gd->cached_power_down_state_idx;
		return gd->cached_power_down_ok;
	}

	/*
	 * We have to invalidate the cached results for the parents, so
	 * use the observation that default_power_down_ok() is not
	 * going to be called for any parent until this instance
	 * returns.
	 */
	list_for_each_entry(link, &genpd->child_links, child_node) {
		struct genpd_governor_data *pgd = link->parent->gd;

		if (pgd)
			pgd->max_off_time_changed = true;
	}

	gd->max_off_time_ns = -1;
	gd->max_off_time_changed = false;
	gd->cached_power_down_ok = true;

	/*
	 * Find a state to power down to, starting from the state
	 * determined by the next wakeup.
	 */
	while (!__default_power_down_ok(pd, state_idx)) {
		if (state_idx == 0) {
			gd->cached_power_down_ok = false;
			break;
		}
		state_idx--;
	}

done:
	genpd->state_idx = state_idx;
	gd->cached_power_down_state_idx = genpd->state_idx;
	return gd->cached_power_down_ok;
}

static bool default_power_down_ok(struct dev_pm_domain *pd)
{
	return _default_power_down_ok(pd, ktime_get());
}

#ifdef CONFIG_CPU_IDLE
static bool cpu_power_down_ok(struct dev_pm_domain *pd)
{
	struct generic_pm_domain *genpd = pd_to_genpd(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, wakeup_constraint;
	s64 idle_duration_ns;
	int cpu, i;

	/* Validate dev PM QoS constraints. */
	if (!_default_power_down_ok(pd, now))
		return false;

	if (!(genpd->flags & GENPD_FLAG_CPU_DOMAIN))
		return true;

	wakeup_constraint = cpu_wakeup_latency_qos_limit();
	global_constraint = cpu_latency_qos_limit();
	if (global_constraint > wakeup_constraint)
		global_constraint = wakeup_constraint;

	/*
	 * 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
	 * contains a mask of all CPUs from subdomains.
	 */
	domain_wakeup = ktime_set(KTIME_SEC_MAX, 0);

Annotation

Implementation Notes