Skip to content

Commit 4da6e6f

Browse files
author
Sarah Sharp
committed
xhci 1.0: Update TD size field format.
The xHCI 1.0 specification changes the format of the TD size field in Normal and Isochronous TRBs. The field in control TRBs is still set to reserved zero. Instead of representing the number of bytes left to transfer in the TD (including the current TRB's buffer), it now represents the number of packets left to transfer (*not* including this TRB). See section 4.11.2.4 of the xHCI 1.0 specification for details. The math is basically copied straight from there. Create a new function, xhci_v1_0_td_remainder(), that should be called for all xHCI 1.0 host controllers. The field location and maximum value is still the same, so reuse the old function, xhci_td_remainder(), to handle the bit shifting. Signed-off-by: Sarah Sharp <[email protected]>
1 parent af8b9e6 commit 4da6e6f

File tree

1 file changed

+70
-6
lines changed

1 file changed

+70
-6
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,6 +2655,35 @@ static u32 xhci_td_remainder(unsigned int remainder)
26552655
return (remainder >> 10) << 17;
26562656
}
26572657

2658+
/*
2659+
* For xHCI 1.0 host controllers, TD size is the number of packets remaining in
2660+
* the TD (*not* including this TRB).
2661+
*
2662+
* Total TD packet count = total_packet_count =
2663+
* roundup(TD size in bytes / wMaxPacketSize)
2664+
*
2665+
* Packets transferred up to and including this TRB = packets_transferred =
2666+
* rounddown(total bytes transferred including this TRB / wMaxPacketSize)
2667+
*
2668+
* TD size = total_packet_count - packets_transferred
2669+
*
2670+
* It must fit in bits 21:17, so it can't be bigger than 31.
2671+
*/
2672+
2673+
static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
2674+
unsigned int total_packet_count, struct urb *urb)
2675+
{
2676+
int packets_transferred;
2677+
2678+
/* All the TRB queueing functions don't count the current TRB in
2679+
* running_total.
2680+
*/
2681+
packets_transferred = (running_total + trb_buff_len) /
2682+
le16_to_cpu(urb->ep->desc.wMaxPacketSize);
2683+
2684+
return xhci_td_remainder(total_packet_count - packets_transferred);
2685+
}
2686+
26582687
static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
26592688
struct urb *urb, int slot_id, unsigned int ep_index)
26602689
{
@@ -2665,6 +2694,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
26652694
struct scatterlist *sg;
26662695
int num_sgs;
26672696
int trb_buff_len, this_sg_len, running_total;
2697+
unsigned int total_packet_count;
26682698
bool first_trb;
26692699
u64 addr;
26702700
bool more_trbs_coming;
@@ -2678,6 +2708,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
26782708

26792709
num_trbs = count_sg_trbs_needed(xhci, urb);
26802710
num_sgs = urb->num_sgs;
2711+
total_packet_count = roundup(urb->transfer_buffer_length,
2712+
le16_to_cpu(urb->ep->desc.wMaxPacketSize));
26812713

26822714
trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
26832715
ep_index, urb->stream_id,
@@ -2758,11 +2790,20 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
27582790
(unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1),
27592791
(unsigned int) addr + trb_buff_len);
27602792
}
2761-
remainder = xhci_td_remainder(urb->transfer_buffer_length -
2762-
running_total) ;
2793+
2794+
/* Set the TRB length, TD size, and interrupter fields. */
2795+
if (xhci->hci_version < 0x100) {
2796+
remainder = xhci_td_remainder(
2797+
urb->transfer_buffer_length -
2798+
running_total);
2799+
} else {
2800+
remainder = xhci_v1_0_td_remainder(running_total,
2801+
trb_buff_len, total_packet_count, urb);
2802+
}
27632803
length_field = TRB_LEN(trb_buff_len) |
27642804
remainder |
27652805
TRB_INTR_TARGET(0);
2806+
27662807
if (num_trbs > 1)
27672808
more_trbs_coming = true;
27682809
else
@@ -2819,6 +2860,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
28192860
u32 field, length_field;
28202861

28212862
int running_total, trb_buff_len, ret;
2863+
unsigned int total_packet_count;
28222864
u64 addr;
28232865

28242866
if (urb->num_sgs)
@@ -2873,6 +2915,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
28732915
start_cycle = ep_ring->cycle_state;
28742916

28752917
running_total = 0;
2918+
total_packet_count = roundup(urb->transfer_buffer_length,
2919+
le16_to_cpu(urb->ep->desc.wMaxPacketSize));
28762920
/* How much data is in the first TRB? */
28772921
addr = (u64) urb->transfer_dma;
28782922
trb_buff_len = TRB_MAX_BUFF_SIZE -
@@ -2910,11 +2954,19 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
29102954
if (usb_urb_dir_in(urb))
29112955
field |= TRB_ISP;
29122956

2913-
remainder = xhci_td_remainder(urb->transfer_buffer_length -
2914-
running_total);
2957+
/* Set the TRB length, TD size, and interrupter fields. */
2958+
if (xhci->hci_version < 0x100) {
2959+
remainder = xhci_td_remainder(
2960+
urb->transfer_buffer_length -
2961+
running_total);
2962+
} else {
2963+
remainder = xhci_v1_0_td_remainder(running_total,
2964+
trb_buff_len, total_packet_count, urb);
2965+
}
29152966
length_field = TRB_LEN(trb_buff_len) |
29162967
remainder |
29172968
TRB_INTR_TARGET(0);
2969+
29182970
if (num_trbs > 1)
29192971
more_trbs_coming = true;
29202972
else
@@ -3111,12 +3163,15 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31113163

31123164
/* Queue the first TRB, even if it's zero-length */
31133165
for (i = 0; i < num_tds; i++) {
3114-
first_trb = true;
3166+
unsigned int total_packet_count;
31153167

3168+
first_trb = true;
31163169
running_total = 0;
31173170
addr = start_addr + urb->iso_frame_desc[i].offset;
31183171
td_len = urb->iso_frame_desc[i].length;
31193172
td_remain_len = td_len;
3173+
total_packet_count = roundup(td_len,
3174+
le16_to_cpu(urb->ep->desc.wMaxPacketSize));
31203175

31213176
trbs_per_td = count_isoc_trbs_needed(xhci, urb, i);
31223177

@@ -3172,10 +3227,19 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
31723227
if (trb_buff_len > td_remain_len)
31733228
trb_buff_len = td_remain_len;
31743229

3175-
remainder = xhci_td_remainder(td_len - running_total);
3230+
/* Set the TRB length, TD size, & interrupter fields. */
3231+
if (xhci->hci_version < 0x100) {
3232+
remainder = xhci_td_remainder(
3233+
td_len - running_total);
3234+
} else {
3235+
remainder = xhci_v1_0_td_remainder(
3236+
running_total, trb_buff_len,
3237+
total_packet_count, urb);
3238+
}
31763239
length_field = TRB_LEN(trb_buff_len) |
31773240
remainder |
31783241
TRB_INTR_TARGET(0);
3242+
31793243
queue_trb(xhci, ep_ring, false, more_trbs_coming,
31803244
lower_32_bits(addr),
31813245
upper_32_bits(addr),

0 commit comments

Comments
 (0)