Skip to contentSkip to conversation

regulator: Fix recursive mutex lockdep warning

PATCH Applied Stephen Boyd 2 participants 6 messages Jul 3, 2012 Voltage and current regulator framework

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 regulator: Fix recursive mutex lockdep warning

A recursive lockdep warning occurs if you call regulator_set_optimum_mode() on a regulator with a supply because there is no nesting annotation for the rdev->mutex. To avoid this warning, get the supply's load before locking the regulator's mutex to avoid grabbing the same class of lock twice.

=============================================
[ INFO: possible recursive locking detected ]
3.4.0 #3257 Tainted: G W
---------------------------------------------
swapper/0/1 is trying to acquire lock:
(&rdev->mutex){+.+.+.}, at: [<c036e9e0>] regulator_get_voltage+0x18/0x38

but task is already holding lock:
(&rdev->mutex){+.+.+.}, at: [<c036ef38>] regulator_set_optimum_mode+0x24/0x224

other info that might help us debug this:

 Possible unsafe locking scenario:
       CPU0
       ----

lock(&rdev->mutex);
lock(&rdev->mutex);

*** DEADLOCK ***

May be due to missing lock nesting notation

3 locks held by swapper/0/1:

 #0:  (&__lockdep_no_validate__){......}, at: [<c03dbb48>] __driver_attach+0x40/0x8c
 #1:  (&__lockdep_no_validate__){......}, at: [<c03dbb58>] __driver_attach+0x50/0x8c
 #2:  (&rdev->mutex){+.+.+.}, at: [<c036ef38>] regulator_set_optimum_mode+0x24/0x224
stack backtrace:
[<c001521c>] (unwind_backtrace+0x0/0x12c) from [<c00cc4d4>] (validate_chain+0x760/0x1080)
[<c00cc4d4>] (validate_chain+0x760/0x1080) from [<c00cd744>] (__lock_acquire+0x950/0xa10)
[<c00cd744>] (__lock_acquire+0x950/0xa10) from [<c00cd990>] (lock_acquire+0x18c/0x1e8)
[<c00cd990>] (lock_acquire+0x18c/0x1e8) from [<c080c248>] (mutex_lock_nested+0x68/0x3c4)
[<c080c248>] (mutex_lock_nested+0x68/0x3c4) from [<c036e9e0>] (regulator_get_voltage+0x18/0x38)
[<c036e9e0>] (regulator_get_voltage+0x18/0x38) from [<c036efb8>] (regulator_set_optimum_mode+0xa4/0x224)

...

---

I'm not sure if this is the preferred solution. I also believe there is a similar warning in regulator_enable()/disable() when drms_uA_update() is called.

Is anything wrong with regulator_get_voltage() never taking the mutex? If we did that then this lockdep warning would go away in addition to the one in drms_uA_update().

 drivers/regulator/core.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/regulator/core.c +5 -5
index ef07b62..db119f3 100644
@@ -2544,9 +2544,12 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
 {
 	struct regulator_dev *rdev = regulator->rdev;
 	struct regulator *consumer;
-	int ret, output_uV, input_uV, total_uA_load = 0;
+	int ret, output_uV, input_uV = 0, total_uA_load = 0;
 	unsigned int mode;
 
+	if (rdev->supply)
+		input_uV = regulator_get_voltage(rdev->supply);
+
 	mutex_lock(&rdev->mutex);
 
 	/*
@@ -2579,10 +2582,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
 		goto out;
 	}
 
-	/* get input voltage */
-	input_uV = 0;
-	if (rdev->supply)
-		input_uV = regulator_get_voltage(rdev->supply);
+	/* No supply? Use constraint voltage */
 	if (input_uV <= 0)
 		input_uV = rdev->constraints->input_uV;
 	if (input_uV <= 0) {
Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Applied
#1 lore raw
Quoted 5 lines · Stephen Boyd

A recursive lockdep warning occurs if you call regulator_set_optimum_mode() on a regulator with a supply because there is no nesting annotation for the rdev->mutex. To avoid this warning, get the supply's load before locking the regulator's mutex to avoid grabbing the same class of lock twice.

Applied, thanks. Though we should probably just remove the optimal mode stuff on account of the total absence of any users...

#2 lore raw
Quoted 8 lines · Mark Brown
Quoted 5 lines · Stephen Boyd

A recursive lockdep warning occurs if you call regulator_set_optimum_mode() on a regulator with a supply because there is no nesting annotation for the rdev->mutex. To avoid this warning, get the supply's load before locking the regulator's mutex to avoid grabbing the same class of lock twice.

Applied, thanks. Though we should probably just remove the optimal mode stuff on account of the total absence of any users...

Please don't remove it. We use the optimal stuff fairly often internally, plus our usb driver is upstream and using the API.

What do you think about removing the locking in get_voltage? Is that better?

Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
#3 lore raw
Quoted 9 lines · Stephen Boyd
Quoted 2 lines · Mark Brown

Applied, thanks. Though we should probably just remove the optimal mode stuff on account of the total absence of any users...

Please don't remove it. We use the optimal stuff fairly often internally, plus our usb driver is upstream and using the API.

From what I remember there's a fair bit of non-upstream code you guys

have for regulators... your usage is certainly very unusual.

Quoted 1 line

What do you think about removing the locking in get_voltage? Is that better?

There's already an unlocked version of get_voltage()?

#4 lore raw
Quoted 3 lines · Mark Brown
Quoted 2 lines

What do you think about removing the locking in get_voltage? Is that better?

There's already an unlocked version of get_voltage()?

Yes, I'm suggesting we just use that unlocked version for all of the code that gets the input voltage.

index ef07b62..4c63336 100644

drivers/regulator/core.c +2 -2
@@ -628,7 +628,7 @@ static void drms_uA_update(struct regulator_dev *rdev)
        /* get input voltage */
        input_uV = 0;
        if (rdev->supply)
-               input_uV = regulator_get_voltage(rdev->supply);
+               input_uV = _regulator_get_voltage(rdev->supply->rdev);
        if (input_uV <= 0)
                input_uV = rdev->constraints->input_uV;
        if (input_uV <= 0)
@@ -2582,7 +2582,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
        /* get input voltage */
        input_uV = 0;
        if (rdev->supply)
-               input_uV = regulator_get_voltage(rdev->supply);
+               input_uV = _regulator_get_voltage(rdev->supply->rdev);
        if (input_uV <= 0)
                input_uV = rdev->constraints->input_uV;
        if (input_uV <= 0) {
Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
#5 lore raw
Quoted 7 lines · Stephen Boyd
Quoted 2 lines · Mark Brown
Quoted 1 line

What do you think about removing the locking in get_voltage? Is that better?

There's already an unlocked version of get_voltage()?

Yes, I'm suggesting we just use that unlocked version for all of the code that gets the input voltage.

Either way works.