* [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront.
2012-05-10 7:05 ` [RFCv1 PATCH 1/5] v4l2-dev: make it possible to skip locking for selected ioctls Hans Verkuil
@ 2012-05-10 7:05 ` Hans Verkuil
2012-05-10 8:06 ` Hans Verkuil
` (2 more replies)
2012-05-10 7:05 ` [RFCv1 PATCH 3/5] tea575x-tuner: mark VIDIOC_S_HW_FREQ_SEEK as an invalid ioctl Hans Verkuil
` (3 subsequent siblings)
4 siblings, 3 replies; 20+ messages in thread
From: Hans Verkuil @ 2012-05-10 7:05 UTC (permalink / raw)
To: linux-media; +Cc: Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Rather than testing whether an ioctl is implemented in the driver or not
every time the ioctl is called, do it upfront when the device is registered.
This also allows a driver to disable certain ioctls based on the capabilities
of the detected board, something you can't do today without creating separate
v4l2_ioctl_ops structs for each new variation.
For the most part it is pretty straightforward, but for control ioctls a flag
is needed since it is possible that you have per-filehandle controls, and that
can't be determined upfront of course.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/video/v4l2-dev.c | 171 +++++++++++++++++
drivers/media/video/v4l2-ioctl.c | 391 +++++++++++---------------------------
include/media/v4l2-dev.h | 11 ++
3 files changed, 297 insertions(+), 276 deletions(-)
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index a51a061..4d98ee1 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -516,6 +516,175 @@ static int get_index(struct video_device *vdev)
return find_first_zero_bit(used, VIDEO_NUM_DEVICES);
}
+#define SET_VALID_IOCTL(ops, cmd, op) \
+ if (ops->op) \
+ set_bit(_IOC_NR(cmd), valid_ioctls)
+
+/* This determines which ioctls are actually implemented in the driver.
+ It's a one-time thing which simplifies video_ioctl2 as it can just do
+ a bit test.
+
+ Note that drivers can override this by setting bits to 1 in
+ vdev->valid_ioctls. If an ioctl is marked as 1 when this function is
+ called, then that ioctl will actually be marked as unimplemented.
+
+ It does that by first setting up the local valid_ioctls bitmap, and
+ at the end do a:
+
+ vdev->valid_ioctls = valid_ioctls & ~(vdev->valid_ioctls)
+ */
+static void determine_valid_ioctls(struct video_device *vdev)
+{
+ DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
+ const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
+
+ bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE);
+
+ SET_VALID_IOCTL(ops, VIDIOC_QUERYCAP, vidioc_querycap);
+ if (ops->vidioc_g_priority ||
+ test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
+ set_bit(_IOC_NR(VIDIOC_G_PRIORITY), valid_ioctls);
+ if (ops->vidioc_s_priority ||
+ test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
+ set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls);
+ if (ops->vidioc_enum_fmt_vid_cap ||
+ ops->vidioc_enum_fmt_vid_out ||
+ ops->vidioc_enum_fmt_vid_cap_mplane ||
+ ops->vidioc_enum_fmt_vid_out_mplane ||
+ ops->vidioc_enum_fmt_vid_overlay ||
+ ops->vidioc_enum_fmt_type_private)
+ set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
+ if (ops->vidioc_g_fmt_vid_cap ||
+ ops->vidioc_g_fmt_vid_out ||
+ ops->vidioc_g_fmt_vid_cap_mplane ||
+ ops->vidioc_g_fmt_vid_out_mplane ||
+ ops->vidioc_g_fmt_vid_overlay ||
+ ops->vidioc_g_fmt_vbi_cap ||
+ ops->vidioc_g_fmt_vid_out_overlay ||
+ ops->vidioc_g_fmt_vbi_out ||
+ ops->vidioc_g_fmt_sliced_vbi_cap ||
+ ops->vidioc_g_fmt_sliced_vbi_out ||
+ ops->vidioc_g_fmt_type_private)
+ set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
+ if (ops->vidioc_s_fmt_vid_cap ||
+ ops->vidioc_s_fmt_vid_out ||
+ ops->vidioc_s_fmt_vid_cap_mplane ||
+ ops->vidioc_s_fmt_vid_out_mplane ||
+ ops->vidioc_s_fmt_vid_overlay ||
+ ops->vidioc_s_fmt_vbi_cap ||
+ ops->vidioc_s_fmt_vid_out_overlay ||
+ ops->vidioc_s_fmt_vbi_out ||
+ ops->vidioc_s_fmt_sliced_vbi_cap ||
+ ops->vidioc_s_fmt_sliced_vbi_out ||
+ ops->vidioc_s_fmt_type_private)
+ set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
+ if (ops->vidioc_try_fmt_vid_cap ||
+ ops->vidioc_try_fmt_vid_out ||
+ ops->vidioc_try_fmt_vid_cap_mplane ||
+ ops->vidioc_try_fmt_vid_out_mplane ||
+ ops->vidioc_try_fmt_vid_overlay ||
+ ops->vidioc_try_fmt_vbi_cap ||
+ ops->vidioc_try_fmt_vid_out_overlay ||
+ ops->vidioc_try_fmt_vbi_out ||
+ ops->vidioc_try_fmt_sliced_vbi_cap ||
+ ops->vidioc_try_fmt_sliced_vbi_out ||
+ ops->vidioc_try_fmt_type_private)
+ set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
+ SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
+ SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
+ SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
+ SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
+ SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay);
+ SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf);
+ SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf);
+ SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
+ SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
+ if (vdev->tvnorms)
+ set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls);
+ if (ops->vidioc_g_std || vdev->current_norm)
+ set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls);
+ SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std);
+ SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd);
+ SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
+ SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
+ SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);
+ SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output);
+ SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output);
+ SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output);
+ /* Note: the control handler can also be passed through the filehandle,
+ and that can't be tested here. If the bit for these control ioctls
+ is set, then the ioctl is valid. But if it is 0, then it can still
+ be valid if the filehandle passed the control handler. */
+ if (vdev->ctrl_handler || ops->vidioc_queryctrl)
+ set_bit(_IOC_NR(VIDIOC_QUERYCTRL), valid_ioctls);
+ if (vdev->ctrl_handler || ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls)
+ set_bit(_IOC_NR(VIDIOC_G_CTRL), valid_ioctls);
+ if (vdev->ctrl_handler || ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls)
+ set_bit(_IOC_NR(VIDIOC_S_CTRL), valid_ioctls);
+ if (vdev->ctrl_handler || ops->vidioc_g_ext_ctrls)
+ set_bit(_IOC_NR(VIDIOC_G_EXT_CTRLS), valid_ioctls);
+ if (vdev->ctrl_handler || ops->vidioc_s_ext_ctrls)
+ set_bit(_IOC_NR(VIDIOC_S_EXT_CTRLS), valid_ioctls);
+ if (vdev->ctrl_handler || ops->vidioc_try_ext_ctrls)
+ set_bit(_IOC_NR(VIDIOC_TRY_EXT_CTRLS), valid_ioctls);
+ if (vdev->ctrl_handler || ops->vidioc_querymenu)
+ set_bit(_IOC_NR(VIDIOC_QUERYMENU), valid_ioctls);
+ SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio);
+ SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio);
+ SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio);
+ SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDOUT, vidioc_enumaudout);
+ SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout);
+ SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout);
+ SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator);
+ SET_VALID_IOCTL(ops, VIDIOC_S_MODULATOR, vidioc_s_modulator);
+ if (ops->vidioc_g_crop || ops->vidioc_g_selection)
+ set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls);
+ if (ops->vidioc_s_crop || ops->vidioc_s_selection)
+ set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls);
+ SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection);
+ SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection);
+ if (ops->vidioc_cropcap || ops->vidioc_g_selection)
+ set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls);
+ SET_VALID_IOCTL(ops, VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp);
+ SET_VALID_IOCTL(ops, VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp);
+ SET_VALID_IOCTL(ops, VIDIOC_G_ENC_INDEX, vidioc_g_enc_index);
+ SET_VALID_IOCTL(ops, VIDIOC_ENCODER_CMD, vidioc_encoder_cmd);
+ SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd);
+ SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd);
+ SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd);
+ if (ops->vidioc_g_parm || vdev->current_norm)
+ set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls);
+ SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm);
+ SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner);
+ SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner);
+ SET_VALID_IOCTL(ops, VIDIOC_G_FREQUENCY, vidioc_g_frequency);
+ SET_VALID_IOCTL(ops, VIDIOC_S_FREQUENCY, vidioc_s_frequency);
+ SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);
+ SET_VALID_IOCTL(ops, VIDIOC_LOG_STATUS, vidioc_log_status);
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+ SET_VALID_IOCTL(ops, VIDIOC_DBG_G_REGISTER, vidioc_g_register);
+ SET_VALID_IOCTL(ops, VIDIOC_DBG_S_REGISTER, vidioc_s_register);
+#endif
+ SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident);
+ SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek);
+ SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes);
+ SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals);
+ SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets);
+ SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset);
+ SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset);
+ SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset);
+ SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings);
+ SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings);
+ /* yes, really vidioc_subscribe_event */
+ SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event);
+ SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event);
+ SET_VALID_IOCTL(ops, VIDIOC_UNSUBSCRIBE_EVENT, vidioc_unsubscribe_event);
+ SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs);
+ SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
+ bitmap_andnot(vdev->valid_ioctls, valid_ioctls, vdev->valid_ioctls,
+ BASE_VIDIOC_PRIVATE);
+}
+
/**
* __video_register_device - register video4linux devices
* @vdev: video device structure we want to register
@@ -663,6 +832,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
vdev->index = get_index(vdev);
mutex_unlock(&videodev_lock);
+ determine_valid_ioctls(vdev);
+
/* Part 3: Initialize the character device */
vdev->cdev = cdev_alloc();
if (vdev->cdev == NULL) {
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 3f34098..21da16d 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -55,19 +55,6 @@
memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
-#define have_fmt_ops(foo) ( \
- ops->vidioc_##foo##_fmt_vid_cap || \
- ops->vidioc_##foo##_fmt_vid_out || \
- ops->vidioc_##foo##_fmt_vid_cap_mplane || \
- ops->vidioc_##foo##_fmt_vid_out_mplane || \
- ops->vidioc_##foo##_fmt_vid_overlay || \
- ops->vidioc_##foo##_fmt_vbi_cap || \
- ops->vidioc_##foo##_fmt_vid_out_overlay || \
- ops->vidioc_##foo##_fmt_vbi_out || \
- ops->vidioc_##foo##_fmt_sliced_vbi_cap || \
- ops->vidioc_##foo##_fmt_sliced_vbi_out || \
- ops->vidioc_##foo##_fmt_type_private)
-
struct std_descr {
v4l2_std_id std;
const char *descr;
@@ -198,93 +185,98 @@ static const char *v4l2_memory_names[] = {
struct v4l2_ioctl_info {
unsigned int ioctl;
+ u16 flags;
const char * const name;
};
-#define IOCTL_INFO(_ioctl) [_IOC_NR(_ioctl)] = { \
- .ioctl = _ioctl, \
- .name = #_ioctl, \
+/* This control can be valid if the filehandle passes a control handler. */
+#define INFO_FL_CTRL (1 << 1)
+
+#define IOCTL_INFO(_ioctl, _flags) [_IOC_NR(_ioctl)] = { \
+ .ioctl = _ioctl, \
+ .flags = _flags, \
+ .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),
+ IOCTL_INFO(VIDIOC_QUERYCAP, 0),
+ IOCTL_INFO(VIDIOC_ENUM_FMT, 0),
+ IOCTL_INFO(VIDIOC_G_FMT, 0),
+ IOCTL_INFO(VIDIOC_S_FMT, 0),
+ IOCTL_INFO(VIDIOC_REQBUFS, 0),
+ IOCTL_INFO(VIDIOC_QUERYBUF, 0),
+ IOCTL_INFO(VIDIOC_G_FBUF, 0),
+ IOCTL_INFO(VIDIOC_S_FBUF, 0),
+ IOCTL_INFO(VIDIOC_OVERLAY, 0),
+ IOCTL_INFO(VIDIOC_QBUF, 0),
+ IOCTL_INFO(VIDIOC_DQBUF, 0),
+ IOCTL_INFO(VIDIOC_STREAMON, 0),
+ IOCTL_INFO(VIDIOC_STREAMOFF, 0),
+ IOCTL_INFO(VIDIOC_G_PARM, 0),
+ IOCTL_INFO(VIDIOC_S_PARM, 0),
+ IOCTL_INFO(VIDIOC_G_STD, 0),
+ IOCTL_INFO(VIDIOC_S_STD, 0),
+ IOCTL_INFO(VIDIOC_ENUMSTD, 0),
+ IOCTL_INFO(VIDIOC_ENUMINPUT, 0),
+ IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL),
+ IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_CTRL),
+ IOCTL_INFO(VIDIOC_G_TUNER, 0),
+ IOCTL_INFO(VIDIOC_S_TUNER, 0),
+ IOCTL_INFO(VIDIOC_G_AUDIO, 0),
+ IOCTL_INFO(VIDIOC_S_AUDIO, 0),
+ IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL),
+ IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL),
+ IOCTL_INFO(VIDIOC_G_INPUT, 0),
+ IOCTL_INFO(VIDIOC_S_INPUT, 0),
+ IOCTL_INFO(VIDIOC_G_OUTPUT, 0),
+ IOCTL_INFO(VIDIOC_S_OUTPUT, 0),
+ IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0),
+ IOCTL_INFO(VIDIOC_G_AUDOUT, 0),
+ IOCTL_INFO(VIDIOC_S_AUDOUT, 0),
+ IOCTL_INFO(VIDIOC_G_MODULATOR, 0),
+ IOCTL_INFO(VIDIOC_S_MODULATOR, 0),
+ IOCTL_INFO(VIDIOC_G_FREQUENCY, 0),
+ IOCTL_INFO(VIDIOC_S_FREQUENCY, 0),
+ IOCTL_INFO(VIDIOC_CROPCAP, 0),
+ IOCTL_INFO(VIDIOC_G_CROP, 0),
+ IOCTL_INFO(VIDIOC_S_CROP, 0),
+ IOCTL_INFO(VIDIOC_G_SELECTION, 0),
+ IOCTL_INFO(VIDIOC_S_SELECTION, 0),
+ IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0),
+ IOCTL_INFO(VIDIOC_S_JPEGCOMP, 0),
+ IOCTL_INFO(VIDIOC_QUERYSTD, 0),
+ IOCTL_INFO(VIDIOC_TRY_FMT, 0),
+ IOCTL_INFO(VIDIOC_ENUMAUDIO, 0),
+ IOCTL_INFO(VIDIOC_ENUMAUDOUT, 0),
+ IOCTL_INFO(VIDIOC_G_PRIORITY, 0),
+ IOCTL_INFO(VIDIOC_S_PRIORITY, 0),
+ IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, 0),
+ IOCTL_INFO(VIDIOC_LOG_STATUS, 0),
+ IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL),
+ IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_CTRL),
+ IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0),
+ IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, 0),
+ IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, 0),
+ IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0),
+ IOCTL_INFO(VIDIOC_ENCODER_CMD, 0),
+ IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, 0),
+ IOCTL_INFO(VIDIOC_DECODER_CMD, 0),
+ IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0),
+ IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0),
+ IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0),
+ IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0),
+ IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, 0),
+ IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0),
+ IOCTL_INFO(VIDIOC_S_DV_PRESET, 0),
+ IOCTL_INFO(VIDIOC_G_DV_PRESET, 0),
+ IOCTL_INFO(VIDIOC_QUERY_DV_PRESET, 0),
+ IOCTL_INFO(VIDIOC_S_DV_TIMINGS, 0),
+ IOCTL_INFO(VIDIOC_G_DV_TIMINGS, 0),
+ IOCTL_INFO(VIDIOC_DQEVENT, 0),
+ IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0),
+ IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0),
+ IOCTL_INFO(VIDIOC_CREATE_BUFS, 0),
+ IOCTL_INFO(VIDIOC_PREPARE_BUF, 0),
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -526,19 +518,28 @@ static long __video_do_ioctl(struct file *file,
return ret;
}
- if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
- !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
- v4l_print_ioctl(vfd->name, cmd);
- printk(KERN_CONT "\n");
- }
-
if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
vfh = file->private_data;
use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+ if (use_fh_prio)
+ ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
}
- if (use_fh_prio)
- ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
+ if (v4l2_is_valid_ioctl(cmd)) {
+ struct v4l2_ioctl_info *info = &v4l2_ioctls[_IOC_NR(cmd)];
+
+ if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls)) {
+ if (!(info->flags & INFO_FL_CTRL) ||
+ !(vfh && vfh->ctrl_handler))
+ return -ENOTTY;
+ }
+ }
+
+ if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
+ !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
+ v4l_print_ioctl(vfd->name, cmd);
+ printk(KERN_CONT "\n");
+ }
switch (cmd) {
@@ -547,9 +548,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_capability *cap = (struct v4l2_capability *)arg;
- if (!ops->vidioc_querycap)
- break;
-
cap->version = LINUX_VERSION_CODE;
ret = ops->vidioc_querycap(file, fh, cap);
if (!ret)
@@ -600,6 +598,7 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_fmtdesc *f = arg;
+ ret = -EINVAL;
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (likely(ops->vidioc_enum_fmt_vid_cap))
@@ -632,7 +631,7 @@ static long __video_do_ioctl(struct file *file,
default:
break;
}
- if (likely (!ret))
+ if (likely(!ret))
dbgarg(cmd, "index=%d, type=%d, flags=%d, "
"pixelformat=%c%c%c%c, description='%s'\n",
f->index, f->type, f->flags,
@@ -641,14 +640,6 @@ static long __video_do_ioctl(struct file *file,
(f->pixelformat >> 16) & 0xff,
(f->pixelformat >> 24) & 0xff,
f->description);
- else if (ret == -ENOTTY &&
- (ops->vidioc_enum_fmt_vid_cap ||
- ops->vidioc_enum_fmt_vid_out ||
- ops->vidioc_enum_fmt_vid_cap_mplane ||
- ops->vidioc_enum_fmt_vid_out_mplane ||
- ops->vidioc_enum_fmt_vid_overlay ||
- ops->vidioc_enum_fmt_type_private))
- ret = -EINVAL;
break;
}
case VIDIOC_G_FMT:
@@ -658,6 +649,7 @@ static long __video_do_ioctl(struct file *file,
/* FIXME: Should be one dump per type */
dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
+ ret = -EINVAL;
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (ops->vidioc_g_fmt_vid_cap)
@@ -719,17 +711,12 @@ static long __video_do_ioctl(struct file *file,
fh, f);
break;
}
- if (unlikely(ret == -ENOTTY && have_fmt_ops(g)))
- ret = -EINVAL;
-
break;
}
case VIDIOC_S_FMT:
{
struct v4l2_format *f = (struct v4l2_format *)arg;
- if (!have_fmt_ops(s))
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -817,6 +804,7 @@ static long __video_do_ioctl(struct file *file,
/* FIXME: Should be one dump per type */
dbgarg(cmd, "type=%s\n", prt_names(f->type,
v4l2_type_names));
+ ret = -EINVAL;
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
CLEAR_AFTER_FIELD(f, fmt.pix);
@@ -889,8 +877,6 @@ static long __video_do_ioctl(struct file *file,
fh, f);
break;
}
- if (unlikely(ret == -ENOTTY && have_fmt_ops(try)))
- ret = -EINVAL;
break;
}
/* FIXME: Those buf reqs could be handled here,
@@ -901,8 +887,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_requestbuffers *p = arg;
- if (!ops->vidioc_reqbufs)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -925,8 +909,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_buffer *p = arg;
- if (!ops->vidioc_querybuf)
- break;
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -940,8 +922,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_buffer *p = arg;
- if (!ops->vidioc_qbuf)
- break;
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -955,8 +935,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_buffer *p = arg;
- if (!ops->vidioc_dqbuf)
- break;
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -970,8 +948,6 @@ static long __video_do_ioctl(struct file *file,
{
int *i = arg;
- if (!ops->vidioc_overlay)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -984,8 +960,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_framebuffer *p = arg;
- if (!ops->vidioc_g_fbuf)
- break;
ret = ops->vidioc_g_fbuf(file, fh, arg);
if (!ret) {
dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
@@ -999,8 +973,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_framebuffer *p = arg;
- if (!ops->vidioc_s_fbuf)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1015,8 +987,6 @@ static long __video_do_ioctl(struct file *file,
{
enum v4l2_buf_type i = *(int *)arg;
- if (!ops->vidioc_streamon)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1029,8 +999,6 @@ static long __video_do_ioctl(struct file *file,
{
enum v4l2_buf_type i = *(int *)arg;
- if (!ops->vidioc_streamoff)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1104,9 +1072,6 @@ static long __video_do_ioctl(struct file *file,
dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
- if (!ops->vidioc_s_std)
- break;
-
if (ret_prio) {
ret = ret_prio;
break;
@@ -1128,8 +1093,6 @@ static long __video_do_ioctl(struct file *file,
{
v4l2_std_id *p = arg;
- if (!ops->vidioc_querystd)
- break;
/*
* If nothing detected, it should return all supported
* Drivers just need to mask the std argument, in order
@@ -1163,9 +1126,6 @@ static long __video_do_ioctl(struct file *file,
if (ops->vidioc_s_dv_timings)
p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
- if (!ops->vidioc_enum_input)
- break;
-
ret = ops->vidioc_enum_input(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1181,8 +1141,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (!ops->vidioc_g_input)
- break;
ret = ops->vidioc_g_input(file, fh, i);
if (!ret)
dbgarg(cmd, "value=%d\n", *i);
@@ -1192,8 +1150,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (!ops->vidioc_s_input)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1208,9 +1164,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_output *p = arg;
- if (!ops->vidioc_enum_output)
- break;
-
/*
* We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
* CAP_STD here based on ioctl handler provided by the
@@ -1237,8 +1190,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (!ops->vidioc_g_output)
- break;
ret = ops->vidioc_g_output(file, fh, i);
if (!ret)
dbgarg(cmd, "value=%d\n", *i);
@@ -1248,8 +1199,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (!ops->vidioc_s_output)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1441,8 +1390,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audio *p = arg;
- if (!ops->vidioc_enumaudio)
- break;
ret = ops->vidioc_enumaudio(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
@@ -1456,9 +1403,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audio *p = arg;
- if (!ops->vidioc_g_audio)
- break;
-
ret = ops->vidioc_g_audio(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
@@ -1472,8 +1416,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audio *p = arg;
- if (!ops->vidioc_s_audio)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1488,8 +1430,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audioout *p = arg;
- if (!ops->vidioc_enumaudout)
- break;
dbgarg(cmd, "Enum for index=%d\n", p->index);
ret = ops->vidioc_enumaudout(file, fh, p);
if (!ret)
@@ -1502,9 +1442,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audioout *p = arg;
- if (!ops->vidioc_g_audout)
- break;
-
ret = ops->vidioc_g_audout(file, fh, p);
if (!ret)
dbgarg2("index=%d, name=%s, capability=%d, "
@@ -1516,8 +1453,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audioout *p = arg;
- if (!ops->vidioc_s_audout)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1533,8 +1468,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_modulator *p = arg;
- if (!ops->vidioc_g_modulator)
- break;
ret = ops->vidioc_g_modulator(file, fh, p);
if (!ret)
dbgarg(cmd, "index=%d, name=%s, "
@@ -1549,8 +1482,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_modulator *p = arg;
- if (!ops->vidioc_s_modulator)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1566,9 +1497,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_crop *p = arg;
- if (!ops->vidioc_g_crop && !ops->vidioc_g_selection)
- break;
-
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
if (ops->vidioc_g_crop) {
@@ -1600,9 +1528,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_crop *p = arg;
- if (!ops->vidioc_s_crop && !ops->vidioc_s_selection)
- break;
-
if (ret_prio) {
ret = ret_prio;
break;
@@ -1633,9 +1558,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_selection *p = arg;
- if (!ops->vidioc_g_selection)
- break;
-
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
ret = ops->vidioc_g_selection(file, fh, p);
@@ -1647,9 +1569,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_selection *p = arg;
- if (!ops->vidioc_s_selection)
- break;
-
if (ret_prio) {
ret = ret_prio;
break;
@@ -1666,9 +1585,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_cropcap *p = arg;
/*FIXME: Should also show v4l2_fract pixelaspect */
- if (!ops->vidioc_cropcap && !ops->vidioc_g_selection)
- break;
-
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
if (ops->vidioc_cropcap) {
ret = ops->vidioc_cropcap(file, fh, p);
@@ -1712,9 +1628,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_jpegcompression *p = arg;
- if (!ops->vidioc_g_jpegcomp)
- break;
-
ret = ops->vidioc_g_jpegcomp(file, fh, p);
if (!ret)
dbgarg(cmd, "quality=%d, APPn=%d, "
@@ -1728,8 +1641,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_jpegcompression *p = arg;
- if (!ops->vidioc_g_jpegcomp)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1745,8 +1656,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_enc_idx *p = arg;
- if (!ops->vidioc_g_enc_index)
- break;
ret = ops->vidioc_g_enc_index(file, fh, p);
if (!ret)
dbgarg(cmd, "entries=%d, entries_cap=%d\n",
@@ -1757,8 +1666,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_encoder_cmd *p = arg;
- if (!ops->vidioc_encoder_cmd)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1772,8 +1679,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_encoder_cmd *p = arg;
- if (!ops->vidioc_try_encoder_cmd)
- break;
ret = ops->vidioc_try_encoder_cmd(file, fh, p);
if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1783,8 +1688,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_decoder_cmd *p = arg;
- if (!ops->vidioc_decoder_cmd)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1798,8 +1701,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_decoder_cmd *p = arg;
- if (!ops->vidioc_try_decoder_cmd)
- break;
ret = ops->vidioc_try_decoder_cmd(file, fh, p);
if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1809,8 +1710,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_streamparm *p = arg;
- if (!ops->vidioc_g_parm && !vfd->current_norm)
- break;
if (ops->vidioc_g_parm) {
ret = check_fmt(ops, p->type);
if (ret)
@@ -1838,8 +1737,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_streamparm *p = arg;
- if (!ops->vidioc_s_parm)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1856,9 +1753,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_tuner *p = arg;
- if (!ops->vidioc_g_tuner)
- break;
-
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
ret = ops->vidioc_g_tuner(file, fh, p);
@@ -1877,8 +1771,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_tuner *p = arg;
- if (!ops->vidioc_s_tuner)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1900,9 +1792,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_frequency *p = arg;
- if (!ops->vidioc_g_frequency)
- break;
-
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
ret = ops->vidioc_g_frequency(file, fh, p);
@@ -1916,8 +1805,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_frequency *p = arg;
enum v4l2_tuner_type type;
- if (!ops->vidioc_s_frequency)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -1936,9 +1823,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_sliced_vbi_cap *p = arg;
- if (!ops->vidioc_g_sliced_vbi_cap)
- break;
-
/* Clear up to type, everything after type is zerod already */
memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
@@ -1950,8 +1834,6 @@ static long __video_do_ioctl(struct file *file,
}
case VIDIOC_LOG_STATUS:
{
- if (!ops->vidioc_log_status)
- break;
if (vfd->v4l2_dev)
pr_info("%s: ================= START STATUS =================\n",
vfd->v4l2_dev->name);
@@ -1966,12 +1848,10 @@ static long __video_do_ioctl(struct file *file,
#ifdef CONFIG_VIDEO_ADV_DEBUG
struct v4l2_dbg_register *p = arg;
- if (ops->vidioc_g_register) {
- if (!capable(CAP_SYS_ADMIN))
- ret = -EPERM;
- else
- ret = ops->vidioc_g_register(file, fh, p);
- }
+ if (!capable(CAP_SYS_ADMIN))
+ ret = -EPERM;
+ else
+ ret = ops->vidioc_g_register(file, fh, p);
#endif
break;
}
@@ -1980,12 +1860,10 @@ static long __video_do_ioctl(struct file *file,
#ifdef CONFIG_VIDEO_ADV_DEBUG
struct v4l2_dbg_register *p = arg;
- if (ops->vidioc_s_register) {
- if (!capable(CAP_SYS_ADMIN))
- ret = -EPERM;
- else
- ret = ops->vidioc_s_register(file, fh, p);
- }
+ if (!capable(CAP_SYS_ADMIN))
+ ret = -EPERM;
+ else
+ ret = ops->vidioc_s_register(file, fh, p);
#endif
break;
}
@@ -1993,8 +1871,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dbg_chip_ident *p = arg;
- if (!ops->vidioc_g_chip_ident)
- break;
p->ident = V4L2_IDENT_NONE;
p->revision = 0;
ret = ops->vidioc_g_chip_ident(file, fh, p);
@@ -2007,8 +1883,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_hw_freq_seek *p = arg;
enum v4l2_tuner_type type;
- if (!ops->vidioc_s_hw_freq_seek)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -2028,9 +1902,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_frmsizeenum *p = arg;
- if (!ops->vidioc_enum_framesizes)
- break;
-
ret = ops->vidioc_enum_framesizes(file, fh, p);
dbgarg(cmd,
"index=%d, pixelformat=%c%c%c%c, type=%d ",
@@ -2064,9 +1935,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_frmivalenum *p = arg;
- if (!ops->vidioc_enum_frameintervals)
- break;
-
ret = ops->vidioc_enum_frameintervals(file, fh, p);
dbgarg(cmd,
"index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
@@ -2099,9 +1967,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_enum_preset *p = arg;
- if (!ops->vidioc_enum_dv_presets)
- break;
-
ret = ops->vidioc_enum_dv_presets(file, fh, p);
if (!ret)
dbgarg(cmd,
@@ -2115,8 +1980,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_preset *p = arg;
- if (!ops->vidioc_s_dv_preset)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -2130,9 +1993,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_preset *p = arg;
- if (!ops->vidioc_g_dv_preset)
- break;
-
ret = ops->vidioc_g_dv_preset(file, fh, p);
if (!ret)
dbgarg(cmd, "preset=%d\n", p->preset);
@@ -2142,9 +2002,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_preset *p = arg;
- if (!ops->vidioc_query_dv_preset)
- break;
-
ret = ops->vidioc_query_dv_preset(file, fh, p);
if (!ret)
dbgarg(cmd, "preset=%d\n", p->preset);
@@ -2154,8 +2011,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_timings *p = arg;
- if (!ops->vidioc_s_dv_timings)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -2188,9 +2043,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_timings *p = arg;
- if (!ops->vidioc_g_dv_timings)
- break;
-
ret = ops->vidioc_g_dv_timings(file, fh, p);
if (!ret) {
switch (p->type) {
@@ -2222,9 +2074,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_event *ev = arg;
- if (!ops->vidioc_subscribe_event)
- break;
-
ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK);
if (ret < 0) {
dbgarg(cmd, "no pending events?");
@@ -2241,9 +2090,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_event_subscription *sub = arg;
- if (!ops->vidioc_subscribe_event)
- break;
-
ret = ops->vidioc_subscribe_event(fh, sub);
if (ret < 0) {
dbgarg(cmd, "failed, ret=%ld", ret);
@@ -2256,9 +2102,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_event_subscription *sub = arg;
- if (!ops->vidioc_unsubscribe_event)
- break;
-
ret = ops->vidioc_unsubscribe_event(fh, sub);
if (ret < 0) {
dbgarg(cmd, "failed, ret=%ld", ret);
@@ -2271,8 +2114,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_create_buffers *create = arg;
- if (!ops->vidioc_create_bufs)
- break;
if (ret_prio) {
ret = ret_prio;
break;
@@ -2290,8 +2131,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_buffer *b = arg;
- if (!ops->vidioc_prepare_buf)
- break;
ret = check_fmt(ops, b->type);
if (ret)
break;
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 0da84dc..15e2fe4 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -126,6 +126,7 @@ struct video_device
/* ioctl callbacks */
const struct v4l2_ioctl_ops *ioctl_ops;
+ DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
/* serialization lock */
DECLARE_BITMAP(dont_use_lock, BASE_VIDIOC_PRIVATE);
@@ -184,6 +185,16 @@ static inline void v4l2_dont_use_lock(struct video_device *vdev, unsigned int cm
set_bit(_IOC_NR(cmd), vdev->dont_use_lock);
}
+/* Mark that this command isn't implemented, must be called before
+ video_device_register. See also the comments in determine_valid_ioctls().
+ This function allows drivers to provide just one v4l2_ioctl_ops struct, but
+ disable ioctls based on the specific card that is actually found. */
+static inline void v4l2_dont_use_cmd(struct video_device *vdev, unsigned int cmd)
+{
+ if (_IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
+ set_bit(_IOC_NR(cmd), vdev->valid_ioctls);
+}
+
/* helper functions to access driver private data. */
static inline void *video_get_drvdata(struct video_device *vdev)
{
--
1.7.10
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront.
2012-05-10 7:05 ` [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront Hans Verkuil
@ 2012-05-10 8:06 ` Hans Verkuil
2012-05-10 8:10 ` Hans de Goede
2012-05-14 13:00 ` Laurent Pinchart
2 siblings, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2012-05-10 8:06 UTC (permalink / raw)
To: linux-media; +Cc: Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
On Thu 10 May 2012 09:05:11 Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Rather than testing whether an ioctl is implemented in the driver or not
> every time the ioctl is called, do it upfront when the device is registered.
>
> This also allows a driver to disable certain ioctls based on the capabilities
> of the detected board, something you can't do today without creating separate
> v4l2_ioctl_ops structs for each new variation.
>
> For the most part it is pretty straightforward, but for control ioctls a flag
> is needed since it is possible that you have per-filehandle controls, and that
> can't be determined upfront of course.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
> drivers/media/video/v4l2-dev.c | 171 +++++++++++++++++
> drivers/media/video/v4l2-ioctl.c | 391 +++++++++++---------------------------
> include/media/v4l2-dev.h | 11 ++
> 3 files changed, 297 insertions(+), 276 deletions(-)
>
> diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
> index a51a061..4d98ee1 100644
> --- a/drivers/media/video/v4l2-dev.c
> +++ b/drivers/media/video/v4l2-dev.c
> @@ -516,6 +516,175 @@ static int get_index(struct video_device *vdev)
> return find_first_zero_bit(used, VIDEO_NUM_DEVICES);
> }
>
> +#define SET_VALID_IOCTL(ops, cmd, op) \
> + if (ops->op) \
> + set_bit(_IOC_NR(cmd), valid_ioctls)
> +
> +/* This determines which ioctls are actually implemented in the driver.
> + It's a one-time thing which simplifies video_ioctl2 as it can just do
> + a bit test.
> +
> + Note that drivers can override this by setting bits to 1 in
> + vdev->valid_ioctls. If an ioctl is marked as 1 when this function is
> + called, then that ioctl will actually be marked as unimplemented.
> +
> + It does that by first setting up the local valid_ioctls bitmap, and
> + at the end do a:
> +
> + vdev->valid_ioctls = valid_ioctls & ~(vdev->valid_ioctls)
> + */
> +static void determine_valid_ioctls(struct video_device *vdev)
> +{
> + DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
> + const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
> +
> + bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE);
> +
> + SET_VALID_IOCTL(ops, VIDIOC_QUERYCAP, vidioc_querycap);
> + if (ops->vidioc_g_priority ||
> + test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
> + set_bit(_IOC_NR(VIDIOC_G_PRIORITY), valid_ioctls);
> + if (ops->vidioc_s_priority ||
> + test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
> + set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls);
> + if (ops->vidioc_enum_fmt_vid_cap ||
> + ops->vidioc_enum_fmt_vid_out ||
> + ops->vidioc_enum_fmt_vid_cap_mplane ||
> + ops->vidioc_enum_fmt_vid_out_mplane ||
> + ops->vidioc_enum_fmt_vid_overlay ||
> + ops->vidioc_enum_fmt_type_private)
> + set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
> + if (ops->vidioc_g_fmt_vid_cap ||
> + ops->vidioc_g_fmt_vid_out ||
> + ops->vidioc_g_fmt_vid_cap_mplane ||
> + ops->vidioc_g_fmt_vid_out_mplane ||
> + ops->vidioc_g_fmt_vid_overlay ||
> + ops->vidioc_g_fmt_vbi_cap ||
> + ops->vidioc_g_fmt_vid_out_overlay ||
> + ops->vidioc_g_fmt_vbi_out ||
> + ops->vidioc_g_fmt_sliced_vbi_cap ||
> + ops->vidioc_g_fmt_sliced_vbi_out ||
> + ops->vidioc_g_fmt_type_private)
> + set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
> + if (ops->vidioc_s_fmt_vid_cap ||
> + ops->vidioc_s_fmt_vid_out ||
> + ops->vidioc_s_fmt_vid_cap_mplane ||
> + ops->vidioc_s_fmt_vid_out_mplane ||
> + ops->vidioc_s_fmt_vid_overlay ||
> + ops->vidioc_s_fmt_vbi_cap ||
> + ops->vidioc_s_fmt_vid_out_overlay ||
> + ops->vidioc_s_fmt_vbi_out ||
> + ops->vidioc_s_fmt_sliced_vbi_cap ||
> + ops->vidioc_s_fmt_sliced_vbi_out ||
> + ops->vidioc_s_fmt_type_private)
> + set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
> + if (ops->vidioc_try_fmt_vid_cap ||
> + ops->vidioc_try_fmt_vid_out ||
> + ops->vidioc_try_fmt_vid_cap_mplane ||
> + ops->vidioc_try_fmt_vid_out_mplane ||
> + ops->vidioc_try_fmt_vid_overlay ||
> + ops->vidioc_try_fmt_vbi_cap ||
> + ops->vidioc_try_fmt_vid_out_overlay ||
> + ops->vidioc_try_fmt_vbi_out ||
> + ops->vidioc_try_fmt_sliced_vbi_cap ||
> + ops->vidioc_try_fmt_sliced_vbi_out ||
> + ops->vidioc_try_fmt_type_private)
> + set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
> + SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
> + SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
> + SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
> + SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay);
> + SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf);
> + SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf);
> + SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
> + SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
> + if (vdev->tvnorms)
> + set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls);
> + if (ops->vidioc_g_std || vdev->current_norm)
> + set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std);
> + SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
> + SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
> + SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output);
> + SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output);
> + SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output);
> + /* Note: the control handler can also be passed through the filehandle,
> + and that can't be tested here. If the bit for these control ioctls
> + is set, then the ioctl is valid. But if it is 0, then it can still
> + be valid if the filehandle passed the control handler. */
> + if (vdev->ctrl_handler || ops->vidioc_queryctrl)
> + set_bit(_IOC_NR(VIDIOC_QUERYCTRL), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_G_CTRL), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_S_CTRL), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_g_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_G_EXT_CTRLS), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_s_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_S_EXT_CTRLS), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_try_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_TRY_EXT_CTRLS), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_querymenu)
> + set_bit(_IOC_NR(VIDIOC_QUERYMENU), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio);
> + SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio);
> + SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDOUT, vidioc_enumaudout);
> + SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout);
> + SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout);
> + SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator);
> + SET_VALID_IOCTL(ops, VIDIOC_S_MODULATOR, vidioc_s_modulator);
> + if (ops->vidioc_g_crop || ops->vidioc_g_selection)
> + set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls);
> + if (ops->vidioc_s_crop || ops->vidioc_s_selection)
> + set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection);
> + SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection);
> + if (ops->vidioc_cropcap || ops->vidioc_g_selection)
> + set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp);
> + SET_VALID_IOCTL(ops, VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp);
> + SET_VALID_IOCTL(ops, VIDIOC_G_ENC_INDEX, vidioc_g_enc_index);
> + SET_VALID_IOCTL(ops, VIDIOC_ENCODER_CMD, vidioc_encoder_cmd);
> + SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd);
> + SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd);
> + SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd);
> + if (ops->vidioc_g_parm || vdev->current_norm)
> + set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm);
> + SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner);
> + SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner);
> + SET_VALID_IOCTL(ops, VIDIOC_G_FREQUENCY, vidioc_g_frequency);
> + SET_VALID_IOCTL(ops, VIDIOC_S_FREQUENCY, vidioc_s_frequency);
> + SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);
> + SET_VALID_IOCTL(ops, VIDIOC_LOG_STATUS, vidioc_log_status);
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> + SET_VALID_IOCTL(ops, VIDIOC_DBG_G_REGISTER, vidioc_g_register);
> + SET_VALID_IOCTL(ops, VIDIOC_DBG_S_REGISTER, vidioc_s_register);
> +#endif
> + SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident);
> + SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets);
> + SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset);
> + SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset);
> + SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset);
> + SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings);
> + SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings);
> + /* yes, really vidioc_subscribe_event */
> + SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event);
> + SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event);
> + SET_VALID_IOCTL(ops, VIDIOC_UNSUBSCRIBE_EVENT, vidioc_unsubscribe_event);
> + SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs);
> + SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
> + bitmap_andnot(vdev->valid_ioctls, valid_ioctls, vdev->valid_ioctls,
> + BASE_VIDIOC_PRIVATE);
> +}
> +
> /**
> * __video_register_device - register video4linux devices
> * @vdev: video device structure we want to register
> @@ -663,6 +832,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
> vdev->index = get_index(vdev);
> mutex_unlock(&videodev_lock);
>
> + determine_valid_ioctls(vdev);
OK, this fails if ioctl_ops == NULL :-) I need to check for that before
calling determine_valid_ioctls().
I've prepared a new patch series that fixes this (and that also documents
v4l2_dont_use_cmd).
Hans, that one is available here:
git://linuxtv.org/hverkuil/media_tree.git ioctlv2
Regards,
Hans
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront.
2012-05-10 7:05 ` [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront Hans Verkuil
2012-05-10 8:06 ` Hans Verkuil
@ 2012-05-10 8:10 ` Hans de Goede
2012-05-10 8:21 ` Hans de Goede
2012-05-10 8:27 ` Hans Verkuil
2012-05-14 13:00 ` Laurent Pinchart
2 siblings, 2 replies; 20+ messages in thread
From: Hans de Goede @ 2012-05-10 8:10 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Mauro Carvalho Chehab, Hans Verkuil
Hi,
Comments inline.
On 05/10/2012 09:05 AM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> Rather than testing whether an ioctl is implemented in the driver or not
> every time the ioctl is called, do it upfront when the device is registered.
>
> This also allows a driver to disable certain ioctls based on the capabilities
> of the detected board, something you can't do today without creating separate
> v4l2_ioctl_ops structs for each new variation.
>
> For the most part it is pretty straightforward, but for control ioctls a flag
> is needed since it is possible that you have per-filehandle controls, and that
> can't be determined upfront of course.
>
> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>
> ---
> drivers/media/video/v4l2-dev.c | 171 +++++++++++++++++
> drivers/media/video/v4l2-ioctl.c | 391 +++++++++++---------------------------
> include/media/v4l2-dev.h | 11 ++
> 3 files changed, 297 insertions(+), 276 deletions(-)
>
> diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
> index a51a061..4d98ee1 100644
> --- a/drivers/media/video/v4l2-dev.c
> +++ b/drivers/media/video/v4l2-dev.c
> @@ -516,6 +516,175 @@ static int get_index(struct video_device *vdev)
> return find_first_zero_bit(used, VIDEO_NUM_DEVICES);
> }
>
> +#define SET_VALID_IOCTL(ops, cmd, op) \
> + if (ops->op) \
> + set_bit(_IOC_NR(cmd), valid_ioctls)
> +
> +/* This determines which ioctls are actually implemented in the driver.
> + It's a one-time thing which simplifies video_ioctl2 as it can just do
> + a bit test.
> +
> + Note that drivers can override this by setting bits to 1 in
> + vdev->valid_ioctls. If an ioctl is marked as 1 when this function is
> + called, then that ioctl will actually be marked as unimplemented.
> +
> + It does that by first setting up the local valid_ioctls bitmap, and
> + at the end do a:
> +
> + vdev->valid_ioctls = valid_ioctls& ~(vdev->valid_ioctls)
> + */
> +static void determine_valid_ioctls(struct video_device *vdev)
> +{
> + DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
> + const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
> +
> + bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE);
> +
> + SET_VALID_IOCTL(ops, VIDIOC_QUERYCAP, vidioc_querycap);
> + if (ops->vidioc_g_priority ||
> + test_bit(V4L2_FL_USE_FH_PRIO,&vdev->flags))
> + set_bit(_IOC_NR(VIDIOC_G_PRIORITY), valid_ioctls);
> + if (ops->vidioc_s_priority ||
> + test_bit(V4L2_FL_USE_FH_PRIO,&vdev->flags))
> + set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls);
> + if (ops->vidioc_enum_fmt_vid_cap ||
> + ops->vidioc_enum_fmt_vid_out ||
> + ops->vidioc_enum_fmt_vid_cap_mplane ||
> + ops->vidioc_enum_fmt_vid_out_mplane ||
> + ops->vidioc_enum_fmt_vid_overlay ||
> + ops->vidioc_enum_fmt_type_private)
> + set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
> + if (ops->vidioc_g_fmt_vid_cap ||
> + ops->vidioc_g_fmt_vid_out ||
> + ops->vidioc_g_fmt_vid_cap_mplane ||
> + ops->vidioc_g_fmt_vid_out_mplane ||
> + ops->vidioc_g_fmt_vid_overlay ||
> + ops->vidioc_g_fmt_vbi_cap ||
> + ops->vidioc_g_fmt_vid_out_overlay ||
> + ops->vidioc_g_fmt_vbi_out ||
> + ops->vidioc_g_fmt_sliced_vbi_cap ||
> + ops->vidioc_g_fmt_sliced_vbi_out ||
> + ops->vidioc_g_fmt_type_private)
> + set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
> + if (ops->vidioc_s_fmt_vid_cap ||
> + ops->vidioc_s_fmt_vid_out ||
> + ops->vidioc_s_fmt_vid_cap_mplane ||
> + ops->vidioc_s_fmt_vid_out_mplane ||
> + ops->vidioc_s_fmt_vid_overlay ||
> + ops->vidioc_s_fmt_vbi_cap ||
> + ops->vidioc_s_fmt_vid_out_overlay ||
> + ops->vidioc_s_fmt_vbi_out ||
> + ops->vidioc_s_fmt_sliced_vbi_cap ||
> + ops->vidioc_s_fmt_sliced_vbi_out ||
> + ops->vidioc_s_fmt_type_private)
> + set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
> + if (ops->vidioc_try_fmt_vid_cap ||
> + ops->vidioc_try_fmt_vid_out ||
> + ops->vidioc_try_fmt_vid_cap_mplane ||
> + ops->vidioc_try_fmt_vid_out_mplane ||
> + ops->vidioc_try_fmt_vid_overlay ||
> + ops->vidioc_try_fmt_vbi_cap ||
> + ops->vidioc_try_fmt_vid_out_overlay ||
> + ops->vidioc_try_fmt_vbi_out ||
> + ops->vidioc_try_fmt_sliced_vbi_cap ||
> + ops->vidioc_try_fmt_sliced_vbi_out ||
> + ops->vidioc_try_fmt_type_private)
> + set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
> + SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
> + SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
> + SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
> + SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay);
> + SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf);
> + SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf);
> + SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
> + SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
> + if (vdev->tvnorms)
> + set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls);
> + if (ops->vidioc_g_std || vdev->current_norm)
> + set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std);
> + SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
> + SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
> + SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output);
> + SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output);
> + SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output);
> + /* Note: the control handler can also be passed through the filehandle,
> + and that can't be tested here. If the bit for these control ioctls
> + is set, then the ioctl is valid. But if it is 0, then it can still
> + be valid if the filehandle passed the control handler. */
> + if (vdev->ctrl_handler || ops->vidioc_queryctrl)
> + set_bit(_IOC_NR(VIDIOC_QUERYCTRL), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_G_CTRL), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_S_CTRL), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_g_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_G_EXT_CTRLS), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_s_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_S_EXT_CTRLS), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_try_ext_ctrls)
> + set_bit(_IOC_NR(VIDIOC_TRY_EXT_CTRLS), valid_ioctls);
> + if (vdev->ctrl_handler || ops->vidioc_querymenu)
> + set_bit(_IOC_NR(VIDIOC_QUERYMENU), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio);
> + SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio);
> + SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDOUT, vidioc_enumaudout);
> + SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout);
> + SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout);
> + SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator);
> + SET_VALID_IOCTL(ops, VIDIOC_S_MODULATOR, vidioc_s_modulator);
> + if (ops->vidioc_g_crop || ops->vidioc_g_selection)
> + set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls);
> + if (ops->vidioc_s_crop || ops->vidioc_s_selection)
> + set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection);
> + SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection);
> + if (ops->vidioc_cropcap || ops->vidioc_g_selection)
> + set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp);
> + SET_VALID_IOCTL(ops, VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp);
> + SET_VALID_IOCTL(ops, VIDIOC_G_ENC_INDEX, vidioc_g_enc_index);
> + SET_VALID_IOCTL(ops, VIDIOC_ENCODER_CMD, vidioc_encoder_cmd);
> + SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd);
> + SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd);
> + SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd);
> + if (ops->vidioc_g_parm || vdev->current_norm)
> + set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls);
> + SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm);
> + SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner);
> + SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner);
> + SET_VALID_IOCTL(ops, VIDIOC_G_FREQUENCY, vidioc_g_frequency);
> + SET_VALID_IOCTL(ops, VIDIOC_S_FREQUENCY, vidioc_s_frequency);
> + SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);
> + SET_VALID_IOCTL(ops, VIDIOC_LOG_STATUS, vidioc_log_status);
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> + SET_VALID_IOCTL(ops, VIDIOC_DBG_G_REGISTER, vidioc_g_register);
> + SET_VALID_IOCTL(ops, VIDIOC_DBG_S_REGISTER, vidioc_s_register);
> +#endif
> + SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident);
> + SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals);
> + SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets);
> + SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset);
> + SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset);
> + SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset);
> + SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings);
> + SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings);
> + /* yes, really vidioc_subscribe_event */
> + SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event);
> + SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event);
> + SET_VALID_IOCTL(ops, VIDIOC_UNSUBSCRIBE_EVENT, vidioc_unsubscribe_event);
> + SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs);
> + SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
> + bitmap_andnot(vdev->valid_ioctls, valid_ioctls, vdev->valid_ioctls,
> + BASE_VIDIOC_PRIVATE);
> +}
> +
> /**
> * __video_register_device - register video4linux devices
> * @vdev: video device structure we want to register
> @@ -663,6 +832,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
> vdev->index = get_index(vdev);
> mutex_unlock(&videodev_lock);
>
> + determine_valid_ioctls(vdev);
> +
> /* Part 3: Initialize the character device */
> vdev->cdev = cdev_alloc();
> if (vdev->cdev == NULL) {
> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> index 3f34098..21da16d 100644
> --- a/drivers/media/video/v4l2-ioctl.c
> +++ b/drivers/media/video/v4l2-ioctl.c
> @@ -55,19 +55,6 @@
> memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
> 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
>
> -#define have_fmt_ops(foo) ( \
> - ops->vidioc_##foo##_fmt_vid_cap || \
> - ops->vidioc_##foo##_fmt_vid_out || \
> - ops->vidioc_##foo##_fmt_vid_cap_mplane || \
> - ops->vidioc_##foo##_fmt_vid_out_mplane || \
> - ops->vidioc_##foo##_fmt_vid_overlay || \
> - ops->vidioc_##foo##_fmt_vbi_cap || \
> - ops->vidioc_##foo##_fmt_vid_out_overlay || \
> - ops->vidioc_##foo##_fmt_vbi_out || \
> - ops->vidioc_##foo##_fmt_sliced_vbi_cap || \
> - ops->vidioc_##foo##_fmt_sliced_vbi_out || \
> - ops->vidioc_##foo##_fmt_type_private)
> -
> struct std_descr {
> v4l2_std_id std;
> const char *descr;
> @@ -198,93 +185,98 @@ static const char *v4l2_memory_names[] = {
>
> struct v4l2_ioctl_info {
> unsigned int ioctl;
> + u16 flags;
> const char * const name;
> };
>
> -#define IOCTL_INFO(_ioctl) [_IOC_NR(_ioctl)] = { \
> - .ioctl = _ioctl, \
> - .name = #_ioctl, \
> +/* This control can be valid if the filehandle passes a control handler. */
> +#define INFO_FL_CTRL (1<< 1)
> +
> +#define IOCTL_INFO(_ioctl, _flags) [_IOC_NR(_ioctl)] = { \
> + .ioctl = _ioctl, \
> + .flags = _flags, \
> + .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),
> + IOCTL_INFO(VIDIOC_QUERYCAP, 0),
> + IOCTL_INFO(VIDIOC_ENUM_FMT, 0),
> + IOCTL_INFO(VIDIOC_G_FMT, 0),
> + IOCTL_INFO(VIDIOC_S_FMT, 0),
> + IOCTL_INFO(VIDIOC_REQBUFS, 0),
> + IOCTL_INFO(VIDIOC_QUERYBUF, 0),
> + IOCTL_INFO(VIDIOC_G_FBUF, 0),
> + IOCTL_INFO(VIDIOC_S_FBUF, 0),
> + IOCTL_INFO(VIDIOC_OVERLAY, 0),
> + IOCTL_INFO(VIDIOC_QBUF, 0),
> + IOCTL_INFO(VIDIOC_DQBUF, 0),
> + IOCTL_INFO(VIDIOC_STREAMON, 0),
> + IOCTL_INFO(VIDIOC_STREAMOFF, 0),
> + IOCTL_INFO(VIDIOC_G_PARM, 0),
> + IOCTL_INFO(VIDIOC_S_PARM, 0),
> + IOCTL_INFO(VIDIOC_G_STD, 0),
> + IOCTL_INFO(VIDIOC_S_STD, 0),
> + IOCTL_INFO(VIDIOC_ENUMSTD, 0),
> + IOCTL_INFO(VIDIOC_ENUMINPUT, 0),
> + IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL),
> + IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_CTRL),
> + IOCTL_INFO(VIDIOC_G_TUNER, 0),
> + IOCTL_INFO(VIDIOC_S_TUNER, 0),
> + IOCTL_INFO(VIDIOC_G_AUDIO, 0),
> + IOCTL_INFO(VIDIOC_S_AUDIO, 0),
> + IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL),
> + IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL),
> + IOCTL_INFO(VIDIOC_G_INPUT, 0),
> + IOCTL_INFO(VIDIOC_S_INPUT, 0),
> + IOCTL_INFO(VIDIOC_G_OUTPUT, 0),
> + IOCTL_INFO(VIDIOC_S_OUTPUT, 0),
> + IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0),
> + IOCTL_INFO(VIDIOC_G_AUDOUT, 0),
> + IOCTL_INFO(VIDIOC_S_AUDOUT, 0),
> + IOCTL_INFO(VIDIOC_G_MODULATOR, 0),
> + IOCTL_INFO(VIDIOC_S_MODULATOR, 0),
> + IOCTL_INFO(VIDIOC_G_FREQUENCY, 0),
> + IOCTL_INFO(VIDIOC_S_FREQUENCY, 0),
> + IOCTL_INFO(VIDIOC_CROPCAP, 0),
> + IOCTL_INFO(VIDIOC_G_CROP, 0),
> + IOCTL_INFO(VIDIOC_S_CROP, 0),
> + IOCTL_INFO(VIDIOC_G_SELECTION, 0),
> + IOCTL_INFO(VIDIOC_S_SELECTION, 0),
> + IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0),
> + IOCTL_INFO(VIDIOC_S_JPEGCOMP, 0),
> + IOCTL_INFO(VIDIOC_QUERYSTD, 0),
> + IOCTL_INFO(VIDIOC_TRY_FMT, 0),
> + IOCTL_INFO(VIDIOC_ENUMAUDIO, 0),
> + IOCTL_INFO(VIDIOC_ENUMAUDOUT, 0),
> + IOCTL_INFO(VIDIOC_G_PRIORITY, 0),
> + IOCTL_INFO(VIDIOC_S_PRIORITY, 0),
> + IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, 0),
> + IOCTL_INFO(VIDIOC_LOG_STATUS, 0),
> + IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL),
> + IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_CTRL),
> + IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0),
> + IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, 0),
> + IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, 0),
> + IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0),
> + IOCTL_INFO(VIDIOC_ENCODER_CMD, 0),
> + IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, 0),
> + IOCTL_INFO(VIDIOC_DECODER_CMD, 0),
> + IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0),
> + IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0),
> + IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0),
> + IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0),
> + IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, 0),
> + IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0),
> + IOCTL_INFO(VIDIOC_S_DV_PRESET, 0),
> + IOCTL_INFO(VIDIOC_G_DV_PRESET, 0),
> + IOCTL_INFO(VIDIOC_QUERY_DV_PRESET, 0),
> + IOCTL_INFO(VIDIOC_S_DV_TIMINGS, 0),
> + IOCTL_INFO(VIDIOC_G_DV_TIMINGS, 0),
> + IOCTL_INFO(VIDIOC_DQEVENT, 0),
> + IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0),
> + IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0),
> + IOCTL_INFO(VIDIOC_CREATE_BUFS, 0),
> + IOCTL_INFO(VIDIOC_PREPARE_BUF, 0),
> };
> #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
>
> @@ -526,19 +518,28 @@ static long __video_do_ioctl(struct file *file,
> return ret;
> }
>
> - if ((vfd->debug& V4L2_DEBUG_IOCTL)&&
> - !(vfd->debug& V4L2_DEBUG_IOCTL_ARG)) {
> - v4l_print_ioctl(vfd->name, cmd);
> - printk(KERN_CONT "\n");
> - }
> -
> if (test_bit(V4L2_FL_USES_V4L2_FH,&vfd->flags)) {
> vfh = file->private_data;
> use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO,&vfd->flags);
> + if (use_fh_prio)
> + ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
> }
>
> - if (use_fh_prio)
> - ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
> + if (v4l2_is_valid_ioctl(cmd)) {
I would prefer for this check to be the first check in the function
in the form of:
if (!v4l2_is_valid_ioctl(cmd))
return -ENOTTY;
This will drop an indentation level from the code below and also drop an
indentation level from the prio check introduced in a later patch,
making the end result much more readable IMHO.
> + struct v4l2_ioctl_info *info =&v4l2_ioctls[_IOC_NR(cmd)];
> +
> + if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls)) {
> + if (!(info->flags& INFO_FL_CTRL) ||
> + !(vfh&& vfh->ctrl_handler))
> + return -ENOTTY;
> + }
> + }
Sort of hard to read, IMHO the below is easier to parse by us humans:
if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) &&
!((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
return -ENOTTY;
Note lots of more patch below, on which I've no further comments.
Regards,
Hans
> +
> + if ((vfd->debug& V4L2_DEBUG_IOCTL)&&
> + !(vfd->debug& V4L2_DEBUG_IOCTL_ARG)) {
> + v4l_print_ioctl(vfd->name, cmd);
> + printk(KERN_CONT "\n");
> + }
>
> switch (cmd) {
>
> @@ -547,9 +548,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_capability *cap = (struct v4l2_capability *)arg;
>
> - if (!ops->vidioc_querycap)
> - break;
> -
> cap->version = LINUX_VERSION_CODE;
> ret = ops->vidioc_querycap(file, fh, cap);
> if (!ret)
> @@ -600,6 +598,7 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_fmtdesc *f = arg;
>
> + ret = -EINVAL;
> switch (f->type) {
> case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> if (likely(ops->vidioc_enum_fmt_vid_cap))
> @@ -632,7 +631,7 @@ static long __video_do_ioctl(struct file *file,
> default:
> break;
> }
> - if (likely (!ret))
> + if (likely(!ret))
> dbgarg(cmd, "index=%d, type=%d, flags=%d, "
> "pixelformat=%c%c%c%c, description='%s'\n",
> f->index, f->type, f->flags,
> @@ -641,14 +640,6 @@ static long __video_do_ioctl(struct file *file,
> (f->pixelformat>> 16)& 0xff,
> (f->pixelformat>> 24)& 0xff,
> f->description);
> - else if (ret == -ENOTTY&&
> - (ops->vidioc_enum_fmt_vid_cap ||
> - ops->vidioc_enum_fmt_vid_out ||
> - ops->vidioc_enum_fmt_vid_cap_mplane ||
> - ops->vidioc_enum_fmt_vid_out_mplane ||
> - ops->vidioc_enum_fmt_vid_overlay ||
> - ops->vidioc_enum_fmt_type_private))
> - ret = -EINVAL;
> break;
> }
> case VIDIOC_G_FMT:
> @@ -658,6 +649,7 @@ static long __video_do_ioctl(struct file *file,
> /* FIXME: Should be one dump per type */
> dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
>
> + ret = -EINVAL;
> switch (f->type) {
> case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> if (ops->vidioc_g_fmt_vid_cap)
> @@ -719,17 +711,12 @@ static long __video_do_ioctl(struct file *file,
> fh, f);
> break;
> }
> - if (unlikely(ret == -ENOTTY&& have_fmt_ops(g)))
> - ret = -EINVAL;
> -
> break;
> }
> case VIDIOC_S_FMT:
> {
> struct v4l2_format *f = (struct v4l2_format *)arg;
>
> - if (!have_fmt_ops(s))
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -817,6 +804,7 @@ static long __video_do_ioctl(struct file *file,
> /* FIXME: Should be one dump per type */
> dbgarg(cmd, "type=%s\n", prt_names(f->type,
> v4l2_type_names));
> + ret = -EINVAL;
> switch (f->type) {
> case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> CLEAR_AFTER_FIELD(f, fmt.pix);
> @@ -889,8 +877,6 @@ static long __video_do_ioctl(struct file *file,
> fh, f);
> break;
> }
> - if (unlikely(ret == -ENOTTY&& have_fmt_ops(try)))
> - ret = -EINVAL;
> break;
> }
> /* FIXME: Those buf reqs could be handled here,
> @@ -901,8 +887,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_requestbuffers *p = arg;
>
> - if (!ops->vidioc_reqbufs)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -925,8 +909,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_buffer *p = arg;
>
> - if (!ops->vidioc_querybuf)
> - break;
> ret = check_fmt(ops, p->type);
> if (ret)
> break;
> @@ -940,8 +922,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_buffer *p = arg;
>
> - if (!ops->vidioc_qbuf)
> - break;
> ret = check_fmt(ops, p->type);
> if (ret)
> break;
> @@ -955,8 +935,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_buffer *p = arg;
>
> - if (!ops->vidioc_dqbuf)
> - break;
> ret = check_fmt(ops, p->type);
> if (ret)
> break;
> @@ -970,8 +948,6 @@ static long __video_do_ioctl(struct file *file,
> {
> int *i = arg;
>
> - if (!ops->vidioc_overlay)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -984,8 +960,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_framebuffer *p = arg;
>
> - if (!ops->vidioc_g_fbuf)
> - break;
> ret = ops->vidioc_g_fbuf(file, fh, arg);
> if (!ret) {
> dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
> @@ -999,8 +973,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_framebuffer *p = arg;
>
> - if (!ops->vidioc_s_fbuf)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1015,8 +987,6 @@ static long __video_do_ioctl(struct file *file,
> {
> enum v4l2_buf_type i = *(int *)arg;
>
> - if (!ops->vidioc_streamon)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1029,8 +999,6 @@ static long __video_do_ioctl(struct file *file,
> {
> enum v4l2_buf_type i = *(int *)arg;
>
> - if (!ops->vidioc_streamoff)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1104,9 +1072,6 @@ static long __video_do_ioctl(struct file *file,
>
> dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
>
> - if (!ops->vidioc_s_std)
> - break;
> -
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1128,8 +1093,6 @@ static long __video_do_ioctl(struct file *file,
> {
> v4l2_std_id *p = arg;
>
> - if (!ops->vidioc_querystd)
> - break;
> /*
> * If nothing detected, it should return all supported
> * Drivers just need to mask the std argument, in order
> @@ -1163,9 +1126,6 @@ static long __video_do_ioctl(struct file *file,
> if (ops->vidioc_s_dv_timings)
> p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
>
> - if (!ops->vidioc_enum_input)
> - break;
> -
> ret = ops->vidioc_enum_input(file, fh, p);
> if (!ret)
> dbgarg(cmd, "index=%d, name=%s, type=%d, "
> @@ -1181,8 +1141,6 @@ static long __video_do_ioctl(struct file *file,
> {
> unsigned int *i = arg;
>
> - if (!ops->vidioc_g_input)
> - break;
> ret = ops->vidioc_g_input(file, fh, i);
> if (!ret)
> dbgarg(cmd, "value=%d\n", *i);
> @@ -1192,8 +1150,6 @@ static long __video_do_ioctl(struct file *file,
> {
> unsigned int *i = arg;
>
> - if (!ops->vidioc_s_input)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1208,9 +1164,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_output *p = arg;
>
> - if (!ops->vidioc_enum_output)
> - break;
> -
> /*
> * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS&
> * CAP_STD here based on ioctl handler provided by the
> @@ -1237,8 +1190,6 @@ static long __video_do_ioctl(struct file *file,
> {
> unsigned int *i = arg;
>
> - if (!ops->vidioc_g_output)
> - break;
> ret = ops->vidioc_g_output(file, fh, i);
> if (!ret)
> dbgarg(cmd, "value=%d\n", *i);
> @@ -1248,8 +1199,6 @@ static long __video_do_ioctl(struct file *file,
> {
> unsigned int *i = arg;
>
> - if (!ops->vidioc_s_output)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1441,8 +1390,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_audio *p = arg;
>
> - if (!ops->vidioc_enumaudio)
> - break;
> ret = ops->vidioc_enumaudio(file, fh, p);
> if (!ret)
> dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
> @@ -1456,9 +1403,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_audio *p = arg;
>
> - if (!ops->vidioc_g_audio)
> - break;
> -
> ret = ops->vidioc_g_audio(file, fh, p);
> if (!ret)
> dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
> @@ -1472,8 +1416,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_audio *p = arg;
>
> - if (!ops->vidioc_s_audio)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1488,8 +1430,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_audioout *p = arg;
>
> - if (!ops->vidioc_enumaudout)
> - break;
> dbgarg(cmd, "Enum for index=%d\n", p->index);
> ret = ops->vidioc_enumaudout(file, fh, p);
> if (!ret)
> @@ -1502,9 +1442,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_audioout *p = arg;
>
> - if (!ops->vidioc_g_audout)
> - break;
> -
> ret = ops->vidioc_g_audout(file, fh, p);
> if (!ret)
> dbgarg2("index=%d, name=%s, capability=%d, "
> @@ -1516,8 +1453,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_audioout *p = arg;
>
> - if (!ops->vidioc_s_audout)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1533,8 +1468,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_modulator *p = arg;
>
> - if (!ops->vidioc_g_modulator)
> - break;
> ret = ops->vidioc_g_modulator(file, fh, p);
> if (!ret)
> dbgarg(cmd, "index=%d, name=%s, "
> @@ -1549,8 +1482,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_modulator *p = arg;
>
> - if (!ops->vidioc_s_modulator)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1566,9 +1497,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_crop *p = arg;
>
> - if (!ops->vidioc_g_crop&& !ops->vidioc_g_selection)
> - break;
> -
> dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
>
> if (ops->vidioc_g_crop) {
> @@ -1600,9 +1528,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_crop *p = arg;
>
> - if (!ops->vidioc_s_crop&& !ops->vidioc_s_selection)
> - break;
> -
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1633,9 +1558,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_selection *p = arg;
>
> - if (!ops->vidioc_g_selection)
> - break;
> -
> dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
>
> ret = ops->vidioc_g_selection(file, fh, p);
> @@ -1647,9 +1569,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_selection *p = arg;
>
> - if (!ops->vidioc_s_selection)
> - break;
> -
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1666,9 +1585,6 @@ static long __video_do_ioctl(struct file *file,
> struct v4l2_cropcap *p = arg;
>
> /*FIXME: Should also show v4l2_fract pixelaspect */
> - if (!ops->vidioc_cropcap&& !ops->vidioc_g_selection)
> - break;
> -
> dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
> if (ops->vidioc_cropcap) {
> ret = ops->vidioc_cropcap(file, fh, p);
> @@ -1712,9 +1628,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_jpegcompression *p = arg;
>
> - if (!ops->vidioc_g_jpegcomp)
> - break;
> -
> ret = ops->vidioc_g_jpegcomp(file, fh, p);
> if (!ret)
> dbgarg(cmd, "quality=%d, APPn=%d, "
> @@ -1728,8 +1641,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_jpegcompression *p = arg;
>
> - if (!ops->vidioc_g_jpegcomp)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1745,8 +1656,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_enc_idx *p = arg;
>
> - if (!ops->vidioc_g_enc_index)
> - break;
> ret = ops->vidioc_g_enc_index(file, fh, p);
> if (!ret)
> dbgarg(cmd, "entries=%d, entries_cap=%d\n",
> @@ -1757,8 +1666,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_encoder_cmd *p = arg;
>
> - if (!ops->vidioc_encoder_cmd)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1772,8 +1679,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_encoder_cmd *p = arg;
>
> - if (!ops->vidioc_try_encoder_cmd)
> - break;
> ret = ops->vidioc_try_encoder_cmd(file, fh, p);
> if (!ret)
> dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
> @@ -1783,8 +1688,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_decoder_cmd *p = arg;
>
> - if (!ops->vidioc_decoder_cmd)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1798,8 +1701,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_decoder_cmd *p = arg;
>
> - if (!ops->vidioc_try_decoder_cmd)
> - break;
> ret = ops->vidioc_try_decoder_cmd(file, fh, p);
> if (!ret)
> dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
> @@ -1809,8 +1710,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_streamparm *p = arg;
>
> - if (!ops->vidioc_g_parm&& !vfd->current_norm)
> - break;
> if (ops->vidioc_g_parm) {
> ret = check_fmt(ops, p->type);
> if (ret)
> @@ -1838,8 +1737,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_streamparm *p = arg;
>
> - if (!ops->vidioc_s_parm)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1856,9 +1753,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_tuner *p = arg;
>
> - if (!ops->vidioc_g_tuner)
> - break;
> -
> p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> ret = ops->vidioc_g_tuner(file, fh, p);
> @@ -1877,8 +1771,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_tuner *p = arg;
>
> - if (!ops->vidioc_s_tuner)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1900,9 +1792,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_frequency *p = arg;
>
> - if (!ops->vidioc_g_frequency)
> - break;
> -
> p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> ret = ops->vidioc_g_frequency(file, fh, p);
> @@ -1916,8 +1805,6 @@ static long __video_do_ioctl(struct file *file,
> struct v4l2_frequency *p = arg;
> enum v4l2_tuner_type type;
>
> - if (!ops->vidioc_s_frequency)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -1936,9 +1823,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_sliced_vbi_cap *p = arg;
>
> - if (!ops->vidioc_g_sliced_vbi_cap)
> - break;
> -
> /* Clear up to type, everything after type is zerod already */
> memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
>
> @@ -1950,8 +1834,6 @@ static long __video_do_ioctl(struct file *file,
> }
> case VIDIOC_LOG_STATUS:
> {
> - if (!ops->vidioc_log_status)
> - break;
> if (vfd->v4l2_dev)
> pr_info("%s: ================= START STATUS =================\n",
> vfd->v4l2_dev->name);
> @@ -1966,12 +1848,10 @@ static long __video_do_ioctl(struct file *file,
> #ifdef CONFIG_VIDEO_ADV_DEBUG
> struct v4l2_dbg_register *p = arg;
>
> - if (ops->vidioc_g_register) {
> - if (!capable(CAP_SYS_ADMIN))
> - ret = -EPERM;
> - else
> - ret = ops->vidioc_g_register(file, fh, p);
> - }
> + if (!capable(CAP_SYS_ADMIN))
> + ret = -EPERM;
> + else
> + ret = ops->vidioc_g_register(file, fh, p);
> #endif
> break;
> }
> @@ -1980,12 +1860,10 @@ static long __video_do_ioctl(struct file *file,
> #ifdef CONFIG_VIDEO_ADV_DEBUG
> struct v4l2_dbg_register *p = arg;
>
> - if (ops->vidioc_s_register) {
> - if (!capable(CAP_SYS_ADMIN))
> - ret = -EPERM;
> - else
> - ret = ops->vidioc_s_register(file, fh, p);
> - }
> + if (!capable(CAP_SYS_ADMIN))
> + ret = -EPERM;
> + else
> + ret = ops->vidioc_s_register(file, fh, p);
> #endif
> break;
> }
> @@ -1993,8 +1871,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_dbg_chip_ident *p = arg;
>
> - if (!ops->vidioc_g_chip_ident)
> - break;
> p->ident = V4L2_IDENT_NONE;
> p->revision = 0;
> ret = ops->vidioc_g_chip_ident(file, fh, p);
> @@ -2007,8 +1883,6 @@ static long __video_do_ioctl(struct file *file,
> struct v4l2_hw_freq_seek *p = arg;
> enum v4l2_tuner_type type;
>
> - if (!ops->vidioc_s_hw_freq_seek)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -2028,9 +1902,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_frmsizeenum *p = arg;
>
> - if (!ops->vidioc_enum_framesizes)
> - break;
> -
> ret = ops->vidioc_enum_framesizes(file, fh, p);
> dbgarg(cmd,
> "index=%d, pixelformat=%c%c%c%c, type=%d ",
> @@ -2064,9 +1935,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_frmivalenum *p = arg;
>
> - if (!ops->vidioc_enum_frameintervals)
> - break;
> -
> ret = ops->vidioc_enum_frameintervals(file, fh, p);
> dbgarg(cmd,
> "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
> @@ -2099,9 +1967,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_dv_enum_preset *p = arg;
>
> - if (!ops->vidioc_enum_dv_presets)
> - break;
> -
> ret = ops->vidioc_enum_dv_presets(file, fh, p);
> if (!ret)
> dbgarg(cmd,
> @@ -2115,8 +1980,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_dv_preset *p = arg;
>
> - if (!ops->vidioc_s_dv_preset)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -2130,9 +1993,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_dv_preset *p = arg;
>
> - if (!ops->vidioc_g_dv_preset)
> - break;
> -
> ret = ops->vidioc_g_dv_preset(file, fh, p);
> if (!ret)
> dbgarg(cmd, "preset=%d\n", p->preset);
> @@ -2142,9 +2002,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_dv_preset *p = arg;
>
> - if (!ops->vidioc_query_dv_preset)
> - break;
> -
> ret = ops->vidioc_query_dv_preset(file, fh, p);
> if (!ret)
> dbgarg(cmd, "preset=%d\n", p->preset);
> @@ -2154,8 +2011,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_dv_timings *p = arg;
>
> - if (!ops->vidioc_s_dv_timings)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -2188,9 +2043,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_dv_timings *p = arg;
>
> - if (!ops->vidioc_g_dv_timings)
> - break;
> -
> ret = ops->vidioc_g_dv_timings(file, fh, p);
> if (!ret) {
> switch (p->type) {
> @@ -2222,9 +2074,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_event *ev = arg;
>
> - if (!ops->vidioc_subscribe_event)
> - break;
> -
> ret = v4l2_event_dequeue(fh, ev, file->f_flags& O_NONBLOCK);
> if (ret< 0) {
> dbgarg(cmd, "no pending events?");
> @@ -2241,9 +2090,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_event_subscription *sub = arg;
>
> - if (!ops->vidioc_subscribe_event)
> - break;
> -
> ret = ops->vidioc_subscribe_event(fh, sub);
> if (ret< 0) {
> dbgarg(cmd, "failed, ret=%ld", ret);
> @@ -2256,9 +2102,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_event_subscription *sub = arg;
>
> - if (!ops->vidioc_unsubscribe_event)
> - break;
> -
> ret = ops->vidioc_unsubscribe_event(fh, sub);
> if (ret< 0) {
> dbgarg(cmd, "failed, ret=%ld", ret);
> @@ -2271,8 +2114,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_create_buffers *create = arg;
>
> - if (!ops->vidioc_create_bufs)
> - break;
> if (ret_prio) {
> ret = ret_prio;
> break;
> @@ -2290,8 +2131,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_buffer *b = arg;
>
> - if (!ops->vidioc_prepare_buf)
> - break;
> ret = check_fmt(ops, b->type);
> if (ret)
> break;
> diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
> index 0da84dc..15e2fe4 100644
> --- a/include/media/v4l2-dev.h
> +++ b/include/media/v4l2-dev.h
> @@ -126,6 +126,7 @@ struct video_device
>
> /* ioctl callbacks */
> const struct v4l2_ioctl_ops *ioctl_ops;
> + DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
>
> /* serialization lock */
> DECLARE_BITMAP(dont_use_lock, BASE_VIDIOC_PRIVATE);
> @@ -184,6 +185,16 @@ static inline void v4l2_dont_use_lock(struct video_device *vdev, unsigned int cm
> set_bit(_IOC_NR(cmd), vdev->dont_use_lock);
> }
>
> +/* Mark that this command isn't implemented, must be called before
> + video_device_register. See also the comments in determine_valid_ioctls().
> + This function allows drivers to provide just one v4l2_ioctl_ops struct, but
> + disable ioctls based on the specific card that is actually found. */
> +static inline void v4l2_dont_use_cmd(struct video_device *vdev, unsigned int cmd)
> +{
> + if (_IOC_NR(cmd)< BASE_VIDIOC_PRIVATE)
> + set_bit(_IOC_NR(cmd), vdev->valid_ioctls);
> +}
> +
> /* helper functions to access driver private data. */
> static inline void *video_get_drvdata(struct video_device *vdev)
> {
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront.
2012-05-10 8:10 ` Hans de Goede
@ 2012-05-10 8:21 ` Hans de Goede
2012-05-10 8:27 ` Hans Verkuil
1 sibling, 0 replies; 20+ messages in thread
From: Hans de Goede @ 2012-05-10 8:21 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Mauro Carvalho Chehab, Hans Verkuil
Hi,
On 05/10/2012 10:10 AM, Hans de Goede wrote:
<snip>
>> @@ -526,19 +518,28 @@ static long __video_do_ioctl(struct file *file,
>> return ret;
>> }
>>
>> - if ((vfd->debug& V4L2_DEBUG_IOCTL)&&
>> - !(vfd->debug& V4L2_DEBUG_IOCTL_ARG)) {
>> - v4l_print_ioctl(vfd->name, cmd);
>> - printk(KERN_CONT "\n");
>> - }
>> -
>> if (test_bit(V4L2_FL_USES_V4L2_FH,&vfd->flags)) {
>> vfh = file->private_data;
>> use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO,&vfd->flags);
>> + if (use_fh_prio)
>> + ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
>> }
>>
>> - if (use_fh_prio)
>> - ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
>> + if (v4l2_is_valid_ioctl(cmd)) {
>
> I would prefer for this check to be the first check in the function
> in the form of:
>
> if (!v4l2_is_valid_ioctl(cmd))
> return -ENOTTY;
>
Oops, sorry we cannot do that because the drv my have its own
custom ioctls handled by the default case <sigh>, so scrap this.
> This will drop an indentation level from the code below and also drop an
> indentation level from the prio check introduced in a later patch,
> making the end result much more readable IMHO.
>
>> + struct v4l2_ioctl_info *info =&v4l2_ioctls[_IOC_NR(cmd)];
>> +
>> + if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls)) {
>> + if (!(info->flags& INFO_FL_CTRL) ||
>> + !(vfh&& vfh->ctrl_handler))
>> + return -ENOTTY;
> > + }
> > + }
>
I still think the above can be simplified a bit, in the form of:
if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) &&
!((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
return -ENOTYY;
Regards,
Hans
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront.
2012-05-10 8:10 ` Hans de Goede
2012-05-10 8:21 ` Hans de Goede
@ 2012-05-10 8:27 ` Hans Verkuil
1 sibling, 0 replies; 20+ messages in thread
From: Hans Verkuil @ 2012-05-10 8:27 UTC (permalink / raw)
To: Hans de Goede; +Cc: linux-media, Mauro Carvalho Chehab, Hans Verkuil
On Thu 10 May 2012 10:10:21 Hans de Goede wrote:
> Hi,
>
> Comments inline.
>
> On 05/10/2012 09:05 AM, Hans Verkuil wrote:
> > From: Hans Verkuil<hans.verkuil@cisco.com>
> >
> > Rather than testing whether an ioctl is implemented in the driver or not
> > every time the ioctl is called, do it upfront when the device is registered.
> >
> > This also allows a driver to disable certain ioctls based on the capabilities
> > of the detected board, something you can't do today without creating separate
> > v4l2_ioctl_ops structs for each new variation.
> >
> > For the most part it is pretty straightforward, but for control ioctls a flag
> > is needed since it is possible that you have per-filehandle controls, and that
> > can't be determined upfront of course.
> >
> > Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>
> > ---
> > drivers/media/video/v4l2-dev.c | 171 +++++++++++++++++
> > drivers/media/video/v4l2-ioctl.c | 391 +++++++++++---------------------------
> > include/media/v4l2-dev.h | 11 ++
> > 3 files changed, 297 insertions(+), 276 deletions(-)
> >
...
> > diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> > index 3f34098..21da16d 100644
> > --- a/drivers/media/video/v4l2-ioctl.c
> > +++ b/drivers/media/video/v4l2-ioctl.c
> > @@ -526,19 +518,28 @@ static long __video_do_ioctl(struct file *file,
> > return ret;
> > }
> >
> > - if ((vfd->debug& V4L2_DEBUG_IOCTL)&&
> > - !(vfd->debug& V4L2_DEBUG_IOCTL_ARG)) {
> > - v4l_print_ioctl(vfd->name, cmd);
> > - printk(KERN_CONT "\n");
> > - }
> > -
> > if (test_bit(V4L2_FL_USES_V4L2_FH,&vfd->flags)) {
> > vfh = file->private_data;
> > use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO,&vfd->flags);
> > + if (use_fh_prio)
> > + ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
> > }
> >
> > - if (use_fh_prio)
> > - ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
> > + if (v4l2_is_valid_ioctl(cmd)) {
>
> I would prefer for this check to be the first check in the function
> in the form of:
>
> if (!v4l2_is_valid_ioctl(cmd))
> return -ENOTTY;
>
> This will drop an indentation level from the code below and also drop an
> indentation level from the prio check introduced in a later patch,
> making the end result much more readable IMHO.
Ah, no. That's why I renamed v4l2_is_valid_ioctl to v4l2_is_known_ioctl in my
new ioctlv2 branch. v4l2_is_known_ioctl means whether it is a known, standard
v4l2 ioctl. If it is, then it is handled by the table, if it isn't, then it
will be handled by the vidioc_default callback.
I realized myself that that name was very ambiguous.
>
> > + struct v4l2_ioctl_info *info =&v4l2_ioctls[_IOC_NR(cmd)];
> > +
> > + if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls)) {
> > + if (!(info->flags& INFO_FL_CTRL) ||
> > + !(vfh&& vfh->ctrl_handler))
> > + return -ENOTTY;
> > + }
> > + }
>
> Sort of hard to read, IMHO the below is easier to parse by us humans:
>
> if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) &&
> !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
> return -ENOTTY;
Yeah, I agree. That's better.
Regards,
Hans
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront.
2012-05-10 7:05 ` [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront Hans Verkuil
2012-05-10 8:06 ` Hans Verkuil
2012-05-10 8:10 ` Hans de Goede
@ 2012-05-14 13:00 ` Laurent Pinchart
2012-05-14 13:51 ` Hans Verkuil
2 siblings, 1 reply; 20+ messages in thread
From: Laurent Pinchart @ 2012-05-14 13:00 UTC (permalink / raw)
To: Hans Verkuil
Cc: linux-media, Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
Hi Hans,
Thanks for the patch.
On Thursday 10 May 2012 09:05:11 Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> Rather than testing whether an ioctl is implemented in the driver or not
> every time the ioctl is called, do it upfront when the device is registered.
>
> This also allows a driver to disable certain ioctls based on the
> capabilities of the detected board, something you can't do today without
> creating separate v4l2_ioctl_ops structs for each new variation.
>
> For the most part it is pretty straightforward, but for control ioctls a
> flag is needed since it is possible that you have per-filehandle controls,
> and that can't be determined upfront of course.
>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> ---
> drivers/media/video/v4l2-dev.c | 171 +++++++++++++++++
> drivers/media/video/v4l2-ioctl.c | 391 ++++++++++-------------------------
> include/media/v4l2-dev.h | 11 ++
> 3 files changed, 297 insertions(+), 276 deletions(-)
>
> diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
> index a51a061..4d98ee1 100644
> --- a/drivers/media/video/v4l2-dev.c
> +++ b/drivers/media/video/v4l2-dev.c
> @@ -516,6 +516,175 @@ static int get_index(struct video_device *vdev)
> return find_first_zero_bit(used, VIDEO_NUM_DEVICES);
> }
>
> +#define SET_VALID_IOCTL(ops, cmd, op) \
> + if (ops->op) \
> + set_bit(_IOC_NR(cmd), valid_ioctls)
> +
> +/* This determines which ioctls are actually implemented in the driver.
> + It's a one-time thing which simplifies video_ioctl2 as it can just do
> + a bit test.
> +
> + Note that drivers can override this by setting bits to 1 in
> + vdev->valid_ioctls. If an ioctl is marked as 1 when this function is
> + called, then that ioctl will actually be marked as unimplemented.
> +
> + It does that by first setting up the local valid_ioctls bitmap, and
> + at the end do a:
> +
> + vdev->valid_ioctls = valid_ioctls & ~(vdev->valid_ioctls)
Wouldn't it be more logical to initialize valid_ioctls to all 1s and clear
bits in v4l2_dont_use_cmd() ? Otherwise the meaning of the field changes
depending on whether the device is registered or not.
Another bikeshedding comment, what about renaming v4l2_dont_use_cmd() with
something that includes ioctl in the name ?
- v4l2_dont_use_ioctl
- v4l2_dont_use_ioctl_cmd
- v4l2_ioctl_cmd_not_used
- v4l2_ioctl_dont_use
- v4l2_ioctl_dont_use_cmd
- v4l2_disable_ioctl
- v4l2_disable_ioctl_cmd
...
(I like "disable" slightly better than "don't use").
> + */
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront.
2012-05-14 13:00 ` Laurent Pinchart
@ 2012-05-14 13:51 ` Hans Verkuil
2012-05-14 14:10 ` Laurent Pinchart
0 siblings, 1 reply; 20+ messages in thread
From: Hans Verkuil @ 2012-05-14 13:51 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
On Mon May 14 2012 15:00:05 Laurent Pinchart wrote:
> Hi Hans,
>
> Thanks for the patch.
>
> On Thursday 10 May 2012 09:05:11 Hans Verkuil wrote:
> > From: Hans Verkuil <hans.verkuil@cisco.com>
> >
> > Rather than testing whether an ioctl is implemented in the driver or not
> > every time the ioctl is called, do it upfront when the device is registered.
> >
> > This also allows a driver to disable certain ioctls based on the
> > capabilities of the detected board, something you can't do today without
> > creating separate v4l2_ioctl_ops structs for each new variation.
> >
> > For the most part it is pretty straightforward, but for control ioctls a
> > flag is needed since it is possible that you have per-filehandle controls,
> > and that can't be determined upfront of course.
> >
> > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > ---
> > drivers/media/video/v4l2-dev.c | 171 +++++++++++++++++
> > drivers/media/video/v4l2-ioctl.c | 391 ++++++++++-------------------------
> > include/media/v4l2-dev.h | 11 ++
> > 3 files changed, 297 insertions(+), 276 deletions(-)
> >
> > diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
> > index a51a061..4d98ee1 100644
> > --- a/drivers/media/video/v4l2-dev.c
> > +++ b/drivers/media/video/v4l2-dev.c
> > @@ -516,6 +516,175 @@ static int get_index(struct video_device *vdev)
> > return find_first_zero_bit(used, VIDEO_NUM_DEVICES);
> > }
> >
> > +#define SET_VALID_IOCTL(ops, cmd, op) \
> > + if (ops->op) \
> > + set_bit(_IOC_NR(cmd), valid_ioctls)
> > +
> > +/* This determines which ioctls are actually implemented in the driver.
> > + It's a one-time thing which simplifies video_ioctl2 as it can just do
> > + a bit test.
> > +
> > + Note that drivers can override this by setting bits to 1 in
> > + vdev->valid_ioctls. If an ioctl is marked as 1 when this function is
> > + called, then that ioctl will actually be marked as unimplemented.
> > +
> > + It does that by first setting up the local valid_ioctls bitmap, and
> > + at the end do a:
> > +
> > + vdev->valid_ioctls = valid_ioctls & ~(vdev->valid_ioctls)
>
> Wouldn't it be more logical to initialize valid_ioctls to all 1s and clear
> bits in v4l2_dont_use_cmd() ? Otherwise the meaning of the field changes
> depending on whether the device is registered or not.
The reason is that drivers initialize struct video_device to 0. There is also
no initialization function that can set it to all 1. So then you would have to
modify all drivers, and that's way overkill.
If you have a better suggestion, then I'm all ears!
>
> Another bikeshedding comment, what about renaming v4l2_dont_use_cmd() with
> something that includes ioctl in the name ?
>
> - v4l2_dont_use_ioctl
> - v4l2_dont_use_ioctl_cmd
> - v4l2_ioctl_cmd_not_used
> - v4l2_ioctl_dont_use
> - v4l2_ioctl_dont_use_cmd
> - v4l2_disable_ioctl
> - v4l2_disable_ioctl_cmd
How about:
v4l2_is_known_ioctl -> v4l2_is_known_ioctl_cmd
v4l2_dont_use_lock -> v4l2_disable_ioctl_cmd_locking
v4l2_dont_use_cmd -> v4l2_disable_ioctl_cmd
or:
v4l2_ioctl_cmd_is_known
v4l2_ioctl_cmd_disable_locking
v4l2_ioctl_cmd_disable
The last set looks better but sounds worse :-)
Regards,
Hans
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront.
2012-05-14 13:51 ` Hans Verkuil
@ 2012-05-14 14:10 ` Laurent Pinchart
0 siblings, 0 replies; 20+ messages in thread
From: Laurent Pinchart @ 2012-05-14 14:10 UTC (permalink / raw)
To: Hans Verkuil
Cc: linux-media, Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
Hi Hans,
On Monday 14 May 2012 15:51:27 Hans Verkuil wrote:
> On Mon May 14 2012 15:00:05 Laurent Pinchart wrote:
> > On Thursday 10 May 2012 09:05:11 Hans Verkuil wrote:
> > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > >
> > > Rather than testing whether an ioctl is implemented in the driver or not
> > > every time the ioctl is called, do it upfront when the device is
> > > registered.
> > >
> > > This also allows a driver to disable certain ioctls based on the
> > > capabilities of the detected board, something you can't do today without
> > > creating separate v4l2_ioctl_ops structs for each new variation.
> > >
> > > For the most part it is pretty straightforward, but for control ioctls a
> > > flag is needed since it is possible that you have per-filehandle
> > > controls, and that can't be determined upfront of course.
> > >
> > > Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> > > ---
> > >
> > > drivers/media/video/v4l2-dev.c | 171 +++++++++++++++++
> > > drivers/media/video/v4l2-ioctl.c | 391
> > > ++++++++++-------------------------
> > > include/media/v4l2-dev.h | 11 ++
> > > 3 files changed, 297 insertions(+), 276 deletions(-)
> > >
> > > diff --git a/drivers/media/video/v4l2-dev.c
> > > b/drivers/media/video/v4l2-dev.c index a51a061..4d98ee1 100644
> > > --- a/drivers/media/video/v4l2-dev.c
> > > +++ b/drivers/media/video/v4l2-dev.c
> > > @@ -516,6 +516,175 @@ static int get_index(struct video_device *vdev)
> > >
> > > return find_first_zero_bit(used, VIDEO_NUM_DEVICES);
> > >
> > > }
> > >
> > > +#define SET_VALID_IOCTL(ops, cmd, op) \
> > > + if (ops->op) \
> > > + set_bit(_IOC_NR(cmd), valid_ioctls)
> > > +
> > > +/* This determines which ioctls are actually implemented in the driver.
> > > + It's a one-time thing which simplifies video_ioctl2 as it can just
> > > do
> > > + a bit test.
> > > +
> > > + Note that drivers can override this by setting bits to 1 in
> > > + vdev->valid_ioctls. If an ioctl is marked as 1 when this function is
> > > + called, then that ioctl will actually be marked as unimplemented.
> > > +
> > > + It does that by first setting up the local valid_ioctls bitmap, and
> > > + at the end do a:
> > > +
> > > + vdev->valid_ioctls = valid_ioctls & ~(vdev->valid_ioctls)
> >
> > Wouldn't it be more logical to initialize valid_ioctls to all 1s and clear
> > bits in v4l2_dont_use_cmd() ? Otherwise the meaning of the field changes
> > depending on whether the device is registered or not.
>
> The reason is that drivers initialize struct video_device to 0. There is
> also no initialization function that can set it to all 1. So then you would
> have to modify all drivers, and that's way overkill.
>
> If you have a better suggestion, then I'm all ears!
Right, that's a problem. One possible solution would be to rename valid_ioctls
to invalid_ioctls (and obviously update the code accordingly).
> > Another bikeshedding comment, what about renaming v4l2_dont_use_cmd() with
> > something that includes ioctl in the name ?
> >
> > - v4l2_dont_use_ioctl
> > - v4l2_dont_use_ioctl_cmd
> > - v4l2_ioctl_cmd_not_used
> > - v4l2_ioctl_dont_use
> > - v4l2_ioctl_dont_use_cmd
> > - v4l2_disable_ioctl
> > - v4l2_disable_ioctl_cmd
>
> How about:
>
> v4l2_is_known_ioctl -> v4l2_is_known_ioctl_cmd
> v4l2_dont_use_lock -> v4l2_disable_ioctl_cmd_locking
> v4l2_dont_use_cmd -> v4l2_disable_ioctl_cmd
>
> or:
>
> v4l2_ioctl_cmd_is_known
> v4l2_ioctl_cmd_disable_locking
> v4l2_ioctl_cmd_disable
>
> The last set looks better but sounds worse :-)
I have no strong preference, the format sounds a little bit better to me. I
would probably have dropped cmd, but that's up to you.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFCv1 PATCH 3/5] tea575x-tuner: mark VIDIOC_S_HW_FREQ_SEEK as an invalid ioctl.
2012-05-10 7:05 ` [RFCv1 PATCH 1/5] v4l2-dev: make it possible to skip locking for selected ioctls Hans Verkuil
2012-05-10 7:05 ` [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront Hans Verkuil
@ 2012-05-10 7:05 ` Hans Verkuil
2012-05-10 8:12 ` Hans de Goede
2012-05-10 7:05 ` [RFCv1 PATCH 4/5] v4l2-ioctl: handle priority handling based on a table lookup Hans Verkuil
` (2 subsequent siblings)
4 siblings, 1 reply; 20+ messages in thread
From: Hans Verkuil @ 2012-05-10 7:05 UTC (permalink / raw)
To: linux-media; +Cc: Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
The tea575x-tuner framework can support the VIDIOC_S_HW_FREQ_SEEK for only
some of the tea575x-based boards. Mark this ioctl as invalid if the board
doesn't support it.
This fixes an issue with S_HW_FREQ_SEEK in combination with priority handling:
since the priority check is done first it could return -EBUSY, even though
calling the S_HW_FREQ_SEEK ioctl would return -ENOTTY. It should always return
ENOTTY in such a case.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
sound/i2c/other/tea575x-tuner.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index a63faec..6e9ca7b 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -375,6 +375,9 @@ int snd_tea575x_init(struct snd_tea575x *tea)
tea->vd.v4l2_dev = tea->v4l2_dev;
tea->vd.ctrl_handler = &tea->ctrl_handler;
set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
+ /* disable hw_freq_seek if we can't use it */
+ if (tea->cannot_read_data)
+ v4l2_dont_use_cmd(&tea->vd, VIDIOC_S_HW_FREQ_SEEK);
v4l2_ctrl_handler_init(&tea->ctrl_handler, 1);
v4l2_ctrl_new_std(&tea->ctrl_handler, &tea575x_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
--
1.7.10
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [RFCv1 PATCH 3/5] tea575x-tuner: mark VIDIOC_S_HW_FREQ_SEEK as an invalid ioctl.
2012-05-10 7:05 ` [RFCv1 PATCH 3/5] tea575x-tuner: mark VIDIOC_S_HW_FREQ_SEEK as an invalid ioctl Hans Verkuil
@ 2012-05-10 8:12 ` Hans de Goede
0 siblings, 0 replies; 20+ messages in thread
From: Hans de Goede @ 2012-05-10 8:12 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Mauro Carvalho Chehab, Hans Verkuil
Hi,
Looks good, ack.
Acked-by: Hans de Goede <hdegoede@redhat.com>
Regards,
Hans
On 05/10/2012 09:05 AM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> The tea575x-tuner framework can support the VIDIOC_S_HW_FREQ_SEEK for only
> some of the tea575x-based boards. Mark this ioctl as invalid if the board
> doesn't support it.
>
> This fixes an issue with S_HW_FREQ_SEEK in combination with priority handling:
> since the priority check is done first it could return -EBUSY, even though
> calling the S_HW_FREQ_SEEK ioctl would return -ENOTTY. It should always return
> ENOTTY in such a case.
>
> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>
> ---
> sound/i2c/other/tea575x-tuner.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
> index a63faec..6e9ca7b 100644
> --- a/sound/i2c/other/tea575x-tuner.c
> +++ b/sound/i2c/other/tea575x-tuner.c
> @@ -375,6 +375,9 @@ int snd_tea575x_init(struct snd_tea575x *tea)
> tea->vd.v4l2_dev = tea->v4l2_dev;
> tea->vd.ctrl_handler =&tea->ctrl_handler;
> set_bit(V4L2_FL_USE_FH_PRIO,&tea->vd.flags);
> + /* disable hw_freq_seek if we can't use it */
> + if (tea->cannot_read_data)
> + v4l2_dont_use_cmd(&tea->vd, VIDIOC_S_HW_FREQ_SEEK);
>
> v4l2_ctrl_handler_init(&tea->ctrl_handler, 1);
> v4l2_ctrl_new_std(&tea->ctrl_handler,&tea575x_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFCv1 PATCH 4/5] v4l2-ioctl: handle priority handling based on a table lookup.
2012-05-10 7:05 ` [RFCv1 PATCH 1/5] v4l2-dev: make it possible to skip locking for selected ioctls Hans Verkuil
2012-05-10 7:05 ` [RFCv1 PATCH 2/5] v4l2-dev/ioctl: determine the valid ioctls upfront Hans Verkuil
2012-05-10 7:05 ` [RFCv1 PATCH 3/5] tea575x-tuner: mark VIDIOC_S_HW_FREQ_SEEK as an invalid ioctl Hans Verkuil
@ 2012-05-10 7:05 ` Hans Verkuil
2012-05-10 8:13 ` Hans de Goede
2012-05-10 7:05 ` [RFCv1 PATCH 5/5] v4l2-dev: add flag to have the core lock all file operations Hans Verkuil
2012-05-10 8:00 ` [RFCv1 PATCH 1/5] v4l2-dev: make it possible to skip locking for selected ioctls Hans de Goede
4 siblings, 1 reply; 20+ messages in thread
From: Hans Verkuil @ 2012-05-10 7:05 UTC (permalink / raw)
To: linux-media; +Cc: Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
Rather than checking the priority for each ioctl that needs to, just mark
such ioctls in the table and do it only once.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/video/v4l2-ioctl.c | 181 +++++++++-----------------------------
1 file changed, 40 insertions(+), 141 deletions(-)
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 21da16d..8d2fdeb 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -189,6 +189,8 @@ struct v4l2_ioctl_info {
const char * const name;
};
+/* This control needs a priority check */
+#define INFO_FL_PRIO (1 << 0)
/* This control can be valid if the filehandle passes a control handler. */
#define INFO_FL_CTRL (1 << 1)
@@ -202,80 +204,82 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO(VIDIOC_QUERYCAP, 0),
IOCTL_INFO(VIDIOC_ENUM_FMT, 0),
IOCTL_INFO(VIDIOC_G_FMT, 0),
- IOCTL_INFO(VIDIOC_S_FMT, 0),
- IOCTL_INFO(VIDIOC_REQBUFS, 0),
+ IOCTL_INFO(VIDIOC_S_FMT, INFO_FL_PRIO),
+ IOCTL_INFO(VIDIOC_REQBUFS, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QUERYBUF, 0),
IOCTL_INFO(VIDIOC_G_FBUF, 0),
- IOCTL_INFO(VIDIOC_S_FBUF, 0),
- IOCTL_INFO(VIDIOC_OVERLAY, 0),
+ IOCTL_INFO(VIDIOC_S_FBUF, INFO_FL_PRIO),
+ IOCTL_INFO(VIDIOC_OVERLAY, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QBUF, 0),
IOCTL_INFO(VIDIOC_DQBUF, 0),
- IOCTL_INFO(VIDIOC_STREAMON, 0),
- IOCTL_INFO(VIDIOC_STREAMOFF, 0),
+ IOCTL_INFO(VIDIOC_STREAMON, INFO_FL_PRIO),
+ IOCTL_INFO(VIDIOC_STREAMOFF, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_PARM, 0),
- IOCTL_INFO(VIDIOC_S_PARM, 0),
+ IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_STD, 0),
- IOCTL_INFO(VIDIOC_S_STD, 0),
+ IOCTL_INFO(VIDIOC_S_STD, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_ENUMSTD, 0),
IOCTL_INFO(VIDIOC_ENUMINPUT, 0),
IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL),
- IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_CTRL),
+ IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_G_TUNER, 0),
- IOCTL_INFO(VIDIOC_S_TUNER, 0),
+ IOCTL_INFO(VIDIOC_S_TUNER, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_AUDIO, 0),
- IOCTL_INFO(VIDIOC_S_AUDIO, 0),
+ IOCTL_INFO(VIDIOC_S_AUDIO, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_G_INPUT, 0),
- IOCTL_INFO(VIDIOC_S_INPUT, 0),
+ IOCTL_INFO(VIDIOC_S_INPUT, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_OUTPUT, 0),
- IOCTL_INFO(VIDIOC_S_OUTPUT, 0),
+ IOCTL_INFO(VIDIOC_S_OUTPUT, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0),
IOCTL_INFO(VIDIOC_G_AUDOUT, 0),
- IOCTL_INFO(VIDIOC_S_AUDOUT, 0),
+ IOCTL_INFO(VIDIOC_S_AUDOUT, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_MODULATOR, 0),
- IOCTL_INFO(VIDIOC_S_MODULATOR, 0),
+ IOCTL_INFO(VIDIOC_S_MODULATOR, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_FREQUENCY, 0),
- IOCTL_INFO(VIDIOC_S_FREQUENCY, 0),
+ IOCTL_INFO(VIDIOC_S_FREQUENCY, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_CROPCAP, 0),
IOCTL_INFO(VIDIOC_G_CROP, 0),
- IOCTL_INFO(VIDIOC_S_CROP, 0),
+ IOCTL_INFO(VIDIOC_S_CROP, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_SELECTION, 0),
- IOCTL_INFO(VIDIOC_S_SELECTION, 0),
+ IOCTL_INFO(VIDIOC_S_SELECTION, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0),
- IOCTL_INFO(VIDIOC_S_JPEGCOMP, 0),
+ IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_QUERYSTD, 0),
IOCTL_INFO(VIDIOC_TRY_FMT, 0),
IOCTL_INFO(VIDIOC_ENUMAUDIO, 0),
IOCTL_INFO(VIDIOC_ENUMAUDOUT, 0),
IOCTL_INFO(VIDIOC_G_PRIORITY, 0),
- IOCTL_INFO(VIDIOC_S_PRIORITY, 0),
+ IOCTL_INFO(VIDIOC_S_PRIORITY, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, 0),
IOCTL_INFO(VIDIOC_LOG_STATUS, 0),
IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL),
- IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_CTRL),
+ IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_PRIO | INFO_FL_CTRL),
IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0),
IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, 0),
IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, 0),
IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0),
- IOCTL_INFO(VIDIOC_ENCODER_CMD, 0),
+ IOCTL_INFO(VIDIOC_ENCODER_CMD, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, 0),
- IOCTL_INFO(VIDIOC_DECODER_CMD, 0),
+ IOCTL_INFO(VIDIOC_DECODER_CMD, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0),
+#ifdef CONFIG_VIDEO_ADV_DEBUG
IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0),
IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0),
+#endif
IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0),
- IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, 0),
+ IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0),
- IOCTL_INFO(VIDIOC_S_DV_PRESET, 0),
+ IOCTL_INFO(VIDIOC_S_DV_PRESET, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_DV_PRESET, 0),
IOCTL_INFO(VIDIOC_QUERY_DV_PRESET, 0),
- IOCTL_INFO(VIDIOC_S_DV_TIMINGS, 0),
+ IOCTL_INFO(VIDIOC_S_DV_TIMINGS, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_G_DV_TIMINGS, 0),
IOCTL_INFO(VIDIOC_DQEVENT, 0),
IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0),
IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0),
- IOCTL_INFO(VIDIOC_CREATE_BUFS, 0),
+ IOCTL_INFO(VIDIOC_CREATE_BUFS, INFO_FL_PRIO),
IOCTL_INFO(VIDIOC_PREPARE_BUF, 0),
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -509,7 +513,6 @@ static long __video_do_ioctl(struct file *file,
void *fh = file->private_data;
struct v4l2_fh *vfh = NULL;
int use_fh_prio = 0;
- long ret_prio = 0;
long ret = -ENOTTY;
if (ops == NULL) {
@@ -521,8 +524,6 @@ static long __video_do_ioctl(struct file *file,
if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
vfh = file->private_data;
use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
- if (use_fh_prio)
- ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
}
if (v4l2_is_valid_ioctl(cmd)) {
@@ -533,6 +534,11 @@ static long __video_do_ioctl(struct file *file,
!(vfh && vfh->ctrl_handler))
return -ENOTTY;
}
+ if (use_fh_prio && (info->flags & INFO_FL_PRIO)) {
+ ret = v4l2_prio_check(vfd->prio, vfh->prio);
+ if (ret)
+ return ret;
+ }
}
if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
@@ -581,14 +587,11 @@ static long __video_do_ioctl(struct file *file,
{
enum v4l2_priority *p = arg;
- if (!ops->vidioc_s_priority && !use_fh_prio)
- break;
dbgarg(cmd, "setting priority to %d\n", *p);
if (ops->vidioc_s_priority)
ret = ops->vidioc_s_priority(file, fh, *p);
else
- ret = ret_prio ? ret_prio :
- v4l2_prio_change(&vfd->v4l2_dev->prio,
+ ret = v4l2_prio_change(&vfd->v4l2_dev->prio,
&vfh->prio, *p);
break;
}
@@ -717,10 +720,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_format *f = (struct v4l2_format *)arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = -EINVAL;
/* FIXME: Should be one dump per type */
@@ -887,10 +886,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_requestbuffers *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -948,10 +943,6 @@ static long __video_do_ioctl(struct file *file,
{
int *i = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_overlay(file, fh, *i);
break;
@@ -973,10 +964,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_framebuffer *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
p->capability, p->flags, (unsigned long)p->base);
v4l_print_pix_fmt(vfd, &p->fmt);
@@ -987,10 +974,6 @@ static long __video_do_ioctl(struct file *file,
{
enum v4l2_buf_type i = *(int *)arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret = ops->vidioc_streamon(file, fh, i);
break;
@@ -999,10 +982,6 @@ static long __video_do_ioctl(struct file *file,
{
enum v4l2_buf_type i = *(int *)arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
ret = ops->vidioc_streamoff(file, fh, i);
break;
@@ -1072,10 +1051,6 @@ static long __video_do_ioctl(struct file *file,
dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = -EINVAL;
norm = (*id) & vfd->tvnorms;
if (vfd->tvnorms && !norm) /* Check if std is supported */
@@ -1150,10 +1125,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_s_input(file, fh, *i);
break;
@@ -1199,10 +1170,6 @@ static long __video_do_ioctl(struct file *file,
{
unsigned int *i = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "value=%d\n", *i);
ret = ops->vidioc_s_output(file, fh, *i);
break;
@@ -1272,10 +1239,6 @@ static long __video_do_ioctl(struct file *file,
if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
@@ -1331,10 +1294,6 @@ static long __video_do_ioctl(struct file *file,
if (!(vfh && vfh->ctrl_handler) && !vfd->ctrl_handler &&
!ops->vidioc_s_ext_ctrls)
break;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
v4l_print_ext_ctrls(cmd, vfd, p, 1);
if (vfh && vfh->ctrl_handler)
ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
@@ -1416,10 +1375,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audio *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
"mode=0x%x\n", p->index, p->name,
p->capability, p->mode);
@@ -1453,10 +1408,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_audioout *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "index=%d, name=%s, capability=%d, "
"mode=%d\n", p->index, p->name,
p->capability, p->mode);
@@ -1482,10 +1433,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_modulator *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "index=%d, name=%s, capability=%d, "
"rangelow=%d, rangehigh=%d, txsubchans=%d\n",
p->index, p->name, p->capability, p->rangelow,
@@ -1528,10 +1475,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_crop *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
dbgrect(vfd, "", &p->c);
@@ -1569,10 +1512,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_selection *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
dbgrect(vfd, "", &p->r);
@@ -1641,10 +1580,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_jpegcompression *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
"COM_len=%d, jpeg_markers=%d\n",
p->quality, p->APPn, p->APP_len,
@@ -1666,10 +1601,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_encoder_cmd *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = ops->vidioc_encoder_cmd(file, fh, p);
if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1688,10 +1619,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_decoder_cmd *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = ops->vidioc_decoder_cmd(file, fh, p);
if (!ret)
dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
@@ -1737,10 +1664,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_streamparm *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = check_fmt(ops, p->type);
if (ret)
break;
@@ -1771,10 +1694,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_tuner *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd, "index=%d, name=%s, type=%d, "
@@ -1805,10 +1724,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_frequency *p = arg;
enum v4l2_tuner_type type;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
@@ -1883,10 +1798,6 @@ static long __video_do_ioctl(struct file *file,
struct v4l2_hw_freq_seek *p = arg;
enum v4l2_tuner_type type;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
dbgarg(cmd,
@@ -1980,11 +1891,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_preset *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
-
dbgarg(cmd, "preset=%d\n", p->preset);
ret = ops->vidioc_s_dv_preset(file, fh, p);
break;
@@ -2011,11 +1917,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_dv_timings *p = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
-
switch (p->type) {
case V4L2_DV_BT_656_1120:
dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld,"
@@ -2114,10 +2015,6 @@ static long __video_do_ioctl(struct file *file,
{
struct v4l2_create_buffers *create = arg;
- if (ret_prio) {
- ret = ret_prio;
- break;
- }
ret = check_fmt(ops, create->format.type);
if (ret)
break;
@@ -2143,7 +2040,9 @@ static long __video_do_ioctl(struct file *file,
default:
if (!ops->vidioc_default)
break;
- ret = ops->vidioc_default(file, fh, ret_prio >= 0, cmd, arg);
+ ret = ops->vidioc_default(file, fh, use_fh_prio ?
+ v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
+ cmd, arg);
break;
} /* switch */
--
1.7.10
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [RFCv1 PATCH 4/5] v4l2-ioctl: handle priority handling based on a table lookup.
2012-05-10 7:05 ` [RFCv1 PATCH 4/5] v4l2-ioctl: handle priority handling based on a table lookup Hans Verkuil
@ 2012-05-10 8:13 ` Hans de Goede
0 siblings, 0 replies; 20+ messages in thread
From: Hans de Goede @ 2012-05-10 8:13 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Mauro Carvalho Chehab, Hans Verkuil
Hi,
Looks good, ack.
Acked-by: Hans de Goede <hdegoede@redhat.com>
Regards,
Hans
On 05/10/2012 09:05 AM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> Rather than checking the priority for each ioctl that needs to, just mark
> such ioctls in the table and do it only once.
>
> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>
> ---
> drivers/media/video/v4l2-ioctl.c | 181 +++++++++-----------------------------
> 1 file changed, 40 insertions(+), 141 deletions(-)
>
> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> index 21da16d..8d2fdeb 100644
> --- a/drivers/media/video/v4l2-ioctl.c
> +++ b/drivers/media/video/v4l2-ioctl.c
> @@ -189,6 +189,8 @@ struct v4l2_ioctl_info {
> const char * const name;
> };
>
> +/* This control needs a priority check */
> +#define INFO_FL_PRIO (1<< 0)
> /* This control can be valid if the filehandle passes a control handler. */
> #define INFO_FL_CTRL (1<< 1)
>
> @@ -202,80 +204,82 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
> IOCTL_INFO(VIDIOC_QUERYCAP, 0),
> IOCTL_INFO(VIDIOC_ENUM_FMT, 0),
> IOCTL_INFO(VIDIOC_G_FMT, 0),
> - IOCTL_INFO(VIDIOC_S_FMT, 0),
> - IOCTL_INFO(VIDIOC_REQBUFS, 0),
> + IOCTL_INFO(VIDIOC_S_FMT, INFO_FL_PRIO),
> + IOCTL_INFO(VIDIOC_REQBUFS, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_QUERYBUF, 0),
> IOCTL_INFO(VIDIOC_G_FBUF, 0),
> - IOCTL_INFO(VIDIOC_S_FBUF, 0),
> - IOCTL_INFO(VIDIOC_OVERLAY, 0),
> + IOCTL_INFO(VIDIOC_S_FBUF, INFO_FL_PRIO),
> + IOCTL_INFO(VIDIOC_OVERLAY, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_QBUF, 0),
> IOCTL_INFO(VIDIOC_DQBUF, 0),
> - IOCTL_INFO(VIDIOC_STREAMON, 0),
> - IOCTL_INFO(VIDIOC_STREAMOFF, 0),
> + IOCTL_INFO(VIDIOC_STREAMON, INFO_FL_PRIO),
> + IOCTL_INFO(VIDIOC_STREAMOFF, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_PARM, 0),
> - IOCTL_INFO(VIDIOC_S_PARM, 0),
> + IOCTL_INFO(VIDIOC_S_PARM, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_STD, 0),
> - IOCTL_INFO(VIDIOC_S_STD, 0),
> + IOCTL_INFO(VIDIOC_S_STD, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_ENUMSTD, 0),
> IOCTL_INFO(VIDIOC_ENUMINPUT, 0),
> IOCTL_INFO(VIDIOC_G_CTRL, INFO_FL_CTRL),
> - IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_CTRL),
> + IOCTL_INFO(VIDIOC_S_CTRL, INFO_FL_PRIO | INFO_FL_CTRL),
> IOCTL_INFO(VIDIOC_G_TUNER, 0),
> - IOCTL_INFO(VIDIOC_S_TUNER, 0),
> + IOCTL_INFO(VIDIOC_S_TUNER, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_AUDIO, 0),
> - IOCTL_INFO(VIDIOC_S_AUDIO, 0),
> + IOCTL_INFO(VIDIOC_S_AUDIO, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_QUERYCTRL, INFO_FL_CTRL),
> IOCTL_INFO(VIDIOC_QUERYMENU, INFO_FL_CTRL),
> IOCTL_INFO(VIDIOC_G_INPUT, 0),
> - IOCTL_INFO(VIDIOC_S_INPUT, 0),
> + IOCTL_INFO(VIDIOC_S_INPUT, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_OUTPUT, 0),
> - IOCTL_INFO(VIDIOC_S_OUTPUT, 0),
> + IOCTL_INFO(VIDIOC_S_OUTPUT, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_ENUMOUTPUT, 0),
> IOCTL_INFO(VIDIOC_G_AUDOUT, 0),
> - IOCTL_INFO(VIDIOC_S_AUDOUT, 0),
> + IOCTL_INFO(VIDIOC_S_AUDOUT, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_MODULATOR, 0),
> - IOCTL_INFO(VIDIOC_S_MODULATOR, 0),
> + IOCTL_INFO(VIDIOC_S_MODULATOR, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_FREQUENCY, 0),
> - IOCTL_INFO(VIDIOC_S_FREQUENCY, 0),
> + IOCTL_INFO(VIDIOC_S_FREQUENCY, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_CROPCAP, 0),
> IOCTL_INFO(VIDIOC_G_CROP, 0),
> - IOCTL_INFO(VIDIOC_S_CROP, 0),
> + IOCTL_INFO(VIDIOC_S_CROP, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_SELECTION, 0),
> - IOCTL_INFO(VIDIOC_S_SELECTION, 0),
> + IOCTL_INFO(VIDIOC_S_SELECTION, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_JPEGCOMP, 0),
> - IOCTL_INFO(VIDIOC_S_JPEGCOMP, 0),
> + IOCTL_INFO(VIDIOC_S_JPEGCOMP, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_QUERYSTD, 0),
> IOCTL_INFO(VIDIOC_TRY_FMT, 0),
> IOCTL_INFO(VIDIOC_ENUMAUDIO, 0),
> IOCTL_INFO(VIDIOC_ENUMAUDOUT, 0),
> IOCTL_INFO(VIDIOC_G_PRIORITY, 0),
> - IOCTL_INFO(VIDIOC_S_PRIORITY, 0),
> + IOCTL_INFO(VIDIOC_S_PRIORITY, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_SLICED_VBI_CAP, 0),
> IOCTL_INFO(VIDIOC_LOG_STATUS, 0),
> IOCTL_INFO(VIDIOC_G_EXT_CTRLS, INFO_FL_CTRL),
> - IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_CTRL),
> + IOCTL_INFO(VIDIOC_S_EXT_CTRLS, INFO_FL_PRIO | INFO_FL_CTRL),
> IOCTL_INFO(VIDIOC_TRY_EXT_CTRLS, 0),
> IOCTL_INFO(VIDIOC_ENUM_FRAMESIZES, 0),
> IOCTL_INFO(VIDIOC_ENUM_FRAMEINTERVALS, 0),
> IOCTL_INFO(VIDIOC_G_ENC_INDEX, 0),
> - IOCTL_INFO(VIDIOC_ENCODER_CMD, 0),
> + IOCTL_INFO(VIDIOC_ENCODER_CMD, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_TRY_ENCODER_CMD, 0),
> - IOCTL_INFO(VIDIOC_DECODER_CMD, 0),
> + IOCTL_INFO(VIDIOC_DECODER_CMD, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_TRY_DECODER_CMD, 0),
> +#ifdef CONFIG_VIDEO_ADV_DEBUG
> IOCTL_INFO(VIDIOC_DBG_S_REGISTER, 0),
> IOCTL_INFO(VIDIOC_DBG_G_REGISTER, 0),
> +#endif
> IOCTL_INFO(VIDIOC_DBG_G_CHIP_IDENT, 0),
> - IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, 0),
> + IOCTL_INFO(VIDIOC_S_HW_FREQ_SEEK, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_ENUM_DV_PRESETS, 0),
> - IOCTL_INFO(VIDIOC_S_DV_PRESET, 0),
> + IOCTL_INFO(VIDIOC_S_DV_PRESET, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_DV_PRESET, 0),
> IOCTL_INFO(VIDIOC_QUERY_DV_PRESET, 0),
> - IOCTL_INFO(VIDIOC_S_DV_TIMINGS, 0),
> + IOCTL_INFO(VIDIOC_S_DV_TIMINGS, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_G_DV_TIMINGS, 0),
> IOCTL_INFO(VIDIOC_DQEVENT, 0),
> IOCTL_INFO(VIDIOC_SUBSCRIBE_EVENT, 0),
> IOCTL_INFO(VIDIOC_UNSUBSCRIBE_EVENT, 0),
> - IOCTL_INFO(VIDIOC_CREATE_BUFS, 0),
> + IOCTL_INFO(VIDIOC_CREATE_BUFS, INFO_FL_PRIO),
> IOCTL_INFO(VIDIOC_PREPARE_BUF, 0),
> };
> #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
> @@ -509,7 +513,6 @@ static long __video_do_ioctl(struct file *file,
> void *fh = file->private_data;
> struct v4l2_fh *vfh = NULL;
> int use_fh_prio = 0;
> - long ret_prio = 0;
> long ret = -ENOTTY;
>
> if (ops == NULL) {
> @@ -521,8 +524,6 @@ static long __video_do_ioctl(struct file *file,
> if (test_bit(V4L2_FL_USES_V4L2_FH,&vfd->flags)) {
> vfh = file->private_data;
> use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO,&vfd->flags);
> - if (use_fh_prio)
> - ret_prio = v4l2_prio_check(vfd->prio, vfh->prio);
> }
>
> if (v4l2_is_valid_ioctl(cmd)) {
> @@ -533,6 +534,11 @@ static long __video_do_ioctl(struct file *file,
> !(vfh&& vfh->ctrl_handler))
> return -ENOTTY;
> }
> + if (use_fh_prio&& (info->flags& INFO_FL_PRIO)) {
> + ret = v4l2_prio_check(vfd->prio, vfh->prio);
> + if (ret)
> + return ret;
> + }
> }
>
> if ((vfd->debug& V4L2_DEBUG_IOCTL)&&
> @@ -581,14 +587,11 @@ static long __video_do_ioctl(struct file *file,
> {
> enum v4l2_priority *p = arg;
>
> - if (!ops->vidioc_s_priority&& !use_fh_prio)
> - break;
> dbgarg(cmd, "setting priority to %d\n", *p);
> if (ops->vidioc_s_priority)
> ret = ops->vidioc_s_priority(file, fh, *p);
> else
> - ret = ret_prio ? ret_prio :
> - v4l2_prio_change(&vfd->v4l2_dev->prio,
> + ret = v4l2_prio_change(&vfd->v4l2_dev->prio,
> &vfh->prio, *p);
> break;
> }
> @@ -717,10 +720,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_format *f = (struct v4l2_format *)arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> ret = -EINVAL;
>
> /* FIXME: Should be one dump per type */
> @@ -887,10 +886,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_requestbuffers *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> ret = check_fmt(ops, p->type);
> if (ret)
> break;
> @@ -948,10 +943,6 @@ static long __video_do_ioctl(struct file *file,
> {
> int *i = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "value=%d\n", *i);
> ret = ops->vidioc_overlay(file, fh, *i);
> break;
> @@ -973,10 +964,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_framebuffer *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
> p->capability, p->flags, (unsigned long)p->base);
> v4l_print_pix_fmt(vfd,&p->fmt);
> @@ -987,10 +974,6 @@ static long __video_do_ioctl(struct file *file,
> {
> enum v4l2_buf_type i = *(int *)arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
> ret = ops->vidioc_streamon(file, fh, i);
> break;
> @@ -999,10 +982,6 @@ static long __video_do_ioctl(struct file *file,
> {
> enum v4l2_buf_type i = *(int *)arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
> ret = ops->vidioc_streamoff(file, fh, i);
> break;
> @@ -1072,10 +1051,6 @@ static long __video_do_ioctl(struct file *file,
>
> dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> ret = -EINVAL;
> norm = (*id)& vfd->tvnorms;
> if (vfd->tvnorms&& !norm) /* Check if std is supported */
> @@ -1150,10 +1125,6 @@ static long __video_do_ioctl(struct file *file,
> {
> unsigned int *i = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "value=%d\n", *i);
> ret = ops->vidioc_s_input(file, fh, *i);
> break;
> @@ -1199,10 +1170,6 @@ static long __video_do_ioctl(struct file *file,
> {
> unsigned int *i = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "value=%d\n", *i);
> ret = ops->vidioc_s_output(file, fh, *i);
> break;
> @@ -1272,10 +1239,6 @@ static long __video_do_ioctl(struct file *file,
> if (!(vfh&& vfh->ctrl_handler)&& !vfd->ctrl_handler&&
> !ops->vidioc_s_ctrl&& !ops->vidioc_s_ext_ctrls)
> break;
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
>
> dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
>
> @@ -1331,10 +1294,6 @@ static long __video_do_ioctl(struct file *file,
> if (!(vfh&& vfh->ctrl_handler)&& !vfd->ctrl_handler&&
> !ops->vidioc_s_ext_ctrls)
> break;
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> v4l_print_ext_ctrls(cmd, vfd, p, 1);
> if (vfh&& vfh->ctrl_handler)
> ret = v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
> @@ -1416,10 +1375,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_audio *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
> "mode=0x%x\n", p->index, p->name,
> p->capability, p->mode);
> @@ -1453,10 +1408,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_audioout *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "index=%d, name=%s, capability=%d, "
> "mode=%d\n", p->index, p->name,
> p->capability, p->mode);
> @@ -1482,10 +1433,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_modulator *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "index=%d, name=%s, capability=%d, "
> "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
> p->index, p->name, p->capability, p->rangelow,
> @@ -1528,10 +1475,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_crop *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
> dbgrect(vfd, "",&p->c);
>
> @@ -1569,10 +1512,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_selection *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
>
> dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
> dbgrect(vfd, "",&p->r);
> @@ -1641,10 +1580,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_jpegcompression *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
> "COM_len=%d, jpeg_markers=%d\n",
> p->quality, p->APPn, p->APP_len,
> @@ -1666,10 +1601,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_encoder_cmd *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> ret = ops->vidioc_encoder_cmd(file, fh, p);
> if (!ret)
> dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
> @@ -1688,10 +1619,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_decoder_cmd *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> ret = ops->vidioc_decoder_cmd(file, fh, p);
> if (!ret)
> dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
> @@ -1737,10 +1664,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_streamparm *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> ret = check_fmt(ops, p->type);
> if (ret)
> break;
> @@ -1771,10 +1694,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_tuner *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> dbgarg(cmd, "index=%d, name=%s, type=%d, "
> @@ -1805,10 +1724,6 @@ static long __video_do_ioctl(struct file *file,
> struct v4l2_frequency *p = arg;
> enum v4l2_tuner_type type;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
> @@ -1883,10 +1798,6 @@ static long __video_do_ioctl(struct file *file,
> struct v4l2_hw_freq_seek *p = arg;
> enum v4l2_tuner_type type;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
> V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
> dbgarg(cmd,
> @@ -1980,11 +1891,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_dv_preset *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> -
> dbgarg(cmd, "preset=%d\n", p->preset);
> ret = ops->vidioc_s_dv_preset(file, fh, p);
> break;
> @@ -2011,11 +1917,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_dv_timings *p = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> -
> switch (p->type) {
> case V4L2_DV_BT_656_1120:
> dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld,"
> @@ -2114,10 +2015,6 @@ static long __video_do_ioctl(struct file *file,
> {
> struct v4l2_create_buffers *create = arg;
>
> - if (ret_prio) {
> - ret = ret_prio;
> - break;
> - }
> ret = check_fmt(ops, create->format.type);
> if (ret)
> break;
> @@ -2143,7 +2040,9 @@ static long __video_do_ioctl(struct file *file,
> default:
> if (!ops->vidioc_default)
> break;
> - ret = ops->vidioc_default(file, fh, ret_prio>= 0, cmd, arg);
> + ret = ops->vidioc_default(file, fh, use_fh_prio ?
> + v4l2_prio_check(vfd->prio, vfh->prio)>= 0 : 0,
> + cmd, arg);
> break;
> } /* switch */
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFCv1 PATCH 5/5] v4l2-dev: add flag to have the core lock all file operations.
2012-05-10 7:05 ` [RFCv1 PATCH 1/5] v4l2-dev: make it possible to skip locking for selected ioctls Hans Verkuil
` (2 preceding siblings ...)
2012-05-10 7:05 ` [RFCv1 PATCH 4/5] v4l2-ioctl: handle priority handling based on a table lookup Hans Verkuil
@ 2012-05-10 7:05 ` Hans Verkuil
2012-05-10 8:14 ` Hans de Goede
2012-05-14 12:31 ` Laurent Pinchart
2012-05-10 8:00 ` [RFCv1 PATCH 1/5] v4l2-dev: make it possible to skip locking for selected ioctls Hans de Goede
4 siblings, 2 replies; 20+ messages in thread
From: Hans Verkuil @ 2012-05-10 7:05 UTC (permalink / raw)
To: linux-media; +Cc: Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
From: Hans Verkuil <hans.verkuil@cisco.com>
This used to be the default if the lock pointer was set, but now that lock is by
default only used for ioctl serialization. Those drivers that already used
core locking have this flag set explicitly, except for some drivers where
it was obvious that there was no need to serialize any file operations other
than ioctl.
The drivers that didn't need this flag were:
drivers/media/radio/dsbr100.c
drivers/media/radio/radio-isa.c
drivers/media/radio/radio-keene.c
drivers/media/radio/radio-miropcm20.c
drivers/media/radio/radio-mr800.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/radio-timb.c
drivers/media/video/vivi.c
sound/i2c/other/tea575x-tuner.c
The other drivers that use core locking and where it was not immediately
obvious that this flag wasn't needed were changed so that the flag is set
together with a comment that that driver needs work to avoid having to
set that flag. This will often involve taking the core lock in the fops
themselves.
Eventually this flag should go and it should not be used in new drivers.
There are a few reasons why we want to avoid core locking of non-ioctl
fops: in the case of mmap this can lead to a deadlock in rare situations
since when mmap is called the mmap_sem is held and it is possible for
other parts of the code to take that lock as well (copy_from_user()/copy_to_user()
perform a down_read(&mm->mmap_sem) when a page fault occurs).
It is very unlikely that that happens since the core lock serializes all
fops, but the kernel warns about it if lock validation is turned on.
For poll it is also undesirable to take the core lock as that can introduce
increased latency. The same is true for read/write.
While it was possible to make flags or something to turn on/off taking the
core lock for each file operation, in practice it is much simpler to just
not take it at all except for ioctl and leave it to the driver to take the
lock. There are only a handful fops compared to the zillion ioctls we have.
I also wanted to make it obvious which drivers still take the lock for all
fops, so that's why I chose to have drivers set it explicitly.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
drivers/media/common/saa7146_fops.c | 4 +++
drivers/media/radio/wl128x/fmdrv_v4l2.c | 4 +++
drivers/media/video/blackfin/bfin_capture.c | 4 +++
drivers/media/video/cpia2/cpia2_v4l.c | 4 +++
drivers/media/video/cx231xx/cx231xx-video.c | 4 +++
drivers/media/video/davinci/vpbe_display.c | 4 +++
drivers/media/video/davinci/vpif_capture.c | 4 +++
drivers/media/video/davinci/vpif_display.c | 4 +++
drivers/media/video/em28xx/em28xx-video.c | 4 +++
drivers/media/video/fsl-viu.c | 4 +++
drivers/media/video/ivtv/ivtv-streams.c | 4 +++
drivers/media/video/mem2mem_testdev.c | 4 +++
drivers/media/video/mx2_emmaprp.c | 4 +++
drivers/media/video/s2255drv.c | 4 +++
drivers/media/video/s5p-fimc/fimc-capture.c | 4 +++
drivers/media/video/s5p-fimc/fimc-core.c | 4 +++
drivers/media/video/s5p-g2d/g2d.c | 4 +++
drivers/media/video/s5p-jpeg/jpeg-core.c | 8 ++++++
drivers/media/video/s5p-mfc/s5p_mfc.c | 6 +++++
drivers/media/video/s5p-tv/mixer_video.c | 4 +++
drivers/media/video/sh_vou.c | 4 +++
drivers/media/video/soc_camera.c | 4 +++
drivers/media/video/tm6000/tm6000-video.c | 4 +++
drivers/media/video/usbvision/usbvision-video.c | 4 +++
drivers/media/video/v4l2-dev.c | 32 ++++++++++++++---------
drivers/staging/media/dt3155v4l/dt3155v4l.c | 4 +++
include/media/v4l2-dev.h | 3 +++
27 files changed, 129 insertions(+), 12 deletions(-)
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 71f8e01..8d7df1a 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -511,6 +511,10 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
vfd->fops = &video_fops;
vfd->ioctl_ops = &dev->ext_vv_data->ops;
vfd->release = video_device_release;
+ /* Locking in file operations other than ioctl should be done by
+ the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
vfd->lock = &dev->v4l2_lock;
vfd->tvnorms = 0;
for (i = 0; i < dev->ext_vv_data->num_stds; i++)
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index 077d369..080b96a 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -518,6 +518,10 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
video_set_drvdata(gradio_dev, fmdev);
gradio_dev->lock = &fmdev->mutex;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &gradio_dev->flags);
/* Register with V4L2 subsystem as RADIO device */
if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
diff --git a/drivers/media/video/blackfin/bfin_capture.c b/drivers/media/video/blackfin/bfin_capture.c
index 514fcf7..0aba45e 100644
--- a/drivers/media/video/blackfin/bfin_capture.c
+++ b/drivers/media/video/blackfin/bfin_capture.c
@@ -942,6 +942,10 @@ static int __devinit bcap_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&bcap_dev->dma_queue);
vfd->lock = &bcap_dev->mutex;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
/* register video device */
ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1);
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index bb4f1d0..55e9290 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -1147,6 +1147,10 @@ int cpia2_register_camera(struct camera_data *cam)
cam->vdev.ctrl_handler = hdl;
cam->vdev.v4l2_dev = &cam->v4l2_dev;
set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &cam->vdev.flags);
reset_camera_struct_v4l(cam);
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
index 7f916f0..2a04558 100644
--- a/drivers/media/video/cx231xx/cx231xx-video.c
+++ b/drivers/media/video/cx231xx/cx231xx-video.c
@@ -2561,6 +2561,10 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
vfd->release = video_device_release;
vfd->debug = video_debug;
vfd->lock = &dev->lock;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c
index 1f3b1c7..e106b72 100644
--- a/drivers/media/video/davinci/vpbe_display.c
+++ b/drivers/media/video/davinci/vpbe_display.c
@@ -1618,6 +1618,10 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
vbd->ioctl_ops = &vpbe_ioctl_ops;
vbd->minor = -1;
vbd->v4l2_dev = &disp_dev->vpbe_dev->v4l2_dev;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vbd->flags);
vbd->lock = &vpbe_display_layer->opslock;
if (disp_dev->vpbe_dev->current_timings.timings_type &
diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c
index 6504e40..9604695 100644
--- a/drivers/media/video/davinci/vpif_capture.c
+++ b/drivers/media/video/davinci/vpif_capture.c
@@ -2228,6 +2228,10 @@ static __init int vpif_probe(struct platform_device *pdev)
common = &(ch->common[VPIF_VIDEO_INDEX]);
spin_lock_init(&common->irqlock);
mutex_init(&common->lock);
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &ch->video_dev->flags);
ch->video_dev->lock = &common->lock;
/* Initialize prio member of channel object */
v4l2_prio_init(&ch->prio);
diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
index 7fa34b4..e6488ee 100644
--- a/drivers/media/video/davinci/vpif_display.c
+++ b/drivers/media/video/davinci/vpif_display.c
@@ -1778,6 +1778,10 @@ static __init int vpif_probe(struct platform_device *pdev)
v4l2_prio_init(&ch->prio);
ch->common[VPIF_VIDEO_INDEX].fmt.type =
V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &ch->video_dev->flags);
ch->video_dev->lock = &common->lock;
/* register video device */
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index bcc4160..308a1dd 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -2495,6 +2495,10 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
vfd->release = video_device_release;
vfd->debug = video_debug;
vfd->lock = &dev->lock;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
snprintf(vfd->name, sizeof(vfd->name), "%s %s",
dev->name, type_name);
diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c
index 27e3e0c..777486f 100644
--- a/drivers/media/video/fsl-viu.c
+++ b/drivers/media/video/fsl-viu.c
@@ -1544,6 +1544,10 @@ static int __devinit viu_of_probe(struct platform_device *op)
/* initialize locks */
mutex_init(&viu_dev->lock);
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &viu_dev->vdev->flags);
viu_dev->vdev->lock = &viu_dev->lock;
spin_lock_init(&viu_dev->slock);
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 7ea5ca7..6738592 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -228,6 +228,10 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
s->vdev->release = video_device_release;
s->vdev->tvnorms = V4L2_STD_ALL;
s->vdev->lock = &itv->serialize_lock;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &s->vdev->flags);
set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
ivtv_set_funcs(s->vdev);
return 0;
diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c
index 12897e8..ee3efbd 100644
--- a/drivers/media/video/mem2mem_testdev.c
+++ b/drivers/media/video/mem2mem_testdev.c
@@ -958,6 +958,10 @@ static int m2mtest_probe(struct platform_device *pdev)
}
*vfd = m2mtest_videodev;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
vfd->lock = &dev->dev_mutex;
ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
diff --git a/drivers/media/video/mx2_emmaprp.c b/drivers/media/video/mx2_emmaprp.c
index 55ac173..0bd5815 100644
--- a/drivers/media/video/mx2_emmaprp.c
+++ b/drivers/media/video/mx2_emmaprp.c
@@ -904,6 +904,10 @@ static int emmaprp_probe(struct platform_device *pdev)
}
*vfd = emmaprp_videodev;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
vfd->lock = &pcdev->dev_mutex;
video_set_drvdata(vfd, pcdev);
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 37845de..ea974fa 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -1948,6 +1948,10 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
/* register 4 video devices */
channel->vdev = template;
channel->vdev.lock = &dev->lock;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &channel->vdev.flags);
channel->vdev.v4l2_dev = &dev->v4l2_dev;
video_set_drvdata(&channel->vdev, channel);
if (video_nr == -1)
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index dc18ba5..72d5150 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -1516,6 +1516,10 @@ int fimc_register_capture_device(struct fimc_dev *fimc,
vfd->minor = -1;
vfd->release = video_device_release;
vfd->lock = &fimc->lock;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
video_set_drvdata(vfd, fimc);
vid_cap = &fimc->vid_cap;
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 7b90a89..c58dd9f 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -1520,6 +1520,10 @@ int fimc_register_m2m_device(struct fimc_dev *fimc,
vfd->minor = -1;
vfd->release = video_device_release;
vfd->lock = &fimc->lock;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
snprintf(vfd->name, sizeof(vfd->name), "%s.m2m", dev_name(&pdev->dev));
video_set_drvdata(vfd, fimc);
diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c
index 789de74..02605ce 100644
--- a/drivers/media/video/s5p-g2d/g2d.c
+++ b/drivers/media/video/s5p-g2d/g2d.c
@@ -762,6 +762,10 @@ static int g2d_probe(struct platform_device *pdev)
goto unreg_v4l2_dev;
}
*vfd = g2d_videodev;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
vfd->lock = &dev->mutex;
ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
if (ret) {
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c
index 5a49c30..ecf7b0b 100644
--- a/drivers/media/video/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
@@ -1386,6 +1386,10 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
jpeg->vfd_encoder->release = video_device_release;
jpeg->vfd_encoder->lock = &jpeg->lock;
jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &jpeg->vfd_encoder->flags);
ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
if (ret) {
@@ -1413,6 +1417,10 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
jpeg->vfd_decoder->release = video_device_release;
jpeg->vfd_decoder->lock = &jpeg->lock;
jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev;
+ /* Locking in file operations other than ioctl should be done by the driver,
+ not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &jpeg->vfd_decoder->flags);
ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
if (ret) {
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
index 83fe461..7600854 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
@@ -1048,6 +1048,10 @@ static int s5p_mfc_probe(struct platform_device *pdev)
vfd->ioctl_ops = get_dec_v4l2_ioctl_ops();
vfd->release = video_device_release,
vfd->lock = &dev->mfc_mutex;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
vfd->v4l2_dev = &dev->v4l2_dev;
snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
dev->vfd_dec = vfd;
@@ -1072,6 +1076,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
vfd->ioctl_ops = get_enc_v4l2_ioctl_ops();
vfd->release = video_device_release,
vfd->lock = &dev->mfc_mutex;
+ /* This should not be necessary */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
vfd->v4l2_dev = &dev->v4l2_dev;
snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
dev->vfd_enc = vfd;
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
index f7ca5cc..c0eadd7 100644
--- a/drivers/media/video/s5p-tv/mixer_video.c
+++ b/drivers/media/video/s5p-tv/mixer_video.c
@@ -1069,6 +1069,10 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
set_bit(V4L2_FL_USE_FH_PRIO, &layer->vfd.flags);
video_set_drvdata(&layer->vfd, layer);
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &layer->vfd.flags);
layer->vfd.lock = &layer->mutex;
layer->vfd.v4l2_dev = &mdev->v4l2_dev;
diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c
index 9644bd8..8fd1874 100644
--- a/drivers/media/video/sh_vou.c
+++ b/drivers/media/video/sh_vou.c
@@ -1390,6 +1390,10 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
vdev->v4l2_dev = &vou_dev->v4l2_dev;
vdev->release = video_device_release;
vdev->lock = &vou_dev->fop_lock;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags);
vou_dev->vdev = vdev;
video_set_drvdata(vdev, vou_dev);
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index eb25756..c27bb6d 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -1425,6 +1425,10 @@ static int video_dev_create(struct soc_camera_device *icd)
vdev->tvnorms = V4L2_STD_UNKNOWN;
vdev->ctrl_handler = &icd->ctrl_handler;
vdev->lock = &icd->video_lock;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags);
icd->vdev = vdev;
diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c
index 1ba26d5..375f26a 100644
--- a/drivers/media/video/tm6000/tm6000-video.c
+++ b/drivers/media/video/tm6000/tm6000-video.c
@@ -1731,6 +1731,10 @@ static struct video_device *vdev_init(struct tm6000_core *dev,
vfd->release = video_device_release;
vfd->debug = tm6000_debug;
vfd->lock = &dev->lock;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index 5a74f5e..9bd8f08 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1296,6 +1296,10 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
if (NULL == vdev)
return NULL;
*vdev = *vdev_template;
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags);
vdev->lock = &usbvision->v4l2_lock;
vdev->v4l2_dev = &usbvision->v4l2_dev;
snprintf(vdev->name, sizeof(vdev->name), "%s", name);
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 4d98ee1..5b819c9 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -274,11 +274,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
if (!vdev->fops->read)
return -EINVAL;
- if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) &&
+ mutex_lock_interruptible(vdev->lock))
return -ERESTARTSYS;
if (video_is_registered(vdev))
ret = vdev->fops->read(filp, buf, sz, off);
- if (vdev->lock)
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
mutex_unlock(vdev->lock);
return ret;
}
@@ -291,11 +292,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
if (!vdev->fops->write)
return -EINVAL;
- if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) &&
+ mutex_lock_interruptible(vdev->lock))
return -ERESTARTSYS;
if (video_is_registered(vdev))
ret = vdev->fops->write(filp, buf, sz, off);
- if (vdev->lock)
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
mutex_unlock(vdev->lock);
return ret;
}
@@ -307,11 +309,11 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
if (!vdev->fops->poll)
return DEFAULT_POLLMASK;
- if (vdev->lock)
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
mutex_lock(vdev->lock);
if (video_is_registered(vdev))
ret = vdev->fops->poll(filp, poll);
- if (vdev->lock)
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
mutex_unlock(vdev->lock);
return ret;
}
@@ -399,11 +401,12 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
if (!vdev->fops->mmap)
return ret;
- if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) &&
+ mutex_lock_interruptible(vdev->lock))
return -ERESTARTSYS;
if (video_is_registered(vdev))
ret = vdev->fops->mmap(filp, vm);
- if (vdev->lock)
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
mutex_unlock(vdev->lock);
return ret;
}
@@ -426,7 +429,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
video_get(vdev);
mutex_unlock(&videodev_lock);
if (vdev->fops->open) {
- if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) &&
+ mutex_lock_interruptible(vdev->lock)) {
ret = -ERESTARTSYS;
goto err;
}
@@ -434,7 +438,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
ret = vdev->fops->open(filp);
else
ret = -ENODEV;
- if (vdev->lock)
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
mutex_unlock(vdev->lock);
}
@@ -452,10 +456,10 @@ static int v4l2_release(struct inode *inode, struct file *filp)
int ret = 0;
if (vdev->fops->release) {
- if (vdev->lock)
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
mutex_lock(vdev->lock);
vdev->fops->release(filp);
- if (vdev->lock)
+ if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
mutex_unlock(vdev->lock);
}
/* decrease the refcount unconditionally since the release()
@@ -831,6 +835,10 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
WARN_ON(video_device[vdev->minor] != NULL);
vdev->index = get_index(vdev);
mutex_unlock(&videodev_lock);
+ /* if no lock was passed, then make sure the LOCK_ALL_FOPS bit is
+ clear and warn if it wasn't. */
+ if (vdev->lock == NULL)
+ WARN_ON(test_and_clear_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags));
determine_valid_ioctls(vdev);
diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
index 280c84e..c365cdf 100644
--- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
+++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
@@ -898,6 +898,10 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&pd->dmaq);
mutex_init(&pd->mux);
pd->vdev->lock = &pd->mux; /* for locking v4l2_file_operations */
+ /* Locking in file operations other than ioctl should be done
+ by the driver, not the V4L2 core.
+ This driver needs auditing so that this flag can be removed. */
+ set_bit(V4L2_FL_LOCK_ALL_FOPS, &pd->vdev->flags);
spin_lock_init(&pd->lock);
pd->csr2 = csr2_init;
pd->config = config_init;
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 15e2fe4..9eb970b 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -39,6 +39,9 @@ struct v4l2_ctrl_handler;
#define V4L2_FL_USES_V4L2_FH (1)
/* Use the prio field of v4l2_fh for core priority checking */
#define V4L2_FL_USE_FH_PRIO (2)
+/* If ioctl core locking is in use, then apply that also to all
+ file operations. */
+#define V4L2_FL_LOCK_ALL_FOPS (3)
/* Priority helper functions */
--
1.7.10
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [RFCv1 PATCH 5/5] v4l2-dev: add flag to have the core lock all file operations.
2012-05-10 7:05 ` [RFCv1 PATCH 5/5] v4l2-dev: add flag to have the core lock all file operations Hans Verkuil
@ 2012-05-10 8:14 ` Hans de Goede
2012-05-14 12:31 ` Laurent Pinchart
1 sibling, 0 replies; 20+ messages in thread
From: Hans de Goede @ 2012-05-10 8:14 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Mauro Carvalho Chehab, Hans Verkuil
Hi,
Looks good, ack.
Acked-by: Hans de Goede <hdegoede@redhat.com>
Regards,
Hans
On 05/10/2012 09:05 AM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> This used to be the default if the lock pointer was set, but now that lock is by
> default only used for ioctl serialization. Those drivers that already used
> core locking have this flag set explicitly, except for some drivers where
> it was obvious that there was no need to serialize any file operations other
> than ioctl.
>
> The drivers that didn't need this flag were:
>
> drivers/media/radio/dsbr100.c
> drivers/media/radio/radio-isa.c
> drivers/media/radio/radio-keene.c
> drivers/media/radio/radio-miropcm20.c
> drivers/media/radio/radio-mr800.c
> drivers/media/radio/radio-tea5764.c
> drivers/media/radio/radio-timb.c
> drivers/media/video/vivi.c
> sound/i2c/other/tea575x-tuner.c
>
> The other drivers that use core locking and where it was not immediately
> obvious that this flag wasn't needed were changed so that the flag is set
> together with a comment that that driver needs work to avoid having to
> set that flag. This will often involve taking the core lock in the fops
> themselves.
>
> Eventually this flag should go and it should not be used in new drivers.
>
> There are a few reasons why we want to avoid core locking of non-ioctl
> fops: in the case of mmap this can lead to a deadlock in rare situations
> since when mmap is called the mmap_sem is held and it is possible for
> other parts of the code to take that lock as well (copy_from_user()/copy_to_user()
> perform a down_read(&mm->mmap_sem) when a page fault occurs).
>
> It is very unlikely that that happens since the core lock serializes all
> fops, but the kernel warns about it if lock validation is turned on.
>
> For poll it is also undesirable to take the core lock as that can introduce
> increased latency. The same is true for read/write.
>
> While it was possible to make flags or something to turn on/off taking the
> core lock for each file operation, in practice it is much simpler to just
> not take it at all except for ioctl and leave it to the driver to take the
> lock. There are only a handful fops compared to the zillion ioctls we have.
>
> I also wanted to make it obvious which drivers still take the lock for all
> fops, so that's why I chose to have drivers set it explicitly.
>
> Signed-off-by: Hans Verkuil<hans.verkuil@cisco.com>
> ---
> drivers/media/common/saa7146_fops.c | 4 +++
> drivers/media/radio/wl128x/fmdrv_v4l2.c | 4 +++
> drivers/media/video/blackfin/bfin_capture.c | 4 +++
> drivers/media/video/cpia2/cpia2_v4l.c | 4 +++
> drivers/media/video/cx231xx/cx231xx-video.c | 4 +++
> drivers/media/video/davinci/vpbe_display.c | 4 +++
> drivers/media/video/davinci/vpif_capture.c | 4 +++
> drivers/media/video/davinci/vpif_display.c | 4 +++
> drivers/media/video/em28xx/em28xx-video.c | 4 +++
> drivers/media/video/fsl-viu.c | 4 +++
> drivers/media/video/ivtv/ivtv-streams.c | 4 +++
> drivers/media/video/mem2mem_testdev.c | 4 +++
> drivers/media/video/mx2_emmaprp.c | 4 +++
> drivers/media/video/s2255drv.c | 4 +++
> drivers/media/video/s5p-fimc/fimc-capture.c | 4 +++
> drivers/media/video/s5p-fimc/fimc-core.c | 4 +++
> drivers/media/video/s5p-g2d/g2d.c | 4 +++
> drivers/media/video/s5p-jpeg/jpeg-core.c | 8 ++++++
> drivers/media/video/s5p-mfc/s5p_mfc.c | 6 +++++
> drivers/media/video/s5p-tv/mixer_video.c | 4 +++
> drivers/media/video/sh_vou.c | 4 +++
> drivers/media/video/soc_camera.c | 4 +++
> drivers/media/video/tm6000/tm6000-video.c | 4 +++
> drivers/media/video/usbvision/usbvision-video.c | 4 +++
> drivers/media/video/v4l2-dev.c | 32 ++++++++++++++---------
> drivers/staging/media/dt3155v4l/dt3155v4l.c | 4 +++
> include/media/v4l2-dev.h | 3 +++
> 27 files changed, 129 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
> index 71f8e01..8d7df1a 100644
> --- a/drivers/media/common/saa7146_fops.c
> +++ b/drivers/media/common/saa7146_fops.c
> @@ -511,6 +511,10 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
> vfd->fops =&video_fops;
> vfd->ioctl_ops =&dev->ext_vv_data->ops;
> vfd->release = video_device_release;
> + /* Locking in file operations other than ioctl should be done by
> + the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
> vfd->lock =&dev->v4l2_lock;
> vfd->tvnorms = 0;
> for (i = 0; i< dev->ext_vv_data->num_stds; i++)
> diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
> index 077d369..080b96a 100644
> --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
> +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
> @@ -518,6 +518,10 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
> video_set_drvdata(gradio_dev, fmdev);
>
> gradio_dev->lock =&fmdev->mutex;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&gradio_dev->flags);
>
> /* Register with V4L2 subsystem as RADIO device */
> if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
> diff --git a/drivers/media/video/blackfin/bfin_capture.c b/drivers/media/video/blackfin/bfin_capture.c
> index 514fcf7..0aba45e 100644
> --- a/drivers/media/video/blackfin/bfin_capture.c
> +++ b/drivers/media/video/blackfin/bfin_capture.c
> @@ -942,6 +942,10 @@ static int __devinit bcap_probe(struct platform_device *pdev)
> INIT_LIST_HEAD(&bcap_dev->dma_queue);
>
> vfd->lock =&bcap_dev->mutex;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
>
> /* register video device */
> ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1);
> diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
> index bb4f1d0..55e9290 100644
> --- a/drivers/media/video/cpia2/cpia2_v4l.c
> +++ b/drivers/media/video/cpia2/cpia2_v4l.c
> @@ -1147,6 +1147,10 @@ int cpia2_register_camera(struct camera_data *cam)
> cam->vdev.ctrl_handler = hdl;
> cam->vdev.v4l2_dev =&cam->v4l2_dev;
> set_bit(V4L2_FL_USE_FH_PRIO,&cam->vdev.flags);
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&cam->vdev.flags);
>
> reset_camera_struct_v4l(cam);
>
> diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
> index 7f916f0..2a04558 100644
> --- a/drivers/media/video/cx231xx/cx231xx-video.c
> +++ b/drivers/media/video/cx231xx/cx231xx-video.c
> @@ -2561,6 +2561,10 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
> vfd->release = video_device_release;
> vfd->debug = video_debug;
> vfd->lock =&dev->lock;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
>
> snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
>
> diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c
> index 1f3b1c7..e106b72 100644
> --- a/drivers/media/video/davinci/vpbe_display.c
> +++ b/drivers/media/video/davinci/vpbe_display.c
> @@ -1618,6 +1618,10 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
> vbd->ioctl_ops =&vpbe_ioctl_ops;
> vbd->minor = -1;
> vbd->v4l2_dev =&disp_dev->vpbe_dev->v4l2_dev;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vbd->flags);
> vbd->lock =&vpbe_display_layer->opslock;
>
> if (disp_dev->vpbe_dev->current_timings.timings_type&
> diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c
> index 6504e40..9604695 100644
> --- a/drivers/media/video/davinci/vpif_capture.c
> +++ b/drivers/media/video/davinci/vpif_capture.c
> @@ -2228,6 +2228,10 @@ static __init int vpif_probe(struct platform_device *pdev)
> common =&(ch->common[VPIF_VIDEO_INDEX]);
> spin_lock_init(&common->irqlock);
> mutex_init(&common->lock);
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&ch->video_dev->flags);
> ch->video_dev->lock =&common->lock;
> /* Initialize prio member of channel object */
> v4l2_prio_init(&ch->prio);
> diff --git a/drivers/media/video/davinci/vpif_display.c b/drivers/media/video/davinci/vpif_display.c
> index 7fa34b4..e6488ee 100644
> --- a/drivers/media/video/davinci/vpif_display.c
> +++ b/drivers/media/video/davinci/vpif_display.c
> @@ -1778,6 +1778,10 @@ static __init int vpif_probe(struct platform_device *pdev)
> v4l2_prio_init(&ch->prio);
> ch->common[VPIF_VIDEO_INDEX].fmt.type =
> V4L2_BUF_TYPE_VIDEO_OUTPUT;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&ch->video_dev->flags);
> ch->video_dev->lock =&common->lock;
>
> /* register video device */
> diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
> index bcc4160..308a1dd 100644
> --- a/drivers/media/video/em28xx/em28xx-video.c
> +++ b/drivers/media/video/em28xx/em28xx-video.c
> @@ -2495,6 +2495,10 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
> vfd->release = video_device_release;
> vfd->debug = video_debug;
> vfd->lock =&dev->lock;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
>
> snprintf(vfd->name, sizeof(vfd->name), "%s %s",
> dev->name, type_name);
> diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c
> index 27e3e0c..777486f 100644
> --- a/drivers/media/video/fsl-viu.c
> +++ b/drivers/media/video/fsl-viu.c
> @@ -1544,6 +1544,10 @@ static int __devinit viu_of_probe(struct platform_device *op)
>
> /* initialize locks */
> mutex_init(&viu_dev->lock);
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&viu_dev->vdev->flags);
> viu_dev->vdev->lock =&viu_dev->lock;
> spin_lock_init(&viu_dev->slock);
>
> diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
> index 7ea5ca7..6738592 100644
> --- a/drivers/media/video/ivtv/ivtv-streams.c
> +++ b/drivers/media/video/ivtv/ivtv-streams.c
> @@ -228,6 +228,10 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
> s->vdev->release = video_device_release;
> s->vdev->tvnorms = V4L2_STD_ALL;
> s->vdev->lock =&itv->serialize_lock;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&s->vdev->flags);
> set_bit(V4L2_FL_USE_FH_PRIO,&s->vdev->flags);
> ivtv_set_funcs(s->vdev);
> return 0;
> diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c
> index 12897e8..ee3efbd 100644
> --- a/drivers/media/video/mem2mem_testdev.c
> +++ b/drivers/media/video/mem2mem_testdev.c
> @@ -958,6 +958,10 @@ static int m2mtest_probe(struct platform_device *pdev)
> }
>
> *vfd = m2mtest_videodev;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
> vfd->lock =&dev->dev_mutex;
>
> ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
> diff --git a/drivers/media/video/mx2_emmaprp.c b/drivers/media/video/mx2_emmaprp.c
> index 55ac173..0bd5815 100644
> --- a/drivers/media/video/mx2_emmaprp.c
> +++ b/drivers/media/video/mx2_emmaprp.c
> @@ -904,6 +904,10 @@ static int emmaprp_probe(struct platform_device *pdev)
> }
>
> *vfd = emmaprp_videodev;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
> vfd->lock =&pcdev->dev_mutex;
>
> video_set_drvdata(vfd, pcdev);
> diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
> index 37845de..ea974fa 100644
> --- a/drivers/media/video/s2255drv.c
> +++ b/drivers/media/video/s2255drv.c
> @@ -1948,6 +1948,10 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
> /* register 4 video devices */
> channel->vdev = template;
> channel->vdev.lock =&dev->lock;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&channel->vdev.flags);
> channel->vdev.v4l2_dev =&dev->v4l2_dev;
> video_set_drvdata(&channel->vdev, channel);
> if (video_nr == -1)
> diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
> index dc18ba5..72d5150 100644
> --- a/drivers/media/video/s5p-fimc/fimc-capture.c
> +++ b/drivers/media/video/s5p-fimc/fimc-capture.c
> @@ -1516,6 +1516,10 @@ int fimc_register_capture_device(struct fimc_dev *fimc,
> vfd->minor = -1;
> vfd->release = video_device_release;
> vfd->lock =&fimc->lock;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
> video_set_drvdata(vfd, fimc);
>
> vid_cap =&fimc->vid_cap;
> diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
> index 7b90a89..c58dd9f 100644
> --- a/drivers/media/video/s5p-fimc/fimc-core.c
> +++ b/drivers/media/video/s5p-fimc/fimc-core.c
> @@ -1520,6 +1520,10 @@ int fimc_register_m2m_device(struct fimc_dev *fimc,
> vfd->minor = -1;
> vfd->release = video_device_release;
> vfd->lock =&fimc->lock;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
>
> snprintf(vfd->name, sizeof(vfd->name), "%s.m2m", dev_name(&pdev->dev));
> video_set_drvdata(vfd, fimc);
> diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c
> index 789de74..02605ce 100644
> --- a/drivers/media/video/s5p-g2d/g2d.c
> +++ b/drivers/media/video/s5p-g2d/g2d.c
> @@ -762,6 +762,10 @@ static int g2d_probe(struct platform_device *pdev)
> goto unreg_v4l2_dev;
> }
> *vfd = g2d_videodev;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
> vfd->lock =&dev->mutex;
> ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
> if (ret) {
> diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c
> index 5a49c30..ecf7b0b 100644
> --- a/drivers/media/video/s5p-jpeg/jpeg-core.c
> +++ b/drivers/media/video/s5p-jpeg/jpeg-core.c
> @@ -1386,6 +1386,10 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
> jpeg->vfd_encoder->release = video_device_release;
> jpeg->vfd_encoder->lock =&jpeg->lock;
> jpeg->vfd_encoder->v4l2_dev =&jpeg->v4l2_dev;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&jpeg->vfd_encoder->flags);
>
> ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
> if (ret) {
> @@ -1413,6 +1417,10 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
> jpeg->vfd_decoder->release = video_device_release;
> jpeg->vfd_decoder->lock =&jpeg->lock;
> jpeg->vfd_decoder->v4l2_dev =&jpeg->v4l2_dev;
> + /* Locking in file operations other than ioctl should be done by the driver,
> + not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&jpeg->vfd_decoder->flags);
>
> ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
> if (ret) {
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
> index 83fe461..7600854 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
> @@ -1048,6 +1048,10 @@ static int s5p_mfc_probe(struct platform_device *pdev)
> vfd->ioctl_ops = get_dec_v4l2_ioctl_ops();
> vfd->release = video_device_release,
> vfd->lock =&dev->mfc_mutex;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
> vfd->v4l2_dev =&dev->v4l2_dev;
> snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
> dev->vfd_dec = vfd;
> @@ -1072,6 +1076,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
> vfd->ioctl_ops = get_enc_v4l2_ioctl_ops();
> vfd->release = video_device_release,
> vfd->lock =&dev->mfc_mutex;
> + /* This should not be necessary */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
> vfd->v4l2_dev =&dev->v4l2_dev;
> snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
> dev->vfd_enc = vfd;
> diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c
> index f7ca5cc..c0eadd7 100644
> --- a/drivers/media/video/s5p-tv/mixer_video.c
> +++ b/drivers/media/video/s5p-tv/mixer_video.c
> @@ -1069,6 +1069,10 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
> set_bit(V4L2_FL_USE_FH_PRIO,&layer->vfd.flags);
>
> video_set_drvdata(&layer->vfd, layer);
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&layer->vfd.flags);
> layer->vfd.lock =&layer->mutex;
> layer->vfd.v4l2_dev =&mdev->v4l2_dev;
>
> diff --git a/drivers/media/video/sh_vou.c b/drivers/media/video/sh_vou.c
> index 9644bd8..8fd1874 100644
> --- a/drivers/media/video/sh_vou.c
> +++ b/drivers/media/video/sh_vou.c
> @@ -1390,6 +1390,10 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
> vdev->v4l2_dev =&vou_dev->v4l2_dev;
> vdev->release = video_device_release;
> vdev->lock =&vou_dev->fop_lock;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags);
>
> vou_dev->vdev = vdev;
> video_set_drvdata(vdev, vou_dev);
> diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
> index eb25756..c27bb6d 100644
> --- a/drivers/media/video/soc_camera.c
> +++ b/drivers/media/video/soc_camera.c
> @@ -1425,6 +1425,10 @@ static int video_dev_create(struct soc_camera_device *icd)
> vdev->tvnorms = V4L2_STD_UNKNOWN;
> vdev->ctrl_handler =&icd->ctrl_handler;
> vdev->lock =&icd->video_lock;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags);
>
> icd->vdev = vdev;
>
> diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c
> index 1ba26d5..375f26a 100644
> --- a/drivers/media/video/tm6000/tm6000-video.c
> +++ b/drivers/media/video/tm6000/tm6000-video.c
> @@ -1731,6 +1731,10 @@ static struct video_device *vdev_init(struct tm6000_core *dev,
> vfd->release = video_device_release;
> vfd->debug = tm6000_debug;
> vfd->lock =&dev->lock;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vfd->flags);
>
> snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
>
> diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
> index 5a74f5e..9bd8f08 100644
> --- a/drivers/media/video/usbvision/usbvision-video.c
> +++ b/drivers/media/video/usbvision/usbvision-video.c
> @@ -1296,6 +1296,10 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
> if (NULL == vdev)
> return NULL;
> *vdev = *vdev_template;
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags);
> vdev->lock =&usbvision->v4l2_lock;
> vdev->v4l2_dev =&usbvision->v4l2_dev;
> snprintf(vdev->name, sizeof(vdev->name), "%s", name);
> diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
> index 4d98ee1..5b819c9 100644
> --- a/drivers/media/video/v4l2-dev.c
> +++ b/drivers/media/video/v4l2-dev.c
> @@ -274,11 +274,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
>
> if (!vdev->fops->read)
> return -EINVAL;
> - if (vdev->lock&& mutex_lock_interruptible(vdev->lock))
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags)&&
> + mutex_lock_interruptible(vdev->lock))
> return -ERESTARTSYS;
> if (video_is_registered(vdev))
> ret = vdev->fops->read(filp, buf, sz, off);
> - if (vdev->lock)
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags))
> mutex_unlock(vdev->lock);
> return ret;
> }
> @@ -291,11 +292,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
>
> if (!vdev->fops->write)
> return -EINVAL;
> - if (vdev->lock&& mutex_lock_interruptible(vdev->lock))
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags)&&
> + mutex_lock_interruptible(vdev->lock))
> return -ERESTARTSYS;
> if (video_is_registered(vdev))
> ret = vdev->fops->write(filp, buf, sz, off);
> - if (vdev->lock)
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags))
> mutex_unlock(vdev->lock);
> return ret;
> }
> @@ -307,11 +309,11 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
>
> if (!vdev->fops->poll)
> return DEFAULT_POLLMASK;
> - if (vdev->lock)
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags))
> mutex_lock(vdev->lock);
> if (video_is_registered(vdev))
> ret = vdev->fops->poll(filp, poll);
> - if (vdev->lock)
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags))
> mutex_unlock(vdev->lock);
> return ret;
> }
> @@ -399,11 +401,12 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
>
> if (!vdev->fops->mmap)
> return ret;
> - if (vdev->lock&& mutex_lock_interruptible(vdev->lock))
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags)&&
> + mutex_lock_interruptible(vdev->lock))
> return -ERESTARTSYS;
> if (video_is_registered(vdev))
> ret = vdev->fops->mmap(filp, vm);
> - if (vdev->lock)
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags))
> mutex_unlock(vdev->lock);
> return ret;
> }
> @@ -426,7 +429,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
> video_get(vdev);
> mutex_unlock(&videodev_lock);
> if (vdev->fops->open) {
> - if (vdev->lock&& mutex_lock_interruptible(vdev->lock)) {
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags)&&
> + mutex_lock_interruptible(vdev->lock)) {
> ret = -ERESTARTSYS;
> goto err;
> }
> @@ -434,7 +438,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
> ret = vdev->fops->open(filp);
> else
> ret = -ENODEV;
> - if (vdev->lock)
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags))
> mutex_unlock(vdev->lock);
> }
>
> @@ -452,10 +456,10 @@ static int v4l2_release(struct inode *inode, struct file *filp)
> int ret = 0;
>
> if (vdev->fops->release) {
> - if (vdev->lock)
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags))
> mutex_lock(vdev->lock);
> vdev->fops->release(filp);
> - if (vdev->lock)
> + if (test_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags))
> mutex_unlock(vdev->lock);
> }
> /* decrease the refcount unconditionally since the release()
> @@ -831,6 +835,10 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
> WARN_ON(video_device[vdev->minor] != NULL);
> vdev->index = get_index(vdev);
> mutex_unlock(&videodev_lock);
> + /* if no lock was passed, then make sure the LOCK_ALL_FOPS bit is
> + clear and warn if it wasn't. */
> + if (vdev->lock == NULL)
> + WARN_ON(test_and_clear_bit(V4L2_FL_LOCK_ALL_FOPS,&vdev->flags));
>
> determine_valid_ioctls(vdev);
>
> diff --git a/drivers/staging/media/dt3155v4l/dt3155v4l.c b/drivers/staging/media/dt3155v4l/dt3155v4l.c
> index 280c84e..c365cdf 100644
> --- a/drivers/staging/media/dt3155v4l/dt3155v4l.c
> +++ b/drivers/staging/media/dt3155v4l/dt3155v4l.c
> @@ -898,6 +898,10 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> INIT_LIST_HEAD(&pd->dmaq);
> mutex_init(&pd->mux);
> pd->vdev->lock =&pd->mux; /* for locking v4l2_file_operations */
> + /* Locking in file operations other than ioctl should be done
> + by the driver, not the V4L2 core.
> + This driver needs auditing so that this flag can be removed. */
> + set_bit(V4L2_FL_LOCK_ALL_FOPS,&pd->vdev->flags);
> spin_lock_init(&pd->lock);
> pd->csr2 = csr2_init;
> pd->config = config_init;
> diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
> index 15e2fe4..9eb970b 100644
> --- a/include/media/v4l2-dev.h
> +++ b/include/media/v4l2-dev.h
> @@ -39,6 +39,9 @@ struct v4l2_ctrl_handler;
> #define V4L2_FL_USES_V4L2_FH (1)
> /* Use the prio field of v4l2_fh for core priority checking */
> #define V4L2_FL_USE_FH_PRIO (2)
> +/* If ioctl core locking is in use, then apply that also to all
> + file operations. */
> +#define V4L2_FL_LOCK_ALL_FOPS (3)
>
> /* Priority helper functions */
>
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [RFCv1 PATCH 5/5] v4l2-dev: add flag to have the core lock all file operations.
2012-05-10 7:05 ` [RFCv1 PATCH 5/5] v4l2-dev: add flag to have the core lock all file operations Hans Verkuil
2012-05-10 8:14 ` Hans de Goede
@ 2012-05-14 12:31 ` Laurent Pinchart
2012-05-14 13:42 ` Hans Verkuil
1 sibling, 1 reply; 20+ messages in thread
From: Laurent Pinchart @ 2012-05-14 12:31 UTC (permalink / raw)
To: Hans Verkuil
Cc: linux-media, Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
Hi Hans,
Thanks for the patch.
On Thursday 10 May 2012 09:05:14 Hans Verkuil wrote:
> From: Hans Verkuil <hans.verkuil@cisco.com>
>
> This used to be the default if the lock pointer was set, but now that lock
> is by default only used for ioctl serialization.
Shouldn't that be documented ? Documentation/video4linux/v4l2-framework.txt
still states that the lock is taken for each file operation.
> Those drivers that already used core locking have this flag set explicitly,
> except for some drivers where it was obvious that there was no need to
> serialize any file operations other than ioctl.
>
> The drivers that didn't need this flag were:
>
> drivers/media/radio/dsbr100.c
> drivers/media/radio/radio-isa.c
> drivers/media/radio/radio-keene.c
> drivers/media/radio/radio-miropcm20.c
> drivers/media/radio/radio-mr800.c
> drivers/media/radio/radio-tea5764.c
> drivers/media/radio/radio-timb.c
> drivers/media/video/vivi.c
> sound/i2c/other/tea575x-tuner.c
Be careful that drivers for hot-pluggable devices can use the core lock to
serialize open/disconnect. The dsbr100 driver takes the core lock in its
disconnect handler for instance. Have you double-checked that no race
condition exists in those cases ?
> The other drivers that use core locking and where it was not immediately
> obvious that this flag wasn't needed were changed so that the flag is set
> together with a comment that that driver needs work to avoid having to
> set that flag. This will often involve taking the core lock in the fops
> themselves.
Or not using the core lock :-)
> Eventually this flag should go and it should not be used in new drivers.
Could you please add a comment above the flag to state that new drivers must
not use it ?
> There are a few reasons why we want to avoid core locking of non-ioctl
> fops: in the case of mmap this can lead to a deadlock in rare situations
> since when mmap is called the mmap_sem is held and it is possible for
> other parts of the code to take that lock as well
> (copy_from_user()/copy_to_user() perform a down_read(&mm->mmap_sem) when a
> page fault occurs).
This patch won't solve the problem. We have (at least) two AB-BA deadlock
issues with the mm->mmap_sem. Both of them share the fact that the mmap()
handler is called with mm->mmap_sem held and will then take a device-related
lock (could be a global driver lock, a device-wide lock or a queue-specific
lock). I don't think we can do anything about that.
The first problem was solved some time ago. VIDIOC_QBUF is called with the
same device-related lock held and then needs to take mm->mmap_sem. We solved
that be calling the queue wait_prepare() and wait_finish() around down(&mm-
>mmap_sem) and up(&mm->mmap_sem). Maybe not ideal, but that seems to work.
The second problem comes from the copy_from_user()/copy_to_user() code in
video_usercopy(). That function is called by video_ioctl2() which is itself
called with the device lock held. Copying from/to user can fault if the
userspace memory has been paged out, in which case the fault handler needs to
take mm->mmap_sem to solve the fault. This can deadlock with mmap().
To solve the second issue we must delay taking the device lock until after
copying from user, as we can't forbid the mmap() handler from taking the
device lock (that would introduce race conditions). I think that can be done
by pushing the device lock into __video_do_ioctl.
> It is very unlikely that that happens since the core lock serializes all
> fops, but the kernel warns about it if lock validation is turned on.
>
> For poll it is also undesirable to take the core lock as that can introduce
> increased latency. The same is true for read/write.
>
> While it was possible to make flags or something to turn on/off taking the
> core lock for each file operation, in practice it is much simpler to just
> not take it at all except for ioctl and leave it to the driver to take the
> lock. There are only a handful fops compared to the zillion ioctls we have.
>
> I also wanted to make it obvious which drivers still take the lock for all
> fops, so that's why I chose to have drivers set it explicitly.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFCv1 PATCH 5/5] v4l2-dev: add flag to have the core lock all file operations.
2012-05-14 12:31 ` Laurent Pinchart
@ 2012-05-14 13:42 ` Hans Verkuil
2012-05-14 14:12 ` Laurent Pinchart
0 siblings, 1 reply; 20+ messages in thread
From: Hans Verkuil @ 2012-05-14 13:42 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-media, Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
Hi Laurent,
Thanks for the review!
On Mon May 14 2012 14:31:32 Laurent Pinchart wrote:
> Hi Hans,
>
> Thanks for the patch.
>
> On Thursday 10 May 2012 09:05:14 Hans Verkuil wrote:
> > From: Hans Verkuil <hans.verkuil@cisco.com>
> >
> > This used to be the default if the lock pointer was set, but now that lock
> > is by default only used for ioctl serialization.
>
> Shouldn't that be documented ? Documentation/video4linux/v4l2-framework.txt
> still states that the lock is taken for each file operation.
I'd have sworn I'd done that, but obviously my memory is playing tricks on me.
Will fix.
> > Those drivers that already used core locking have this flag set explicitly,
> > except for some drivers where it was obvious that there was no need to
> > serialize any file operations other than ioctl.
> >
> > The drivers that didn't need this flag were:
> >
> > drivers/media/radio/dsbr100.c
> > drivers/media/radio/radio-isa.c
> > drivers/media/radio/radio-keene.c
> > drivers/media/radio/radio-miropcm20.c
> > drivers/media/radio/radio-mr800.c
> > drivers/media/radio/radio-tea5764.c
> > drivers/media/radio/radio-timb.c
> > drivers/media/video/vivi.c
> > sound/i2c/other/tea575x-tuner.c
>
> Be careful that drivers for hot-pluggable devices can use the core lock to
> serialize open/disconnect. The dsbr100 driver takes the core lock in its
> disconnect handler for instance. Have you double-checked that no race
> condition exists in those cases ?
Yes. This drivers use core helper functions for open/release/poll where we
know that there is no race condition.
>
> > The other drivers that use core locking and where it was not immediately
> > obvious that this flag wasn't needed were changed so that the flag is set
> > together with a comment that that driver needs work to avoid having to
> > set that flag. This will often involve taking the core lock in the fops
> > themselves.
>
> Or not using the core lock :-)
>
> > Eventually this flag should go and it should not be used in new drivers.
>
> Could you please add a comment above the flag to state that new drivers must
> not use it ?
Good one. Will do.
> > There are a few reasons why we want to avoid core locking of non-ioctl
> > fops: in the case of mmap this can lead to a deadlock in rare situations
> > since when mmap is called the mmap_sem is held and it is possible for
> > other parts of the code to take that lock as well
> > (copy_from_user()/copy_to_user() perform a down_read(&mm->mmap_sem) when a
> > page fault occurs).
>
> This patch won't solve the problem. We have (at least) two AB-BA deadlock
> issues with the mm->mmap_sem. Both of them share the fact that the mmap()
> handler is called with mm->mmap_sem held and will then take a device-related
> lock (could be a global driver lock, a device-wide lock or a queue-specific
> lock). I don't think we can do anything about that.
>
> The first problem was solved some time ago. VIDIOC_QBUF is called with the
> same device-related lock held and then needs to take mm->mmap_sem. We solved
> that be calling the queue wait_prepare() and wait_finish() around down(&mm-
> >mmap_sem) and up(&mm->mmap_sem). Maybe not ideal, but that seems to work.
>
> The second problem comes from the copy_from_user()/copy_to_user() code in
> video_usercopy(). That function is called by video_ioctl2() which is itself
> called with the device lock held. Copying from/to user can fault if the
> userspace memory has been paged out, in which case the fault handler needs to
> take mm->mmap_sem to solve the fault. This can deadlock with mmap().
>
> To solve the second issue we must delay taking the device lock until after
> copying from user, as we can't forbid the mmap() handler from taking the
> device lock (that would introduce race conditions). I think that can be done
> by pushing the device lock into __video_do_ioctl.
Good idea, but for 3.6. This will be a nice one to combine with my v4l2-ioctl.c
reorganization.
Regards,
Hans
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFCv1 PATCH 5/5] v4l2-dev: add flag to have the core lock all file operations.
2012-05-14 13:42 ` Hans Verkuil
@ 2012-05-14 14:12 ` Laurent Pinchart
0 siblings, 0 replies; 20+ messages in thread
From: Laurent Pinchart @ 2012-05-14 14:12 UTC (permalink / raw)
To: Hans Verkuil
Cc: linux-media, Mauro Carvalho Chehab, Hans de Goede, Hans Verkuil
Hi Hans,
On Monday 14 May 2012 15:42:37 Hans Verkuil wrote:
> On Mon May 14 2012 14:31:32 Laurent Pinchart wrote:
> > On Thursday 10 May 2012 09:05:14 Hans Verkuil wrote:
> > > From: Hans Verkuil <hans.verkuil@cisco.com>
> > >
> > > This used to be the default if the lock pointer was set, but now that
> > > lock is by default only used for ioctl serialization.
> >
> > Shouldn't that be documented ?
> > Documentation/video4linux/v4l2-framework.txt
> > still states that the lock is taken for each file operation.
>
> I'd have sworn I'd done that, but obviously my memory is playing tricks on
> me.
>
> Will fix.
Thanks.
> > > Those drivers that already used core locking have this flag set
> > > explicitly, except for some drivers where it was obvious that there was
> > > no need to serialize any file operations other than ioctl.
> > >
> > > The drivers that didn't need this flag were:
> > >
> > > drivers/media/radio/dsbr100.c
> > > drivers/media/radio/radio-isa.c
> > > drivers/media/radio/radio-keene.c
> > > drivers/media/radio/radio-miropcm20.c
> > > drivers/media/radio/radio-mr800.c
> > > drivers/media/radio/radio-tea5764.c
> > > drivers/media/radio/radio-timb.c
> > > drivers/media/video/vivi.c
> > > sound/i2c/other/tea575x-tuner.c
> >
> > Be careful that drivers for hot-pluggable devices can use the core lock to
> > serialize open/disconnect. The dsbr100 driver takes the core lock in its
> > disconnect handler for instance. Have you double-checked that no race
> > condition exists in those cases ?
>
> Yes. This drivers use core helper functions for open/release/poll where we
> know that there is no race condition.
>
> > > The other drivers that use core locking and where it was not immediately
> > > obvious that this flag wasn't needed were changed so that the flag is
> > > set together with a comment that that driver needs work to avoid having
> > > to set that flag. This will often involve taking the core lock in the
> > > fops themselves.
> >
> > Or not using the core lock :-)
> >
> > > Eventually this flag should go and it should not be used in new drivers.
> >
> > Could you please add a comment above the flag to state that new drivers
> > must not use it ?
>
> Good one. Will do.
>
> > > There are a few reasons why we want to avoid core locking of non-ioctl
> > > fops: in the case of mmap this can lead to a deadlock in rare situations
> > > since when mmap is called the mmap_sem is held and it is possible for
> > > other parts of the code to take that lock as well
> > > (copy_from_user()/copy_to_user() perform a down_read(&mm->mmap_sem) when
> > > a page fault occurs).
> >
> > This patch won't solve the problem. We have (at least) two AB-BA deadlock
> > issues with the mm->mmap_sem. Both of them share the fact that the mmap()
> > handler is called with mm->mmap_sem held and will then take a
> > device-related lock (could be a global driver lock, a device-wide lock or
> > a queue-specific lock). I don't think we can do anything about that.
> >
> > The first problem was solved some time ago. VIDIOC_QBUF is called with the
> > same device-related lock held and then needs to take mm->mmap_sem. We
> > solved that be calling the queue wait_prepare() and wait_finish() around
> > down(&mm->
> > >mmap_sem) and up(&mm->mmap_sem). Maybe not ideal, but that seems to work.
> >
> > The second problem comes from the copy_from_user()/copy_to_user() code in
> > video_usercopy(). That function is called by video_ioctl2() which is
> > itself called with the device lock held. Copying from/to user can fault if
> > the userspace memory has been paged out, in which case the fault handler
> > needs to take mm->mmap_sem to solve the fault. This can deadlock with
> > mmap().
> >
> > To solve the second issue we must delay taking the device lock until after
> > copying from user, as we can't forbid the mmap() handler from taking the
> > device lock (that would introduce race conditions). I think that can be
> > done by pushing the device lock into __video_do_ioctl.
>
> Good idea, but for 3.6. This will be a nice one to combine with my
> v4l2-ioctl.c reorganization.
I'm fine with 3.6, but then I'd appreciate if you could reword your commit
message. It gives the false impression that this commit solves the issue.
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFCv1 PATCH 1/5] v4l2-dev: make it possible to skip locking for selected ioctls.
2012-05-10 7:05 ` [RFCv1 PATCH 1/5] v4l2-dev: make it possible to skip locking for selected ioctls Hans Verkuil
` (3 preceding siblings ...)
2012-05-10 7:05 ` [RFCv1 PATCH 5/5] v4l2-dev: add flag to have the core lock all file operations Hans Verkuil
@ 2012-05-10 8:00 ` Hans de Goede
4 siblings, 0 replies; 20+ messages in thread
From: Hans de Goede @ 2012-05-10 8:00 UTC (permalink / raw)
To: Hans Verkuil; +Cc: linux-media, Mauro Carvalho Chehab, Hans Verkuil
Hi,
Looks good, ack.
Acked-by: Hans de Goede <hdegoede@redhat.com>
Regards,
Hans
On 05/10/2012 09:05 AM, Hans Verkuil wrote:
> From: Hans Verkuil<hans.verkuil@cisco.com>
>
> 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>
> ---
> Documentation/video4linux/v4l2-framework.txt | 27 +++-
> drivers/media/video/v4l2-dev.c | 14 +-
> drivers/media/video/v4l2-ioctl.c | 189 ++++++++++++++------------
> include/media/v4l2-dev.h | 11 ++
> 4 files changed, 148 insertions(+), 93 deletions(-)
>
> diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
> index 369d4bc..4b9b407 100644
> --- a/Documentation/video4linux/v4l2-framework.txt
> +++ b/Documentation/video4linux/v4l2-framework.txt
> @@ -559,19 +559,25 @@ allocated memory.
> You should also set these fields:
>
> - v4l2_dev: set to the v4l2_device parent device.
> +
> - name: set to something descriptive and unique.
> +
> - fops: set to the v4l2_file_operations struct.
> +
> - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
> (highly recommended to use this and it might become compulsory in the
> future!), then set this to your v4l2_ioctl_ops struct.
> +
> - lock: leave to NULL if you want to do all the locking in the driver.
> Otherwise you give it a pointer to a struct mutex_lock and before any
> of the v4l2_file_operations is called this lock will be taken by the
> - core and released afterwards.
> + core and released afterwards. See the next section for more details.
> +
> - prio: keeps track of the priorities. Used to implement VIDIOC_G/S_PRIORITY.
> If left to NULL, then it will use the struct v4l2_prio_state in v4l2_device.
> If you want to have a separate priority state per (group of) device node(s),
> then you can point it to your own struct v4l2_prio_state.
> +
> - parent: you only set this if v4l2_device was registered with NULL as
> the parent device struct. This only happens in cases where one hardware
> device has multiple PCI devices that all share the same v4l2_device core.
> @@ -581,6 +587,7 @@ You should also set these fields:
> (cx8802). Since the v4l2_device cannot be associated with a particular
> PCI device it is setup without a parent device. But when the struct
> video_device is setup you do know which parent PCI device to use.
> +
> - flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework
> handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct
> v4l2_fh. Eventually this flag will disappear once all drivers use the core
> @@ -613,8 +620,22 @@ v4l2_file_operations and locking
> --------------------------------
>
> You can set a pointer to a mutex_lock in struct video_device. Usually this
> -will be either a top-level mutex or a mutex per device node. If you want
> -finer-grained locking then you have to set it to NULL and do you own locking.
> +will be either a top-level mutex or a mutex per device node. By default this
> +lock will be used for each file operation and ioctl, but you can disable
> +locking for selected ioctls by calling:
> +
> + void v4l2_dont_use_lock(struct video_device *vdev, unsigned int cmd);
> +
> +E.g.: v4l2_dont_use_lock(vdev, VIDIOC_DQBUF);
> +
> +You have to call this before you register the video_device.
> +
> +Particularly with USB drivers where certain commands such as setting controls
> +can take a long time you may want to do your own locking for the buffer queuing
> +ioctls.
> +
> +If you want still finer-grained locking then you have to set mutex_lock to NULL
> +and do you own locking completely.
>
> It is up to the driver developer to decide which method to use. However, if
> your driver has high-latency operations (for example, changing the exposure
> diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
> index 70bec54..a51a061 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_valid_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 5b2ec1f..3f34098 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_valid_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;
> diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
> index 96d2221..0da84dc 100644
> --- a/include/media/v4l2-dev.h
> +++ b/include/media/v4l2-dev.h
> @@ -128,6 +128,7 @@ struct video_device
> const struct v4l2_ioctl_ops *ioctl_ops;
>
> /* serialization lock */
> + DECLARE_BITMAP(dont_use_lock, BASE_VIDIOC_PRIVATE);
> struct mutex *lock;
> };
>
> @@ -173,6 +174,16 @@ void video_device_release(struct video_device *vdev);
> a dubious construction at best. */
> void video_device_release_empty(struct video_device *vdev);
>
> +/* returns true if cmd is a valid V4L2 ioctl */
> +bool v4l2_is_valid_ioctl(unsigned int cmd);
> +
> +/* mark that this command shouldn't use core locking */
> +static inline void v4l2_dont_use_lock(struct video_device *vdev, unsigned int cmd)
> +{
> + if (_IOC_NR(cmd)< BASE_VIDIOC_PRIVATE)
> + set_bit(_IOC_NR(cmd), vdev->dont_use_lock);
> +}
> +
> /* helper functions to access driver private data. */
> static inline void *video_get_drvdata(struct video_device *vdev)
> {
^ permalink raw reply [flat|nested] 20+ messages in thread