Skip to content

Commit 474ed23

Browse files
matnymangregkh
authored andcommitted
xhci: align the last trb before link if it is easily splittable.
TD fragments section 4.11.7.1 in xhci specs have additional requirements on how trbs in TDs must be organized. TD fragments shall not span transfer ring segments and TD fragments must be packet aligned. Normally we don't care about TD fragments, on TD is one big fragment, but if a TD spans ring segments it will be treated as two fragments, and we need to comply with the alignment requirements. For us this means that the payload data must be packet aligned in the last trb before a link trb. In most mass storage bulk tranfers we are lucky as the block size aligns nicely with packet size, and there are no issues. However, usb network adapters using scatterlists can hit this alignment issue, and usbtest in kernel triggers this in minutes. This patch is a partial solution, it solves the easy case when the last trb before the link trb contains a packet boundary. If that is the case then just split the trb at the boundary. If not, then just print a debug message and continue as we have always done, hoping for the best Signed-off-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 86065c2 commit 474ed23

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3116,6 +3116,27 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
31163116
return (total_packet_count - ((transferred + trb_buff_len) / maxp));
31173117
}
31183118

3119+
static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len,
3120+
u32 *trb_buff_len)
3121+
{
3122+
unsigned int unalign;
3123+
unsigned int max_pkt;
3124+
3125+
max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
3126+
unalign = (enqd_len + *trb_buff_len) % max_pkt;
3127+
3128+
/* we got lucky, last normal TRB data on segment is packet aligned */
3129+
if (unalign == 0)
3130+
return 0;
3131+
3132+
/* is the last nornal TRB alignable by splitting it */
3133+
if (*trb_buff_len > unalign) {
3134+
*trb_buff_len -= unalign;
3135+
return 0;
3136+
}
3137+
return 1;
3138+
}
3139+
31193140
/* This is very similar to what ehci-q.c qtd_fill() does */
31203141
int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31213142
struct urb *urb, int slot_id, unsigned int ep_index)
@@ -3198,6 +3219,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31983219
*/
31993220
if (enqd_len + trb_buff_len < full_len) {
32003221
field |= TRB_CHAIN;
3222+
if (last_trb(xhci, ring, ring->enq_seg,
3223+
ring->enqueue + 1)) {
3224+
if (xhci_align_td(xhci, urb, enqd_len,
3225+
&trb_buff_len))
3226+
xhci_dbg(xhci, "TRB align fail\n");
3227+
}
32013228
} else {
32023229
field |= TRB_IOC;
32033230
more_trbs_coming = false;

0 commit comments

Comments
 (0)