Message ID | 20200830185356.5365-3-digetx@gmail.com |
---|---|
State | Accepted |
Commit | 2b32d2f7ce0a54ce74a75f0d939b5ee063a05ec5 |
Headers | show |
Series | Introduce Embedded Controller driver for Acer A500 | expand |
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@gmail.com> 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
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; }
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@gmail.com> --- drivers/base/regmap/regmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)