aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/soc_camera.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@pengutronix.de>2008-04-04 12:46:34 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:07:57 -0400
commit1a0063a9852380190a7172c1a1cb79e934b06cd4 (patch)
tree71b91bdeaae1b72c3718507dec6922f609b9edd0 /drivers/media/video/soc_camera.c
parentb8d9904c3525c0a149976ffaad48fcb03e8703f7 (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>
Diffstat (limited to 'drivers/media/video/soc_camera.c')
-rw-r--r--drivers/media/video/soc_camera.c46
1 files changed, 41 insertions, 5 deletions
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 */
240eiciadd: 247eiciadd:
248 lock = icf->lock;
249 icf->lock = NULL;
250 if (ici->ops->spinlock_free)
251 ici->ops->spinlock_free(lock);
252esla:
241 module_put(ici->ops->owner); 253 module_put(ici->ops->owner);
242emgi: 254emgi:
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
781static 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
791static void spinlock_free(spinlock_t *lock)
792{
793 kfree(lock);
794}
795
765int soc_camera_host_register(struct soc_camera_host *ici) 796int 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;