[RFC 1/4] xhci 1.0: Only interrupt on short packet for IN EPs.

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

 



It doesn't make sense to set the interrupt on short packet (TRB_ISP) flag
for TRBs queued to endpoints that only receive packets from the host
controller (i.e. OUT endpoints).  Packets can only be short when they are
sent from a USB device.  Plus, the xHCI 1.0 specification forbids setting
the flag for anything but IN endpoints.

While we're at it, remove some of my snide remarks about the inefficiency
of event data TRBs.

Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>
---
 drivers/usb/host/xhci-ring.c |   45 ++++++++++++++++++++++-------------------
 1 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index a24a885..be12a8d 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2698,6 +2698,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 			td->last_trb = ep_ring->enqueue;
 			field |= TRB_IOC;
 		}
+
+		/* Only set interrupt on short packet for IN endpoints */
+		if (usb_urb_dir_in(urb))
+			field |= TRB_ISP;
+
 		xhci_dbg(xhci, " sg entry: dma = %#x, len = %#x (%d), "
 				"64KB boundary at %#x, end dma = %#x\n",
 				(unsigned int) addr, trb_buff_len, trb_buff_len,
@@ -2723,12 +2728,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 				lower_32_bits(addr),
 				upper_32_bits(addr),
 				length_field,
-				/* We always want to know if the TRB was short,
-				 * or we won't get an event when it completes.
-				 * (Unless we use event data TRBs, which are a
-				 * waste of space and HC resources.)
-				 */
-				field | TRB_ISP | TRB_TYPE(TRB_NORMAL));
+				field | TRB_TYPE(TRB_NORMAL));
 		--num_trbs;
 		running_total += trb_buff_len;
 
@@ -2862,6 +2862,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 			td->last_trb = ep_ring->enqueue;
 			field |= TRB_IOC;
 		}
+
+		/* Only set interrupt on short packet for IN endpoints */
+		if (usb_urb_dir_in(urb))
+			field |= TRB_ISP;
+
 		remainder = xhci_td_remainder(urb->transfer_buffer_length -
 				running_total);
 		length_field = TRB_LEN(trb_buff_len) |
@@ -2875,12 +2880,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 				lower_32_bits(addr),
 				upper_32_bits(addr),
 				length_field,
-				/* We always want to know if the TRB was short,
-				 * or we won't get an event when it completes.
-				 * (Unless we use event data TRBs, which are a
-				 * waste of space and HC resources.)
-				 */
-				field | TRB_ISP | TRB_TYPE(TRB_NORMAL));
+				field | TRB_TYPE(TRB_NORMAL));
 		--num_trbs;
 		running_total += trb_buff_len;
 
@@ -2967,7 +2967,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 			field);
 
 	/* If there's data, queue data TRBs */
-	field = 0;
+	/* Only set interrupt on short packet for IN endpoints */
+	if (usb_urb_dir_in(urb))
+		field = TRB_ISP | TRB_TYPE(TRB_DATA);
+	else
+		field = TRB_TYPE(TRB_DATA);
+
 	length_field = TRB_LEN(urb->transfer_buffer_length) |
 		xhci_td_remainder(urb->transfer_buffer_length) |
 		TRB_INTR_TARGET(0);
@@ -2978,8 +2983,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 				lower_32_bits(urb->transfer_dma),
 				upper_32_bits(urb->transfer_dma),
 				length_field,
-				/* Event on short tx */
-				field | TRB_ISP | TRB_TYPE(TRB_DATA) | ep_ring->cycle_state);
+				field | ep_ring->cycle_state);
 	}
 
 	/* Save the DMA address of the last TRB in the TD */
@@ -3103,6 +3107,10 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 				field |= ep_ring->cycle_state;
 			}
 
+			/* Only set interrupt on short packet for IN EPs */
+			if (usb_urb_dir_in(urb))
+				field |= TRB_ISP;
+
 			/* Chain all the TRBs together; clear the chain bit in
 			 * the last TRB to indicate it's the last TRB in the
 			 * chain.
@@ -3130,12 +3138,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 				lower_32_bits(addr),
 				upper_32_bits(addr),
 				length_field,
-				/* We always want to know if the TRB was short,
-				 * or we won't get an event when it completes.
-				 * (Unless we use event data TRBs, which are a
-				 * waste of space and HC resources.)
-				 */
-				field | TRB_ISP);
+				field);
 			running_total += trb_buff_len;
 
 			addr += trb_buff_len;
-- 
1.7.1

--
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