Skip to contentSkip to conversation

Add logic to consolidate TRBs for Synopsys xHC

PATCH In review Tejas Joglekar 5 participants 13 messages Nov 23, 2020 – Jan 8, 2021

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v6 cover Add logic to consolidate TRBs for Synopsys xHC

The Synopsys xHC has an internal TRB cache of size TRB_CACHE_SIZE for each endpoint. The default value for TRB_CACHE_SIZE is 16 for SS and 8 for HS. The controller loads and updates the TRB cache from the transfer ring in system memory whenever the driver issues a start transfer or update transfer command.

For chained TRBs, the Synopsys xHC requires that the total amount of bytes for all TRBs loaded in the TRB cache be greater than or equal to 1 MPS. Or the chain ends within the TRB cache (with a last TRB).

If this requirement is not met, the controller will not be able to send or receive a packet and it will hang causing a driver timeout and error.

This patch set adds logic to the XHCI driver to detect and prevent this from happening along with the quirk to enable this logic for Synopsys HAPS platform.

Based on Mathias's feedback on previous implementation where consolidation was done in TRB cache, with this patch series the implementation is done during mapping of the URB by consolidating the SG list into a temporary buffer if the SG list buffer sizes within TRB_CACHE_SIZE is less than MPS.

Changes since v5:
- Update the quirk macro to have next number [Patch 1/3]
- Fixed the issues reported by kernel test robot [Patch 2/3]

Changes since v4:
- Updated [Patch 3/3] platform data structure initialization
- Trivial changes in commit wordings

Changes since v3:
- Removed the dt-binding patch
- Added new patch to pass the quirk as platform data
- Modified the patch to set the quirk

Changes since v2:
- Modified the xhci_unmap_temp_buffer function to unmap dma and c the dma flag
- Removed RFC tag

Changes since v1:
- Comments from Greg are addressed on [PATCH 4/4] and [PATCH 1/4]
- Renamed the property and quirk as in other patches based on [PATCH 1/4]

Tejas Joglekar (3):
usb: xhci: Set quirk for XHCI_SG_TRB_CACHE_SIZE_QUIRK
usb: xhci: Use temporary buffer to consolidate SG
usb: dwc3: Pass quirk as platform data

 drivers/usb/dwc3/host.c      |  10 +++
 drivers/usb/host/xhci-plat.c |   3 +
 drivers/usb/host/xhci-ring.c |   2 +-
 drivers/usb/host/xhci.c      | 129 ++++++++++++++++++++++++++++++++++-
 drivers/usb/host/xhci.h      |   5 ++
 5 files changed, 147 insertions(+), 2 deletions(-)
Signature · 1 line
2.28.0
#1 lore raw

PATCH v6 1/3 usb: xhci: Set quirk for XHCI_SG_TRB_CACHE_SIZE_QUIRK

This commit uses the private data passed by parent device to set the quirk for Synopsys xHC. This patch fixes the SNPS xHC hang issue when the data is scattered across small buffers which does not make atleast MPS size for given TRB cache size of SNPS xHC.

---
 drivers/usb/host/xhci-plat.c | 3 +++
 drivers/usb/host/xhci.h      | 1 +
 2 files changed, 4 insertions(+)
drivers/usb/host/xhci-plat.c +3 -0
index aa2d35f98200..4d34f6005381 100644
@@ -333,6 +333,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
 	if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT))
 		hcd->skip_phy_initialization = 1;
 
+	if (priv && (priv->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK))
+		xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK;
+
 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (ret)
 		goto disable_usb_phy;
drivers/usb/host/xhci.h +1 -0
index ebb359ebb261..d90c0d5df3b3 100644
@@ -1878,6 +1878,7 @@ struct xhci_hcd {
 #define XHCI_RENESAS_FW_QUIRK	BIT_ULL(36)
 #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)
 
 	unsigned int		num_active_eps;
 	unsigned int		limit_active_eps;
Signature · 1 line
2.28.0
#2 lore raw

PATCH v6 2/3 usb: xhci: Use temporary buffer to consolidate SG

In reply to Tejas Joglekar

The Synopsys xHC has an internal TRB cache of size TRB_CACHE_SIZE for each endpoint. The default value for TRB_CACHE_SIZE is 16 for SS and 8 for HS. The controller loads and updates the TRB cache from the transfer ring in system memory whenever the driver issues a start transfer or update transfer command.

For chained TRBs, the Synopsys xHC requires that the total amount of bytes for all TRBs loaded in the TRB cache be greater than or equal to 1 MPS. Or the chain ends within the TRB cache (with a last TRB).

If this requirement is not met, the controller will not be able to send or receive a packet and it will hang causing a driver timeout and error.

This can be a problem if a class driver queues SG requests with many small-buffer entries. The XHCI driver will create a chained TRB for each entry which may trigger this issue.

This patch adds logic to the XHCI driver to detect and prevent this from happening.

For every (TRB_CACHE_SIZE - 2), we check the total buffer size of the SG list and if the last window of (TRB_CACHE_SIZE - 2) SG list length and we don't make up at least 1 MPS, we create a temporary buffer to consolidate full SG list into the buffer.

We check at (TRB_CACHE_SIZE - 2) window because it is possible that there would be a link and/or event data TRB that take up to 2 of the cache entries.

We discovered this issue with devices on other platforms but have not yet come across any device that triggers this on Linux. But it could be a real problem now or in the future. All it takes is N number of small chained TRBs. And other instances of the Synopsys IP may have smaller values for the TRB_CACHE_SIZE which would exacerbate the problem.

---
 drivers/usb/host/xhci-ring.c |   2 +-
 drivers/usb/host/xhci.c      | 129 ++++++++++++++++++++++++++++++++++-
 drivers/usb/host/xhci.h      |   4 ++
 3 files changed, 133 insertions(+), 2 deletions(-)
drivers/usb/host/xhci-ring.c +1 -1
index 167dae117f73..6d4dae5e5f21 100644
@@ -3325,7 +3325,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
 	full_len = urb->transfer_buffer_length;
 	/* If we have scatter/gather list, we use it. */
-	if (urb->num_sgs) {
+	if (urb->num_sgs && !(urb->transfer_flags & URB_DMA_MAP_SINGLE)) {
 		num_sgs = urb->num_mapped_sgs;
 		sg = urb->sg;
 		addr = (u64) sg_dma_address(sg);
drivers/usb/host/xhci.c +128 -1

153 lines not on this page · raw message

drivers/usb/host/xhci.h +4 -0
index d90c0d5df3b3..25e57bc9c3cc 100644
@@ -1330,6 +1330,10 @@ enum xhci_setup_dev {
 #define TRB_SIA			(1<<31)
 #define TRB_FRAME_ID(p)		(((p) & 0x7ff) << 20)
 
+/* TRB cache size for xHC with TRB cache */
+#define TRB_CACHE_SIZE_HS	8
+#define TRB_CACHE_SIZE_SS	16
+
 struct xhci_generic_trb {
 	__le32 field[4];
 };
Signature · 1 line
2.28.0
#3 lore raw

Re: [PATCH v6 2/3] usb: xhci: Use temporary buffer to consolidate SG

On 2020/11/24 0:38, Tejas Joglekar Wrote:

Quoted 10 lines

The Synopsys xHC has an internal TRB cache of size TRB_CACHE_SIZE for each endpoint. The default value for TRB_CACHE_SIZE is 16 for SS and 8 for HS. The controller loads and updates the TRB cache from the transfer ring in system memory whenever the driver issues a start transfer or update transfer command.

For chained TRBs, the Synopsys xHC requires that the total amount of bytes for all TRBs loaded in the TRB cache be greater than or equal to 1 MPS. Or the chain ends within the TRB cache (with a last TRB).

Is there a similar problem on Synopsys ehci controller?
Because of the TRB cache,the EHCI controller's Next Link queue head is NULL.

Quoted 220 lines

If this requirement is not met, the controller will not be able to send or receive a packet and it will hang causing a driver timeout and error.

This can be a problem if a class driver queues SG requests with many small-buffer entries. The XHCI driver will create a chained TRB for each entry which may trigger this issue.

This patch adds logic to the XHCI driver to detect and prevent this from happening.

For every (TRB_CACHE_SIZE - 2), we check the total buffer size of the SG list and if the last window of (TRB_CACHE_SIZE - 2) SG list length and we don't make up at least 1 MPS, we create a temporary buffer to consolidate full SG list into the buffer.

We check at (TRB_CACHE_SIZE - 2) window because it is possible that there would be a link and/or event data TRB that take up to 2 of the cache entries.

We discovered this issue with devices on other platforms but have not yet come across any device that triggers this on Linux. But it could be a real problem now or in the future. All it takes is N number of small chained TRBs. And other instances of the Synopsys IP may have smaller values for the TRB_CACHE_SIZE which would exacerbate the problem.

---
 drivers/usb/host/xhci-ring.c |   2 +-
 drivers/usb/host/xhci.c      | 129 ++++++++++++++++++++++++++++++++++-
 drivers/usb/host/xhci.h      |   4 ++
 3 files changed, 133 insertions(+), 2 deletions(-)
drivers/usb/host/xhci-ring.c +1 -1
index 167dae117f73..6d4dae5e5f21 100644
@@ -3325,7 +3325,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
 	full_len = urb->transfer_buffer_length;
 	/* If we have scatter/gather list, we use it. */
-	if (urb->num_sgs) {
+	if (urb->num_sgs && !(urb->transfer_flags & URB_DMA_MAP_SINGLE)) {
 		num_sgs = urb->num_mapped_sgs;
 		sg = urb->sg;
 		addr = (u64) sg_dma_address(sg);
drivers/usb/host/xhci.c +128 -1
index d4a8d0efbbc4..5b0b5f1bb40d 100644
@@ -1259,6 +1259,108 @@ EXPORT_SYMBOL_GPL(xhci_resume);
 
 /*-------------------------------------------------------------------------*/
 
+static int xhci_map_temp_buffer(struct usb_hcd *hcd, struct urb *urb)
+{
+	void *temp;
+	int ret = 0;
+	unsigned int buf_len;
+	enum dma_data_direction dir;
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	buf_len = urb->transfer_buffer_length;
+
+	temp = kzalloc_node(buf_len, GFP_ATOMIC,
+			    dev_to_node(hcd->self.sysdev));
+
+	if (usb_urb_dir_out(urb))
+		sg_pcopy_to_buffer(urb->sg, urb->num_sgs,
+				   temp, buf_len, 0);
+
+	urb->transfer_buffer = temp;
+	urb->transfer_dma = dma_map_single(hcd->self.sysdev,
+					   urb->transfer_buffer,
+					   urb->transfer_buffer_length,
+					   dir);
+
+	if (dma_mapping_error(hcd->self.sysdev,
+			      urb->transfer_dma)) {
+		ret = -EAGAIN;
+		kfree(temp);
+	} else {
+		urb->transfer_flags |= URB_DMA_MAP_SINGLE;
+	}
+
+	return ret;
+}
+
+static bool xhci_urb_temp_buffer_required(struct usb_hcd *hcd,
+					  struct urb *urb)
+{
+	bool ret = false;
+	unsigned int i;
+	unsigned int len = 0;
+	unsigned int trb_size;
+	unsigned int max_pkt;
+	struct scatterlist *sg;
+	struct scatterlist *tail_sg;
+
+	tail_sg = urb->sg;
+	max_pkt = usb_endpoint_maxp(&urb->ep->desc);
+
+	if (!urb->num_sgs)
+		return ret;
+
+	if (urb->dev->speed >= USB_SPEED_SUPER)
+		trb_size = TRB_CACHE_SIZE_SS;
+	else
+		trb_size = TRB_CACHE_SIZE_HS;
+
+	if (urb->transfer_buffer_length != 0 &&
+	    !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+		for_each_sg(urb->sg, sg, urb->num_sgs, i) {
+			len = len + sg->length;
+			if (i > trb_size - 2) {
+				len = len - tail_sg->length;
+				if (len < max_pkt) {
+					ret = true;
+					break;
+				}
+
+				tail_sg = sg_next(tail_sg);
+			}
+		}
+	}
+	return ret;
+}
+
+static void xhci_unmap_temp_buf(struct usb_hcd *hcd, struct urb *urb)
+{
+	unsigned int len;
+	unsigned int buf_len;
+	enum dma_data_direction dir;
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	buf_len = urb->transfer_buffer_length;
+
+	if (IS_ENABLED(CONFIG_HAS_DMA) &&
+	    (urb->transfer_flags & URB_DMA_MAP_SINGLE))
+		dma_unmap_single(hcd->self.sysdev,
+				 urb->transfer_dma,
+				 urb->transfer_buffer_length,
+				 dir);
+
+	if (usb_urb_dir_in(urb))
+		len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs,
+					   urb->transfer_buffer,
+					   buf_len,
+					   0);
+
+	urb->transfer_flags &= ~URB_DMA_MAP_SINGLE;
+	kfree(urb->transfer_buffer);
+	urb->transfer_buffer = NULL;
+}
+
 /*
  * Bypass the DMA mapping if URB is suitable for Immediate Transfer (IDT),
  * we'll copy the actual data into the TRB address register. This is limited to
@@ -1268,13 +1370,37 @@ EXPORT_SYMBOL_GPL(xhci_resume);
 static int xhci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
 				gfp_t mem_flags)
 {
+	struct xhci_hcd *xhci;
+
+	xhci = hcd_to_xhci(hcd);
+
 	if (xhci_urb_suitable_for_idt(urb))
 		return 0;
 
+	if (xhci->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK) {
+		if (xhci_urb_temp_buffer_required(hcd, urb))
+			return xhci_map_temp_buffer(hcd, urb);
+	}
 	return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
 }
 
-/*
+static void xhci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+	struct xhci_hcd *xhci;
+	bool unmap_temp_buf = false;
+
+	xhci = hcd_to_xhci(hcd);
+
+	if (urb->num_sgs && (urb->transfer_flags & URB_DMA_MAP_SINGLE))
+		unmap_temp_buf = true;
+
+	if ((xhci->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK) && unmap_temp_buf)
+		xhci_unmap_temp_buf(hcd, urb);
+	else
+		usb_hcd_unmap_urb_for_dma(hcd, urb);
+}
+
+/**
  * xhci_get_endpoint_index - Used for passing endpoint bitmasks between the core and
  * HCDs.  Find the index for an endpoint given its descriptor.  Use the return
  * value to right shift 1 for the bitmask.
@@ -5329,6 +5455,7 @@ static const struct hc_driver xhci_hc_driver = {
 	 * managing i/o requests and associated device resources
 	 */
 	.map_urb_for_dma =      xhci_map_urb_for_dma,
+	.unmap_urb_for_dma =    xhci_unmap_urb_for_dma,
 	.urb_enqueue =		xhci_urb_enqueue,
 	.urb_dequeue =		xhci_urb_dequeue,
 	.alloc_dev =		xhci_alloc_dev,
drivers/usb/host/xhci.h +4 -0
index d90c0d5df3b3..25e57bc9c3cc 100644
@@ -1330,6 +1330,10 @@ enum xhci_setup_dev {
 #define TRB_SIA			(1<<31)
 #define TRB_FRAME_ID(p)		(((p) & 0x7ff) << 20)
 
+/* TRB cache size for xHC with TRB cache */
+#define TRB_CACHE_SIZE_HS	8
+#define TRB_CACHE_SIZE_SS	16
+
 struct xhci_generic_trb {
 	__le32 field[4];
 };
Quoted 1 line

Thanks,

Liu Longfang

#4 lore raw

PATCH v6 3/3 usb: dwc3: Pass quirk as platform data

In reply to Tejas Joglekar

This commit adds the platform device data to setup the XHCI_SG_TRB_CACHE_SIZE_QUIRK quirk. DWC3 hosts which are PCI devices does not use OF to create platform device but create xhci-plat platform device at runtime. So this patch allows parent device to supply the quirk through platform data.

---
 drivers/usb/dwc3/host.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
drivers/usb/dwc3/host.c +10 -0
index e195176580de..0434bc8cec12 100644
@@ -11,6 +11,11 @@
 #include <linux/platform_device.h>
 
 #include "core.h"
+#include "../host/xhci-plat.h"
+
+static const struct xhci_plat_priv dwc3_pdata = {
+	.quirks = XHCI_SG_TRB_CACHE_SIZE_QUIRK,
+};
 
 static int dwc3_host_get_irq(struct dwc3 *dwc)
 {
@@ -87,6 +92,11 @@ int dwc3_host_init(struct dwc3 *dwc)
 		goto err;
 	}
 
+	ret = platform_device_add_data(xhci, &dwc3_pdata, sizeof(dwc3_pdata));
+	if (ret) {
+		dev_err(dwc->dev, "couldn't add platform data to xHCI device\n");
+		goto err;
+	}
 	memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));
 
 	if (dwc->usb3_lpm_capable)
Signature · 1 line
2.28.0
#5 lore raw

Re: [RESEND PATCH v6 3/3] usb: dwc3: Pass quirk as platform data

Quoted 11 lines · Tejas Joglekar

This commit adds the platform device data to setup the XHCI_SG_TRB_CACHE_SIZE_QUIRK quirk. DWC3 hosts which are PCI devices does not use OF to create platform device but create xhci-plat platform device at runtime. So this patch allows parent device to supply the quirk through platform data.

---
 drivers/usb/dwc3/host.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

What changed from previous versions?

drivers/usb/dwc3/host.c line 14

Quoted 10 lines
drivers/usb/dwc3/host.c +1 -0
index e195176580de..0434bc8cec12 100644
@@ -11,6 +11,11 @@
 #include <linux/platform_device.h>
 
 #include "core.h"
+#include "../host/xhci-plat.h"

That feels really wrong. Are you sure about that?

thanks,

greg k-h

#6 lore raw

Re: [RESEND PATCH v6 3/3] usb: dwc3: Pass quirk as platform data

Hi Greg,

Quoted 8 lines · Greg Kroah-Hartman
Quoted 7 lines · Tejas Joglekar

This commit adds the platform device data to setup the XHCI_SG_TRB_CACHE_SIZE_QUIRK quirk. DWC3 hosts which are PCI devices does not use OF to create platform device but create xhci-plat platform device at runtime. So this patch allows parent device to supply the quirk through platform data.

Quoted 5 lines
Quoted 4 lines
---
 drivers/usb/dwc3/host.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

What changed from previous versions?

Resent the patch as it was missed for review by Felipe and I saw your mail

to resend the patch if not reviewed. Other two patches from series are

picked up by Mathias, this one is remaining for review.

Quoted 11 lines

drivers/usb/dwc3/host.c line 14

Quoted 10 lines
drivers/usb/dwc3/host.c +1 -0
index e195176580de..0434bc8cec12 100644
@@ -11,6 +11,11 @@
 #include <linux/platform_device.h>
 
 #include "core.h"
+#include "../host/xhci-plat.h"

That feels really wrong. Are you sure about that?

To use the struct xhci_plat_priv this was included, can you suggest alternative?

Quoted 4 lines

thanks,

greg k-h

Thanks & Regards,

 Tejas Joglekar

#7 lore raw

Re: [RESEND PATCH v6 3/3] usb: dwc3: Pass quirk as platform data

Quoted 14 lines · Tejas Joglekar

Hi Greg,

Quoted 12 lines · Greg Kroah-Hartman
Quoted 11 lines · Tejas Joglekar

This commit adds the platform device data to setup the XHCI_SG_TRB_CACHE_SIZE_QUIRK quirk. DWC3 hosts which are PCI devices does not use OF to create platform device but create xhci-plat platform device at runtime. So this patch allows parent device to supply the quirk through platform data.

---
 drivers/usb/dwc3/host.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
Quoted 7 lines
Quoted 1 line

What changed from previous versions?

Resent the patch as it was missed for review by Felipe and I saw your mail

to resend the patch if not reviewed. Other two patches from series are

picked up by Mathias, this one is remaining for review.

Ah, how was I supposed to guess that? :)

Quoted 11 lines
Quoted 10 lines

drivers/usb/dwc3/host.c line 14

Quoted 9 lines
drivers/usb/dwc3/host.c +1 -0
index e195176580de..0434bc8cec12 100644
@@ -11,6 +11,11 @@
 #include <linux/platform_device.h>
 
 #include "core.h"
+#include "../host/xhci-plat.h"

That feels really wrong. Are you sure about that?

To use the struct xhci_plat_priv this was included, can you suggest alternative?

If that is the "normal" way to do this with the xhci driver, ok, but I would like to get an ack from Mathias for this before taking it.

thanks,

greg k-h

#8 lore raw

Re: [RESEND PATCH v6 3/3] usb: dwc3: Pass quirk as platform data

Hi Mathias,

Quoted 30 lines · Greg Kroah-Hartman
Quoted 14 lines · Tejas Joglekar

Hi Greg,

Quoted 12 lines · Greg Kroah-Hartman
Quoted 11 lines · Tejas Joglekar

This commit adds the platform device data to setup the XHCI_SG_TRB_CACHE_SIZE_QUIRK quirk. DWC3 hosts which are PCI devices does not use OF to create platform device but create xhci-plat platform device at runtime. So this patch allows parent device to supply the quirk through platform data.

---
 drivers/usb/dwc3/host.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
Quoted 6 lines
Quoted 1 line

What changed from previous versions?

Resent the patch as it was missed for review by Felipe and I saw your mail

to resend the patch if not reviewed. Other two patches from series are

picked up by Mathias, this one is remaining for review.

Ah, how was I supposed to guess that? :)

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/usb/dwc3/host.c +0 -0
index e195176580de..0434bc8cec12 100644
@@ -11,6 +11,11 @@
 #include <linux/platform_device.h>
 
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines

drivers/usb/dwc3/host.c line 14

Quoted 2 lines
drivers/usb/dwc3/host.c +1 -0
 #include "core.h"
+#include "../host/xhci-plat.h"

That feels really wrong. Are you sure about that?

To use the struct xhci_plat_priv this was included, can you suggest alternative?

If that is the "normal" way to do this with the xhci driver, ok, but I would like to get an ack from Mathias for this before taking it.

Can you please review this patch which is including the xhci-plat header?  Let me

know if anything should be modified. Ack if this patch looks ok so Greg can

take it.

Quoted 3 lines

thanks,

greg k-h

#9 lore raw

Re: [RESEND PATCH v6 3/3] usb: dwc3: Pass quirk as platform data

Quoted 36 lines · Tejas Joglekar

Hi Mathias,

Quoted 34 lines · Greg Kroah-Hartman
Quoted 14 lines · Tejas Joglekar

Hi Greg,

Quoted 12 lines · Greg Kroah-Hartman
Quoted 11 lines · Tejas Joglekar

This commit adds the platform device data to setup the XHCI_SG_TRB_CACHE_SIZE_QUIRK quirk. DWC3 hosts which are PCI devices does not use OF to create platform device but create xhci-plat platform device at runtime. So this patch allows parent device to supply the quirk through platform data.

---
 drivers/usb/dwc3/host.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
Quoted 6 lines
Quoted 1 line

What changed from previous versions?

Resent the patch as it was missed for review by Felipe and I saw your mail

to resend the patch if not reviewed. Other two patches from series are

picked up by Mathias, this one is remaining for review.

Ah, how was I supposed to guess that? :)

Quoted 11 lines
Quoted 10 lines

drivers/usb/dwc3/host.c line 14

Quoted 9 lines
drivers/usb/dwc3/host.c +1 -0
index e195176580de..0434bc8cec12 100644
@@ -11,6 +11,11 @@
 #include <linux/platform_device.h>
 
 #include "core.h"
+#include "../host/xhci-plat.h"

That feels really wrong. Are you sure about that?

To use the struct xhci_plat_priv this was included, can you suggest alternative?

Quoted 9 lines
Quoted 3 lines

If that is the "normal" way to do this with the xhci driver, ok, but I would like to get an ack from Mathias for this before taking it.

Can you please review this patch which is including the xhci-plat header?  Let me

know if anything should be modified. Ack if this patch looks ok so Greg can

take it.

This doesn't look right.

dwc3 shouldn't need to know about xhci platform private structures, besides, this patch now adds the quirk to all xhci platform devices created by dwc3.

I haven't touched dwc3 at all, but I'd guess you probably need to add a new entry to the dwc3_pci_id_table[] in dwc3-pci.c, add a device property, and then look for that property in xhci-plat.c, and set the quirk.

-Mathias

#10 lore raw

Re: [RESEND PATCH v6 3/3] usb: dwc3: Pass quirk as platform data

Quoted 42 lines · Mathias Nyman
Quoted 41 lines · Tejas Joglekar

Hi Mathias,

Quoted 30 lines · Greg Kroah-Hartman
Quoted 14 lines · Tejas Joglekar

Hi Greg,

Quoted 12 lines · Greg Kroah-Hartman
Quoted 11 lines · Tejas Joglekar

This commit adds the platform device data to setup the XHCI_SG_TRB_CACHE_SIZE_QUIRK quirk. DWC3 hosts which are PCI devices does not use OF to create platform device but create xhci-plat platform device at runtime. So this patch allows parent device to supply the quirk through platform data.

---
 drivers/usb/dwc3/host.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
Quoted 6 lines
Quoted 1 line

What changed from previous versions?

Resent the patch as it was missed for review by Felipe and I saw your mail

to resend the patch if not reviewed. Other two patches from series are

picked up by Mathias, this one is remaining for review.

Ah, how was I supposed to guess that? :)

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/usb/dwc3/host.c +0 -0
index e195176580de..0434bc8cec12 100644
@@ -11,6 +11,11 @@
 #include <linux/platform_device.h>
 
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines

