Skip to content

Commit

Permalink
xhci 1.0: Only interrupt on short packet for IN EPs.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sarah Sharp committed May 2, 2011
1 parent 00161f7 commit af8b9e6
Showing 1 changed file with 24 additions and 21 deletions.
45 changes: 24 additions & 21 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -2741,6 +2741,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,
Expand All @@ -2766,12 +2771,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;

Expand Down Expand Up @@ -2905,6 +2905,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) |
Expand All @@ -2918,12 +2923,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;

Expand Down Expand Up @@ -3009,7 +3009,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);
Expand All @@ -3020,8 +3025,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 */
Expand Down Expand Up @@ -3145,6 +3149,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.
Expand Down Expand Up @@ -3172,12 +3180,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;
Expand Down

0 comments on commit af8b9e6

Please sign in to comment.