PM / devfreq: Fix devfreq_remove_device() to improve the sequence of resource free
authorChanwoo Choi <cw00.choi@samsung.com>
Fri, 9 May 2014 07:43:07 +0000 (16:43 +0900)
committerMyungJoo Ham <myungjoo.ham@samsung.com>
Sat, 24 May 2014 13:33:34 +0000 (22:33 +0900)
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>
drivers/devfreq/devfreq.c

index 2042ec3..af4af77 100644 (file)
@@ -394,7 +394,7 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
  * @devfreq:   the devfreq struct
  * @skip:      skip calling device_unregister().
  */
-static void _remove_devfreq(struct devfreq *devfreq, bool skip)
+static void _remove_devfreq(struct devfreq *devfreq)
 {
        mutex_lock(&devfreq_list_lock);
        if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
@@ -412,11 +412,6 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
        if (devfreq->profile->exit)
                devfreq->profile->exit(devfreq->dev.parent);
 
-       if (!skip && get_device(&devfreq->dev)) {
-               device_unregister(&devfreq->dev);
-               put_device(&devfreq->dev);
-       }
-
        mutex_destroy(&devfreq->lock);
        kfree(devfreq);
 }
@@ -426,14 +421,12 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
  * @dev:       the devfreq device
  *
  * This calls _remove_devfreq() if _remove_devfreq() is not called.
- * Note that devfreq_dev_release() could be called by _remove_devfreq() as
- * well as by others unregistering the device.
  */
 static void devfreq_dev_release(struct device *dev)
 {
        struct devfreq *devfreq = to_devfreq(dev);
 
-       _remove_devfreq(devfreq, true);
+       _remove_devfreq(devfreq);
 }
 
 /**
@@ -544,7 +537,8 @@ int devfreq_remove_device(struct devfreq *devfreq)
        if (!devfreq)
                return -EINVAL;
 
-       _remove_devfreq(devfreq, false);
+       device_unregister(&devfreq->dev);
+       put_device(&devfreq->dev);
 
        return 0;
 }