Re: [PATCH v2 2/6] regmap: Use flexible sleep

From: Marek Szyprowski
Date: Wed Sep 02 2020 - 08:47:49 EST


Hi Dmitry,

On 30.08.2020 20:53, Dmitry Osipenko wrote:
> The multi-reg write function uses udelay(), which is a busy-loop based
> delaying function that is not suitable for a long delays. Hence let's
> replace the udelay() with fsleep(), which is flexible sleep function that
> selects best delay function based on the delay-time.
>
> Signed-off-by: Dmitry Osipenko <digetx@xxxxxxxxx>

This patch landed in today's linux-next (20200902) as commit
2b32d2f7ce0a. Sadly it breaks booting of ARM 64bit Amlogic S922X based
Odroid N2 board. Here is the log:

BUG: scheduling while atomic: kworker/4:1/46/0x00000003
5 locks held by kworker/4:1/46:
 #0: ffff0000dfc06738 ((wq_completion)events){+.+.}-{0:0}, at:
process_one_work+0x200/0x718
 #1: ffff80001320bdd0 (deferred_probe_work){+.+.}-{0:0}, at:
process_one_work+0x200/0x718
 #2: ffff0000df4b6188 (&dev->mutex){....}-{3:3}, at:
__device_attach+0x3c/0x150
 #3: ffff800012306e70 (enable_lock){+.+.}-{2:2}, at:
clk_enable_lock+0x48/0x128
 #4: ffff0000de01c418 (syscon:110:(&syscon_config)->lock){+.+.}-{2:2},
at: regmap_lock_spinlock+0x14/0x28
Modules linked in:
CPU: 4 PID: 46 Comm: kworker/4:1 Not tainted 5.9.0-rc2+ #1570
Hardware name: Hardkernel ODROID-N2 (DT)
Workqueue: events deferred_probe_work_func
Call trace:
 dump_backtrace+0x0/0x1d0
 show_stack+0x14/0x20
 dump_stack+0xec/0x16c
 __schedule_bug+0x64/0x98
 __schedule+0x7e0/0x8a0
 schedule+0x78/0x118
 schedule_hrtimeout_range_clock+0x84/0x108
 schedule_hrtimeout_range+0x10/0x18
 usleep_range+0x88/0xb8
 _regmap_multi_reg_write+0x188/0x4e0
 regmap_multi_reg_write+0x38/0x58
 meson_clk_pll_init+0x80/0xd8
 meson_clk_pcie_pll_enable+0x48/0xd8
 clk_core_enable+0xc8/0x2b0
 clk_core_enable+0xa8/0x2b0
 clk_core_enable+0xa8/0x2b0
 clk_core_enable+0xa8/0x2b0
 clk_core_enable_lock+0x20/0x40
 clk_enable+0x14/0x28
 phy_g12a_usb3_pcie_probe+0x130/0x210
 platform_drv_probe+0x50/0xa8
 really_probe+0x110/0x400
 driver_probe_device+0x54/0xb8
 __device_attach_driver+0x90/0xc0
 bus_for_each_drv+0x70/0xc8
 __device_attach+0xec/0x150
 device_initial_probe+0x10/0x18
 bus_probe_device+0x94/0xa0
 deferred_probe_work_func+0x70/0xa8
 process_one_work+0x2a8/0x718
 worker_thread+0x48/0x460
 kthread+0x134/0x160
 ret_from_fork+0x10/0x1c
BUG: sleeping function called from invalid context at mm/slab.h:498
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 46, name: kworker/4:1
3 locks held by kworker/4:1/46:
 #0: ffff0000dfc06738 ((wq_completion)events){+.+.}-{0:0}, at:
process_one_work+0x200/0x718
 #1: ffff80001320bdd0 (deferred_probe_work){+.+.}-{0:0}, at:
process_one_work+0x200/0x718
 #2: ffff0000df4b6188 (&dev->mutex){....}-{3:3}, at:
