Skip to content

Commit c840d6c

Browse files
matnymangregkh
authored andcommitted
xhci: create one unified function to calculate TRB TD remainder.
xhci versions 1.0 and later report the untransferred data remaining in a TD a bit differently than older hosts. We used to have separate functions for these, and needed to check host version before calling the right function. Now Mediatek host has an additional quirk on how it uses the TD Size field for remaining data. To prevent yet another function for calculating remainder we instead want to make one quirk friendly unified function. Tested-by: Chunfeng Yun <chunfeng.yun@mediatek.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b1630da commit c840d6c

File tree

2 files changed

+46
-62
lines changed

2 files changed

+46
-62
lines changed

drivers/usb/host/xhci-ring.c

Lines changed: 44 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -3028,21 +3028,6 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
30283028
return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index);
30293029
}
30303030

3031-
/*
3032-
* The TD size is the number of bytes remaining in the TD (including this TRB),
3033-
* right shifted by 10.
3034-
* It must fit in bits 21:17, so it can't be bigger than 31.
3035-
*/
3036-
static u32 xhci_td_remainder(unsigned int remainder)
3037-
{
3038-
u32 max = (1 << (21 - 17 + 1)) - 1;
3039-
3040-
if ((remainder >> 10) >= max)
3041-
return max << 17;
3042-
else
3043-
return (remainder >> 10) << 17;
3044-
}
3045-
30463031
/*
30473032
* For xHCI 1.0 host controllers, TD size is the number of max packet sized
30483033
* packets remaining in the TD (*not* including this TRB).
@@ -3055,30 +3040,36 @@ static u32 xhci_td_remainder(unsigned int remainder)
30553040
*
30563041
* TD size = total_packet_count - packets_transferred
30573042
*
3058-
* It must fit in bits 21:17, so it can't be bigger than 31.
3043+
* For xHCI 0.96 and older, TD size field should be the remaining bytes
3044+
* including this TRB, right shifted by 10
3045+
*
3046+
* For all hosts it must fit in bits 21:17, so it can't be bigger than 31.
3047+
* This is taken care of in the TRB_TD_SIZE() macro
3048+
*
30593049
* The last TRB in a TD must have the TD size set to zero.
30603050
*/
3061-
static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
3062-
unsigned int total_packet_count, struct urb *urb,
3063-
unsigned int num_trbs_left)
3051+
static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
3052+
int trb_buff_len, unsigned int td_total_len,
3053+
struct urb *urb, unsigned int num_trbs_left)
30643054
{
3065-
int packets_transferred;
3055+
u32 maxp, total_packet_count;
3056+
3057+
if (xhci->hci_version < 0x100)
3058+
return ((td_total_len - transferred) >> 10);
3059+
3060+
maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
3061+
total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
30663062

30673063
/* One TRB with a zero-length data packet. */
3068-
if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
3064+
if (num_trbs_left == 0 || (transferred == 0 && trb_buff_len == 0) ||
3065+
trb_buff_len == td_total_len)
30693066
return 0;
30703067

3071-
/* All the TRB queueing functions don't count the current TRB in
3072-
* running_total.
3073-
*/
3074-
packets_transferred = (running_total + trb_buff_len) /
3075-
GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
3076-
3077-
if ((total_packet_count - packets_transferred) > 31)
3078-
return 31 << 17;
3079-
return (total_packet_count - packets_transferred) << 17;
3068+
/* Queueing functions don't count the current TRB into transferred */
3069+
return (total_packet_count - ((transferred + trb_buff_len) / maxp));
30803070
}
30813071

3072+
30823073
static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
30833074
struct urb *urb, int slot_id, unsigned int ep_index)
30843075
{
@@ -3200,17 +3191,12 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
32003191
}
32013192

32023193
/* Set the TRB length, TD size, and interrupter fields. */
3203-
if (xhci->hci_version < 0x100) {
3204-
remainder = xhci_td_remainder(
3205-
urb->transfer_buffer_length -
3206-
running_total);
3207-
} else {
3208-
remainder = xhci_v1_0_td_remainder(running_total,
3209-
trb_buff_len, total_packet_count, urb,
3210-
num_trbs - 1);
3211-
}
3194+
remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
3195+
urb->transfer_buffer_length,
3196+
urb, num_trbs - 1);
3197+
32123198
length_field = TRB_LEN(trb_buff_len) |
3213-
remainder |
3199+
TRB_TD_SIZE(remainder) |
32143200
TRB_INTR_TARGET(0);
32153201

32163202
if (num_trbs > 1)
@@ -3373,17 +3359,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
33733359
field |= TRB_ISP;
33743360

33753361
/* Set the TRB length, TD size, and interrupter fields. */
3376-
if (xhci->hci_version < 0x100) {
3377-
remainder = xhci_td_remainder(
3378-
urb->transfer_buffer_length -
3379-
running_total);
3380-
} else {
3381-
remainder = xhci_v1_0_td_remainder(running_total,
3382-
trb_buff_len, total_packet_count, urb,
3383-
num_trbs - 1);
3384-
}
3362+
remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
3363+
urb->transfer_buffer_length,
3364+
urb, num_trbs - 1);
3365+
33853366
length_field = TRB_LEN(trb_buff_len) |
3386-
remainder |
3367+
TRB_TD_SIZE(remainder) |
33873368
TRB_INTR_TARGET(0);
33883369

33893370
if (num_trbs > 1)
@@ -3421,7 +3402,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
34213402
struct usb_ctrlrequest *setup;
34223403
struct xhci_generic_trb *start_trb;
34233404
int start_cycle;
3424-
u32 field, length_field;
3405+
u32 field, length_field, remainder;
34253406
struct urb_priv *urb_priv;
34263407
struct xhci_td *td;
34273408

@@ -3494,9 +3475,15 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
34943475
else
34953476
field = TRB_TYPE(TRB_DATA);
34963477

3478+
remainder = xhci_td_remainder(xhci, 0,
3479+
urb->transfer_buffer_length,
3480+
urb->transfer_buffer_length,
3481+
urb, 1);
3482+
34973483
length_field = TRB_LEN(urb->transfer_buffer_length) |
3498-
xhci_td_remainder(urb->transfer_buffer_length) |
3484+
TRB_TD_SIZE(remainder) |
34993485
TRB_INTR_TARGET(0);
3486+
35003487
if (urb->transfer_buffer_length > 0) {
35013488
if (setup->bRequestType & USB_DIR_IN)
35023489
field |= TRB_DIR_IN;
@@ -3825,17 +3812,12 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
38253812
trb_buff_len = td_remain_len;
38263813

38273814
/* Set the TRB length, TD size, & interrupter fields. */
3828-
if (xhci->hci_version < 0x100) {
3829-
remainder = xhci_td_remainder(
3830-
td_len - running_total);
3831-
} else {
3832-
remainder = xhci_v1_0_td_remainder(
3833-
running_total, trb_buff_len,
3834-
total_packet_count, urb,
3835-
(trbs_per_td - j - 1));
3836-
}
3815+
remainder = xhci_td_remainder(xhci, running_total,
3816+
trb_buff_len, td_len,
3817+
urb, trbs_per_td - j - 1);
3818+
38373819
length_field = TRB_LEN(trb_buff_len) |
3838-
remainder |
3820+
TRB_TD_SIZE(remainder) |
38393821
TRB_INTR_TARGET(0);
38403822

38413823
queue_trb(xhci, ep_ring, more_trbs_coming,

drivers/usb/host/xhci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,8 @@ enum xhci_setup_dev {
11791179
/* Normal TRB fields */
11801180
/* transfer_len bitmasks - bits 0:16 */
11811181
#define TRB_LEN(p) ((p) & 0x1ffff)
1182+
/* TD Size, packets remaining in this TD, bits 21:17 (5 bits, so max 31) */
1183+
#define TRB_TD_SIZE(p) (min((p), (u32)31) << 17)
11821184
/* Interrupter Target - which MSI-X vector to target the completion event at */
11831185
#define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22)
11841186
#define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff)

0 commit comments

Comments
 (0)