media: v4l2-ctrls: alloc arrays in ctrl_ref
authorHans Verkuil <hverkuil-cisco@xs4all.nl>
Mon, 11 Jul 2022 10:21:08 +0000 (12:21 +0200)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Fri, 19 Aug 2022 11:47:00 +0000 (13:47 +0200)
Also allocate space for arrays in struct ctrl_ref.

This is in preparation for allowing to change the array size from
a driver.

Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
drivers/media/v4l2-core/v4l2-ctrls-api.c
drivers/media/v4l2-core/v4l2-ctrls-core.c
include/media/v4l2-ctrls.h

index 1b90bd7..6f1b72c 100644 (file)
@@ -467,7 +467,7 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
 
                        if (is_default)
                                ret = def_to_user(cs->controls + idx, ref->ctrl);
-                       else if (is_request && ref->p_req_dyn_enomem)
+                       else if (is_request && ref->p_req_array_enomem)
                                ret = -ENOMEM;
                        else if (is_request && ref->p_req_valid)
                                ret = req_to_user(cs->controls + idx, ref);
index 9871c77..a004fea 100644 (file)
@@ -1048,23 +1048,26 @@ void cur_to_new(struct v4l2_ctrl *ctrl)
        ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new, ctrl->new_elems);
 }
 
-static bool req_alloc_dyn_array(struct v4l2_ctrl_ref *ref, u32 elems)
+static bool req_alloc_array(struct v4l2_ctrl_ref *ref, u32 elems)
 {
        void *tmp;
 
-       if (elems < ref->p_req_dyn_alloc_elems)
+       if (elems == ref->p_req_array_alloc_elems)
+               return true;
+       if (ref->ctrl->is_dyn_array &&
+           elems < ref->p_req_array_alloc_elems)
                return true;
 
        tmp = kvmalloc(elems * ref->ctrl->elem_size, GFP_KERNEL);
 
        if (!tmp) {
-               ref->p_req_dyn_enomem = true;
+               ref->p_req_array_enomem = true;
                return false;
        }
-       ref->p_req_dyn_enomem = false;
+       ref->p_req_array_enomem = false;
        kvfree(ref->p_req.p);
        ref->p_req.p = tmp;
-       ref->p_req_dyn_alloc_elems = elems;
+       ref->p_req_array_alloc_elems = elems;
        return true;
 }
 
@@ -1077,7 +1080,7 @@ void new_to_req(struct v4l2_ctrl_ref *ref)
                return;
 
        ctrl = ref->ctrl;
-       if (ctrl->is_dyn_array && !req_alloc_dyn_array(ref, ctrl->new_elems))
+       if (ctrl->is_array && !req_alloc_array(ref, ctrl->new_elems))
                return;
 
        ref->p_req_elems = ctrl->new_elems;
@@ -1094,7 +1097,7 @@ void cur_to_req(struct v4l2_ctrl_ref *ref)
                return;
 
        ctrl = ref->ctrl;
-       if (ctrl->is_dyn_array && !req_alloc_dyn_array(ref, ctrl->elems))
+       if (ctrl->is_array && !req_alloc_array(ref, ctrl->elems))
                return;
 
        ref->p_req_elems = ctrl->elems;
@@ -1123,14 +1126,18 @@ int req_to_new(struct v4l2_ctrl_ref *ref)
                return 0;
        }
 
-       /* Not a dynamic array, so just copy the request value */
-       if (!ctrl->is_dyn_array) {
+       /* Not an array, so just copy the request value */
+       if (!ctrl->is_array) {
                ptr_to_ptr(ctrl, ref->p_req, ctrl->p_new, ctrl->new_elems);
                return 0;
        }
 
        /* Sanity check, should never happen */
-       if (WARN_ON(!ref->p_req_dyn_alloc_elems))
+       if (WARN_ON(!ref->p_req_array_alloc_elems))
+               return -ENOMEM;
+
+       if (!ctrl->is_dyn_array &&
+           ref->p_req_elems != ctrl->p_array_alloc_elems)
                return -ENOMEM;
 
        /*
@@ -1243,7 +1250,7 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
        /* Free all nodes */
        list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
                list_del(&ref->node);
-               if (ref->p_req_dyn_alloc_elems)
+               if (ref->p_req_array_alloc_elems)
                        kvfree(ref->p_req.p);
                kfree(ref);
        }
@@ -1368,7 +1375,7 @@ int handler_new_ref(struct v4l2_ctrl_handler *hdl,
        if (hdl->error)
                return hdl->error;
 
-       if (allocate_req && !ctrl->is_dyn_array)
+       if (allocate_req && !ctrl->is_array)
                size_extra_req = ctrl->elems * ctrl->elem_size;
        new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL);
        if (!new_ref)
index 5ddd506..c7a082c 100644 (file)
@@ -318,15 +318,15 @@ struct v4l2_ctrl {
  *             from a cluster with multiple controls twice (when the first
  *             control of a cluster is applied, they all are).
  * @p_req_valid: If set, then p_req contains the control value for the request.
- * @p_req_dyn_enomem: If set, then p_req is invalid since allocating space for
- *             a dynamic array failed. Attempting to read this value shall
- *             result in ENOMEM. Only valid if ctrl->is_dyn_array is true.
- * @p_req_dyn_alloc_elems: The number of elements allocated for the dynamic
- *             array. Only valid if @p_req_valid and ctrl->is_dyn_array are
+ * @p_req_array_enomem: If set, then p_req is invalid since allocating space for
+ *             an array failed. Attempting to read this value shall
+ *             result in ENOMEM. Only valid if ctrl->is_array is true.
+ * @p_req_array_alloc_elems: The number of elements allocated for the
+ *             array. Only valid if @p_req_valid and ctrl->is_array are
  *             true.
  * @p_req_elems: The number of elements in @p_req. This is the same as
  *             ctrl->elems, except for dynamic arrays. In that case it is in
- *             the range of 1 to @p_req_dyn_alloc_elems. Only valid if
+ *             the range of 1 to @p_req_array_alloc_elems. Only valid if
  *             @p_req_valid is true.
  * @p_req:     If the control handler containing this control reference
  *             is bound to a media request, then this points to the
@@ -348,8 +348,8 @@ struct v4l2_ctrl_ref {
        bool from_other_dev;
        bool req_done;
        bool p_req_valid;
-       bool p_req_dyn_enomem;
-       u32 p_req_dyn_alloc_elems;
+       bool p_req_array_enomem;
+       u32 p_req_array_alloc_elems;
        u32 p_req_elems;
        union v4l2_ctrl_ptr p_req;
 };