root/drivers/cpuidle/driver.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __cpuidle_get_cpu_driver
  2. __cpuidle_unset_driver
  3. __cpuidle_set_driver
  4. __cpuidle_get_cpu_driver
  5. __cpuidle_set_driver
  6. __cpuidle_unset_driver
  7. cpuidle_setup_broadcast_timer
  8. __cpuidle_driver_init
  9. __cpuidle_register_driver
  10. __cpuidle_unregister_driver
  11. cpuidle_register_driver
  12. cpuidle_unregister_driver
  13. cpuidle_get_driver
  14. cpuidle_get_cpu_driver
  15. cpuidle_driver_ref
  16. cpuidle_driver_unref

   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 
  22 DEFINE_SPINLOCK(cpuidle_driver_lock);
  23 
  24 #ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
  25 
  26 static 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  */
  35 static 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  */
  48 static 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  */
  68 static 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 
  88 static 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  */
  97 static 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  */
 108 static 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  */
 125 static 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  */
 142 static 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  */
 154 static void __cpuidle_driver_init(struct cpuidle_driver *drv)
 155 {
 156         int i;
 157 
 158         drv->refcnt = 0;
 159 
 160         /*
 161          * Use all possible CPUs as the default, because if the kernel boots
 162          * with some CPUs offline and then we online one of them, the CPU
 163          * notifier has to know which driver to assign.
 164          */
 165         if (!drv->cpumask)
 166                 drv->cpumask = (struct cpumask *)cpu_possible_mask;
 167 
 168         /*
 169          * Look for the timer stop flag in the different states, so that we know
 170          * if the broadcast timer has to be set up.  The loop is in the reverse
 171          * order, because usually one of the deeper states have this flag set.
 172          */
 173         for (i = drv->state_count - 1; i >= 0 ; i--) {
 174                 if (drv->states[i].flags & CPUIDLE_FLAG_TIMER_STOP) {
 175                         drv->bctimer = 1;
 176                         break;
 177                 }
 178         }
 179 }
 180 
 181 /**
 182  * __cpuidle_register_driver: register the driver
 183  * @drv: a valid pointer to a struct cpuidle_driver
 184  *
 185  * Do some sanity checks, initialize the driver, assign the driver to the
 186  * global cpuidle driver variable(s) and set up the broadcast timer if the
 187  * cpuidle driver has some states that shut down the local timer.
 188  *
 189  * Returns 0 on success, a negative error code otherwise:
 190  *  * -EINVAL if the driver pointer is NULL or no idle states are available
 191  *  * -ENODEV if the cpuidle framework is disabled
 192  *  * -EBUSY if the driver is already assigned to the global variable(s)
 193  */
 194 static int __cpuidle_register_driver(struct cpuidle_driver *drv)
 195 {
 196         int ret;
 197 
 198         if (!drv || !drv->state_count)
 199                 return -EINVAL;
 200 
 201         ret = cpuidle_coupled_state_verify(drv);
 202         if (ret)
 203                 return ret;
 204 
 205         if (cpuidle_disabled())
 206                 return -ENODEV;
 207 
 208         __cpuidle_driver_init(drv);
 209 
 210         ret = __cpuidle_set_driver(drv);
 211         if (ret)
 212                 return ret;
 213 
 214         if (drv->bctimer)
 215                 on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
 216                                  (void *)1, 1);
 217 
 218         return 0;
 219 }
 220 
 221 /**
 222  * __cpuidle_unregister_driver - unregister the driver
 223  * @drv: a valid pointer to a struct cpuidle_driver
 224  *
 225  * Check if the driver is no longer in use, reset the global cpuidle driver
 226  * variable(s) and disable the timer broadcast notification mechanism if it was
 227  * in use.
 228  *
 229  */
 230 static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
 231 {
 232         if (WARN_ON(drv->refcnt > 0))
 233                 return;
 234 
 235         if (drv->bctimer) {
 236                 drv->bctimer = 0;
 237                 on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer,
 238                                  NULL, 1);
 239         }
 240 
 241         __cpuidle_unset_driver(drv);
 242 }
 243 
 244 /**
 245  * cpuidle_register_driver - registers a driver
 246  * @drv: a pointer to a valid struct cpuidle_driver
 247  *
 248  * Register the driver under a lock to prevent concurrent attempts to
 249  * [un]register the driver from occuring at the same time.
 250  *
 251  * Returns 0 on success, a negative error code (returned by
 252  * __cpuidle_register_driver()) otherwise.
 253  */
 254 int cpuidle_register_driver(struct cpuidle_driver *drv)
 255 {
 256         struct cpuidle_governor *gov;
 257         int ret;
 258 
 259         spin_lock(&cpuidle_driver_lock);
 260         ret = __cpuidle_register_driver(drv);
 261         spin_unlock(&cpuidle_driver_lock);
 262 
 263         if (!ret && !strlen(param_governor) && drv->governor &&
 264             (cpuidle_get_driver() == drv)) {
 265                 mutex_lock(&cpuidle_lock);
 266                 gov = cpuidle_find_governor(drv->governor);
 267                 if (gov) {
 268                         cpuidle_prev_governor = cpuidle_curr_governor;
 269                         if (cpuidle_switch_governor(gov) < 0)
 270                                 cpuidle_prev_governor = NULL;
 271                 }
 272                 mutex_unlock(&cpuidle_lock);
 273         }
 274 
 275         return ret;
 276 }
 277 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
 278 
 279 /**
 280  * cpuidle_unregister_driver - unregisters a driver
 281  * @drv: a pointer to a valid struct cpuidle_driver
 282  *
 283  * Unregisters the cpuidle driver under a lock to prevent concurrent attempts
 284  * to [un]register the driver from occuring at the same time.  @drv has to
 285  * match the currently registered driver.
 286  */
 287 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
 288 {
 289         bool enabled = (cpuidle_get_driver() == drv);
 290 
 291         spin_lock(&cpuidle_driver_lock);
 292         __cpuidle_unregister_driver(drv);
 293         spin_unlock(&cpuidle_driver_lock);
 294 
 295         if (!enabled)
 296                 return;
 297 
 298         mutex_lock(&cpuidle_lock);
 299         if (cpuidle_prev_governor) {
 300                 if (!cpuidle_switch_governor(cpuidle_prev_governor))
 301                         cpuidle_prev_governor = NULL;
 302         }
 303         mutex_unlock(&cpuidle_lock);
 304 }
 305 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
 306 
 307 /**
 308  * cpuidle_get_driver - return the driver tied to the current CPU.
 309  *
 310  * Returns a struct cpuidle_driver pointer, or NULL if no driver is registered.
 311  */
 312 struct cpuidle_driver *cpuidle_get_driver(void)
 313 {
 314         struct cpuidle_driver *drv;
 315         int cpu;
 316 
 317         cpu = get_cpu();
 318         drv = __cpuidle_get_cpu_driver(cpu);
 319         put_cpu();
 320 
 321         return drv;
 322 }
 323 EXPORT_SYMBOL_GPL(cpuidle_get_driver);
 324 
 325 /**
 326  * cpuidle_get_cpu_driver - return the driver registered for a CPU.
 327  * @dev: a valid pointer to a struct cpuidle_device
 328  *
 329  * Returns a struct cpuidle_driver pointer, or NULL if no driver is registered
 330  * for the CPU associated with @dev.
 331  */
 332 struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev)
 333 {
 334         if (!dev)
 335                 return NULL;
 336 
 337         return __cpuidle_get_cpu_driver(dev->cpu);
 338 }
 339 EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);
 340 
 341 /**
 342  * cpuidle_driver_ref - get a reference to the driver.
 343  *
 344  * Increment the reference counter of the cpuidle driver associated with
 345  * the current CPU.
 346  *
 347  * Returns a pointer to the driver, or NULL if the current CPU has no driver.
 348  */
 349 struct cpuidle_driver *cpuidle_driver_ref(void)
 350 {
 351         struct cpuidle_driver *drv;
 352 
 353         spin_lock(&cpuidle_driver_lock);
 354 
 355         drv = cpuidle_get_driver();
 356         if (drv)
 357                 drv->refcnt++;
 358 
 359         spin_unlock(&cpuidle_driver_lock);
 360         return drv;
 361 }
 362 
 363 /**
 364  * cpuidle_driver_unref - puts down the refcount for the driver
 365  *
 366  * Decrement the reference counter of the cpuidle driver associated with
 367  * the current CPU.
 368  */
 369 void cpuidle_driver_unref(void)
 370 {
 371         struct cpuidle_driver *drv;
 372 
 373         spin_lock(&cpuidle_driver_lock);
 374 
 375         drv = cpuidle_get_driver();
 376         if (drv && !WARN_ON(drv->refcnt <= 0))
 377                 drv->refcnt--;
 378 
 379         spin_unlock(&cpuidle_driver_lock);
 380 }

/* [<][>][^][v][top][bottom][index][help] */