lkml.org 
[lkml]   [2020]   [Aug]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 2/7] regulator: push allocation in regulator_ena_gpio_request() out of lock
    Move another allocation out of regulator_list_mutex-protected region, as
    reclaim might want to take the same lock.

    WARNING: possible circular locking dependency detected
    5.7.13+ #534 Not tainted
    ------------------------------------------------------
    kswapd0/383 is trying to acquire lock:
    c0e5d920 (regulator_list_mutex){+.+.}-{3:3}, at: regulator_lock_dependent+0x54/0x2c0

    but task is already holding lock:
    c0e38518 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x0/0x50

    which lock already depends on the new lock.

    the existing dependency chain (in reverse order) is:

    -> #1 (fs_reclaim){+.+.}-{0:0}:
    fs_reclaim_acquire.part.11+0x40/0x50
    fs_reclaim_acquire+0x24/0x28
    kmem_cache_alloc_trace+0x40/0x1e8
    regulator_register+0x384/0x1630
    devm_regulator_register+0x50/0x84
    reg_fixed_voltage_probe+0x248/0x35c
    [...]
    other info that might help us debug this:

    Possible unsafe locking scenario:

    CPU0 CPU1
    ---- ----
    lock(fs_reclaim);
    lock(regulator_list_mutex);
    lock(fs_reclaim);
    lock(regulator_list_mutex);

    *** DEADLOCK ***
    [...]
    2 locks held by kswapd0/383:
    #0: c0e38518 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x0/0x50
    #1: cb70e5e0 (hctx->srcu){....}-{0:0}, at: hctx_lock+0x60/0xb8
    [...]

    Fixes: 541d052d7215 ("regulator: core: Only support passing enable GPIO descriptors")
    [this commit only changes context]
    Fixes: f8702f9e4aa7 ("regulator: core: Use ww_mutex for regulators locking")
    [this is when the regulator_list_mutex was introduced in reclaim locking path]

    Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
    ---
    drivers/regulator/core.c | 19 ++++++++++++++-----
    1 file changed, 14 insertions(+), 5 deletions(-)

    diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
    index 510d234f6c46..3dd4d4914075 100644
    --- a/drivers/regulator/core.c
    +++ b/drivers/regulator/core.c
    @@ -2203,10 +2203,13 @@ EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
    static int regulator_ena_gpio_request(struct regulator_dev *rdev,
    const struct regulator_config *config)
    {
    - struct regulator_enable_gpio *pin;
    + struct regulator_enable_gpio *pin, *new_pin;
    struct gpio_desc *gpiod;

    gpiod = config->ena_gpiod;
    + new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL);
    +
    + mutex_lock(&regulator_list_mutex);

    list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
    if (pin->gpiod == gpiod) {
    @@ -2215,9 +2218,13 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
    }
    }

    - pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
    - if (pin == NULL)
    + if (new_pin == NULL) {
    + mutex_unlock(&regulator_list_mutex);
    return -ENOMEM;
    + }
    +
    + pin = new_pin;
    + new_pin = NULL;

    pin->gpiod = gpiod;
    list_add(&pin->list, &regulator_ena_gpio_list);
    @@ -2225,6 +2232,10 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
    update_ena_gpio_to_rdev:
    pin->request_count++;
    rdev->ena_pin = pin;
    +
    + mutex_unlock(&regulator_list_mutex);
    + kfree(new_pin);
    +
    return 0;
    }

    @@ -5179,9 +5190,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
    }

    if (config->ena_gpiod) {
    - mutex_lock(&regulator_list_mutex);
    ret = regulator_ena_gpio_request(rdev, config);
    - mutex_unlock(&regulator_list_mutex);
    if (ret != 0) {
    rdev_err(rdev, "Failed to request enable GPIO: %d\n",
    ret);
    --
    2.20.1
    \
     
     \ /
      Last update: 2020-08-11 03:08    [W:3.174 / U:0.060 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site