uvc: sync bitland
authorddl <ddl@rock-chips.com>
Thu, 5 Sep 2013 09:10:49 +0000 (17:10 +0800)
committerddl <ddl@rock-chips.com>
Thu, 5 Sep 2013 09:11:06 +0000 (17:11 +0800)
drivers/media/video/uvc/uvc_queue.c [changed mode: 0644->0755]
drivers/media/video/uvc/uvc_video.c
drivers/media/video/uvc/uvcvideo.h

old mode 100644 (file)
new mode 100755 (executable)
index 1b9f126..0abe145
@@ -390,9 +390,9 @@ checks:
         /* ddl@rock-chips.com: It is timeout */
         if (ret == 0) {
             ret = -EINVAL;
-            printk(KERN_ERR "uvcvideo: uvc_dequeue_buffer is timeout!!");
+            printk(KERN_ERR "uvcvideo: uvc_dequeue_buffer is timeout!!\n");
         } else {
-            printk(KERN_ERR "uvcvideo: uvc_dequeue_buffer is failed!!(ret:%d)",ret);
+            printk(KERN_ERR "uvcvideo: uvc_dequeue_buffer is failed!!(ret:%d)\n",ret);
         }
                goto done;
        }
index c7a054fa655467803f4b42890f84072a19d30be2..b596442d32e81be10302998029a6451f2bb1aba5 100755 (executable)
@@ -750,6 +750,8 @@ static void uvc_video_complete_fun (struct urb *urb)
        struct uvc_buffer *buf = NULL;
        unsigned long flags;
        int ret;
+       int i;
+       atomic_t *urb_state=NULL;
 
        switch (urb->status) {
        case 0:
@@ -769,14 +771,33 @@ static void uvc_video_complete_fun (struct urb *urb)
                return;
        }
 
+    for (i = 0; i < UVC_URBS; ++i) {    
+        if (stream->urb[i] == urb) {
+            urb_state = &stream->urb_state[i];
+            break;
+        }
+    }
+
+    if (urb_state == NULL) {
+        printk("urb(%p) cann't be finded in stream->urb(%p, %p, %p, %p, %p)\n",
+              urb,stream->urb[0],stream->urb[1],stream->urb[2],stream->urb[3],stream->urb[4]);
+        BUG();
+    }
+       
+       if (atomic_read(urb_state)==UrbDeactive) {
+           printk(KERN_DEBUG "urb is deactive, this urb complete cancel!");
+               uvc_queue_cancel(queue, urb->status == -ESHUTDOWN);
+           return;
+       }
+
        spin_lock_irqsave(&queue->irqlock, flags);
        if (!list_empty(&queue->irqqueue))
                buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
                                       queue);
-       spin_unlock_irqrestore(&queue->irqlock, flags);
-
+    spin_unlock_irqrestore(&queue->irqlock, flags);    
+    
        stream->decode(urb, stream, buf);
-
+       
        if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
                uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
                        ret);
@@ -784,18 +805,9 @@ static void uvc_video_complete_fun (struct urb *urb)
 }
 static void uvc_video_complete_tasklet(unsigned long data)
 {
-    struct urb *urb = (struct urb*)data;
-    struct uvc_streaming *stream = urb->context;
-    struct tasklet_struct *tasklet = NULL;
-    int i;
+    struct urb *urb = (struct urb*)data;   
     
-    uvc_video_complete_fun(urb);
-    for (i = 0; i < UVC_URBS; ++i) {    
-        if (stream->urb[i] == urb) {
-            tasklet = stream->tasklet[i];
-            break;
-        }
-    }
+    uvc_video_complete_fun(urb);    
     
     return;
 }
@@ -804,15 +816,17 @@ static void uvc_video_complete(struct urb *urb)
     int i;
     struct uvc_streaming *stream = urb->context;
     struct tasklet_struct *tasklet = NULL;
+    atomic_t *urb_state;
     
     for (i = 0; i < UVC_URBS; ++i) {    
         if (stream->urb[i] == urb) {
             tasklet = stream->tasklet[i];
+            urb_state = &stream->urb_state[i];
             break;
         }
     }
 
-    if (tasklet != NULL) {
+    if ((tasklet != NULL)&&(atomic_read(urb_state)==UrbActive)) {
         tasklet_schedule(tasklet);
     } else {
         uvc_video_complete_fun(urb);
@@ -903,8 +917,9 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
                urb = stream->urb[i];
                if (urb == NULL)
                        continue;
-
-        /* ddl@rock-chips.com: Tasklet must be kill before kill urb in uninit */
+               else
+                   atomic_set(&stream->urb_state[i],UrbDeactive);
+               
         if (stream->tasklet[i]) {
             tasklet_kill(stream->tasklet[i]);
             kfree(stream->tasklet[i]);
@@ -969,6 +984,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
 
                stream->urb[i] = urb;
         /* ddl@rock-chips.com  */
+        atomic_set(&stream->urb_state[i],UrbActive);
         stream->tasklet[i] = kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
         if (stream->tasklet[i] == NULL) {
             uvc_printk(KERN_ERR, "device %s requested tasklet memory fail!\n",
index 4abb2f2f0a2be9a8f9d3d5388b906a529e6fd1e9..a85879cacb3baddac5d2541aee675430c033bb90 100755 (executable)
@@ -452,7 +452,10 @@ struct uvc_video_chain {
 
        struct mutex ctrl_mutex;                /* Protects ctrl.info */
 };
-
+enum uvc_urb_state {
+    UrbActive,
+    UrbDeactive
+};
 struct uvc_streaming {
        struct list_head list;
        struct uvc_device *dev;
@@ -501,6 +504,8 @@ struct uvc_streaming {
        __u8 last_fid;
 
     struct tasklet_struct *tasklet[UVC_URBS];     /* ddl@rock-chips.com */
+    atomic_t urb_state[UVC_URBS];
+    
     unsigned int flags;
 };