Branch data Line data Source code
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 : 3 : static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu) 98 : : { 99 : 3 : 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 : 0 : static inline int __cpuidle_set_driver(struct cpuidle_driver *drv) 109 : : { 110 : 0 : if (cpuidle_curr_driver) 111 : : return -EBUSY; 112 : : 113 : 0 : cpuidle_curr_driver = drv; 114 : : 115 : 0 : 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 : 0 : static inline void __cpuidle_unset_driver(struct cpuidle_driver *drv) 126 : : { 127 : 0 : if (drv == cpuidle_curr_driver) 128 : 0 : 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 : 0 : static void cpuidle_setup_broadcast_timer(void *arg) 143 : : { 144 [ # # ]: 0 : if (arg) 145 : 0 : tick_broadcast_enable(); 146 : : else 147 : 0 : tick_broadcast_disable(); 148 : 0 : } 149 : : 150 : : /** 151 : : * __cpuidle_driver_init - initialize the driver's internal data 152 : : * @drv: a valid pointer to a struct cpuidle_driver 153 : : */ 154 : 0 : static void __cpuidle_driver_init(struct cpuidle_driver *drv) 155 : : { 156 : 0 : 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 [ # # ]: 0 : if (!drv->cpumask) 164 : 0 : drv->cpumask = (struct cpumask *)cpu_possible_mask; 165 : : 166 [ # # ]: 0 : for (i = 0; i < drv->state_count; i++) { 167 : 0 : 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 [ # # ]: 0 : if (s->flags & CPUIDLE_FLAG_TIMER_STOP) 175 : 0 : 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 [ # # ]: 0 : if (s->target_residency > 0) 183 : 0 : s->target_residency_ns = s->target_residency * NSEC_PER_USEC; 184 : : 185 [ # # ]: 0 : if (s->exit_latency > 0) 186 : 0 : s->exit_latency_ns = s->exit_latency * NSEC_PER_USEC; 187 : : } 188 : 0 : } 189 : : 190 : : /** 191 : : * __cpuidle_register_driver: register the driver 192 : : * @drv: a valid pointer to a struct cpuidle_driver 193 : : * 194 : : * Do some sanity checks, initialize the driver, assign the driver to the 195 : : * global cpuidle driver variable(s) and set up the broadcast timer if the 196 : : * cpuidle driver has some states that shut down the local timer. 197 : : * 198 : : * Returns 0 on success, a negative error code otherwise: 199 : : * * -EINVAL if the driver pointer is NULL or no idle states are available 200 : : * * -ENODEV if the cpuidle framework is disabled 201 : : * * -EBUSY if the driver is already assigned to the global variable(s) 202 : : */ 203 : 0 : static int __cpuidle_register_driver(struct cpuidle_driver *drv) 204 : : { 205 : 0 : int ret; 206 : : 207 [ # # # # ]: 0 : if (!drv || !drv->state_count) 208 : : return -EINVAL; 209 : : 210 : 0 : ret = cpuidle_coupled_state_verify(drv); 211 : 0 : if (ret) 212 : : return ret; 213 : : 214 [ # # ]: 0 : if (cpuidle_disabled()) 215 : : return -ENODEV; 216 : : 217 : 0 : __cpuidle_driver_init(drv); 218 : : 219 [ # # ]: 0 : ret = __cpuidle_set_driver(drv); 220 : 0 : if (ret) 221 : : return ret; 222 : : 223 [ # # ]: 0 : if (drv->bctimer) 224 : 0 : on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, 225 : : (void *)1, 1); 226 : : 227 : : return 0; 228 : : } 229 : : 230 : : /** 231 : : * __cpuidle_unregister_driver - unregister the driver 232 : : * @drv: a valid pointer to a struct cpuidle_driver 233 : : * 234 : : * Check if the driver is no longer in use, reset the global cpuidle driver 235 : : * variable(s) and disable the timer broadcast notification mechanism if it was 236 : : * in use. 237 : : * 238 : : */ 239 : 0 : static void __cpuidle_unregister_driver(struct cpuidle_driver *drv) 240 : : { 241 [ # # ]: 0 : if (drv->bctimer) { 242 : 0 : drv->bctimer = 0; 243 : 0 : on_each_cpu_mask(drv->cpumask, cpuidle_setup_broadcast_timer, 244 : : NULL, 1); 245 : : } 246 : : 247 [ # # ]: 0 : __cpuidle_unset_driver(drv); 248 : 0 : } 249 : : 250 : : /** 251 : : * cpuidle_register_driver - registers a driver 252 : : * @drv: a pointer to a valid struct cpuidle_driver 253 : : * 254 : : * Register the driver under a lock to prevent concurrent attempts to 255 : : * [un]register the driver from occuring at the same time. 256 : : * 257 : : * Returns 0 on success, a negative error code (returned by 258 : : * __cpuidle_register_driver()) otherwise. 259 : : */ 260 : 0 : int cpuidle_register_driver(struct cpuidle_driver *drv) 261 : : { 262 : 0 : struct cpuidle_governor *gov; 263 : 0 : int ret; 264 : : 265 : 0 : spin_lock(&cpuidle_driver_lock); 266 : 0 : ret = __cpuidle_register_driver(drv); 267 : 0 : spin_unlock(&cpuidle_driver_lock); 268 : : 269 [ # # # # : 0 : if (!ret && !strlen(param_governor) && drv->governor && # # ] 270 : : (cpuidle_get_driver() == drv)) { 271 : 0 : mutex_lock(&cpuidle_lock); 272 : 0 : gov = cpuidle_find_governor(drv->governor); 273 [ # # ]: 0 : if (gov) { 274 : 0 : cpuidle_prev_governor = cpuidle_curr_governor; 275 [ # # ]: 0 : if (cpuidle_switch_governor(gov) < 0) 276 : 0 : cpuidle_prev_governor = NULL; 277 : : } 278 : 0 : mutex_unlock(&cpuidle_lock); 279 : : } 280 : : 281 : 0 : return ret; 282 : : } 283 : : EXPORT_SYMBOL_GPL(cpuidle_register_driver); 284 : : 285 : : /** 286 : : * cpuidle_unregister_driver - unregisters a driver 287 : : * @drv: a pointer to a valid struct cpuidle_driver 288 : : * 289 : : * Unregisters the cpuidle driver under a lock to prevent concurrent attempts 290 : : * to [un]register the driver from occuring at the same time. @drv has to 291 : : * match the currently registered driver. 292 : : */ 293 : 0 : void cpuidle_unregister_driver(struct cpuidle_driver *drv) 294 : : { 295 : 0 : bool enabled = (cpuidle_get_driver() == drv); 296 : : 297 : 0 : spin_lock(&cpuidle_driver_lock); 298 : 0 : __cpuidle_unregister_driver(drv); 299 : 0 : spin_unlock(&cpuidle_driver_lock); 300 : : 301 [ # # ]: 0 : if (!enabled) 302 : : return; 303 : : 304 : 0 : mutex_lock(&cpuidle_lock); 305 [ # # ]: 0 : if (cpuidle_prev_governor) { 306 [ # # ]: 0 : if (!cpuidle_switch_governor(cpuidle_prev_governor)) 307 : 0 : cpuidle_prev_governor = NULL; 308 : : } 309 : 0 : mutex_unlock(&cpuidle_lock); 310 : : } 311 : : EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); 312 : : 313 : : /** 314 : : * cpuidle_get_driver - return the driver tied to the current CPU. 315 : : * 316 : : * Returns a struct cpuidle_driver pointer, or NULL if no driver is registered. 317 : : */ 318 : 3 : struct cpuidle_driver *cpuidle_get_driver(void) 319 : : { 320 : 3 : struct cpuidle_driver *drv; 321 : 3 : int cpu; 322 : : 323 : 3 : cpu = get_cpu(); 324 : 3 : drv = __cpuidle_get_cpu_driver(cpu); 325 : 3 : put_cpu(); 326 : : 327 [ # # ]: 0 : return drv; 328 : : } 329 : : EXPORT_SYMBOL_GPL(cpuidle_get_driver); 330 : : 331 : : /** 332 : : * cpuidle_get_cpu_driver - return the driver registered for a CPU. 333 : : * @dev: a valid pointer to a struct cpuidle_device 334 : : * 335 : : * Returns a struct cpuidle_driver pointer, or NULL if no driver is registered 336 : : * for the CPU associated with @dev. 337 : : */ 338 : 1135 : struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev) 339 : : { 340 [ - + ]: 1135 : if (!dev) 341 : : return NULL; 342 : : 343 : 0 : return __cpuidle_get_cpu_driver(dev->cpu); 344 : : } 345 : : EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver); 346 : : 347 : : /** 348 : : * cpuidle_driver_state_disabled - Disable or enable an idle state 349 : : * @drv: cpuidle driver owning the state 350 : : * @idx: State index 351 : : * @disable: Whether or not to disable the state 352 : : */ 353 : 0 : void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx, 354 : : bool disable) 355 : : { 356 : 0 : unsigned int cpu; 357 : : 358 : 0 : mutex_lock(&cpuidle_lock); 359 : : 360 : 0 : spin_lock(&cpuidle_driver_lock); 361 : : 362 [ # # ]: 0 : if (!drv->cpumask) { 363 : 0 : drv->states[idx].flags |= CPUIDLE_FLAG_UNUSABLE; 364 : 0 : goto unlock; 365 : : } 366 : : 367 [ # # ]: 0 : for_each_cpu(cpu, drv->cpumask) { 368 : 0 : struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu); 369 : : 370 [ # # ]: 0 : if (!dev) 371 : 0 : continue; 372 : : 373 [ # # ]: 0 : if (disable) 374 : 0 : dev->states_usage[idx].disable |= CPUIDLE_STATE_DISABLED_BY_DRIVER; 375 : : else 376 : 0 : dev->states_usage[idx].disable &= ~CPUIDLE_STATE_DISABLED_BY_DRIVER; 377 : : } 378 : : 379 : 0 : unlock: 380 : 0 : spin_unlock(&cpuidle_driver_lock); 381 : : 382 : 0 : mutex_unlock(&cpuidle_lock); 383 : 0 : }