summaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2023-12-15 14:57:07 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-12-15 18:29:02 +0100
commit80602b6b5a23b210224a5b44d9e5b5c1dc193632 (patch)
treefb11f5a286564d5589091680efbf7baac0f13424 /drivers/usb/host/xhci.c
parentc084af69a8f425b8cb56479ff0ea11e48aba0c62 (diff)
xhci: Fix null pointer dereference during S4 resume when resetting ep0
During device enumeration usb core resets endpoint 0 if the max packet size value differs from the one read from the device descriptor. usb core will additionally reset endpoint 0 during S4 resume, before re-enumerating the device, if the device has a reset-resume flag set. In this case the xhci device representation vdev may be lost due to xHC restore error and re-initialization during S4 resume. Make sure slot_id and vdev are valid before trying to re-configure max packet size during endpoint 0 reset. max packet size will be re-configured later during re-enumeration. This fixes commit e34900f46cd6 ("xhci: Reconfigure endpoint 0 max packet size only during endpoint reset") which is currently in usb-next, on its way to 6.8 Fixes: e34900f46cd6 ("xhci: Reconfigure endpoint 0 max packet size only during endpoint reset") Tested-by: Wendy Wang <wendy.wang@intel.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Link: https://lore.kernel.org/r/20231215125707.1732989-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 08fbabff23a0..7d5b94905b9c 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3077,6 +3077,9 @@ done:
* of an endpoint that isn't in the halted state this function will issue a
* configure endpoint command with the Drop and Add bits set for the target
* endpoint. Refer to the additional note in xhci spcification section 4.6.8.
+ *
+ * vdev may be lost due to xHC restore error and re-initialization during S3/S4
+ * resume. A new vdev will be allocated later by xhci_discover_or_reset_device()
*/
static void xhci_endpoint_reset(struct usb_hcd *hcd,
@@ -3102,9 +3105,17 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
* mismatch. Reconfigure the xhci ep0 endpoint context here in that case
*/
if (usb_endpoint_xfer_control(&host_ep->desc) && ep_index == 0) {
+
udev = container_of(host_ep, struct usb_device, ep0);
- if (udev->speed == USB_SPEED_FULL)
- xhci_check_ep0_maxpacket(xhci, xhci->devs[udev->slot_id]);
+ if (udev->speed != USB_SPEED_FULL || !udev->slot_id)
+ return;
+
+ vdev = xhci->devs[udev->slot_id];
+ if (!vdev || vdev->udev != udev)
+ return;
+
+ xhci_check_ep0_maxpacket(xhci, vdev);
+
/* Nothing else should be done here for ep0 during ep reset */
return;
}
@@ -3114,11 +3125,6 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
udev = (struct usb_device *) host_ep->hcpriv;
vdev = xhci->devs[udev->slot_id];
- /*
- * vdev may be lost due to xHC restore error and re-initialization
- * during S3/S4 resume. A new vdev will be allocated later by
- * xhci_discover_or_reset_device()
- */
if (!udev->slot_id || !vdev)
return;