public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Stefan Herbrechtsmeier <stefan@herbrechtsmeier.net>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 2/5] ehci-hcd: Boost transfer speed
Date: Fri, 20 Jul 2012 13:37:37 +0200	[thread overview]
Message-ID: <50094301.5010507@herbrechtsmeier.net> (raw)
In-Reply-To: <1024949320.326453.1342783584348.JavaMail.root@advansee.com>

Am 20.07.2012 13:26, schrieb Beno?t Th?baudeau:
> 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>
> ---
> Changes for v2:
>   - Use DIV_ROUND_UP to make code more readable.
>
>   .../drivers/usb/host/ehci-hcd.c                    |   92 ++++++++++++++------
>   1 file changed, 63 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..cf9ab92 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,23 @@ 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 += DIV_ROUND_UP(((uint32_t)buffer & 4095) +
> +					length, (QT_BUFFER_CNT - 1) * 4096);
> +		else					/* page-aligned */
> +			qtd_count += DIV_ROUND_UP(length, 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 +307,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);
Why you align the length to 4096?
> +
> +			/*
> +			 * 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 +377,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 +409,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 +482,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-20 11:37 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-19 20:17 [U-Boot] [PATCH 2/5] ehci-hcd: Boost transfer speed Benoît Thébaudeau
2012-07-20 11:26 ` [U-Boot] [PATCH v2 " Benoît Thébaudeau
2012-07-20 11:37   ` Stefan Herbrechtsmeier [this message]
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=50094301.5010507@herbrechtsmeier.net \
    --to=stefan@herbrechtsmeier.net \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox