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-next>] [day] [month] [year] [list]
Message-ID: <taw2mvbj6a2lqwy5h3tuqeifqy2w4gt4pzh4uahxuw27yw64q2@koxg54wgp2a2>
Date: Tue, 24 Jun 2025 17:08:32 +0200
From: Ernest Van Hoecke <ernestvanhoecke@...il.com>
To: Alan Stern <stern@...land.harvard.edu>, 
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>, Thinh Nguyen <Thinh.Nguyen@...opsys.com>, 
	Roger Quadros <rogerq@...nel.org>, Nishanth Menon <nm@...com>, 
	Vignesh Raghavendra <vigneshr@...com>
Cc: Sebastian Reichel <sebastian.reichel@...labora.com>, 
	Chance Yang <chance.yang@...ron.us>, Prashanth K <prashanth.k@....qualcomm.com>, 
	linux-usb@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: dwc3-am62/usb-conn-gpio: USB gadget not added when booting in host
 mode

Hi all,

On the TI AM62 when using a USB OTG port, I found some unexpected
behaviour when booting with this port in host mode.

This happens, for example, when booting with a USB pen drive inserted.
When the pen drive is later removed, the OTG port correctly switches
to "device" mode instead of "host" mode, but the related USB gadget
does not come up (in my case, a CDC NCM configuration).

This issue only occurs when CONFIG_USB_CONN_GPIO and
CONFIG_USB_DWC3_AM62 are set to m and not when these modules are
built-in.

I tried to find the differences in their setup using ftrace and printk.

When they are built-in, I can see that the USB connector module
(usb-conn-gpio) is always probed (usb_conn_probe()) after dwc3-am62.

When built as modules, usb_conn_probe can happen before the probe of
dwc3-am62 is finished. This is problematic since the USB Role Switch
device needs to be registered first by DWC3. Namely, `dwc3_drd_init()`
calls `usb_role_switch_register()`, and `usb_conn_probe()` gets it with
`usb_role_switch_get()`. When `usb_conn_probe()` cannot get the role
switch device, it defers its probe until it can. This logic seems to
be working well, so the only difference here seems to be probe order.

In both cases:
 * The (last) usb_conn_probe gets the correct usb role switch.
 * The dual role mode is the same, and switches as expected

When the pen drive is unplugged, the USB OTG port correctly switches
to device mode for both cases. `dwc3_gadget_init()` is then called, but
when built as modules, strange things seem to happen once this method
hits `usb_add_gadget()`. Ftrace shows that it is executed, and executes
its body and returns, but my printk's after this point don't end up in
the kernel log anymore.

Ftrace snippet in working (builtin) case:
[...]
     kworker/1:2-52      [001] .....    80.070233: dwc3_gadget_init <-__dwc3_set_mode
     kworker/1:2-52      [001] .....    80.073332: usb_initialize_gadget <-dwc3_gadget_init
[...]
     kworker/1:2-52      [001] .....    80.855694: dwc3_debugfs_create_endpoint_dir <-dwc3_gadget_init
     kworker/1:2-52      [001] .....    80.875767: usb_add_gadget <-dwc3_gadget_init
     kworker/1:2-52      [001] .....    80.896299: usb_udc_uevent <-dev_uevent
   systemd-udevd-132     [000] .....    80.898973: usb_udc_uevent <-dev_uevent
   (udev-worker)-469     [000] .....    80.899839: usb_udc_uevent <-dev_uevent
     kworker/1:3-53      [001] .....    80.900302: usb_gadget_state_work <-process_one_work
   gadget-import-512     [000] .....    80.963264: gadgets_make <-configfs_mkdir
[...]

Ftrace snippet in nonworking (modules) case:
[...]
     kworker/0:4-60      [000] .....   104.112791: dwc3_gadget_init <-__dwc3_set_mode
     kworker/0:4-60      [000] .....   104.115912: usb_initialize_gadget <-dwc3_gadget_init
[...]
     kworker/0:4-60      [000] .....   104.918814: usb_add_gadget <-dwc3_gadget_init
     kworker/0:4-60      [000] .....   104.939290: usb_udc_uevent <-dev_uevent
   systemd-udevd-127     [000] .....   104.943682: usb_udc_uevent <-dev_uevent
     kworker/0:0-9       [000] .....   104.944201: usb_gadget_state_work <-process_one_work
   (udev-worker)-417     [001] .....   104.944411: usb_udc_uevent <-dev_uevent
[end of ]

When built as modules, gadgets_make() is never called, and the resulting
chain of gadget events thus does not happen.

My printk logging after unplugging the pen drive shows the following:

Builtin:
usb_conn_isr
usb_conn_queue_dwork
usb_conn_detect_cable
usb_role_string
usb_role_string
usb_conn_detect_cable role host -> device, gpios: id 1, vbus 1
usb_role_switch_set_role
usb_role_switch_get_drvdata
dwc3_usb_role_switch_set, role: 2
usb_role_switch_uevent
__dwc3_set_mode: dwc->current_dr_role: 1
__dwc3_set_mode: desired_dr_role: 2
usb_role_switch_uevent
usb_role_switch_uevent
dwc3_gadget_init
dwc3_gadget_init: usb_initialize_gadget
dwc3_gadget_init: dwc3_gadget_init_endpoints
dwc3_gadget_init: usb_add_gadget
dwc3_gadget_check_config
dwc3_gadget_start
__dwc3_gadget_start
dwc3_gadget_start_config, resource_index: 0
dwc3_send_gadget_ep_cmd, dep: ep0out, cmd: 9, params: 0000000013236000
__dwc3_gadget_ep_enable, dep: ep0out, action: 0
dwc3_gadget_set_ep_config, dep: ep0out, action: 0
dwc3_send_gadget_ep_cmd, dep: ep0out, cmd: 1, params: 0000000013236000
dwc3_send_gadget_ep_cmd, dep: ep0out, cmd: 2, params: 0000000013236000
__dwc3_gadget_ep_enable, dep: ep0in, action: 0
dwc3_gadget_set_ep_config, dep: ep0in, action: 0
dwc3_send_gadget_ep_cmd, dep: ep0in, cmd: 1, params: 0000000013236000
dwc3_send_gadget_ep_cmd, dep: ep0in, cmd: 2, params: 0000000013236000
dwc3_send_gadget_ep_cmd, dep: ep0out, cmd: 6, params: 00000000c3883fbf
dwc3_gadget_run_stop: start

Modules:
usb_conn_isr
usb_conn_queue_dwork
usb_conn_detect_cable
usb_role_string
usb_role_string
usb_conn_detect_cable role host -> device, gpios: id 1, vbus 1
usb_role_switch_set_role
usb_role_switch_get_drvdata
dwc3_usb_role_switch_set, role: 2
usb_role_switch_uevent
__dwc3_set_mode: dwc->current_dr_role: 1
usb_role_switch_uevent
__dwc3_set_mode: desired_dr_role: 2
usb_role_switch_uevent
dwc3_gadget_init
dwc3_gadget_init: usb_initialize_gadget
dwc3_gadget_init: dwc3_gadget_init_endpoints


Logs before the unplug are identical to each other except for the
usb_conn_probe that can happen earlier in the boot and potentially get
deferred.

I will be investigating this further, any input is more than welcome.

Thanks,
Ernest

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