drivers/usb/dwc3/host.c line 14

Quoted 2 lines
drivers/usb/dwc3/host.c +1 -0
 #include "core.h"
+#include "../host/xhci-plat.h"

That feels really wrong. Are you sure about that?

To use the struct xhci_plat_priv this was included, can you suggest alternative?

If that is the "normal" way to do this with the xhci driver, ok, but I would like to get an ack from Mathias for this before taking it.

Can you please review this patch which is including the xhci-plat header?  Let me

Quoted 8 lines
Quoted 4 lines

know if anything should be modified. Ack if this patch looks ok so Greg can

take it.

This doesn't look right.

dwc3 shouldn't need to know about xhci platform private structures,

Then, how dwc3 host let xhci know which xhci quirks it needs to use?

Quoted 6 lines

besides, this patch now adds the quirk to all xhci platform devices created by dwc3.

I haven't touched dwc3 at all, but I'd guess you probably need to add a new entry to the dwc3_pci_id_table[] in dwc3-pci.c, add a device property, and then look for that property in xhci-plat.c, and set the quirk.

For non-PCI devices, it uses common platform bus, the specific platform drivers use platform data to pass platform quirks to common driver, so I added below patch.

46034a999c07 usb: host: xhci-plat: add platform data support

At platform data, the specific host driver could add xhci quirks and let xhci handle later.

