summaryrefslogtreecommitdiff
path: root/drivers/media/video/v4l2-ioctl.c
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-10 02:51:31 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 09:13:43 -0300
commit8ab75e3ecd8f232d9564510f0c601a6aa7a149ea (patch)
treed0a0a2e1b8fa4cef8234c09582c622a3e1aa1d42 /drivers/media/video/v4l2-ioctl.c
parentccfc97bdb5ae8b8edc55169ac6924e08449836ac (diff)
[media] v4l2-dev: make it possible to skip locking for selected ioctls
Using the V4L2 core lock is a very robust method that is usually very good at doing the right thing. But some drivers, particularly USB drivers, may want to prevent the core from taking the lock for specific ioctls, particularly buffer queuing ioctls. The reason is that certain commands like S_CTRL can take a long time to process over USB and all the time the core has the lock, preventing VIDIOC_DQBUF from proceeding, even though a frame may be ready in the queue. This introduces unwanted latency. Since the buffer queuing commands often have their own internal lock it is often not necessary to take the core lock. Drivers can now say that they don't want the core to take the lock for specific ioctls. As it is a specific opt-out it makes it clear to the reviewer that those ioctls will need more care when reviewing. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/v4l2-ioctl.c')
-rw-r--r--drivers/media/video/v4l2-ioctl.c189
1 files changed, 102 insertions, 87 deletions
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;