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
This commit is contained in:
parent
63e0a1ec08
commit
568d8472b3
@ -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;
|
||||
@ -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";
|
||||
};
|
||||
@ -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;
|
||||
@ -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";
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user