__device_attach+0x3c/0x150
CPU: 4 PID: 46 Comm: kworker/4:1 Tainted: G        W 5.9.0-rc2+ #1570
Hardware name: Hardkernel ODROID-N2 (DT)
Workqueue: events deferred_probe_work_func
Call trace:
 dump_backtrace+0x0/0x1d0
 show_stack+0x14/0x20
 dump_stack+0xec/0x16c
 ___might_sleep+0x1d4/0x1f8
 __might_sleep+0x4c/0x88
 slab_pre_alloc_hook.constprop.96+0xf4/0x138
 __kmalloc_node_track_caller+0x6c/0x288
 devres_alloc_node+0x54/0xc0
 devm_reset_control_array_get+0x34/0xc0
 phy_g12a_usb3_pcie_probe+0x148/0x210
 platform_drv_probe+0x50/0xa8
 really_probe+0x110/0x400
 driver_probe_device+0x54/0xb8
 __device_attach_driver+0x90/0xc0
 bus_for_each_drv+0x70/0xc8
 __device_attach+0xec/0x150
 device_initial_probe+0x10/0x18
 bus_probe_device+0x94/0xa0
 deferred_probe_work_func+0x70/0xa8
 process_one_work+0x2a8/0x718
 worker_thread+0x48/0x460
 kthread+0x134/0x160
 ret_from_fork+0x10/0x1c
------------[ cut here ]------------
kernel BUG at mm/vmalloc.c:2066!
Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
Modules linked in:
CPU: 4 PID: 46 Comm: kworker/4:1 Tainted: G        W 5.9.0-rc2+ #1570
Hardware name: Hardkernel ODROID-N2 (DT)
Workqueue: events deferred_probe_work_func
pstate: 00000005 (nzcv daif -PAN -UAO BTYPE=--)
pc : __get_vm_area_node+0x190/0x198
lr : get_vm_area_caller+0x34/0x40
sp : ffff80001320b9f0
x29: ffff80001320b9f0 x28: ffff8000124bf68d
x27: ffff0000e47ce005 x26: ffff0000e484a6a8
x25: 0000000000000009 x24: ffff80001220f000
x23: 0068000000000707 x22: ffff800010531544
x21: 0000000000000000 x20: 00000000ffe09000
x19: 0000000000001000 x18: ffffffffffffffff
x17: 0000000089f66c61 x16: 00000000b502d7d1
x15: ffff80001220fa48 x14: ffff0000de6df18a
x13: ffff0000de6df189 x12: 0000000000000030
x11: 0000000000000003 x10: ffff8000124f8c58
x9 : 0000000000000000 x8 : 00000000fffffffe
x7 : ffff800010531544 x6 : 0000000000000cc0
x5 : 00000000ffffffff x4 : fffffdffbfff0000
x3 : ffff800010000000 x2 : 0000000000000001
x1 : 0000000000000001 x0 : 0000000000001000
Call trace:
 __get_vm_area_node+0x190/0x198
 __ioremap_caller+0x68/0xe0
 __ioremap+0x38/0x40
 __devm_ioremap+0x7c/0xf8
 __devm_ioremap_resource+0xa8/0x160
 devm_ioremap_resource+0x10/0x18
 devm_platform_get_and_ioremap_resource+0x70/0x78
 devm_platform_ioremap_resource+0x10/0x18
 dwc3_meson_g12a_probe+0x60/0x518
 platform_drv_probe+0x50/0xa8
 really_probe+0x110/0x400
 driver_probe_device+0x54/0xb8
 __device_attach_driver+0x90/0xc0
 bus_for_each_drv+0x70/0xc8
 __device_attach+0xec/0x150
 device_initial_probe+0x10/0x18
 bus_probe_device+0x94/0xa0
 deferred_probe_work_func+0x70/0xa8
 process_one_work+0x2a8/0x718
 worker_thread+0x48/0x460
 kthread+0x134/0x160
 ret_from_fork+0x10/0x1c
Code: cb010000 11000400 17ffffe8 d503201f (d4210000)
---[ end trace b621320ae7bce6b7 ]---
Kernel panic - not syncing: Aiee, killing interrupt handler!
SMP: stopping secondary CPUs
Kernel Offset: disabled
CPU features: 0x0240002,20082004
Memory Limit: none
---[ end Kernel panic - not syncing: Aiee, killing interrupt handler! ]---

Reverting this commit on top of current linux-next fixes board booting.

> ---
> drivers/base/regmap/regmap.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
> index e93700af7e6e..a417cb1a11dc 100644
> --- a/drivers/base/regmap/regmap.c
> +++ b/drivers/base/regmap/regmap.c
> @@ -2231,7 +2231,7 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map,
> return ret;
>
> if (regs[i].delay_us)
> - udelay(regs[i].delay_us);
> + fsleep(regs[i].delay_us);
>
> base += n;
> n = 0;
> @@ -2268,7 +2268,7 @@ static int _regmap_multi_reg_write(struct regmap *map,
> return ret;
>
> if (regs[i].delay_us)
> - udelay(regs[i].delay_us);
> + fsleep(regs[i].delay_us);
> }
> return 0;
> }

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland