Commit | Line | Data |
---|---|---|
a3c98b8b MH |
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 | /** | |
441 | * devfreq_start_polling() - Initialize data structure for devfreq framework and | |
442 | * start polling registered devfreq devices. | |
443 | */ | |
444 | static int __init devfreq_start_polling(void) | |
445 | { | |
446 | mutex_lock(&devfreq_list_lock); | |
447 | polling = false; | |
448 | devfreq_wq = create_freezable_workqueue("devfreq_wq"); | |
449 | INIT_DELAYED_WORK_DEFERRABLE(&devfreq_work, devfreq_monitor); | |
450 | mutex_unlock(&devfreq_list_lock); | |
451 | ||
452 | devfreq_monitor(&devfreq_work.work); | |
453 | return 0; | |
454 | } | |
455 | late_initcall(devfreq_start_polling); | |
456 | ||
457 | static int __init devfreq_init(void) | |
458 | { | |
459 | devfreq_class = class_create(THIS_MODULE, "devfreq"); | |
460 | if (IS_ERR(devfreq_class)) { | |
461 | pr_err("%s: couldn't create class\n", __FILE__); | |
462 | return PTR_ERR(devfreq_class); | |
463 | } | |
464 | return 0; | |
465 | } | |
466 | subsys_initcall(devfreq_init); | |
467 | ||
468 | static void __exit devfreq_exit(void) | |
469 | { | |
470 | class_destroy(devfreq_class); | |
471 | } | |
472 | module_exit(devfreq_exit); | |
473 | ||
474 | /* | |
475 | * The followings are helper functions for devfreq user device drivers with | |
476 | * OPP framework. | |
477 | */ | |
478 | ||
479 | /** | |
480 | * devfreq_recommended_opp() - Helper function to get proper OPP for the | |
481 | * freq value given to target callback. | |
482 | * @dev The devfreq user device. (parent of devfreq) | |
483 | * @freq The frequency given to target function | |
484 | * | |
485 | */ | |
486 | struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) | |
487 | { | |
488 | struct opp *opp = opp_find_freq_ceil(dev, freq); | |
489 | ||
490 | if (opp == ERR_PTR(-ENODEV)) | |
491 | opp = opp_find_freq_floor(dev, freq); | |
492 | return opp; | |
493 | } | |
494 | ||
495 | /** | |
496 | * devfreq_register_opp_notifier() - Helper function to get devfreq notified | |
497 | * for any changes in the OPP availability | |
498 | * changes | |
499 | * @dev The devfreq user device. (parent of devfreq) | |
500 | * @devfreq The devfreq object. | |
501 | */ | |
502 | int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq) | |
503 | { | |
504 | struct srcu_notifier_head *nh = opp_get_notifier(dev); | |
505 | ||
506 | if (IS_ERR(nh)) | |
507 | return PTR_ERR(nh); | |
508 | return srcu_notifier_chain_register(nh, &devfreq->nb); | |
509 | } | |
510 | ||
511 | /** | |
512 | * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq | |
513 | * notified for any changes in the OPP | |
514 | * availability changes anymore. | |
515 | * @dev The devfreq user device. (parent of devfreq) | |
516 | * @devfreq The devfreq object. | |
517 | * | |
518 | * At exit() callback of devfreq_dev_profile, this must be included if | |
519 | * devfreq_recommended_opp is used. | |
520 | */ | |
521 | int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq) | |
522 | { | |
523 | struct srcu_notifier_head *nh = opp_get_notifier(dev); | |
524 | ||
525 | if (IS_ERR(nh)) | |
526 | return PTR_ERR(nh); | |
527 | return srcu_notifier_chain_unregister(nh, &devfreq->nb); | |
528 | } | |
529 | ||
530 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | |
531 | MODULE_DESCRIPTION("devfreq class support"); | |
532 | MODULE_LICENSE("GPL"); |