aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry <thierry.merle@free.fr>2006-12-04 06:31:17 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-12-10 06:05:46 -0500
commit5f7fb877be14da92803f0b5b60955e071ebe2d58 (patch)
tree31f2201908f778d5d02ffb798bfa37346efaf108
parentf2242ee5474f46d87a45cd4e214b5c3aa02ff293 (diff)
V4L/DVB (4928): Usbvision_v4l2 robustness on disconnect
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 Signed-off-by: Thierry MERLE <thierry.merle@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/usbvision/usbvision-core.c17
-rw-r--r--drivers/media/video/usbvision/usbvision.h7
2 files changed, 12 insertions, 12 deletions
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index 06e8e67da362..5a61ed728b35 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -2287,7 +2287,7 @@ static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs)
2287 2287
2288 /* Manage streaming interruption */ 2288 /* Manage streaming interruption */
2289 if (usbvision->streaming == Stream_Interrupt) { 2289 if (usbvision->streaming == Stream_Interrupt) {
2290 usbvision->streaming = Stream_Off; 2290 usbvision->streaming = Stream_Idle;
2291 if ((*f)) { 2291 if ((*f)) {
2292 (*f)->grabstate = FrameState_Ready; 2292 (*f)->grabstate = FrameState_Ready;
2293 (*f)->scanstate = ScanState_Scanning; 2293 (*f)->scanstate = ScanState_Scanning;
@@ -3092,7 +3092,7 @@ static int usbvision_stream_interrupt(struct usb_usbvision *usbvision)
3092 3092
3093 usbvision->streaming = Stream_Interrupt; 3093 usbvision->streaming = Stream_Interrupt;
3094 ret = wait_event_timeout(usbvision->wait_stream, 3094 ret = wait_event_timeout(usbvision->wait_stream,
3095 (usbvision->streaming == Stream_Off), 3095 (usbvision->streaming == Stream_Idle),
3096 msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES)); 3096 msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
3097 return ret; 3097 return ret;
3098} 3098}
@@ -3579,7 +3579,7 @@ static int usbvision_init_isoc(struct usb_usbvision *usbvision)
3579 } 3579 }
3580 } 3580 }
3581 3581
3582 usbvision->streaming = Stream_On; 3582 usbvision->streaming = Stream_Idle;
3583 PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); 3583 PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
3584 return 0; 3584 return 0;
3585} 3585}
@@ -3595,8 +3595,7 @@ static void usbvision_stop_isoc(struct usb_usbvision *usbvision)
3595{ 3595{
3596 int bufIdx, errCode, regValue; 3596 int bufIdx, errCode, regValue;
3597 3597
3598 // FIXME : removed the streaming==Stream_Off. This field has not the same signification than before ! 3598 if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
3599 if (usbvision->dev == NULL)
3600 return; 3599 return;
3601 3600
3602 /* Unschedule all of the iso td's */ 3601 /* Unschedule all of the iso td's */
@@ -4292,7 +4291,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
4292 return -EINVAL; 4291 return -EINVAL;
4293 4292
4294 if (list_empty(&(usbvision->outqueue))) { 4293 if (list_empty(&(usbvision->outqueue))) {
4295 if (usbvision->streaming == Stream_Off) 4294 if (usbvision->streaming == Stream_Idle)
4296 return -EINVAL; 4295 return -EINVAL;
4297 ret = wait_event_interruptible 4296 ret = wait_event_interruptible
4298 (usbvision->wait_frame, 4297 (usbvision->wait_frame,
@@ -5665,6 +5664,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
5665 usbvision->isocPacketSize = 0; 5664 usbvision->isocPacketSize = 0;
5666 usbvision->usb_bandwidth = 0; 5665 usbvision->usb_bandwidth = 0;
5667 usbvision->user = 0; 5666 usbvision->user = 0;
5667 usbvision->streaming = Stream_Off;
5668 5668
5669 usbvision_register_video(usbvision); 5669 usbvision_register_video(usbvision);
5670 usbvision_configure_video(usbvision); 5670 usbvision_configure_video(usbvision);
@@ -5713,13 +5713,12 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
5713 usb_put_dev(usbvision->dev); 5713 usb_put_dev(usbvision->dev);
5714 usbvision->dev = NULL; // USB device is no more 5714 usbvision->dev = NULL; // USB device is no more
5715 5715
5716 wake_up_interruptible(&usbvision->wait_frame);
5717 wake_up_interruptible(&usbvision->wait_stream);
5718
5719 up(&usbvision->lock); 5716 up(&usbvision->lock);
5720 5717
5721 if (usbvision->user) { 5718 if (usbvision->user) {
5722 info("%s: In use, disconnect pending", __FUNCTION__); 5719 info("%s: In use, disconnect pending", __FUNCTION__);
5720 wake_up_interruptible(&usbvision->wait_frame);
5721 wake_up_interruptible(&usbvision->wait_stream);
5723 } 5722 }
5724 else { 5723 else {
5725 usbvision_release(usbvision); 5724 usbvision_release(usbvision);
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index 870c0cc81d84..ef83a5c4d2fd 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -227,9 +227,10 @@ enum FrameState {
227 227
228/* stream states */ 228/* stream states */
229enum StreamState { 229enum StreamState {
230 Stream_Off, 230 Stream_Off, /* Driver streaming is completely OFF */
231 Stream_Interrupt, 231 Stream_Idle, /* Driver streaming is ready to be put ON by the application */
232 Stream_On, 232 Stream_Interrupt, /* Driver streaming must be interrupted */
233 Stream_On, /* Driver streaming is put ON by the application */
233}; 234};
234 235
235enum IsocState { 236enum IsocState {