|
@@ -184,6 +184,7 @@ static int soc_camera_open(struct inode *inode, struct file *file)
|
|
|
struct soc_camera_device *icd;
|
|
|
struct soc_camera_host *ici;
|
|
|
struct soc_camera_file *icf;
|
|
|
+ spinlock_t *lock;
|
|
|
int ret;
|
|
|
|
|
|
icf = vmalloc(sizeof(*icf));
|
|
@@ -209,10 +210,16 @@ static int soc_camera_open(struct inode *inode, struct file *file)
|
|
|
goto emgi;
|
|
|
}
|
|
|
|
|
|
- icd->use_count++;
|
|
|
-
|
|
|
icf->icd = icd;
|
|
|
|
|
|
+ icf->lock = ici->ops->spinlock_alloc(icf);
|
|
|
+ if (!icf->lock) {
|
|
|
+ ret = -ENOMEM;
|
|
|
+ goto esla;
|
|
|
+ }
|
|
|
+
|
|
|
+ icd->use_count++;
|
|
|
+
|
|
|
/* Now we really have to activate the camera */
|
|
|
if (icd->use_count == 1) {
|
|
|
ret = ici->ops->add(icd);
|
|
@@ -229,8 +236,8 @@ static int soc_camera_open(struct inode *inode, struct file *file)
|
|
|
dev_dbg(&icd->dev, "camera device open\n");
|
|
|
|
|
|
/* We must pass NULL as dev pointer, then all pci_* dma operations
|
|
|
- * transform to normal dma_* ones. Do we need an irqlock? */
|
|
|
- videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL,
|
|
|
+ * transform to normal dma_* ones. */
|
|
|
+ videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock,
|
|
|
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
|
|
|
ici->msize, icd);
|
|
|
|
|
@@ -238,6 +245,11 @@ static int soc_camera_open(struct inode *inode, struct file *file)
|
|
|
|
|
|
/* All errors are entered with the video_lock held */
|
|
|
eiciadd:
|
|
|
+ lock = icf->lock;
|
|
|
+ icf->lock = NULL;
|
|
|
+ if (ici->ops->spinlock_free)
|
|
|
+ ici->ops->spinlock_free(lock);
|
|
|
+esla:
|
|
|
module_put(ici->ops->owner);
|
|
|
emgi:
|
|
|
module_put(icd->ops->owner);
|
|
@@ -253,16 +265,20 @@ static int soc_camera_close(struct inode *inode, struct file *file)
|
|
|
struct soc_camera_device *icd = icf->icd;
|
|
|
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
|
|
struct video_device *vdev = icd->vdev;
|
|
|
+ spinlock_t *lock = icf->lock;
|
|
|
|
|
|
mutex_lock(&video_lock);
|
|
|
icd->use_count--;
|
|
|
if (!icd->use_count)
|
|
|
ici->ops->remove(icd);
|
|
|
+ icf->lock = NULL;
|
|
|
+ if (ici->ops->spinlock_free)
|
|
|
+ ici->ops->spinlock_free(lock);
|
|
|
module_put(icd->ops->owner);
|
|
|
module_put(ici->ops->owner);
|
|
|
mutex_unlock(&video_lock);
|
|
|
|
|
|
- vfree(file->private_data);
|
|
|
+ vfree(icf);
|
|
|
|
|
|
dev_dbg(vdev->dev, "camera device close\n");
|
|
|
|
|
@@ -762,6 +778,21 @@ static void dummy_release(struct device *dev)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+static spinlock_t *spinlock_alloc(struct soc_camera_file *icf)
|
|
|
+{
|
|
|
+ spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
|
|
|
+
|
|
|
+ if (lock)
|
|
|
+ spin_lock_init(lock);
|
|
|
+
|
|
|
+ return lock;
|
|
|
+}
|
|
|
+
|
|
|
+static void spinlock_free(spinlock_t *lock)
|
|
|
+{
|
|
|
+ kfree(lock);
|
|
|
+}
|
|
|
+
|
|
|
int soc_camera_host_register(struct soc_camera_host *ici)
|
|
|
{
|
|
|
int ret;
|
|
@@ -792,6 +823,11 @@ int soc_camera_host_register(struct soc_camera_host *ici)
|
|
|
if (ret)
|
|
|
goto edevr;
|
|
|
|
|
|
+ if (!ici->ops->spinlock_alloc) {
|
|
|
+ ici->ops->spinlock_alloc = spinlock_alloc;
|
|
|
+ ici->ops->spinlock_free = spinlock_free;
|
|
|
+ }
|
|
|
+
|
|
|
scan_add_host(ici);
|
|
|
|
|
|
return 0;
|