Signature · 2 lines
Thanks,
Peter Chen
#11 lore raw

Re: [RESEND PATCH v6 3/3] usb: dwc3: Pass quirk as platform data

In reply to Mathias Nyman

Hello Mathias,

Quoted 42 lines · Mathias Nyman
Quoted 41 lines · Tejas Joglekar

Hi Mathias,

Quoted 30 lines · Greg Kroah-Hartman
Quoted 14 lines · Tejas Joglekar

Hi Greg,

Quoted 12 lines · Greg Kroah-Hartman
Quoted 11 lines · Tejas Joglekar

This commit adds the platform device data to setup the XHCI_SG_TRB_CACHE_SIZE_QUIRK quirk. DWC3 hosts which are PCI devices does not use OF to create platform device but create xhci-plat platform device at runtime. So this patch allows parent device to supply the quirk through platform data.

---
 drivers/usb/dwc3/host.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
Quoted 6 lines
Quoted 1 line

What changed from previous versions?

Resent the patch as it was missed for review by Felipe and I saw your mail

to resend the patch if not reviewed. Other two patches from series are

picked up by Mathias, this one is remaining for review.

Ah, how was I supposed to guess that? :)

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/usb/dwc3/host.c +0 -0
index e195176580de..0434bc8cec12 100644
@@ -11,6 +11,11 @@
 #include <linux/platform_device.h>
 
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines

