Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'pm-devfreq' into pm-for-linus

* pm-devfreq:
PM / devfreq: Add basic governors
PM / devfreq: Add common sysfs interfaces
PM: Introduce devfreq: generic DVFS framework with device-specific OPPs
PM / OPP: Add OPP availability change notifier.

+1303
+52
Documentation/ABI/testing/sysfs-class-devfreq
··· 1 + What: /sys/class/devfreq/.../ 2 + Date: September 2011 3 + Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 4 + Description: 5 + Provide a place in sysfs for the devfreq objects. 6 + This allows accessing various devfreq specific variables. 7 + The name of devfreq object denoted as ... is same as the 8 + name of device using devfreq. 9 + 10 + What: /sys/class/devfreq/.../governor 11 + Date: September 2011 12 + Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 13 + Description: 14 + The /sys/class/devfreq/.../governor shows the name of the 15 + governor used by the corresponding devfreq object. 16 + 17 + What: /sys/class/devfreq/.../cur_freq 18 + Date: September 2011 19 + Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 20 + Description: 21 + The /sys/class/devfreq/.../cur_freq shows the current 22 + frequency of the corresponding devfreq object. 23 + 24 + What: /sys/class/devfreq/.../central_polling 25 + Date: September 2011 26 + Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 27 + Description: 28 + The /sys/class/devfreq/.../central_polling shows whether 29 + the devfreq ojbect is using devfreq-provided central 30 + polling mechanism or not. 31 + 32 + What: /sys/class/devfreq/.../polling_interval 33 + Date: September 2011 34 + Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 35 + Description: 36 + The /sys/class/devfreq/.../polling_interval shows and sets 37 + the requested polling interval of the corresponding devfreq 38 + object. The values are represented in ms. If the value is 39 + less than 1 jiffy, it is considered to be 0, which means 40 + no polling. This value is meaningless if the governor is 41 + not polling; thus. If the governor is not using 42 + devfreq-provided central polling 43 + (/sys/class/devfreq/.../central_polling is 0), this value 44 + may be useless. 45 + 46 + What: /sys/class/devfreq/.../userspace/set_freq 47 + Date: September 2011 48 + Contact: MyungJoo Ham <myungjoo.ham@samsung.com> 49 + Description: 50 + The /sys/class/devfreq/.../userspace/set_freq shows and 51 + sets the requested frequency for the devfreq object if 52 + userspace governor is in effect.
+2
drivers/Kconfig
··· 130 130 131 131 source "drivers/virt/Kconfig" 132 132 133 + source "drivers/devfreq/Kconfig" 134 + 133 135 endmenu
+2
drivers/Makefile
··· 127 127 128 128 # Virtualization drivers 129 129 obj-$(CONFIG_VIRT_DRIVERS) += virt/ 130 + 131 + obj-$(CONFIG_PM_DEVFREQ) += devfreq/
+30
drivers/base/power/opp.c
··· 73 73 * RCU usage: nodes are not modified in the list of device_opp, 74 74 * however addition is possible and is secured by dev_opp_list_lock 75 75 * @dev: device pointer 76 + * @head: notifier head to notify the OPP availability changes. 76 77 * @opp_list: list of opps 77 78 * 78 79 * This is an internal data structure maintaining the link to opps attached to ··· 84 83 struct list_head node; 85 84 86 85 struct device *dev; 86 + struct srcu_notifier_head head; 87 87 struct list_head opp_list; 88 88 }; 89 89 ··· 406 404 } 407 405 408 406 dev_opp->dev = dev; 407 + srcu_init_notifier_head(&dev_opp->head); 409 408 INIT_LIST_HEAD(&dev_opp->opp_list); 410 409 411 410 /* Secure the device list modification */ ··· 431 428 list_add_rcu(&new_opp->node, head); 432 429 mutex_unlock(&dev_opp_list_lock); 433 430 431 + /* 432 + * Notify the changes in the availability of the operable 433 + * frequency/voltage list. 434 + */ 435 + srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp); 434 436 return 0; 435 437 } 436 438 ··· 511 503 list_replace_rcu(&opp->node, &new_opp->node); 512 504 mutex_unlock(&dev_opp_list_lock); 513 505 synchronize_rcu(); 506 + 507 + /* Notify the change of the OPP availability */ 508 + if (availability_req) 509 + srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ENABLE, 510 + new_opp); 511 + else 512 + srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE, 513 + new_opp); 514 514 515 515 /* clean up old opp */ 516 516 new_opp = opp; ··· 659 643 *table = NULL; 660 644 } 661 645 #endif /* CONFIG_CPU_FREQ */ 646 + 647 + /** 648 + * opp_get_notifier() - find notifier_head of the device with opp 649 + * @dev: device pointer used to lookup device OPPs. 650 + */ 651 + struct srcu_notifier_head *opp_get_notifier(struct device *dev) 652 + { 653 + struct device_opp *dev_opp = find_device_opp(dev); 654 + 655 + if (IS_ERR(dev_opp)) 656 + return ERR_PTR(PTR_ERR(dev_opp)); /* matching type */ 657 + 658 + return &dev_opp->head; 659 + }
+75
drivers/devfreq/Kconfig
··· 1 + config ARCH_HAS_DEVFREQ 2 + bool 3 + depends on ARCH_HAS_OPP 4 + help 5 + Denotes that the architecture supports DEVFREQ. If the architecture 6 + supports multiple OPP entries per device and the frequency of the 7 + devices with OPPs may be altered dynamically, the architecture 8 + supports DEVFREQ. 9 + 10 + menuconfig PM_DEVFREQ 11 + bool "Generic Dynamic Voltage and Frequency Scaling (DVFS) support" 12 + depends on PM_OPP && ARCH_HAS_DEVFREQ 13 + help 14 + With OPP support, a device may have a list of frequencies and 15 + voltages available. DEVFREQ, a generic DVFS framework can be 16 + registered for a device with OPP support in order to let the 17 + governor provided to DEVFREQ choose an operating frequency 18 + based on the OPP's list and the policy given with DEVFREQ. 19 + 20 + Each device may have its own governor and policy. DEVFREQ can 21 + reevaluate the device state periodically and/or based on the 22 + OPP list changes (each frequency/voltage pair in OPP may be 23 + disabled or enabled). 24 + 25 + Like some CPUs with CPUFREQ, a device may have multiple clocks. 26 + However, because the clock frequencies of a single device are 27 + determined by the single device's state, an instance of DEVFREQ 28 + is attached to a single device and returns a "representative" 29 + clock frequency from the OPP of the device, which is also attached 30 + to a device by 1-to-1. The device registering DEVFREQ takes the 31 + responsiblity to "interpret" the frequency listed in OPP and 32 + to set its every clock accordingly with the "target" callback 33 + given to DEVFREQ. 34 + 35 + if PM_DEVFREQ 36 + 37 + comment "DEVFREQ Governors" 38 + 39 + config DEVFREQ_GOV_SIMPLE_ONDEMAND 40 + bool "Simple Ondemand" 41 + help 42 + Chooses frequency based on the recent load on the device. Works 43 + similar as ONDEMAND governor of CPUFREQ does. A device with 44 + Simple-Ondemand should be able to provide busy/total counter 45 + values that imply the usage rate. A device may provide tuned 46 + values to the governor with data field at devfreq_add_device(). 47 + 48 + config DEVFREQ_GOV_PERFORMANCE 49 + bool "Performance" 50 + help 51 + Sets the frequency at the maximum available frequency. 52 + This governor always returns UINT_MAX as frequency so that 53 + the DEVFREQ framework returns the highest frequency available 54 + at any time. 55 + 56 + config DEVFREQ_GOV_POWERSAVE 57 + bool "Powersave" 58 + help 59 + Sets the frequency at the minimum available frequency. 60 + This governor always returns 0 as frequency so that 61 + the DEVFREQ framework returns the lowest frequency available 62 + at any time. 63 + 64 + config DEVFREQ_GOV_USERSPACE 65 + bool "Userspace" 66 + help 67 + Sets the frequency at the user specified one. 68 + This governor returns the user configured frequency if there 69 + has been an input to /sys/devices/.../power/devfreq_set_freq. 70 + Otherwise, the governor does not change the frequnecy 71 + given at the initialization. 72 + 73 + comment "DEVFREQ Drivers" 74 + 75 + endif # PM_DEVFREQ
+5
drivers/devfreq/Makefile
··· 1 + obj-$(CONFIG_PM_DEVFREQ) += devfreq.o 2 + obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) += governor_simpleondemand.o 3 + obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE) += governor_performance.o 4 + obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE) += governor_powersave.o 5 + obj-$(CONFIG_DEVFREQ_GOV_USERSPACE) += governor_userspace.o
+601
drivers/devfreq/devfreq.c
··· 1 + /* 2 + * devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework 3 + * for Non-CPU Devices. 4 + * 5 + * Copyright (C) 2011 Samsung Electronics 6 + * MyungJoo Ham <myungjoo.ham@samsung.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + #include <linux/kernel.h> 14 + #include <linux/sched.h> 15 + #include <linux/errno.h> 16 + #include <linux/err.h> 17 + #include <linux/init.h> 18 + #include <linux/slab.h> 19 + #include <linux/opp.h> 20 + #include <linux/devfreq.h> 21 + #include <linux/workqueue.h> 22 + #include <linux/platform_device.h> 23 + #include <linux/list.h> 24 + #include <linux/printk.h> 25 + #include <linux/hrtimer.h> 26 + #include "governor.h" 27 + 28 + struct class *devfreq_class; 29 + 30 + /* 31 + * devfreq_work periodically monitors every registered device. 32 + * The minimum polling interval is one jiffy. The polling interval is 33 + * determined by the minimum polling period among all polling devfreq 34 + * devices. The resolution of polling interval is one jiffy. 35 + */ 36 + static bool polling; 37 + static struct workqueue_struct *devfreq_wq; 38 + static struct delayed_work devfreq_work; 39 + 40 + /* wait removing if this is to be removed */ 41 + static struct devfreq *wait_remove_device; 42 + 43 + /* The list of all device-devfreq */ 44 + static LIST_HEAD(devfreq_list); 45 + static DEFINE_MUTEX(devfreq_list_lock); 46 + 47 + /** 48 + * find_device_devfreq() - find devfreq struct using device pointer 49 + * @dev: device pointer used to lookup device devfreq. 50 + * 51 + * Search the list of device devfreqs and return the matched device's 52 + * devfreq info. devfreq_list_lock should be held by the caller. 53 + */ 54 + static struct devfreq *find_device_devfreq(struct device *dev) 55 + { 56 + struct devfreq *tmp_devfreq; 57 + 58 + if (unlikely(IS_ERR_OR_NULL(dev))) { 59 + pr_err("DEVFREQ: %s: Invalid parameters\n", __func__); 60 + return ERR_PTR(-EINVAL); 61 + } 62 + WARN(!mutex_is_locked(&devfreq_list_lock), 63 + "devfreq_list_lock must be locked."); 64 + 65 + list_for_each_entry(tmp_devfreq, &devfreq_list, node) { 66 + if (tmp_devfreq->dev.parent == dev) 67 + return tmp_devfreq; 68 + } 69 + 70 + return ERR_PTR(-ENODEV); 71 + } 72 + 73 + /** 74 + * update_devfreq() - Reevaluate the device and configure frequency. 75 + * @devfreq: the devfreq instance. 76 + * 77 + * Note: Lock devfreq->lock before calling update_devfreq 78 + * This function is exported for governors. 79 + */ 80 + int update_devfreq(struct devfreq *devfreq) 81 + { 82 + unsigned long freq; 83 + int err = 0; 84 + 85 + if (!mutex_is_locked(&devfreq->lock)) { 86 + WARN(true, "devfreq->lock must be locked by the caller.\n"); 87 + return -EINVAL; 88 + } 89 + 90 + /* Reevaluate the proper frequency */ 91 + err = devfreq->governor->get_target_freq(devfreq, &freq); 92 + if (err) 93 + return err; 94 + 95 + err = devfreq->profile->target(devfreq->dev.parent, &freq); 96 + if (err) 97 + return err; 98 + 99 + devfreq->previous_freq = freq; 100 + return err; 101 + } 102 + 103 + /** 104 + * devfreq_notifier_call() - Notify that the device frequency requirements 105 + * has been changed out of devfreq framework. 106 + * @nb the notifier_block (supposed to be devfreq->nb) 107 + * @type not used 108 + * @devp not used 109 + * 110 + * Called by a notifier that uses devfreq->nb. 111 + */ 112 + static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type, 113 + void *devp) 114 + { 115 + struct devfreq *devfreq = container_of(nb, struct devfreq, nb); 116 + int ret; 117 + 118 + mutex_lock(&devfreq->lock); 119 + ret = update_devfreq(devfreq); 120 + mutex_unlock(&devfreq->lock); 121 + 122 + return ret; 123 + } 124 + 125 + /** 126 + * _remove_devfreq() - Remove devfreq from the device. 127 + * @devfreq: the devfreq struct 128 + * @skip: skip calling device_unregister(). 129 + * 130 + * Note that the caller should lock devfreq->lock before calling 131 + * this. _remove_devfreq() will unlock it and free devfreq 132 + * internally. devfreq_list_lock should be locked by the caller 133 + * as well (not relased at return) 134 + * 135 + * Lock usage: 136 + * devfreq->lock: locked before call. 137 + * unlocked at return (and freed) 138 + * devfreq_list_lock: locked before call. 139 + * kept locked at return. 140 + * if devfreq is centrally polled. 141 + * 142 + * Freed memory: 143 + * devfreq 144 + */ 145 + static void _remove_devfreq(struct devfreq *devfreq, bool skip) 146 + { 147 + if (!mutex_is_locked(&devfreq->lock)) { 148 + WARN(true, "devfreq->lock must be locked by the caller.\n"); 149 + return; 150 + } 151 + if (!devfreq->governor->no_central_polling && 152 + !mutex_is_locked(&devfreq_list_lock)) { 153 + WARN(true, "devfreq_list_lock must be locked by the caller.\n"); 154 + return; 155 + } 156 + 157 + if (devfreq->being_removed) 158 + return; 159 + 160 + devfreq->being_removed = true; 161 + 162 + if (devfreq->profile->exit) 163 + devfreq->profile->exit(devfreq->dev.parent); 164 + 165 + if (devfreq->governor->exit) 166 + devfreq->governor->exit(devfreq); 167 + 168 + if (!skip && get_device(&devfreq->dev)) { 169 + device_unregister(&devfreq->dev); 170 + put_device(&devfreq->dev); 171 + } 172 + 173 + if (!devfreq->governor->no_central_polling) 174 + list_del(&devfreq->node); 175 + 176 + mutex_unlock(&devfreq->lock); 177 + mutex_destroy(&devfreq->lock); 178 + 179 + kfree(devfreq); 180 + } 181 + 182 + /** 183 + * devfreq_dev_release() - Callback for struct device to release the device. 184 + * @dev: the devfreq device 185 + * 186 + * This calls _remove_devfreq() if _remove_devfreq() is not called. 187 + * Note that devfreq_dev_release() could be called by _remove_devfreq() as 188 + * well as by others unregistering the device. 189 + */ 190 + static void devfreq_dev_release(struct device *dev) 191 + { 192 + struct devfreq *devfreq = to_devfreq(dev); 193 + bool central_polling = !devfreq->governor->no_central_polling; 194 + 195 + /* 196 + * If devfreq_dev_release() was called by device_unregister() of 197 + * _remove_devfreq(), we cannot mutex_lock(&devfreq->lock) and 198 + * being_removed is already set. This also partially checks the case 199 + * where devfreq_dev_release() is called from a thread other than 200 + * the one called _remove_devfreq(); however, this case is 201 + * dealt completely with another following being_removed check. 202 + * 203 + * Because being_removed is never being 204 + * unset, we do not need to worry about race conditions on 205 + * being_removed. 206 + */ 207 + if (devfreq->being_removed) 208 + return; 209 + 210 + if (central_polling) 211 + mutex_lock(&devfreq_list_lock); 212 + 213 + mutex_lock(&devfreq->lock); 214 + 215 + /* 216 + * Check being_removed flag again for the case where 217 + * devfreq_dev_release() was called in a thread other than the one 218 + * possibly called _remove_devfreq(). 219 + */ 220 + if (devfreq->being_removed) { 221 + mutex_unlock(&devfreq->lock); 222 + goto out; 223 + } 224 + 225 + /* devfreq->lock is unlocked and removed in _removed_devfreq() */ 226 + _remove_devfreq(devfreq, true); 227 + 228 + out: 229 + if (central_polling) 230 + mutex_unlock(&devfreq_list_lock); 231 + } 232 + 233 + /** 234 + * devfreq_monitor() - Periodically poll devfreq objects. 235 + * @work: the work struct used to run devfreq_monitor periodically. 236 + * 237 + */ 238 + static void devfreq_monitor(struct work_struct *work) 239 + { 240 + static unsigned long last_polled_at; 241 + struct devfreq *devfreq, *tmp; 242 + int error; 243 + unsigned long jiffies_passed; 244 + unsigned long next_jiffies = ULONG_MAX, now = jiffies; 245 + struct device *dev; 246 + 247 + /* Initially last_polled_at = 0, polling every device at bootup */ 248 + jiffies_passed = now - last_polled_at; 249 + last_polled_at = now; 250 + if (jiffies_passed == 0) 251 + jiffies_passed = 1; 252 + 253 + mutex_lock(&devfreq_list_lock); 254 + list_for_each_entry_safe(devfreq, tmp, &devfreq_list, node) { 255 + mutex_lock(&devfreq->lock); 256 + dev = devfreq->dev.parent; 257 + 258 + /* Do not remove tmp for a while */ 259 + wait_remove_device = tmp; 260 + 261 + if (devfreq->governor->no_central_polling || 262 + devfreq->next_polling == 0) { 263 + mutex_unlock(&devfreq->lock); 264 + continue; 265 + } 266 + mutex_unlock(&devfreq_list_lock); 267 + 268 + /* 269 + * Reduce more next_polling if devfreq_wq took an extra 270 + * delay. (i.e., CPU has been idled.) 271 + */ 272 + if (devfreq->next_polling <= jiffies_passed) { 273 + error = update_devfreq(devfreq); 274 + 275 + /* Remove a devfreq with an error. */ 276 + if (error && error != -EAGAIN) { 277 + 278 + dev_err(dev, "Due to update_devfreq error(%d), devfreq(%s) is removed from the device\n", 279 + error, devfreq->governor->name); 280 + 281 + /* 282 + * Unlock devfreq before locking the list 283 + * in order to avoid deadlock with 284 + * find_device_devfreq or others 285 + */ 286 + mutex_unlock(&devfreq->lock); 287 + mutex_lock(&devfreq_list_lock); 288 + /* Check if devfreq is already removed */ 289 + if (IS_ERR(find_device_devfreq(dev))) 290 + continue; 291 + mutex_lock(&devfreq->lock); 292 + /* This unlocks devfreq->lock and free it */ 293 + _remove_devfreq(devfreq, false); 294 + continue; 295 + } 296 + devfreq->next_polling = devfreq->polling_jiffies; 297 + } else { 298 + devfreq->next_polling -= jiffies_passed; 299 + } 300 + 301 + if (devfreq->next_polling) 302 + next_jiffies = (next_jiffies > devfreq->next_polling) ? 303 + devfreq->next_polling : next_jiffies; 304 + 305 + mutex_unlock(&devfreq->lock); 306 + mutex_lock(&devfreq_list_lock); 307 + } 308 + wait_remove_device = NULL; 309 + mutex_unlock(&devfreq_list_lock); 310 + 311 + if (next_jiffies > 0 && next_jiffies < ULONG_MAX) { 312 + polling = true; 313 + queue_delayed_work(devfreq_wq, &devfreq_work, next_jiffies); 314 + } else { 315 + polling = false; 316 + } 317 + } 318 + 319 + /** 320 + * devfreq_add_device() - Add devfreq feature to the device 321 + * @dev: the device to add devfreq feature. 322 + * @profile: device-specific profile to run devfreq. 323 + * @governor: the policy to choose frequency. 324 + * @data: private data for the governor. The devfreq framework does not 325 + * touch this value. 326 + */ 327 + struct devfreq *devfreq_add_device(struct device *dev, 328 + struct devfreq_dev_profile *profile, 329 + const struct devfreq_governor *governor, 330 + void *data) 331 + { 332 + struct devfreq *devfreq; 333 + int err = 0; 334 + 335 + if (!dev || !profile || !governor) { 336 + dev_err(dev, "%s: Invalid parameters.\n", __func__); 337 + return ERR_PTR(-EINVAL); 338 + } 339 + 340 + 341 + if (!governor->no_central_polling) { 342 + mutex_lock(&devfreq_list_lock); 343 + devfreq = find_device_devfreq(dev); 344 + mutex_unlock(&devfreq_list_lock); 345 + if (!IS_ERR(devfreq)) { 346 + dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__); 347 + err = -EINVAL; 348 + goto out; 349 + } 350 + } 351 + 352 + devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL); 353 + if (!devfreq) { 354 + dev_err(dev, "%s: Unable to create devfreq for the device\n", 355 + __func__); 356 + err = -ENOMEM; 357 + goto out; 358 + } 359 + 360 + mutex_init(&devfreq->lock); 361 + mutex_lock(&devfreq->lock); 362 + devfreq->dev.parent = dev; 363 + devfreq->dev.class = devfreq_class; 364 + devfreq->dev.release = devfreq_dev_release; 365 + devfreq->profile = profile; 366 + devfreq->governor = governor; 367 + devfreq->previous_freq = profile->initial_freq; 368 + devfreq->data = data; 369 + devfreq->next_polling = devfreq->polling_jiffies 370 + = msecs_to_jiffies(devfreq->profile->polling_ms); 371 + devfreq->nb.notifier_call = devfreq_notifier_call; 372 + 373 + dev_set_name(&devfreq->dev, dev_name(dev)); 374 + err = device_register(&devfreq->dev); 375 + if (err) { 376 + put_device(&devfreq->dev); 377 + goto err_dev; 378 + } 379 + 380 + if (governor->init) 381 + err = governor->init(devfreq); 382 + if (err) 383 + goto err_init; 384 + 385 + mutex_unlock(&devfreq->lock); 386 + 387 + if (governor->no_central_polling) 388 + goto out; 389 + 390 + mutex_lock(&devfreq_list_lock); 391 + 392 + list_add(&devfreq->node, &devfreq_list); 393 + 394 + if (devfreq_wq && devfreq->next_polling && !polling) { 395 + polling = true; 396 + queue_delayed_work(devfreq_wq, &devfreq_work, 397 + devfreq->next_polling); 398 + } 399 + mutex_unlock(&devfreq_list_lock); 400 + goto out; 401 + err_init: 402 + device_unregister(&devfreq->dev); 403 + err_dev: 404 + mutex_unlock(&devfreq->lock); 405 + kfree(devfreq); 406 + out: 407 + if (err) 408 + return ERR_PTR(err); 409 + else 410 + return devfreq; 411 + } 412 + 413 + /** 414 + * devfreq_remove_device() - Remove devfreq feature from a device. 415 + * @devfreq the devfreq instance to be removed 416 + */ 417 + int devfreq_remove_device(struct devfreq *devfreq) 418 + { 419 + if (!devfreq) 420 + return -EINVAL; 421 + 422 + if (!devfreq->governor->no_central_polling) { 423 + mutex_lock(&devfreq_list_lock); 424 + while (wait_remove_device == devfreq) { 425 + mutex_unlock(&devfreq_list_lock); 426 + schedule(); 427 + mutex_lock(&devfreq_list_lock); 428 + } 429 + } 430 + 431 + mutex_lock(&devfreq->lock); 432 + _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */ 433 + 434 + if (!devfreq->governor->no_central_polling) 435 + mutex_unlock(&devfreq_list_lock); 436 + 437 + return 0; 438 + } 439 + 440 + static ssize_t show_governor(struct device *dev, 441 + struct device_attribute *attr, char *buf) 442 + { 443 + return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name); 444 + } 445 + 446 + static ssize_t show_freq(struct device *dev, 447 + struct device_attribute *attr, char *buf) 448 + { 449 + return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq); 450 + } 451 + 452 + static ssize_t show_polling_interval(struct device *dev, 453 + struct device_attribute *attr, char *buf) 454 + { 455 + return sprintf(buf, "%d\n", to_devfreq(dev)->profile->polling_ms); 456 + } 457 + 458 + static ssize_t store_polling_interval(struct device *dev, 459 + struct device_attribute *attr, 460 + const char *buf, size_t count) 461 + { 462 + struct devfreq *df = to_devfreq(dev); 463 + unsigned int value; 464 + int ret; 465 + 466 + ret = sscanf(buf, "%u", &value); 467 + if (ret != 1) 468 + goto out; 469 + 470 + mutex_lock(&df->lock); 471 + df->profile->polling_ms = value; 472 + df->next_polling = df->polling_jiffies 473 + = msecs_to_jiffies(value); 474 + mutex_unlock(&df->lock); 475 + 476 + ret = count; 477 + 478 + if (df->governor->no_central_polling) 479 + goto out; 480 + 481 + mutex_lock(&devfreq_list_lock); 482 + if (df->next_polling > 0 && !polling) { 483 + polling = true; 484 + queue_delayed_work(devfreq_wq, &devfreq_work, 485 + df->next_polling); 486 + } 487 + mutex_unlock(&devfreq_list_lock); 488 + out: 489 + return ret; 490 + } 491 + 492 + static ssize_t show_central_polling(struct device *dev, 493 + struct device_attribute *attr, char *buf) 494 + { 495 + return sprintf(buf, "%d\n", 496 + !to_devfreq(dev)->governor->no_central_polling); 497 + } 498 + 499 + static struct device_attribute devfreq_attrs[] = { 500 + __ATTR(governor, S_IRUGO, show_governor, NULL), 501 + __ATTR(cur_freq, S_IRUGO, show_freq, NULL), 502 + __ATTR(central_polling, S_IRUGO, show_central_polling, NULL), 503 + __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval, 504 + store_polling_interval), 505 + { }, 506 + }; 507 + 508 + /** 509 + * devfreq_start_polling() - Initialize data structure for devfreq framework and 510 + * start polling registered devfreq devices. 511 + */ 512 + static int __init devfreq_start_polling(void) 513 + { 514 + mutex_lock(&devfreq_list_lock); 515 + polling = false; 516 + devfreq_wq = create_freezable_workqueue("devfreq_wq"); 517 + INIT_DELAYED_WORK_DEFERRABLE(&devfreq_work, devfreq_monitor); 518 + mutex_unlock(&devfreq_list_lock); 519 + 520 + devfreq_monitor(&devfreq_work.work); 521 + return 0; 522 + } 523 + late_initcall(devfreq_start_polling); 524 + 525 + static int __init devfreq_init(void) 526 + { 527 + devfreq_class = class_create(THIS_MODULE, "devfreq"); 528 + if (IS_ERR(devfreq_class)) { 529 + pr_err("%s: couldn't create class\n", __FILE__); 530 + return PTR_ERR(devfreq_class); 531 + } 532 + devfreq_class->dev_attrs = devfreq_attrs; 533 + return 0; 534 + } 535 + subsys_initcall(devfreq_init); 536 + 537 + static void __exit devfreq_exit(void) 538 + { 539 + class_destroy(devfreq_class); 540 + } 541 + module_exit(devfreq_exit); 542 + 543 + /* 544 + * The followings are helper functions for devfreq user device drivers with 545 + * OPP framework. 546 + */ 547 + 548 + /** 549 + * devfreq_recommended_opp() - Helper function to get proper OPP for the 550 + * freq value given to target callback. 551 + * @dev The devfreq user device. (parent of devfreq) 552 + * @freq The frequency given to target function 553 + * 554 + */ 555 + struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) 556 + { 557 + struct opp *opp = opp_find_freq_ceil(dev, freq); 558 + 559 + if (opp == ERR_PTR(-ENODEV)) 560 + opp = opp_find_freq_floor(dev, freq); 561 + return opp; 562 + } 563 + 564 + /** 565 + * devfreq_register_opp_notifier() - Helper function to get devfreq notified 566 + * for any changes in the OPP availability 567 + * changes 568 + * @dev The devfreq user device. (parent of devfreq) 569 + * @devfreq The devfreq object. 570 + */ 571 + int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq) 572 + { 573 + struct srcu_notifier_head *nh = opp_get_notifier(dev); 574 + 575 + if (IS_ERR(nh)) 576 + return PTR_ERR(nh); 577 + return srcu_notifier_chain_register(nh, &devfreq->nb); 578 + } 579 + 580 + /** 581 + * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq 582 + * notified for any changes in the OPP 583 + * availability changes anymore. 584 + * @dev The devfreq user device. (parent of devfreq) 585 + * @devfreq The devfreq object. 586 + * 587 + * At exit() callback of devfreq_dev_profile, this must be included if 588 + * devfreq_recommended_opp is used. 589 + */ 590 + int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq) 591 + { 592 + struct srcu_notifier_head *nh = opp_get_notifier(dev); 593 + 594 + if (IS_ERR(nh)) 595 + return PTR_ERR(nh); 596 + return srcu_notifier_chain_unregister(nh, &devfreq->nb); 597 + } 598 + 599 + MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); 600 + MODULE_DESCRIPTION("devfreq class support"); 601 + MODULE_LICENSE("GPL");
+24
drivers/devfreq/governor.h
··· 1 + /* 2 + * governor.h - internal header for devfreq governors. 3 + * 4 + * Copyright (C) 2011 Samsung Electronics 5 + * MyungJoo Ham <myungjoo.ham@samsung.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + * 11 + * This header is for devfreq governors in drivers/devfreq/ 12 + */ 13 + 14 + #ifndef _GOVERNOR_H 15 + #define _GOVERNOR_H 16 + 17 + #include <linux/devfreq.h> 18 + 19 + #define to_devfreq(DEV) container_of((DEV), struct devfreq, dev) 20 + 21 + /* Caution: devfreq->lock must be locked before calling update_devfreq */ 22 + extern int update_devfreq(struct devfreq *devfreq); 23 + 24 + #endif /* _GOVERNOR_H */
+29
drivers/devfreq/governor_performance.c
··· 1 + /* 2 + * linux/drivers/devfreq/governor_performance.c 3 + * 4 + * Copyright (C) 2011 Samsung Electronics 5 + * MyungJoo Ham <myungjoo.ham@samsung.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/devfreq.h> 13 + 14 + static int devfreq_performance_func(struct devfreq *df, 15 + unsigned long *freq) 16 + { 17 + /* 18 + * target callback should be able to get floor value as 19 + * said in devfreq.h 20 + */ 21 + *freq = UINT_MAX; 22 + return 0; 23 + } 24 + 25 + const struct devfreq_governor devfreq_performance = { 26 + .name = "performance", 27 + .get_target_freq = devfreq_performance_func, 28 + .no_central_polling = true, 29 + };
+29
drivers/devfreq/governor_powersave.c
··· 1 + /* 2 + * linux/drivers/devfreq/governor_powersave.c 3 + * 4 + * Copyright (C) 2011 Samsung Electronics 5 + * MyungJoo Ham <myungjoo.ham@samsung.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/devfreq.h> 13 + 14 + static int devfreq_powersave_func(struct devfreq *df, 15 + unsigned long *freq) 16 + { 17 + /* 18 + * target callback should be able to get ceiling value as 19 + * said in devfreq.h 20 + */ 21 + *freq = 0; 22 + return 0; 23 + } 24 + 25 + const struct devfreq_governor devfreq_powersave = { 26 + .name = "powersave", 27 + .get_target_freq = devfreq_powersave_func, 28 + .no_central_polling = true, 29 + };
+88
drivers/devfreq/governor_simpleondemand.c
··· 1 + /* 2 + * linux/drivers/devfreq/governor_simpleondemand.c 3 + * 4 + * Copyright (C) 2011 Samsung Electronics 5 + * MyungJoo Ham <myungjoo.ham@samsung.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/errno.h> 13 + #include <linux/devfreq.h> 14 + #include <linux/math64.h> 15 + 16 + /* Default constants for DevFreq-Simple-Ondemand (DFSO) */ 17 + #define DFSO_UPTHRESHOLD (90) 18 + #define DFSO_DOWNDIFFERENCTIAL (5) 19 + static int devfreq_simple_ondemand_func(struct devfreq *df, 20 + unsigned long *freq) 21 + { 22 + struct devfreq_dev_status stat; 23 + int err = df->profile->get_dev_status(df->dev.parent, &stat); 24 + unsigned long long a, b; 25 + unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD; 26 + unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL; 27 + struct devfreq_simple_ondemand_data *data = df->data; 28 + 29 + if (err) 30 + return err; 31 + 32 + if (data) { 33 + if (data->upthreshold) 34 + dfso_upthreshold = data->upthreshold; 35 + if (data->downdifferential) 36 + dfso_downdifferential = data->downdifferential; 37 + } 38 + if (dfso_upthreshold > 100 || 39 + dfso_upthreshold < dfso_downdifferential) 40 + return -EINVAL; 41 + 42 + /* Assume MAX if it is going to be divided by zero */ 43 + if (stat.total_time == 0) { 44 + *freq = UINT_MAX; 45 + return 0; 46 + } 47 + 48 + /* Prevent overflow */ 49 + if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) { 50 + stat.busy_time >>= 7; 51 + stat.total_time >>= 7; 52 + } 53 + 54 + /* Set MAX if it's busy enough */ 55 + if (stat.busy_time * 100 > 56 + stat.total_time * dfso_upthreshold) { 57 + *freq = UINT_MAX; 58 + return 0; 59 + } 60 + 61 + /* Set MAX if we do not know the initial frequency */ 62 + if (stat.current_frequency == 0) { 63 + *freq = UINT_MAX; 64 + return 0; 65 + } 66 + 67 + /* Keep the current frequency */ 68 + if (stat.busy_time * 100 > 69 + stat.total_time * (dfso_upthreshold - dfso_downdifferential)) { 70 + *freq = stat.current_frequency; 71 + return 0; 72 + } 73 + 74 + /* Set the desired frequency based on the load */ 75 + a = stat.busy_time; 76 + a *= stat.current_frequency; 77 + b = div_u64(a, stat.total_time); 78 + b *= 100; 79 + b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2)); 80 + *freq = (unsigned long) b; 81 + 82 + return 0; 83 + } 84 + 85 + const struct devfreq_governor devfreq_simple_ondemand = { 86 + .name = "simple_ondemand", 87 + .get_target_freq = devfreq_simple_ondemand_func, 88 + };
+116
drivers/devfreq/governor_userspace.c
··· 1 + /* 2 + * linux/drivers/devfreq/governor_simpleondemand.c 3 + * 4 + * Copyright (C) 2011 Samsung Electronics 5 + * MyungJoo Ham <myungjoo.ham@samsung.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/slab.h> 13 + #include <linux/device.h> 14 + #include <linux/devfreq.h> 15 + #include <linux/pm.h> 16 + #include <linux/mutex.h> 17 + #include "governor.h" 18 + 19 + struct userspace_data { 20 + unsigned long user_frequency; 21 + bool valid; 22 + }; 23 + 24 + static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq) 25 + { 26 + struct userspace_data *data = df->data; 27 + 28 + if (!data->valid) 29 + *freq = df->previous_freq; /* No user freq specified yet */ 30 + else 31 + *freq = data->user_frequency; 32 + return 0; 33 + } 34 + 35 + static ssize_t store_freq(struct device *dev, struct device_attribute *attr, 36 + const char *buf, size_t count) 37 + { 38 + struct devfreq *devfreq = to_devfreq(dev); 39 + struct userspace_data *data; 40 + unsigned long wanted; 41 + int err = 0; 42 + 43 + 44 + mutex_lock(&devfreq->lock); 45 + data = devfreq->data; 46 + 47 + sscanf(buf, "%lu", &wanted); 48 + data->user_frequency = wanted; 49 + data->valid = true; 50 + err = update_devfreq(devfreq); 51 + if (err == 0) 52 + err = count; 53 + mutex_unlock(&devfreq->lock); 54 + return err; 55 + } 56 + 57 + static ssize_t show_freq(struct device *dev, struct device_attribute *attr, 58 + char *buf) 59 + { 60 + struct devfreq *devfreq = to_devfreq(dev); 61 + struct userspace_data *data; 62 + int err = 0; 63 + 64 + mutex_lock(&devfreq->lock); 65 + data = devfreq->data; 66 + 67 + if (data->valid) 68 + err = sprintf(buf, "%lu\n", data->user_frequency); 69 + else 70 + err = sprintf(buf, "undefined\n"); 71 + mutex_unlock(&devfreq->lock); 72 + return err; 73 + } 74 + 75 + static DEVICE_ATTR(set_freq, 0644, show_freq, store_freq); 76 + static struct attribute *dev_entries[] = { 77 + &dev_attr_set_freq.attr, 78 + NULL, 79 + }; 80 + static struct attribute_group dev_attr_group = { 81 + .name = "userspace", 82 + .attrs = dev_entries, 83 + }; 84 + 85 + static int userspace_init(struct devfreq *devfreq) 86 + { 87 + int err = 0; 88 + struct userspace_data *data = kzalloc(sizeof(struct userspace_data), 89 + GFP_KERNEL); 90 + 91 + if (!data) { 92 + err = -ENOMEM; 93 + goto out; 94 + } 95 + data->valid = false; 96 + devfreq->data = data; 97 + 98 + err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group); 99 + out: 100 + return err; 101 + } 102 + 103 + static void userspace_exit(struct devfreq *devfreq) 104 + { 105 + sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group); 106 + kfree(devfreq->data); 107 + devfreq->data = NULL; 108 + } 109 + 110 + const struct devfreq_governor devfreq_userspace = { 111 + .name = "userspace", 112 + .get_target_freq = devfreq_userspace_func, 113 + .init = userspace_init, 114 + .exit = userspace_exit, 115 + .no_central_polling = true, 116 + };
+238
include/linux/devfreq.h
··· 1 + /* 2 + * devfreq: Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework 3 + * for Non-CPU Devices. 4 + * 5 + * Copyright (C) 2011 Samsung Electronics 6 + * MyungJoo Ham <myungjoo.ham@samsung.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License version 2 as 10 + * published by the Free Software Foundation. 11 + */ 12 + 13 + #ifndef __LINUX_DEVFREQ_H__ 14 + #define __LINUX_DEVFREQ_H__ 15 + 16 + #include <linux/device.h> 17 + #include <linux/notifier.h> 18 + #include <linux/opp.h> 19 + 20 + #define DEVFREQ_NAME_LEN 16 21 + 22 + struct devfreq; 23 + 24 + /** 25 + * struct devfreq_dev_status - Data given from devfreq user device to 26 + * governors. Represents the performance 27 + * statistics. 28 + * @total_time The total time represented by this instance of 29 + * devfreq_dev_status 30 + * @busy_time The time that the device was working among the 31 + * total_time. 32 + * @current_frequency The operating frequency. 33 + * @private_data An entry not specified by the devfreq framework. 34 + * A device and a specific governor may have their 35 + * own protocol with private_data. However, because 36 + * this is governor-specific, a governor using this 37 + * will be only compatible with devices aware of it. 38 + */ 39 + struct devfreq_dev_status { 40 + /* both since the last measure */ 41 + unsigned long total_time; 42 + unsigned long busy_time; 43 + unsigned long current_frequency; 44 + void *private_date; 45 + }; 46 + 47 + /** 48 + * struct devfreq_dev_profile - Devfreq's user device profile 49 + * @initial_freq The operating frequency when devfreq_add_device() is 50 + * called. 51 + * @polling_ms The polling interval in ms. 0 disables polling. 52 + * @target The device should set its operating frequency at 53 + * freq or lowest-upper-than-freq value. If freq is 54 + * higher than any operable frequency, set maximum. 55 + * Before returning, target function should set 56 + * freq at the current frequency. 57 + * @get_dev_status The device should provide the current performance 58 + * status to devfreq, which is used by governors. 59 + * @exit An optional callback that is called when devfreq 60 + * is removing the devfreq object due to error or 61 + * from devfreq_remove_device() call. If the user 62 + * has registered devfreq->nb at a notifier-head, 63 + * this is the time to unregister it. 64 + */ 65 + struct devfreq_dev_profile { 66 + unsigned long initial_freq; 67 + unsigned int polling_ms; 68 + 69 + int (*target)(struct device *dev, unsigned long *freq); 70 + int (*get_dev_status)(struct device *dev, 71 + struct devfreq_dev_status *stat); 72 + void (*exit)(struct device *dev); 73 + }; 74 + 75 + /** 76 + * struct devfreq_governor - Devfreq policy governor 77 + * @name Governor's name 78 + * @get_target_freq Returns desired operating frequency for the device. 79 + * Basically, get_target_freq will run 80 + * devfreq_dev_profile.get_dev_status() to get the 81 + * status of the device (load = busy_time / total_time). 82 + * If no_central_polling is set, this callback is called 83 + * only with update_devfreq() notified by OPP. 84 + * @init Called when the devfreq is being attached to a device 85 + * @exit Called when the devfreq is being removed from a 86 + * device. Governor should stop any internal routines 87 + * before return because related data may be 88 + * freed after exit(). 89 + * @no_central_polling Do not use devfreq's central polling mechanism. 90 + * When this is set, devfreq will not call 91 + * get_target_freq with devfreq_monitor(). However, 92 + * devfreq will call get_target_freq with 93 + * devfreq_update() notified by OPP framework. 94 + * 95 + * Note that the callbacks are called with devfreq->lock locked by devfreq. 96 + */ 97 + struct devfreq_governor { 98 + const char name[DEVFREQ_NAME_LEN]; 99 + int (*get_target_freq)(struct devfreq *this, unsigned long *freq); 100 + int (*init)(struct devfreq *this); 101 + void (*exit)(struct devfreq *this); 102 + const bool no_central_polling; 103 + }; 104 + 105 + /** 106 + * struct devfreq - Device devfreq structure 107 + * @node list node - contains the devices with devfreq that have been 108 + * registered. 109 + * @lock a mutex to protect accessing devfreq. 110 + * @dev device registered by devfreq class. dev.parent is the device 111 + * using devfreq. 112 + * @profile device-specific devfreq profile 113 + * @governor method how to choose frequency based on the usage. 114 + * @nb notifier block used to notify devfreq object that it should 115 + * reevaluate operable frequencies. Devfreq users may use 116 + * devfreq.nb to the corresponding register notifier call chain. 117 + * @polling_jiffies interval in jiffies. 118 + * @previous_freq previously configured frequency value. 119 + * @next_polling the number of remaining jiffies to poll with 120 + * "devfreq_monitor" executions to reevaluate 121 + * frequency/voltage of the device. Set by 122 + * profile's polling_ms interval. 123 + * @data Private data of the governor. The devfreq framework does not 124 + * touch this. 125 + * @being_removed a flag to mark that this object is being removed in 126 + * order to prevent trying to remove the object multiple times. 127 + * 128 + * This structure stores the devfreq information for a give device. 129 + * 130 + * Note that when a governor accesses entries in struct devfreq in its 131 + * functions except for the context of callbacks defined in struct 132 + * devfreq_governor, the governor should protect its access with the 133 + * struct mutex lock in struct devfreq. A governor may use this mutex 134 + * to protect its own private data in void *data as well. 135 + */ 136 + struct devfreq { 137 + struct list_head node; 138 + 139 + struct mutex lock; 140 + struct device dev; 141 + struct devfreq_dev_profile *profile; 142 + const struct devfreq_governor *governor; 143 + struct notifier_block nb; 144 + 145 + unsigned long polling_jiffies; 146 + unsigned long previous_freq; 147 + unsigned int next_polling; 148 + 149 + void *data; /* private data for governors */ 150 + 151 + bool being_removed; 152 + }; 153 + 154 + #if defined(CONFIG_PM_DEVFREQ) 155 + extern struct devfreq *devfreq_add_device(struct device *dev, 156 + struct devfreq_dev_profile *profile, 157 + const struct devfreq_governor *governor, 158 + void *data); 159 + extern int devfreq_remove_device(struct devfreq *devfreq); 160 + 161 + /* Helper functions for devfreq user device driver with OPP. */ 162 + extern struct opp *devfreq_recommended_opp(struct device *dev, 163 + unsigned long *freq); 164 + extern int devfreq_register_opp_notifier(struct device *dev, 165 + struct devfreq *devfreq); 166 + extern int devfreq_unregister_opp_notifier(struct device *dev, 167 + struct devfreq *devfreq); 168 + 169 + #ifdef CONFIG_DEVFREQ_GOV_POWERSAVE 170 + extern const struct devfreq_governor devfreq_powersave; 171 + #endif 172 + #ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE 173 + extern const struct devfreq_governor devfreq_performance; 174 + #endif 175 + #ifdef CONFIG_DEVFREQ_GOV_USERSPACE 176 + extern const struct devfreq_governor devfreq_userspace; 177 + #endif 178 + #ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND 179 + extern const struct devfreq_governor devfreq_simple_ondemand; 180 + /** 181 + * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq 182 + * and devfreq_add_device 183 + * @ upthreshold If the load is over this value, the frequency jumps. 184 + * Specify 0 to use the default. Valid value = 0 to 100. 185 + * @ downdifferential If the load is under upthreshold - downdifferential, 186 + * the governor may consider slowing the frequency down. 187 + * Specify 0 to use the default. Valid value = 0 to 100. 188 + * downdifferential < upthreshold must hold. 189 + * 190 + * If the fed devfreq_simple_ondemand_data pointer is NULL to the governor, 191 + * the governor uses the default values. 192 + */ 193 + struct devfreq_simple_ondemand_data { 194 + unsigned int upthreshold; 195 + unsigned int downdifferential; 196 + }; 197 + #endif 198 + 199 + #else /* !CONFIG_PM_DEVFREQ */ 200 + static struct devfreq *devfreq_add_device(struct device *dev, 201 + struct devfreq_dev_profile *profile, 202 + struct devfreq_governor *governor, 203 + void *data); 204 + { 205 + return NULL; 206 + } 207 + 208 + static int devfreq_remove_device(struct devfreq *devfreq); 209 + { 210 + return 0; 211 + } 212 + 213 + static struct opp *devfreq_recommended_opp(struct device *dev, 214 + unsigned long *freq) 215 + { 216 + return -EINVAL; 217 + } 218 + 219 + static int devfreq_register_opp_notifier(struct device *dev, 220 + struct devfreq *devfreq) 221 + { 222 + return -EINVAL; 223 + } 224 + 225 + static int devfreq_unregister_opp_notifier(struct device *dev, 226 + struct devfreq *devfreq) 227 + { 228 + return -EINVAL; 229 + } 230 + 231 + #define devfreq_powersave NULL 232 + #define devfreq_performance NULL 233 + #define devfreq_userspace NULL 234 + #define devfreq_simple_ondemand NULL 235 + 236 + #endif /* CONFIG_PM_DEVFREQ */ 237 + 238 + #endif /* __LINUX_DEVFREQ_H__ */
+12
include/linux/opp.h
··· 16 16 17 17 #include <linux/err.h> 18 18 #include <linux/cpufreq.h> 19 + #include <linux/notifier.h> 19 20 20 21 struct opp; 22 + 23 + enum opp_event { 24 + OPP_EVENT_ADD, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE, 25 + }; 21 26 22 27 #if defined(CONFIG_PM_OPP) 23 28 ··· 44 39 int opp_enable(struct device *dev, unsigned long freq); 45 40 46 41 int opp_disable(struct device *dev, unsigned long freq); 42 + 43 + struct srcu_notifier_head *opp_get_notifier(struct device *dev); 47 44 48 45 #else 49 46 static inline unsigned long opp_get_voltage(struct opp *opp) ··· 95 88 static inline int opp_disable(struct device *dev, unsigned long freq) 96 89 { 97 90 return 0; 91 + } 92 + 93 + struct srcu_notifier_head *opp_get_notifier(struct device *dev) 94 + { 95 + return ERR_PTR(-EINVAL); 98 96 } 99 97 #endif /* CONFIG_PM */ 100 98