LOCAL / PM / devfreq: rollback mutex locking for update_devfreq()
authorJoonyoung Shim <jy0922.shim@samsung.com>
Mon, 7 Sep 2015 07:42:31 +0000 (16:42 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Wed, 14 Dec 2016 04:48:19 +0000 (13:48 +0900)
Userspace, performance and powersave governers call update_devfreq()
with mutex locking. It causes nested mutex locking error.

I'm not sure that i should make a choice which reverting change that
includes mutex locking in update_devfreq() or removing mutex locking
before update_devfreq() is called on each governers.

IMHO, the upstream codes don't include mutex locking in update_devfreq()
so first option is better.

Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
drivers/devfreq/devfreq.c
drivers/thermal/devfreq_cooling.c

index 2aa5e4e..ca1b362 100644 (file)
@@ -163,17 +163,18 @@ int update_devfreq(struct devfreq *devfreq)
        int err = 0;
        u32 flags = 0;
 
-       if (!devfreq->governor)
+       if (!mutex_is_locked(&devfreq->lock)) {
+               WARN(true, "devfreq->lock must be locked by the caller.\n");
                return -EINVAL;
+       }
 
-       mutex_lock(&devfreq->lock);
+       if (!devfreq->governor)
+               return -EINVAL;
 
        /* Reevaluate the proper frequency */
        err = devfreq->governor->get_target_freq(devfreq, &freq);
-       if (err) {
-               mutex_unlock(&devfreq->lock);
+       if (err)
                return err;
-       }
 
        /*
         * Adjust the freuqency with user freq and QoS.
@@ -193,10 +194,8 @@ int update_devfreq(struct devfreq *devfreq)
        }
 
        err = devfreq->profile->target(devfreq->dev.parent, &freq, flags);
-       if (err) {
-               mutex_unlock(&devfreq->lock);
+       if (err)
                return err;
-       }
 
        if (devfreq->profile->freq_table)
                if (devfreq_update_status(devfreq, freq))
@@ -204,9 +203,6 @@ int update_devfreq(struct devfreq *devfreq)
                                "Couldn't update frequency transition information.\n");
 
        devfreq->previous_freq = freq;
-
-       mutex_unlock(&devfreq->lock);
-
        return err;
 }
 EXPORT_SYMBOL(update_devfreq);
@@ -222,12 +218,14 @@ static void devfreq_monitor(struct work_struct *work)
        struct devfreq *devfreq = container_of(work,
                                        struct devfreq, work.work);
 
+       mutex_lock(&devfreq->lock);
        err = update_devfreq(devfreq);
        if (err)
                dev_err(&devfreq->dev, "dvfs failed with (%d) error\n", err);
 
        queue_delayed_work(devfreq_wq, &devfreq->work,
                                msecs_to_jiffies(devfreq->profile->polling_ms));
+       mutex_unlock(&devfreq->lock);
 }
 
 /**
@@ -384,7 +382,9 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
        struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
        int ret;
 
+       mutex_lock(&devfreq->lock);
        ret = update_devfreq(devfreq);
+       mutex_unlock(&devfreq->lock);
 
        return ret;
 }
index fb2c065..abbbcad 100644 (file)
@@ -123,6 +123,7 @@ static int devfreq_set_cur_state(struct thermal_cooling_device *cdev,
 {
        struct devfreq_cooling_device *devfreq_dev = cdev->devdata;
        unsigned int limited_freq;
+       int ret;
 
        /* Request state should be less than max_level */
        if (WARN_ON(state > devfreq_dev->max_state))
@@ -138,9 +139,11 @@ static int devfreq_set_cur_state(struct thermal_cooling_device *cdev,
 
        /* Set the limited frequency to maximum frequency of devfreq */
        devfreq_dev->devfreq->max_freq = limited_freq;
-       update_devfreq(devfreq_dev->devfreq);
+       mutex_lock(&devfreq_dev->devfreq->lock);
+       ret = update_devfreq(devfreq_dev->devfreq);
+       mutex_unlock(&devfreq_dev->devfreq->lock);
 
-       return 0;
+       return ret;
 }
 
 /* Bind devfreq callbacks to thermal cooling device ops */