drivers/usb/dwc3/host.c line 14

Quoted 2 lines
drivers/usb/dwc3/host.c +1 -0
 #include "core.h"
+#include "../host/xhci-plat.h"

That feels really wrong. Are you sure about that?

To use the struct xhci_plat_priv this was included, can you suggest alternative?

If that is the "normal" way to do this with the xhci driver, ok, but I would like to get an ack from Mathias for this before taking it.

Can you please review this patch which is including the xhci-plat header?  Let me

Quoted 8 lines
Quoted 4 lines

know if anything should be modified. Ack if this patch looks ok so Greg can

take it.

This doesn't look right.

dwc3 shouldn't need to know about xhci platform private structures, besides, this patch now adds the quirk to all xhci platform devices created by dwc3.

As per understanding the TRB cache is present and used in all dwc3 controllers, so we would

need the quirk for all.

Quoted 3 lines

I haven't touched dwc3 at all, but I'd guess you probably need to add a new entry to the dwc3_pci_id_table[] in dwc3-pci.c, add a device property, and then look for that property in xhci-plat.c, and set the quirk.

The first approach was the same as you mentioned where I added device property with

dt-binding for enabling the quirk, but Rob was not OK to add new bindings for each new

quirk.

With PCI devices compatible string would not work and dt bindings solution was not

