diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3b671122106de0317d163ad56c823127a742f564..7cf66212ceae0cfbe1c161877044755057373781 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3770,12 +3770,15 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, * Prevent HW from getting the TRBs by keeping the cycle state * inverted in the first TDs isoc TRB. */ - field = TRB_TBC(burst_count) | - TRB_TYPE(TRB_ISOC) | + field = TRB_TYPE(TRB_ISOC) | TRB_TLBPC(last_burst_pkt_count) | sia_frame_id | (i ? ep_ring->cycle_state : !start_cycle); + /* xhci 1.1 with ETE uses TD_Size field for TBC, old is Rsvdz */ + if (!xep->use_extended_tbc) + field |= TRB_TBC(burst_count); + /* fill the rest of the TRB fields, and remaining normal TRBs */ for (j = 0; j < trbs_per_td; j++) { u32 remainder = 0; @@ -3784,7 +3787,6 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, if (!first_trb) field = TRB_TYPE(TRB_NORMAL) | ep_ring->cycle_state; - first_trb = false; /* Only set interrupt on short packet for IN EPs */ if (usb_urb_dir_in(urb)) @@ -3816,9 +3818,15 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb, trbs_per_td - j - 1); length_field = TRB_LEN(trb_buff_len) | - TRB_TD_SIZE(remainder) | TRB_INTR_TARGET(0); + /* xhci 1.1 with ETE uses TD Size field for TBC */ + if (first_trb && xep->use_extended_tbc) + length_field |= TRB_TD_SIZE_TBC(burst_count); + else + length_field |= TRB_TD_SIZE(remainder); + first_trb = false; + queue_trb(xhci, ep_ring, more_trbs_coming, lower_32_bits(addr), upper_32_bits(addr), diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 40a7efd86b9c3fa3f6ed95ff3329eb796288a009..e293e0974f48257e32653e9ae30501d09c64ea1c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -232,7 +232,9 @@ struct xhci_op_regs { * disabled, or powered-off state. */ #define CMD_PM_INDEX (1 << 11) -/* bits 12:31 are reserved (and should be preserved on writes). */ +/* bit 14 Extended TBC Enable, changes Isoc TRB fields to support larger TBC */ +#define CMD_ETE (1 << 14) +/* bits 15:31 are reserved (and should be preserved on writes). */ /* IMAN - Interrupt Management Register */ #define IMAN_IE (1 << 1) @@ -943,6 +945,8 @@ struct xhci_virt_ep { struct list_head bw_endpoint_list; /* Isoch Frame ID checking storage */ int next_frame_id; + /* Use new Isoch TRB layout needed for extended TBC support */ + bool use_extended_tbc; }; enum xhci_overhead_type { @@ -1184,9 +1188,12 @@ enum xhci_setup_dev { #define TRB_LEN(p) ((p) & 0x1ffff) /* TD Size, packets remaining in this TD, bits 21:17 (5 bits, so max 31) */ #define TRB_TD_SIZE(p) (min((p), (u32)31) << 17) +/* xhci 1.1 uses the TD_SIZE field for TBC if Extended TBC is enabled (ETE) */ +#define TRB_TD_SIZE_TBC(p) (min((p), (u32)31) << 17) /* Interrupter Target - which MSI-X vector to target the completion event at */ #define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22) #define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff) +/* Total burst count field, Rsvdz on xhci 1.1 with Extended TBC enabled (ETE) */ #define TRB_TBC(p) (((p) & 0x3) << 7) #define TRB_TLBPC(p) (((p) & 0xf) << 16)