/*1* driver.c - driver support2*3* (C) 2006-2007 Venkatesh Pallipadi <[email protected]>4* Shaohua Li <[email protected]>5* Adam Belay <[email protected]>6*7* This code is licenced under the GPL.8*/910#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt1112#include <linux/mutex.h>13#include <linux/module.h>14#include <linux/sched.h>15#include <linux/sched/idle.h>16#include <linux/cpuidle.h>17#include <linux/cpumask.h>18#include <linux/tick.h>19#include <linux/cpu.h>20#include <linux/math64.h>2122#include "cpuidle.h"2324DEFINE_SPINLOCK(cpuidle_driver_lock);2526#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS2728static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers);2930/**31* __cpuidle_get_cpu_driver - return the cpuidle driver tied to a CPU.32* @cpu: the CPU handled by the driver33*34* Returns a pointer to struct cpuidle_driver or NULL if no driver has been35* registered for @cpu.36*/37static struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)38{39return per_cpu(cpuidle_drivers, cpu);40}4142/**43* __cpuidle_unset_driver - unset per CPU driver variables.44* @drv: a valid pointer to a struct cpuidle_driver45*46* For each CPU in the driver's CPU mask, unset the registered driver per CPU47* variable. If @drv is different from the registered driver, the corresponding48* variable is not cleared.49*/50static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv)51{52int cpu;5354for_each_cpu(cpu, drv->cpumask) {5556if (drv != __cpuidle_get_cpu_driver(cpu))57continue;5859per_cpu(cpuidle_drivers, cpu) = NULL;60}61}6263/**64* __cpuidle_set_driver - set per CPU driver variables for the given driver.65* @drv: a valid pointer to a struct cpuidle_driver66*67* Returns 0 on success, -EBUSY if any CPU in the cpumask have a driver68* different from drv already.69*/70static inline int __cpuidle_set_driver(struct cpuidle_driver *drv)71{72int cpu;7374for_each_cpu(cpu, drv->cpumask) {75struct cpuidle_driver *old_drv;7677old_drv = __cpuidle_get_cpu_driver(cpu);78if (old_drv && old_drv != drv)79return -EBUSY;80}8182for_each_cpu(cpu, drv->cpumask)83per_cpu(cpuidle_drivers, cpu) = drv;8485return 0;86}8788#else8990static struct cpuidle_driver *cpuidle_curr_driver;9192/**93* __cpuidle_get_cpu_driver - return the global cpuidle driver pointer.94* @cpu: ignored without the multiple driver support95*96* Return a pointer to a struct cpuidle_driver object or NULL if no driver was97* previously registered.98*/99static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)100{101return cpuidle_curr_driver;102}103104/**105* __cpuidle_set_driver - assign the global cpuidle driver variable.106* @drv: pointer to a struct cpuidle_driver object107*108* Returns 0 on success, -EBUSY if the driver is already registered.109*/110static inline int __cpuidle_set_driver(struct cpuidle_driver *drv)111{112if (cpuidle_curr_driver)113return -EBUSY;114115cpuidle_curr_driver = drv;116117return 0;118}119120/**121* __cpuidle_unset_driver - unset the global cpuidle driver variable.122* @drv: a pointer to a struct cpuidle_driver123*124* Reset the global cpuidle variable to NULL. If @drv does not match the125* registered driver, do nothing.126*/127static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv)128{129if (drv == cpuidle_curr_driver)130cpuidle_curr_driver = NULL;131}132133#endif134135/**136* cpuidle_setup_broadcast_timer - enable/disable the broadcast timer on a cpu137* @arg: a void pointer used to match the SMP cross call API138*139* If @arg is NULL broadcast is disabled otherwise enabled140*141* This function is executed per CPU by an SMP cross call. It's not142* supposed to be called directly.143*/144static void cpuidle_setup_broadcast_timer(void *arg)145{146if (arg)147tick_broadcast_enable();148else149tick_broadcast_disable();150}151152/**153* __cpuidle_driver_init - initialize the driver's internal data154* @drv: a valid pointer to a struct cpuidle_driver155*/156static void __cpuidle_driver_init(struct cpuidle_driver *drv)157{158int i;159160/*161* Use all possible CPUs as the default, because if the kernel boots162* with some CPUs offline and then we online one of them, the CPU163* notifier has to know which driver to assign.164*/165if (!drv->cpumask)166drv->cpumask = (struct cpumask *)cpu_possible_mask;167168for (i = 0; i < drv->state_count; i++) {169struct cpuidle_state *s = &drv->states[i];170171/*172* Look for the timer stop flag in the different states and if173* it is found, indicate that the broadcast timer has to be set174* up.175*/176if (s->flags & CPUIDLE_FLAG_TIMER_STOP)177drv->bctimer = 1;178179/*180* The core will use the target residency and exit latency181* values in nanoseconds, but allow drivers to provide them in182* microseconds too.183*/184if (s->target_residency > 0)185s->target_residency_ns = s->target_residency * NSEC_PER_USEC;186else if (s->target_residency_ns < 0)187s->target_residency_ns = 0;188else189s->target_residency = div_u64(s->target_residency_ns, NSEC_PER_USEC);190191if (s->exit_latency > 0)192s->exit_latency_ns = mul_u32_u32(s->exit_latency, NSEC_PER_USEC);193else if (s->exit_latency_ns < 0)194s->exit_latency_ns = 0;195else196s->exit_latency = div_u64(s->exit_latency_ns, NSEC_PER_USEC);197198/*199* Warn if the exit latency of a CPU idle state exceeds its200* target residency which is assumed to never happen in cpuidle201* in multiple places.202*/203if (s->exit_latency_ns > s->target_residency_ns)204pr_warn("Idle state %d target residency too low\n", i);205}206}207208/**209* __cpuidle_register_driver: register the driver210* @drv: a valid pointer to a struct cpuidle_driver211*212* Do some sanity checks, initialize the driver, assign the driver to the213* global cpuidle driver variable(s) and set up the broadcast timer if the214* cpuidle driver has some states that shut down the local timer.215*216* Returns 0 on success, a negative error code otherwise:217* * -EINVAL if the driver pointer is NULL or no idle states are available218* * -ENODEV if the cpuidle framework is disabled219* * -EBUSY if the driver is already assigned to the global variable(s)220*/221static int __cpuidle_register_driver(struct cpuidle_driver *drv)222{223int ret;224225if (!drv || !drv->state_count)226return -EINVAL;227228ret = cpuidle_coupled_state_verify(drv);229if (ret)230return ret;231232if (cpuidle_disabled())233return -ENODEV;234235__cpuidle_driver_init(drv);236237ret = __cpuidle_set_driver(drv);238if (ret)239return ret;240241if (drv->bctimer)242on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,243(void *)1, 1);244245return 0;246}247248/**249* __cpuidle_unregister_driver - unregister the driver250* @drv: a valid pointer to a struct cpuidle_driver251*252* Check if the driver is no longer in use, reset the global cpuidle driver253* variable(s) and disable the timer broadcast notification mechanism if it was254* in use.255*256*/257static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)258{259if (drv->bctimer) {260drv->bctimer = 0;261on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,262NULL, 1);263}264265__cpuidle_unset_driver(drv);266}267268/**269* cpuidle_register_driver - registers a driver270* @drv: a pointer to a valid struct cpuidle_driver271*272* Register the driver under a lock to prevent concurrent attempts to273* [un]register the driver from occurring at the same time.274*275* Returns 0 on success, a negative error code (returned by276* __cpuidle_register_driver()) otherwise.277*/278int cpuidle_register_driver(struct cpuidle_driver *drv)279{280struct cpuidle_governor *gov;281int ret;282283spin_lock(&cpuidle_driver_lock);284ret = __cpuidle_register_driver(drv);285spin_unlock(&cpuidle_driver_lock);286287if (!ret && !strlen(param_governor) && drv->governor &&288(cpuidle_get_driver() == drv)) {289mutex_lock(&cpuidle_lock);290gov = cpuidle_find_governor(drv->governor);291if (gov) {292cpuidle_prev_governor = cpuidle_curr_governor;293if (cpuidle_switch_governor(gov) < 0)294cpuidle_prev_governor = NULL;295}296mutex_unlock(&cpuidle_lock);297}298299return ret;300}301EXPORT_SYMBOL_GPL(cpuidle_register_driver);302303/**304* cpuidle_unregister_driver - unregisters a driver305* @drv: a pointer to a valid struct cpuidle_driver306*307* Unregisters the cpuidle driver under a lock to prevent concurrent attempts308* to [un]register the driver from occurring at the same time. @drv has to309* match the currently registered driver.310*/311void cpuidle_unregister_driver(struct cpuidle_driver *drv)312{313bool enabled = (cpuidle_get_driver() == drv);314315spin_lock(&cpuidle_driver_lock);316__cpuidle_unregister_driver(drv);317spin_unlock(&cpuidle_driver_lock);318319if (!enabled)320return;321322mutex_lock(&cpuidle_lock);323if (cpuidle_prev_governor) {324if (!cpuidle_switch_governor(cpuidle_prev_governor))325cpuidle_prev_governor = NULL;326}327mutex_unlock(&cpuidle_lock);328}329EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);330331/**332* cpuidle_get_driver - return the driver tied to the current CPU.333*334* Returns a struct cpuidle_driver pointer, or NULL if no driver is registered.335*/336struct cpuidle_driver *cpuidle_get_driver(void)337{338struct cpuidle_driver *drv;339int cpu;340341cpu = get_cpu();342drv = __cpuidle_get_cpu_driver(cpu);343put_cpu();344345return drv;346}347EXPORT_SYMBOL_GPL(cpuidle_get_driver);348349/**350* cpuidle_get_cpu_driver - return the driver registered for a CPU.351* @dev: a valid pointer to a struct cpuidle_device352*353* Returns a struct cpuidle_driver pointer, or NULL if no driver is registered354* for the CPU associated with @dev.355*/356struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev)357{358if (!dev)359return NULL;360361return __cpuidle_get_cpu_driver(dev->cpu);362}363EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);364365/**366* cpuidle_driver_state_disabled - Disable or enable an idle state367* @drv: cpuidle driver owning the state368* @idx: State index369* @disable: Whether or not to disable the state370*/371void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx,372bool disable)373{374unsigned int cpu;375376mutex_lock(&cpuidle_lock);377378spin_lock(&cpuidle_driver_lock);379380if (!drv->cpumask) {381drv->states[idx].flags |= CPUIDLE_FLAG_UNUSABLE;382goto unlock;383}384385for_each_cpu(cpu, drv->cpumask) {386struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);387388if (!dev)389continue;390391if (disable)392dev->states_usage[idx].disable |= CPUIDLE_STATE_DISABLED_BY_DRIVER;393else394dev->states_usage[idx].disable &= ~CPUIDLE_STATE_DISABLED_BY_DRIVER;395}396397unlock:398spin_unlock(&cpuidle_driver_lock);399400mutex_unlock(&cpuidle_lock);401}402403404