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