aboutsummaryrefslogtreecommitdiffstats
path: root/include/media
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2011-06-13 18:24:17 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:53:31 -0400
commitf1e393de382af9b9bd2462a42bfa16b8c501d81b (patch)
tree1135a4a27166d3947ebfcf2be171efa2d8cd3228 /include/media
parent77068d36d8b9e9902a89b4bb01011d41926f5420 (diff)
[media] v4l2-event/ctrls/fh: allocate events per fh and per type instead of just per-fh
The driver had to decide how many events to allocate when the v4l2_fh struct was created. It was possible to add more events afterwards, but there was no way to ensure that you wouldn't miss important events if the event queue would fill up for that filehandle. In addition, once there were no more free events, any new events were simply dropped on the floor. For the control event in particular this made life very difficult since control status/value changes could just be missed if the number of allocated events and the speed at which the application read events was too low to keep up with the number of generated events. The application would have no idea what the latest state was for a control since it could have missed the latest control change. So this patch makes some major changes in how events are allocated. Instead of allocating events per-filehandle they are now allocated when subscribing an event. So for that particular event type N events (determined by the driver) are allocated. Those events are reserved for that particular event type. This ensures that you will not miss events for a particular type altogether. In addition, if there are N events in use and a new event is raised, then the oldest event is dropped and the new one is added. So the latest event is always available. This can be further improved by adding the ability to merge the state of two events together, ensuring that no data is lost at all. This will be added in the next patch. This also makes it possible to allow the user to determine the number of events that will be allocated. This is not implemented at the moment, but would be trivial. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'include/media')
-rw-r--r--include/media/v4l2-ctrls.h19
-rw-r--r--include/media/v4l2-event.h18
-rw-r--r--include/media/v4l2-fh.h2
-rw-r--r--include/media/v4l2-subdev.h2
4 files changed, 15 insertions, 26 deletions
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index a15e9098f98b..69662912e50c 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -171,7 +171,6 @@ struct v4l2_ctrl_ref {
171 * control is needed multiple times, so this is a simple 171 * control is needed multiple times, so this is a simple
172 * optimization. 172 * optimization.
173 * @buckets: Buckets for the hashing. Allows for quick control lookup. 173 * @buckets: Buckets for the hashing. Allows for quick control lookup.
174 * @nr_of_refs: Total number of control references in the list.
175 * @nr_of_buckets: Total number of buckets in the array. 174 * @nr_of_buckets: Total number of buckets in the array.
176 * @error: The error code of the first failed control addition. 175 * @error: The error code of the first failed control addition.
177 */ 176 */
@@ -181,7 +180,6 @@ struct v4l2_ctrl_handler {
181 struct list_head ctrl_refs; 180 struct list_head ctrl_refs;
182 struct v4l2_ctrl_ref *cached; 181 struct v4l2_ctrl_ref *cached;
183 struct v4l2_ctrl_ref **buckets; 182 struct v4l2_ctrl_ref **buckets;
184 u16 nr_of_refs;
185 u16 nr_of_buckets; 183 u16 nr_of_buckets;
186 int error; 184 int error;
187}; 185};
@@ -499,23 +497,6 @@ void v4l2_ctrl_add_event(struct v4l2_ctrl *ctrl,
499void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl, 497void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
500 struct v4l2_subscribed_event *sev); 498 struct v4l2_subscribed_event *sev);
501 499
502/** v4l2_ctrl_subscribe_fh() - Helper function that subscribes a control event.
503 * @fh: The file handler that subscribed the control event.
504 * @sub: The event to subscribe (type must be V4L2_EVENT_CTRL).
505 * @n: How many events should be allocated? (Passed to v4l2_event_alloc).
506 * Recommended to set to twice the number of controls plus whatever
507 * is needed for other events. This function will set n to
508 * max(n, 2 * fh->ctrl_handler->nr_of_refs).
509 *
510 * A helper function that initializes the fh for events, allocates the
511 * list of events and subscribes the control event.
512 *
513 * Typically called in the handler of VIDIOC_SUBSCRIBE_EVENT in the
514 * V4L2_EVENT_CTRL case.
515 */
516int v4l2_ctrl_subscribe_fh(struct v4l2_fh *fh,
517 struct v4l2_event_subscription *sub, unsigned n);
518
519/* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */ 500/* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */
520int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc); 501int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc);
521int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm); 502int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm);
diff --git a/include/media/v4l2-event.h b/include/media/v4l2-event.h
index eda17f8d78bc..8d681e5ca552 100644
--- a/include/media/v4l2-event.h
+++ b/include/media/v4l2-event.h
@@ -30,10 +30,15 @@
30#include <linux/wait.h> 30#include <linux/wait.h>
31 31
32struct v4l2_fh; 32struct v4l2_fh;
33struct v4l2_subscribed_event;
33struct video_device; 34struct video_device;
34 35
35struct v4l2_kevent { 36struct v4l2_kevent {
37 /* list node for the v4l2_fh->available list */
36 struct list_head list; 38 struct list_head list;
39 /* pointer to parent v4l2_subscribed_event */
40 struct v4l2_subscribed_event *sev;
41 /* event itself */
37 struct v4l2_event event; 42 struct v4l2_event event;
38}; 43};
39 44
@@ -50,18 +55,25 @@ struct v4l2_subscribed_event {
50 struct v4l2_fh *fh; 55 struct v4l2_fh *fh;
51 /* list node that hooks into the object's event list (if there is one) */ 56 /* list node that hooks into the object's event list (if there is one) */
52 struct list_head node; 57 struct list_head node;
58 /* the number of elements in the events array */
59 unsigned elems;
60 /* the index of the events containing the oldest available event */
61 unsigned first;
62 /* the number of queued events */
63 unsigned in_use;
64 /* an array of elems events */
65 struct v4l2_kevent events[];
53}; 66};
54 67
55int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n);
56void v4l2_event_free(struct v4l2_fh *fh);
57int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event, 68int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
58 int nonblocking); 69 int nonblocking);
59void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev); 70void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev);
60void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev); 71void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev);
61int v4l2_event_pending(struct v4l2_fh *fh); 72int v4l2_event_pending(struct v4l2_fh *fh);
62int v4l2_event_subscribe(struct v4l2_fh *fh, 73int v4l2_event_subscribe(struct v4l2_fh *fh,
63 struct v4l2_event_subscription *sub); 74 struct v4l2_event_subscription *sub, unsigned elems);
64int v4l2_event_unsubscribe(struct v4l2_fh *fh, 75int v4l2_event_unsubscribe(struct v4l2_fh *fh,
65 struct v4l2_event_subscription *sub); 76 struct v4l2_event_subscription *sub);
77void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);
66 78
67#endif /* V4L2_EVENT_H */ 79#endif /* V4L2_EVENT_H */
diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h
index bfc0457ca6ef..52513c225c18 100644
--- a/include/media/v4l2-fh.h
+++ b/include/media/v4l2-fh.h
@@ -40,10 +40,8 @@ struct v4l2_fh {
40 /* Events */ 40 /* Events */
41 wait_queue_head_t wait; 41 wait_queue_head_t wait;
42 struct list_head subscribed; /* Subscribed events */ 42 struct list_head subscribed; /* Subscribed events */
43 struct list_head free; /* Events ready for use */
44 struct list_head available; /* Dequeueable event */ 43 struct list_head available; /* Dequeueable event */
45 unsigned int navailable; 44 unsigned int navailable;
46 unsigned int nallocated; /* Number of allocated events */
47 u32 sequence; 45 u32 sequence;
48}; 46};
49 47
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 2884e3e69cb1..b05579b4adb7 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -513,8 +513,6 @@ struct v4l2_subdev {
513 void *host_priv; 513 void *host_priv;
514 /* subdev device node */ 514 /* subdev device node */
515 struct video_device devnode; 515 struct video_device devnode;
516 /* number of events to be allocated on open */
517 unsigned int nevents;
518}; 516};
519 517
520#define media_entity_to_v4l2_subdev(ent) \ 518#define media_entity_to_v4l2_subdev(ent) \