given clearance, I referred other approach taken by Peter in commit ed22764847e8100f0af9af91ccfa58e5c559bd47,

(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ed22764847e8100f0af9af91ccfa58e5c559bd47)

where he used xhci platform data to pass the quirk. I followed the same approach and added the quirk.

I think another way might be to make the xhci platform data structure, public so dwc3 can use it ?

Quoted 1 line

-Mathias

Thanks & Regards,

  Tejas Joglekar

#12 lore raw
In reply to Tejas Joglekar
Quoted 52 lines · Tejas Joglekar

The Synopsys xHC has an internal TRB cache of size TRB_CACHE_SIZE for each endpoint. The default value for TRB_CACHE_SIZE is 16 for SS and 8 for HS. The controller loads and updates the TRB cache from the transfer ring in system memory whenever the driver issues a start transfer or update transfer command.

For chained TRBs, the Synopsys xHC requires that the total amount of bytes for all TRBs loaded in the TRB cache be greater than or equal to 1 MPS. Or the chain ends within the TRB cache (with a last TRB).

If this requirement is not met, the controller will not be able to send or receive a packet and it will hang causing a driver timeout and error.

This patch set adds logic to the XHCI driver to detect and prevent this from happening along with the quirk to enable this logic for Synopsys HAPS platform.

