Skip to content

Commit 860f5d0

Browse files
matnymangregkh
authored andcommitted
xhci: Prevent early endpoint restart when handling STALL errors.
Ensure that an endpoint halted due to device STALL is not restarted before a Clear_Feature(ENDPOINT_HALT) request is sent to the device. The host side of the endpoint may otherwise be started early by the 'Set TR Deq' command completion handler which is called if dequeue is moved past a cancelled or halted TD. Prevent this with a new flag set for bulk and interrupt endpoints when a Stall Error is received. Clear it in hcd->endpoint_reset() which is called after Clear_Feature(ENDPOINT_HALT) is sent. Also add a debug message if a class driver queues a new URB after the STALL. Note that class driver might not be aware of the STALL yet when it submits the URB as URBs are given back in BH. Signed-off-by: Mathias Nyman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 9a7f4bc commit 860f5d0

File tree

3 files changed

+13
-3
lines changed

3 files changed

+13
-3
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,8 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
556556
* pointer command pending because the device can choose to start any
557557
* stream once the endpoint is on the HW schedule.
558558
*/
559-
if ((ep_state & EP_STOP_CMD_PENDING) || (ep_state & SET_DEQ_PENDING) ||
560-
(ep_state & EP_HALTED) || (ep_state & EP_CLEARING_TT))
559+
if (ep_state & (EP_STOP_CMD_PENDING | SET_DEQ_PENDING | EP_HALTED |
560+
EP_CLEARING_TT | EP_STALLED))
561561
return;
562562

563563
trace_xhci_ring_ep_doorbell(slot_id, DB_VALUE(ep_index, stream_id));
@@ -2555,6 +2555,9 @@ static void process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
25552555

25562556
xhci_handle_halted_endpoint(xhci, ep, td, EP_SOFT_RESET);
25572557
return;
2558+
case COMP_STALL_ERROR:
2559+
ep->ep_state |= EP_STALLED;
2560+
break;
25582561
default:
25592562
/* do nothing */
25602563
break;

drivers/usb/host/xhci.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,11 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
16041604
goto free_priv;
16051605
}
16061606

1607+
/* Class driver might not be aware ep halted due to async URB giveback */
1608+
if (*ep_state & EP_STALLED)
1609+
dev_dbg(&urb->dev->dev, "URB %p queued before clearing halt\n",
1610+
urb);
1611+
16071612
switch (usb_endpoint_type(&urb->ep->desc)) {
16081613

16091614
case USB_ENDPOINT_XFER_CONTROL:
@@ -3202,6 +3207,7 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
32023207
return;
32033208

32043209
ep = &vdev->eps[ep_index];
3210+
ep->ep_state &= ~EP_STALLED;
32053211

32063212
/* Bail out if toggle is already being cleared by a endpoint reset */
32073213
spin_lock_irqsave(&xhci->lock, flags);

drivers/usb/host/xhci.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ struct xhci_virt_ep {
664664
unsigned int err_count;
665665
unsigned int ep_state;
666666
#define SET_DEQ_PENDING (1 << 0)
667-
#define EP_HALTED (1 << 1) /* For stall handling */
667+
#define EP_HALTED (1 << 1) /* Halted host ep handling */
668668
#define EP_STOP_CMD_PENDING (1 << 2) /* For URB cancellation */
669669
/* Transitioning the endpoint to using streams, don't enqueue URBs */
670670
#define EP_GETTING_STREAMS (1 << 3)
@@ -675,6 +675,7 @@ struct xhci_virt_ep {
675675
#define EP_SOFT_CLEAR_TOGGLE (1 << 7)
676676
/* usb_hub_clear_tt_buffer is in progress */
677677
#define EP_CLEARING_TT (1 << 8)
678+
#define EP_STALLED (1 << 9) /* For stall handling */
678679
/* ---- Related to URB cancellation ---- */
679680
struct list_head cancelled_td_list;
680681
struct xhci_hcd *xhci;

0 commit comments

Comments
 (0)