diff options
author | Guennadi Liakhovetski <g.liakhovetski@pengutronix.de> | 2008-04-04 12:46:34 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:07:57 -0400 |
commit | 1a0063a9852380190a7172c1a1cb79e934b06cd4 (patch) | |
tree | 71b91bdeaae1b72c3718507dec6922f609b9edd0 | |
parent | b8d9904c3525c0a149976ffaad48fcb03e8703f7 (diff) |
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>
-rw-r--r-- | drivers/media/video/pxa_camera.c | 10 | ||||
-rw-r--r-- | drivers/media/video/soc_camera.c | 46 | ||||
-rw-r--r-- | include/media/soc_camera.h | 3 |
3 files changed, 54 insertions, 5 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 9758f7eb5932..bef3c9c7902a 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -803,6 +803,15 @@ static int pxa_camera_querycap(struct soc_camera_host *ici, | |||
803 | return 0; | 803 | return 0; |
804 | } | 804 | } |
805 | 805 | ||
806 | static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf) | ||
807 | { | ||
808 | struct soc_camera_host *ici = | ||
809 | to_soc_camera_host(icf->icd->dev.parent); | ||
810 | struct pxa_camera_dev *pcdev = ici->priv; | ||
811 | |||
812 | return &pcdev->lock; | ||
813 | } | ||
814 | |||
806 | static struct soc_camera_host_ops pxa_soc_camera_host_ops = { | 815 | static struct soc_camera_host_ops pxa_soc_camera_host_ops = { |
807 | .owner = THIS_MODULE, | 816 | .owner = THIS_MODULE, |
808 | .add = pxa_camera_add_device, | 817 | .add = pxa_camera_add_device, |
@@ -814,6 +823,7 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = { | |||
814 | .querycap = pxa_camera_querycap, | 823 | .querycap = pxa_camera_querycap, |
815 | .try_bus_param = pxa_camera_try_bus_param, | 824 | .try_bus_param = pxa_camera_try_bus_param, |
816 | .set_bus_param = pxa_camera_set_bus_param, | 825 | .set_bus_param = pxa_camera_set_bus_param, |
826 | .spinlock_alloc = pxa_camera_spinlock_alloc, | ||
817 | }; | 827 | }; |
818 | 828 | ||
819 | /* Should be allocated dynamically too, but we have only one. */ | 829 | /* Should be allocated dynamically too, but we have only one. */ |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 43c8110599e8..1e921578804f 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -184,6 +184,7 @@ static int soc_camera_open(struct inode *inode, struct file *file) | |||
184 | struct soc_camera_device *icd; | 184 | struct soc_camera_device *icd; |
185 | struct soc_camera_host *ici; | 185 | struct soc_camera_host *ici; |
186 | struct soc_camera_file *icf; | 186 | struct soc_camera_file *icf; |
187 | spinlock_t *lock; | ||
187 | int ret; | 188 | int ret; |
188 | 189 | ||
189 | icf = vmalloc(sizeof(*icf)); | 190 | icf = vmalloc(sizeof(*icf)); |
@@ -209,10 +210,16 @@ static int soc_camera_open(struct inode *inode, struct file *file) | |||
209 | goto emgi; | 210 | goto emgi; |
210 | } | 211 | } |
211 | 212 | ||
212 | icd->use_count++; | ||
213 | |||
214 | icf->icd = icd; | 213 | icf->icd = icd; |
215 | 214 | ||
215 | icf->lock = ici->ops->spinlock_alloc(icf); | ||
216 | if (!icf->lock) { | ||
217 | ret = -ENOMEM; | ||
218 | goto esla; | ||
219 | } | ||
220 | |||
221 | icd->use_count++; | ||
222 | |||
216 | /* Now we really have to activate the camera */ | 223 | /* Now we really have to activate the camera */ |
217 | if (icd->use_count == 1) { | 224 | if (icd->use_count == 1) { |
218 | ret = ici->ops->add(icd); | 225 | ret = ici->ops->add(icd); |
@@ -229,8 +236,8 @@ static int soc_camera_open(struct inode *inode, struct file *file) | |||
229 | dev_dbg(&icd->dev, "camera device open\n"); | 236 | dev_dbg(&icd->dev, "camera device open\n"); |
230 | 237 | ||
231 | /* We must pass NULL as dev pointer, then all pci_* dma operations | 238 | /* We must pass NULL as dev pointer, then all pci_* dma operations |
232 | * transform to normal dma_* ones. Do we need an irqlock? */ | 239 | * transform to normal dma_* ones. */ |
233 | videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL, | 240 | videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock, |
234 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, | 241 | V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, |
235 | ici->msize, icd); | 242 | ici->msize, icd); |
236 | 243 | ||
@@ -238,6 +245,11 @@ static int soc_camera_open(struct inode *inode, struct file *file) | |||
238 | 245 | ||
239 | /* All errors are entered with the video_lock held */ | 246 | /* All errors are entered with the video_lock held */ |
240 | eiciadd: | 247 | eiciadd: |
248 | lock = icf->lock; | ||
249 | icf->lock = NULL; | ||
250 | if (ici->ops->spinlock_free) | ||
251 | ici->ops->spinlock_free(lock); | ||
252 | esla: | ||
241 | module_put(ici->ops->owner); | 253 | module_put(ici->ops->owner); |
242 | emgi: | 254 | emgi: |
243 | module_put(icd->ops->owner); | 255 | module_put(icd->ops->owner); |
@@ -253,16 +265,20 @@ static int soc_camera_close(struct inode *inode, struct file *file) | |||
253 | struct soc_camera_device *icd = icf->icd; | 265 | struct soc_camera_device *icd = icf->icd; |
254 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); | 266 | struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); |
255 | struct video_device *vdev = icd->vdev; | 267 | struct video_device *vdev = icd->vdev; |
268 | spinlock_t *lock = icf->lock; | ||
256 | 269 | ||
257 | mutex_lock(&video_lock); | 270 | mutex_lock(&video_lock); |
258 | icd->use_count--; | 271 | icd->use_count--; |
259 | if (!icd->use_count) | 272 | if (!icd->use_count) |
260 | ici->ops->remove(icd); | 273 | ici->ops->remove(icd); |
274 | icf->lock = NULL; | ||
275 | if (ici->ops->spinlock_free) | ||
276 | ici->ops->spinlock_free(lock); | ||
261 | module_put(icd->ops->owner); | 277 | module_put(icd->ops->owner); |
262 | module_put(ici->ops->owner); | 278 | module_put(ici->ops->owner); |
263 | mutex_unlock(&video_lock); | 279 | mutex_unlock(&video_lock); |
264 | 280 | ||
265 | vfree(file->private_data); | 281 | vfree(icf); |
266 | 282 | ||
267 | dev_dbg(vdev->dev, "camera device close\n"); | 283 | dev_dbg(vdev->dev, "camera device close\n"); |
268 | 284 | ||
@@ -762,6 +778,21 @@ static void dummy_release(struct device *dev) | |||
762 | { | 778 | { |
763 | } | 779 | } |
764 | 780 | ||
781 | static spinlock_t *spinlock_alloc(struct soc_camera_file *icf) | ||
782 | { | ||
783 | spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL); | ||
784 | |||
785 | if (lock) | ||
786 | spin_lock_init(lock); | ||
787 | |||
788 | return lock; | ||
789 | } | ||
790 | |||
791 | static void spinlock_free(spinlock_t *lock) | ||
792 | { | ||
793 | kfree(lock); | ||
794 | } | ||
795 | |||
765 | int soc_camera_host_register(struct soc_camera_host *ici) | 796 | int soc_camera_host_register(struct soc_camera_host *ici) |
766 | { | 797 | { |
767 | int ret; | 798 | int ret; |
@@ -792,6 +823,11 @@ int soc_camera_host_register(struct soc_camera_host *ici) | |||
792 | if (ret) | 823 | if (ret) |
793 | goto edevr; | 824 | goto edevr; |
794 | 825 | ||
826 | if (!ici->ops->spinlock_alloc) { | ||
827 | ici->ops->spinlock_alloc = spinlock_alloc; | ||
828 | ici->ops->spinlock_free = spinlock_free; | ||
829 | } | ||
830 | |||
795 | scan_add_host(ici); | 831 | scan_add_host(ici); |
796 | 832 | ||
797 | return 0; | 833 | return 0; |
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 80e1193c07d5..6a8c8be7a1ae 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
@@ -48,6 +48,7 @@ struct soc_camera_device { | |||
48 | struct soc_camera_file { | 48 | struct soc_camera_file { |
49 | struct soc_camera_device *icd; | 49 | struct soc_camera_device *icd; |
50 | struct videobuf_queue vb_vidq; | 50 | struct videobuf_queue vb_vidq; |
51 | spinlock_t *lock; | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | struct soc_camera_host { | 54 | struct soc_camera_host { |
@@ -73,6 +74,8 @@ struct soc_camera_host_ops { | |||
73 | int (*try_bus_param)(struct soc_camera_device *, __u32); | 74 | int (*try_bus_param)(struct soc_camera_device *, __u32); |
74 | int (*set_bus_param)(struct soc_camera_device *, __u32); | 75 | int (*set_bus_param)(struct soc_camera_device *, __u32); |
75 | unsigned int (*poll)(struct file *, poll_table *); | 76 | unsigned int (*poll)(struct file *, poll_table *); |
77 | spinlock_t* (*spinlock_alloc)(struct soc_camera_file *); | ||
78 | void (*spinlock_free)(spinlock_t *); | ||
76 | }; | 79 | }; |
77 | 80 | ||
78 | struct soc_camera_link { | 81 | struct soc_camera_link { |