diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/v4l2-dev.c | 14 | ||||
-rw-r--r-- | drivers/media/video/v4l2-ioctl.c | 189 |
2 files changed, 113 insertions, 90 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 70bec548d904..e4a9ed67bb2e 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -322,11 +322,19 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) int ret = -ENODEV; if (vdev->fops->unlocked_ioctl) { - if (vdev->lock && mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; + bool locked = false; + + if (vdev->lock) { + /* always lock unless the cmd is marked as "don't use lock" */ + locked = !v4l2_is_known_ioctl(cmd) || + !test_bit(_IOC_NR(cmd), vdev->dont_use_lock); + + if (locked && mutex_lock_interruptible(vdev->lock)) + return -ERESTARTSYS; + } if (video_is_registered(vdev)) ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); - if (vdev->lock) + if (locked) mutex_unlock(vdev->lock); } else if (vdev->fops->ioctl) { /* This code path is a replacement for the BKL. It is a major diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index 5b2ec1fd2d0a..ef44b084132a 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -195,93 +195,106 @@ static const char *v4l2_memory_names[] = { /* ------------------------------------------------------------------ */ /* debug help functions */ -static const char *v4l2_ioctls[] = { - [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", - [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", - [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT", - [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT", - [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT", - [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS", - [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF", - [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF", - [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF", - [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY", - [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF", - [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF", - [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON", - [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF", - [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM", - [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM", - [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD", - [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD", - [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD", - [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT", - [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL", - [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL", - [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER", - [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER", - [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO", - [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO", - [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL", - [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU", - [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT", - [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT", - [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT", - [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT", - [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT", - [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT", - [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT", - [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR", - [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR", - [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY", - [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY", - [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", - [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", - [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", - [_IOC_NR(VIDIOC_G_SELECTION)] = "VIDIOC_G_SELECTION", - [_IOC_NR(VIDIOC_S_SELECTION)] = "VIDIOC_S_SELECTION", - [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", - [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", - [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", - [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT", - [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO", - [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT", - [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY", - [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY", - [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", - [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS", - [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS", - [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS", - [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS", -#if 1 - [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES", - [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS", - [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX", - [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", - [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", - - [_IOC_NR(VIDIOC_DECODER_CMD)] = "VIDIOC_DECODER_CMD", - [_IOC_NR(VIDIOC_TRY_DECODER_CMD)] = "VIDIOC_TRY_DECODER_CMD", - [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", - [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", - - [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT", - [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK", -#endif - [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS", - [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET", - [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET", - [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET", - [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS", - [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS", - [_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT", - [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT", - [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT", - [_IOC_NR(VIDIOC_CREATE_BUFS)] = "VIDIOC_CREATE_BUFS", - [_IOC_NR(VIDIOC_PREPARE_BUF)] = "VIDIOC_PREPARE_BUF", + +struct v4l2_ioctl_info { + unsigned int ioctl; + const char * const name; +}; + +#define IOCTL_INFO(_ioctl) [_IOC_NR(_ioctl)] = { \ + .ioctl = _ioctl, \ + .name = #_ioctl, \ +} + +static struct v4l2_ioctl_info v4l2_ioctls[] = { + IOCTL_INFO(VIDIOC_QUERYCAP), + IOCTL_INFO(VIDIOC_ENUM_FMT), + IOCTL_INFO(VIDIOC_G_FMT), + IOCTL_INFO(VIDIOC_S_FMT), + IOCTL_INFO(VIDIOC_REQBUFS), + IOCTL_INFO(VIDIOC_QUERYBUF), + IOCTL_INFO(VIDIOC_G_FBUF), + IOCTL_INFO(VIDIOC_S_FBUF), + IOCTL_INFO(VIDIOC_OVERLAY), + IOCTL_INFO(VIDIOC_QBUF), + IOCTL_INFO(VIDIOC_DQBUF), + IOCTL_INFO(VIDIOC_STREAMON), + IOCTL_INFO(VIDIOC_STREAMOFF), + IOCTL_INFO(VIDIOC_G_PARM), + IOCTL_INFO(VIDIOC_S_PARM), + IOCTL_INFO(VIDIOC_G_STD), + IOCTL_INFO(VIDIOC_S_STD), + IOCTL_INFO(VIDIOC_ENUMSTD), + IOCTL_INFO(VIDIOC_ENUMINPUT), + IOCTL_INFO(VIDIOC_G_CTRL), + IOCTL_INFO(VIDIOC_S_CTRL), + IOCTL_INFO(VIDIOC_G_TUNER), + IOCTL_INFO(VIDIOC_S_TUNER), + IOCTL_INFO(VIDIOC_G_AUDIO), + IOCTL_INFO(VIDIOC_S_AUDIO), + IOCTL_INFO(VIDIOC_QUERYCTRL), + IOCTL_INFO(VIDIOC_QUERYMENU), + IOCTL_INFO(VIDIOC_G_INPUT), + IOCTL_INFO(VIDIOC_S_INPUT), + IOCTL_INFO(VIDIOC_G_OUTPUT), + IOCTL_INFO(VIDIOC_S_OUTPUT), + IOCTL_INFO(VIDIOC_ENUMOUTPUT), + IOCTL_INFO(VIDIOC_G_AUDOUT), + IOCTL_INFO(VIDIOC_S_AUDOUT), + IOCTL_INFO(VIDIOC_G_MODULATOR), + IOCTL_INFO(VIDIOC_S_MODULATOR), + IOCTL_INFO(VIDIOC_G_FREQUENCY), + IOCTL_INFO(VIDIOC_S_FREQUENCY), + IOCTL_INFO(VIDIOC_CROPCAP), + IOCTL_INFO(VIDIOC_G_CROP), + IOCTL_INFO(VIDIOC_S_CROP), + IOCTL_INFO(VIDIOC_G_SELECTION), + IOCTL_INFO(VIDIOC_S_SELECTION), + IOCTL_INFO(VIDIOC_G_JPEGCOMP), + IOCTL_INFO(VIDIOC_S_JPEGCOMP), + IOCTL_INFO(VIDIOC_QUERYSTD), + IOCTL_INFO(VIDIOC_TRY_FMT), + IOCTL_INFO(VIDIOC_ENUMAUDIO), + IOCTL_INFO(VIDIOC_ENUMAUDOUT), + IOCTL_INFO(VIDIOC_G_PRIORITY), + IOCTL_INFO(VIDIOC_S_PRIORITY), + IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP), + IOCTL_INFO(VIDIOC_LOG_STATUS), + IOCTL_INFO(VIDIOC_G_EXT_CTRLS), + IOCTL_INFO(VIDIOC_S_EXT_CTRLS), + IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS), + IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES), + IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS), + IOCTL_INFO(VIDIOC_G_ENC_INDEX), + IOCTL_INFO(VIDIOC_ENCODER_CMD), + IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD), + IOCTL_INFO(VIDIOC_DECODER_CMD), + IOCTL_INFO(VIDIOC_TRY_DECODER_CMD), + IOCTL_INFO(VIDIOC_DBG_S_REGISTER), + IOCTL_INFO(VIDIOC_DBG_G_REGISTER), + IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT), + IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK), + IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS), + IOCTL_INFO(VIDIOC_S_DV_PRESET), + IOCTL_INFO(VIDIOC_G_DV_PRESET), + IOCTL_INFO(VIDIOC_QUERY_DV_PRESET), + IOCTL_INFO(VIDIOC_S_DV_TIMINGS), + IOCTL_INFO(VIDIOC_G_DV_TIMINGS), + IOCTL_INFO(VIDIOC_DQEVENT), + IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT), + IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT), + IOCTL_INFO(VIDIOC_CREATE_BUFS), + IOCTL_INFO(VIDIOC_PREPARE_BUF), }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) +bool v4l2_is_known_ioctl(unsigned int cmd) +{ + if (_IOC_NR(cmd) >= V4L2_IOCTLS) + return false; + return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; +} + /* Common ioctl debug function. This function can be used by external ioctl messages as well as internal V4L ioctl */ void v4l_printk_ioctl(unsigned int cmd) @@ -297,7 +310,7 @@ void v4l_printk_ioctl(unsigned int cmd) type = "v4l2"; break; } - printk("%s", v4l2_ioctls[_IOC_NR(cmd)]); + printk("%s", v4l2_ioctls[_IOC_NR(cmd)].name); return; default: type = "unknown"; @@ -1948,9 +1961,9 @@ static long __video_do_ioctl(struct file *file, vfd->v4l2_dev->name); break; } -#ifdef CONFIG_VIDEO_ADV_DEBUG case VIDIOC_DBG_G_REGISTER: { +#ifdef CONFIG_VIDEO_ADV_DEBUG struct v4l2_dbg_register *p = arg; if (ops->vidioc_g_register) { @@ -1959,10 +1972,12 @@ static long __video_do_ioctl(struct file *file, else ret = ops->vidioc_g_register(file, fh, p); } +#endif break; } case VIDIOC_DBG_S_REGISTER: { +#ifdef CONFIG_VIDEO_ADV_DEBUG struct v4l2_dbg_register *p = arg; if (ops->vidioc_s_register) { @@ -1971,9 +1986,9 @@ static long __video_do_ioctl(struct file *file, else ret = ops->vidioc_s_register(file, fh, p); } +#endif break; } -#endif case VIDIOC_DBG_G_CHIP_IDENT: { struct v4l2_dbg_chip_ident *p = arg; |