[PATCH 2/5] xhci: isoc transfers can't fail when partially queued - remove cleanup code.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The 'cleanup' code at the bottom of xhci_queue_isoc_tx() can never be executed.

For 'i != 0' on an ISOC ring prepare_transfer can only fail if the endpoint
ring cannot be determined, but it was found only moments earlier (it could
be passed as a parameter).

The 'running_total' check is just checking that the code is correct
and can just be deleted now the code is working.

Remove the 'flip_cycle' parameter to td_to_noop() since it is no longer
ever set.

Signed-off-by: David Laight <david.laight@xxxxxxxxxx>
---
 drivers/usb/host/xhci-ring.c | 56 ++++----------------------------------------
 1 file changed, 5 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 62049e5..ae5d32c 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -617,12 +617,8 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 			(unsigned long long) addr);
 }
 
-/* flip_cycle means flip the cycle bit of all but the first and last TRB.
- * (The last TRB actually points to the ring enqueue pointer, which is not part
- * of this TD.)  This is used to remove partially enqueued isoc TDs from a ring.
- */
 static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
-		struct xhci_td *cur_td, bool flip_cycle)
+		struct xhci_td *cur_td)
 {
 	struct xhci_segment *cur_seg;
 	union xhci_trb *cur_trb;
@@ -635,12 +631,6 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 			 * leave the pointers intact.
 			 */
 			cur_trb->generic.field[3] &= cpu_to_le32(~TRB_CHAIN);
-			/* Flip the cycle bit (link TRBs can't be the first
-			 * or last TRB).
-			 */
-			if (flip_cycle)
-				cur_trb->generic.field[3] ^=
-					cpu_to_le32(TRB_CYCLE);
 			xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 					"Cancel (unchain) link TRB");
 			xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
@@ -656,11 +646,6 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 			cur_trb->generic.field[2] = 0;
 			/* Preserve only the cycle bit of this TRB */
 			cur_trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE);
-			/* Flip the cycle bit except on the first or last TRB */
-			if (flip_cycle && cur_trb != cur_td->first_trb &&
-					cur_trb != cur_td->last_trb)
-				cur_trb->generic.field[3] ^=
-					cpu_to_le32(TRB_CYCLE);
 			cur_trb->generic.field[3] |= cpu_to_le32(
 				TRB_TYPE(TRB_TR_NOOP));
 			xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
@@ -834,7 +819,7 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
 					cur_td->urb->stream_id,
 					cur_td, &deq_state);
 		else
-			td_to_noop(xhci, ep_ring, cur_td, false);
+			td_to_noop(xhci, ep_ring, cur_td);
 remove_finished_td:
 		/*
 		 * The event handler won't see a completion for this TD anymore,
@@ -3834,11 +3819,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
 		ret = prepare_transfer(xhci, xhci->devs[slot_id], ep_index,
 				urb->stream_id, trbs_per_td, urb, i, mem_flags);
-		if (ret < 0) {
-			if (i == 0)
-				return ret;
-			goto cleanup;
-		}
+		if (ret < 0)
+			/* This can only happen when for the first TD */
+			return ret;
 
 		td = urb_priv->td[i];
 		for (j = 0; j < trbs_per_td; j++) {
@@ -3922,13 +3905,6 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 			addr += trb_buff_len;
 			td_remain_len -= trb_buff_len;
 		}
-
-		/* Check TD length */
-		if (running_total != td_len) {
-			xhci_err(xhci, "ISOC TD length unmatch\n");
-			ret = -EINVAL;
-			goto cleanup;
-		}
 	}
 
 	if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) {
@@ -3939,28 +3915,6 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
 	giveback_first_trb(xhci, slot_id, ep_index, ep_ring);
 	return 0;
-cleanup:
-	/* Clean up a partially enqueued isoc transfer. */
-
-	for (i--; i >= 0; i--)
-		list_del_init(&urb_priv->td[i]->td_list);
-
-	/* Use the first TD as a temporary variable to turn the TDs we've queued
-	 * into No-ops with a software-owned cycle bit. That way the hardware
-	 * won't accidentally start executing bogus TDs when we partially
-	 * overwrite them.  td->first_trb and td->start_seg are already set.
-	 */
-	urb_priv->td[0]->last_trb = ep_ring->enqueue;
-	/* Every TRB except the first & last will have its cycle bit flipped. */
-	td_to_noop(xhci, ep_ring, urb_priv->td[0], true);
-
-	/* Reset the ring enqueue back to the first TRB and its cycle bit. */
-	ep_ring->enqueue = urb_priv->td[0]->first_trb;
-	ep_ring->enq_seg = urb_priv->td[0]->start_seg;
-	ep_ring->cycle_state = start_cycle;
-	ep_ring->num_trbs_free = ep_ring->num_trbs_free_temp;
-	usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
-	return ret;
 }
 
 /*
-- 
1.8.1.2



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux