Skip to content

Commit 96ccd5a

Browse files
osctobegregkh
authored andcommitted
regulator: push allocation in regulator_init_coupling() outside of lock
commit 73a3212 upstream. Allocating memory with regulator_list_mutex held makes lockdep unhappy when memory pressure makes the system do fs_reclaim on eg. eMMC using a regulator. Push the lock inside regulator_init_coupling() after the allocation. ====================================================== WARNING: possible circular locking dependency detected 5.7.13+ torvalds#533 Not tainted ------------------------------------------------------ kswapd0/383 is trying to acquire lock: cca78ca4 (&sbi->write_io[i][j].io_rwsem){++++}-{3:3}, at: __submit_merged_write_cond+0x104/0x154 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: -> #2 (fs_reclaim){+.+.}-{0:0}: fs_reclaim_acquire.part.11+0x40/0x50 fs_reclaim_acquire+0x24/0x28 __kmalloc+0x54/0x218 regulator_register+0x860/0x1584 dummy_regulator_probe+0x60/0xa8 [...] other info that might help us debug this: Chain exists of: &sbi->write_io[i][j].io_rwsem --> regulator_list_mutex --> fs_reclaim Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(fs_reclaim); lock(regulator_list_mutex); lock(fs_reclaim); lock(&sbi->write_io[i][j].io_rwsem); *** DEADLOCK *** 1 lock held by kswapd0/383: #0: c0e38518 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x0/0x50 [...] Fixes: d8ca7d1 ("regulator: core: Introduce API for regulators coupling customization") Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> Reviewed-by: Dmitry Osipenko <digetx@gmail.com> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/1a889cf7f61c6429c9e6b34ddcdde99be77a26b6.1597195321.git.mirq-linux@rere.qmqm.pl Signed-off-by: Mark Brown <broonie@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 4705250 commit 96ccd5a

File tree

1 file changed

+3
-2
lines changed

1 file changed

+3
-2
lines changed

drivers/regulator/core.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -4978,7 +4978,10 @@ static int regulator_init_coupling(struct regulator_dev *rdev)
49784978
if (!of_check_coupling_data(rdev))
49794979
return -EPERM;
49804980

4981+
mutex_lock(&regulator_list_mutex);
49814982
rdev->coupling_desc.coupler = regulator_find_coupler(rdev);
4983+
mutex_unlock(&regulator_list_mutex);
4984+
49824985
if (IS_ERR(rdev->coupling_desc.coupler)) {
49834986
err = PTR_ERR(rdev->coupling_desc.coupler);
49844987
rdev_err(rdev, "failed to get coupler: %d\n", err);
@@ -5184,9 +5187,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
51845187
if (ret < 0)
51855188
goto wash;
51865189

5187-
mutex_lock(&regulator_list_mutex);
51885190
ret = regulator_init_coupling(rdev);
5189-
mutex_unlock(&regulator_list_mutex);
51905191
if (ret < 0)
51915192
goto wash;
51925193

0 commit comments

Comments
 (0)