All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 2/5] ehci-hcd: Boost transfer speed
Date: Thu, 19 Jul 2012 22:17:04 +0200 (CEST)	[thread overview]
Message-ID: <1857491712.292135.1342729024425.JavaMail.root@advansee.com> (raw)

This patch takes advantage of the hardware EHCI qTD queuing mechanism to avoid
software overhead and to make transfers as fast as possible.

The only drawback is a call to memalign. However, this is fast compared to the
transfer timings, and the heap size to allocate is small, e.g. a little bit more
than 100 kB for a transfer length of 65535 packets of 512 bytes.

Tested on i.MX25 and i.MX35. In my test conditions, the speedup was about 15x
using page-aligned buffers, which is really appreciable when accessing large
files.

Signed-off-by: Beno?t Th?baudeau <benoit.thebaudeau@advansee.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Stefan Herbrechtsmeier <stefan@herbrechtsmeier.net>
---
 .../drivers/usb/host/ehci-hcd.c                    |   94 ++++++++++++++------
 1 file changed, 65 insertions(+), 29 deletions(-)

diff --git u-boot-usb-1b4bd0e.orig/drivers/usb/host/ehci-hcd.c u-boot-usb-1b4bd0e/drivers/usb/host/ehci-hcd.c
index 5b3b906..b5645fa 100644
--- u-boot-usb-1b4bd0e.orig/drivers/usb/host/ehci-hcd.c
+++ u-boot-usb-1b4bd0e/drivers/usb/host/ehci-hcd.c
@@ -208,7 +208,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		   int length, struct devrequest *req)
 {
 	ALLOC_ALIGN_BUFFER(struct QH, qh, 1, USB_DMA_MINALIGN);
-	ALLOC_ALIGN_BUFFER(struct qTD, qtd, 3, USB_DMA_MINALIGN);
+	struct qTD *qtd;
+	int qtd_count = 0;
 	int qtd_counter = 0;
 
 	volatile struct qTD *vtd;
@@ -229,8 +230,25 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		      le16_to_cpu(req->value), le16_to_cpu(req->value),
 		      le16_to_cpu(req->index));
 
+	if (req != NULL)			/* SETUP + ACK */
+		qtd_count += 1 + 1;
+	if (length > 0 || req == NULL) {	/* buffer */
+		if ((uint32_t)buffer & 4095)		/* page-unaligned */
+			qtd_count += (((uint32_t)buffer & 4095) + length +
+					(QT_BUFFER_CNT - 1) * 4096 - 1) /
+						((QT_BUFFER_CNT - 1) * 4096);
+		else					/* page-aligned */
+			qtd_count += (length + QT_BUFFER_CNT * 4096 - 1) /
+					(QT_BUFFER_CNT * 4096);
+	}
+	qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD));
+	if (qtd == NULL) {
+		printf("unable to allocate TDs\n");
+		return -1;
+	}
+
 	memset(qh, 0, sizeof(struct QH));
-	memset(qtd, 0, 3 * sizeof(*qtd));
+	memset(qtd, 0, qtd_count * sizeof(*qtd));
 
 	toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
 
