diff options
Diffstat (limited to 'drivers/media/video/v4l2-dev.c')
-rw-r--r-- | drivers/media/video/v4l2-dev.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 83dbb2ddff10..d13c47fc7202 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -46,6 +46,29 @@ static ssize_t show_index(struct device *cd, | |||
46 | return sprintf(buf, "%i\n", vdev->index); | 46 | return sprintf(buf, "%i\n", vdev->index); |
47 | } | 47 | } |
48 | 48 | ||
49 | static ssize_t show_debug(struct device *cd, | ||
50 | struct device_attribute *attr, char *buf) | ||
51 | { | ||
52 | struct video_device *vdev = to_video_device(cd); | ||
53 | |||
54 | return sprintf(buf, "%i\n", vdev->debug); | ||
55 | } | ||
56 | |||
57 | static ssize_t set_debug(struct device *cd, struct device_attribute *attr, | ||
58 | const char *buf, size_t len) | ||
59 | { | ||
60 | struct video_device *vdev = to_video_device(cd); | ||
61 | int res = 0; | ||
62 | u16 value; | ||
63 | |||
64 | res = kstrtou16(buf, 0, &value); | ||
65 | if (res) | ||
66 | return res; | ||
67 | |||
68 | vdev->debug = value; | ||
69 | return len; | ||
70 | } | ||
71 | |||
49 | static ssize_t show_name(struct device *cd, | 72 | static ssize_t show_name(struct device *cd, |
50 | struct device_attribute *attr, char *buf) | 73 | struct device_attribute *attr, char *buf) |
51 | { | 74 | { |
@@ -56,6 +79,7 @@ static ssize_t show_name(struct device *cd, | |||
56 | 79 | ||
57 | static struct device_attribute video_device_attrs[] = { | 80 | static struct device_attribute video_device_attrs[] = { |
58 | __ATTR(name, S_IRUGO, show_name, NULL), | 81 | __ATTR(name, S_IRUGO, show_name, NULL), |
82 | __ATTR(debug, 0644, show_debug, set_debug), | ||
59 | __ATTR(index, S_IRUGO, show_index, NULL), | 83 | __ATTR(index, S_IRUGO, show_index, NULL), |
60 | __ATTR_NULL | 84 | __ATTR_NULL |
61 | }; | 85 | }; |
@@ -281,6 +305,9 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf, | |||
281 | ret = vdev->fops->read(filp, buf, sz, off); | 305 | ret = vdev->fops->read(filp, buf, sz, off); |
282 | if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) | 306 | if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) |
283 | mutex_unlock(vdev->lock); | 307 | mutex_unlock(vdev->lock); |
308 | if (vdev->debug) | ||
309 | printk(KERN_DEBUG "%s: read: %zd (%d)\n", | ||
310 | video_device_node_name(vdev), sz, ret); | ||
284 | return ret; | 311 | return ret; |
285 | } | 312 | } |
286 | 313 | ||
@@ -299,6 +326,9 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf, | |||
299 | ret = vdev->fops->write(filp, buf, sz, off); | 326 | ret = vdev->fops->write(filp, buf, sz, off); |
300 | if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) | 327 | if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) |
301 | mutex_unlock(vdev->lock); | 328 | mutex_unlock(vdev->lock); |
329 | if (vdev->debug) | ||
330 | printk(KERN_DEBUG "%s: write: %zd (%d)\n", | ||
331 | video_device_node_name(vdev), sz, ret); | ||
302 | return ret; | 332 | return ret; |
303 | } | 333 | } |
304 | 334 | ||
@@ -315,6 +345,9 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) | |||
315 | ret = vdev->fops->poll(filp, poll); | 345 | ret = vdev->fops->poll(filp, poll); |
316 | if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) | 346 | if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) |
317 | mutex_unlock(vdev->lock); | 347 | mutex_unlock(vdev->lock); |
348 | if (vdev->debug) | ||
349 | printk(KERN_DEBUG "%s: poll: %08x\n", | ||
350 | video_device_node_name(vdev), ret); | ||
318 | return ret; | 351 | return ret; |
319 | } | 352 | } |
320 | 353 | ||
@@ -324,20 +357,14 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
324 | int ret = -ENODEV; | 357 | int ret = -ENODEV; |
325 | 358 | ||
326 | if (vdev->fops->unlocked_ioctl) { | 359 | if (vdev->fops->unlocked_ioctl) { |
327 | bool locked = false; | 360 | struct mutex *lock = v4l2_ioctl_get_lock(vdev, cmd); |
328 | 361 | ||
329 | if (vdev->lock) { | 362 | if (lock && mutex_lock_interruptible(lock)) |
330 | /* always lock unless the cmd is marked as "don't use lock" */ | 363 | return -ERESTARTSYS; |
331 | locked = !v4l2_is_known_ioctl(cmd) || | ||
332 | !test_bit(_IOC_NR(cmd), vdev->disable_locking); | ||
333 | |||
334 | if (locked && mutex_lock_interruptible(vdev->lock)) | ||
335 | return -ERESTARTSYS; | ||
336 | } | ||
337 | if (video_is_registered(vdev)) | 364 | if (video_is_registered(vdev)) |
338 | ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); | 365 | ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); |
339 | if (locked) | 366 | if (lock) |
340 | mutex_unlock(vdev->lock); | 367 | mutex_unlock(lock); |
341 | } else if (vdev->fops->ioctl) { | 368 | } else if (vdev->fops->ioctl) { |
342 | /* This code path is a replacement for the BKL. It is a major | 369 | /* This code path is a replacement for the BKL. It is a major |
343 | * hack but it will have to do for those drivers that are not | 370 | * hack but it will have to do for those drivers that are not |
@@ -385,12 +412,17 @@ static unsigned long v4l2_get_unmapped_area(struct file *filp, | |||
385 | unsigned long flags) | 412 | unsigned long flags) |
386 | { | 413 | { |
387 | struct video_device *vdev = video_devdata(filp); | 414 | struct video_device *vdev = video_devdata(filp); |
415 | int ret; | ||
388 | 416 | ||
389 | if (!vdev->fops->get_unmapped_area) | 417 | if (!vdev->fops->get_unmapped_area) |
390 | return -ENOSYS; | 418 | return -ENOSYS; |
391 | if (!video_is_registered(vdev)) | 419 | if (!video_is_registered(vdev)) |
392 | return -ENODEV; | 420 | return -ENODEV; |
393 | return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); | 421 | ret = vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); |
422 | if (vdev->debug) | ||
423 | printk(KERN_DEBUG "%s: get_unmapped_area (%d)\n", | ||
424 | video_device_node_name(vdev), ret); | ||
425 | return ret; | ||
394 | } | 426 | } |
395 | #endif | 427 | #endif |
396 | 428 | ||
@@ -408,6 +440,9 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) | |||
408 | ret = vdev->fops->mmap(filp, vm); | 440 | ret = vdev->fops->mmap(filp, vm); |
409 | if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) | 441 | if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags)) |
410 | mutex_unlock(vdev->lock); | 442 | mutex_unlock(vdev->lock); |
443 | if (vdev->debug) | ||
444 | printk(KERN_DEBUG "%s: mmap (%d)\n", | ||
445 | video_device_node_name(vdev), ret); | ||
411 | return ret; | 446 | return ret; |
412 | } | 447 | } |
413 | 448 | ||
@@ -446,6 +481,9 @@ err: | |||
446 | /* decrease the refcount in case of an error */ | 481 | /* decrease the refcount in case of an error */ |
447 | if (ret) | 482 | if (ret) |
448 | video_put(vdev); | 483 | video_put(vdev); |
484 | if (vdev->debug) | ||
485 | printk(KERN_DEBUG "%s: open (%d)\n", | ||
486 | video_device_node_name(vdev), ret); | ||
449 | return ret; | 487 | return ret; |
450 | } | 488 | } |
451 | 489 | ||
@@ -465,6 +503,9 @@ static int v4l2_release(struct inode *inode, struct file *filp) | |||
465 | /* decrease the refcount unconditionally since the release() | 503 | /* decrease the refcount unconditionally since the release() |
466 | return value is ignored. */ | 504 | return value is ignored. */ |
467 | video_put(vdev); | 505 | video_put(vdev); |
506 | if (vdev->debug) | ||
507 | printk(KERN_DEBUG "%s: release\n", | ||
508 | video_device_node_name(vdev)); | ||
468 | return ret; | 509 | return ret; |
469 | } | 510 | } |
470 | 511 | ||