summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls.c36
1 files changed, 32 insertions, 4 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index d4e2c7318ee6..09992e76bad6 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -4121,8 +4121,19 @@ v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
obj = media_request_object_find(req, &req_ops, hdl);
if (obj)
return obj;
+ /*
+ * If there are no controls in this completed request,
+ * then that can only happen if:
+ *
+ * 1) no controls were present in the queued request, and
+ * 2) v4l2_ctrl_request_complete() could not allocate a
+ * control handler object to store the completed state in.
+ *
+ * So return ENOMEM to indicate that there was an out-of-memory
+ * error.
+ */
if (!set)
- return ERR_PTR(-ENOENT);
+ return ERR_PTR(-ENOMEM);
new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL);
if (!new_hdl)
@@ -4133,8 +4144,8 @@ v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
if (!ret)
ret = v4l2_ctrl_request_bind(req, new_hdl, hdl);
if (ret) {
+ v4l2_ctrl_handler_free(new_hdl);
kfree(new_hdl);
-
return ERR_PTR(ret);
}
@@ -4728,8 +4739,25 @@ void v4l2_ctrl_request_complete(struct media_request *req,
* wants to leave the controls unchanged.
*/
obj = media_request_object_find(req, &req_ops, main_hdl);
- if (!obj)
- return;
+ if (!obj) {
+ int ret;
+
+ /* Create a new request so the driver can return controls */
+ hdl = kzalloc(sizeof(*hdl), GFP_KERNEL);
+ if (!hdl)
+ return;
+
+ ret = v4l2_ctrl_handler_init(hdl, (main_hdl->nr_of_buckets - 1) * 8);
+ if (!ret)
+ ret = v4l2_ctrl_request_bind(req, hdl, main_hdl);
+ if (ret) {
+ v4l2_ctrl_handler_free(hdl);
+ kfree(hdl);
+ return;
+ }
+ hdl->request_is_queued = true;
+ obj = media_request_object_find(req, &req_ops, main_hdl);
+ }
hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj);
list_for_each_entry(ref, &hdl->ctrl_refs, node) {