Re: [PATCH 32/37] usb: host: xhci: switch to running avg trb length

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 29.12.2016 13:01, Felipe Balbi wrote:
It's unlikely that we will ever know the avg so
instead of assuming it'll be something really large,
we will calculate the avg as we go as mentioned in
XHCI specification section 4.14.1.1.

Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx>
---
  drivers/usb/host/xhci-mem.c  | 34 ++++++++++++++++++++++++----------
  drivers/usb/host/xhci-ring.c | 20 ++++++++++++++++++++
  drivers/usb/host/xhci.h      |  3 ++-
  3 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index f7cfbab5ba4c..9e1ccfadf128 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1451,18 +1451,34 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,

  	ring_type = usb_endpoint_type(&ep->desc);

-	/*
-	 * Get values to fill the endpoint context, mostly from ep descriptor.
-	 * The average TRB buffer lengt for bulk endpoints is unclear as we
-	 * have no clue on scatter gather list entry size. For Isoc and Int,
-	 * set it to max available. See xHCI 1.1 spec 4.14.1.1 for details.
-	 */
+	/* Get values to fill the endpoint context, mostly from ep descriptor. */
  	max_esit_payload = xhci_get_max_esit_payload(udev, ep);
  	interval = xhci_get_endpoint_interval(udev, ep);
  	mult = xhci_get_endpoint_mult(udev, ep);
  	max_packet = usb_endpoint_maxp(&ep->desc);
  	max_burst = xhci_get_endpoint_max_burst(udev, ep);
-	avg_trb_len = max_esit_payload;
+
+	/*
+	 * We are using a running avg for our endpoint's avg_trb_len. The reason
+	 * is that we have no clue about average transfer sizes for any
+	 * endpoints because the HCD does not know which USB Class is running on
+	 * the other end.
+	 *
+	 * See xHCI 1.1 spec 4.14.1.1 for details about initial avg_trb_len
+	 * setting.
+	 */
+	switch (usb_endpoint_type(&ep->desc)) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		avg_trb_len = 8;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		avg_trb_len = 1024;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+	case USB_ENDPOINT_XFER_BULK:
+		avg_trb_len = 3072;
+		break;
+	}

  	/* FIXME dig Mult and streams info out of ep companion desc */

@@ -1472,9 +1488,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
  	/* Some devices get this wrong */
  	if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH)
  		max_packet = 512;
-	/* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */
-	if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
-		avg_trb_len = 8;
+
  	/* xhci 1.1 with LEC support doesn't use mult field, use RsvdZ */
  	if ((xhci->hci_version > 0x100) && HCC2_LEC(xhci->hcc_params2))
  		mult = 0;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 1431e0651e78..f5f999d8a72c 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2752,6 +2752,8 @@ static int prepare_transfer(struct xhci_hcd *xhci,
  	struct xhci_td	*td;
  	struct xhci_ring *ep_ring;
  	struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+	unsigned int avg_trb_len;
+	unsigned int tx_info;

  	ep_ring = xhci_stream_id_to_ring(xdev, ep_index, stream_id);
  	if (!ep_ring) {
@@ -2760,6 +2762,24 @@ static int prepare_transfer(struct xhci_hcd *xhci,
  		return -EINVAL;
  	}

+	/*
+	 * Here we update avg_trb_len so that, over time, we get a better
+	 * representation of what the actual average length for this endpoint's
+	 * TRBs are going to be.
+	 */
+	if (urb->transfer_buffer_length > 0) {
+		tx_info = le32_to_cpu(ep_ctx->tx_info);
+
+		avg_trb_len = EP_AVG_TRB_LENGTH(tx_info);
+		avg_trb_len += urb->transfer_buffer_length;
+		avg_trb_len /= 2;

This avg calculation will give 50% weight to the latest urb length, and only 50% to all
the previous ones. If the lengths vary a lot then the running avg will also fluctuate a lot,
consider if URB1 1024bytes data, URB2 6bytes command, USB3 1024bytes data.

If I remember correctly we couldn't see any benefit from this change. Maybe a
more extensive avg length calculation could be implemented if we start seeing
bandwidth issues.

Skipping this patch

-Mathias


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux