From: sashiko-bot@kernel.org
To: "Sebastian Reichel" <sebastian.reichel@collabora.com>
Cc: linux-usb@vger.kernel.org, linux-phy@lists.infradead.org,
vkoul@kernel.org, neil.armstrong@linaro.org, olteanv@gmail.com
Subject: Re: [PATCH v18 7/7] usb: dwc3: rockchip: fix USB-C reconnect in gadget mode
Date: Wed, 21 Oct 2026 18:31:49 +0000 [thread overview]
Message-ID: <sashiko-outbox-180556@kernel.org> (raw)
In-Reply-To: <20261021-b4-rockchip-dwc3-rockchip-glue-v18-7-60000d03fca2@collabora.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] usb: dwc3: rockchip: wrong role check in dwc3_rockchip_phy_post_reset()
- [High] usb: dwc3: rockchip: async vbus_work race in dwc3_rockchip_phy_reset()
- [High] usb: dwc3: rockchip: dropped VBUS state in dwc3_rockchip_vbus_handler()
--
commit 97e99b8258d01d9f23d8408a81715cbe540da468
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
usb: dwc3: rockchip: fix USB-C reconnect in gadget mode
This commit adds a vbus handler to the Rockchip dwc3 glue driver and invokes
it from the phy reset callbacks and the .pre_set_role glue callback so that
the gadget core is notified of vbus state changes across usb-c disconnects
and reconnects.
> diff --git a/drivers/usb/dwc3/dwc3-rockchip.c b/drivers/usb/dwc3/dwc3-rockchip.c
> index 75e647e04cc52..65d17536af142 100644
> --- a/drivers/usb/dwc3/dwc3-rockchip.c
> +++ b/drivers/usb/dwc3/dwc3-rockchip.c
> @@ -10,8 +10,19 @@
> struct dwc3_rockchip {
> struct dwc3 dwc;
> u8 phy_reset_active;
> + enum usb_role role;
> };
>
> +static void dwc3_rockchip_vbus_handler(struct dwc3 *dwc, bool present)
> +{
> + guard(spinlock_irqsave)(&dwc->lock);
> +
> + if (!dwc->gadget || !dwc->gadget_driver)
> + return;
> +
> + usb_udc_vbus_handler(dwc->gadget, present);
> +}
[Severity: High]
What happens in dwc3_rockchip_vbus_handler() when a role switch occurs before
a gadget driver is bound or before dwc->gadget is initialized?
When dwc3_gadget_init() registers a gadget via usb_add_gadget(), udc->vbus is
initialized to true:
drivers/usb/gadget/udc/core.c:usb_add_gadget() {
...
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
udc->vbus = true;
...
}
If the system boots without a usb-c cable attached, tcpm invokes
usb_role_switch_set_role() -> dwc3_usb_role_switch_set() ->
dwc3_pre_set_role() -> dwc3_rockchip_set_role(dwc, USB_ROLE_NONE) ->
dwc3_rockchip_vbus_handler(dwc, false). If no gadget driver is bound yet
(dwc->gadget_driver is NULL), dwc3_rockchip_vbus_handler() returns early and
drops the present = false update, leaving udc->vbus as true.
The same thing happens when unplugging a usb-c host cable (transitioning from
USB_ROLE_HOST to USB_ROLE_NONE): dwc3_usb_role_switch_set() calls
dwc3_pre_set_role() synchronously while still in host mode, before
dwc3_set_mode() queues dwc->drd_work (__dwc3_set_mode) to call
dwc3_gadget_init(), so the newly created udc also starts with udc->vbus set
to true while dwc_rk->role is USB_ROLE_NONE.
When userspace later binds a configfs gadget driver while unplugged,
gadget_bind_driver() calls usb_udc_connect_control_locked(), which sees
udc->vbus == true and calls usb_gadget_connect_locked(), setting
gadget->connected = 1 with no cable attached. Once dwc3 runtime-suspends,
plugging in a usb-c device cable calls usb_udc_vbus_handler(dwc->gadget, true)
-> usb_gadget_connect_locked(), which sees gadget->connected == 1 and returns
early without calling dwc3_gadget_pullup() to resume the controller.
Conversely, if a cable is unplugged while a gadget driver is bound (setting
udc->vbus = false), the gadget driver is unbound (setting dwc->gadget_driver
to NULL), and the cable is plugged back in before rebinding, the present =
true update is dropped and the gadget stays disconnected after bind.
> +
> static void dwc3_rockchip_phy_pre_reset(struct dwc3_rockchip *dwc_rk, int port)
> {
> struct dwc3 *dwc = &dwc_rk->dwc;
> @@ -26,6 +37,8 @@ static void dwc3_rockchip_phy_pre_reset(struct dwc3_rockchip *dwc_rk, int port)
> if (!pm_runtime_active(dwc->dev))
> return;
>
> + dwc3_rockchip_vbus_handler(dwc, false);
[Severity: High]
Can calling dwc3_rockchip_vbus_handler(dwc, false) in
dwc3_rockchip_phy_pre_reset() followed by
dwc3_rockchip_vbus_handler(dwc, gadget_mode) in
dwc3_rockchip_phy_post_reset() race with udc->vbus_work?
In drivers/usb/gadget/udc/core.c, usb_udc_vbus_handler() does not disconnect
or connect synchronously; it overwrites a single boolean and schedules
asynchronous work:
void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status)
{
struct usb_udc *udc = gadget->udc;
if (udc) {
udc->vbus = status;
schedule_work(&udc->vbus_work);
}
}
During phy initialization in rk_udphy_power_on(), rk_udphy_run_reset_handler()
calls dwc3_rockchip_phy_pre_reset(), runs rk_udphy_setup() and rk_udphy_init(),
and then calls dwc3_rockchip_phy_post_reset(). This creates several issues:
1. If udc->vbus_work (vbus_event_work) has not started before
dwc3_rockchip_phy_post_reset() runs, the second usb_udc_vbus_handler() call
overwrites udc->vbus back to true. When vbus_event_work finally runs, it
calls usb_gadget_connect_locked(), sees gadget->connected is already set,
and returns as a no-op without performing the disconnect or reconnect.
2. If vbus_event_work runs on another cpu during rk_udphy_init() while
DWC3_GUSB3PIPECTL_PHYSOFTRST is asserted and the external phy is held in
reset without pipe clocks, usb_gadget_disconnect_locked() invokes
dwc3_gadget_pullup(gadget, 0) -> dwc3_gadget_soft_disconnect() ->
dwc3_gadget_run_stop(dwc, false), issuing endpoint commands and polling
DWC3_DSTS_DEVCTRLHLT while the phy is in reset.
3. During system resume, dwc3_pm_resume() in drivers/usb/dwc3/core.c calls
pm_runtime_disable(dev) and pm_runtime_set_active(dev) before
dwc3_resume_common() -> dwc3_core_init() -> dwc3_phy_init():
pm_runtime_disable(dev);
ret = pm_runtime_set_active(dev);
if (ret)
goto out;
ret = dwc3_resume_common(dwc, PMSG_RESUME);
Because pm_runtime_active(dwc->dev) is true, the phy reset callbacks
schedule vbus_event_work while runtime pm is disabled. If vbus_event_work
runs before pm_runtime_enable(dev), dwc3_gadget_pullup() clears
dwc->softconnect, fails pm_runtime_get_sync(dwc->dev) with -EACCES, calls
pm_runtime_set_suspended(dwc->dev), and leaves gadget->connected = 1 with
dwc->softconnect = 0.
4. When dwc->dev is already runtime-suspended (!pm_runtime_active(dwc->dev))
in a fixed peripheral configuration (dr_mode == USB_DR_MODE_PERIPHERAL),
both dwc3_rockchip_phy_pre_reset() and dwc3_rockchip_phy_post_reset()
return early without calling dwc3_rockchip_vbus_handler().
> +
> /*
> * Assert USB3 PHY soft reset within DWC3 before the external
> * PHY resets. This disconnects the PIPE interface, preventing
> @@ -43,6 +56,9 @@ static void dwc3_rockchip_phy_pre_reset(struct dwc3_rockchip *dwc_rk, int port)
> static void dwc3_rockchip_phy_post_reset(struct dwc3_rockchip *dwc_rk, int port)
> {
> struct dwc3 *dwc = &dwc_rk->dwc;
> + bool gadget_mode = (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE) ||
> + ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG) &&
> + (dwc_rk->role == USB_ROLE_DEVICE));
> u32 reg;
>
> scoped_guard(spinlock_irqsave, &dwc->lock) {
> @@ -56,6 +72,8 @@ static void dwc3_rockchip_phy_post_reset(struct dwc3_rockchip *dwc_rk, int port)
> reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
> dwc3_writel(dwc, DWC3_GUSB3PIPECTL(port), reg);
> }
> +
> + dwc3_rockchip_vbus_handler(dwc, gadget_mode);
> }
[Severity: High]
Does gadget_mode in dwc3_rockchip_phy_post_reset() check the right field on
dual-role controllers using usb-role-switch?
Here dwc->current_dr_role is compared against DWC3_GCTL_PRTCAP_DEVICE and
DWC3_GCTL_PRTCAP_OTG. However, in drivers/usb/dwc3/drd.c,
dwc3_usb_role_switch_set() never sets mode to DWC3_GCTL_PRTCAP_OTG:
switch (role) {
case USB_ROLE_HOST:
mode = DWC3_GCTL_PRTCAP_HOST;
break;
case USB_ROLE_DEVICE:
mode = DWC3_GCTL_PRTCAP_DEVICE;
break;
default:
if (dwc->role_switch_default_mode == USB_DR_MODE_HOST)
mode = DWC3_GCTL_PRTCAP_HOST;
else
mode = DWC3_GCTL_PRTCAP_DEVICE;
break;
}
dwc3_pre_set_role(dwc, role);
dwc3_set_mode(dwc, mode);
When the cable is unplugged or in displayport-only altmode (role is
USB_ROLE_NONE), dwc3_usb_role_switch_set() selects DWC3_GCTL_PRTCAP_DEVICE
because dwc->role_switch_default_mode defaults to USB_DR_MODE_PERIPHERAL.
As a result, dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE evaluates to true
even when dwc_rk->role is USB_ROLE_NONE. When a phy reset completes in
dwc3_rockchip_phy_post_reset() (for example during rk_udphy_dp_phy_power_on()
or system resume), dwc3_rockchip_vbus_handler(dwc, true) is called while no
usb device cable is connected, setting gadget->connected = 1 so that a later
USB_ROLE_DEVICE plug-in becomes a no-op in usb_gadget_connect_locked().
In addition, dwc3_pre_set_role() updates dwc_rk->role synchronously in
dwc3_rockchip_set_role(), whereas dwc3_set_mode() queues dwc->drd_work
(__dwc3_set_mode) asynchronously. During a USB_ROLE_DEVICE to USB_ROLE_HOST
transition, dwc->current_dr_role is still DWC3_GCTL_PRTCAP_DEVICE (making
gadget_mode true while dwc_rk->role is USB_ROLE_HOST), and during a
USB_ROLE_HOST to USB_ROLE_DEVICE transition, dwc->current_dr_role is still
DWC3_GCTL_PRTCAP_HOST until __dwc3_set_mode() finishes (making gadget_mode
false while dwc_rk->role is USB_ROLE_DEVICE).
Also, dwc->current_dr_role and dwc_rk->role are read at the top of
dwc3_rockchip_phy_post_reset() outside dwc->lock, and dwc_rk->role is written
in dwc3_rockchip_set_role() without holding dwc->lock:
static void dwc3_rockchip_set_role(struct dwc3 *dwc, enum usb_role role)
{
struct dwc3_rockchip *dwc_rk = container_of(dwc, struct dwc3_rockchip, dwc);
dwc_rk->role = role;
dwc3_rockchip_vbus_handler(dwc, role == USB_ROLE_DEVICE);
}
Could a concurrent dwc3_rockchip_set_role(dwc, USB_ROLE_NONE) run between the
initial gadget_mode evaluation and the dwc3_rockchip_vbus_handler() call at
the end of dwc3_rockchip_phy_post_reset(), causing the stale gadget_mode value
to overwrite the vbus state? Should this check dwc->dr_mode ==
USB_DR_MODE_PERIPHERAL (and dwc_rk->role == USB_ROLE_DEVICE for otg) under
dwc->lock instead?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261021-b4-rockchip-dwc3-rockchip-glue-v18-0-60000d03fca2@collabora.com?part=7
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
WARNING: multiple messages have this Message-ID (diff)
From: sashiko-bot@kernel.org
To: "Sebastian Reichel" <sebastian.reichel@collabora.com>
Cc: linux-usb@vger.kernel.org, linux-phy@lists.infradead.org,
vkoul@kernel.org, neil.armstrong@linaro.org, olteanv@gmail.com
Subject: Re: [PATCH v18 7/7] usb: dwc3: rockchip: fix USB-C reconnect in gadget mode
Date: Wed, 21 Oct 2026 18:31:49 +0000 [thread overview]
Message-ID: <sashiko-outbox-180556@kernel.org> (raw)
In-Reply-To: <20261021-b4-rockchip-dwc3-rockchip-glue-v18-7-60000d03fca2@collabora.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] usb: dwc3: rockchip: wrong role check in dwc3_rockchip_phy_post_reset()
- [High] usb: dwc3: rockchip: async vbus_work race in dwc3_rockchip_phy_reset()
- [High] usb: dwc3: rockchip: dropped VBUS state in dwc3_rockchip_vbus_handler()
--
commit 97e99b8258d01d9f23d8408a81715cbe540da468
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
usb: dwc3: rockchip: fix USB-C reconnect in gadget mode
This commit adds a vbus handler to the Rockchip dwc3 glue driver and invokes
it from the phy reset callbacks and the .pre_set_role glue callback so that
the gadget core is notified of vbus state changes across usb-c disconnects
and reconnects.
> diff --git a/drivers/usb/dwc3/dwc3-rockchip.c b/drivers/usb/dwc3/dwc3-rockchip.c
> index 75e647e04cc52..65d17536af142 100644
> --- a/drivers/usb/dwc3/dwc3-rockchip.c
> +++ b/drivers/usb/dwc3/dwc3-rockchip.c
> @@ -10,8 +10,19 @@
> struct dwc3_rockchip {
> struct dwc3 dwc;
> u8 phy_reset_active;
> + enum usb_role role;
> };
>
> +static void dwc3_rockchip_vbus_handler(struct dwc3 *dwc, bool present)
> +{
> + guard(spinlock_irqsave)(&dwc->lock);
> +
> + if (!dwc->gadget || !dwc->gadget_driver)
> + return;
> +
> + usb_udc_vbus_handler(dwc->gadget, present);
> +}
[Severity: High]
What happens in dwc3_rockchip_vbus_handler() when a role switch occurs before
a gadget driver is bound or before dwc->gadget is initialized?
When dwc3_gadget_init() registers a gadget via usb_add_gadget(), udc->vbus is
initialized to true:
drivers/usb/gadget/udc/core.c:usb_add_gadget() {
...
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
udc->vbus = true;
...
}
If the system boots without a usb-c cable attached, tcpm invokes
usb_role_switch_set_role() -> dwc3_usb_role_switch_set() ->
dwc3_pre_set_role() -> dwc3_rockchip_set_role(dwc, USB_ROLE_NONE) ->
dwc3_rockchip_vbus_handler(dwc, false). If no gadget driver is bound yet
(dwc->gadget_driver is NULL), dwc3_rockchip_vbus_handler() returns early and
drops the present = false update, leaving udc->vbus as true.
The same thing happens when unplugging a usb-c host cable (transitioning from
USB_ROLE_HOST to USB_ROLE_NONE): dwc3_usb_role_switch_set() calls
dwc3_pre_set_role() synchronously while still in host mode, before
dwc3_set_mode() queues dwc->drd_work (__dwc3_set_mode) to call
dwc3_gadget_init(), so the newly created udc also starts with udc->vbus set
to true while dwc_rk->role is USB_ROLE_NONE.
When userspace later binds a configfs gadget driver while unplugged,
gadget_bind_driver() calls usb_udc_connect_control_locked(), which sees
udc->vbus == true and calls usb_gadget_connect_locked(), setting
gadget->connected = 1 with no cable attached. Once dwc3 runtime-suspends,
plugging in a usb-c device cable calls usb_udc_vbus_handler(dwc->gadget, true)
-> usb_gadget_connect_locked(), which sees gadget->connected == 1 and returns
early without calling dwc3_gadget_pullup() to resume the controller.
Conversely, if a cable is unplugged while a gadget driver is bound (setting
udc->vbus = false), the gadget driver is unbound (setting dwc->gadget_driver
to NULL), and the cable is plugged back in before rebinding, the present =
true update is dropped and the gadget stays disconnected after bind.
> +
> static void dwc3_rockchip_phy_pre_reset(struct dwc3_rockchip *dwc_rk, int port)
> {
> struct dwc3 *dwc = &dwc_rk->dwc;
> @@ -26,6 +37,8 @@ static void dwc3_rockchip_phy_pre_reset(struct dwc3_rockchip *dwc_rk, int port)
> if (!pm_runtime_active(dwc->dev))
> return;
>
> + dwc3_rockchip_vbus_handler(dwc, false);
[Severity: High]
Can calling dwc3_rockchip_vbus_handler(dwc, false) in
dwc3_rockchip_phy_pre_reset() followed by
dwc3_rockchip_vbus_handler(dwc, gadget_mode) in
dwc3_rockchip_phy_post_reset() race with udc->vbus_work?
In drivers/usb/gadget/udc/core.c, usb_udc_vbus_handler() does not disconnect
or connect synchronously; it overwrites a single boolean and schedules
asynchronous work:
void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status)
{
struct usb_udc *udc = gadget->udc;
if (udc) {
udc->vbus = status;
schedule_work(&udc->vbus_work);
}
}
During phy initialization in rk_udphy_power_on(), rk_udphy_run_reset_handler()
calls dwc3_rockchip_phy_pre_reset(), runs rk_udphy_setup() and rk_udphy_init(),
and then calls dwc3_rockchip_phy_post_reset(). This creates several issues:
1. If udc->vbus_work (vbus_event_work) has not started before
dwc3_rockchip_phy_post_reset() runs, the second usb_udc_vbus_handler() call
overwrites udc->vbus back to true. When vbus_event_work finally runs, it
calls usb_gadget_connect_locked(), sees gadget->connected is already set,
and returns as a no-op without performing the disconnect or reconnect.
2. If vbus_event_work runs on another cpu during rk_udphy_init() while
DWC3_GUSB3PIPECTL_PHYSOFTRST is asserted and the external phy is held in
reset without pipe clocks, usb_gadget_disconnect_locked() invokes
dwc3_gadget_pullup(gadget, 0) -> dwc3_gadget_soft_disconnect() ->
dwc3_gadget_run_stop(dwc, false), issuing endpoint commands and polling
DWC3_DSTS_DEVCTRLHLT while the phy is in reset.
3. During system resume, dwc3_pm_resume() in drivers/usb/dwc3/core.c calls
pm_runtime_disable(dev) and pm_runtime_set_active(dev) before
dwc3_resume_common() -> dwc3_core_init() -> dwc3_phy_init():
pm_runtime_disable(dev);
ret = pm_runtime_set_active(dev);
if (ret)
goto out;
ret = dwc3_resume_common(dwc, PMSG_RESUME);
Because pm_runtime_active(dwc->dev) is true, the phy reset callbacks
schedule vbus_event_work while runtime pm is disabled. If vbus_event_work
runs before pm_runtime_enable(dev), dwc3_gadget_pullup() clears
dwc->softconnect, fails pm_runtime_get_sync(dwc->dev) with -EACCES, calls
pm_runtime_set_suspended(dwc->dev), and leaves gadget->connected = 1 with
dwc->softconnect = 0.
4. When dwc->dev is already runtime-suspended (!pm_runtime_active(dwc->dev))
in a fixed peripheral configuration (dr_mode == USB_DR_MODE_PERIPHERAL),
both dwc3_rockchip_phy_pre_reset() and dwc3_rockchip_phy_post_reset()
return early without calling dwc3_rockchip_vbus_handler().
> +
> /*
> * Assert USB3 PHY soft reset within DWC3 before the external
> * PHY resets. This disconnects the PIPE interface, preventing
> @@ -43,6 +56,9 @@ static void dwc3_rockchip_phy_pre_reset(struct dwc3_rockchip *dwc_rk, int port)
> static void dwc3_rockchip_phy_post_reset(struct dwc3_rockchip *dwc_rk, int port)
> {
> struct dwc3 *dwc = &dwc_rk->dwc;
> + bool gadget_mode = (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE) ||
> + ((dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG) &&
> + (dwc_rk->role == USB_ROLE_DEVICE));
> u32 reg;
>
> scoped_guard(spinlock_irqsave, &dwc->lock) {
> @@ -56,6 +72,8 @@ static void dwc3_rockchip_phy_post_reset(struct dwc3_rockchip *dwc_rk, int port)
> reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST;
> dwc3_writel(dwc, DWC3_GUSB3PIPECTL(port), reg);
> }
> +
> + dwc3_rockchip_vbus_handler(dwc, gadget_mode);
> }
[Severity: High]
Does gadget_mode in dwc3_rockchip_phy_post_reset() check the right field on
dual-role controllers using usb-role-switch?
Here dwc->current_dr_role is compared against DWC3_GCTL_PRTCAP_DEVICE and
DWC3_GCTL_PRTCAP_OTG. However, in drivers/usb/dwc3/drd.c,
dwc3_usb_role_switch_set() never sets mode to DWC3_GCTL_PRTCAP_OTG:
switch (role) {
case USB_ROLE_HOST:
mode = DWC3_GCTL_PRTCAP_HOST;
break;
case USB_ROLE_DEVICE:
mode = DWC3_GCTL_PRTCAP_DEVICE;
break;
default:
if (dwc->role_switch_default_mode == USB_DR_MODE_HOST)
mode = DWC3_GCTL_PRTCAP_HOST;
else
mode = DWC3_GCTL_PRTCAP_DEVICE;
break;
}
dwc3_pre_set_role(dwc, role);
dwc3_set_mode(dwc, mode);
When the cable is unplugged or in displayport-only altmode (role is
USB_ROLE_NONE), dwc3_usb_role_switch_set() selects DWC3_GCTL_PRTCAP_DEVICE
because dwc->role_switch_default_mode defaults to USB_DR_MODE_PERIPHERAL.
As a result, dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE evaluates to true
even when dwc_rk->role is USB_ROLE_NONE. When a phy reset completes in
dwc3_rockchip_phy_post_reset() (for example during rk_udphy_dp_phy_power_on()
or system resume), dwc3_rockchip_vbus_handler(dwc, true) is called while no
usb device cable is connected, setting gadget->connected = 1 so that a later
USB_ROLE_DEVICE plug-in becomes a no-op in usb_gadget_connect_locked().
In addition, dwc3_pre_set_role() updates dwc_rk->role synchronously in
dwc3_rockchip_set_role(), whereas dwc3_set_mode() queues dwc->drd_work
(__dwc3_set_mode) asynchronously. During a USB_ROLE_DEVICE to USB_ROLE_HOST
transition, dwc->current_dr_role is still DWC3_GCTL_PRTCAP_DEVICE (making
gadget_mode true while dwc_rk->role is USB_ROLE_HOST), and during a
USB_ROLE_HOST to USB_ROLE_DEVICE transition, dwc->current_dr_role is still
DWC3_GCTL_PRTCAP_HOST until __dwc3_set_mode() finishes (making gadget_mode
false while dwc_rk->role is USB_ROLE_DEVICE).
Also, dwc->current_dr_role and dwc_rk->role are read at the top of
dwc3_rockchip_phy_post_reset() outside dwc->lock, and dwc_rk->role is written
in dwc3_rockchip_set_role() without holding dwc->lock:
static void dwc3_rockchip_set_role(struct dwc3 *dwc, enum usb_role role)
{
struct dwc3_rockchip *dwc_rk = container_of(dwc, struct dwc3_rockchip, dwc);
dwc_rk->role = role;
dwc3_rockchip_vbus_handler(dwc, role == USB_ROLE_DEVICE);
}
Could a concurrent dwc3_rockchip_set_role(dwc, USB_ROLE_NONE) run between the
initial gadget_mode evaluation and the dwc3_rockchip_vbus_handler() call at
the end of dwc3_rockchip_phy_post_reset(), causing the stale gadget_mode value
to overwrite the vbus state? Should this check dwc->dr_mode ==
USB_DR_MODE_PERIPHERAL (and dwc_rk->role == USB_ROLE_DEVICE for otg) under
dwc->lock instead?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261021-b4-rockchip-dwc3-rockchip-glue-v18-0-60000d03fca2@collabora.com?part=7
next prev parent reply other threads:[~2026-10-21 18:31 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 18:05 [PATCH v18 0/7] usb: dwc3: introduce Rockchip glue driver Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:05 ` [PATCH v18 1/7] phy: rockchip: usbdp: Track PHY power state Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:10 ` sashiko-bot
2026-10-21 18:05 ` [PATCH v18 2/7] phy: rockchip: usbdp: Add reset hook support for dwc3 Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:20 ` sashiko-bot
2026-10-21 18:05 ` [PATCH v18 3/7] usb: dwc3: rockchip: introduce glue driver Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:12 ` sashiko-bot
2026-10-21 18:05 ` [PATCH v18 4/7] usb: dwc3: core: add post PHY registration hook for platform glue Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:10 ` sashiko-bot
2026-10-21 18:05 ` [PATCH v18 5/7] usb: dwc3: rockchip: add USBDP PHY reset quirk Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:35 ` sashiko-bot
2026-10-21 18:35 ` sashiko-bot
2026-10-21 18:05 ` [PATCH v18 6/7] usb: gadget: define stub for usb_udc_vbus_handler Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:13 ` sashiko-bot
2026-10-21 18:05 ` [PATCH v18 7/7] usb: dwc3: rockchip: fix USB-C reconnect in gadget mode Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:05 ` Sebastian Reichel
2026-10-21 18:31 ` sashiko-bot [this message]
2026-10-21 18:31 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-180556@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=linux-usb@vger.kernel.org \
--cc=neil.armstrong@linaro.org \
--cc=olteanv@gmail.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=sebastian.reichel@collabora.com \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.