This is an automatic generated email to let you know that the following patch 
were queued at the 
http://git.linuxtv.org/media_tree.git tree:

Subject: [media] media: Fix a UVC performance problem on systems with 
non-coherent DMA
Author:  Al Cooper <[email protected]>
Date:    Thu Aug 18 10:28:29 2011 -0300

The UVC driver uses usb_alloc_coherent() to allocate DMA data buffers.
On systems without coherent DMA this ends up allocating buffers in
uncached memory. The subsequent memcpy's done to coalesce the DMA
chunks into contiguous buffers then run VERY slowly. On a MIPS test
system the memcpy is about 200 times slower. This issue prevents the
system from keeping up with 720p YUYV data at 10fps.

The following patch uses kmalloc to alloc the DMA buffers instead of
usb_alloc_coherent on systems without coherent DMA. With this patch
the system was easily able to keep up with 720p at 10fps.

Signed-off-by: Al Cooper <[email protected]>
Acked-by: Laurent Pinchart <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>

 drivers/media/video/uvc/uvc_video.c |   17 ++++++++++++++++-
 1 files changed, 16 insertions(+), 1 deletions(-)

---

http://git.linuxtv.org/media_tree.git?a=commitdiff;h=3e0ac6717b0a2593243ef3850025a42cb199880f

diff --git a/drivers/media/video/uvc/uvc_video.c 
b/drivers/media/video/uvc/uvc_video.c
index ffd1158..b015e8e 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -790,8 +790,12 @@ static void uvc_free_urb_buffers(struct uvc_streaming 
*stream)
 
        for (i = 0; i < UVC_URBS; ++i) {
                if (stream->urb_buffer[i]) {
+#ifndef CONFIG_DMA_NONCOHERENT
                        usb_free_coherent(stream->dev->udev, stream->urb_size,
                                stream->urb_buffer[i], stream->urb_dma[i]);
+#else
+                       kfree(stream->urb_buffer[i]);
+#endif
                        stream->urb_buffer[i] = NULL;
                }
        }
@@ -831,9 +835,14 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming 
*stream,
        for (; npackets > 1; npackets /= 2) {
                for (i = 0; i < UVC_URBS; ++i) {
                        stream->urb_size = psize * npackets;
+#ifndef CONFIG_DMA_NONCOHERENT
                        stream->urb_buffer[i] = usb_alloc_coherent(
                                stream->dev->udev, stream->urb_size,
                                gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
+#else
+                       stream->urb_buffer[i] =
+                           kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN);
+#endif
                        if (!stream->urb_buffer[i]) {
                                uvc_free_urb_buffers(stream);
                                break;
@@ -908,10 +917,14 @@ static int uvc_init_video_isoc(struct uvc_streaming 
*stream,
                urb->context = stream;
                urb->pipe = usb_rcvisocpipe(stream->dev->udev,
                                ep->desc.bEndpointAddress);
+#ifndef CONFIG_DMA_NONCOHERENT
                urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               urb->transfer_dma = stream->urb_dma[i];
+#else
+               urb->transfer_flags = URB_ISO_ASAP;
+#endif
                urb->interval = ep->desc.bInterval;
                urb->transfer_buffer = stream->urb_buffer[i];
-               urb->transfer_dma = stream->urb_dma[i];
                urb->complete = uvc_video_complete;
                urb->number_of_packets = npackets;
                urb->transfer_buffer_length = size;
@@ -969,8 +982,10 @@ static int uvc_init_video_bulk(struct uvc_streaming 
*stream,
                usb_fill_bulk_urb(urb, stream->dev->udev, pipe,
                        stream->urb_buffer[i], size, uvc_video_complete,
                        stream);
+#ifndef CONFIG_DMA_NONCOHERENT
                urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
                urb->transfer_dma = stream->urb_dma[i];
+#endif
 
                stream->urb[i] = urb;
        }

_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to