static int soc_camera_open(struct inode *inode, struct file *file)
 {
-       struct video_device *vdev = video_devdata(file);
-       struct soc_camera_device *icd = container_of(vdev->dev,
-                                            struct soc_camera_device, dev);
-       struct soc_camera_host *ici =
-               to_soc_camera_host(icd->dev.parent);
+       struct video_device *vdev;
+       struct soc_camera_device *icd;
+       struct soc_camera_host *ici;
        struct soc_camera_file *icf;
        int ret;
 
        if (!icf)
                return -ENOMEM;
 
-       icf->icd = icd;
+       /* Protect against icd->remove() until we module_get() both drivers. */
+       mutex_lock(&video_lock);
+
+       vdev = video_devdata(file);
+       icd = container_of(vdev->dev, struct soc_camera_device, dev);
+       ici = to_soc_camera_host(icd->dev.parent);
 
        if (!try_module_get(icd->ops->owner)) {
                dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
                goto emgi;
        }
 
+       icd->use_count++;
+
+       icf->icd = icd;
+
+       /* Now we really have to activate the camera */
+       if (icd->use_count == 1) {
+               ret = ici->add(icd);
+               if (ret < 0) {
+                       dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
+                       icd->use_count--;
+                       goto eiciadd;
+               }
+       }
+
+       mutex_unlock(&video_lock);
+
        file->private_data = icf;
        dev_dbg(&icd->dev, "camera device open\n");
 
 
        return 0;
 
+       /* All errors are entered with the video_lock held */
+eiciadd:
+       module_put(ici->owner);
 emgi:
        module_put(icd->ops->owner);
 emgd:
+       mutex_unlock(&video_lock);
        vfree(icf);
        return ret;
 }
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct video_device *vdev = icd->vdev;
 
+       mutex_lock(&video_lock);
+       icd->use_count--;
+       if (!icd->use_count)
+               ici->remove(icd);
        module_put(icd->ops->owner);
        module_put(ici->owner);
+       mutex_unlock(&video_lock);
+
        vfree(file->private_data);
 
        dev_dbg(vdev->dev, "camera device close\n");
        if (!icd->probe)
                return -ENODEV;
 
+       /* We only call ->add() here to activate and probe the camera.
+        * We shall ->remove() and deactivate it immediately afterwards. */
        ret = ici->add(icd);
        if (ret < 0)
                return ret;
 
        ret = icd->probe(icd);
-       if (ret < 0)
-               ici->remove(icd);
-       else {
+       if (ret >= 0) {
                const struct v4l2_queryctrl *qctrl;
 
                qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
                icd->exposure = qctrl ? qctrl->default_value :
                        (unsigned short)~0;
        }
+       ici->remove(icd);
 
        return ret;
 }
 static int soc_camera_remove(struct device *dev)
 {
        struct soc_camera_device *icd = to_soc_camera_dev(dev);
-       struct soc_camera_host *ici =
-               to_soc_camera_host(icd->dev.parent);
 
        if (icd->remove)
                icd->remove(icd);
 
-       ici->remove(icd);
-
        return 0;
 }