From 01b6d97d0059d0f1b5e00d0a6f0e3031460d762f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 4 Apr 2008 13:41:25 +0000 Subject: soc-camera: extract function pointers from host object into operations From: Guennadi Liakhovetski Function pointers and the driver owner are not expected to change throughout soc-camera host's life. Extract them into an operations struct. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pxa_camera.c | 27 +++++++++++++++---------- linux/drivers/media/video/soc_camera.c | 37 +++++++++++++++++----------------- 2 files changed, 34 insertions(+), 30 deletions(-) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 4756699d1..9758f7eb5 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -803,20 +803,25 @@ static int pxa_camera_querycap(struct soc_camera_host *ici, return 0; } -/* Should beallocated dynamically too, but we have only one. */ +static struct soc_camera_host_ops pxa_soc_camera_host_ops = { + .owner = THIS_MODULE, + .add = pxa_camera_add_device, + .remove = pxa_camera_remove_device, + .set_fmt_cap = pxa_camera_set_fmt_cap, + .try_fmt_cap = pxa_camera_try_fmt_cap, + .reqbufs = pxa_camera_reqbufs, + .poll = pxa_camera_poll, + .querycap = pxa_camera_querycap, + .try_bus_param = pxa_camera_try_bus_param, + .set_bus_param = pxa_camera_set_bus_param, +}; + +/* Should be allocated dynamically too, but we have only one. */ static struct soc_camera_host pxa_soc_camera_host = { .drv_name = PXA_CAM_DRV_NAME, .vbq_ops = &pxa_videobuf_ops, - .add = pxa_camera_add_device, - .remove = pxa_camera_remove_device, .msize = sizeof(struct pxa_buffer), - .set_fmt_cap = pxa_camera_set_fmt_cap, - .try_fmt_cap = pxa_camera_try_fmt_cap, - .reqbufs = pxa_camera_reqbufs, - .poll = pxa_camera_poll, - .querycap = pxa_camera_querycap, - .try_bus_param = pxa_camera_try_bus_param, - .set_bus_param = pxa_camera_set_bus_param, + .ops = &pxa_soc_camera_host_ops, }; static int pxa_camera_probe(struct platform_device *pdev) @@ -912,7 +917,7 @@ static int pxa_camera_probe(struct platform_device *pdev) pxa_soc_camera_host.priv = pcdev; pxa_soc_camera_host.dev.parent = &pdev->dev; pxa_soc_camera_host.nr = pdev->id; - err = soc_camera_host_register(&pxa_soc_camera_host, THIS_MODULE); + err = soc_camera_host_register(&pxa_soc_camera_host); if (err) goto exit_free_irq; diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 4af38d444..43c811059 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -76,12 +76,12 @@ static int soc_camera_try_fmt_cap(struct file *file, void *priv, } /* test physical bus parameters */ - ret = ici->try_bus_param(icd, f->fmt.pix.pixelformat); + ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat); if (ret) return ret; /* limit format to hardware capabilities */ - ret = ici->try_fmt_cap(icd, f); + ret = ici->ops->try_fmt_cap(icd, f); /* calculate missing fields */ f->fmt.pix.field = field; @@ -143,7 +143,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv, if (ret < 0) return ret; - return ici->reqbufs(icf, p); + return ici->ops->reqbufs(icf, p); return ret; } @@ -203,7 +203,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) goto emgd; } - if (!try_module_get(ici->owner)) { + if (!try_module_get(ici->ops->owner)) { dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); ret = -EINVAL; goto emgi; @@ -215,7 +215,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* Now we really have to activate the camera */ if (icd->use_count == 1) { - ret = ici->add(icd); + ret = ici->ops->add(icd); if (ret < 0) { dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); icd->use_count--; @@ -238,7 +238,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) /* All errors are entered with the video_lock held */ eiciadd: - module_put(ici->owner); + module_put(ici->ops->owner); emgi: module_put(icd->ops->owner); emgd: @@ -257,9 +257,9 @@ static int soc_camera_close(struct inode *inode, struct file *file) mutex_lock(&video_lock); icd->use_count--; if (!icd->use_count) - ici->remove(icd); + ici->ops->remove(icd); module_put(icd->ops->owner); - module_put(ici->owner); + module_put(ici->ops->owner); mutex_unlock(&video_lock); vfree(file->private_data); @@ -312,7 +312,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt) return POLLERR; } - return ici->poll(file, pt); + return ici->ops->poll(file, pt); } @@ -356,7 +356,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, rect.top = icd->y_current; rect.width = f->fmt.pix.width; rect.height = f->fmt.pix.height; - ret = ici->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); + ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect); if (ret < 0) return ret; @@ -372,7 +372,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv, icd->width, icd->height); /* set physical bus parameters */ - return ici->set_bus_param(icd, f->fmt.pix.pixelformat); + return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat); } static int soc_camera_enum_fmt_cap(struct file *file, void *priv, @@ -426,7 +426,7 @@ static int soc_camera_querycap(struct file *file, void *priv, WARN_ON(priv != file->private_data); strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver)); - return ici->querycap(ici, cap); + return ici->ops->querycap(ici, cap); } static int soc_camera_streamon(struct file *file, void *priv, @@ -579,7 +579,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - ret = ici->set_fmt_cap(icd, 0, &a->c); + ret = ici->ops->set_fmt_cap(icd, 0, &a->c); if (!ret) { icd->width = a->c.width; icd->height = a->c.height; @@ -706,7 +706,7 @@ static int soc_camera_probe(struct device *dev) /* We only call ->add() here to activate and probe the camera. * We shall ->remove() and deactivate it immediately afterwards. */ - ret = ici->add(icd); + ret = ici->ops->add(icd); if (ret < 0) return ret; @@ -720,7 +720,7 @@ static int soc_camera_probe(struct device *dev) icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0; } - ici->remove(icd); + ici->ops->remove(icd); return ret; } @@ -762,12 +762,12 @@ static void dummy_release(struct device *dev) { } -int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) +int soc_camera_host_register(struct soc_camera_host *ici) { int ret; struct soc_camera_host *ix; - if (!ici->vbq_ops || !ici->add || !ici->remove || !owner) + if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove) return -EINVAL; /* Number might be equal to the platform device ID */ @@ -785,7 +785,6 @@ int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner) list_add_tail(&ici->list, &hosts); mutex_unlock(&list_lock); - ici->owner = owner; ici->dev.release = dummy_release; ret = device_register(&ici->dev); @@ -819,7 +818,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) if (icd->dev.parent == &ici->dev) { device_unregister(&icd->dev); /* Not before device_unregister(), .remove - * needs parent to call ici->remove() */ + * needs parent to call ici->ops->remove() */ icd->dev.parent = NULL; memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); } -- cgit v1.2.3 From c03a147c1c7804df6087513c653e2613e72aa407 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 4 Apr 2008 13:46:34 +0000 Subject: soc-camera: use a spinlock for videobuffer queue From: Guennadi Liakhovetski All drivers should provide a spinlock to be used in videobuf operations. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Brandon Philips Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/video/pxa_camera.c | 10 ++++++++ linux/drivers/media/video/soc_camera.c | 46 ++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 5 deletions(-) (limited to 'linux/drivers/media') diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c index 9758f7eb5..bef3c9c79 100644 --- a/linux/drivers/media/video/pxa_camera.c +++ b/linux/drivers/media/video/pxa_camera.c @@ -803,6 +803,15 @@ static int pxa_camera_querycap(struct soc_camera_host *ici, 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 = { .owner = THIS_MODULE, .add = pxa_camera_add_device, @@ -814,6 +823,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { .querycap = pxa_camera_querycap, .try_bus_param = pxa_camera_try_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. */ diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c index 43c811059..1e9215788 100644 --- a/linux/drivers/media/video/soc_camera.c +++ b/linux/drivers/media/video/soc_camera.c @@ -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; -- cgit v1.2.3