diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 43988036ecae..334c17e32843 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -57,6 +57,14 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdata && pdata->usb3_warm_reset_on_resume) xhci->quirks |= XHCI_WARM_RESET_ON_RESUME; + + /* + * 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. + */ + if (pdata && pdata->xhci_trb_ent) + xhci->quirks |= XHCI_TRB_ENT_QUIRK; } /* called during probe() after chip reset completes */ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4de1cd1dcf57..e5e4a20aa5e9 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3301,6 +3301,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, */ if (num_trbs > last_trb_num) { field |= TRB_CHAIN; + if (xhci->quirks & XHCI_TRB_ENT_QUIRK) + field |= TRB_ENT; } else if (num_trbs == last_trb_num) { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; @@ -3477,6 +3479,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, */ if (num_trbs > last_trb_num) { field |= TRB_CHAIN; + if (xhci->quirks & XHCI_TRB_ENT_QUIRK) + field |= TRB_ENT; } else if (num_trbs == last_trb_num) { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 21cf26b21c73..da4544eeac8e 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1828,6 +1828,7 @@ struct xhci_hcd { #define XHCI_DIS_AUTOSUSPEND (1 << 21) #define XHCI_MISSING_CAS (1 << 24) #define XHCI_WARM_RESET_ON_RESUME (1 << 25) +#define XHCI_TRB_ENT_QUIRK (1 << 26) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ diff --git a/include/linux/usb/xhci_pdriver.h b/include/linux/usb/xhci_pdriver.h index 5df42af8a404..11d813d2bcdc 100644 --- a/include/linux/usb/xhci_pdriver.h +++ b/include/linux/usb/xhci_pdriver.h @@ -21,6 +21,9 @@ * @xhci_slow_suspend: set if this xhci platform need an extraordinary * delay to wait for xHC enter the Halted state * after the Run/Stop (R/S) bit is cleared to '0'. + * @xhci_trb_ent: set if this xhci platform need to enable the Evaluate + * Next TRB(ENT) flag in the TRB data structure to force + * xHC to pre-fetch the next TRB of a TD. * @usb3_disable_autosuspend: determines if this xhci platform supports * USB3 autosuspend capability * @usb3_warm_reset_on_resume: determines if it need warm reset on resume. @@ -29,6 +32,7 @@ struct usb_xhci_pdata { unsigned usb3_lpm_capable:1; unsigned xhci_slow_suspend:1; + unsigned xhci_trb_ent:1; unsigned usb3_disable_autosuspend:1; unsigned usb3_warm_reset_on_resume:1; };