lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
 <TYCPR01MB11040727E81F6DF8647D92343D8B52@TYCPR01MB11040.jpnprd01.prod.outlook.com>
Date: Tue, 8 Apr 2025 10:40:08 +0000
From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@...esas.com>
To: Prabhakar <prabhakar.csengg@...il.com>, Greg Kroah-Hartman
	<gregkh@...uxfoundation.org>, Geert Uytterhoeven <geert+renesas@...der.be>,
	Kuninori Morimoto <kuninori.morimoto.gx@...esas.com>
CC: "linux-usb@...r.kernel.org" <linux-usb@...r.kernel.org>,
	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
	"linux-renesas-soc@...r.kernel.org" <linux-renesas-soc@...r.kernel.org>, Biju
 Das <biju.das.jz@...renesas.com>, Claudiu Beznea
	<claudiu.beznea.uj@...renesas.com>, Fabrizio Castro
	<fabrizio.castro.jz@...esas.com>, Prabhakar Mahadev Lad
	<prabhakar.mahadev-lad.rj@...renesas.com>
Subject: RE: [PATCH v2 3/3] usb: renesas_usbhs: Reorder clock handling and
 power management in probe

Hello Prabhakar-san,

Thank you for the patch!

> From: Prabhakar, Sent: Monday, April 7, 2025 7:50 PM
> 
> Reorder the initialization sequence in `usbhs_probe()` to enable runtime
> PM before accessing registers, preventing potential crashes due to
> uninitialized clocks.

Just for a record. I don't know why, but the issue didn't occur on the original code
with my environment (R-Car H3). But, anyway, I understood that we need this patch for RZ/V2H.

----- I added some debug printk -----
<snip>
[    3.193400] usbhs_probe:706
[    3.196204] usbhs_probe:710
[    3.199012] usbhs_probe:715
[    3.201808] usbhs_probe:720
[    3.204605] usbhs_read: reg = 0
[    3.207754] usbhs_write: reg = 0, data = 20
[    3.211941] usbhs_probe:727
[    3.214738] usbhs_read: reg = 102
[    3.218061] usbhs_write: reg = 102, data = 4000
[    3.222697] usbhs_read: reg = 0
[    3.225845] usbhs_write: reg = 0, data = 420
[    3.230118] usbhs_write: reg = 30, data = 0
[    3.234304] usbhs_write: reg = 32, data = 0
[    3.238489] usbhs_write: reg = 3a, data = 0
[    3.242673] usbhs_write: reg = 36, data = 0
[    3.246859] usbhs_write: reg = 30, data = 8000
[    3.251312] usbhs_read: reg = 40
[    3.254540] renesas_usbhs e659c000.usb: probed
[    3.802010] usbhs_probe:690
[    3.808677] renesas-cpg-mssr e6150000.clock-controller: MSTP 704/hsusb ON
-----

> 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: f1407d5c66240 ("usb: renesas_usbhs: Add Renesas USBHS common code")
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@...renesas.com>
> ---
>  drivers/usb/renesas_usbhs/common.c | 50 +++++++++++++++++++++++-------
>  1 file changed, 38 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
> index 703cf5d0cb41..f52418fe3fd4 100644
> --- a/drivers/usb/renesas_usbhs/common.c
> +++ b/drivers/usb/renesas_usbhs/common.c
> @@ -685,10 +685,29 @@ static int usbhs_probe(struct platform_device *pdev)
>  	INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
>  	spin_lock_init(usbhs_priv_to_lock(priv));
> 
> +	/*
> +	 * Acquire clocks and enable power management (PM) early in the
> +	 * probe process, as the driver accesses registers during
> +	 * initialization. Ensure the device is active before proceeding.
> +	 */
> +	pm_runtime_enable(dev);
> +
> +	ret = usbhsc_clk_get(dev, priv);
> +	if (ret)
> +		goto probe_pm_disable;
> +
> +	ret = pm_runtime_resume_and_get(dev);
> +	if (ret)
> +		goto probe_clk_put;
> +
> +	ret = usbhsc_clk_prepare_enable(priv);
> +	if (ret)
> +		goto probe_pm_put;
> +

Did you really need to call these functions at this timing?
IIUC, usbhs_{pipe,fifo,mod}_probe() will not access any registers.

>  	/* call pipe and module init */
>  	ret = usbhs_pipe_probe(priv);
>  	if (ret < 0)
> -		return ret;
> +		goto probe_clk_dis_unprepare;
> 
>  	ret = usbhs_fifo_probe(priv);
>  	if (ret < 0)
> @@ -705,10 +724,6 @@ static int usbhs_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto probe_fail_rst;
> 
> -	ret = usbhsc_clk_get(dev, priv);
> -	if (ret)
> -		goto probe_fail_clks;
> -

If my understanding above is correct, I would like to add some functions calling around here
to reduce modification lines.

Best regards,
Yoshihiro Shimoda

>  	/*
>  	 * device reset here because
>  	 * USB device might be used in boot loader.
> @@ -721,7 +736,7 @@ static int usbhs_probe(struct platform_device *pdev)
>  		if (ret) {
>  			dev_warn(dev, "USB function not selected (GPIO)\n");
>  			ret = -ENOTSUPP;
> -			goto probe_end_mod_exit;
> +			goto probe_assert_rest;
>  		}
>  	}
> 
> @@ -735,14 +750,19 @@ static int usbhs_probe(struct platform_device *pdev)
>  	ret = usbhs_platform_call(priv, hardware_init, pdev);
>  	if (ret < 0) {
>  		dev_err(dev, "platform init failed.\n");
> -		goto probe_end_mod_exit;
> +		goto probe_assert_rest;
>  	}
> 
>  	/* reset phy for connection */
>  	usbhs_platform_call(priv, phy_reset, pdev);
> 
> -	/* power control */
> -	pm_runtime_enable(dev);
> +	/*
> +	 * Disable the clocks that were enabled earlier in the probe path,
> +	 * and let the driver handle the clocks beyond this point.
> +	 */
> +	usbhsc_clk_disable_unprepare(priv);
> +	pm_runtime_put(dev);
> +
>  	if (!usbhs_get_dparam(priv, runtime_pwctrl)) {
>  		usbhsc_power_ctrl(priv, 1);
>  		usbhs_mod_autonomy_mode(priv);
> @@ -759,9 +779,7 @@ static int usbhs_probe(struct platform_device *pdev)
> 
>  	return ret;
> 
> -probe_end_mod_exit:
> -	usbhsc_clk_put(priv);
> -probe_fail_clks:
> +probe_assert_rest:
>  	reset_control_assert(priv->rsts);
>  probe_fail_rst:
>  	usbhs_mod_remove(priv);
> @@ -769,6 +787,14 @@ static int usbhs_probe(struct platform_device *pdev)
>  	usbhs_fifo_remove(priv);
>  probe_end_pipe_exit:
>  	usbhs_pipe_remove(priv);
> +probe_clk_dis_unprepare:
> +	usbhsc_clk_disable_unprepare(priv);
> +probe_pm_put:
> +	pm_runtime_put(dev);
> +probe_clk_put:
> +	usbhsc_clk_put(priv);
> +probe_pm_disable:
> +	pm_runtime_disable(dev);
> 
>  	dev_info(dev, "probe failed (%d)\n", ret);
> 
> --
> 2.49.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