regulator: push allocation in regulator_init_coupling() outside of lock
commit73a32129f8
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+ #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:d8ca7d184b
("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>
This commit is contained in:
parent
b9fb631f6b
commit
e7249ceb7f
|
@ -4955,7 +4955,10 @@ static int regulator_init_coupling(struct regulator_dev *rdev)
|
|||
if (!of_check_coupling_data(rdev))
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
rdev->coupling_desc.coupler = regulator_find_coupler(rdev);
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
|
||||
if (IS_ERR(rdev->coupling_desc.coupler)) {
|
||||
err = PTR_ERR(rdev->coupling_desc.coupler);
|
||||
rdev_err(rdev, "failed to get coupler: %d\n", err);
|
||||
|
@ -5155,9 +5158,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
|
|||
if (ret < 0)
|
||||
goto wash;
|
||||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
ret = regulator_init_coupling(rdev);
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
if (ret < 0)
|
||||
goto wash;
|
||||
|
||||
|
|
Loading…
Reference in New Issue