Merge branch 'master' into for_paulus
[linux-drm-fsl-dcu.git] / drivers / media / video / sn9c102 / sn9c102_core.c
index 48d138a7c7235c6c1197afa6c9d9d0010cdd191a..04d4c8f28b89a97f8f9c345b66c9a38f95cae14a 100644 (file)
@@ -518,7 +518,7 @@ sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
 }
 
 
-static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
+static void sn9c102_urb_complete(struct urb *urb)
 {
        struct sn9c102_device* cam = urb->context;
        struct sn9c102_frame_t** f;
@@ -775,7 +775,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
        return 0;
 
 free_urbs:
-       for (i = 0; (i < SN9C102_URBS) &&  cam->urb[i]; i++)
+       for (i = 0; i < SN9C102_URBS; i++)
                usb_free_urb(cam->urb[i]);
 
 free_buffers:
@@ -1240,23 +1240,53 @@ static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
                         sn9c102_show_frame_header, NULL);
 
 
-static void sn9c102_create_sysfs(struct sn9c102_device* cam)
+static int sn9c102_create_sysfs(struct sn9c102_device* cam)
 {
        struct video_device *v4ldev = cam->v4ldev;
+       int rc;
+
+       rc = video_device_create_file(v4ldev, &class_device_attr_reg);
+       if (rc) goto err;
+       rc = video_device_create_file(v4ldev, &class_device_attr_val);
+       if (rc) goto err_reg;
+       rc = video_device_create_file(v4ldev, &class_device_attr_frame_header);
+       if (rc) goto err_val;
 
-       video_device_create_file(v4ldev, &class_device_attr_reg);
-       video_device_create_file(v4ldev, &class_device_attr_val);
-       video_device_create_file(v4ldev, &class_device_attr_frame_header);
-       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
-               video_device_create_file(v4ldev, &class_device_attr_green);
-       else if (cam->bridge == BRIDGE_SN9C103) {
-               video_device_create_file(v4ldev, &class_device_attr_blue);
-               video_device_create_file(v4ldev, &class_device_attr_red);
-       }
        if (cam->sensor.sysfs_ops) {
-               video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
-               video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+               rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
+               if (rc) goto err_frhead;
+               rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val);
+               if (rc) goto err_i2c_reg;
+       }
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
+               rc = video_device_create_file(v4ldev, &class_device_attr_green);
+               if (rc) goto err_i2c_val;
+       } else if (cam->bridge == BRIDGE_SN9C103) {
+               rc = video_device_create_file(v4ldev, &class_device_attr_blue);
+               if (rc) goto err_i2c_val;
+               rc = video_device_create_file(v4ldev, &class_device_attr_red);
+               if (rc) goto err_blue;
        }
+
+       return 0;
+
+err_blue:
+       video_device_remove_file(v4ldev, &class_device_attr_blue);
+err_i2c_val:
+       if (cam->sensor.sysfs_ops)
+               video_device_remove_file(v4ldev, &class_device_attr_i2c_val);
+err_i2c_reg:
+       if (cam->sensor.sysfs_ops)
+               video_device_remove_file(v4ldev, &class_device_attr_i2c_reg);
+err_frhead:
+       video_device_remove_file(v4ldev, &class_device_attr_frame_header);
+err_val:
+       video_device_remove_file(v4ldev, &class_device_attr_val);
+err_reg:
+       video_device_remove_file(v4ldev, &class_device_attr_reg);
+err:
+       return rc;
 }
 #endif /* CONFIG_VIDEO_ADV_DEBUG */
 
@@ -1432,8 +1462,6 @@ static void sn9c102_release_resources(struct sn9c102_device* cam)
        video_set_drvdata(cam->v4ldev, NULL);
        video_unregister_device(cam->v4ldev);
 
-       usb_put_dev(cam->usbdev);
-
        mutex_unlock(&sn9c102_sysfs_lock);
 
        kfree(cam->control_buffer);
@@ -1525,6 +1553,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp)
 
        if (cam->state & DEV_DISCONNECTED) {
                sn9c102_release_resources(cam);
+               usb_put_dev(cam->usbdev);
                mutex_unlock(&cam->dev_mutex);
                kfree(cam);
                return 0;
@@ -2707,7 +2736,7 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
 
 /*****************************************************************************/
 
-static struct file_operations sn9c102_fops = {
+static const struct file_operations sn9c102_fops = {
        .owner = THIS_MODULE,
        .open =    sn9c102_open,
        .release = sn9c102_release,
@@ -2809,10 +2838,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
                DBG(1, "V4L2 device registration failed");
                if (err == -ENFILE && video_nr[dev_nr] == -1)
                        DBG(1, "Free /dev/videoX node not found");
-               video_nr[dev_nr] = -1;
-               dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-               mutex_unlock(&cam->dev_mutex);
-               goto fail;
+               goto fail2;
        }
 
        DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor);
@@ -2823,7 +2849,9 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
        dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-       sn9c102_create_sysfs(cam);
+       err = sn9c102_create_sysfs(cam);
+       if (err)
+               goto fail3;
        DBG(2, "Optional device control through 'sysfs' interface ready");
 #endif
 
@@ -2833,6 +2861,14 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 
        return 0;
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+fail3:
+       video_unregister_device(cam->v4ldev);
+#endif
+fail2:
+       video_nr[dev_nr] = -1;
+       dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
+       mutex_unlock(&cam->dev_mutex);
 fail:
        if (cam) {
                kfree(cam->control_buffer);