Commit 7392d87a authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

media: v4l2-ctrls: alloc arrays in ctrl_ref

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: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 5f2c5c69
...@@ -467,7 +467,7 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, ...@@ -467,7 +467,7 @@ int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
if (is_default) if (is_default)
ret = def_to_user(cs->controls + idx, ref->ctrl); 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; ret = -ENOMEM;
else if (is_request && ref->p_req_valid) else if (is_request && ref->p_req_valid)
ret = req_to_user(cs->controls + idx, ref); ret = req_to_user(cs->controls + idx, ref);
......
...@@ -1048,23 +1048,26 @@ void cur_to_new(struct v4l2_ctrl *ctrl) ...@@ -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); 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; 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; return true;
tmp = kvmalloc(elems * ref->ctrl->elem_size, GFP_KERNEL); tmp = kvmalloc(elems * ref->ctrl->elem_size, GFP_KERNEL);
if (!tmp) { if (!tmp) {
ref->p_req_dyn_enomem = true; ref->p_req_array_enomem = true;
return false; return false;
} }
ref->p_req_dyn_enomem = false; ref->p_req_array_enomem = false;
kvfree(ref->p_req.p); kvfree(ref->p_req.p);
ref->p_req.p = tmp; ref->p_req.p = tmp;
ref->p_req_dyn_alloc_elems = elems; ref->p_req_array_alloc_elems = elems;
return true; return true;
} }
...@@ -1077,7 +1080,7 @@ void new_to_req(struct v4l2_ctrl_ref *ref) ...@@ -1077,7 +1080,7 @@ void new_to_req(struct v4l2_ctrl_ref *ref)
return; return;
ctrl = ref->ctrl; 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; return;
ref->p_req_elems = ctrl->new_elems; ref->p_req_elems = ctrl->new_elems;
...@@ -1094,7 +1097,7 @@ void cur_to_req(struct v4l2_ctrl_ref *ref) ...@@ -1094,7 +1097,7 @@ void cur_to_req(struct v4l2_ctrl_ref *ref)
return; return;
ctrl = ref->ctrl; 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; return;
ref->p_req_elems = ctrl->elems; ref->p_req_elems = ctrl->elems;
...@@ -1123,14 +1126,18 @@ int req_to_new(struct v4l2_ctrl_ref *ref) ...@@ -1123,14 +1126,18 @@ int req_to_new(struct v4l2_ctrl_ref *ref)
return 0; return 0;
} }
/* Not a dynamic array, so just copy the request value */ /* Not an array, so just copy the request value */
if (!ctrl->is_dyn_array) { if (!ctrl->is_array) {
ptr_to_ptr(ctrl, ref->p_req, ctrl->p_new, ctrl->new_elems); ptr_to_ptr(ctrl, ref->p_req, ctrl->p_new, ctrl->new_elems);
return 0; return 0;
} }
/* Sanity check, should never happen */ /* 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; return -ENOMEM;
/* /*
...@@ -1243,7 +1250,7 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl) ...@@ -1243,7 +1250,7 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl)
/* Free all nodes */ /* Free all nodes */
list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) { list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
list_del(&ref->node); list_del(&ref->node);
if (ref->p_req_dyn_alloc_elems) if (ref->p_req_array_alloc_elems)
kvfree(ref->p_req.p); kvfree(ref->p_req.p);
kfree(ref); kfree(ref);
} }
...@@ -1368,7 +1375,7 @@ int handler_new_ref(struct v4l2_ctrl_handler *hdl, ...@@ -1368,7 +1375,7 @@ int handler_new_ref(struct v4l2_ctrl_handler *hdl,
if (hdl->error) if (hdl->error)
return 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; size_extra_req = ctrl->elems * ctrl->elem_size;
new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL); new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL);
if (!new_ref) if (!new_ref)
......
...@@ -318,15 +318,15 @@ struct v4l2_ctrl { ...@@ -318,15 +318,15 @@ struct v4l2_ctrl {
* from a cluster with multiple controls twice (when the first * from a cluster with multiple controls twice (when the first
* control of a cluster is applied, they all are). * 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_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 * @p_req_array_enomem: If set, then p_req is invalid since allocating space for
* a dynamic array failed. Attempting to read this value shall * an array failed. Attempting to read this value shall
* result in ENOMEM. Only valid if ctrl->is_dyn_array is true. * result in ENOMEM. Only valid if ctrl->is_array is true.
* @p_req_dyn_alloc_elems: The number of elements allocated for the dynamic * @p_req_array_alloc_elems: The number of elements allocated for the
* array. Only valid if @p_req_valid and ctrl->is_dyn_array are * array. Only valid if @p_req_valid and ctrl->is_array are
* true. * true.
* @p_req_elems: The number of elements in @p_req. This is the same as * @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 * 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_valid is true.
* @p_req: If the control handler containing this control reference * @p_req: If the control handler containing this control reference
* is bound to a media request, then this points to the * is bound to a media request, then this points to the
...@@ -348,8 +348,8 @@ struct v4l2_ctrl_ref { ...@@ -348,8 +348,8 @@ struct v4l2_ctrl_ref {
bool from_other_dev; bool from_other_dev;
bool req_done; bool req_done;
bool p_req_valid; bool p_req_valid;
bool p_req_dyn_enomem; bool p_req_array_enomem;
u32 p_req_dyn_alloc_elems; u32 p_req_array_alloc_elems;
u32 p_req_elems; u32 p_req_elems;
union v4l2_ctrl_ptr p_req; union v4l2_ctrl_ptr p_req;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment