From 568d8472b3c2ab406fd3897e6b952c7a71a8165b Mon Sep 17 00:00:00 2001 From: Aditya Prayoga Date: Fri, 22 Jan 2021 19:12:09 +0700 Subject: [PATCH] Fix 2.5G Ethernet on Helios64 Mainline kernel (#2567) * rockchip64: Added XHCI HCD USB 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 prefetch the next TRB of a TD. Enable the quirk on RK3399 through device tree node properties. Ported from Rockchip Linux 4.19 * add to dev branch --- .../general-add-dwc3-xhci-usb-trb-quirk.patch | 145 ++++++++++++++++++ ...k3399-enable-dwc3-xhci-usb-trb-quirk.patch | 20 +++ .../general-add-dwc3-xhci-usb-trb-quirk.patch | 145 ++++++++++++++++++ ...k3399-enable-dwc3-xhci-usb-trb-quirk.patch | 20 +++ 4 files changed, 330 insertions(+) create mode 100644 patch/kernel/rockchip64-current/general-add-dwc3-xhci-usb-trb-quirk.patch create mode 100644 patch/kernel/rockchip64-current/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch create mode 100644 patch/kernel/rockchip64-dev/general-add-dwc3-xhci-usb-trb-quirk.patch create mode 100644 patch/kernel/rockchip64-dev/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch diff --git a/patch/kernel/rockchip64-current/general-add-dwc3-xhci-usb-trb-quirk.patch b/patch/kernel/rockchip64-current/general-add-dwc3-xhci-usb-trb-quirk.patch new file mode 100644 index 0000000000..9f76b3af2f --- /dev/null +++ b/patch/kernel/rockchip64-current/general-add-dwc3-xhci-usb-trb-quirk.patch @@ -0,0 +1,145 @@ +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 841daec70..48825b870 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1340,6 +1340,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) + "snps,dis-del-phy-power-chg-quirk"); + dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev, + "snps,dis-tx-ipgap-linecheck-quirk"); ++ dwc->xhci_trb_ent_quirk = device_property_read_bool(dev, ++ "snps,xhci-trb-ent-quirk"); + dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev, + "snps,parkmode-disable-ss-quirk"); + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 1b241f937..e1ded14fd 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -1049,6 +1049,9 @@ struct dwc3_scratchpad_array { + * change quirk. + * @dis_tx_ipgap_linecheck_quirk: set if we disable u2mac linestate + * check during HS transmit. ++ * @xhci_trb_ent_quirk: set if 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. + * @parkmode_disable_ss_quirk: set if we need to disable all SuperSpeed + * instances in park mode. + * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk +@@ -1245,6 +1248,7 @@ struct dwc3 { + unsigned dis_u2_freeclk_exists_quirk:1; + unsigned dis_del_phy_power_chg_quirk:1; + unsigned dis_tx_ipgap_linecheck_quirk:1; ++ unsigned xhci_trb_ent_quirk:1; + unsigned parkmode_disable_ss_quirk:1; + + unsigned tx_de_emphasis_quirk:1; +diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c +index e19517658..19d48703d 100644 +--- a/drivers/usb/dwc3/host.c ++++ b/drivers/usb/dwc3/host.c +@@ -44,7 +44,7 @@ static int dwc3_host_get_irq(struct dwc3 *dwc) + + int dwc3_host_init(struct dwc3 *dwc) + { +- struct property_entry props[4]; ++ struct property_entry props[5]; + struct platform_device *xhci; + int ret, irq; + struct resource *res; +@@ -92,6 +92,9 @@ int dwc3_host_init(struct dwc3 *dwc) + if (dwc->usb3_lpm_capable) + props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable"); + ++ if (dwc->xhci_trb_ent_quirk) ++ props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-trb-ent-quirk"); ++ + if (dwc->usb2_lpm_disable) + props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb2-lpm-disable"); + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index 4d34f6005..6972cb5b2 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -312,6 +312,9 @@ static int xhci_plat_probe(struct platform_device *pdev) + if (device_property_read_bool(tmpdev, "quirk-broken-port-ped")) + xhci->quirks |= XHCI_BROKEN_PORT_PED; + ++ 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); + } +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 167dae117..b1bc3bd03 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -3312,6 +3312,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; +@@ -3348,6 +3349,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]; + + /* +@@ -3376,6 +3384,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; + +@@ -3384,6 +3399,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, +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index d90c0d5df..b32b04d85 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1512,7 +1512,11 @@ static inline const char *xhci_trb_type_string(u8 type) + #define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT*16) + #define TRB_SEGMENT_SHIFT (ilog2(TRB_SEGMENT_SIZE)) + /* TRB buffer pointers can't cross 64KB boundaries */ ++#ifdef CONFIG_ARCH_ROCKCHIP ++#define TRB_MAX_BUFF_SHIFT 12 ++#else + #define TRB_MAX_BUFF_SHIFT 16 ++#endif + #define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT) + /* How much data is left before the 64KB boundary? */ + #define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_BUFF_SIZE - \ +@@ -1879,6 +1883,7 @@ struct xhci_hcd { + #define XHCI_SKIP_PHY_INIT BIT_ULL(37) + #define XHCI_DISABLE_SPARSE BIT_ULL(38) + #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) ++#define XHCI_TRB_ENT_QUIRK BIT_ULL(40) + + unsigned int num_active_eps; + unsigned int limit_active_eps; diff --git a/patch/kernel/rockchip64-current/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch b/patch/kernel/rockchip64-current/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch new file mode 100644 index 0000000000..be76facca9 --- /dev/null +++ b/patch/kernel/rockchip64-current/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch @@ -0,0 +1,20 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index bcd31e9d6..91f1aa809 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -425,6 +425,7 @@ usbdrd_dwc3_0: usb@fe800000 { + snps,dis_u2_susphy_quirk; + snps,dis-del-phy-power-chg-quirk; + snps,dis-tx-ipgap-linecheck-quirk; ++ snps,xhci-trb-ent-quirk; + power-domains = <&power RK3399_PD_USB3>; + status = "disabled"; + }; +@@ -461,6 +462,7 @@ usbdrd_dwc3_1: usb@fe900000 { + snps,dis_u2_susphy_quirk; + snps,dis-del-phy-power-chg-quirk; + snps,dis-tx-ipgap-linecheck-quirk; ++ snps,xhci-trb-ent-quirk; + power-domains = <&power RK3399_PD_USB3>; + status = "disabled"; + }; diff --git a/patch/kernel/rockchip64-dev/general-add-dwc3-xhci-usb-trb-quirk.patch b/patch/kernel/rockchip64-dev/general-add-dwc3-xhci-usb-trb-quirk.patch new file mode 100644 index 0000000000..9f76b3af2f --- /dev/null +++ b/patch/kernel/rockchip64-dev/general-add-dwc3-xhci-usb-trb-quirk.patch @@ -0,0 +1,145 @@ +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 841daec70..48825b870 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1340,6 +1340,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) + "snps,dis-del-phy-power-chg-quirk"); + dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev, + "snps,dis-tx-ipgap-linecheck-quirk"); ++ dwc->xhci_trb_ent_quirk = device_property_read_bool(dev, ++ "snps,xhci-trb-ent-quirk"); + dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev, + "snps,parkmode-disable-ss-quirk"); + +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 1b241f937..e1ded14fd 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -1049,6 +1049,9 @@ struct dwc3_scratchpad_array { + * change quirk. + * @dis_tx_ipgap_linecheck_quirk: set if we disable u2mac linestate + * check during HS transmit. ++ * @xhci_trb_ent_quirk: set if 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. + * @parkmode_disable_ss_quirk: set if we need to disable all SuperSpeed + * instances in park mode. + * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk +@@ -1245,6 +1248,7 @@ struct dwc3 { + unsigned dis_u2_freeclk_exists_quirk:1; + unsigned dis_del_phy_power_chg_quirk:1; + unsigned dis_tx_ipgap_linecheck_quirk:1; ++ unsigned xhci_trb_ent_quirk:1; + unsigned parkmode_disable_ss_quirk:1; + + unsigned tx_de_emphasis_quirk:1; +diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c +index e19517658..19d48703d 100644 +--- a/drivers/usb/dwc3/host.c ++++ b/drivers/usb/dwc3/host.c +@@ -44,7 +44,7 @@ static int dwc3_host_get_irq(struct dwc3 *dwc) + + int dwc3_host_init(struct dwc3 *dwc) + { +- struct property_entry props[4]; ++ struct property_entry props[5]; + struct platform_device *xhci; + int ret, irq; + struct resource *res; +@@ -92,6 +92,9 @@ int dwc3_host_init(struct dwc3 *dwc) + if (dwc->usb3_lpm_capable) + props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable"); + ++ if (dwc->xhci_trb_ent_quirk) ++ props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-trb-ent-quirk"); ++ + if (dwc->usb2_lpm_disable) + props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb2-lpm-disable"); + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index 4d34f6005..6972cb5b2 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -312,6 +312,9 @@ static int xhci_plat_probe(struct platform_device *pdev) + if (device_property_read_bool(tmpdev, "quirk-broken-port-ped")) + xhci->quirks |= XHCI_BROKEN_PORT_PED; + ++ 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); + } +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index 167dae117..b1bc3bd03 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -3312,6 +3312,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; +@@ -3348,6 +3349,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]; + + /* +@@ -3376,6 +3384,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; + +@@ -3384,6 +3399,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, +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index d90c0d5df..b32b04d85 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1512,7 +1512,11 @@ static inline const char *xhci_trb_type_string(u8 type) + #define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT*16) + #define TRB_SEGMENT_SHIFT (ilog2(TRB_SEGMENT_SIZE)) + /* TRB buffer pointers can't cross 64KB boundaries */ ++#ifdef CONFIG_ARCH_ROCKCHIP ++#define TRB_MAX_BUFF_SHIFT 12 ++#else + #define TRB_MAX_BUFF_SHIFT 16 ++#endif + #define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT) + /* How much data is left before the 64KB boundary? */ + #define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_BUFF_SIZE - \ +@@ -1879,6 +1883,7 @@ struct xhci_hcd { + #define XHCI_SKIP_PHY_INIT BIT_ULL(37) + #define XHCI_DISABLE_SPARSE BIT_ULL(38) + #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) ++#define XHCI_TRB_ENT_QUIRK BIT_ULL(40) + + unsigned int num_active_eps; + unsigned int limit_active_eps; diff --git a/patch/kernel/rockchip64-dev/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch b/patch/kernel/rockchip64-dev/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch new file mode 100644 index 0000000000..be76facca9 --- /dev/null +++ b/patch/kernel/rockchip64-dev/rk3399-enable-dwc3-xhci-usb-trb-quirk.patch @@ -0,0 +1,20 @@ +diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +index bcd31e9d6..91f1aa809 100644 +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -425,6 +425,7 @@ usbdrd_dwc3_0: usb@fe800000 { + snps,dis_u2_susphy_quirk; + snps,dis-del-phy-power-chg-quirk; + snps,dis-tx-ipgap-linecheck-quirk; ++ snps,xhci-trb-ent-quirk; + power-domains = <&power RK3399_PD_USB3>; + status = "disabled"; + }; +@@ -461,6 +462,7 @@ usbdrd_dwc3_1: usb@fe900000 { + snps,dis_u2_susphy_quirk; + snps,dis-del-phy-power-chg-quirk; + snps,dis-tx-ipgap-linecheck-quirk; ++ snps,xhci-trb-ent-quirk; + power-domains = <&power RK3399_PD_USB3>; + status = "disabled"; + };