lkml.org 
[lkml]   [2019]   [Feb]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 052/305] PM / devfreq: Fix devfreq_add_device() when drivers are built as modules.
    3.16.63-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Enric Balletbo i Serra <enric.balletbo@collabora.com>

    commit 23c7b54ca1cd1797ef39169ab85e6d46f1c2d061 upstream.

    When the devfreq driver and the governor driver are built as modules,
    the call to devfreq_add_device() or governor_store() fails because the
    governor driver is not loaded at the time the devfreq driver loads. The
    devfreq driver has a build dependency on the governor but also should
    have a runtime dependency. We need to make sure that the governor driver
    is loaded before the devfreq driver.

    This patch fixes this bug by adding a try_then_request_governor()
    function. First tries to find the governor, and then, if it is not found,
    it requests the module and tries again.

    Fixes: 1b5c1be2c88e (PM / devfreq: map devfreq drivers to governor using name)
    Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
    Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>
    Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
    [bwh: Backported to 3.16:
    - Use string literal instead of DEVFREQ_GOV_SIMPLE_ONDEMAND
    - Adjust context]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/devfreq/devfreq.c | 53 ++++++++++++++++++++++++++++++++++++---
    1 file changed, 49 insertions(+), 4 deletions(-)

    --- a/drivers/devfreq/devfreq.c
    +++ b/drivers/devfreq/devfreq.c
    @@ -11,6 +11,7 @@
    */

    #include <linux/kernel.h>
    +#include <linux/kmod.h>
    #include <linux/sched.h>
    #include <linux/errno.h>
    #include <linux/err.h>
    @@ -148,6 +149,49 @@ static struct devfreq_governor *find_dev
    return ERR_PTR(-ENODEV);
    }

    +/**
    + * try_then_request_governor() - Try to find the governor and request the
    + * module if is not found.
    + * @name: name of the governor
    + *
    + * Search the list of devfreq governors and request the module and try again
    + * if is not found. This can happen when both drivers (the governor driver
    + * and the driver that call devfreq_add_device) are built as modules.
    + * devfreq_list_lock should be held by the caller. Returns the matched
    + * governor's pointer.
    + */
    +static struct devfreq_governor *try_then_request_governor(const char *name)
    +{
    + struct devfreq_governor *governor;
    + int err = 0;
    +
    + if (IS_ERR_OR_NULL(name)) {
    + pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
    + return ERR_PTR(-EINVAL);
    + }
    + WARN(!mutex_is_locked(&devfreq_list_lock),
    + "devfreq_list_lock must be locked.");
    +
    + governor = find_devfreq_governor(name);
    + if (IS_ERR(governor)) {
    + mutex_unlock(&devfreq_list_lock);
    +
    + if (!strncmp(name, "simple_ondemand",
    + DEVFREQ_NAME_LEN))
    + err = request_module("governor_%s", "simpleondemand");
    + else
    + err = request_module("governor_%s", name);
    + /* Restore previous state before return */
    + mutex_lock(&devfreq_list_lock);
    + if (err)
    + return NULL;
    +
    + governor = find_devfreq_governor(name);
    + }
    +
    + return governor;
    +}
    +
    /* Load monitoring helper functions for governors use */

    /**
    @@ -499,9 +543,8 @@ struct devfreq *devfreq_add_device(struc
    mutex_unlock(&devfreq->lock);

    mutex_lock(&devfreq_list_lock);
    - list_add(&devfreq->node, &devfreq_list);

    - governor = find_devfreq_governor(devfreq->governor_name);
    + governor = try_then_request_governor(devfreq->governor_name);
    if (IS_ERR(governor)) {
    dev_err(dev, "%s: Unable to find governor for the device\n",
    __func__);
    @@ -517,12 +560,14 @@ struct devfreq *devfreq_add_device(struc
    __func__);
    goto err_init;
    }
    +
    + list_add(&devfreq->node, &devfreq_list);
    +
    mutex_unlock(&devfreq_list_lock);

    return devfreq;

    err_init:
    - list_del(&devfreq->node);
    mutex_unlock(&devfreq_list_lock);

    device_unregister(&devfreq->dev);
    @@ -798,7 +843,7 @@ static ssize_t governor_store(struct dev
    return -EINVAL;

    mutex_lock(&devfreq_list_lock);
    - governor = find_devfreq_governor(str_governor);
    + governor = try_then_request_governor(str_governor);
    if (IS_ERR(governor)) {
    ret = PTR_ERR(governor);
    goto out;
    \
     
     \ /
      Last update: 2022-09-17 16:05    [W:2.859 / U:0.124 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site