V4L/DVB: usbvision: remove BKL from usbvision
authorHans Verkuil <hverkuil@xs4all.nl>
Fri, 17 Sep 2010 18:07:28 +0000 (15:07 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 21 Oct 2010 03:06:06 +0000 (01:06 -0200)
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>
drivers/media/video/usbvision/usbvision-i2c.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/usbvision/usbvision.h

index 42ba287..a5fd2aa 100644 (file)
@@ -211,6 +211,9 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision)
                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 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision)
                                &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 @@ int usbvision_i2c_register(struct usb_usbvision *usbvision)
                        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);
 
index c2690df..db6b828 100644 (file)
@@ -357,7 +357,7 @@ static int usbvision_v4l2_open(struct file *file)
 
        PDEBUG(DBG_IO, "open");
 
-       lock_kernel();
+       mutex_lock(&usbvision->lock);
        usbvision_reset_powerOffTimer(usbvision);
 
        if (usbvision->user)
@@ -379,7 +379,6 @@ static int usbvision_v4l2_open(struct file *file)
 
        /* 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 @@ static int usbvision_v4l2_open(struct file *file)
                                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 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
        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);
index d1b3cc0..cc4e96c 100644 (file)
@@ -363,6 +363,7 @@ struct usb_usbvision {
 
        /* i2c Declaration Section*/
        struct i2c_adapter i2c_adap;
+       int registered_i2c;
 
        struct urb *ctrlUrb;
        unsigned char ctrlUrbBuffer[8];