Based on Mathias's feedback on previous implementation where consolidation was done in TRB cache, with this patch series the implementation is done during mapping of the URB by consolidating the SG list into a temporary buffer if the SG list buffer sizes within TRB_CACHE_SIZE is less than MPS.

Changes since v5:
- Update the quirk macro to have next number [Patch 1/3]
- Fixed the issues reported by kernel test robot [Patch 2/3]

Changes since v4:
- Updated [Patch 3/3] platform data structure initialization
- Trivial changes in commit wordings

Changes since v3:
- Removed the dt-binding patch
- Added new patch to pass the quirk as platform data
- Modified the patch to set the quirk

Changes since v2:
- Modified the xhci_unmap_temp_buffer function to unmap dma and c the dma flag
- Removed RFC tag

Changes since v1:
- Comments from Greg are addressed on [PATCH 4/4] and [PATCH 1/4]
- Renamed the property and quirk as in other patches based on [PATCH 1/4]

Tejas Joglekar (3):
usb: xhci: Set quirk for XHCI_SG_TRB_CACHE_SIZE_QUIRK
usb: xhci: Use temporary buffer to consolidate SG
usb: dwc3: Pass quirk as platform data

Quoted 7 lines
 drivers/usb/dwc3/host.c      |  10 +++
 drivers/usb/host/xhci-plat.c |   3 +
 drivers/usb/host/xhci-ring.c |   2 +-
 drivers/usb/host/xhci.c      | 129 ++++++++++++++++++++++++++++++++++-
 drivers/usb/host/xhci.h      |   5 ++
 5 files changed, 147 insertions(+), 2 deletions(-)

Dropped last version and picked first two patches from this series.

-Mathias