mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
f2242ee547
commit
5f7fb877be
|
@ -2287,7 +2287,7 @@ static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs)
|
||||||
|
|
||||||
/* Manage streaming interruption */
|
/* Manage streaming interruption */
|
||||||
if (usbvision->streaming == Stream_Interrupt) {
|
if (usbvision->streaming == Stream_Interrupt) {
|
||||||
usbvision->streaming = Stream_Off;
|
usbvision->streaming = Stream_Idle;
|
||||||
if ((*f)) {
|
if ((*f)) {
|
||||||
(*f)->grabstate = FrameState_Ready;
|
(*f)->grabstate = FrameState_Ready;
|
||||||
(*f)->scanstate = ScanState_Scanning;
|
(*f)->scanstate = ScanState_Scanning;
|
||||||
|
@ -3092,7 +3092,7 @@ static int usbvision_stream_interrupt(struct usb_usbvision *usbvision)
|
||||||
|
|
||||||
usbvision->streaming = Stream_Interrupt;
|
usbvision->streaming = Stream_Interrupt;
|
||||||
ret = wait_event_timeout(usbvision->wait_stream,
|
ret = wait_event_timeout(usbvision->wait_stream,
|
||||||
(usbvision->streaming == Stream_Off),
|
(usbvision->streaming == Stream_Idle),
|
||||||
msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
|
msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3579,7 +3579,7 @@ static int usbvision_init_isoc(struct usb_usbvision *usbvision)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usbvision->streaming = Stream_On;
|
usbvision->streaming = Stream_Idle;
|
||||||
PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
|
PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3595,8 +3595,7 @@ static void usbvision_stop_isoc(struct usb_usbvision *usbvision)
|
||||||
{
|
{
|
||||||
int bufIdx, errCode, regValue;
|
int bufIdx, errCode, regValue;
|
||||||
|
|
||||||
// FIXME : removed the streaming==Stream_Off. This field has not the same signification than before !
|
if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
|
||||||
if (usbvision->dev == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Unschedule all of the iso td's */
|
/* Unschedule all of the iso td's */
|
||||||
|
@ -4292,7 +4291,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (list_empty(&(usbvision->outqueue))) {
|
if (list_empty(&(usbvision->outqueue))) {
|
||||||
if (usbvision->streaming == Stream_Off)
|
if (usbvision->streaming == Stream_Idle)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
ret = wait_event_interruptible
|
ret = wait_event_interruptible
|
||||||
(usbvision->wait_frame,
|
(usbvision->wait_frame,
|
||||||
|
@ -5665,6 +5664,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
|
||||||
usbvision->isocPacketSize = 0;
|
usbvision->isocPacketSize = 0;
|
||||||
usbvision->usb_bandwidth = 0;
|
usbvision->usb_bandwidth = 0;
|
||||||
usbvision->user = 0;
|
usbvision->user = 0;
|
||||||
|
usbvision->streaming = Stream_Off;
|
||||||
|
|
||||||
usbvision_register_video(usbvision);
|
usbvision_register_video(usbvision);
|
||||||
usbvision_configure_video(usbvision);
|
usbvision_configure_video(usbvision);
|
||||||
|
@ -5713,13 +5713,12 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
|
||||||
usb_put_dev(usbvision->dev);
|
usb_put_dev(usbvision->dev);
|
||||||
usbvision->dev = NULL; // USB device is no more
|
usbvision->dev = NULL; // USB device is no more
|
||||||
|
|
||||||
wake_up_interruptible(&usbvision->wait_frame);
|
|
||||||
wake_up_interruptible(&usbvision->wait_stream);
|
|
||||||
|
|
||||||
up(&usbvision->lock);
|
up(&usbvision->lock);
|
||||||
|
|
||||||
if (usbvision->user) {
|
if (usbvision->user) {
|
||||||
info("%s: In use, disconnect pending", __FUNCTION__);
|
info("%s: In use, disconnect pending", __FUNCTION__);
|
||||||
|
wake_up_interruptible(&usbvision->wait_frame);
|
||||||
|
wake_up_interruptible(&usbvision->wait_stream);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
usbvision_release(usbvision);
|
usbvision_release(usbvision);
|
||||||
|
|
|
@ -227,9 +227,10 @@ enum FrameState {
|
||||||
|
|
||||||
/* stream states */
|
/* stream states */
|
||||||
enum StreamState {
|
enum StreamState {
|
||||||
Stream_Off,
|
Stream_Off, /* Driver streaming is completely OFF */
|
||||||
Stream_Interrupt,
|
Stream_Idle, /* Driver streaming is ready to be put ON by the application */
|
||||||
Stream_On,
|
Stream_Interrupt, /* Driver streaming must be interrupted */
|
||||||
|
Stream_On, /* Driver streaming is put ON by the application */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum IsocState {
|
enum IsocState {
|
||||||
|
|
Loading…
Reference in New Issue