From: sashiko-bot@kernel.org
To: "Pengfei Lv" <lvpengfei20@huawei.com>
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH] usb: core: hub: Re-guess ep0 maxpacket size on reset
Date: Wed, 04 Nov 2026 12:57:11 +0000 [thread overview]
Message-ID: <sashiko-outbox-197312@kernel.org> (raw)
In-Reply-To: <20261104124402.1269650-1-lvpengfei20@huawei.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] usb: core: hub: missing usb_ep0_reinit() in hub_port_init() after ep0 guess
--
commit 8488ba17cb81d9272c99646f158ad82af5c82843
Author: Pengfei Lv <lvpengfei20@huawei.com>
usb: core: hub: Re-guess ep0 maxpacket size on reset
This commit removes the if (initial) guard around the ep0 maxpacket size
initialization in hub_port_init() so that udev->ep0.desc.wMaxPacketSize is
re-guessed from udev->speed during port resets as well as initial
enumeration.
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 199d3f535a891..51f66b24b3538 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -4969,31 +4969,29 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
> }
> oldspeed = udev->speed;
>
> - if (initial) {
> - /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
> - * it's fixed size except for full speed devices.
> + /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
> + * it's fixed size except for full speed devices.
> + */
> + switch (udev->speed) {
> + case USB_SPEED_SUPER_PLUS:
> + case USB_SPEED_SUPER:
> + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
> + break;
> + case USB_SPEED_HIGH: /* fixed at 64 */
> + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
> + break;
> + case USB_SPEED_FULL: /* 8, 16, 32, or 64 */
> + /* to determine the ep0 maxpacket size, try to read
> + * the device descriptor to get bMaxPacketSize0 and
> + * then correct our initial guess.
> */
> - switch (udev->speed) {
> - case USB_SPEED_SUPER_PLUS:
> - case USB_SPEED_SUPER:
> - udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
> - break;
> - case USB_SPEED_HIGH: /* fixed at 64 */
> - udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
> - break;
> - case USB_SPEED_FULL: /* 8, 16, 32, or 64 */
> - /* to determine the ep0 maxpacket size, try to read
> - * the device descriptor to get bMaxPacketSize0 and
> - * then correct our initial guess.
> - */
> - udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
> - break;
> - case USB_SPEED_LOW: /* fixed at 8 */
> - udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
> - break;
> - default:
> - goto fail;
> - }
> + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
> + break;
[Severity: High]
Does hub_port_init() also need to call usb_ep0_reinit(udev) after resetting
udev->ep0.desc.wMaxPacketSize to 64 when !initial?
The commit message notes that re-establishing the 64-byte guess makes
xhci_check_maxpacket() issue an Evaluate Context command before the
GET_DESCRIPTOR data stage. However, commit e34900f46cd6 ("xhci: Reconfigure
endpoint 0 max packet size only during endpoint reset") removed that check
from xhci_urb_enqueue() and replaced it with xhci_check_ep0_maxpacket(),
which is only invoked from xhci_endpoint_reset() via usb_ep0_reinit():
drivers/usb/host/xhci.c:xhci_endpoint_reset() {
if (usb_endpoint_xfer_control(&host_ep->desc) && ep_index == 0) {
...
xhci_check_ep0_maxpacket(xhci, vdev);
/* Nothing else should be done here for ep0 during ep reset */
return;
}
}
During a port reset in usb_reset_and_verify_device(), usb_ep0_reinit(udev)
is called before hub_port_init():
drivers/usb/core/hub.c:usb_reset_and_verify_device() {
for (i = 0; i < SET_CONFIG_TRIES; ++i) {
/* ep0 maxpacket size may change; let the HCD know about it.
* Other endpoints will be handled by re-enumeration. */
usb_ep0_reinit(udev);
ret = hub_port_init(parent_hub, udev, port1, i, &descriptor);
}
On the first attempt (i == 0), udev->ep0.desc.wMaxPacketSize still holds the
pre-reset value (e.g. 8) when usb_ep0_reinit(udev) runs, matching the xHC
output EP0 context, so xhci_check_ep0_maxpacket() does nothing.
Then hub_port_init() resets the port (leaving the slot in SLOT_STATE_DEFAULT
with max_packet = 8) and sets udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64)
in software without calling usb_ep0_reinit(udev). When do_new_scheme is true,
hub_enable_device() -> xhci_enable_device() -> xhci_setup_device() sees the
slot is already in SLOT_STATE_DEFAULT and returns early without updating the
EP0 context:
drivers/usb/host/xhci.c:xhci_setup_device() {
if (setup == SETUP_CONTEXT_ONLY) {
if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) ==
SLOT_STATE_DEFAULT) {
xhci_dbg(xhci, "Slot already in default state\n");
goto out;
}
}
}
As a result, when get_bMaxPacketSize0() submits the 64-byte GET_DESCRIPTOR
URB on i == 0, the xHC hardware EP0 context still has max_packet = 8, so the
first hub_port_init() call still times out across all GET_DESCRIPTOR_TRIES *
GET_MAXPACKET0_TRIES attempts before usb_reset_and_verify_device() retries
with i == 1.
In addition, for standard full-speed devices with bMaxPacketSize0 = 8 whose
18-byte descriptor read succeeds on i == 0 in do_new_scheme,
hub_set_address() calls usb_ep0_reinit(udev) while
udev->ep0.desc.wMaxPacketSize is still 64, issuing an Evaluate Context
command to change max_packet from 8 to 64 right before hub_port_init() sets
wMaxPacketSize back to 8 and calls usb_ep0_reinit(udev) a second time.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261104124402.1269650-1-lvpengfei20@huawei.com?part=1
next prev parent reply other threads:[~2026-11-04 12:57 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 12:44 [PATCH] usb: core: hub: Re-guess ep0 maxpacket size on reset Pengfei Lv
2026-11-04 12:57 ` sashiko-bot [this message]
2026-11-04 14:59 ` Alan Stern
2026-11-04 17:36 ` Michal Pecio
2026-11-05 5:06 ` Alan Stern
2026-11-05 12:30 ` Michal Pecio
2026-11-05 8:41 ` Pengfei Lv
2026-11-05 15:46 ` Alan Stern
2026-11-06 3:16 ` [PATCH v2] " Pengfei Lv
2026-11-06 3:34 ` sashiko-bot
2026-11-06 22:01 ` Michal Pecio
2026-11-06 7:17 ` Michal Pecio
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-197312@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=lvpengfei20@huawei.com \
--cc=sashiko-reviews@lists.linux.dev \
/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.