usb: xhci: add support for xhci trb ent quirk

On some xHCI controllers (e.g. Rockchip RK3399/RK3328/RK1808),
they need to enable the ENT flag in the TRB data structure to
force xHC to pre-fetch the next TRB of a TD. This patch add
a new quirk to enable the ENT flag.

And this patch also avoids to enable the ENT flag in the
following two cases:
1. The transfer length of the first TRB isn't an integer
   multiple of the EP maxpacket.
2. The EP support bulk streaming protocol.

Change-Id: Ib7cc095a848f0846ad995529ad703ae4e4ee4d44
Signed-off-by: William Wu <william.wu@rock-chips.com>
This commit is contained in:
William Wu
2019-04-08 17:46:01 +08:00
committed by Tao Huang
parent da1f09f2a2
commit 0f580acb01
3 changed files with 21 additions and 0 deletions

View File

@@ -291,6 +291,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (device_property_read_bool(tmpdev, "xhci-slow-suspend"))
xhci->quirks |= XHCI_SLOW_SUSPEND;
if (device_property_read_bool(tmpdev, "xhci-trb-ent-quirk"))
xhci->quirks |= XHCI_TRB_ENT_QUIRK;
device_property_read_u32(tmpdev, "imod-interval-ns",
&xhci->imod_interval);
}

View File

@@ -3166,6 +3166,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
bool more_trbs_coming = true;
bool need_zero_pkt = false;
bool first_trb = true;
bool en_trb_ent = true;
unsigned int num_trbs;
unsigned int start_cycle, num_sgs = 0;
unsigned int enqd_len, block_len, trb_buff_len, full_len;
@@ -3202,6 +3203,13 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (urb->transfer_flags & URB_ZERO_PACKET && urb_priv->num_tds > 1)
need_zero_pkt = true;
/*
* Don't enable the ENT flag in the TRB if
* the EP support bulk streaming protocol.
*/
if (urb->stream_id)
en_trb_ent = false;
td = &urb_priv->td[0];
/*
@@ -3230,6 +3238,13 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
first_trb = false;
if (start_cycle == 0)
field |= TRB_CYCLE;
/*
* Don't enable the ENT flag in the TRB if the
* transfer length of the first TRB isn't an
* integer multiple of the EP maxpacket.
*/
if (trb_buff_len % usb_endpoint_maxp(&urb->ep->desc))
en_trb_ent = false;
} else
field |= ring->cycle_state;
@@ -3238,6 +3253,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
*/
if (enqd_len + trb_buff_len < full_len) {
field |= TRB_CHAIN;
if (xhci->quirks & XHCI_TRB_ENT_QUIRK && en_trb_ent)
field |= TRB_ENT;
if (trb_is_link(ring->enqueue + 1)) {
if (xhci_align_td(xhci, urb, enqd_len,
&trb_buff_len,

View File

@@ -1852,6 +1852,7 @@ struct xhci_hcd {
#define XHCI_ZERO_64B_REGS BIT_ULL(32)
#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
#define XHCI_TRB_ENT_QUIRK BIT_ULL(36)
unsigned int num_active_eps;
unsigned int limit_active_eps;