On 4 June 2018 at 08:46, Hans Verkuil <hverk...@xs4all.nl> wrote:
> From: Hans Verkuil <hans.verk...@cisco.com>
>
> Integrate the request support. This adds the v4l2_ctrl_request_complete
> and v4l2_ctrl_request_setup functions to complete a request and (as a
> helper function) to apply a request to the hardware.
>
> It takes care of queuing requests and correctly chaining control values
> in the request queue.
>
> Note that when a request is marked completed it will copy control values
> to the internal request state. This can be optimized in the future since
> this is sub-optimal when dealing with large compound and/or array controls.
>
> For the initial 'stateless codec' use-case the current implementation is
> sufficient.
>
> Signed-off-by: Hans Verkuil <hans.verk...@cisco.com>
> ---
>  drivers/media/v4l2-core/v4l2-ctrls.c | 331 ++++++++++++++++++++++++++-
>  include/media/v4l2-ctrls.h           |  51 +++++
>  2 files changed, 376 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
> b/drivers/media/v4l2-core/v4l2-ctrls.c
> index da4cc1485dc4..bd4818507486 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -1647,6 +1647,13 @@ static int new_to_user(struct v4l2_ext_control *c,
>         return ptr_to_user(c, ctrl, ctrl->p_new);
>  }
>
> +/* Helper function: copy the request value back to the caller */
> +static int req_to_user(struct v4l2_ext_control *c,
> +                      struct v4l2_ctrl_ref *ref)
> +{
> +       return ptr_to_user(c, ref->ctrl, ref->p_req);
> +}
> +
>  /* Helper function: copy the initial control value back to the caller */
>  static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
>  {
> @@ -1766,6 +1773,26 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
>         ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
>  }
>
> +/* Copy the new value to the request value */
> +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;
> +}
> +
> +/* Copy the request value to the new value */
> +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);
> +       else
> +               ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);
> +}
> +
>  /* Return non-zero if one or more of the controls in the cluster has a new
>     value that differs from the current value. */
>  static int cluster_changed(struct v4l2_ctrl *master)
> @@ -1875,6 +1902,9 @@ int v4l2_ctrl_handler_init_class(struct 
> v4l2_ctrl_handler *hdl,
>         lockdep_set_class_and_name(hdl->lock, key, name);
>         INIT_LIST_HEAD(&hdl->ctrls);
>         INIT_LIST_HEAD(&hdl->ctrl_refs);
> +       INIT_LIST_HEAD(&hdl->requests);
> +       INIT_LIST_HEAD(&hdl->requests_queued);
> +       hdl->request_is_queued = false;
>         hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
>         hdl->buckets = kvmalloc_array(hdl->nr_of_buckets,
>                                       sizeof(hdl->buckets[0]),
> @@ -1895,6 +1925,14 @@ 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)) {
> +               struct v4l2_ctrl_handler *req, *next_req;
> +
> +               list_for_each_entry_safe(req, next_req, &hdl->requests, 
> requests) {
> +                       media_request_object_unbind(&req->req_obj);
> +                       media_request_object_put(&req->req_obj);
> +               }
> +       }
>         mutex_lock(hdl->lock);
>         /* Free all nodes */
>         list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) {
> @@ -2816,6 +2854,128 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, 
> struct v4l2_querymenu *qm)
>  }
>  EXPORT_SYMBOL(v4l2_querymenu);
>
> +static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl,
> +                                  const struct v4l2_ctrl_handler *from)
> +{
> +       struct v4l2_ctrl_ref *ref;
> +       int err;
> +
> +       if (WARN_ON(!hdl || hdl == from))
> +               return -EINVAL;
> +
> +       if (hdl->error)
> +               return hdl->error;
> +
> +       WARN_ON(hdl->lock != &hdl->_lock);
> +
> +       mutex_lock(from->lock);
> +       list_for_each_entry(ref, &from->ctrl_refs, node) {
> +               struct v4l2_ctrl *ctrl = ref->ctrl;
> +               struct v4l2_ctrl_ref *new_ref;
> +
> +               /* Skip refs inherited from other devices */
> +               if (ref->from_other_dev)
> +                       continue;
> +               /* And buttons */
> +               if (ctrl->type == V4L2_CTRL_TYPE_BUTTON)
> +                       continue;
> +               err = handler_new_ref(hdl, ctrl, &new_ref, false, true);
> +               if (err) {
> +                       printk("%s: handler_new_ref on control %x (%s) 
> returned %d\n", __func__, ctrl->id, ctrl->name, err);

Nit: pr_err + pr_fmt above?
-- 
Ezequiel GarcĂ­a, VanguardiaSur
www.vanguardiasur.com.ar

Reply via email to