@@ -291,31 +309,46 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	}
 
 	if (length > 0 || req == NULL) {
-		/*
-		 * Setup request qTD (3.5 in ehci-r10.pdf)
-		 *
-		 *   qt_next ................ 03-00 H
-		 *   qt_altnext ............. 07-04 H
-		 *   qt_token ............... 0B-08 H
-		 *
-		 *   [ buffer, buffer_hi ] loaded with "buffer".
-		 */
-		qtd[qtd_counter].qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
-		qtd[qtd_counter].qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
-		token = (toggle << 31) |
-		    (length << 16) |
-		    ((req == NULL ? 1 : 0) << 15) |
-		    (0 << 12) |
-		    (3 << 10) |
-		    ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
-		qtd[qtd_counter].qt_token = cpu_to_hc32(token);
-		if (ehci_td_buffer(&qtd[qtd_counter], buffer, length) != 0) {
-			printf("unable construct DATA td\n");
-			goto fail;
-		}
-		/* Update previous qTD! */
-		*tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]);
-		tdp = &qtd[qtd_counter++].qt_next;
+		uint8_t *buf_ptr = buffer;
+		int left_length = length;
+
+		do {
+			int xfr_bytes = min(left_length,
+					    (QT_BUFFER_CNT * 4096 -
+					     ((uint32_t)buf_ptr & 4095)) &
+					    ~4095);
+
+			/*
+			 * Setup request qTD (3.5 in ehci-r10.pdf)
+			 *
+			 *   qt_next ................ 03-00 H
+			 *   qt_altnext ............. 07-04 H
+			 *   qt_token ............... 0B-08 H
+			 *
+			 *   [ buffer, buffer_hi ] loaded with "buffer".
+			 */
+			qtd[qtd_counter].qt_next =
+					cpu_to_hc32(QT_NEXT_TERMINATE);
+			qtd[qtd_counter].qt_altnext =
+					cpu_to_hc32(QT_NEXT_TERMINATE);
+			token = (toggle << 31) |
+			    (xfr_bytes << 16) |
+			    ((req == NULL ? 1 : 0) << 15) |
+			    (0 << 12) |
+			    (3 << 10) |
+			    ((usb_pipein(pipe) ? 1 : 0) << 8) | (0x80 << 0);
+			qtd[qtd_counter].qt_token = cpu_to_hc32(token);
+			if (ehci_td_buffer(&qtd[qtd_counter], buf_ptr,
+						xfr_bytes) != 0) {
+				printf("unable construct DATA td\n");
+				goto fail;
+			}
+			/* Update previous qTD! */
+			*tdp = cpu_to_hc32((uint32_t)&qtd[qtd_counter]);
+			tdp = &qtd[qtd_counter++].qt_next;
+			buf_ptr += xfr_bytes;
+			left_length -= xfr_bytes;
+		} while (left_length > 0);
 	}
 
 	if (req != NULL) {
@@ -346,7 +379,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 	flush_dcache_range((uint32_t)qh_list,
 		ALIGN_END_ADDR(struct QH, qh_list, 1));
 	flush_dcache_range((uint32_t)qh, ALIGN_END_ADDR(struct QH, qh, 1));
-	flush_dcache_range((uint32_t)qtd, ALIGN_END_ADDR(struct qTD, qtd, 3));
+	flush_dcache_range((uint32_t)qtd,
+			   ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
 
 	/* Set async. queue head pointer. */
 	ehci_writel(&hcor->or_asynclistaddr, (uint32_t)qh_list);
@@ -377,7 +411,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		invalidate_dcache_range((uint32_t)qh,
 			ALIGN_END_ADDR(struct QH, qh, 1));
 		invalidate_dcache_range((uint32_t)qtd,
-			ALIGN_END_ADDR(struct qTD, qtd, 3));
+			ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
 
 		token = hc32_to_cpu(vtd->qt_token);
 		if (!(token & 0x80))
@@ -450,9 +484,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
 		      ehci_readl(&hcor->or_portsc[1]));
 	}
 
+	free(qtd);
 	return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
 
 fail:
+	free(qtd);
 	return -1;
 }
 

             reply	other threads:[~2012-07-19 20:17 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-19 20:17 Benoît Thébaudeau [this message]
2012-07-20 11:26 ` [U-Boot] [PATCH v2 2/5] ehci-hcd: Boost transfer speed Benoît Thébaudeau
2012-07-20 11:37   ` Stefan Herbrechtsmeier
2012-07-20 13:17     ` Benoît Thébaudeau
2012-07-20 13:44       ` Marek Vasut
2012-07-20 13:56         ` Benoît Thébaudeau
2012-07-20 14:51           ` Stefan Herbrechtsmeier
2012-07-20 15:03             ` Benoît Thébaudeau
2012-07-20 15:15               ` Stefan Herbrechtsmeier
2012-07-20 15:35                 ` Benoît Thébaudeau
2012-07-23 13:35                   ` Stefan Herbrechtsmeier
2012-07-23 17:15                     ` Benoît Thébaudeau
2012-07-24 13:02                       ` Stefan Herbrechtsmeier
2012-07-29  0:48                         ` Benoît Thébaudeau
2012-07-30 22:38                           ` Marek Vasut
2012-07-31  1:06                             ` Benoît Thébaudeau
2012-07-31 19:52                               ` Stefan Herbrechtsmeier
2012-08-01  2:41                                 ` Marek Vasut
2012-08-03 23:02                               ` Benoît Thébaudeau
2012-08-04  7:45                                 ` Marek Vasut
2012-08-08 23:14                                   ` Benoît Thébaudeau
2012-08-08 23:14                                     ` Marek Vasut
2012-07-31 20:01                           ` Stefan Herbrechtsmeier
2012-07-27 14:07   ` Marek Vasut
2012-07-27 14:16     ` Benoît Thébaudeau
2012-07-27 14:30       ` Marek Vasut
2012-08-09 21:51   ` [U-Boot] [PATCH v3 3/8] " Benoît Thébaudeau
2012-08-09 22:32     ` Marek Vasut
2012-07-27 12:54 ` [U-Boot] [PATCH 2/5] " Marek Vasut
2012-07-27 13:59   ` Benoît Thébaudeau
2012-07-27 14:01     ` Marek Vasut
2012-07-27 14:13       ` Benoît Thébaudeau
2012-07-27 14:31         ` Marek Vasut
2012-07-29  0:58         ` Benoît Thébaudeau
2012-07-29  1:40           ` Marek Vasut
2012-07-29 14:14             ` Benoît Thébaudeau
2012-07-29 18:08               ` Marek Vasut

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1857491712.292135.1342729024425.JavaMail.root@advansee.com \
    --to=benoit.thebaudeau@advansee.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.