mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 16:41:58 +00:00
V4L/DVB (7501): soc-camera: use a spinlock for videobuffer queue
All drivers should provide a spinlock to be used in videobuf operations. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> Reviewed-by: Brandon Philips <bphilips@suse.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
parent
b8d9904c35
commit
1a0063a985
@ -803,6 +803,15 @@ static int pxa_camera_querycap(struct soc_camera_host *ici,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf)
|
||||||
|
{
|
||||||
|
struct soc_camera_host *ici =
|
||||||
|
to_soc_camera_host(icf->icd->dev.parent);
|
||||||
|
struct pxa_camera_dev *pcdev = ici->priv;
|
||||||
|
|
||||||
|
return &pcdev->lock;
|
||||||
|
}
|
||||||
|
|
||||||
static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
|
static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.add = pxa_camera_add_device,
|
.add = pxa_camera_add_device,
|
||||||
@ -814,6 +823,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
|
|||||||
.querycap = pxa_camera_querycap,
|
.querycap = pxa_camera_querycap,
|
||||||
.try_bus_param = pxa_camera_try_bus_param,
|
.try_bus_param = pxa_camera_try_bus_param,
|
||||||
.set_bus_param = pxa_camera_set_bus_param,
|
.set_bus_param = pxa_camera_set_bus_param,
|
||||||
|
.spinlock_alloc = pxa_camera_spinlock_alloc,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Should be allocated dynamically too, but we have only one. */
|
/* Should be allocated dynamically too, but we have only one. */
|
||||||
|
@ -184,6 +184,7 @@ static int soc_camera_open(struct inode *inode, struct file *file)
|
|||||||
struct soc_camera_device *icd;
|
struct soc_camera_device *icd;
|
||||||
struct soc_camera_host *ici;
|
struct soc_camera_host *ici;
|
||||||
struct soc_camera_file *icf;
|
struct soc_camera_file *icf;
|
||||||
|
spinlock_t *lock;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
icf = vmalloc(sizeof(*icf));
|
icf = vmalloc(sizeof(*icf));
|
||||||
@ -209,10 +210,16 @@ static int soc_camera_open(struct inode *inode, struct file *file)
|
|||||||
goto emgi;
|
goto emgi;
|
||||||
}
|
}
|
||||||
|
|
||||||
icd->use_count++;
|
|
||||||
|
|
||||||
icf->icd = icd;
|
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 */
|
/* Now we really have to activate the camera */
|
||||||
if (icd->use_count == 1) {
|
if (icd->use_count == 1) {
|
||||||
ret = ici->ops->add(icd);
|
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");
|
dev_dbg(&icd->dev, "camera device open\n");
|
||||||
|
|
||||||
/* We must pass NULL as dev pointer, then all pci_* dma operations
|
/* We must pass NULL as dev pointer, then all pci_* dma operations
|
||||||
* transform to normal dma_* ones. Do we need an irqlock? */
|
* transform to normal dma_* ones. */
|
||||||
videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL,
|
videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock,
|
||||||
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
|
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
|
||||||
ici->msize, icd);
|
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 */
|
/* All errors are entered with the video_lock held */
|
||||||
eiciadd:
|
eiciadd:
|
||||||
|
lock = icf->lock;
|
||||||
|
icf->lock = NULL;
|
||||||
|
if (ici->ops->spinlock_free)
|
||||||
|
ici->ops->spinlock_free(lock);
|
||||||
|
esla:
|
||||||
module_put(ici->ops->owner);
|
module_put(ici->ops->owner);
|
||||||
emgi:
|
emgi:
|
||||||
module_put(icd->ops->owner);
|
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_device *icd = icf->icd;
|
||||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||||
struct video_device *vdev = icd->vdev;
|
struct video_device *vdev = icd->vdev;
|
||||||
|
spinlock_t *lock = icf->lock;
|
||||||
|
|
||||||
mutex_lock(&video_lock);
|
mutex_lock(&video_lock);
|
||||||
icd->use_count--;
|
icd->use_count--;
|
||||||
if (!icd->use_count)
|
if (!icd->use_count)
|
||||||
ici->ops->remove(icd);
|
ici->ops->remove(icd);
|
||||||
|
icf->lock = NULL;
|
||||||
|
if (ici->ops->spinlock_free)
|
||||||
|
ici->ops->spinlock_free(lock);
|
||||||
module_put(icd->ops->owner);
|
module_put(icd->ops->owner);
|
||||||
module_put(ici->ops->owner);
|
module_put(ici->ops->owner);
|
||||||
mutex_unlock(&video_lock);
|
mutex_unlock(&video_lock);
|
||||||
|
|
||||||
vfree(file->private_data);
|
vfree(icf);
|
||||||
|
|
||||||
dev_dbg(vdev->dev, "camera device close\n");
|
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 soc_camera_host_register(struct soc_camera_host *ici)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -792,6 +823,11 @@ int soc_camera_host_register(struct soc_camera_host *ici)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto edevr;
|
goto edevr;
|
||||||
|
|
||||||
|
if (!ici->ops->spinlock_alloc) {
|
||||||
|
ici->ops->spinlock_alloc = spinlock_alloc;
|
||||||
|
ici->ops->spinlock_free = spinlock_free;
|
||||||
|
}
|
||||||
|
|
||||||
scan_add_host(ici);
|
scan_add_host(ici);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -48,6 +48,7 @@ struct soc_camera_device {
|
|||||||
struct soc_camera_file {
|
struct soc_camera_file {
|
||||||
struct soc_camera_device *icd;
|
struct soc_camera_device *icd;
|
||||||
struct videobuf_queue vb_vidq;
|
struct videobuf_queue vb_vidq;
|
||||||
|
spinlock_t *lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct soc_camera_host {
|
struct soc_camera_host {
|
||||||
@ -73,6 +74,8 @@ struct soc_camera_host_ops {
|
|||||||
int (*try_bus_param)(struct soc_camera_device *, __u32);
|
int (*try_bus_param)(struct soc_camera_device *, __u32);
|
||||||
int (*set_bus_param)(struct soc_camera_device *, __u32);
|
int (*set_bus_param)(struct soc_camera_device *, __u32);
|
||||||
unsigned int (*poll)(struct file *, poll_table *);
|
unsigned int (*poll)(struct file *, poll_table *);
|
||||||
|
spinlock_t* (*spinlock_alloc)(struct soc_camera_file *);
|
||||||
|
void (*spinlock_free)(spinlock_t *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct soc_camera_link {
|
struct soc_camera_link {
|
||||||
|
Loading…
Reference in New Issue
Block a user