[U-Boot] [PATCH v3 8/8] ehci: Optimize qTD allocations
Marek Vasut
marex at denx.de
Sun Aug 12 01:41:05 CEST 2012
Dear Benoît Thébaudeau,
> Relax the qTD transfer alignment constraints in order to need less qTDs for
> buffers that are aligned to 512 bytes but not to pages.
>
> Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau at advansee.com>
> Cc: Marek Vasut <marex at denx.de>
> Cc: Ilya Yanok <ilya.yanok at cogentembedded.com>
> Cc: Stefan Herbrechtsmeier <stefan at herbrechtsmeier.net>
> ---
> Changes for v2: N/A.
> Changes for v3:
> - New patch.
>
> .../drivers/usb/host/ehci-hcd.c | 68
> +++++++++++--------- 1 file changed, 38 insertions(+), 30 deletions(-)
>
> diff --git u-boot-usb-8d5fb14.orig/drivers/usb/host/ehci-hcd.c
> u-boot-usb-8d5fb14/drivers/usb/host/ehci-hcd.c index 84c7d08..37517cb
> 100644
> --- u-boot-usb-8d5fb14.orig/drivers/usb/host/ehci-hcd.c
> +++ u-boot-usb-8d5fb14/drivers/usb/host/ehci-hcd.c
> @@ -215,7 +215,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long
> pipe, void *buffer, volatile struct qTD *vtd;
> unsigned long ts;
> uint32_t *tdp;
> - uint32_t endpt, token, usbsts;
> + uint32_t endpt, maxpacket, token, usbsts;
> uint32_t c, toggle;
> uint32_t cmd;
> int timeout;
> @@ -230,6 +230,7 @@ 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));
>
> +#define PKT_ALIGN 512
Make this const int maybe ?
> /*
> * The USB transfer is split into qTD transfers. Eeach qTD transfer is
> * described by a transfer descriptor (the qTD). The qTDs form a linked
> @@ -251,43 +252,41 @@ ehci_submit_async(struct usb_device *dev, unsigned
> long pipe, void *buffer, if (length > 0 || req == NULL) {
> /*
> * Determine the qTD transfer size that will be used for the
> - * data payload (not considering the final qTD transfer, which
> - * may be shorter).
> + * data payload (not considering the first qTD transfer, which
> + * may be longer or shorter, and the final one, which may be
> + * shorter).
> *
> * In order to keep each packet within a qTD transfer, the qTD
> - * transfer size is aligned to EHCI_PAGE_SIZE, which is a
> - * multiple of wMaxPacketSize (except in some cases for
> - * interrupt transfers, see comment in submit_int_msg()).
> + * transfer size is aligned to PKT_ALIGN, which is a multiple of
> + * wMaxPacketSize (except in some cases for interrupt transfers,
> + * see comment in submit_int_msg()).
> *
> - * By default, i.e. if the input buffer is page-aligned,
> + * By default, i.e. if the input buffer is aligned to PKT_ALIGN,
> * QT_BUFFER_CNT full pages will be used.
> */
> int xfr_sz = QT_BUFFER_CNT;
> /*
> - * However, if the input buffer is not page-aligned, the qTD
> - * transfer size will be one page shorter, and the first qTD
> + * However, if the input buffer is not aligned to PKT_ALIGN, the
> + * qTD transfer size will be one page shorter, and the first qTD
> * data buffer of each transfer will be page-unaligned.
> */
> - if ((uint32_t)buffer & (EHCI_PAGE_SIZE - 1))
> + if ((uint32_t)buffer & (PKT_ALIGN - 1))
> xfr_sz--;
> /* Convert the qTD transfer size to bytes. */
> xfr_sz *= EHCI_PAGE_SIZE;
> /*
> - * Determine the number of qTDs that will be required for the
> - * data payload. This value has to be rounded up since the final
> - * qTD transfer may be shorter than the regular qTD transfer
> - * size that has just been computed.
> + * Approximate by excess the number of qTDs that will be
> + * required for the data payload. The exact formula is way more
> + * complicated and saves at most 2 qTDs, i.e. a total of 128
> + * bytes.
> */
> - qtd_count += DIV_ROUND_UP(length, xfr_sz);
> - /* ZLPs also need a qTD. */
> - if (!qtd_count)
> - qtd_count++;
> + qtd_count += 2 + length / xfr_sz;
> }
> /*
> - * Threshold value based on the worst-case total size of the qTDs to
> allocate - * for a mass-storage transfer of 65535 blocks of 512 bytes.
> + * Threshold value based on the worst-case total size of the allocated
> qTDs for + * a mass-storage transfer of 65535 blocks of 512 bytes.
> */
> -#if CONFIG_SYS_MALLOC_LEN <= 128 * 1024
> +#if CONFIG_SYS_MALLOC_LEN <= 64 + 128 * 1024
> #warning CONFIG_SYS_MALLOC_LEN may be too small for EHCI
> #endif
> qtd = memalign(USB_DMA_MINALIGN, qtd_count * sizeof(struct qTD));
> @@ -314,9 +313,10 @@ ehci_submit_async(struct usb_device *dev, unsigned
> long pipe, void *buffer, qh->qh_link = cpu_to_hc32((uint32_t)qh_list |
> QH_LINK_TYPE_QH);
> c = (usb_pipespeed(pipe) != USB_SPEED_HIGH &&
> usb_pipeendpoint(pipe) == 0);
> + maxpacket = usb_maxpacket(dev, pipe);
> endpt = (8 << QH_ENDPT1_RL) |
> (c << QH_ENDPT1_C) |
> - (usb_maxpacket(dev, pipe) << QH_ENDPT1_MAXPKTLEN) |
> + (maxpacket << QH_ENDPT1_MAXPKTLEN) |
Is this change really needed? (not that I care much).
[...]
Took me a bit to make it through, but I think I get it ... just real nits above.
More information about the U-Boot
mailing list