ChangeSet 1.893.2.16, 2002/12/26 18:53:13-08:00, [EMAIL PROTECTED]

[PATCH] 2.4.20 usbvideo fixes from 2.5  1/5

This patch backports some fixes from 2.5 for the RingQueue_*
functions

Make the buffer length be a power of 2 to speed up index manipulation
Make RingQueue_Dequeue use memcpy() rather than a byte by byte copy
Make RingQueue_Enqueue use memcpy() instead of memmove() as the memory
  regions do not overlap
Add RingQueue_Flush() and RingQueue_GetFreeSpace()
Make RingQueue_GetLength() an inline


diff -Nru a/drivers/usb/usbvideo.c b/drivers/usb/usbvideo.c
--- a/drivers/usb/usbvideo.c    Mon Jan  6 11:30:42 2003
+++ b/drivers/usb/usbvideo.c    Mon Jan  6 11:30:42 2003
@@ -109,29 +109,41 @@
        vfree(mem);
 }
 
-void RingQueue_Initialize(struct RingQueue *rq)
+static void RingQueue_Initialize(struct RingQueue *rq)
 {
        assert(rq != NULL);
        init_waitqueue_head(&rq->wqh);
 }
 
-void RingQueue_Allocate(struct RingQueue *rq, int rqLen)
+static void RingQueue_Allocate(struct RingQueue *rq, int rqLen)
 {
+       /* Make sure the requested size is a power of 2 and
+          round up if necessary. This allows index wrapping
+          using masks rather than modulo */
+
+       int i = 1;
        assert(rq != NULL);
        assert(rqLen > 0);
+
+       while(rqLen >> i)
+               i++;
+       if(rqLen != 1 << (i-1))
+               rqLen = 1 << i;
+
        rq->length = rqLen;
+       rq->ri = rq->wi = 0;
        rq->queue = usbvideo_rvmalloc(rq->length);
        assert(rq->queue != NULL);
 }
 
-int RingQueue_IsAllocated(const struct RingQueue *rq)
+static int RingQueue_IsAllocated(const struct RingQueue *rq)
 {
        if (rq == NULL)
                return 0;
        return (rq->queue != NULL) && (rq->length > 0);
 }
 
-void RingQueue_Free(struct RingQueue *rq)
+static void RingQueue_Free(struct RingQueue *rq)
 {
        assert(rq != NULL);
        if (RingQueue_IsAllocated(rq)) {
@@ -143,12 +155,32 @@
 
 int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len)
 {
-       int i;
+       int rql, toread;
+
        assert(rq != NULL);
        assert(dst != NULL);
-       for (i=0; i < len; i++) {
-               dst[i] = rq->queue[rq->ri];
-               RING_QUEUE_DEQUEUE_BYTES(rq,1);
+
+       rql = RingQueue_GetLength(rq);
+       if(!rql)
+               return 0;
+
+       /* Clip requested length to available data */
+       if(len > rql)
+               len = rql;
+
+       toread = len;
+       if(rq->ri > rq->wi) {
+               /* Read data from tail */
+               int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - 
+rq->ri;
+               memcpy(dst, rq->queue + rq->ri, read);
+               toread -= read;
+               dst += read;
+               rq->ri = (rq->ri + read) & (rq->length-1);
+       }
+       if(toread) {
+               /* Read data from head */
+               memcpy(dst, rq->queue + rq->ri, toread);
+               rq->ri = (rq->ri + toread) & (rq->length-1);
        }
        return len;
 }
@@ -174,7 +206,7 @@
                if (m > q_avail)
                        m = q_avail;
 
-               memmove(rq->queue + rq->wi, cdata, m);
+               memcpy(rq->queue + rq->wi, cdata, m);
                RING_QUEUE_ADVANCE_INDEX(rq, wi, m);
                cdata += m;
                enqueued += m;
@@ -183,23 +215,7 @@
        return enqueued;
 }
 
-int RingQueue_GetLength(const struct RingQueue *rq)
-{
-       int ri, wi;
-
-       assert(rq != NULL);
-
-       ri = rq->ri;
-       wi = rq->wi;
-       if (ri == wi)
-               return 0;
-       else if (ri < wi)
-               return wi - ri;
-       else
-               return wi + (rq->length - ri);
-}
-
-void RingQueue_InterruptibleSleepOn(struct RingQueue *rq)
+static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq)
 {
        assert(rq != NULL);
        interruptible_sleep_on(&rq->wqh);
@@ -212,6 +228,14 @@
                wake_up_interruptible(&rq->wqh);
 }
 
+void RingQueue_Flush(struct RingQueue *rq)
+{
+       assert(rq != NULL);
+       rq->ri = 0;
+       rq->wi = 0;
+}
+
+
 /*
  * usbvideo_VideosizeToString()
  *
@@ -348,7 +372,7 @@
                q_used = RingQueue_GetLength(&uvd->dp);
                if ((uvd->dp.ri + q_used) >= uvd->dp.length) {
                        u_hi = uvd->dp.length;
-                       u_lo = (q_used + uvd->dp.ri) % uvd->dp.length;
+                       u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1);
                } else {
                        u_hi = (q_used + uvd->dp.ri);
                        u_lo = -1;
@@ -1203,7 +1227,7 @@
                /* Allocate memory for the frame buffers */
                uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;
                uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size);
-               RingQueue_Allocate(&uvd->dp, 128*1024); /* FIXME #define */
+               RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
                if ((uvd->fbuf == NULL) ||
                    (!RingQueue_IsAllocated(&uvd->dp))) {
                        err("%s: Failed to allocate fbuf or dp", __FUNCTION__);
diff -Nru a/drivers/usb/usbvideo.h b/drivers/usb/usbvideo.h
--- a/drivers/usb/usbvideo.h    Mon Jan  6 11:30:42 2003
+++ b/drivers/usb/usbvideo.h    Mon Jan  6 11:30:42 2003
@@ -113,9 +113,10 @@
     mr = LIMIT_RGB(mm_r); \
 }
 
-#define        RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) % 
(rq)->length
+#define        RING_QUEUE_SIZE         (128*1024)      /* Must be a power of 2 */
+#define        RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & 
+((rq)->length-1)
 #define        RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n)
-#define        RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) % 
(rq)->length])
+#define        RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & 
+((rq)->length-1)])
 
 struct RingQueue {
        unsigned char *queue;   /* Data from the Isoc data pump */
@@ -300,15 +301,20 @@
 #define        VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \
                ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL)
 
-void RingQueue_Initialize(struct RingQueue *rq);
-void RingQueue_Allocate(struct RingQueue *rq, int rqLen);
-int  RingQueue_IsAllocated(const struct RingQueue *rq);
-void RingQueue_Free(struct RingQueue *rq);
 int  RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len);
 int  RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n);
-int  RingQueue_GetLength(const struct RingQueue *rq);
-void RingQueue_InterruptibleSleepOn(struct RingQueue *rq);
 void RingQueue_WakeUpInterruptible(struct RingQueue *rq);
+void RingQueue_Flush(struct RingQueue *rq);
+
+static inline int RingQueue_GetLength(const struct RingQueue *rq)
+{
+       return (rq->wi - rq->ri + rq->length) & (rq->length-1);
+}
+
+static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq)
+{
+       return rq->length - RingQueue_GetLength(rq);
+}
 
 void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame);
 void usbvideo_DrawLine(


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to