# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.489 -> 1.490 # drivers/usb/media/usbvideo.h 1.12 -> 1.13 # drivers/usb/media/usbvideo.c 1.21 -> 1.22 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/08/17 spse@secret.org.uk 1.490 # [PATCH] cleanup RingQueue_* functions in usbvideo.c # # This patch against 2.5.31 cleans up 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/media/usbvideo.c b/drivers/usb/media/usbvideo.c --- a/drivers/usb/media/usbvideo.c Sun Aug 18 20:48:36 2002 +++ b/drivers/usb/media/usbvideo.c Sun Aug 18 20:48:36 2002 @@ -135,9 +135,21 @@ static void RingQueue_Allocate(RingQueue_t *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); } @@ -161,12 +173,32 @@ int RingQueue_Dequeue(RingQueue_t *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; } @@ -194,7 +226,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; @@ -205,24 +237,6 @@ EXPORT_SYMBOL(RingQueue_Enqueue); -int RingQueue_GetLength(const RingQueue_t *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); -} - -EXPORT_SYMBOL(RingQueue_GetLength); - static void RingQueue_InterruptibleSleepOn(RingQueue_t *rq) { assert(rq != NULL); @@ -238,6 +252,16 @@ EXPORT_SYMBOL(RingQueue_WakeUpInterruptible); +void RingQueue_Flush(RingQueue_t *rq) +{ + assert(rq != NULL); + rq->ri = 0; + rq->wi = 0; +} + +EXPORT_SYMBOL(RingQueue_Flush); + + /* * usbvideo_VideosizeToString() * @@ -374,7 +398,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; @@ -1256,7 +1280,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", proc); diff -Nru a/drivers/usb/media/usbvideo.h b/drivers/usb/media/usbvideo.h --- a/drivers/usb/media/usbvideo.h Sun Aug 18 20:48:36 2002 +++ b/drivers/usb/media/usbvideo.h Sun Aug 18 20:48:36 2002 @@ -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)]) typedef struct { unsigned char *queue; /* Data from the Isoc data pump */ @@ -306,8 +307,18 @@ int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len); int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n); -int RingQueue_GetLength(const RingQueue_t *rq); void RingQueue_WakeUpInterruptible(RingQueue_t *rq); +void RingQueue_Flush(RingQueue_t *rq); + +static inline int RingQueue_GetLength(const RingQueue_t *rq) +{ + return (rq->wi - rq->ri + rq->length) & (rq->length-1); +} + +static inline int RingQueue_GetFreeSpace(const RingQueue_t *rq) +{ + return rq->length - RingQueue_GetLength(rq); +} void usbvideo_DrawLine( usbvideo_frame_t *frame,