[PATCH 2/2] usb: dwc2: fix data toggle reset direction on ClearFeature(ENDPOINT_HALT)

Sascha Hauer
2026-04-20T11:21:29Z

From: Sascha Hauer <sascha@saschahauer.de>

dwc2_submit_control_msg() resets the data toggle after a successful
ClearFeature(ENDPOINT_HALT) request. It passes usb_pipein(pipe) as the
direction to dwc2_endpoint_reset(), but pipe is always the control-out
pipe used to send the request, so usb_pipein() always returns 0 (OUT).

As a result, clearing an IN endpoint halt resets the OUT toggle instead
of the IN toggle, leaving the IN data toggle in an incorrect state for
subsequent transfers.

Fix by extracting the direction from the endpoint address in setup->index
(wIndex), where bit 7 is the direction flag per USB 2.0 section 9.3.4.

Fixes: 446bcf875395 ("usb: dwc2: host: Fix toggle reset")
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Sascha Hauer <sascha@saschahauer.de>
---
drivers/usb/dwc2/host.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/host.c b/drivers/usb/dwc2/host.c
index ddad51c882..2be2666574 100644
--- a/drivers/usb/dwc2/host.c
+++ b/drivers/usb/dwc2/host.c
@@ -401,8 +401,8 @@ static int dwc2_submit_control_msg(struct usb_device *udev,
* ClearFeature(ENDPOINT_HALT) request always results
* in the data toggle being reinitialized to DATA0.
*/
- int ep = le16_to_cpu(setup->index) & 0xf;
- dwc2_endpoint_reset(dwc2, usb_pipein(pipe), devnum, ep);
+ int ep_addr = le16_to_cpu(setup->index);
+ dwc2_endpoint_reset(dwc2, ep_addr >> 7, devnum, ep_addr & 0xf);
}

udev->act_len = act_len;

--
2.47.3