usb: dwc3: core: Add support for XHCI_SG_TRB_CACHE_SIZE_QUIRK

Message ID 20231121135936.1669167-1-quic_prashk@quicinc.com
State New
Headers
Series usb: dwc3: core: Add support for XHCI_SG_TRB_CACHE_SIZE_QUIRK |

Commit Message

Prashanth K Nov. 21, 2023, 1:59 p.m. UTC
  Upstream commit bac1ec551434 ("usb: xhci: Set quirk for
XHCI_SG_TRB_CACHE_SIZE_QUIRK") introduced a new quirk in XHCI
which fixes XHC timeout, which was seen on synopsys XHCs while
using SG buffers. But the support for this quirk isn't present
in the DWC3 layer.

We will encounter this XHCI timeout/hung issue if we run iperf
loopback tests using RTL8156 ethernet adaptor on DWC3 targets
with scatter-gather enabled. This gets resolved after enabling
the XHCI_SG_TRB_CACHE_SIZE_QUIRK. This patch enables it using
the xhci_priv_data since its needed for DWC3 controller.

In Synopsys DWC3 databook,
Table 9-3: xHCI Debug Capability Limitations
Chained TRBs greater than TRB cache size: The debug capability
driver must not create a multi-TRB TD that describes smaller
than a 1K packet that spreads across 8 or more TRBs on either
the IN TR or the OUT TR

More information about this XHCI quirk is mentioned on the
following thread.
https://lore.kernel.org/all/20201208092912.1773650-3-mathias.nyman@linux.intel.com/

Cc: <stable@vger.kernel.org> # 5.11
Fixes: bac1ec551434 ("usb: xhci: Set quirk for XHCI_SG_TRB_CACHE_SIZE_QUIRK")
Signed-off-by: Prashanth K <quic_prashk@quicinc.com>
---
 drivers/usb/dwc3/host.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
  

Comments

Prashanth K Nov. 27, 2023, 8:58 a.m. UTC | #1
On 21-11-23 07:29 pm, Prashanth K wrote:
>   drivers/usb/dwc3/host.c | 10 ++++++++++
>   1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
> index 61f57fe5bb78..ee3b667a88b2 100644
> --- a/drivers/usb/dwc3/host.c
> +++ b/drivers/usb/dwc3/host.c
> @@ -11,6 +11,7 @@
>   #include <linux/of.h>
>   #include <linux/platform_device.h>
>   
> +#include "../host/xhci-plat.h"
>   #include "core.h"
>   
>   static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
> @@ -63,6 +64,7 @@ int dwc3_host_init(struct dwc3 *dwc)
>   {
>   	struct property_entry	props[4];
>   	struct platform_device	*xhci;
> +	struct xhci_plat_priv   dwc3_xhci_plat_priv;
>   	int			ret, irq;
>   	int			prop_idx = 0;
>   
> @@ -87,6 +89,14 @@ int dwc3_host_init(struct dwc3 *dwc)
>   		goto err;
>   	}
>   
> +	memset(&dwc3_xhci_plat_priv, 0, sizeof(struct xhci_plat_priv));
> +
> +	dwc3_xhci_plat_priv.quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK;
> +	ret = platform_device_add_data(xhci, &dwc3_xhci_plat_priv,
> +					sizeof(dwc3_xhci_plat_priv));
> +	if (ret)
> +		goto err;
> +
>   	memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
>   
>   	if (dwc->usb3_lpm_capable)

Is the above approach acceptable? I'm not sure if accessing xhci-plat's 
structure from dwc3 is a recommended way. If not, then can we go ahead 
with the following approach where we add a property to XHCI SW node.


--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -89,6 +89,8 @@ int dwc3_host_init(struct dwc3 *dwc)

         memset(props, 0, sizeof(struct property_entry) * 
ARRAY_SIZE(props));

+       props[prop_idx++] = 
PROPERTY_ENTRY_BOOL("xhci-sg-trb-cache-size-quirk");
+
         if (dwc->usb3_lpm_capable)
                 props[prop_idx++] = 
PROPERTY_ENTRY_BOOL("usb3-lpm-capable");


--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -323,6 +323,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-sg-trb-cache-size-quirk"))
+                       xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK;
+
                 device_property_read_u32(tmpdev, "imod-interval-ns",
                                          &xhci->imod_interval);
         }


Regards,
Prashanth K
  
Prashanth K Dec. 12, 2023, 11:35 a.m. UTC | #2
On 27-11-23 02:28 pm, Prashanth K wrote:

> --- a/drivers/usb/dwc3/host.c
> +++ b/drivers/usb/dwc3/host.c
> @@ -89,6 +89,8 @@ int dwc3_host_init(struct dwc3 *dwc)
> 
>          memset(props, 0, sizeof(struct property_entry) * 
> ARRAY_SIZE(props));
> 
> +       props[prop_idx++] = 
> PROPERTY_ENTRY_BOOL("xhci-sg-trb-cache-size-quirk");
> +
>          if (dwc->usb3_lpm_capable)
>                  props[prop_idx++] = 
> PROPERTY_ENTRY_BOOL("usb3-lpm-capable");
> 
> 
> --- a/drivers/usb/host/xhci-plat.c
> +++ b/drivers/usb/host/xhci-plat.c
> @@ -323,6 +323,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-sg-trb-cache-size-quirk"))
> +                       xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK;
> +
>                  device_property_read_u32(tmpdev, "imod-interval-ns",
>                                           &xhci->imod_interval);
>          }
> 
> 
> Regards,
> Prashanth K
> 

Updated the patch by splitting it into a series of 2 patch-sets
https://lore.kernel.org/all/20231212112521.3774610-1-quic_prashk@quicinc.com/

Thanks,
Prashanth K
  

Patch

diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 61f57fe5bb78..ee3b667a88b2 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -11,6 +11,7 @@ 
 #include <linux/of.h>
 #include <linux/platform_device.h>
 
+#include "../host/xhci-plat.h"
 #include "core.h"
 
 static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
@@ -63,6 +64,7 @@  int dwc3_host_init(struct dwc3 *dwc)
 {
 	struct property_entry	props[4];
 	struct platform_device	*xhci;
+	struct xhci_plat_priv   dwc3_xhci_plat_priv;
 	int			ret, irq;
 	int			prop_idx = 0;
 
@@ -87,6 +89,14 @@  int dwc3_host_init(struct dwc3 *dwc)
 		goto err;
 	}
 
+	memset(&dwc3_xhci_plat_priv, 0, sizeof(struct xhci_plat_priv));
+
+	dwc3_xhci_plat_priv.quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK;
+	ret = platform_device_add_data(xhci, &dwc3_xhci_plat_priv,
+					sizeof(dwc3_xhci_plat_priv));
+	if (ret)
+		goto err;
+
 	memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
 
 	if (dwc->usb3_lpm_capable)