Fw: [PATCH] usbvision_v4l2 robustness on disconnect

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





----- Forwarded Message ----
From: Thierry <thierry.merle@xxxxxxx>
To: Linux and Kernel Video <video4linux-list@xxxxxxxxxx>
Sent: Friday, November 10, 2006 2:18:12 AM
Subject: [PATCH] usbvision_v4l2 robustness on disconnect

Hello,
this patch corrects 2 bugs (causes kernel oops) that occur when
unplugging the peripheral whereas nobody has opened it yet :
- do not call usbvision_stop_isoc if usbvision_init_isoc has not been called
- do not call wakeup_interruptible on waitqueues that did not have been
initialized with init_waitqueue_head
Cheers,
Thierry

Signed-off-by: Thierry MERLE <thierry.merle@xxxxxxx>
---

diff -r 2ed79285f83d linux/drivers/media/video/usbvision/usbvision-core.c
--- a/linux/drivers/media/video/usbvision/usbvision-core.c    Wed Nov 08 22:48:37 2006 -0200
+++ b/linux/drivers/media/video/usbvision/usbvision-core.c    Fri Nov 10 07:01:57 2006 +0000
@@ -2347,7 +2347,7 @@ static void usbvision_isocIrq(struct urb

    /* Manage streaming interruption */
    if (usbvision->streaming == Stream_Interrupt) {
-        usbvision->streaming = Stream_Off;
+        usbvision->streaming = Stream_Idle;
        if ((*f)) {
            (*f)->grabstate = FrameState_Ready;
            (*f)->scanstate = ScanState_Scanning;
@@ -3244,7 +3244,7 @@ static int usbvision_stream_interrupt(st

    usbvision->streaming = Stream_Interrupt;
    ret = wait_event_timeout(usbvision->wait_stream,
-                 (usbvision->streaming == Stream_Off),
+                 (usbvision->streaming == Stream_Idle),
                 msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
    return ret;
}
@@ -3770,7 +3770,7 @@ static int usbvision_init_isoc(struct us
        }
    }

-    usbvision->streaming = Stream_On;
+    usbvision->streaming = Stream_Idle;
    PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
    return 0;
}
@@ -3786,8 +3786,7 @@ static void usbvision_stop_isoc(struct u
{
    int bufIdx, errCode, regValue;

-    // FIXME : removed the streaming==Stream_Off. This field has not the same signification than before !
-    if (usbvision->dev == NULL)
+    if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
        return;

    /* Unschedule all of the iso td's */
@@ -4547,7 +4546,7 @@ static int usbvision_v4l2_do_ioctl(struc
                return -EINVAL;

            if (list_empty(&(usbvision->outqueue))) {
-                if (usbvision->streaming == Stream_Off)
+                if (usbvision->streaming == Stream_Idle)
                    return -EINVAL;
                ret = wait_event_interruptible
                    (usbvision->wait_frame,
@@ -6101,6 +6100,7 @@ static int __devinit usbvision_probe(str
    usbvision->isocPacketSize = 0;
    usbvision->usb_bandwidth = 0;
    usbvision->user = 0;
+    usbvision->streaming = Stream_Off;

    usbvision_register_video(usbvision);
    usbvision_configure_video(usbvision);
@@ -6168,13 +6168,12 @@ static void __devexit usbvision_disconne
#endif
    usbvision->dev = NULL;    // USB device is no more

-    wake_up_interruptible(&usbvision->wait_frame);
-    wake_up_interruptible(&usbvision->wait_stream);
-
    up(&usbvision->lock);

    if (usbvision->user) {
        info("%s: In use, disconnect pending", __FUNCTION__);
+        wake_up_interruptible(&usbvision->wait_frame);
+        wake_up_interruptible(&usbvision->wait_stream);
    }
    else {
        usbvision_release(usbvision);
diff -r 2ed79285f83d linux/drivers/media/video/usbvision/usbvision.h
--- a/linux/drivers/media/video/usbvision/usbvision.h    Wed Nov 08 22:48:37 2006 -0200
+++ b/linux/drivers/media/video/usbvision/usbvision.h    Fri Nov 10 07:08:22 2006 +0000
@@ -265,9 +265,10 @@ enum FrameState {

/* stream states */
enum StreamState {
-    Stream_Off,
-    Stream_Interrupt,
-    Stream_On,
+    Stream_Off,        /* Driver streaming is completely OFF */
+    Stream_Idle,        /* Driver streaming is ready to be put ON by the application */
+    Stream_Interrupt,    /* Driver streaming must be interrupted */
+    Stream_On,        /* Driver streaming is put ON by the application */
};

enum IsocState {

--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list

diff -r 2ed79285f83d linux/drivers/media/video/usbvision/usbvision-core.c
--- a/linux/drivers/media/video/usbvision/usbvision-core.c	Wed Nov 08 22:48:37 2006 -0200
+++ b/linux/drivers/media/video/usbvision/usbvision-core.c	Fri Nov 10 07:01:57 2006 +0000
@@ -2347,7 +2347,7 @@ static void usbvision_isocIrq(struct urb
 
 	/* Manage streaming interruption */
 	if (usbvision->streaming == Stream_Interrupt) {
-		usbvision->streaming = Stream_Off;
+		usbvision->streaming = Stream_Idle;
 		if ((*f)) {
 			(*f)->grabstate = FrameState_Ready;
 			(*f)->scanstate = ScanState_Scanning;
@@ -3244,7 +3244,7 @@ static int usbvision_stream_interrupt(st
 
 	usbvision->streaming = Stream_Interrupt;
 	ret = wait_event_timeout(usbvision->wait_stream,
-				 (usbvision->streaming == Stream_Off),
+				 (usbvision->streaming == Stream_Idle),
 				 msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
 	return ret;
 }
@@ -3770,7 +3770,7 @@ static int usbvision_init_isoc(struct us
 		}
 	}
 
-	usbvision->streaming = Stream_On;
+	usbvision->streaming = Stream_Idle;
 	PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
 	return 0;
 }
@@ -3786,8 +3786,7 @@ static void usbvision_stop_isoc(struct u
 {
 	int bufIdx, errCode, regValue;
 
-	// FIXME : removed the streaming==Stream_Off. This field has not the same signification than before !
-	if (usbvision->dev == NULL)
+	if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
 		return;
 
 	/* Unschedule all of the iso td's */
@@ -4547,7 +4546,7 @@ static int usbvision_v4l2_do_ioctl(struc
 				return -EINVAL;
 
 			if (list_empty(&(usbvision->outqueue))) {
-				if (usbvision->streaming == Stream_Off)
+				if (usbvision->streaming == Stream_Idle)
 					return -EINVAL;
 				ret = wait_event_interruptible
 					(usbvision->wait_frame,
@@ -6101,6 +6100,7 @@ static int __devinit usbvision_probe(str
 	usbvision->isocPacketSize = 0;
 	usbvision->usb_bandwidth = 0;
 	usbvision->user = 0;
+	usbvision->streaming = Stream_Off;
 
 	usbvision_register_video(usbvision);
 	usbvision_configure_video(usbvision);
@@ -6168,13 +6168,12 @@ static void __devexit usbvision_disconne
 #endif
 	usbvision->dev = NULL;	// USB device is no more
 
-	wake_up_interruptible(&usbvision->wait_frame);
-	wake_up_interruptible(&usbvision->wait_stream);
-
 	up(&usbvision->lock);
 
 	if (usbvision->user) {
 		info("%s: In use, disconnect pending", __FUNCTION__);
+		wake_up_interruptible(&usbvision->wait_frame);
+		wake_up_interruptible(&usbvision->wait_stream);
 	}
 	else {
 		usbvision_release(usbvision);
diff -r 2ed79285f83d linux/drivers/media/video/usbvision/usbvision.h
--- a/linux/drivers/media/video/usbvision/usbvision.h	Wed Nov 08 22:48:37 2006 -0200
+++ b/linux/drivers/media/video/usbvision/usbvision.h	Fri Nov 10 07:08:22 2006 +0000
@@ -265,9 +265,10 @@ enum FrameState {
 
 /* stream states */
 enum StreamState {
-	Stream_Off,
-	Stream_Interrupt,
-	Stream_On,
+	Stream_Off,		/* Driver streaming is completely OFF */
+	Stream_Idle,		/* Driver streaming is ready to be put ON by the application */
+	Stream_Interrupt,	/* Driver streaming must be interrupted */
+	Stream_On,		/* Driver streaming is put ON by the application */
 };
 
 enum IsocState {

_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux