[PATCH v3 5/9] xhci: Move fragment length calculation to top of loop in queue_bulk_sg_tx()

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

 



The calculation done for the first fragment is exactly the same
as the one for subsequent fragments.
So move both versions to inside the loop at the top.
Simplify the calculation for the distance to the next 64k boundary.
Remove the never-checked 'num_sgs'.

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

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 51cc8a6..bf9a20f 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3272,9 +3272,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 	unsigned int num_trbs;
 	struct urb_priv *urb_priv;
 	struct scatterlist *sg;
-	int num_sgs;
-	int trb_buff_len, this_sg_len, running_total;
-	int len_left;
+	u32 trb_buff_len, this_sg_len, running_total;
+	u32 len_left;
 	unsigned int total_packet_count;
 	u32 trb_type_flags;
 	u64 addr;
@@ -3288,7 +3287,6 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 		return -EINVAL;
 
 	num_trbs = count_sg_trbs_needed(ep_ring, urb);
-	num_sgs = urb->num_mapped_sgs;
 	total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
 			usb_endpoint_maxp(&urb->ep->desc));
 
@@ -3317,34 +3315,29 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
 	running_total = 0;
 	len_left = urb->transfer_buffer_length;
-	/*
-	 * How much data is in the first TRB?
-	 *
-	 * There are three forces at work for TRB buffer pointers and lengths:
-	 * 1. We don't want to walk off the end of this sg-list entry buffer.
-	 * 2. The transfer length that the driver requested may be smaller than
-	 *    the amount of memory allocated for this scatter-gather list.
-	 * 3. TRBs buffers can't cross 64KB boundaries.
-	 */
+
 	sg = urb->sg;
 	addr = (u64) sg_dma_address(sg);
 	this_sg_len = sg_dma_len(sg);
-	trb_buff_len = TRB_MAX_BUFF_SIZE - (addr & (TRB_MAX_BUFF_SIZE - 1));
-	trb_buff_len = min_t(int, trb_buff_len, this_sg_len);
-	if (trb_buff_len > urb->transfer_buffer_length)
-		trb_buff_len = urb->transfer_buffer_length;
 
 	/* Queue the first TRB, even if it's zero-length */
 	for (;;) {
 		u32 length_field = 0;
 		u32 remainder = 0;
-
-		/* Set the correct cycle bit (inverted for first TRB). */
-		trb_type_flags ^= ep_ring->cycle_state;
+		/*
+		 * How much data is in the TRB?
+		 *
+		 * 1) TRB buffers must not cross 64k boundaries.
+		 * 2) Limit to the size of this sg buffer.
+		 * 3) Limit to the overall transfer size.
+		 */
+		trb_buff_len = (~addr & (TRB_MAX_BUFF_SIZE - 1)) + 1;
+		trb_buff_len = min_t(u32, trb_buff_len, this_sg_len);
 
 		/* Check for last fragment... */
-		if (trb_buff_len == len_left) {
+		if (trb_buff_len >= len_left) {
 			/* FIXME - add check for ZERO_PACKET flag before this */
+			trb_buff_len = len_left;
 			urb_priv = urb->hcpriv;
 			urb_priv->td[0]->last_trb = ep_ring->enqueue;
 			/* Request interrupt and clear chain */
@@ -3354,6 +3347,9 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 				goto next_frag;
 		}
 
+		/* Set the correct cycle bit (inverted for first TRB). */
+		trb_type_flags ^= ep_ring->cycle_state;
+
 		/* Set the TRB length, TD size, and interrupter fields. */
 		if (xhci->hci_version < 0x100) {
 			remainder = xhci_td_remainder(len_left);
@@ -3382,25 +3378,16 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 		running_total += trb_buff_len;
 		len_left -= trb_buff_len;
 
-		/* Calculate length for next transfer --
-		 * Are we done queueing all the TRBs for this sg entry?
-		 */
+		/* Advance source data pointer */
 		this_sg_len -= trb_buff_len;
 next_frag:
 		if (this_sg_len == 0) {
-			--num_sgs;
 			sg = sg_next(sg);
 			addr = (u64) sg_dma_address(sg);
 			this_sg_len = sg_dma_len(sg);
 		} else {
 			addr += trb_buff_len;
 		}
-
-		trb_buff_len = TRB_MAX_BUFF_SIZE -
-			(addr & (TRB_MAX_BUFF_SIZE - 1));
-		trb_buff_len = min_t(int, trb_buff_len, this_sg_len);
-		if (trb_buff_len > len_left)
-			trb_buff_len = len_left;
 	}
 
 	giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
-- 
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