Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f7fb877 authored by Thierry's avatar Thierry Committed by Mauro Carvalho Chehab
Browse files

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: default avatarThierry MERLE <thierry.merle@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent f2242ee5
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -2287,7 +2287,7 @@ static void usbvision_isocIrq(struct urb *urb, struct pt_regs *regs)

	/* 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;
@@ -3092,7 +3092,7 @@ static int usbvision_stream_interrupt(struct usb_usbvision *usbvision)

	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;
}
@@ -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);
	return 0;
}
@@ -3595,8 +3595,7 @@ static void usbvision_stop_isoc(struct usb_usbvision *usbvision)
{
	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 */
@@ -4292,7 +4291,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file,
				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,
@@ -5665,6 +5664,7 @@ static int __devinit usbvision_probe(struct usb_interface *intf, const struct us
	usbvision->isocPacketSize = 0;
	usbvision->usb_bandwidth = 0;
	usbvision->user = 0;
	usbvision->streaming = Stream_Off;

	usbvision_register_video(usbvision);
	usbvision_configure_video(usbvision);
@@ -5713,13 +5713,12 @@ static void __devexit usbvision_disconnect(struct usb_interface *intf)
	usb_put_dev(usbvision->dev);
	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);
+4 −3
Original line number Diff line number Diff line
@@ -227,9 +227,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 {