V4L/DVB: usbvision: remove BKL from usbvision

Removed the BKL from usbvision.

There was an initialization bug as well where the i2c bus was registered twice.

Although when the BKL was present no oops was generated, I did run into
other i2c problems. Now that I protect against duplicate i2c registration
that bug is now gone as well.

But trying to disconnect the USB cable while someone is still using the device
still leads to a crash.

Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
index 42ba287..a5fd2aa 100644
--- a/drivers/media/video/usbvision/usbvision-i2c.c
+++ b/drivers/media/video/usbvision/usbvision-i2c.c
@@ -211,6 +211,9 @@
 		0x42 >> 1, 0x40 >> 1,	/* SAA7114, SAA7115 and SAA7118 */
 		I2C_CLIENT_END };
 
+	if (usbvision->registered_i2c)
+		return 0;
+
 	memcpy(&usbvision->i2c_adap, &i2c_adap_template,
 	       sizeof(struct i2c_adapter));
 
@@ -268,6 +271,8 @@
 				&usbvision->i2c_adap, "tuner",
 				"tuner", 0, v4l2_i2c_tuner_addrs(type));
 
+		if (sd == NULL)
+			return -ENODEV;
 		if (usbvision->tuner_type != -1) {
 			tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
 			tun_setup.type = usbvision->tuner_type;
@@ -275,14 +280,18 @@
 			call_all(usbvision, tuner, s_type_addr, &tun_setup);
 		}
 	}
+	usbvision->registered_i2c = 1;
 
 	return 0;
 }
 
 int usbvision_i2c_unregister(struct usb_usbvision *usbvision)
 {
+	if (!usbvision->registered_i2c)
+		return 0;
 
 	i2c_del_adapter(&(usbvision->i2c_adap));
+	usbvision->registered_i2c = 0;
 
 	PDEBUG(DBG_I2C,"i2c bus for %s unregistered", usbvision->i2c_adap.name);
 
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index c2690df..db6b828 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -357,7 +357,7 @@
 
 	PDEBUG(DBG_IO, "open");
 
-	lock_kernel();
+	mutex_lock(&usbvision->lock);
 	usbvision_reset_powerOffTimer(usbvision);
 
 	if (usbvision->user)
@@ -379,7 +379,6 @@
 
 	/* If so far no errors then we shall start the camera */
 	if (!errCode) {
-		mutex_lock(&usbvision->lock);
 		if (usbvision->power == 0) {
 			usbvision_power_on(usbvision);
 			usbvision_i2c_register(usbvision);
@@ -408,14 +407,13 @@
 				usbvision->initialized = 0;
 			}
 		}
-		mutex_unlock(&usbvision->lock);
 	}
 
 	/* prepare queues */
 	usbvision_empty_framequeues(usbvision);
 
 	PDEBUG(DBG_IO, "success");
-	unlock_kernel();
+	mutex_unlock(&usbvision->lock);
 	return errCode;
 }
 
@@ -1645,8 +1643,8 @@
 	usbvision->usb_bandwidth = 0;
 	usbvision->user = 0;
 	usbvision->streaming = Stream_Off;
-	usbvision_register_video(usbvision);
 	usbvision_configure_video(usbvision);
+	usbvision_register_video(usbvision);
 	mutex_unlock(&usbvision->lock);
 
 	usbvision_create_sysfs(usbvision->vdev);
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index d1b3cc0..cc4e96c 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -363,6 +363,7 @@
 
 	/* i2c Declaration Section*/
 	struct i2c_adapter i2c_adap;
+	int registered_i2c;
 
 	struct urb *ctrlUrb;
 	unsigned char ctrlUrbBuffer[8];