Patch "regulator: push allocation in regulator_ena_gpio_request() out of lock" has been added to the 5.8-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    regulator: push allocation in regulator_ena_gpio_request() out of lock

to the 5.8-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     regulator-push-allocation-in-regulator_ena_gpio_requ.patch
and it can be found in the queue-5.8 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit cdac60b705832a69aa0c84966b1e6f69e4f397da
Author: MichaÅ? MirosÅ?aw <mirq-linux@xxxxxxxxxxxx>
Date:   Wed Aug 12 03:31:34 2020 +0200

    regulator: push allocation in regulator_ena_gpio_request() out of lock
    
    [ Upstream commit 467bf30142c64f2eb64e2ac67fa4595126230efd ]
    
    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@xxxxxxxxxxxx>
    Link: https://lore.kernel.org/r/41fe6a9670335721b48e8f5195038c3d67a3bf92.1597195321.git.mirq-linux@xxxxxxxxxxxx
    Signed-off-by: Mark Brown <broonie@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 720f28844795b..86107d2e1733e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2222,10 +2222,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) {
@@ -2234,9 +2237,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);
@@ -2244,6 +2251,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;
 }
 
@@ -5137,9 +5148,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);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux