V4L/DVB (12845): tm6000: more buffer handling fixes
authorMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 28 Nov 2008 10:39:00 +0000 (07:39 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 18 May 2010 03:40:21 +0000 (00:40 -0300)
Before this patch, we were writing outside vmalloced buffer

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/staging/tm6000/tm6000-video.c

index 3723d83..932dfde 100644 (file)
@@ -273,6 +273,11 @@ static int copy_packet(struct urb *urb, u32 header, u8 **ptr, u8 *endp,
                                        get_next_buf (dma_q, buf);
                                        if (!*buf)
                                                return rc;
+                                       out_p = videobuf_to_vmalloc(&((*buf)->vb));
+                                       if (!out_p)
+                                               return rc;
+
+                                       pos = dev->isoc_ctl.pos = 0;
                                }
                        }
 
@@ -420,6 +425,10 @@ static int copy_multiplexed(u8 *ptr, u8 *out_p, unsigned long len,
                        get_next_buf (dma_q, buf);
                        if (!*buf)
                                break;
+                       out_p = videobuf_to_vmalloc(&((*buf)->vb));
+                       if (!out_p)
+                               return rc;
+                       pos = 0;
                }
        }
 
@@ -471,16 +480,25 @@ static void inline print_err_status (struct tm6000_core *dev,
 /*
  * Controls the isoc copy of each urb packet
  */
-static inline int tm6000_isoc_copy(struct urb *urb, struct tm6000_buffer **buf)
+static inline int tm6000_isoc_copy(struct urb *urb)
 {
        struct tm6000_dmaqueue  *dma_q = urb->context;
        struct tm6000_core *dev= container_of(dma_q,struct tm6000_core,vidq);
-       void *outp=videobuf_to_vmalloc (&((*buf)->vb));
+       struct tm6000_buffer *buf;
        int i, len=0, rc=1;
-       int size=(*buf)->vb.size;
-       char *p;
+       int size;
+       char *outp = NULL, *p;
        unsigned long copied;
 
+       get_next_buf(dma_q, &buf);
+       if (!buf)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       if (!outp)
+               return 0;
+
+       size = buf->vb.size;
+
        copied=0;
 
        if (urb->status<0) {
@@ -501,12 +519,12 @@ static inline int tm6000_isoc_copy(struct urb *urb, struct tm6000_buffer **buf)
 //             if (len>=TM6000_URB_MSG_LEN) {
                        p=urb->transfer_buffer + urb->iso_frame_desc[i].offset;
                        if (!urb->iso_frame_desc[i].status) {
-                               if (((*buf)->fmt->fourcc)==V4L2_PIX_FMT_TM6000) {
-                                       rc=copy_multiplexed(p,outp,len,urb,buf);
+                               if ((buf->fmt->fourcc)==V4L2_PIX_FMT_TM6000) {
+                                       rc=copy_multiplexed(p, outp, len, urb, &buf);
                                        if (rc<=0)
                                                return rc;
                                } else {
-                                       copy_streams(p,outp,len,urb,buf);
+                                       copy_streams(p, outp, len, urb, &buf);
                                }
                        }
                        copied += len;
@@ -526,21 +544,22 @@ static inline int tm6000_isoc_copy(struct urb *urb, struct tm6000_buffer **buf)
  */
 static void tm6000_irq_callback(struct urb *urb)
 {
-       struct tm6000_buffer    *buf = NULL;
        struct tm6000_dmaqueue  *dma_q = urb->context;
        struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       unsigned long flags;
+       int i;
 
        if (!dev)
                return;
 
-       spin_lock_irqsave(&dev->slock, flags);
-
-       get_next_buf(dma_q, &buf);
-       if (buf)
-                tm6000_isoc_copy(urb, &buf);
-       spin_unlock_irqrestore(&dev->slock, flags);
+       spin_lock(&dev->slock);
+       tm6000_isoc_copy(urb);
+       spin_unlock(&dev->slock);
 
+       /* Reset urb buffers */
+       for (i = 0; i < urb->number_of_packets; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
 
        urb->status = usb_submit_urb(urb, GFP_ATOMIC);
        if (urb->status)