linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] xhci fixes for usb-linus
@ 2020-04-21 14:08 Mathias Nyman
  2020-04-21 14:08 ` [PATCH 1/3] xhci: Fix handling halted endpoint even if endpoint ring appears empty Mathias Nyman
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Mathias Nyman @ 2020-04-21 14:08 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb, Mathias Nyman

Hi Greg

These xhci fixes for usb-linus sort out halted empty endpoint handling,
protocol stall handling, and overcurrent handling.

Theses issues have caused usb devices to appear as if they stop working
suddenly, failed to enumerate LS/FS devices behind HS hubs (seen on some
audio devices), and host from freezing in case of suspend on over-current.

-Mathias 

Mathias Nyman (3):
  xhci: Fix handling halted endpoint even if endpoint ring appears empty
  xhci: prevent bus suspend if a roothub port detected a over-current
    condition
  xhci: Don't clear hub TT buffer on ep0 protocol stall

 drivers/usb/host/xhci-hub.c  |  9 +++++++
 drivers/usb/host/xhci-ring.c | 46 +++++++++++++++++++++++++++++++-----
 drivers/usb/host/xhci.c      | 14 +++++------
 drivers/usb/host/xhci.h      |  5 ++--
 4 files changed, 59 insertions(+), 15 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] xhci: Fix handling halted endpoint even if endpoint ring appears empty
  2020-04-21 14:08 [PATCH 0/3] xhci fixes for usb-linus Mathias Nyman
@ 2020-04-21 14:08 ` Mathias Nyman
  2020-04-22 13:27   ` Sasha Levin
  2020-04-21 14:08 ` [PATCH 2/3] xhci: prevent bus suspend if a roothub port detected a over-current condition Mathias Nyman
  2020-04-21 14:08 ` [PATCH 3/3] xhci: Don't clear hub TT buffer on ep0 protocol stall Mathias Nyman
  2 siblings, 1 reply; 5+ messages in thread
From: Mathias Nyman @ 2020-04-21 14:08 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb, Mathias Nyman, stable, Jeremy Compostella

If a class driver cancels its only URB then the endpoint ring buffer will
appear empty to the xhci driver. xHC hardware may still process cached
TRBs, and complete with a STALL, halting the endpoint.

This halted endpoint was not handled correctly by xhci driver as events on
empty rings were all assumed to be spurious events.
xhci driver refused to restart the ring with EP_HALTED flag set, so class
driver was never informed the endpoint halted even if it queued new URBs.

The host side of the endpoint needs to be reset, and dequeue pointer should
be moved in order to clear the cached TRBs and resetart the endpoint.

Small adjustments in finding the new dequeue pointer are needed to support
the case of stall on an empty ring and unknown current TD.

Cc: <stable@vger.kernel.org>
cc: Jeremy Compostella <jeremy.compostella@intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-ring.c | 30 +++++++++++++++++++++++++++++-
 drivers/usb/host/xhci.c      | 14 +++++++-------
 drivers/usb/host/xhci.h      |  5 +++--
 3 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index a78787bb5133..a7f4cd35da55 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -547,6 +547,23 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 				stream_id);
 		return;
 	}
+	/*
+	 * A cancelled TD can complete with a stall if HW cached the trb.
+	 * In this case driver can't find cur_td, but if the ring is empty we
+	 * can move the dequeue pointer to the current enqueue position.
+	 */
+	if (!cur_td) {
+		if (list_empty(&ep_ring->td_list)) {
+			state->new_deq_seg = ep_ring->enq_seg;
+			state->new_deq_ptr = ep_ring->enqueue;
+			state->new_cycle_state = ep_ring->cycle_state;
+			goto done;
+		} else {
+			xhci_warn(xhci, "Can't find new dequeue state, missing cur_td\n");
+			return;
+		}
+	}
+
 	/* Dig out the cycle state saved by the xHC during the stop ep cmd */
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 			"Finding endpoint context");
@@ -592,6 +609,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 	state->new_deq_seg = new_seg;
 	state->new_deq_ptr = new_deq;
 
+done:
 	/* Don't update the ring cycle state for the producer (us). */
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 			"Cycle state = 0x%x", state->new_cycle_state);
@@ -1856,7 +1874,8 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
 
 	if (reset_type == EP_HARD_RESET) {
 		ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
-		xhci_cleanup_stalled_ring(xhci, ep_index, stream_id, td);
+		xhci_cleanup_stalled_ring(xhci, slot_id, ep_index, stream_id,
+					  td);
 		xhci_clear_hub_tt_buffer(xhci, td, ep);
 	}
 	xhci_ring_cmd_db(xhci);
@@ -2539,6 +2558,15 @@ static int handle_tx_event(struct xhci_hcd *xhci,
 				xhci_dbg(xhci, "td_list is empty while skip flag set. Clear skip flag for slot %u ep %u.\n",
 					 slot_id, ep_index);
 			}
+			if (trb_comp_code == COMP_STALL_ERROR ||
+			    xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
+							      trb_comp_code)) {
+				xhci_cleanup_halted_endpoint(xhci, slot_id,
+							     ep_index,
+							     ep_ring->stream_id,
+							     NULL,
+							     EP_HARD_RESET);
+			}
 			goto cleanup;
 		}
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index fe38275363e0..bee5deccc83d 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3031,19 +3031,19 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
 			added_ctxs, added_ctxs);
 }
 
-void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
-			       unsigned int stream_id, struct xhci_td *td)
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int slot_id,
+			       unsigned int ep_index, unsigned int stream_id,
+			       struct xhci_td *td)
 {
 	struct xhci_dequeue_state deq_state;
-	struct usb_device *udev = td->urb->dev;
 
 	xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
 			"Cleaning up stalled endpoint ring");
 	/* We need to move the HW's dequeue pointer past this TD,
 	 * or it will attempt to resend it on the next doorbell ring.
 	 */
-	xhci_find_new_dequeue_state(xhci, udev->slot_id,
-			ep_index, stream_id, td, &deq_state);
+	xhci_find_new_dequeue_state(xhci, slot_id, ep_index, stream_id, td,
+				    &deq_state);
 
 	if (!deq_state.new_deq_ptr || !deq_state.new_deq_seg)
 		return;
@@ -3054,7 +3054,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
 	if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
 		xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
 				"Queueing new dequeue state");
-		xhci_queue_new_dequeue_state(xhci, udev->slot_id,
+		xhci_queue_new_dequeue_state(xhci, slot_id,
 				ep_index, &deq_state);
 	} else {
 		/* Better hope no one uses the input context between now and the
@@ -3065,7 +3065,7 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
 		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
 				"Setting up input context for "
 				"configure endpoint command");
-		xhci_setup_input_ctx_for_quirk(xhci, udev->slot_id,
+		xhci_setup_input_ctx_for_quirk(xhci, slot_id,
 				ep_index, &deq_state);
 	}
 }
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 3289bb516201..86cfefdd6632 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -2116,8 +2116,9 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
 		unsigned int slot_id, unsigned int ep_index,
 		struct xhci_dequeue_state *deq_state);
-void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
-		unsigned int stream_id, struct xhci_td *td);
+void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int slot_id,
+			       unsigned int ep_index, unsigned int stream_id,
+			       struct xhci_td *td);
 void xhci_stop_endpoint_command_watchdog(struct timer_list *t);
 void xhci_handle_command_timeout(struct work_struct *work);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] xhci: prevent bus suspend if a roothub port detected a over-current condition
  2020-04-21 14:08 [PATCH 0/3] xhci fixes for usb-linus Mathias Nyman
  2020-04-21 14:08 ` [PATCH 1/3] xhci: Fix handling halted endpoint even if endpoint ring appears empty Mathias Nyman
