On Tue Jun 9 11:47:56 2026 +0300, Sakari Ailus wrote:
> In anticipation of performing work for sub-device operation when the
> driver doesn't implement one, move the check of operation existence to the
> wrapper itself.
> 
> No functional change intended.
> 
> Signed-off-by: Sakari Ailus <[email protected]>
> Reviewed-by: Laurent Pinchart <[email protected]>

Patch committed.

Thanks,
Sakari Ailus

 drivers/media/v4l2-core/v4l2-subdev.c | 92 +++++++++++++++++++++--------------
 include/media/v4l2-subdev.h           |  6 ++-
 2 files changed, 59 insertions(+), 39 deletions(-)

---

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c 
b/drivers/media/v4l2-core/v4l2-subdev.c
index f392586d5dba..f53bac995822 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -244,20 +244,32 @@ static inline int check_format(struct v4l2_subdev *sd,
               check_state(sd, state, format->which, format->pad, 
format->stream);
 }
 
+#define do_subdev_call(sd, check, o, f, args...)       \
+       (!(sd)->ops->o->f ? -ENOIOCTLCMD : (check) ? :  \
+        (sd)->ops->o->f(sd, ##args))
+
 static int call_get_fmt(struct v4l2_subdev *sd,
                        struct v4l2_subdev_state *state,
                        struct v4l2_subdev_format *format)
 {
-       return check_format(sd, state, format) ? :
-              sd->ops->pad->get_fmt(sd, state, format);
+       return do_subdev_call(sd, check_format(sd, state, format), pad, get_fmt,
+                             state, format);
 }
 
 static int call_set_fmt(struct v4l2_subdev *sd,
                        struct v4l2_subdev_state *state,
                        struct v4l2_subdev_format *format)
 {
-       return check_format(sd, state, format) ? :
-              sd->ops->pad->set_fmt(sd, state, format);
+       return do_subdev_call(sd, check_format(sd, state, format), pad, set_fmt,
+                             state, format);
+}
+
+static int check_which_pad_state(struct v4l2_subdev *sd,
+                                struct v4l2_subdev_state *state, u32 which,
+                                u32 pad, u32 stream)
+{
+       return check_which(which) ? : check_pad(sd, pad) ? :
+               check_state(sd, state, which, pad, stream);
 }
 
 static int call_enum_mbus_code(struct v4l2_subdev *sd,
@@ -267,9 +279,9 @@ static int call_enum_mbus_code(struct v4l2_subdev *sd,
        if (!code)
                return -EINVAL;
 
-       return check_which(code->which) ? : check_pad(sd, code->pad) ? :
-              check_state(sd, state, code->which, code->pad, code->stream) ? :
-              sd->ops->pad->enum_mbus_code(sd, state, code);
+       return do_subdev_call(sd, check_which_pad_state(sd, state, code->which,
+                                                       code->pad, 
code->stream),
+                             pad, enum_mbus_code, state, code);
 }
 
 static int call_enum_frame_size(struct v4l2_subdev *sd,
@@ -279,9 +291,9 @@ static int call_enum_frame_size(struct v4l2_subdev *sd,
        if (!fse)
                return -EINVAL;
 
-       return check_which(fse->which) ? : check_pad(sd, fse->pad) ? :
-              check_state(sd, state, fse->which, fse->pad, fse->stream) ? :
-              sd->ops->pad->enum_frame_size(sd, state, fse);
+       return do_subdev_call(sd, check_which_pad_state(sd, state, fse->which,
+                                                       fse->pad, fse->stream),
+                             pad, enum_frame_size, state, fse);
 }
 
 static int call_enum_frame_interval(struct v4l2_subdev *sd,
@@ -291,9 +303,9 @@ static int call_enum_frame_interval(struct v4l2_subdev *sd,
        if (!fie)
                return -EINVAL;
 
-       return check_which(fie->which) ? : check_pad(sd, fie->pad) ? :
-              check_state(sd, state, fie->which, fie->pad, fie->stream) ? :
-              sd->ops->pad->enum_frame_interval(sd, state, fie);
+       return do_subdev_call(sd, check_which_pad_state(sd, state, fie->which,
+                                                       fie->pad, fie->stream),
+                             pad, enum_frame_interval, state, fie);
 }
 
 static inline int check_selection(struct v4l2_subdev *sd,
@@ -311,16 +323,16 @@ static int call_get_selection(struct v4l2_subdev *sd,
                              struct v4l2_subdev_state *state,
                              struct v4l2_subdev_selection *sel)
 {
-       return check_selection(sd, state, sel) ? :
-              sd->ops->pad->get_selection(sd, state, sel);
+       return do_subdev_call(sd, check_selection(sd, state, sel),
+                             pad, get_selection, state, sel);
 }
 
 static int call_set_selection(struct v4l2_subdev *sd,
                              struct v4l2_subdev_state *state,
                              struct v4l2_subdev_selection *sel)
 {
-       return check_selection(sd, state, sel) ? :
-              sd->ops->pad->set_selection(sd, state, sel);
+       return do_subdev_call(sd, check_selection(sd, state, sel),
+                             pad, set_selection, state, sel);
 }
 
 static inline int check_frame_interval(struct v4l2_subdev *sd,
@@ -338,16 +350,16 @@ static int call_get_frame_interval(struct v4l2_subdev *sd,
                                   struct v4l2_subdev_state *state,
                                   struct v4l2_subdev_frame_interval *fi)
 {
-       return check_frame_interval(sd, state, fi) ? :
-              sd->ops->pad->get_frame_interval(sd, state, fi);
+       return do_subdev_call(sd, check_frame_interval(sd, state, fi),
+                             pad, get_frame_interval, state, fi);
 }
 
 static int call_set_frame_interval(struct v4l2_subdev *sd,
                                   struct v4l2_subdev_state *state,
                                   struct v4l2_subdev_frame_interval *fi)
 {
-       return check_frame_interval(sd, state, fi) ? :
-              sd->ops->pad->set_frame_interval(sd, state, fi);
+       return do_subdev_call(sd, check_frame_interval(sd, state, fi),
+                             pad, set_frame_interval, state, fi);
 }
 
 static int call_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
@@ -361,6 +373,9 @@ static int call_get_frame_desc(struct v4l2_subdev *sd, 
unsigned int pad,
                return -EOPNOTSUPP;
 #endif
 
+       if (!sd->ops->pad->get_frame_desc)
+               return -ENOIOCTLCMD;
+
        memset(fd, 0, sizeof(*fd));
 
        ret = sd->ops->pad->get_frame_desc(sd, pad, fd);
@@ -405,12 +420,12 @@ static inline int check_edid(struct v4l2_subdev *sd,
 
 static int call_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
 {
-       return check_edid(sd, edid) ? : sd->ops->pad->get_edid(sd, edid);
+       return do_subdev_call(sd, check_edid(sd, edid), pad, get_edid, edid);
 }
 
 static int call_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
 {
-       return check_edid(sd, edid) ? : sd->ops->pad->set_edid(sd, edid);
+       return do_subdev_call(sd, check_edid(sd, edid), pad, set_edid, edid);
 }
 
 static int call_s_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
@@ -419,8 +434,8 @@ static int call_s_dv_timings(struct v4l2_subdev *sd, 
unsigned int pad,
        if (!timings)
                return -EINVAL;
 
-       return check_pad(sd, pad) ? :
-              sd->ops->pad->s_dv_timings(sd, pad, timings);
+       return do_subdev_call(sd, check_pad(sd, pad),
+                             pad, s_dv_timings, pad, timings);
 }
 
 static int call_g_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
@@ -429,8 +444,8 @@ static int call_g_dv_timings(struct v4l2_subdev *sd, 
unsigned int pad,
        if (!timings)
                return -EINVAL;
 
-       return check_pad(sd, pad) ? :
-              sd->ops->pad->g_dv_timings(sd, pad, timings);
+       return do_subdev_call(sd,  check_pad(sd, pad),
+                             pad, g_dv_timings, pad, timings);
 }
 
 static int call_query_dv_timings(struct v4l2_subdev *sd, unsigned int pad,
@@ -439,8 +454,8 @@ static int call_query_dv_timings(struct v4l2_subdev *sd, 
unsigned int pad,
        if (!timings)
                return -EINVAL;
 
-       return check_pad(sd, pad) ? :
-              sd->ops->pad->query_dv_timings(sd, pad, timings);
+       return do_subdev_call(sd, check_pad(sd, pad),
+                             pad, query_dv_timings, pad, timings);
 }
 
 static int call_dv_timings_cap(struct v4l2_subdev *sd,
@@ -449,8 +464,8 @@ static int call_dv_timings_cap(struct v4l2_subdev *sd,
        if (!cap)
                return -EINVAL;
 
-       return check_pad(sd, cap->pad) ? :
-              sd->ops->pad->dv_timings_cap(sd, cap);
+       return do_subdev_call(sd, check_pad(sd, cap->pad),
+                             pad, dv_timings_cap, cap);
 }
 
 static int call_enum_dv_timings(struct v4l2_subdev *sd,
@@ -459,8 +474,8 @@ static int call_enum_dv_timings(struct v4l2_subdev *sd,
        if (!dvt)
                return -EINVAL;
 
-       return check_pad(sd, dvt->pad) ? :
-              sd->ops->pad->enum_dv_timings(sd, dvt);
+       return do_subdev_call(sd, check_pad(sd, dvt->pad),
+                             pad, enum_dv_timings, dvt);
 }
 
 static int call_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
@@ -468,14 +483,17 @@ static int call_get_mbus_config(struct v4l2_subdev *sd, 
unsigned int pad,
 {
        memset(config, 0, sizeof(*config));
 
-       return check_pad(sd, pad) ? :
-              sd->ops->pad->get_mbus_config(sd, pad, config);
+       return do_subdev_call(sd, check_pad(sd, pad), pad, get_mbus_config,
+                             pad, config);
 }
 
 static int call_s_stream(struct v4l2_subdev *sd, int enable)
 {
        int ret;
 
+       if (!sd->ops->video->s_stream)
+               return -ENOIOCTLCMD;
+
        /*
         * The .s_stream() operation must never be called to start or stop an
         * already started or stopped subdev. Catch offenders but don't return
@@ -509,7 +527,7 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable)
  * wrapper handles the case where the caller does not provide the called
  * subdev's state. This should be removed when all the callers are fixed.
  */
-#define DEFINE_STATE_WRAPPER(f, arg_type)                                  \
+#define DEFINE_STATE_WRAPPER(f, arg_type)                                 \
        static int call_##f##_state(struct v4l2_subdev *sd,                \
                                    struct v4l2_subdev_state *_state,      \
                                    arg_type *arg)                         \
@@ -526,7 +544,7 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable)
 
 #else /* CONFIG_MEDIA_CONTROLLER */
 
-#define DEFINE_STATE_WRAPPER(f, arg_type)                            \
+#define DEFINE_STATE_WRAPPER(f, arg_type)                           \
        static int call_##f##_state(struct v4l2_subdev *sd,          \
                                    struct v4l2_subdev_state *state, \
                                    arg_type *arg)                   \
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 04fa23b9a651..b8874eeec2e5 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1951,14 +1951,16 @@ extern const struct v4l2_subdev_ops 
v4l2_subdev_call_wrappers;
                int __result;                                           \
                if (!__sd)                                              \
                        __result = -ENODEV;                             \
-               else if (!(__sd->ops->o && __sd->ops->o->f))            \
+               else if (!__sd->ops->o)                                 \
                        __result = -ENOIOCTLCMD;                        \
                else if (v4l2_subdev_call_wrappers.o &&                 \
                         v4l2_subdev_call_wrappers.o->f)                \
                        __result = v4l2_subdev_call_wrappers.o->f(      \
                                                        __sd, ##args);  \
-               else                                                    \
+               else if (__sd->ops->o->f)                               \
                        __result = __sd->ops->o->f(__sd, ##args);       \
+               else                                                    \
+                       __result = -ENOIOCTLCMD;                        \
                __result;                                               \
        })
 
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to