From 3e366149b8957f809081e5f0f70d209175127e29 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 8 Apr 2012 12:59:47 -0300 Subject: [PATCH] [media] v4l2-ctrls: Use v4l2_subscribed_event_ops Signed-off-by: Hans de Goede [hans.verkuil@cisco.com: Fix a locking bug] Acked-by: Hans Verkuil Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-ioctl.c | 3 +- drivers/media/video/v4l2-ctrls.c | 41 ++++++++++++++++++++++----- drivers/media/video/v4l2-event.c | 39 ------------------------- include/media/v4l2-ctrls.h | 7 ++--- 4 files changed, 39 insertions(+), 51 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index a7730fd4827f..70cd802c9ca8 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -1468,8 +1468,9 @@ static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscripti switch (sub->type) { case V4L2_EVENT_VSYNC: case V4L2_EVENT_EOS: - case V4L2_EVENT_CTRL: return v4l2_event_subscribe(fh, sub, 0, NULL); + case V4L2_EVENT_CTRL: + return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops); default: return -EINVAL; } diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 91b197819fc2..ae544d870d7d 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c @@ -2424,9 +2424,13 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val) } EXPORT_SYMBOL(v4l2_ctrl_s_ctrl); -void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl, - struct v4l2_subscribed_event *sev) +static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev) { + struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); + + if (ctrl == NULL) + return -EINVAL; + v4l2_ctrl_lock(ctrl); list_add_tail(&sev->node, &ctrl->ev_subs); if (ctrl->type != V4L2_CTRL_TYPE_CTRL_CLASS && @@ -2440,17 +2444,40 @@ void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl, v4l2_event_queue_fh(sev->fh, &ev); } v4l2_ctrl_unlock(ctrl); + return 0; } -EXPORT_SYMBOL(v4l2_ctrl_add_event); -void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, - struct v4l2_subscribed_event *sev) +static void v4l2_ctrl_del_event(struct v4l2_subscribed_event *sev) { + struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id); + v4l2_ctrl_lock(ctrl); list_del(&sev->node); v4l2_ctrl_unlock(ctrl); } -EXPORT_SYMBOL(v4l2_ctrl_del_event); + +void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new) +{ + u32 old_changes = old->u.ctrl.changes; + + old->u.ctrl = new->u.ctrl; + old->u.ctrl.changes |= old_changes; +} +EXPORT_SYMBOL(v4l2_ctrl_replace); + +void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new) +{ + new->u.ctrl.changes |= old->u.ctrl.changes; +} +EXPORT_SYMBOL(v4l2_ctrl_merge); + +const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops = { + .add = v4l2_ctrl_add_event, + .del = v4l2_ctrl_del_event, + .replace = v4l2_ctrl_replace, + .merge = v4l2_ctrl_merge, +}; +EXPORT_SYMBOL(v4l2_ctrl_sub_ev_ops); int v4l2_ctrl_log_status(struct file *file, void *fh) { @@ -2468,7 +2495,7 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub) { if (sub->type == V4L2_EVENT_CTRL) - return v4l2_event_subscribe(fh, sub, 0, NULL); + return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops); return -EINVAL; } EXPORT_SYMBOL(v4l2_ctrl_subscribe_event); diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c index 0ba2dfa86d07..60b4e2e9c874 100644 --- a/drivers/media/video/v4l2-event.c +++ b/drivers/media/video/v4l2-event.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -203,30 +202,11 @@ int v4l2_event_pending(struct v4l2_fh *fh) } EXPORT_SYMBOL_GPL(v4l2_event_pending); -static void ctrls_replace(struct v4l2_event *old, const struct v4l2_event *new) -{ - u32 old_changes = old->u.ctrl.changes; - - old->u.ctrl = new->u.ctrl; - old->u.ctrl.changes |= old_changes; -} - -static void ctrls_merge(const struct v4l2_event *old, struct v4l2_event *new) -{ - new->u.ctrl.changes |= old->u.ctrl.changes; -} - -static const struct v4l2_subscribed_event_ops ctrl_ops = { - .replace = ctrls_replace, - .merge = ctrls_merge, -}; - int v4l2_event_subscribe(struct v4l2_fh *fh, struct v4l2_event_subscription *sub, unsigned elems, const struct v4l2_subscribed_event_ops *ops) { struct v4l2_subscribed_event *sev, *found_ev; - struct v4l2_ctrl *ctrl = NULL; unsigned long flags; unsigned i; @@ -235,11 +215,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, if (elems < 1) elems = 1; - if (sub->type == V4L2_EVENT_CTRL) { - ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id); - if (ctrl == NULL) - return -EINVAL; - } sev = kzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, GFP_KERNEL); if (!sev) @@ -251,9 +226,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, sev->flags = sub->flags; sev->fh = fh; sev->ops = ops; - if (ctrl) { - sev->ops = &ctrl_ops; - } spin_lock_irqsave(&fh->vdev->fh_lock, flags); found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); @@ -275,10 +247,6 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, } } - /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */ - if (ctrl) - v4l2_ctrl_add_event(ctrl, sev); - /* Mark as ready for use */ sev->elems = elems; @@ -338,13 +306,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh, if (sev && sev->ops && sev->ops->del) sev->ops->del(sev); - if (sev && sev->type == V4L2_EVENT_CTRL) { - struct v4l2_ctrl *ctrl = v4l2_ctrl_find(fh->ctrl_handler, sev->id); - - if (ctrl) - v4l2_ctrl_del_event(ctrl, sev); - } - kfree(sev); return 0; diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 8920f8210eab..c6f6b4c2c5f2 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -491,10 +491,9 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl); int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val); /* Internal helper functions that deal with control events. */ -void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl, - struct v4l2_subscribed_event *sev); -void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, - struct v4l2_subscribed_event *sev); +extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops; +void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new); +void v4l2_ctrl_merge(const struct v4l2_event *old, struct v4l2_event *new); struct file; /* Can be used as a vidioc_log_status function that just dumps all controls -- 2.30.2