regulator: Fix recursive mutex lockdep warning
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/0x224stack 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
@@ -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.
Mark Brown
AppliedQuoted 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 therdev->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...
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 therdev->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.
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()?
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.
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.