Skip to content

Commit 5a83f04

Browse files
matnymangregkh
authored andcommitted
xhci: properly prepare zero packet TD after normal bulk TD.
If a zero-length packet is needed after a bulk transfer, then an additional zero length TD was prepared before enqueueing the bulk transfer This set up the zero packet TD structure with incorrect td->start_seg and td->first_trb pointers. Prepare the zero packet TD after the data bulk TD is enqueued instead. It sets these pointers correctly. This change also simplifies unnecessary complexity related to keeping track of the last trb when enqueuing trbs. Signed-off-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5a5a0b1 commit 5a83f04

File tree

1 file changed

+15
-23
lines changed

1 file changed

+15
-23
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3125,8 +3125,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31253125
struct xhci_td *td;
31263126
struct xhci_generic_trb *start_trb;
31273127
struct scatterlist *sg = NULL;
3128-
bool more_trbs_coming;
3129-
bool zero_length_needed;
3128+
bool more_trbs_coming = true;
3129+
bool need_zero_pkt = false;
31303130
unsigned int num_trbs, last_trb_num, i;
31313131
unsigned int start_cycle, num_sgs = 0;
31323132
unsigned int running_total, block_len, trb_buff_len, full_len;
@@ -3157,17 +3157,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31573157
last_trb_num = num_trbs - 1;
31583158

31593159
/* Deal with URB_ZERO_PACKET - need one more td/trb */
3160-
zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET &&
3161-
urb_priv->length == 2;
3162-
if (zero_length_needed) {
3163-
num_trbs++;
3164-
xhci_dbg(xhci, "Creating zero length td.\n");
3165-
ret = prepare_transfer(xhci, xhci->devs[slot_id],
3166-
ep_index, urb->stream_id,
3167-
1, urb, 1, mem_flags);
3168-
if (unlikely(ret < 0))
3169-
return ret;
3170-
}
3160+
if (urb->transfer_flags & URB_ZERO_PACKET && urb_priv->length > 1)
3161+
need_zero_pkt = true;
31713162

31723163
td = urb_priv->td[0];
31733164

@@ -3225,12 +3216,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
32253216
field |= TRB_CHAIN;
32263217
} else {
32273218
field |= TRB_IOC;
3228-
if (i == last_trb_num)
3229-
td->last_trb = ring->enqueue;
3230-
else if (zero_length_needed) {
3231-
trb_buff_len = 0;
3232-
urb_priv->td[1]->last_trb = ring->enqueue;
3233-
}
3219+
more_trbs_coming = need_zero_pkt;
3220+
td->last_trb = ring->enqueue;
32343221
}
32353222

32363223
/* Only set interrupt on short packet for IN endpoints */
@@ -3246,10 +3233,6 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
32463233
TRB_TD_SIZE(remainder) |
32473234
TRB_INTR_TARGET(0);
32483235

3249-
if (i < num_trbs - 1)
3250-
more_trbs_coming = true;
3251-
else
3252-
more_trbs_coming = false;
32533236
queue_trb(xhci, ring, more_trbs_coming,
32543237
lower_32_bits(addr),
32553238
upper_32_bits(addr),
@@ -3271,6 +3254,15 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
32713254
}
32723255
}
32733256

3257+
if (need_zero_pkt) {
3258+
ret = prepare_transfer(xhci, xhci->devs[slot_id],
3259+
ep_index, urb->stream_id,
3260+
1, urb, 1, mem_flags);
3261+
urb_priv->td[1]->last_trb = ring->enqueue;
3262+
field = TRB_TYPE(TRB_NORMAL) | ring->cycle_state | TRB_IOC;
3263+
queue_trb(xhci, ring, 0, 0, 0, TRB_INTR_TARGET(0), field);
3264+
}
3265+
32743266
check_trb_math(urb, running_total);
32753267
giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
32763268
start_cycle, start_trb);

0 commit comments

Comments
 (0)