03074222fe79ecc9bfdd014878d13d900434e0af
[openwrt/staging/rmilecki.git] /
1 From 613b860fe9c37b96d9706b02fe77933f086f9896 Mon Sep 17 00:00:00 2001
2 From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
3 Date: Thu, 15 Apr 2021 13:56:53 +0200
4 Subject: [PATCH] v4l2-ctrls: add support for dynamically allocated
5 arrays.
6
7 Implement support for dynamically allocated arrays.
8
9 Most of the changes concern keeping track of the number of elements
10 of the array and the number of elements allocated for the array and
11 reallocating memory if needed.
12
13 Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
14 (cherry picked from commit fd5d45e6561f6f8c406b81aeddecaa11f0bd15af)
15 ---
16 drivers/media/v4l2-core/v4l2-ctrls-api.c | 103 ++++++++---
17 drivers/media/v4l2-core/v4l2-ctrls-core.c | 182 +++++++++++++++----
18 drivers/media/v4l2-core/v4l2-ctrls-priv.h | 3 +-
19 drivers/media/v4l2-core/v4l2-ctrls-request.c | 13 +-
20 include/media/v4l2-ctrls.h | 42 ++++-
21 5 files changed, 272 insertions(+), 71 deletions(-)
22
23 --- a/drivers/media/v4l2-core/v4l2-ctrls-api.c
24 +++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c
25 @@ -97,29 +97,47 @@ static int def_to_user(struct v4l2_ext_c
26 return ptr_to_user(c, ctrl, ctrl->p_new);
27 }
28
29 -/* Helper function: copy the caller-provider value to the given control value */
30 -static int user_to_ptr(struct v4l2_ext_control *c,
31 - struct v4l2_ctrl *ctrl,
32 - union v4l2_ctrl_ptr ptr)
33 +/* Helper function: copy the caller-provider value as the new control value */
34 +static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
35 {
36 int ret;
37 u32 size;
38
39 - ctrl->is_new = 1;
40 + ctrl->is_new = 0;
41 + if (ctrl->is_dyn_array &&
42 + c->size > ctrl->p_dyn_alloc_elems * ctrl->elem_size) {
43 + void *old = ctrl->p_dyn;
44 + void *tmp = kvzalloc(2 * c->size, GFP_KERNEL);
45 +
46 + if (!tmp)
47 + return -ENOMEM;
48 + memcpy(tmp, ctrl->p_new.p, ctrl->elems * ctrl->elem_size);
49 + memcpy(tmp + c->size, ctrl->p_cur.p, ctrl->elems * ctrl->elem_size);
50 + ctrl->p_new.p = tmp;
51 + ctrl->p_cur.p = tmp + c->size;
52 + ctrl->p_dyn = tmp;
53 + ctrl->p_dyn_alloc_elems = c->size / ctrl->elem_size;
54 + kvfree(old);
55 + }
56 +
57 if (ctrl->is_ptr && !ctrl->is_string) {
58 + unsigned int elems = c->size / ctrl->elem_size;
59 unsigned int idx;
60
61 - ret = copy_from_user(ptr.p, c->ptr, c->size) ? -EFAULT : 0;
62 - if (ret || !ctrl->is_array)
63 - return ret;
64 - for (idx = c->size / ctrl->elem_size; idx < ctrl->elems; idx++)
65 - ctrl->type_ops->init(ctrl, idx, ptr);
66 + if (copy_from_user(ctrl->p_new.p, c->ptr, c->size))
67 + return -EFAULT;
68 + ctrl->is_new = 1;
69 + if (ctrl->is_dyn_array)
70 + ctrl->new_elems = elems;
71 + else if (ctrl->is_array)
72 + for (idx = elems; idx < ctrl->elems; idx++)
73 + ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
74 return 0;
75 }
76
77 switch (ctrl->type) {
78 case V4L2_CTRL_TYPE_INTEGER64:
79 - *ptr.p_s64 = c->value64;
80 + *ctrl->p_new.p_s64 = c->value64;
81 break;
82 case V4L2_CTRL_TYPE_STRING:
83 size = c->size;
84 @@ -127,32 +145,27 @@ static int user_to_ptr(struct v4l2_ext_c
85 return -ERANGE;
86 if (size > ctrl->maximum + 1)
87 size = ctrl->maximum + 1;
88 - ret = copy_from_user(ptr.p_char, c->string, size) ? -EFAULT : 0;
89 + ret = copy_from_user(ctrl->p_new.p_char, c->string, size) ? -EFAULT : 0;
90 if (!ret) {
91 - char last = ptr.p_char[size - 1];
92 + char last = ctrl->p_new.p_char[size - 1];
93
94 - ptr.p_char[size - 1] = 0;
95 + ctrl->p_new.p_char[size - 1] = 0;
96 /*
97 * If the string was longer than ctrl->maximum,
98 * then return an error.
99 */
100 - if (strlen(ptr.p_char) == ctrl->maximum && last)
101 + if (strlen(ctrl->p_new.p_char) == ctrl->maximum && last)
102 return -ERANGE;
103 }
104 return ret;
105 default:
106 - *ptr.p_s32 = c->value;
107 + *ctrl->p_new.p_s32 = c->value;
108 break;
109 }
110 + ctrl->is_new = 1;
111 return 0;
112 }
113
114 -/* Helper function: copy the caller-provider value as the new control value */
115 -static int user_to_new(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
116 -{
117 - return user_to_ptr(c, ctrl, ctrl->p_new);
118 -}
119 -
120 /*
121 * VIDIOC_G/TRY/S_EXT_CTRLS implementation
122 */
123 @@ -254,7 +267,31 @@ static int prepare_ext_ctrls(struct v4l2
124 have_clusters = true;
125 if (ctrl->cluster[0] != ctrl)
126 ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
127 - if (ctrl->is_ptr && !ctrl->is_string) {
128 + if (ctrl->is_dyn_array) {
129 + unsigned int max_size = ctrl->dims[0] * ctrl->elem_size;
130 + unsigned int tot_size = ctrl->elem_size;
131 +
132 + if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL)
133 + tot_size *= ref->p_req_elems;
134 + else
135 + tot_size *= ctrl->elems;
136 +
137 + c->size = ctrl->elem_size * (c->size / ctrl->elem_size);
138 + if (get) {
139 + if (c->size < tot_size) {
140 + c->size = tot_size;
141 + return -ENOSPC;
142 + }
143 + c->size = tot_size;
144 + } else {
145 + if (c->size > max_size) {
146 + c->size = max_size;
147 + return -ENOSPC;
148 + }
149 + if (!c->size)
150 + return -EFAULT;
151 + }
152 + } else if (ctrl->is_ptr && !ctrl->is_string) {
153 unsigned int tot_size = ctrl->elems * ctrl->elem_size;
154
155 if (c->size < tot_size) {
156 @@ -346,7 +383,7 @@ static int class_check(struct v4l2_ctrl_
157 *
158 * Note that v4l2_g_ext_ctrls_common() with 'which' set to
159 * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was
160 - * completed, and in that case valid_p_req is true for all controls.
161 + * completed, and in that case p_req_valid is true for all controls.
162 */
163 int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
164 struct v4l2_ext_controls *cs,
165 @@ -430,7 +467,9 @@ int v4l2_g_ext_ctrls_common(struct v4l2_
166
167 if (is_default)
168 ret = def_to_user(cs->controls + idx, ref->ctrl);
169 - else if (is_request && ref->valid_p_req)
170 + else if (is_request && ref->p_req_dyn_enomem)
171 + ret = -ENOMEM;
172 + else if (is_request && ref->p_req_valid)
173 ret = req_to_user(cs->controls + idx, ref);
174 else if (is_volatile)
175 ret = new_to_user(cs->controls + idx, ref->ctrl);
176 @@ -457,6 +496,17 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_ha
177 }
178 EXPORT_SYMBOL(v4l2_g_ext_ctrls);
179
180 +/* Validate a new control */
181 +static int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new)
182 +{
183 + unsigned int idx;
184 + int err = 0;
185 +
186 + for (idx = 0; !err && idx < ctrl->new_elems; idx++)
187 + err = ctrl->type_ops->validate(ctrl, idx, p_new);
188 + return err;
189 +}
190 +
191 /* Validate controls. */
192 static int validate_ctrls(struct v4l2_ext_controls *cs,
193 struct v4l2_ctrl_helper *helpers,
194 @@ -872,6 +922,9 @@ int __v4l2_ctrl_s_ctrl_compound(struct v
195 /* It's a driver bug if this happens. */
196 if (WARN_ON(ctrl->type != type))
197 return -EINVAL;
198 + /* Setting dynamic arrays is not (yet?) supported. */
199 + if (WARN_ON(ctrl->is_dyn_array))
200 + return -EINVAL;
201 memcpy(ctrl->p_new.p, p, ctrl->elems * ctrl->elem_size);
202 return set_ctrl(NULL, ctrl, 0);
203 }
204 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
205 +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
206 @@ -809,11 +809,12 @@ EXPORT_SYMBOL(v4l2_ctrl_notify);
207
208 /* Copy the one value to another. */
209 static void ptr_to_ptr(struct v4l2_ctrl *ctrl,
210 - union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to)
211 + union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to,
212 + unsigned int elems)
213 {
214 if (ctrl == NULL)
215 return;
216 - memcpy(to.p, from.p_const, ctrl->elems * ctrl->elem_size);
217 + memcpy(to.p, from.p_const, elems * ctrl->elem_size);
218 }
219
220 /* Copy the new value to the current value. */
221 @@ -826,8 +827,11 @@ void new_to_cur(struct v4l2_fh *fh, stru
222
223 /* has_changed is set by cluster_changed */
224 changed = ctrl->has_changed;
225 - if (changed)
226 - ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur);
227 + if (changed) {
228 + if (ctrl->is_dyn_array)
229 + ctrl->elems = ctrl->new_elems;
230 + ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur, ctrl->elems);
231 + }
232
233 if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) {
234 /* Note: CH_FLAGS is only set for auto clusters. */
235 @@ -857,36 +861,122 @@ void cur_to_new(struct v4l2_ctrl *ctrl)
236 {
237 if (ctrl == NULL)
238 return;
239 - ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
240 + if (ctrl->is_dyn_array)
241 + ctrl->new_elems = ctrl->elems;
242 + ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new, ctrl->new_elems);
243 +}
244 +
245 +static bool req_alloc_dyn_array(struct v4l2_ctrl_ref *ref, u32 elems)
246 +{
247 + void *tmp;
248 +
249 + if (elems < ref->p_req_dyn_alloc_elems)
250 + return true;
251 +
252 + tmp = kvmalloc(elems * ref->ctrl->elem_size, GFP_KERNEL);
253 +
254 + if (!tmp) {
255 + ref->p_req_dyn_enomem = true;
256 + return false;
257 + }
258 + ref->p_req_dyn_enomem = false;
259 + kvfree(ref->p_req.p);
260 + ref->p_req.p = tmp;
261 + ref->p_req_dyn_alloc_elems = elems;
262 + return true;
263 }
264
265 /* Copy the new value to the request value */
266 void new_to_req(struct v4l2_ctrl_ref *ref)
267 {
268 + struct v4l2_ctrl *ctrl;
269 +
270 if (!ref)
271 return;
272 - ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req);
273 - ref->valid_p_req = true;
274 +
275 + ctrl = ref->ctrl;
276 + if (ctrl->is_dyn_array && !req_alloc_dyn_array(ref, ctrl->new_elems))
277 + return;
278 +
279 + ref->p_req_elems = ctrl->new_elems;
280 + ptr_to_ptr(ctrl, ctrl->p_new, ref->p_req, ref->p_req_elems);
281 + ref->p_req_valid = true;
282 }
283
284 /* Copy the current value to the request value */
285 void cur_to_req(struct v4l2_ctrl_ref *ref)
286 {
287 + struct v4l2_ctrl *ctrl;
288 +
289 if (!ref)
290 return;
291 - ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->p_req);
292 - ref->valid_p_req = true;
293 +
294 + ctrl = ref->ctrl;
295 + if (ctrl->is_dyn_array && !req_alloc_dyn_array(ref, ctrl->elems))
296 + return;
297 +
298 + ref->p_req_elems = ctrl->elems;
299 + ptr_to_ptr(ctrl, ctrl->p_cur, ref->p_req, ctrl->elems);
300 + ref->p_req_valid = true;
301 }
302
303 /* Copy the request value to the new value */
304 -void req_to_new(struct v4l2_ctrl_ref *ref)
305 +int req_to_new(struct v4l2_ctrl_ref *ref)
306 {
307 + struct v4l2_ctrl *ctrl;
308 +
309 if (!ref)
310 - return;
311 - if (ref->valid_p_req)
312 - ptr_to_ptr(ref->ctrl, ref->p_req, ref->ctrl->p_new);
313 - else
314 - ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);
315 + return 0;
316 +
317 + ctrl = ref->ctrl;
318 +
319 + /*
320 + * This control was never set in the request, so just use the current
321 + * value.
322 + */
323 + if (!ref->p_req_valid) {
324 + if (ctrl->is_dyn_array)
325 + ctrl->new_elems = ctrl->elems;
326 + ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new, ctrl->new_elems);
327 + return 0;
328 + }
329 +
330 + /* Not a dynamic array, so just copy the request value */
331 + if (!ctrl->is_dyn_array) {
332 + ptr_to_ptr(ctrl, ref->p_req, ctrl->p_new, ctrl->new_elems);
333 + return 0;
334 + }
335 +
336 + /* Sanity check, should never happen */
337 + if (WARN_ON(!ref->p_req_dyn_alloc_elems))
338 + return -ENOMEM;
339 +
340 + /*
341 + * Check if the number of elements in the request is more than the
342 + * elements in ctrl->p_dyn. If so, attempt to realloc ctrl->p_dyn.
343 + * Note that p_dyn is allocated with twice the number of elements
344 + * in the dynamic array since it has to store both the current and
345 + * new value of such a control.
346 + */
347 + if (ref->p_req_elems > ctrl->p_dyn_alloc_elems) {
348 + unsigned int sz = ref->p_req_elems * ctrl->elem_size;
349 + void *old = ctrl->p_dyn;
350 + void *tmp = kvzalloc(2 * sz, GFP_KERNEL);
351 +
352 + if (!tmp)
353 + return -ENOMEM;
354 + memcpy(tmp, ctrl->p_new.p, ctrl->elems * ctrl->elem_size);
355 + memcpy(tmp + sz, ctrl->p_cur.p, ctrl->elems * ctrl->elem_size);
356 + ctrl->p_new.p = tmp;
357 + ctrl->p_cur.p = tmp + sz;
358 + ctrl->p_dyn = tmp;
359 + ctrl->p_dyn_alloc_elems = ref->p_req_elems;
360 + kvfree(old);
361 + }
362 +
363 + ctrl->new_elems = ref->p_req_elems;
364 + ptr_to_ptr(ctrl, ref->p_req, ctrl->p_new, ctrl->new_elems);
365 + return 0;
366 }
367
368 /* Control range checking */
369 @@ -928,17 +1018,6 @@ int check_range(enum v4l2_ctrl_type type
370 }
371 }
372
373 -/* Validate a new control */
374 -int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new)
375 -{
376 - unsigned idx;
377 - int err = 0;
378 -
379 - for (idx = 0; !err && idx < ctrl->elems; idx++)
380 - err = ctrl->type_ops->validate(ctrl, idx, p_new);
381 - return err;
382 -}
383 -
384 /* Set the handler's error code if it wasn't set earlier already */
385 static inline int handler_set_err(struct v4l2_ctrl_handler *hdl, int err)
386 {
387 @@ -983,6 +1062,8 @@ void v4l2_ctrl_handler_free(struct v4l2_
388 /* Free all nodes */
389 list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
390 list_del(&ref->node);
391 + if (ref->p_req_dyn_alloc_elems)
392 + kvfree(ref->p_req.p);
393 kfree(ref);
394 }
395 /* Free all controls owned by the handler */
396 @@ -990,6 +1071,7 @@ void v4l2_ctrl_handler_free(struct v4l2_
397 list_del(&ctrl->node);
398 list_for_each_entry_safe(sev, next_sev, &ctrl->ev_subs, node)
399 list_del(&sev->node);
400 + kvfree(ctrl->p_dyn);
401 kvfree(ctrl);
402 }
403 kvfree(hdl->buckets);
404 @@ -1105,7 +1187,7 @@ int handler_new_ref(struct v4l2_ctrl_han
405 if (hdl->error)
406 return hdl->error;
407
408 - if (allocate_req)
409 + if (allocate_req && !ctrl->is_dyn_array)
410 size_extra_req = ctrl->elems * ctrl->elem_size;
411 new_ref = kzalloc(sizeof(*new_ref) + size_extra_req, GFP_KERNEL);
412 if (!new_ref)
413 @@ -1273,7 +1355,6 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
414 elem_size = sizeof(s32);
415 break;
416 }
417 - tot_ctrl_size = elem_size * elems;
418
419 /* Sanity checks */
420 if (id == 0 || name == NULL || !elem_size ||
421 @@ -1294,17 +1375,33 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
422 handler_set_err(hdl, -EINVAL);
423 return NULL;
424 }
425 + if (flags & V4L2_CTRL_FLAG_DYNAMIC_ARRAY) {
426 + /*
427 + * For now only support this for one-dimensional arrays only.
428 + *
429 + * This can be relaxed in the future, but this will
430 + * require more effort.
431 + */
432 + if (nr_of_dims != 1) {
433 + handler_set_err(hdl, -EINVAL);
434 + return NULL;
435 + }
436 + /* Start with just 1 element */
437 + elems = 1;
438 + }
439
440 + tot_ctrl_size = elem_size * elems;
441 sz_extra = 0;
442 if (type == V4L2_CTRL_TYPE_BUTTON)
443 flags |= V4L2_CTRL_FLAG_WRITE_ONLY |
444 V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
445 else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
446 flags |= V4L2_CTRL_FLAG_READ_ONLY;
447 - else if (type == V4L2_CTRL_TYPE_INTEGER64 ||
448 - type == V4L2_CTRL_TYPE_STRING ||
449 - type >= V4L2_CTRL_COMPOUND_TYPES ||
450 - is_array)
451 + else if (!(flags & V4L2_CTRL_FLAG_DYNAMIC_ARRAY) &&
452 + (type == V4L2_CTRL_TYPE_INTEGER64 ||
453 + type == V4L2_CTRL_TYPE_STRING ||
454 + type >= V4L2_CTRL_COMPOUND_TYPES ||
455 + is_array))
456 sz_extra += 2 * tot_ctrl_size;
457
458 if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const)
459 @@ -1333,7 +1430,9 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
460 ctrl->is_ptr = is_array || type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string;
461 ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64;
462 ctrl->is_array = is_array;
463 + ctrl->is_dyn_array = !!(flags & V4L2_CTRL_FLAG_DYNAMIC_ARRAY);
464 ctrl->elems = elems;
465 + ctrl->new_elems = elems;
466 ctrl->nr_of_dims = nr_of_dims;
467 if (nr_of_dims)
468 memcpy(ctrl->dims, dims, nr_of_dims * sizeof(dims[0]));
469 @@ -1346,6 +1445,16 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
470 ctrl->cur.val = ctrl->val = def;
471 data = &ctrl[1];
472
473 + if (ctrl->is_dyn_array) {
474 + ctrl->p_dyn_alloc_elems = elems;
475 + ctrl->p_dyn = kvzalloc(2 * elems * elem_size, GFP_KERNEL);
476 + if (!ctrl->p_dyn) {
477 + kvfree(ctrl);
478 + return NULL;
479 + }
480 + data = ctrl->p_dyn;
481 + }
482 +
483 if (!ctrl->is_int) {
484 ctrl->p_new.p = data;
485 ctrl->p_cur.p = data + tot_ctrl_size;
486 @@ -1355,7 +1464,10 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
487 }
488
489 if (type >= V4L2_CTRL_COMPOUND_TYPES && p_def.p_const) {
490 - ctrl->p_def.p = ctrl->p_cur.p + tot_ctrl_size;
491 + if (ctrl->is_dyn_array)
492 + ctrl->p_def.p = &ctrl[1];
493 + else
494 + ctrl->p_def.p = ctrl->p_cur.p + tot_ctrl_size;
495 memcpy(ctrl->p_def.p, p_def.p_const, elem_size);
496 }
497
498 @@ -1365,6 +1477,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(s
499 }
500
501 if (handler_new_ref(hdl, ctrl, NULL, false, false)) {
502 + kvfree(ctrl->p_dyn);
503 kvfree(ctrl);
504 return NULL;
505 }
506 @@ -1702,6 +1815,9 @@ static int cluster_changed(struct v4l2_c
507 continue;
508 }
509
510 + if (ctrl->elems != ctrl->new_elems)
511 + ctrl_changed = true;
512 +
513 for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++)
514 ctrl_changed = !ctrl->type_ops->equal(ctrl, idx,
515 ctrl->p_cur, ctrl->p_new);
516 --- a/drivers/media/v4l2-core/v4l2-ctrls-priv.h
517 +++ b/drivers/media/v4l2-core/v4l2-ctrls-priv.h
518 @@ -57,10 +57,9 @@ void cur_to_new(struct v4l2_ctrl *ctrl);
519 void cur_to_req(struct v4l2_ctrl_ref *ref);
520 void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags);
521 void new_to_req(struct v4l2_ctrl_ref *ref);
522 -void req_to_new(struct v4l2_ctrl_ref *ref);
523 +int req_to_new(struct v4l2_ctrl_ref *ref);
524 void send_initial_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl);
525 void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes);
526 -int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new);
527 int handler_new_ref(struct v4l2_ctrl_handler *hdl,
528 struct v4l2_ctrl *ctrl,
529 struct v4l2_ctrl_ref **ctrl_ref,
530 --- a/drivers/media/v4l2-core/v4l2-ctrls-request.c
531 +++ b/drivers/media/v4l2-core/v4l2-ctrls-request.c
532 @@ -143,7 +143,7 @@ v4l2_ctrl_request_hdl_ctrl_find(struct v
533 {
534 struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
535
536 - return (ref && ref->valid_p_req) ? ref->ctrl : NULL;
537 + return (ref && ref->p_req_valid) ? ref->ctrl : NULL;
538 }
539 EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find);
540
541 @@ -373,7 +373,7 @@ void v4l2_ctrl_request_complete(struct m
542 v4l2_ctrl_unlock(master);
543 continue;
544 }
545 - if (ref->valid_p_req)
546 + if (ref->p_req_valid)
547 continue;
548
549 /* Copy the current control value into the request */
550 @@ -442,7 +442,7 @@ int v4l2_ctrl_request_setup(struct media
551 struct v4l2_ctrl_ref *r =
552 find_ref(hdl, master->cluster[i]->id);
553
554 - if (r->valid_p_req) {
555 + if (r->p_req_valid) {
556 have_new_data = true;
557 break;
558 }
559 @@ -458,7 +458,11 @@ int v4l2_ctrl_request_setup(struct media
560 struct v4l2_ctrl_ref *r =
561 find_ref(hdl, master->cluster[i]->id);
562
563 - req_to_new(r);
564 + ret = req_to_new(r);
565 + if (ret) {
566 + v4l2_ctrl_unlock(master);
567 + goto error;
568 + }
569 master->cluster[i]->is_new = 1;
570 r->req_done = true;
571 }
572 @@ -490,6 +494,7 @@ int v4l2_ctrl_request_setup(struct media
573 break;
574 }
575
576 +error:
577 media_request_object_put(obj);
578 return ret;
579 }
580 --- a/include/media/v4l2-ctrls.h
581 +++ b/include/media/v4l2-ctrls.h
582 @@ -181,6 +181,8 @@ typedef void (*v4l2_ctrl_notify_fnc)(str
583 * and/or has type %V4L2_CTRL_TYPE_STRING. In other words, &struct
584 * v4l2_ext_control uses field p to point to the data.
585 * @is_array: If set, then this control contains an N-dimensional array.
586 + * @is_dyn_array: If set, then this control contains a dynamically sized 1-dimensional array.
587 + * If this is set, then @is_array is also set.
588 * @has_volatiles: If set, then one or more members of the cluster are volatile.
589 * Drivers should never touch this flag.
590 * @call_notify: If set, then call the handler's notify function whenever the
591 @@ -201,6 +203,9 @@ typedef void (*v4l2_ctrl_notify_fnc)(str
592 * @step: The control's step value for non-menu controls.
593 * @elems: The number of elements in the N-dimensional array.
594 * @elem_size: The size in bytes of the control.
595 + * @new_elems: The number of elements in p_new. This is the same as @elems,
596 + * except for dynamic arrays. In that case it is in the range of
597 + * 1 to @p_dyn_alloc_elems.
598 * @dims: The size of each dimension.
599 * @nr_of_dims:The number of dimensions in @dims.
600 * @menu_skip_mask: The control's skip mask for menu controls. This makes it
601 @@ -219,15 +224,21 @@ typedef void (*v4l2_ctrl_notify_fnc)(str
602 * :math:`ceil(\frac{maximum - minimum}{step}) + 1`.
603 * Used only if the @type is %V4L2_CTRL_TYPE_INTEGER_MENU.
604 * @flags: The control's flags.
605 - * @cur: Structure to store the current value.
606 - * @cur.val: The control's current value, if the @type is represented via
607 - * a u32 integer (see &enum v4l2_ctrl_type).
608 - * @val: The control's new s32 value.
609 * @priv: The control's private pointer. For use by the driver. It is
610 * untouched by the control framework. Note that this pointer is
611 * not freed when the control is deleted. Should this be needed
612 * then a new internal bitfield can be added to tell the framework
613 * to free this pointer.
614 + * @p_dyn: Pointer to the dynamically allocated array. Only valid if
615 + * @is_dyn_array is true.
616 + * @p_dyn_alloc_elems: The number of elements in the dynamically allocated
617 + * array for both the cur and new values. So @p_dyn is actually
618 + * sized for 2 * @p_dyn_alloc_elems * @elem_size. Only valid if
619 + * @is_dyn_array is true.
620 + * @cur: Structure to store the current value.
621 + * @cur.val: The control's current value, if the @type is represented via
622 + * a u32 integer (see &enum v4l2_ctrl_type).
623 + * @val: The control's new s32 value.
624 * @p_def: The control's default value represented via a union which
625 * provides a standard way of accessing control types
626 * through a pointer (for compound controls only).
627 @@ -256,6 +267,7 @@ struct v4l2_ctrl {
628 unsigned int is_string:1;
629 unsigned int is_ptr:1;
630 unsigned int is_array:1;
631 + unsigned int is_dyn_array:1;
632 unsigned int has_volatiles:1;
633 unsigned int call_notify:1;
634 unsigned int manual_mode_value:8;
635 @@ -268,6 +280,7 @@ struct v4l2_ctrl {
636 s64 minimum, maximum, default_value;
637 u32 elems;
638 u32 elem_size;
639 + u32 new_elems;
640 u32 dims[V4L2_CTRL_MAX_DIMS];
641 u32 nr_of_dims;
642 union {
643 @@ -280,6 +293,8 @@ struct v4l2_ctrl {
644 };
645 unsigned long flags;
646 void *priv;
647 + void *p_dyn;
648 + u32 p_dyn_alloc_elems;
649 s32 val;
650 struct {
651 s32 val;
652 @@ -305,12 +320,22 @@ struct v4l2_ctrl {
653 * the control has been applied. This prevents applying controls
654 * from a cluster with multiple controls twice (when the first
655 * control of a cluster is applied, they all are).
656 - * @valid_p_req: If set, then p_req contains the control value for the request.
657 + * @p_req_valid: If set, then p_req contains the control value for the request.
658 + * @p_req_dyn_enomem: If set, then p_req is invalid since allocating space for
659 + * a dynamic array failed. Attempting to read this value shall
660 + * result in ENOMEM. Only valid if ctrl->is_dyn_array is true.
661 + * @p_req_dyn_alloc_elems: The number of elements allocated for the dynamic
662 + * array. Only valid if @p_req_valid and ctrl->is_dyn_array are
663 + * true.
664 + * @p_req_elems: The number of elements in @p_req. This is the same as
665 + * ctrl->elems, except for dynamic arrays. In that case it is in
666 + * the range of 1 to @p_req_dyn_alloc_elems. Only valid if
667 + * @p_req_valid is true.
668 * @p_req: If the control handler containing this control reference
669 * is bound to a media request, then this points to the
670 * value of the control that must be applied when the request
671 * is executed, or to the value of the control at the time
672 - * that the request was completed. If @valid_p_req is false,
673 + * that the request was completed. If @p_req_valid is false,
674 * then this control was never set for this request and the
675 * control will not be updated when this request is applied.
676 *
677 @@ -325,7 +350,10 @@ struct v4l2_ctrl_ref {
678 struct v4l2_ctrl_helper *helper;
679 bool from_other_dev;
680 bool req_done;
681 - bool valid_p_req;
682 + bool p_req_valid;
683 + bool p_req_dyn_enomem;
684 + u32 p_req_dyn_alloc_elems;
685 + u32 p_req_elems;
686 union v4l2_ctrl_ptr p_req;
687 };
688