aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/devfreq
diff options
context:
space:
mode:
authorChanwoo Choi <cw00.choi@samsung.com>2014-05-09 03:43:07 -0400
committerMyungJoo Ham <myungjoo.ham@samsung.com>2014-05-24 09:33:34 -0400
commit585fc83ece43be63d5775e536f855db33dd752cf (patch)
tree0bea4c3fe8e818f8d2e455d48265709c6e429c9e /drivers/devfreq
parent26d518530b19c62dd8165165958d7429db4cd1fe (diff)
PM / devfreq: Fix devfreq_remove_device() to improve the sequence of resource free
This patch modify devfreq_remove_device() to improve the sequence of resource free. If executing existing devfreq_remove_device(), this function always executes _remove_devfreq() twice. In result, second _remove_devfreq() always return error value. So, This patch resolves complicated function sequence as following: [Flow sequence before modification] devfreq_remove_device() _remove_devfreq(devfreq, false) kfree(devfreq); /* Free devfreq */ if (!skip ...) { /* skip is false */ device_unregister(&devfreq->dev) put_device(&devfreq->dev); ... dev->release() devfreq_dev_release() _remove_devfreq(devfreq, true) <- Recall to free devfreq /* * Always return error without freeing resource because * already _remove_devfreq() frees the memory of devfreq. */ } [Flow sequence after modification] devfreq_remove_device device_unregister(&devfreq->dev) put_device(&devfreq->dev); .. dev->release() devfreq_dev_release() _remove_devfreq() kfree(devfreq); /* Free devfreq */ Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> [Merge conflict resolved by MyungJoo] Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Diffstat (limited to 'drivers/devfreq')
-rw-r--r--drivers/devfreq/devfreq.c14
1 files changed, 4 insertions, 10 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 2042ec3656ba..af4af7708574 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -394,7 +394,7 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
394 * @devfreq: the devfreq struct 394 * @devfreq: the devfreq struct
395 * @skip: skip calling device_unregister(). 395 * @skip: skip calling device_unregister().
396 */ 396 */
397static void _remove_devfreq(struct devfreq *devfreq, bool skip) 397static void _remove_devfreq(struct devfreq *devfreq)
398{ 398{
399 mutex_lock(&devfreq_list_lock); 399 mutex_lock(&devfreq_list_lock);
400 if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) { 400 if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
@@ -412,11 +412,6 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
412 if (devfreq->profile->exit) 412 if (devfreq->profile->exit)
413 devfreq->profile->exit(devfreq->dev.parent); 413 devfreq->profile->exit(devfreq->dev.parent);
414 414
415 if (!skip && get_device(&devfreq->dev)) {
416 device_unregister(&devfreq->dev);
417 put_device(&devfreq->dev);
418 }
419
420 mutex_destroy(&devfreq->lock); 415 mutex_destroy(&devfreq->lock);
421 kfree(devfreq); 416 kfree(devfreq);
422} 417}
@@ -426,14 +421,12 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
426 * @dev: the devfreq device 421 * @dev: the devfreq device
427 * 422 *
428 * This calls _remove_devfreq() if _remove_devfreq() is not called. 423 * This calls _remove_devfreq() if _remove_devfreq() is not called.
429 * Note that devfreq_dev_release() could be called by _remove_devfreq() as
430 * well as by others unregistering the device.
431 */ 424 */
432static void devfreq_dev_release(struct device *dev) 425static void devfreq_dev_release(struct device *dev)
433{ 426{
434 struct devfreq *devfreq = to_devfreq(dev); 427 struct devfreq *devfreq = to_devfreq(dev);
435 428
436 _remove_devfreq(devfreq, true); 429 _remove_devfreq(devfreq);
437} 430}
438 431
439/** 432/**
@@ -544,7 +537,8 @@ int devfreq_remove_device(struct devfreq *devfreq)
544 if (!devfreq) 537 if (!devfreq)
545 return -EINVAL; 538 return -EINVAL;
546 539
547 _remove_devfreq(devfreq, false); 540 device_unregister(&devfreq->dev);
541 put_device(&devfreq->dev);
548 542
549 return 0; 543 return 0;
550} 544}