diff options
| -rw-r--r-- | drivers/media/v4l2-core/v4l2-dev.c | 34 |
1 files changed, 14 insertions, 20 deletions
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index 33617c365acc..9aa530a8bea9 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c | |||
| @@ -194,7 +194,7 @@ static void v4l2_device_release(struct device *cd) | |||
| 194 | mutex_unlock(&videodev_lock); | 194 | mutex_unlock(&videodev_lock); |
| 195 | 195 | ||
| 196 | #if defined(CONFIG_MEDIA_CONTROLLER) | 196 | #if defined(CONFIG_MEDIA_CONTROLLER) |
| 197 | if (v4l2_dev && v4l2_dev->mdev && | 197 | if (v4l2_dev->mdev && |
| 198 | vdev->vfl_type != VFL_TYPE_SUBDEV) | 198 | vdev->vfl_type != VFL_TYPE_SUBDEV) |
| 199 | media_device_unregister_entity(&vdev->entity); | 199 | media_device_unregister_entity(&vdev->entity); |
| 200 | #endif | 200 | #endif |
| @@ -207,7 +207,7 @@ static void v4l2_device_release(struct device *cd) | |||
| 207 | * TODO: In the long run all drivers that use v4l2_device should use the | 207 | * TODO: In the long run all drivers that use v4l2_device should use the |
| 208 | * v4l2_device release callback. This check will then be unnecessary. | 208 | * v4l2_device release callback. This check will then be unnecessary. |
| 209 | */ | 209 | */ |
| 210 | if (v4l2_dev && v4l2_dev->release == NULL) | 210 | if (v4l2_dev->release == NULL) |
| 211 | v4l2_dev = NULL; | 211 | v4l2_dev = NULL; |
| 212 | 212 | ||
| 213 | /* Release video_device and perform other | 213 | /* Release video_device and perform other |
| @@ -360,27 +360,22 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 360 | * hack but it will have to do for those drivers that are not | 360 | * hack but it will have to do for those drivers that are not |
| 361 | * yet converted to use unlocked_ioctl. | 361 | * yet converted to use unlocked_ioctl. |
| 362 | * | 362 | * |
| 363 | * There are two options: if the driver implements struct | 363 | * All drivers implement struct v4l2_device, so we use the |
| 364 | * v4l2_device, then the lock defined there is used to | 364 | * lock defined there to serialize the ioctls. |
| 365 | * serialize the ioctls. Otherwise the v4l2 core lock defined | ||
| 366 | * below is used. This lock is really bad since it serializes | ||
| 367 | * completely independent devices. | ||
| 368 | * | 365 | * |
| 369 | * Both variants suffer from the same problem: if the driver | 366 | * However, if the driver sleeps, then it blocks all ioctls |
| 370 | * sleeps, then it blocks all ioctls since the lock is still | 367 | * since the lock is still held. This is very common for |
| 371 | * held. This is very common for VIDIOC_DQBUF since that | 368 | * VIDIOC_DQBUF since that normally waits for a frame to arrive. |
| 372 | * normally waits for a frame to arrive. As a result any other | 369 | * As a result any other ioctl calls will proceed very, very |
| 373 | * ioctl calls will proceed very, very slowly since each call | 370 | * slowly since each call will have to wait for the VIDIOC_QBUF |
| 374 | * will have to wait for the VIDIOC_QBUF to finish. Things that | 371 | * to finish. Things that should take 0.01s may now take 10-20 |
| 375 | * should take 0.01s may now take 10-20 seconds. | 372 | * seconds. |
| 376 | * | 373 | * |
| 377 | * The workaround is to *not* take the lock for VIDIOC_DQBUF. | 374 | * The workaround is to *not* take the lock for VIDIOC_DQBUF. |
| 378 | * This actually works OK for videobuf-based drivers, since | 375 | * This actually works OK for videobuf-based drivers, since |
| 379 | * videobuf will take its own internal lock. | 376 | * videobuf will take its own internal lock. |
| 380 | */ | 377 | */ |
| 381 | static DEFINE_MUTEX(v4l2_ioctl_mutex); | 378 | struct mutex *m = &vdev->v4l2_dev->ioctl_lock; |
| 382 | struct mutex *m = vdev->v4l2_dev ? | ||
| 383 | &vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex; | ||
| 384 | 379 | ||
| 385 | if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m)) | 380 | if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m)) |
| 386 | return -ERESTARTSYS; | 381 | return -ERESTARTSYS; |
| @@ -938,12 +933,11 @@ int __video_register_device(struct video_device *vdev, int type, int nr, | |||
| 938 | name_base, nr, video_device_node_name(vdev)); | 933 | name_base, nr, video_device_node_name(vdev)); |
| 939 | 934 | ||
| 940 | /* Increase v4l2_device refcount */ | 935 | /* Increase v4l2_device refcount */ |
| 941 | if (vdev->v4l2_dev) | 936 | v4l2_device_get(vdev->v4l2_dev); |
| 942 | v4l2_device_get(vdev->v4l2_dev); | ||
| 943 | 937 | ||
| 944 | #if defined(CONFIG_MEDIA_CONTROLLER) | 938 | #if defined(CONFIG_MEDIA_CONTROLLER) |
| 945 | /* Part 5: Register the entity. */ | 939 | /* Part 5: Register the entity. */ |
| 946 | if (vdev->v4l2_dev && vdev->v4l2_dev->mdev && | 940 | if (vdev->v4l2_dev->mdev && |
| 947 | vdev->vfl_type != VFL_TYPE_SUBDEV) { | 941 | vdev->vfl_type != VFL_TYPE_SUBDEV) { |
| 948 | vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; | 942 | vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; |
| 949 | vdev->entity.name = vdev->name; | 943 | vdev->entity.name = vdev->name; |
