/* * arm_enter_idle_state - Programs CPU to enter the specified state * * dev: cpuidle device * drv: cpuidle driver * idx: state index * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor.
*/ static __cpuidle int arm_enter_idle_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, int idx)
{ /* * Pass idle state index to arm_cpuidle_suspend which in turn * will call the CPU ops suspend protocol with idle index as a * parameter.
*/ return CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, idx);
}
staticstruct cpuidle_driver arm_idle_driver __initdata = {
.name = "arm_idle",
.owner = THIS_MODULE, /* * State at index 0 is standby wfi and considered standard * on all ARM platforms. If in some platforms simple wfi * can't be used as "state 0", DT bindings must be implemented * to work around this issue and allow installing a special * handler for idle state index 0.
*/
.states[0] = {
.enter = arm_enter_idle_state,
.exit_latency = 1,
.target_residency = 1,
.power_usage = UINT_MAX,
.name = "WFI",
.desc = "ARM WFI",
}
};
/* * arm_idle_init_cpu * * Registers the arm specific cpuidle driver with the cpuidle * framework. It relies on core code to parse the idle states * and initialize them using driver data structures accordingly.
*/ staticint __init arm_idle_init_cpu(int cpu)
{ int ret; struct cpuidle_driver *drv;
drv = kmemdup(&arm_idle_driver, sizeof(*drv), GFP_KERNEL); if (!drv) return -ENOMEM;
drv->cpumask = (struct cpumask *)cpumask_of(cpu);
/* * Initialize idle states data, starting at index 1. This * driver is DT only, if no DT idle states are detected (ret * == 0) let the driver initialization fail accordingly since * there is no reason to initialize the idle driver if only * wfi is supported.
*/
ret = dt_init_idle_driver(drv, arm_idle_state_match, 1); if (ret <= 0) {
ret = ret ? : -ENODEV; goto out_kfree_drv;
}
/* * Call arch CPU operations in order to initialize * idle states suspend back-end specific data
*/
ret = arm_cpuidle_init(cpu);
/* * Allow the initialization to continue for other CPUs, if the * reported failure is a HW misconfiguration/breakage (-ENXIO). * * Some platforms do not support idle operations * (arm_cpuidle_init() returning -EOPNOTSUPP), we should * not flag this case as an error, it is a valid * configuration.
*/ if (ret) { if (ret != -EOPNOTSUPP)
pr_err("CPU %d failed to init idle CPU ops\n", cpu);
ret = ret == -ENXIO ? 0 : ret; goto out_kfree_drv;
}
ret = cpuidle_register(drv, NULL); if (ret) goto out_kfree_drv;
cpuidle_cooling_register(drv);
return 0;
out_kfree_drv:
kfree(drv); return ret;
}
/* * arm_idle_init - Initializes arm cpuidle driver * * Initializes arm cpuidle driver for all present CPUs, if any * CPU fails to register cpuidle driver then rollback to cancel * all CPUs registration.
*/ staticint __init arm_idle_init(void)
{ int cpu, ret; struct cpuidle_driver *drv; struct cpuidle_device *dev;
for_each_present_cpu(cpu) {
ret = arm_idle_init_cpu(cpu); if (ret) goto out_fail;
}
return 0;
out_fail: while (--cpu >= 0) {
dev = per_cpu(cpuidle_devices, cpu);
drv = cpuidle_get_cpu_driver(dev);
cpuidle_unregister(drv);
kfree(drv);
}
return ret;
}
device_initcall(arm_idle_init);
Messung V0.5
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.