Skip to content

Commit 86065c2

Browse files
matnymangregkh
authored andcommitted
xhci: don't rely on precalculated value of needed trbs in the enqueue loop
Queue trbs until all payload data in the urb is tranferred. The actual number of trbs might need to change from the pre-calculated number when the packet alignment restrictions for td fragments in xhci 4.11.7.1 are taken into account. Long term plan is to get rid of calculating the needed trbs in advance all together. It's an unnecessary extra walk through the scatterlist. This change also allows some bulk queue function simplifications Signed-off-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 124c393 commit 86065c2

File tree

1 file changed

+29
-46
lines changed

1 file changed

+29
-46
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3127,9 +3127,10 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31273127
struct scatterlist *sg = NULL;
31283128
bool more_trbs_coming = true;
31293129
bool need_zero_pkt = false;
3130-
unsigned int num_trbs, last_trb_num, i;
3130+
bool first_trb = true;
3131+
unsigned int num_trbs;
31313132
unsigned int start_cycle, num_sgs = 0;
3132-
unsigned int running_total, block_len, trb_buff_len, full_len;
3133+
unsigned int enqd_len, block_len, trb_buff_len, full_len;
31333134
int ret;
31343135
u32 field, length_field, remainder;
31353136
u64 addr;
@@ -3138,14 +3139,19 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31383139
if (!ring)
31393140
return -EINVAL;
31403141

3142+
full_len = urb->transfer_buffer_length;
31413143
/* If we have scatter/gather list, we use it. */
31423144
if (urb->num_sgs) {
31433145
num_sgs = urb->num_mapped_sgs;
31443146
sg = urb->sg;
3147+
addr = (u64) sg_dma_address(sg);
3148+
block_len = sg_dma_len(sg);
31453149
num_trbs = count_sg_trbs_needed(urb);
3146-
} else
3150+
} else {
31473151
num_trbs = count_trbs_needed(urb);
3148-
3152+
addr = (u64) urb->transfer_dma;
3153+
block_len = full_len;
3154+
}
31493155
ret = prepare_transfer(xhci, xhci->devs[slot_id],
31503156
ep_index, urb->stream_id,
31513157
num_trbs, urb, 0, mem_flags);
@@ -3154,8 +3160,6 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31543160

31553161
urb_priv = urb->hcpriv;
31563162

3157-
last_trb_num = num_trbs - 1;
3158-
31593163
/* Deal with URB_ZERO_PACKET - need one more td/trb */
31603164
if (urb->transfer_flags & URB_ZERO_PACKET && urb_priv->length > 1)
31613165
need_zero_pkt = true;
@@ -3170,40 +3174,20 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31703174
start_trb = &ring->enqueue->generic;
31713175
start_cycle = ring->cycle_state;
31723176

3173-
full_len = urb->transfer_buffer_length;
3174-
running_total = 0;
3175-
block_len = 0;
3176-
31773177
/* Queue the TRBs, even if they are zero-length */
3178-
for (i = 0; i < num_trbs; i++) {
3178+
for (enqd_len = 0; enqd_len < full_len; enqd_len += trb_buff_len) {
31793179
field = TRB_TYPE(TRB_NORMAL);
31803180

3181-
if (block_len == 0) {
3182-
/* A new contiguous block. */
3183-
if (sg) {
3184-
addr = (u64) sg_dma_address(sg);
3185-
block_len = sg_dma_len(sg);
3186-
} else {
3187-
addr = (u64) urb->transfer_dma;
3188-
block_len = full_len;
3189-
}
3190-
/* TRB buffer should not cross 64KB boundaries */
3191-
trb_buff_len = TRB_BUFF_LEN_UP_TO_BOUNDARY(addr);
3192-
trb_buff_len = min_t(unsigned int,
3193-
trb_buff_len,
3194-
block_len);
3195-
} else {
3196-
/* Further through the contiguous block. */
3197-
trb_buff_len = block_len;
3198-
if (trb_buff_len > TRB_MAX_BUFF_SIZE)
3199-
trb_buff_len = TRB_MAX_BUFF_SIZE;
3200-
}
3181+
/* TRB buffer should not cross 64KB boundaries */
3182+
trb_buff_len = TRB_BUFF_LEN_UP_TO_BOUNDARY(addr);
3183+
trb_buff_len = min_t(unsigned int, trb_buff_len, block_len);
32013184

3202-
if (running_total + trb_buff_len > full_len)
3203-
trb_buff_len = full_len - running_total;
3185+
if (enqd_len + trb_buff_len > full_len)
3186+
trb_buff_len = full_len - enqd_len;
32043187

32053188
/* Don't change the cycle bit of the first TRB until later */
3206-
if (i == 0) {
3189+
if (first_trb) {
3190+
first_trb = false;
32073191
if (start_cycle == 0)
32083192
field |= TRB_CYCLE;
32093193
} else
@@ -3212,7 +3196,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
32123196
/* Chain all the TRBs together; clear the chain bit in the last
32133197
* TRB to indicate it's the last TRB in the chain.
32143198
*/
3215-
if (i < last_trb_num) {
3199+
if (enqd_len + trb_buff_len < full_len) {
32163200
field |= TRB_CHAIN;
32173201
} else {
32183202
field |= TRB_IOC;
@@ -3225,9 +3209,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
32253209
field |= TRB_ISP;
32263210

32273211
/* Set the TRB length, TD size, and interrupter fields. */
3228-
remainder = xhci_td_remainder(xhci, running_total,
3229-
trb_buff_len, full_len,
3230-
urb, more_trbs_coming);
3212+
remainder = xhci_td_remainder(xhci, enqd_len, trb_buff_len,
3213+
full_len, urb, more_trbs_coming);
3214+
32313215
length_field = TRB_LEN(trb_buff_len) |
32323216
TRB_TD_SIZE(remainder) |
32333217
TRB_INTR_TARGET(0);
@@ -3238,17 +3222,16 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
32383222
length_field,
32393223
field);
32403224

3241-
running_total += trb_buff_len;
32423225
addr += trb_buff_len;
32433226
block_len -= trb_buff_len;
32443227

3245-
if (sg) {
3246-
if (block_len == 0) {
3247-
/* New sg entry */
3248-
--num_sgs;
3249-
if (num_sgs == 0)
3250-
break;
3228+
if (sg && block_len == 0) {
3229+
/* New sg entry */
3230+
--num_sgs;
3231+
if (num_sgs != 0) {
32513232
sg = sg_next(sg);
3233+
block_len = sg_dma_len(sg);
3234+
addr = (u64) sg_dma_address(sg);
32523235
}
32533236
}
32543237
}
@@ -3262,7 +3245,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
32623245
queue_trb(xhci, ring, 0, 0, 0, TRB_INTR_TARGET(0), field);
32633246
}
32643247

3265-
check_trb_math(urb, running_total);
3248+
check_trb_math(urb, enqd_len);
32663249
giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
32673250
start_cycle, start_trb);
32683251
return 0;

0 commit comments

Comments
 (0)