aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2011-03-23 19:26:26 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-05-02 19:42:55 -0400
commitaf8b9e636065ba1701c4215a8dc4f7a1d69d934b (patch)
tree7f904472baafbf578099d0e653ebae1a06d902ee
parent00161f7d04eb1668fde5e22d3e5a17bf90356d2c (diff)
xhci 1.0: Only interrupt on short packet for IN EPs.
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@linux.intel.com>
-rw-r--r--drivers/usb/host/xhci-ring.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 73f8db0ecc4b..766f6a615b2a 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2741,6 +2741,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
2741 td->last_trb = ep_ring->enqueue; 2741 td->last_trb = ep_ring->enqueue;
2742 field |= TRB_IOC; 2742 field |= TRB_IOC;
2743 } 2743 }
2744
2745 /* Only set interrupt on short packet for IN endpoints */
2746 if (usb_urb_dir_in(urb))
2747 field |= TRB_ISP;
2748
2744 xhci_dbg(xhci, " sg entry: dma = %#x, len = %#x (%d), " 2749 xhci_dbg(xhci, " sg entry: dma = %#x, len = %#x (%d), "
2745 "64KB boundary at %#x, end dma = %#x\n", 2750 "64KB boundary at %#x, end dma = %#x\n",
2746 (unsigned int) addr, trb_buff_len, trb_buff_len, 2751 (unsigned int) addr, trb_buff_len, trb_buff_len,
@@ -2766,12 +2771,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
2766 lower_32_bits(addr), 2771 lower_32_bits(addr),
2767 upper_32_bits(addr), 2772 upper_32_bits(addr),
2768 length_field, 2773 length_field,
2769 /* We always want to know if the TRB was short, 2774 field | TRB_TYPE(TRB_NORMAL));
2770 * or we won't get an event when it completes.
2771 * (Unless we use event data TRBs, which are a
2772 * waste of space and HC resources.)
2773 */
2774 field | TRB_ISP | TRB_TYPE(TRB_NORMAL));
2775 --num_trbs; 2775 --num_trbs;
2776 running_total += trb_buff_len; 2776 running_total += trb_buff_len;
2777 2777
@@ -2905,6 +2905,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
2905 td->last_trb = ep_ring->enqueue; 2905 td->last_trb = ep_ring->enqueue;
2906 field |= TRB_IOC; 2906 field |= TRB_IOC;
2907 } 2907 }
2908
2909 /* Only set interrupt on short packet for IN endpoints */
2910 if (usb_urb_dir_in(urb))
2911 field |= TRB_ISP;
2912
2908 remainder = xhci_td_remainder(urb->transfer_buffer_length - 2913 remainder = xhci_td_remainder(urb->transfer_buffer_length -
2909 running_total); 2914 running_total);
2910 length_field = TRB_LEN(trb_buff_len) | 2915 length_field = TRB_LEN(trb_buff_len) |
@@ -2918,12 +2923,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
2918 lower_32_bits(addr), 2923 lower_32_bits(addr),
2919 upper_32_bits(addr), 2924 upper_32_bits(addr),
2920 length_field, 2925 length_field,
2921 /* We always want to know if the TRB was short, 2926 field | TRB_TYPE(TRB_NORMAL));
2922 * or we won't get an event when it completes.
2923 * (Unless we use event data TRBs, which are a
2924 * waste of space and HC resources.)
2925 */
2926 field | TRB_ISP | TRB_TYPE(TRB_NORMAL));
2927 --num_trbs; 2927 --num_trbs;
2928 running_total += trb_buff_len; 2928 running_total += trb_buff_len;
2929 2929
@@ -3009,7 +3009,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3009 field); 3009 field);
3010 3010
3011 /* If there's data, queue data TRBs */ 3011 /* If there's data, queue data TRBs */
3012 field = 0; 3012 /* Only set interrupt on short packet for IN endpoints */
3013 if (usb_urb_dir_in(urb))
3014 field = TRB_ISP | TRB_TYPE(TRB_DATA);
3015 else
3016 field = TRB_TYPE(TRB_DATA);
3017
3013 length_field = TRB_LEN(urb->transfer_buffer_length) | 3018 length_field = TRB_LEN(urb->transfer_buffer_length) |
3014 xhci_td_remainder(urb->transfer_buffer_length) | 3019 xhci_td_remainder(urb->transfer_buffer_length) |
3015 TRB_INTR_TARGET(0); 3020 TRB_INTR_TARGET(0);
@@ -3020,8 +3025,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3020 lower_32_bits(urb->transfer_dma), 3025 lower_32_bits(urb->transfer_dma),
3021 upper_32_bits(urb->transfer_dma), 3026 upper_32_bits(urb->transfer_dma),
3022 length_field, 3027 length_field,
3023 /* Event on short tx */ 3028 field | ep_ring->cycle_state);
3024 field | TRB_ISP | TRB_TYPE(TRB_DATA) | ep_ring->cycle_state);
3025 } 3029 }
3026 3030
3027 /* Save the DMA address of the last TRB in the TD */ 3031 /* Save the DMA address of the last TRB in the TD */
@@ -3145,6 +3149,10 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3145 field |= ep_ring->cycle_state; 3149 field |= ep_ring->cycle_state;
3146 } 3150 }
3147 3151
3152 /* Only set interrupt on short packet for IN EPs */
3153 if (usb_urb_dir_in(urb))
3154 field |= TRB_ISP;
3155
3148 /* Chain all the TRBs together; clear the chain bit in 3156 /* Chain all the TRBs together; clear the chain bit in
3149 * the last TRB to indicate it's the last TRB in the 3157 * the last TRB to indicate it's the last TRB in the
3150 * chain. 3158 * chain.
@@ -3172,12 +3180,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
3172 lower_32_bits(addr), 3180 lower_32_bits(addr),
3173 upper_32_bits(addr), 3181 upper_32_bits(addr),
3174 length_field, 3182 length_field,
3175 /* We always want to know if the TRB was short, 3183 field);
3176 * or we won't get an event when it completes.
3177 * (Unless we use event data TRBs, which are a
3178 * waste of space and HC resources.)
3179 */
3180 field | TRB_ISP);
3181 running_total += trb_buff_len; 3184 running_total += trb_buff_len;
3182 3185
3183 addr += trb_buff_len; 3186 addr += trb_buff_len;