@ 2020-04-21 14:08 ` Mathias Nyman
  2020-04-21 14:08 ` [PATCH 3/3] xhci: Don't clear hub TT buffer on ep0 protocol stall Mathias Nyman
  2 siblings, 0 replies; 5+ messages in thread
From: Mathias Nyman @ 2020-04-21 14:08 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb, Mathias Nyman, stable

Suspending the bus and host controller while a port is in a over-current
condition may halt the host.
Also keep the roothub running if over-current is active.

Cc: <stable@vger.kernel.org>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-hub.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 9eca1fe81061..f37316d2c8fa 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1571,6 +1571,8 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 		}
 		if ((temp & PORT_RC))
 			reset_change = true;
+		if (temp & PORT_OC)
+			status = 1;
 	}
 	if (!status && !reset_change) {
 		xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
@@ -1636,6 +1638,13 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 				 port_index);
 			goto retry;
 		}
+		/* bail out if port detected a over-current condition */
+		if (t1 & PORT_OC) {
+			bus_state->bus_suspended = 0;
+			spin_unlock_irqrestore(&xhci->lock, flags);
+			xhci_dbg(xhci, "Bus suspend bailout, port over-current detected\n");
+			return -EBUSY;
+		}
 		/* suspend ports in U0, or bail out for new connect changes */
 		if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {
 			if ((t1 & PORT_CSC) && wake_enabled) {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] xhci: Don't clear hub TT buffer on ep0 protocol stall
  2020-04-21 14:08 [PATCH 0/3] xhci fixes for usb-linus Mathias Nyman
  2020-04-21 14:08 ` [PATCH 1/3] xhci: Fix handling halted endpoint even if endpoint ring appears empty Mathias Nyman
  2020-04-21 14:08 ` [PATCH 2/3] xhci: prevent bus suspend if a roothub port detected a over-current condition Mathias Nyman
@ 2020-04-21 14:08 ` Mathias Nyman
  2 siblings, 0 replies; 5+ messages in thread
From: Mathias Nyman @ 2020-04-21 14:08 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb, Mathias Nyman, stable

The default control endpoint ep0 can return a STALL indicating the
device does not support the control transfer requests. This is called
a protocol stall and does not halt the endpoint.

xHC behaves a bit different. Its internal endpoint state will always
be halted on any stall, even if the device side of the endpiont is not
halted. So we do need to issue the reset endpoint command to clear the
xHC host intenal endpoint halt state, but should not request the HS hub
to clear the TT buffer unless device side of endpoint is halted.

Clearing the hub TT buffer at protocol stall caused ep0 to become
unresponsive for some FS/LS devices behind HS hubs, and class drivers
failed to set the interface due to timeout:

usb 1-2.1: 1:1: usb_set_interface failed (-110)

Fixes: ef513be0a905 ("usb: xhci: Add Clear_TT_Buffer")
Cc: <stable@vger.kernel.org> # v5.3
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
 drivers/usb/host/xhci-ring.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index a7f4cd35da55..0fda0c0f4d31 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1876,7 +1876,6 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
 		ep->ep_state |= EP_HARD_CLEAR_TOGGLE;
 		xhci_cleanup_stalled_ring(xhci, slot_id, ep_index, stream_id,
 					  td);
-		xhci_clear_hub_tt_buffer(xhci, td, ep);
 	}
 	xhci_ring_cmd_db(xhci);
 }
@@ -1997,11 +1996,18 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
 	if (trb_comp_code == COMP_STALL_ERROR ||
 		xhci_requires_manual_halt_cleanup(xhci, ep_ctx,
 						trb_comp_code)) {
-		/* Issue a reset endpoint command to clear the host side
-		 * halt, followed by a set dequeue command to move the
-		 * dequeue pointer past the TD.
-		 * The class driver clears the device side halt later.
+		/*
+		 * xhci internal endpoint state will go to a "halt" state for
+		 * any stall, including default control pipe protocol stall.
+		 * To clear the host side halt we need to issue a reset endpoint
+		 * command, followed by a set dequeue command to move past the
+		 * TD.
+		 * Class drivers clear the device side halt from a functional
+		 * stall later. Hub TT buffer should only be cleared for FS/LS
+		 * devices behind HS hubs for functional stalls.
 		 */
+		if ((ep_index != 0) || (trb_comp_code != COMP_STALL_ERROR))
+			xhci_clear_hub_tt_buffer(xhci, td, ep);
 		xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
 					ep_ring->stream_id, td, EP_HARD_RESET);
 	} else {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/3] xhci: Fix handling halted endpoint even if endpoint ring appears empty
  2020-04-21 14:08 ` [PATCH 1/3] xhci: Fix handling halted endpoint even if endpoint ring appears empty Mathias Nyman
@ 2020-04-22 13:27   ` Sasha Levin
  0 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2020-04-22 13:27 UTC (permalink / raw)
  To: Sasha Levin, Mathias Nyman, gregkh
  Cc: linux-usb, stable, Jeremy Compostella, stable

Hi

[This is an automated email]

This commit has been processed because it contains a -stable tag.
The stable tag indicates that it's relevant for the following trees: all

The bot has tested the following trees: v5.6.5, v5.4.33, v4.19.116, v4.14.176, v4.9.219, v4.4.219.

v5.6.5: Build OK!
v5.4.33: Build OK!
v4.19.116: Failed to apply! Possible dependencies:
    ef513be0a905 ("usb: xhci: Add Clear_TT_Buffer")

v4.14.176: Failed to apply! Possible dependencies:
    15febf5eede9 ("xhci: refactor xhci_urb_enqueue a bit with minor changes")
    66a4550308b8 ("xhci: Convert timers to use timer_setup()")
    ef513be0a905 ("usb: xhci: Add Clear_TT_Buffer")
    f5249461b504 ("xhci: Clear the host side toggle manually when endpoint is soft reset")

v4.9.219: Failed to apply! Possible dependencies:
    0b6c324c8b60 ("xhci: cleanup and refactor process_ctrl_td()")
    0ce5749959c6 ("xhci: add trb_is_noop() helper function")
    217491487c43 ("xhci: Add support for endpoint soft reset")
    30a65b45bfb1 ("xhci: cleanup and refactor process_bulk_intr_td()")
    3495e451d137 ("xhci: use trb helper functions when possible")
    52ab86852f74 ("xhci: remove extra URB_SHORT_NOT_OK checks in xhci, core handles most cases")
    5eee4b6b4f57 ("xhci: support calling cleanup_halted_endpoint with soft retry")
    a37c3f76e6a6 ("usb: host: xhci: make a generic TRB tracer")
    d36374fdfb25 ("xhci: cleanup virtual endoint structure, remove stopped_stream")
    f5249461b504 ("xhci: Clear the host side toggle manually when endpoint is soft reset")
    f97c08ae329b ("xhci: rename endpoint related trb variables")

v4.4.219: Failed to apply! Possible dependencies:
    0b6c324c8b60 ("xhci: cleanup and refactor process_ctrl_td()")
    0ce5749959c6 ("xhci: add trb_is_noop() helper function")
    2251198bef42 ("xhci: clean up event ring checks from inc_enq()")
    2d98ef406f17 ("xhci: use and add separate function for checking for link trbs")
    30a65b45bfb1 ("xhci: cleanup and refactor process_bulk_intr_td()")
    3495e451d137 ("xhci: use trb helper functions when possible")
    474ed23a6257 ("xhci: align the last trb before link if it is easily splittable.")
    52ab86852f74 ("xhci: remove extra URB_SHORT_NOT_OK checks in xhci, core handles most cases")
    5eee4b6b4f57 ("xhci: support calling cleanup_halted_endpoint with soft retry")
    d2510342fe93 ("usb: xhci: merge xhci_queue_bulk_tx and queue_bulk_sg_tx functions")
    d36374fdfb25 ("xhci: cleanup virtual endoint structure, remove stopped_stream")
    f5249461b504 ("xhci: Clear the host side toggle manually when endpoint is soft reset")
    f97c08ae329b ("xhci: rename endpoint related trb variables")


NOTE: The patch will not be queued to stable trees until it is upstream.

How should we proceed with this patch?

-- 
Thanks
Sasha

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-04-22 13:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-04-21 14:08 [PATCH 0/3] xhci fixes for usb-linus Mathias Nyman
2020-04-21 14:08 ` [PATCH 1/3] xhci: Fix handling halted endpoint even if endpoint ring appears empty Mathias Nyman
2020-04-22 13:27   ` Sasha Levin
2020-04-21 14:08 ` [PATCH 2/3] xhci: prevent bus suspend if a roothub port detected a over-current condition Mathias Nyman
2020-04-21 14:08 ` [PATCH 3/3] xhci: Don't clear hub TT buffer on ep0 protocol stall Mathias Nyman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).