aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/v4l2-dev.c')
-rw-r--r--drivers/media/video/v4l2-dev.c115
1 files changed, 64 insertions, 51 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index cb77197d480e..0ca7978654b5 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -81,7 +81,7 @@ static inline unsigned long *devnode_bits(int vfl_type)
81 /* Any types not assigned to fixed minor ranges must be mapped to 81 /* Any types not assigned to fixed minor ranges must be mapped to
82 one single bitmap for the purposes of finding a free node number 82 one single bitmap for the purposes of finding a free node number
83 since all those unassigned types use the same minor range. */ 83 since all those unassigned types use the same minor range. */
84 int idx = (vfl_type > VFL_TYPE_VTX) ? VFL_TYPE_MAX - 1 : vfl_type; 84 int idx = (vfl_type > VFL_TYPE_RADIO) ? VFL_TYPE_MAX - 1 : vfl_type;
85 85
86 return devnode_nums[idx]; 86 return devnode_nums[idx];
87} 87}
@@ -187,48 +187,69 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
187 size_t sz, loff_t *off) 187 size_t sz, loff_t *off)
188{ 188{
189 struct video_device *vdev = video_devdata(filp); 189 struct video_device *vdev = video_devdata(filp);
190 int ret = -EIO;
190 191
191 if (!vdev->fops->read) 192 if (!vdev->fops->read)
192 return -EINVAL; 193 return -EINVAL;
193 if (!video_is_registered(vdev)) 194 if (vdev->lock)
194 return -EIO; 195 mutex_lock(vdev->lock);
195 return vdev->fops->read(filp, buf, sz, off); 196 if (video_is_registered(vdev))
197 ret = vdev->fops->read(filp, buf, sz, off);
198 if (vdev->lock)
199 mutex_unlock(vdev->lock);
200 return ret;
196} 201}
197 202
198static ssize_t v4l2_write(struct file *filp, const char __user *buf, 203static ssize_t v4l2_write(struct file *filp, const char __user *buf,
199 size_t sz, loff_t *off) 204 size_t sz, loff_t *off)
200{ 205{
201 struct video_device *vdev = video_devdata(filp); 206 struct video_device *vdev = video_devdata(filp);
207 int ret = -EIO;
202 208
203 if (!vdev->fops->write) 209 if (!vdev->fops->write)
204 return -EINVAL; 210 return -EINVAL;
205 if (!video_is_registered(vdev)) 211 if (vdev->lock)
206 return -EIO; 212 mutex_lock(vdev->lock);
207 return vdev->fops->write(filp, buf, sz, off); 213 if (video_is_registered(vdev))
214 ret = vdev->fops->write(filp, buf, sz, off);
215 if (vdev->lock)
216 mutex_unlock(vdev->lock);
217 return ret;
208} 218}
209 219
210static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) 220static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
211{ 221{
212 struct video_device *vdev = video_devdata(filp); 222 struct video_device *vdev = video_devdata(filp);
223 int ret = DEFAULT_POLLMASK;
213 224
214 if (!vdev->fops->poll || !video_is_registered(vdev)) 225 if (!vdev->fops->poll)
215 return DEFAULT_POLLMASK; 226 return ret;
216 return vdev->fops->poll(filp, poll); 227 if (vdev->lock)
228 mutex_lock(vdev->lock);
229 if (video_is_registered(vdev))
230 ret = vdev->fops->poll(filp, poll);
231 if (vdev->lock)
232 mutex_unlock(vdev->lock);
233 return ret;
217} 234}
218 235
219static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 236static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
220{ 237{
221 struct video_device *vdev = video_devdata(filp); 238 struct video_device *vdev = video_devdata(filp);
222 int ret; 239 int ret = -ENODEV;
223 240
224 /* Allow ioctl to continue even if the device was unregistered.
225 Things like dequeueing buffers might still be useful. */
226 if (vdev->fops->unlocked_ioctl) { 241 if (vdev->fops->unlocked_ioctl) {
227 ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); 242 if (vdev->lock)
243 mutex_lock(vdev->lock);
244 if (video_is_registered(vdev))
245 ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
246 if (vdev->lock)
247 mutex_unlock(vdev->lock);
228 } else if (vdev->fops->ioctl) { 248 } else if (vdev->fops->ioctl) {
229 /* TODO: convert all drivers to unlocked_ioctl */ 249 /* TODO: convert all drivers to unlocked_ioctl */
230 lock_kernel(); 250 lock_kernel();
231 ret = vdev->fops->ioctl(filp, cmd, arg); 251 if (video_is_registered(vdev))
252 ret = vdev->fops->ioctl(filp, cmd, arg);
232 unlock_kernel(); 253 unlock_kernel();
233 } else 254 } else
234 ret = -ENOTTY; 255 ret = -ENOTTY;
@@ -236,30 +257,20 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
236 return ret; 257 return ret;
237} 258}
238 259
239#ifdef CONFIG_MMU
240#define v4l2_get_unmapped_area NULL
241#else
242static unsigned long v4l2_get_unmapped_area(struct file *filp,
243 unsigned long addr, unsigned long len, unsigned long pgoff,
244 unsigned long flags)
245{
246 struct video_device *vdev = video_devdata(filp);
247
248 if (!vdev->fops->get_unmapped_area)
249 return -ENOSYS;
250 if (!video_is_registered(vdev))
251 return -ENODEV;
252 return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags);
253}
254#endif
255
256static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) 260static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
257{ 261{
258 struct video_device *vdev = video_devdata(filp); 262 struct video_device *vdev = video_devdata(filp);
263 int ret = -ENODEV;
259 264
260 if (!vdev->fops->mmap || !video_is_registered(vdev)) 265 if (!vdev->fops->mmap)
261 return -ENODEV; 266 return ret;
262 return vdev->fops->mmap(filp, vm); 267 if (vdev->lock)
268 mutex_lock(vdev->lock);
269 if (video_is_registered(vdev))
270 ret = vdev->fops->mmap(filp, vm);
271 if (vdev->lock)
272 mutex_unlock(vdev->lock);
273 return ret;
263} 274}
264 275
265/* Override for the open function */ 276/* Override for the open function */
@@ -271,17 +282,24 @@ static int v4l2_open(struct inode *inode, struct file *filp)
271 /* Check if the video device is available */ 282 /* Check if the video device is available */
272 mutex_lock(&videodev_lock); 283 mutex_lock(&videodev_lock);
273 vdev = video_devdata(filp); 284 vdev = video_devdata(filp);
274 /* return ENODEV if the video device has been removed 285 /* return ENODEV if the video device has already been removed. */
275 already or if it is not registered anymore. */ 286 if (vdev == NULL) {
276 if (vdev == NULL || !video_is_registered(vdev)) {
277 mutex_unlock(&videodev_lock); 287 mutex_unlock(&videodev_lock);
278 return -ENODEV; 288 return -ENODEV;
279 } 289 }
280 /* and increase the device refcount */ 290 /* and increase the device refcount */
281 video_get(vdev); 291 video_get(vdev);
282 mutex_unlock(&videodev_lock); 292 mutex_unlock(&videodev_lock);
283 if (vdev->fops->open) 293 if (vdev->fops->open) {
284 ret = vdev->fops->open(filp); 294 if (vdev->lock)
295 mutex_lock(vdev->lock);
296 if (video_is_registered(vdev))
297 ret = vdev->fops->open(filp);
298 else
299 ret = -ENODEV;
300 if (vdev->lock)
301 mutex_unlock(vdev->lock);
302 }
285 303
286 /* decrease the refcount in case of an error */ 304 /* decrease the refcount in case of an error */
287 if (ret) 305 if (ret)
@@ -295,8 +313,13 @@ static int v4l2_release(struct inode *inode, struct file *filp)
295 struct video_device *vdev = video_devdata(filp); 313 struct video_device *vdev = video_devdata(filp);
296 int ret = 0; 314 int ret = 0;
297 315
298 if (vdev->fops->release) 316 if (vdev->fops->release) {
317 if (vdev->lock)
318 mutex_lock(vdev->lock);
299 vdev->fops->release(filp); 319 vdev->fops->release(filp);
320 if (vdev->lock)
321 mutex_unlock(vdev->lock);
322 }
300 323
301 /* decrease the refcount unconditionally since the release() 324 /* decrease the refcount unconditionally since the release()
302 return value is ignored. */ 325 return value is ignored. */
@@ -309,7 +332,6 @@ static const struct file_operations v4l2_fops = {
309 .read = v4l2_read, 332 .read = v4l2_read,
310 .write = v4l2_write, 333 .write = v4l2_write,
311 .open = v4l2_open, 334 .open = v4l2_open,
312 .get_unmapped_area = v4l2_get_unmapped_area,
313 .mmap = v4l2_mmap, 335 .mmap = v4l2_mmap,
314 .unlocked_ioctl = v4l2_ioctl, 336 .unlocked_ioctl = v4l2_ioctl,
315#ifdef CONFIG_COMPAT 337#ifdef CONFIG_COMPAT
@@ -377,8 +399,6 @@ static int get_index(struct video_device *vdev)
377 * 399 *
378 * %VFL_TYPE_GRABBER - A frame grabber 400 * %VFL_TYPE_GRABBER - A frame grabber
379 * 401 *
380 * %VFL_TYPE_VTX - A teletext device
381 *
382 * %VFL_TYPE_VBI - Vertical blank data (undecoded) 402 * %VFL_TYPE_VBI - Vertical blank data (undecoded)
383 * 403 *
384 * %VFL_TYPE_RADIO - A radio card 404 * %VFL_TYPE_RADIO - A radio card
@@ -411,9 +431,6 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
411 case VFL_TYPE_GRABBER: 431 case VFL_TYPE_GRABBER:
412 name_base = "video"; 432 name_base = "video";
413 break; 433 break;
414 case VFL_TYPE_VTX:
415 name_base = "vtx";
416 break;
417 case VFL_TYPE_VBI: 434 case VFL_TYPE_VBI:
418 name_base = "vbi"; 435 name_base = "vbi";
419 break; 436 break;
@@ -451,10 +468,6 @@ static int __video_register_device(struct video_device *vdev, int type, int nr,
451 minor_offset = 64; 468 minor_offset = 64;
452 minor_cnt = 64; 469 minor_cnt = 64;
453 break; 470 break;
454 case VFL_TYPE_VTX:
455 minor_offset = 192;
456 minor_cnt = 32;
457 break;
458 case VFL_TYPE_VBI: 471 case VFL_TYPE_VBI:
459 minor_offset = 224; 472 minor_offset = 224;
460 minor_cnt = 32; 473 minor_cnt = 32;