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>
This commit is contained in:
parent
26d518530b
commit
585fc83ece
@ -394,7 +394,7 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
|
|||||||
* @devfreq: the devfreq struct
|
* @devfreq: the devfreq struct
|
||||||
* @skip: skip calling device_unregister().
|
* @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);
|
mutex_lock(&devfreq_list_lock);
|
||||||
if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
|
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)
|
if (devfreq->profile->exit)
|
||||||
devfreq->profile->exit(devfreq->dev.parent);
|
devfreq->profile->exit(devfreq->dev.parent);
|
||||||
|
|
||||||
if (!skip && get_device(&devfreq->dev)) {
|
|
||||||
device_unregister(&devfreq->dev);
|
|
||||||
put_device(&devfreq->dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_destroy(&devfreq->lock);
|
mutex_destroy(&devfreq->lock);
|
||||||
kfree(devfreq);
|
kfree(devfreq);
|
||||||
}
|
}
|
||||||
@ -426,14 +421,12 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
|
|||||||
* @dev: the devfreq device
|
* @dev: the devfreq device
|
||||||
*
|
*
|
||||||
* This calls _remove_devfreq() if _remove_devfreq() is not called.
|
* 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)
|
static void devfreq_dev_release(struct device *dev)
|
||||||
{
|
{
|
||||||
struct devfreq *devfreq = to_devfreq(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)
|
if (!devfreq)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
_remove_devfreq(devfreq, false);
|
device_unregister(&devfreq->dev);
|
||||||
|
put_device(&devfreq->dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user