Skip to content

Commit 3389b4f

Browse files
prabhakarladvijay-suman
authored andcommitted
usb: renesas_usbhs: Reorder clock handling and power management in probe
[ Upstream commit ffb34a60ce86656ba12d46e91f1ccc71dd221251 ] Reorder the initialization sequence in `usbhs_probe()` to enable runtime PM before accessing registers, preventing potential crashes due to uninitialized clocks. Currently, in the probe path, registers are accessed before enabling the clocks, leading to a synchronous external abort on the RZ/V2H SoC. The problematic call flow is as follows: usbhs_probe() usbhs_sys_clock_ctrl() usbhs_bset() usbhs_write() iowrite16() <-- Register access before enabling clocks Since `iowrite16()` is performed without ensuring the required clocks are enabled, this can lead to access errors. To fix this, enable PM runtime early in the probe function and ensure clocks are acquired before register access, preventing crashes like the following on RZ/V2H: [13.272640] Internal error: synchronous external abort: 0000000096000010 [#1] PREEMPT SMP [13.280814] Modules linked in: cec renesas_usbhs(+) drm_kms_helper fuse drm backlight ipv6 [13.289088] CPU: 1 UID: 0 PID: 195 Comm: (udev-worker) Not tainted 6.14.0-rc7+ #98 [13.296640] Hardware name: Renesas RZ/V2H EVK Board based on r9a09g057h44 (DT) [13.303834] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [13.310770] pc : usbhs_bset+0x14/0x4c [renesas_usbhs] [13.315831] lr : usbhs_probe+0x2e4/0x5ac [renesas_usbhs] [13.321138] sp : ffff8000827e3850 [13.324438] x29: ffff8000827e3860 x28: 0000000000000000 x27: ffff8000827e3ca0 [13.331554] x26: ffff8000827e3ba0 x25: ffff800081729668 x24: 0000000000000025 [13.338670] x23: ffff0000c0f08000 x22: 0000000000000000 x21: ffff0000c0f08010 [13.345783] x20: 0000000000000000 x19: ffff0000c3b52080 x18: 00000000ffffffff [13.352895] x17: 0000000000000000 x16: 0000000000000000 x15: ffff8000827e36ce [13.360009] x14: 00000000000003d7 x13: 00000000000003d7 x12: 0000000000000000 [13.367122] x11: 0000000000000000 x10: 0000000000000aa0 x9 : ffff8000827e3750 [13.374235] x8 : ffff0000c1850b00 x7 : 0000000003826060 x6 : 000000000000001c [13.381347] x5 : 000000030d5fcc00 x4 : ffff8000825c0000 x3 : 0000000000000000 [13.388459] x2 : 0000000000000400 x1 : 0000000000000000 x0 : ffff0000c3b52080 [13.395574] Call trace: [13.398013] usbhs_bset+0x14/0x4c [renesas_usbhs] (P) [13.403076] platform_probe+0x68/0xdc [13.406738] really_probe+0xbc/0x2c0 [13.410306] __driver_probe_device+0x78/0x120 [13.414653] driver_probe_device+0x3c/0x154 [13.418825] __driver_attach+0x90/0x1a0 [13.422647] bus_for_each_dev+0x7c/0xe0 [13.426470] driver_attach+0x24/0x30 [13.430032] bus_add_driver+0xe4/0x208 [13.433766] driver_register+0x68/0x130 [13.437587] __platform_driver_register+0x24/0x30 [13.442273] renesas_usbhs_driver_init+0x20/0x1000 [renesas_usbhs] [13.448450] do_one_initcall+0x60/0x1d4 [13.452276] do_init_module+0x54/0x1f8 [13.456014] load_module+0x1754/0x1c98 [13.459750] init_module_from_file+0x88/0xcc [13.464004] __arm64_sys_finit_module+0x1c4/0x328 [13.468689] invoke_syscall+0x48/0x104 [13.472426] el0_svc_common.constprop.0+0xc0/0xe0 [13.477113] do_el0_svc+0x1c/0x28 [13.480415] el0_svc+0x30/0xcc [13.483460] el0t_64_sync_handler+0x10c/0x138 [13.487800] el0t_64_sync+0x198/0x19c [13.491453] Code: 2a0103e1 12003c42 12003c63 8b010084 (79400084) [13.497522] ---[ end trace 0000000000000000 ]--- Fixes: f1407d5 ("usb: renesas_usbhs: Add Renesas USBHS common code") Signed-off-by: Lad Prabhakar <[email protected]> Reviewed-by: Yoshihiro Shimoda <[email protected]> Tested-by: Yoshihiro Shimoda <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit 0a1e16a6cbf4452b46f20b862d6141a1e90844ee) Signed-off-by: Vijayendra Suman <[email protected]>
1 parent 2ddc3af commit 3389b4f

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

drivers/usb/renesas_usbhs/common.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -678,10 +678,29 @@ static int usbhs_probe(struct platform_device *pdev)
678678
INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
679679
spin_lock_init(usbhs_priv_to_lock(priv));
680680

681+
/*
682+
* Acquire clocks and enable power management (PM) early in the
683+
* probe process, as the driver accesses registers during
684+
* initialization. Ensure the device is active before proceeding.
685+
*/
686+
pm_runtime_enable(dev);
687+
688+
ret = usbhsc_clk_get(dev, priv);
689+
if (ret)
690+
goto probe_pm_disable;
691+
692+
ret = pm_runtime_resume_and_get(dev);
693+
if (ret)
694+
goto probe_clk_put;
695+
696+
ret = usbhsc_clk_prepare_enable(priv);
697+
if (ret)
698+
goto probe_pm_put;
699+
681700
/* call pipe and module init */
682701
ret = usbhs_pipe_probe(priv);
683702
if (ret < 0)
684-
return ret;
703+
goto probe_clk_dis_unprepare;
685704

686705
ret = usbhs_fifo_probe(priv);
687706
if (ret < 0)
@@ -698,10 +717,6 @@ static int usbhs_probe(struct platform_device *pdev)
698717
if (ret)
699718
goto probe_fail_rst;
700719

701-
ret = usbhsc_clk_get(dev, priv);
702-
if (ret)
703-
goto probe_fail_clks;
704-
705720
/*
706721
* deviece reset here because
707722
* USB device might be used in boot loader.
@@ -714,7 +729,7 @@ static int usbhs_probe(struct platform_device *pdev)
714729
if (ret) {
715730
dev_warn(dev, "USB function not selected (GPIO)\n");
716731
ret = -ENOTSUPP;
717-
goto probe_end_mod_exit;
732+
goto probe_assert_rest;
718733
}
719734
}
720735

@@ -728,14 +743,19 @@ static int usbhs_probe(struct platform_device *pdev)
728743
ret = usbhs_platform_call(priv, hardware_init, pdev);
729744
if (ret < 0) {
730745
dev_err(dev, "platform init failed.\n");
731-
goto probe_end_mod_exit;
746+
goto probe_assert_rest;
732747
}
733748

734749
/* reset phy for connection */
735750
usbhs_platform_call(priv, phy_reset, pdev);
736751

737-
/* power control */
738-
pm_runtime_enable(dev);
752+
/*
753+
* Disable the clocks that were enabled earlier in the probe path,
754+
* and let the driver handle the clocks beyond this point.
755+
*/
756+
usbhsc_clk_disable_unprepare(priv);
757+
pm_runtime_put(dev);
758+
739759
if (!usbhs_get_dparam(priv, runtime_pwctrl)) {
740760
usbhsc_power_ctrl(priv, 1);
741761
usbhs_mod_autonomy_mode(priv);
@@ -752,16 +772,22 @@ static int usbhs_probe(struct platform_device *pdev)
752772

753773
return ret;
754774

755-
probe_end_mod_exit:
756-
usbhsc_clk_put(priv);
757-
probe_fail_clks:
775+
probe_assert_rest:
758776
reset_control_assert(priv->rsts);
759777
probe_fail_rst:
760778
usbhs_mod_remove(priv);
761779
probe_end_fifo_exit:
762780
usbhs_fifo_remove(priv);
763781
probe_end_pipe_exit:
764782
usbhs_pipe_remove(priv);
783+
probe_clk_dis_unprepare:
784+
usbhsc_clk_disable_unprepare(priv);
785+
probe_pm_put:
786+
pm_runtime_put(dev);
787+
probe_clk_put:
788+
usbhsc_clk_put(priv);
789+
probe_pm_disable:
790+
pm_runtime_disable(dev);
765791

766792
dev_info(dev, "probe failed (%d)\n", ret);
767793

0 commit comments

Comments
 (0)