linux/drivers/cpuidle/driver.c
<<
>>
Prefs
   1/*
   2 * driver.c - driver support
   3 *
   4 * (C) 2006-2007 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
   5 *               Shaohua Li <shaohua.li@intel.com>
   6 *               Adam Belay <abelay@novell.com>
   7 *
   8 * This code is licenced under the GPL.
   9 */
  10
  11#include <linux/mutex.h>
  12#include <linux/module.h>
  13#include <linux/sched.h>
  14#include <linux/sched/idle.h>
  15#include <linux/cpuidle.h>
  16#include <linux/cpumask.h>
  17#include <linux/tick.h>
  18#include <linux/cpu.h>
  19
  20#include "cpuidle.h"
  21
  22DEFINE_SPINLOCK(cpuidle_driver_lock);
  23
  24#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
  25
  26static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers);
  27
  28/**
  29 * __cpuidle_get_cpu_driver - return the cpuidle driver tied to a CPU.
  30 * @cpu: the CPU handled by the driver
  31 *
  32 * Returns a pointer to struct cpuidle_driver or NULL if no driver has been
  33 * registered for @cpu.
  34 */
  35static struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
  36{
  37        return per_cpu(cpuidle_drivers, cpu);
  38}
  39
  40/**
  41 * __cpuidle_unset_driver - unset per CPU driver variables.
  42 * @drv: a valid pointer to a struct cpuidle_driver
  43 *
  44 * For each CPU in the driver's CPU mask, unset the registered driver per CPU
  45 * variable. If @drv is different from the registered driver, the corresponding
  46 * variable is not cleared.
  47 */
  48static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv)
  49{
  50        int cpu;
  51
  52        for_each_cpu(cpu, drv->cpumask) {
  53
  54                if (drv != __cpuidle_get_cpu_driver(cpu))
  55                        continue;
  56
  57                per_cpu(cpuidle_drivers, cpu) = NULL;
  58        }
  59}
  60
  61/**
  62 * __cpuidle_set_driver - set per CPU driver variables for the given driver.
  63 * @drv: a valid pointer to a struct cpuidle_driver
  64 *
  65 * Returns 0 on success, -EBUSY if any CPU in the cpumask have a driver
  66 * different from drv already.
  67 */
  68static inline int __cpuidle_set_driver(struct cpuidle_driver *drv)
  69{
  70        int cpu;
  71
  72        for_each_cpu(cpu, drv->cpumask) {
  73                struct cpuidle_driver *old_drv;
  74
  75                old_drv = __cpuidle_get_cpu_driver(cpu);
  76                if (old_drv && old_drv != drv)
  77                        return -EBUSY;
  78        }
  79
  80        for_each_cpu(cpu, drv->cpumask)
  81                per_cpu(cpuidle_drivers, cpu) = drv;
  82
  83        return 0;
  84}
  85
  86#else
  87
  88static struct cpuidle_driver *cpuidle_curr_driver;
  89
  90/**
  91 * __cpuidle_get_cpu_driver - return the global cpuidle driver pointer.
  92 * @cpu: ignored without the multiple driver support
  93 *
  94 * Return a pointer to a struct cpuidle_driver object or NULL if no driver was
  95 * previously registered.
  96 */
  97static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
  98{
  99        return cpuidle_curr_driver;
 100}
 101
 102/**
 103 * __cpuidle_set_driver - assign the global cpuidle driver variable.
 104 * @drv: pointer to a struct cpuidle_driver object
 105 *
 106 * Returns 0 on success, -EBUSY if the driver is already registered.
 107 */
 108static inline int __cpuidle_set_driver(struct cpuidle_driver *drv)
 109{
 110        if (cpuidle_curr_driver)
 111                return -EBUSY;
 112
 113        cpuidle_curr_driver = drv;
 114
 115        return 0;
 116}
 117
 118/**
 119 * __cpuidle_unset_driver - unset the global cpuidle driver variable.
 120 * @drv: a pointer to a struct cpuidle_driver
 121 *
 122 * Reset the global cpuidle variable to NULL.  If @drv does not match the
 123 * registered driver, do nothing.
 124 */
 125static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv)
 126{
 127        if (drv == cpuidle_curr_driver)
 128                cpuidle_curr_driver = NULL;
 129}
 130
 131#endif
 132
 133/**
 134 * cpuidle_setup_broadcast_timer - enable/disable the broadcast timer on a cpu
 135 * @arg: a void pointer used to match the SMP cross call API
 136 *
 137 * If @arg is NULL broadcast is disabled otherwise enabled
 138 *
 139 * This function is executed per CPU by an SMP cross call.  It's not
 140 * supposed to be called directly.
 141 */
 142static void cpuidle_setup_broadcast_timer(void *arg)
 143{
 144        if (arg)
 145                tick_broadcast_enable();
 146        else
 147                tick_broadcast_disable();
 148}
 149
 150/**
 151 * __cpuidle_driver_init - initialize the driver's internal data
 152 * @drv: a valid pointer to a struct cpuidle_driver
 153 */
 154static void __cpuidle_driver_init(struct cpuidle_driver *drv)
 155{
 156        int i;
 157
 158        /*
 159         * Use all possible CPUs as the default, because if the kernel boots
 160         * with some CPUs offline and then we online one of them, the CPU
 161         * notifier has to know which driver to assign.
 162         */
 163        if (!drv->cpumask)
 164                drv->cpumask = (struct cpumask *)cpu_possible_mask;
 165
 166        for (i = 0; i < drv->state_count; i++) {
 167                struct cpuidle_state *s = &drv->states[i];
 168
 169                /*
 170                 * Look for the timer stop flag in the different states and if
 171                 * it is found, indicate that the broadcast timer has to be set
 172                 * up.
 173                 */
 174                if (s->flags & CPUIDLE_FLAG_TIMER_STOP)
 175                        drv->bctimer = 1;
 176
 177                /*
 178                 * The core will use the target residency and exit latency
 179                 * values in nanoseconds, but allow drivers to provide them in
 180                 * microseconds too.
 181                 */
 182                if (s->target_residency > 0)
 183                        s->target_residency_ns = s->target_residency * NSEC_PER_USEC;
 184                else if (s->target_residency_ns < 0)
 185                        s->target_residency_ns = 0;
 186
 187                if (s->exit_latency > 0)
 188                        s->exit_latency_ns = s->exit_latency * NSEC_PER_USEC;
 189                else if (s->exit_latency_ns < 0)
 190                        s->exit_latency_ns =  0;
 191        }
 192}
 193
 194/**
 195 * __cpuidle_register_driver: register the driver
 196 * @drv: a valid pointer to a struct cpuidle_driver
 197 *
 198 * Do some sanity checks, initialize the driver, assign the driver to the
 199 * global cpuidle driver variable(s) and set up the broadcast timer if the
 200 * cpuidle driver has some states that shut down the local timer.
 201 *
 202 * Returns 0 on success, a negative error code otherwise:
 203 *  * -EINVAL if the driver pointer is NULL or no idle states are available
 204 *  * -ENODEV if the cpuidle framework is disabled
 205 *  * -EBUSY if the driver is already assigned to the global variable(s)
 206 */
 207static int __cpuidle_register_driver(struct cpuidle_driver *drv)
 208{
 209        int ret;
 210
 211        if (!drv || !drv->state_count)
 212                return -EINVAL;
 213
 214        ret = cpuidle_coupled_state_verify(drv);
 215        if (ret)
 216                return ret;
 217
 218        if (cpuidle_disabled())
 219                return -ENODEV;
 220
 221        __cpuidle_driver_init(drv);
 222
 223        ret = __cpuidle_set_driver(drv);
 224        if (ret)
 225                return ret;
 226
 227        if (drv->bctimer)
 228                on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
 229                                 (void *)1, 1);
 230
 231        return 0;
 232}
 233
 234/**
 235 * __cpuidle_unregister_driver - unregister the driver
 236 * @drv: a valid pointer to a struct cpuidle_driver
 237 *
 238 * Check if the driver is no longer in use, reset the global cpuidle driver
 239 * variable(s) and disable the timer broadcast notification mechanism if it was
 240 * in use.
 241 *
 242 */
 243static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
 244{
 245        if (drv->bctimer) {
 246                drv->bctimer = 0;
 247                on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
 248                                 NULL, 1);
 249        }
 250
 251        __cpuidle_unset_driver(drv);
 252}
 253
 254/**
 255 * cpuidle_register_driver - registers a driver
 256 * @drv: a pointer to a valid struct cpuidle_driver
 257 *
 258 * Register the driver under a lock to prevent concurrent attempts to
 259 * [un]register the driver from occuring at the same time.
 260 *
 261 * Returns 0 on success, a negative error code (returned by
 262 * __cpuidle_register_driver()) otherwise.
 263 */
 264int cpuidle_register_driver(struct cpuidle_driver *drv)
 265{
 266        struct cpuidle_governor *gov;
 267        int ret;
 268
 269        spin_lock(&cpuidle_driver_lock);
 270        ret = __cpuidle_register_driver(drv);
 271        spin_unlock(&cpuidle_driver_lock);
 272
 273        if (!ret && !strlen(param_governor) && drv->governor &&
 274            (cpuidle_get_driver() == drv)) {
 275                mutex_lock(&cpuidle_lock);
 276                gov = cpuidle_find_governor(drv->governor);
 277                if (gov) {
 278                        cpuidle_prev_governor = cpuidle_curr_governor;
 279                        if (cpuidle_switch_governor(gov) < 0)
 280                                cpuidle_prev_governor = NULL;
 281                }
 282                mutex_unlock(&cpuidle_lock);
 283        }
 284
 285        return ret;
 286}
 287EXPORT_SYMBOL_GPL(cpuidle_register_driver);
 288
 289/**
 290 * cpuidle_unregister_driver - unregisters a driver
 291 * @drv: a pointer to a valid struct cpuidle_driver
 292 *
 293 * Unregisters the cpuidle driver under a lock to prevent concurrent attempts
 294 * to [un]register the driver from occuring at the same time.  @drv has to
 295 * match the currently registered driver.
 296 */
 297void cpuidle_unregister_driver(struct cpuidle_driver *drv)
 298{
 299        bool enabled = (cpuidle_get_driver() == drv);
 300
 301        spin_lock(&cpuidle_driver_lock);
 302        __cpuidle_unregister_driver(drv);
 303        spin_unlock(&cpuidle_driver_lock);
 304
 305        if (!enabled)
 306                return;
 307
 308        mutex_lock(&cpuidle_lock);
 309        if (cpuidle_prev_governor) {
 310                if (!cpuidle_switch_governor(cpuidle_prev_governor))
 311                        cpuidle_prev_governor = NULL;
 312        }
 313        mutex_unlock(&cpuidle_lock);
 314}
 315EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
 316
 317/**
 318 * cpuidle_get_driver - return the driver tied to the current CPU.
 319 *
 320 * Returns a struct cpuidle_driver pointer, or NULL if no driver is registered.
 321 */
 322struct cpuidle_driver *cpuidle_get_driver(void)
 323{
 324        struct cpuidle_driver *drv;
 325        int cpu;
 326
 327        cpu = get_cpu();
 328        drv = __cpuidle_get_cpu_driver(cpu);
 329        put_cpu();
 330
 331        return drv;
 332}
 333EXPORT_SYMBOL_GPL(cpuidle_get_driver);
 334
 335/**
 336 * cpuidle_get_cpu_driver - return the driver registered for a CPU.
 337 * @dev: a valid pointer to a struct cpuidle_device
 338 *
 339 * Returns a struct cpuidle_driver pointer, or NULL if no driver is registered
 340 * for the CPU associated with @dev.
 341 */
 342struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev)
 343{
 344        if (!dev)
 345                return NULL;
 346
 347        return __cpuidle_get_cpu_driver(dev->cpu);
 348}
 349EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);
 350
 351/**
 352 * cpuidle_driver_state_disabled - Disable or enable an idle state
 353 * @drv: cpuidle driver owning the state
 354 * @idx: State index
 355 * @disable: Whether or not to disable the state
 356 */
 357void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx,
 358                                 bool disable)
 359{
 360        unsigned int cpu;
 361
 362        mutex_lock(&cpuidle_lock);
 363
 364        spin_lock(&cpuidle_driver_lock);
 365
 366        if (!drv->cpumask) {
 367                drv->states[idx].flags |= CPUIDLE_FLAG_UNUSABLE;
 368                goto unlock;
 369        }
 370
 371        for_each_cpu(cpu, drv->cpumask) {
 372                struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
 373
 374                if (!dev)
 375                        continue;
 376
 377                if (disable)
 378                        dev->states_usage[idx].disable |= CPUIDLE_STATE_DISABLED_BY_DRIVER;
 379                else
 380                        dev->states_usage[idx].disable &= ~CPUIDLE_STATE_DISABLED_BY_DRIVER;
 381        }
 382
 383unlock:
 384        spin_unlock(&cpuidle_driver_lock);
 385
 386        mutex_unlock(&cpuidle_lock);
 387}
 388