diff options
author | Thierry <thierry.merle@free.fr> | 2006-12-04 06:31:17 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 06:05:46 -0500 |
commit | 5f7fb877be14da92803f0b5b60955e071ebe2d58 (patch) | |
tree | 31f2201908f778d5d02ffb798bfa37346efaf108 /drivers/media/video/usbvision | |
parent | f2242ee5474f46d87a45cd4e214b5c3aa02ff293 (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>
Diffstat (limited to 'drivers/media/video/usbvision')
-rw-r--r-- | drivers/media/video/usbvision/usbvision-core.c | 17 | ||||
-rw-r--r-- | drivers/media/video/usbvision/usbvision.h | 7 |
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 */ |
229 | enum StreamState { | 229 | enum 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 | ||
235 | enum IsocState { | 236 | enum IsocState { |