diff --git a/projects/Allwinner/patches/linux/0061-arm64-dts-allwinner-Fix-SD-card-CD-GPIO-for-SOPine-s.patch b/projects/Allwinner/patches/linux/0061-arm64-dts-allwinner-Fix-SD-card-CD-GPIO-for-SOPine-s.patch new file mode 100644 index 0000000000..61b7c5efef --- /dev/null +++ b/projects/Allwinner/patches/linux/0061-arm64-dts-allwinner-Fix-SD-card-CD-GPIO-for-SOPine-s.patch @@ -0,0 +1,56 @@ +From 3dd4ce4185df6798dcdcc3669bddb35899d7d5e1 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Tue, 16 Mar 2021 14:42:19 +0000 +Subject: [PATCH] arm64: dts: allwinner: Fix SD card CD GPIO for SOPine systems + +Commit 941432d00768 ("arm64: dts: allwinner: Drop non-removable from +SoPine/LTS SD card") enabled the card detect GPIO for the SOPine module, +along the way with the Pine64-LTS, which share the same base .dtsi. + +However while both boards indeed have a working CD GPIO on PF6, the +polarity is different: the SOPine modules uses a "push-pull" socket, +which has an active-high switch, while the Pine64-LTS use the more +traditional push-push socket and the common active-low switch. + +Fix the polarity in the sopine.dtsi, and overwrite it in the LTS +board .dts, to make the SD card work again on systems using SOPine +modules. + +Fixes: 941432d00768 ("arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card") +Reported-by: Ashley +Signed-off-by: Andre Przywara +Signed-off-by: Maxime Ripard +Link: https://lore.kernel.org/r/20210316144219.5973-1-andre.przywara@arm.com +--- + arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts | 4 ++++ + arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi | 2 +- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts +index 437ffe3628a5..e79ce49e7e6a 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts +@@ -19,3 +19,7 @@ led { + }; + }; + }; ++ ++&mmc0 { ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 push-push switch */ ++}; +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi +index 3402cec87035..df62044ff7a7 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi +@@ -34,7 +34,7 @@ &mmc0 { + vmmc-supply = <®_dcdc1>; + disable-wp; + bus-width = <4>; +- cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 push-pull switch */ + status = "okay"; + }; + +-- +2.31.1 + diff --git a/projects/Allwinner/patches/linux/0062-arm64-dts-allwinner-Revert-SD-card-CD-GPIO-for-Pine64-LTS.patch b/projects/Allwinner/patches/linux/0062-arm64-dts-allwinner-Revert-SD-card-CD-GPIO-for-Pine64-LTS.patch new file mode 100644 index 0000000000..2ac870e000 --- /dev/null +++ b/projects/Allwinner/patches/linux/0062-arm64-dts-allwinner-Revert-SD-card-CD-GPIO-for-Pine64-LTS.patch @@ -0,0 +1,48 @@ +From: Andre Przywara +Subject: [PATCH v2] arm64: dts: allwinner: Revert SD card CD GPIO for + Pine64-LTS +Date: Wed, 14 Apr 2021 11:47:40 +0100 + +Commit 941432d00768 ("arm64: dts: allwinner: Drop non-removable from +SoPine/LTS SD card") enabled the card detect GPIO for the SOPine module, +along the way with the Pine64-LTS, which share the same base .dtsi. + +This was based on the observation that the Pine64-LTS has as "push-push" +SD card socket, and that the schematic mentions the card detect GPIO. + +After having received two reports about failing SD card access with that +patch, some more research and polls on that subject revealed that there +are at least two different versions of the Pine64-LTS out there: +- On some boards (including mine) the card detect pin is "stuck" at + high, regardless of an microSD card being inserted or not. +- On other boards the card-detect is working, but is active-high, by + virtue of an explicit inverter circuit, as shown in the schematic. + +To cover all versions of the board out there, and don't take any chances, +let's revert the introduction of the active-low CD GPIO, but let's use +the broken-cd property for the Pine64-LTS this time. That should avoid +regressions and should work for everyone, even allowing SD card changes +now. +The SOPine card detect has proven to be working, so let's keep that +GPIO in place. + +Fixes: 941432d00768 ("arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card") +Reported-by: Michael Weiser +Reported-by: Daniel Kulesz +Suggested-by: Chen-Yu Tsai +Signed-off-by: Andre Przywara +--- + arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts +index e79ce49e7e6a..596a25907432 100644 +--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts +@@ -21,5 +21,5 @@ + }; + + &mmc0 { +- cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 push-push switch */ ++ broken-cd; /* card detect is broken on *some* boards */ + }; diff --git a/projects/Allwinner/patches/linux/0063-media-v4l2-ctrls.c-fix-race-condition-in-hdl-request.patch b/projects/Allwinner/patches/linux/0063-media-v4l2-ctrls.c-fix-race-condition-in-hdl-request.patch new file mode 100644 index 0000000000..8b0677652b --- /dev/null +++ b/projects/Allwinner/patches/linux/0063-media-v4l2-ctrls.c-fix-race-condition-in-hdl-request.patch @@ -0,0 +1,109 @@ +From be7e8af98f3af729aa9f08b1053f9533a5cceb91 Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Sat, 27 Mar 2021 12:27:40 +0100 +Subject: [PATCH] media: v4l2-ctrls.c: fix race condition in hdl->requests list + +When a request is re-inited it will release all control handler +objects that are still in the request. It does that by unbinding +and putting all those objects. When the object is unbound the +obj->req pointer is set to NULL, and the object's unbind op is +called. When the object it put the object's release op is called +to free the memory. + +For a request object that contains a control handler that means +that v4l2_ctrl_handler_free() is called in the release op. + +A control handler used in a request has a pointer to the main +control handler that is created by the driver and contains the +current state of all controls. If the device is unbound (due to +rmmod or a forced unbind), then that main handler is freed, again +by calling v4l2_ctrl_handler_free(), and any outstanding request +objects that refer to that main handler have to be unbound and put +as well. + +It does that by this test: + + if (!hdl->req_obj.req && !list_empty(&hdl->requests)) { + +I.e. the handler has no pointer to a request, so is the main +handler, and one or more request objects refer to this main +handler. + +However, this test is wrong since hdl->req_obj.req is actually +NULL when re-initing a request (the object unbind will set req to +NULL), and the only reason this seemingly worked is that the +requests list is typically empty since the request's unbind op +will remove the handler from the requests list. + +But if another thread is at the same time adding a new control +to a request, then there is a race condition where one thread +is removing a control handler object from the requests list and +another thread is adding one. The result is that hdl->requests +is no longer empty and the code thinks that a main handler is +being freed instead of a control handler that is part of a request. + +There are two bugs here: first the test for hdl->req_obj.req: this +should be hdl->req_obj.ops since only the main control handler will +have a NULL pointer there. + +The second is that adding or deleting request objects from the +requests list of the main handler isn't protected by taking the +main handler's lock. + +Signed-off-by: Hans Verkuil +Reported-by: John Cox +Fixes: 6fa6f831f095 ("media: v4l2-ctrls: add core request support") +Tested-by: John Cox +Reported-by: John Cox +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/v4l2-core/v4l2-ctrls.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index e7fcbaeec0ae..c7bcc5c25771 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -2650,7 +2650,15 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl) + if (hdl == NULL || hdl->buckets == NULL) + return; + +- if (!hdl->req_obj.req && !list_empty(&hdl->requests)) { ++ /* ++ * If the main handler is freed and it is used by handler objects in ++ * outstanding requests, then unbind and put those objects before ++ * freeing the main handler. ++ * ++ * The main handler can be identified by having a NULL ops pointer in ++ * the request object. ++ */ ++ if (!hdl->req_obj.ops && !list_empty(&hdl->requests)) { + struct v4l2_ctrl_handler *req, *next_req; + + list_for_each_entry_safe(req, next_req, &hdl->requests, requests) { +@@ -3730,8 +3738,8 @@ static void v4l2_ctrl_request_unbind(struct media_request_object *obj) + container_of(obj, struct v4l2_ctrl_handler, req_obj); + struct v4l2_ctrl_handler *main_hdl = obj->priv; + ++ mutex_lock(main_hdl->lock); + list_del_init(&hdl->requests); +- mutex_lock(main_hdl->lock); + if (hdl->request_is_queued) { + list_del_init(&hdl->requests_queued); + hdl->request_is_queued = false; +@@ -3790,8 +3798,11 @@ static int v4l2_ctrl_request_bind(struct media_request *req, + if (!ret) { + ret = media_request_object_bind(req, &req_ops, + from, false, &hdl->req_obj); +- if (!ret) ++ if (!ret) { ++ mutex_lock(from->lock); + list_add_tail(&hdl->requests, &from->requests); ++ mutex_unlock(from->lock); ++ } + } + return ret; + } +-- +2.31.1 + diff --git a/projects/Allwinner/patches/linux/0064-media-v4l2-ctrls-fix-reference-to-freed-memory.patch b/projects/Allwinner/patches/linux/0064-media-v4l2-ctrls-fix-reference-to-freed-memory.patch new file mode 100644 index 0000000000..7021d84966 --- /dev/null +++ b/projects/Allwinner/patches/linux/0064-media-v4l2-ctrls-fix-reference-to-freed-memory.patch @@ -0,0 +1,332 @@ +From ac34b79da14d67a9b494f6125186becbd067e225 Mon Sep 17 00:00:00 2001 +From: Hans Verkuil +Date: Mon, 12 Apr 2021 13:51:23 +0200 +Subject: [PATCH] media: v4l2-ctrls: fix reference to freed memory + +When controls are used together with the Request API, then for +each request a v4l2_ctrl_handler struct is allocated. This contains +the controls that can be set in a request. If a control is *not* set in +the request, then the value used in the most recent previous request +must be used, or the current value if it is not found in any outstanding +requests. + +The framework tried to find such a previous request and it would set +the 'req' pointer in struct v4l2_ctrl_ref to the v4l2_ctrl_ref of the +control in such a previous request. So far, so good. However, when that +previous request was applied to the hardware, returned to userspace, and +then userspace would re-init or free that request, any 'ref' pointer in +still-queued requests would suddenly point to freed memory. + +This was not noticed before since the drivers that use this expected +that each request would always have the controls set, so there was +never any need to find a control in older requests. This requirement +was relaxed, and now this bug surfaced. + +It was also made worse by changeset +2fae4d6aabc8 ("media: v4l2-ctrls: v4l2_ctrl_request_complete() should always set ref->req") +which increased the chance of this happening. + +The use of the 'req' pointer in v4l2_ctrl_ref was very fragile, so +drop this entirely. Instead add a valid_p_req bool to indicate that +p_req contains a valid value for this control. And if it is false, +then just use the current value of the control. + +Note that VIDIOC_G_EXT_CTRLS will always return -EACCES when attempting +to get a control from a request until the request is completed. And in +that case, all controls in the request will have the control value set +(i.e. valid_p_req is true). This means that the whole 'find the most +recent previous request containing a control' idea is pointless, and +the code can be simplified considerably. + +The v4l2_g_ext_ctrls_common() function was refactored a bit to make +it more understandable. It also avoids updating volatile controls +in a completed request since that was already done when the request +was completed. + +Signed-off-by: Hans Verkuil +Fixes: 2fae4d6aabc8 ("media: v4l2-ctrls: v4l2_ctrl_request_complete() should always set ref->req") +Fixes: 6fa6f831f095 ("media: v4l2-ctrls: add core request support") +Cc: # for v5.9 and up +Tested-by: Alexandre Courbot +Signed-off-by: Mauro Carvalho Chehab +--- + drivers/media/v4l2-core/v4l2-ctrls.c | 137 ++++++++++++--------------- + include/media/v4l2-ctrls.h | 12 ++- + 2 files changed, 70 insertions(+), 79 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c +index c7bcc5c25771..0d7fe1bd975a 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls.c +@@ -2504,7 +2504,16 @@ static void new_to_req(struct v4l2_ctrl_ref *ref) + if (!ref) + return; + ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req); +- ref->req = ref; ++ ref->valid_p_req = true; ++} ++ ++/* Copy the current value to the request value */ ++static void cur_to_req(struct v4l2_ctrl_ref *ref) ++{ ++ if (!ref) ++ return; ++ ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->p_req); ++ ref->valid_p_req = true; + } + + /* Copy the request value to the new value */ +@@ -2512,8 +2521,8 @@ static void req_to_new(struct v4l2_ctrl_ref *ref) + { + if (!ref) + return; +- if (ref->req) +- ptr_to_ptr(ref->ctrl, ref->req->p_req, ref->ctrl->p_new); ++ if (ref->valid_p_req) ++ ptr_to_ptr(ref->ctrl, ref->p_req, ref->ctrl->p_new); + else + ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new); + } +@@ -3694,39 +3703,8 @@ static void v4l2_ctrl_request_queue(struct media_request_object *obj) + struct v4l2_ctrl_handler *hdl = + container_of(obj, struct v4l2_ctrl_handler, req_obj); + struct v4l2_ctrl_handler *main_hdl = obj->priv; +- struct v4l2_ctrl_handler *prev_hdl = NULL; +- struct v4l2_ctrl_ref *ref_ctrl, *ref_ctrl_prev = NULL; + + mutex_lock(main_hdl->lock); +- if (list_empty(&main_hdl->requests_queued)) +- goto queue; +- +- prev_hdl = list_last_entry(&main_hdl->requests_queued, +- struct v4l2_ctrl_handler, requests_queued); +- /* +- * Note: prev_hdl and hdl must contain the same list of control +- * references, so if any differences are detected then that is a +- * driver bug and the WARN_ON is triggered. +- */ +- mutex_lock(prev_hdl->lock); +- ref_ctrl_prev = list_first_entry(&prev_hdl->ctrl_refs, +- struct v4l2_ctrl_ref, node); +- list_for_each_entry(ref_ctrl, &hdl->ctrl_refs, node) { +- if (ref_ctrl->req) +- continue; +- while (ref_ctrl_prev->ctrl->id < ref_ctrl->ctrl->id) { +- /* Should never happen, but just in case... */ +- if (list_is_last(&ref_ctrl_prev->node, +- &prev_hdl->ctrl_refs)) +- break; +- ref_ctrl_prev = list_next_entry(ref_ctrl_prev, node); +- } +- if (WARN_ON(ref_ctrl_prev->ctrl->id != ref_ctrl->ctrl->id)) +- break; +- ref_ctrl->req = ref_ctrl_prev->req; +- } +- mutex_unlock(prev_hdl->lock); +-queue: + list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued); + hdl->request_is_queued = true; + mutex_unlock(main_hdl->lock); +@@ -3783,7 +3761,7 @@ v4l2_ctrl_request_hdl_ctrl_find(struct v4l2_ctrl_handler *hdl, u32 id) + { + struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id); + +- return (ref && ref->req == ref) ? ref->ctrl : NULL; ++ return (ref && ref->valid_p_req) ? ref->ctrl : NULL; + } + EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find); + +@@ -3972,7 +3950,13 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 which) + return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL; + } + +-/* Get extended controls. Allocates the helpers array if needed. */ ++/* ++ * Get extended controls. Allocates the helpers array if needed. ++ * ++ * Note that v4l2_g_ext_ctrls_common() with 'which' set to ++ * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was ++ * completed, and in that case valid_p_req is true for all controls. ++ */ + static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, + struct v4l2_ext_controls *cs, + struct video_device *vdev) +@@ -3981,9 +3965,10 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, + struct v4l2_ctrl_helper *helpers = helper; + int ret; + int i, j; +- bool def_value; ++ bool is_default, is_request; + +- def_value = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); ++ is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL); ++ is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL); + + cs->error_idx = cs->count; + cs->which = V4L2_CTRL_ID2WHICH(cs->which); +@@ -4009,11 +3994,9 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, + ret = -EACCES; + + for (i = 0; !ret && i < cs->count; i++) { +- int (*ctrl_to_user)(struct v4l2_ext_control *c, +- struct v4l2_ctrl *ctrl); + struct v4l2_ctrl *master; +- +- ctrl_to_user = def_value ? def_to_user : cur_to_user; ++ bool is_volatile = false; ++ u32 idx = i; + + if (helpers[i].mref == NULL) + continue; +@@ -4023,31 +4006,48 @@ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl, + + v4l2_ctrl_lock(master); + +- /* g_volatile_ctrl will update the new control values */ +- if (!def_value && ++ /* ++ * g_volatile_ctrl will update the new control values. ++ * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and ++ * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests ++ * it is v4l2_ctrl_request_complete() that copies the ++ * volatile controls at the time of request completion ++ * to the request, so you don't want to do that again. ++ */ ++ if (!is_default && !is_request && + ((master->flags & V4L2_CTRL_FLAG_VOLATILE) || + (master->has_volatiles && !is_cur_manual(master)))) { + for (j = 0; j < master->ncontrols; j++) + cur_to_new(master->cluster[j]); + ret = call_op(master, g_volatile_ctrl); +- ctrl_to_user = new_to_user; ++ is_volatile = true; + } +- /* If OK, then copy the current (for non-volatile controls) +- or the new (for volatile controls) control values to the +- caller */ +- if (!ret) { +- u32 idx = i; + +- do { +- if (helpers[idx].ref->req) +- ret = req_to_user(cs->controls + idx, +- helpers[idx].ref->req); +- else +- ret = ctrl_to_user(cs->controls + idx, +- helpers[idx].ref->ctrl); +- idx = helpers[idx].next; +- } while (!ret && idx); ++ if (ret) { ++ v4l2_ctrl_unlock(master); ++ break; + } ++ ++ /* ++ * Copy the default value (if is_default is true), the ++ * request value (if is_request is true and p_req is valid), ++ * the new volatile value (if is_volatile is true) or the ++ * current value. ++ */ ++ do { ++ struct v4l2_ctrl_ref *ref = helpers[idx].ref; ++ ++ if (is_default) ++ ret = def_to_user(cs->controls + idx, ref->ctrl); ++ else if (is_request && ref->valid_p_req) ++ ret = req_to_user(cs->controls + idx, ref); ++ else if (is_volatile) ++ ret = new_to_user(cs->controls + idx, ref->ctrl); ++ else ++ ret = cur_to_user(cs->controls + idx, ref->ctrl); ++ idx = helpers[idx].next; ++ } while (!ret && idx); ++ + v4l2_ctrl_unlock(master); + } + +@@ -4690,8 +4690,6 @@ void v4l2_ctrl_request_complete(struct media_request *req, + unsigned int i; + + if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { +- ref->req = ref; +- + v4l2_ctrl_lock(master); + /* g_volatile_ctrl will update the current control values */ + for (i = 0; i < master->ncontrols; i++) +@@ -4701,21 +4699,12 @@ void v4l2_ctrl_request_complete(struct media_request *req, + v4l2_ctrl_unlock(master); + continue; + } +- if (ref->req == ref) ++ if (ref->valid_p_req) + continue; + ++ /* Copy the current control value into the request */ + v4l2_ctrl_lock(ctrl); +- if (ref->req) { +- ptr_to_ptr(ctrl, ref->req->p_req, ref->p_req); +- } else { +- ptr_to_ptr(ctrl, ctrl->p_cur, ref->p_req); +- /* +- * Set ref->req to ensure that when userspace wants to +- * obtain the controls of this request it will take +- * this value and not the current value of the control. +- */ +- ref->req = ref; +- } ++ cur_to_req(ref); + v4l2_ctrl_unlock(ctrl); + } + +@@ -4779,7 +4768,7 @@ int v4l2_ctrl_request_setup(struct media_request *req, + struct v4l2_ctrl_ref *r = + find_ref(hdl, master->cluster[i]->id); + +- if (r->req && r == r->req) { ++ if (r->valid_p_req) { + have_new_data = true; + break; + } +diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h +index c1d20bd8f25f..a5953b812878 100644 +--- a/include/media/v4l2-ctrls.h ++++ b/include/media/v4l2-ctrls.h +@@ -304,12 +304,14 @@ struct v4l2_ctrl { + * the control has been applied. This prevents applying controls + * from a cluster with multiple controls twice (when the first + * control of a cluster is applied, they all are). +- * @req: If set, this refers to another request that sets this control. ++ * @valid_p_req: If set, then p_req contains the control value for the request. + * @p_req: If the control handler containing this control reference + * is bound to a media request, then this points to the +- * value of the control that should be applied when the request ++ * value of the control that must be applied when the request + * is executed, or to the value of the control at the time +- * that the request was completed. ++ * that the request was completed. If @valid_p_req is false, ++ * then this control was never set for this request and the ++ * control will not be updated when this request is applied. + * + * Each control handler has a list of these refs. The list_head is used to + * keep a sorted-by-control-ID list of all controls, while the next pointer +@@ -322,7 +324,7 @@ struct v4l2_ctrl_ref { + struct v4l2_ctrl_helper *helper; + bool from_other_dev; + bool req_done; +- struct v4l2_ctrl_ref *req; ++ bool valid_p_req; + union v4l2_ctrl_ptr p_req; + }; + +@@ -349,7 +351,7 @@ struct v4l2_ctrl_ref { + * @error: The error code of the first failed control addition. + * @request_is_queued: True if the request was queued. + * @requests: List to keep track of open control handler request objects. +- * For the parent control handler (@req_obj.req == NULL) this ++ * For the parent control handler (@req_obj.ops == NULL) this + * is the list header. When the parent control handler is + * removed, it has to unbind and put all these requests since + * they refer to the parent. +-- +2.31.1 +