aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c4
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c4
-rw-r--r--drivers/media/video/omap3isp/ispccdc.c3
-rw-r--r--drivers/media/video/omap3isp/ispstat.c3
-rw-r--r--drivers/media/video/v4l2-ctrls.c18
-rw-r--r--drivers/media/video/v4l2-event.c88
-rw-r--r--drivers/media/video/v4l2-fh.c4
-rw-r--r--drivers/media/video/v4l2-subdev.c7
-rw-r--r--drivers/media/video/vivi.c2
9 files changed, 38 insertions, 95 deletions
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index d4275d2460cb..38f052257f46 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -966,10 +966,6 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
966 return -ENOMEM; 966 return -ENOMEM;
967 } 967 }
968 v4l2_fh_init(&item->fh, s->vdev); 968 v4l2_fh_init(&item->fh, s->vdev);
969 if (s->type == IVTV_DEC_STREAM_TYPE_YUV ||
970 s->type == IVTV_DEC_STREAM_TYPE_MPG) {
971 res = v4l2_event_alloc(&item->fh, 60);
972 }
973 if (res < 0) { 969 if (res < 0) {
974 v4l2_fh_exit(&item->fh); 970 v4l2_fh_exit(&item->fh);
975 kfree(item); 971 kfree(item);
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index ff75d07097b2..3e5c090af112 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -1450,13 +1450,11 @@ static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscripti
1450 switch (sub->type) { 1450 switch (sub->type) {
1451 case V4L2_EVENT_VSYNC: 1451 case V4L2_EVENT_VSYNC:
1452 case V4L2_EVENT_EOS: 1452 case V4L2_EVENT_EOS:
1453 break;
1454 case V4L2_EVENT_CTRL: 1453 case V4L2_EVENT_CTRL:
1455 return v4l2_ctrl_subscribe_fh(fh, sub, 0); 1454 return v4l2_event_subscribe(fh, sub, 0);
1456 default: 1455 default:
1457 return -EINVAL; 1456 return -EINVAL;
1458 } 1457 }
1459 return v4l2_event_subscribe(fh, sub);
1460} 1458}
1461 1459
1462static int ivtv_log_status(struct file *file, void *fh) 1460static int ivtv_log_status(struct file *file, void *fh)
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index 39d501bda636..67662470661d 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -1691,7 +1691,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
1691 if (sub->type != V4L2_EVENT_OMAP3ISP_HS_VS) 1691 if (sub->type != V4L2_EVENT_OMAP3ISP_HS_VS)
1692 return -EINVAL; 1692 return -EINVAL;
1693 1693
1694 return v4l2_event_subscribe(fh, sub); 1694 return v4l2_event_subscribe(fh, sub, OMAP3ISP_CCDC_NEVENTS);
1695} 1695}
1696 1696
1697static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, 1697static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
@@ -2162,7 +2162,6 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
2162 sd->grp_id = 1 << 16; /* group ID for isp subdevs */ 2162 sd->grp_id = 1 << 16; /* group ID for isp subdevs */
2163 v4l2_set_subdevdata(sd, ccdc); 2163 v4l2_set_subdevdata(sd, ccdc);
2164 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; 2164 sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
2165 sd->nevents = OMAP3ISP_CCDC_NEVENTS;
2166 2165
2167 pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 2166 pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
2168 pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE; 2167 pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
diff --git a/drivers/media/video/omap3isp/ispstat.c b/drivers/media/video/omap3isp/ispstat.c
index b44cb685236a..808065948ac1 100644
--- a/drivers/media/video/omap3isp/ispstat.c
+++ b/drivers/media/video/omap3isp/ispstat.c
@@ -1032,7 +1032,6 @@ static int isp_stat_init_entities(struct ispstat *stat, const char *name,
1032 snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name); 1032 snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
1033 subdev->grp_id = 1 << 16; /* group ID for isp subdevs */ 1033 subdev->grp_id = 1 << 16; /* group ID for isp subdevs */
1034 subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE; 1034 subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
1035 subdev->nevents = STAT_NEVENTS;
1036 v4l2_set_subdevdata(subdev, stat); 1035 v4l2_set_subdevdata(subdev, stat);
1037 1036
1038 stat->pad.flags = MEDIA_PAD_FL_SINK; 1037 stat->pad.flags = MEDIA_PAD_FL_SINK;
@@ -1050,7 +1049,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
1050 if (sub->type != stat->event_type) 1049 if (sub->type != stat->event_type)
1051 return -EINVAL; 1050 return -EINVAL;
1052 1051
1053 return v4l2_event_subscribe(fh, sub); 1052 return v4l2_event_subscribe(fh, sub, STAT_NEVENTS);
1054} 1053}
1055 1054
1056int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, 1055int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index b63fe2a17fce..a37e5bff4342 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -1011,7 +1011,6 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
1011 insertion is an O(1) operation. */ 1011 insertion is an O(1) operation. */
1012 if (list_empty(&hdl->ctrl_refs) || id > node2id(hdl->ctrl_refs.prev)) { 1012 if (list_empty(&hdl->ctrl_refs) || id > node2id(hdl->ctrl_refs.prev)) {
1013 list_add_tail(&new_ref->node, &hdl->ctrl_refs); 1013 list_add_tail(&new_ref->node, &hdl->ctrl_refs);
1014 hdl->nr_of_refs++;
1015 goto insert_in_hash; 1014 goto insert_in_hash;
1016 } 1015 }
1017 1016
@@ -2051,20 +2050,3 @@ void v4l2_ctrl_del_event(struct v4l2_ctrl *ctrl,
2051 v4l2_ctrl_unlock(ctrl); 2050 v4l2_ctrl_unlock(ctrl);
2052} 2051}
2053EXPORT_SYMBOL(v4l2_ctrl_del_event); 2052EXPORT_SYMBOL(v4l2_ctrl_del_event);
2054
2055int v4l2_ctrl_subscribe_fh(struct v4l2_fh *fh,
2056 struct v4l2_event_subscription *sub, unsigned n)
2057{
2058 struct v4l2_ctrl_handler *hdl = fh->ctrl_handler;
2059 int ret = 0;
2060
2061 if (!ret) {
2062 if (hdl->nr_of_refs * 2 > n)
2063 n = hdl->nr_of_refs * 2;
2064 ret = v4l2_event_alloc(fh, n);
2065 }
2066 if (!ret)
2067 ret = v4l2_event_subscribe(fh, sub);
2068 return ret;
2069}
2070EXPORT_SYMBOL(v4l2_ctrl_subscribe_fh);
diff --git a/drivers/media/video/v4l2-event.c b/drivers/media/video/v4l2-event.c
index dc68f6085697..9e325dd3ce27 100644
--- a/drivers/media/video/v4l2-event.c
+++ b/drivers/media/video/v4l2-event.c
@@ -30,44 +30,11 @@
30#include <linux/sched.h> 30#include <linux/sched.h>
31#include <linux/slab.h> 31#include <linux/slab.h>
32 32
33static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh); 33static unsigned sev_pos(const struct v4l2_subscribed_event *sev, unsigned idx)
34
35int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n)
36{
37 unsigned long flags;
38
39 while (fh->nallocated < n) {
40 struct v4l2_kevent *kev;
41
42 kev = kzalloc(sizeof(*kev), GFP_KERNEL);
43 if (kev == NULL)
44 return -ENOMEM;
45
46 spin_lock_irqsave(&fh->vdev->fh_lock, flags);
47 list_add_tail(&kev->list, &fh->free);
48 fh->nallocated++;
49 spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
50 }
51
52 return 0;
53}
54EXPORT_SYMBOL_GPL(v4l2_event_alloc);
55
56#define list_kfree(list, type, member) \
57 while (!list_empty(list)) { \
58 type *hi; \
59 hi = list_first_entry(list, type, member); \
60 list_del(&hi->member); \
61 kfree(hi); \
62 }
63
64void v4l2_event_free(struct v4l2_fh *fh)
65{ 34{
66 list_kfree(&fh->free, struct v4l2_kevent, list); 35 idx += sev->first;
67 list_kfree(&fh->available, struct v4l2_kevent, list); 36 return idx >= sev->elems ? idx - sev->elems : idx;
68 v4l2_event_unsubscribe_all(fh);
69} 37}
70EXPORT_SYMBOL_GPL(v4l2_event_free);
71 38
72static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event) 39static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
73{ 40{
@@ -84,11 +51,13 @@ static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
84 WARN_ON(fh->navailable == 0); 51 WARN_ON(fh->navailable == 0);
85 52
86 kev = list_first_entry(&fh->available, struct v4l2_kevent, list); 53 kev = list_first_entry(&fh->available, struct v4l2_kevent, list);
87 list_move(&kev->list, &fh->free); 54 list_del(&kev->list);
88 fh->navailable--; 55 fh->navailable--;
89 56
90 kev->event.pending = fh->navailable; 57 kev->event.pending = fh->navailable;
91 *event = kev->event; 58 *event = kev->event;
59 kev->sev->first = sev_pos(kev->sev, 1);
60 kev->sev->in_use--;
92 61
93 spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); 62 spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
94 63
@@ -154,17 +123,24 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e
154 fh->sequence++; 123 fh->sequence++;
155 124
156 /* Do we have any free events? */ 125 /* Do we have any free events? */
157 if (list_empty(&fh->free)) 126 if (sev->in_use == sev->elems) {
158 return; 127 /* no, remove the oldest one */
128 kev = sev->events + sev_pos(sev, 0);
129 list_del(&kev->list);
130 sev->in_use--;
131 sev->first = sev_pos(sev, 1);
132 fh->navailable--;
133 }
159 134
160 /* Take one and fill it. */ 135 /* Take one and fill it. */
161 kev = list_first_entry(&fh->free, struct v4l2_kevent, list); 136 kev = sev->events + sev_pos(sev, sev->in_use);
162 kev->event.type = ev->type; 137 kev->event.type = ev->type;
163 kev->event.u = ev->u; 138 kev->event.u = ev->u;
164 kev->event.id = ev->id; 139 kev->event.id = ev->id;
165 kev->event.timestamp = *ts; 140 kev->event.timestamp = *ts;
166 kev->event.sequence = fh->sequence; 141 kev->event.sequence = fh->sequence;
167 list_move_tail(&kev->list, &fh->available); 142 sev->in_use++;
143 list_add_tail(&kev->list, &fh->available);
168 144
169 fh->navailable++; 145 fh->navailable++;
170 146
@@ -209,38 +185,39 @@ int v4l2_event_pending(struct v4l2_fh *fh)
209EXPORT_SYMBOL_GPL(v4l2_event_pending); 185EXPORT_SYMBOL_GPL(v4l2_event_pending);
210 186
211int v4l2_event_subscribe(struct v4l2_fh *fh, 187int v4l2_event_subscribe(struct v4l2_fh *fh,
212 struct v4l2_event_subscription *sub) 188 struct v4l2_event_subscription *sub, unsigned elems)
213{ 189{
214 struct v4l2_subscribed_event *sev, *found_ev; 190 struct v4l2_subscribed_event *sev, *found_ev;
215 struct v4l2_ctrl *ctrl = NULL; 191 struct v4l2_ctrl *ctrl = NULL;
216 unsigned long flags; 192 unsigned long flags;
193 unsigned i;
217 194
195 if (elems < 1)
196 elems = 1;
218 if (sub->type == V4L2_EVENT_CTRL) { 197 if (sub->type == V4L2_EVENT_CTRL) {
219 ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id); 198 ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id);
220 if (ctrl == NULL) 199 if (ctrl == NULL)
221 return -EINVAL; 200 return -EINVAL;
222 } 201 }
223 202
224 sev = kzalloc(sizeof(*sev), GFP_KERNEL); 203 sev = kzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems, GFP_KERNEL);
225 if (!sev) 204 if (!sev)
226 return -ENOMEM; 205 return -ENOMEM;
206 for (i = 0; i < elems; i++)
207 sev->events[i].sev = sev;
208 sev->type = sub->type;
209 sev->id = sub->id;
210 sev->flags = sub->flags;
211 sev->fh = fh;
212 sev->elems = elems;
227 213
228 spin_lock_irqsave(&fh->vdev->fh_lock, flags); 214 spin_lock_irqsave(&fh->vdev->fh_lock, flags);
229
230 found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); 215 found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);
231 if (!found_ev) { 216 if (!found_ev)
232 INIT_LIST_HEAD(&sev->list);
233 sev->type = sub->type;
234 sev->id = sub->id;
235 sev->fh = fh;
236 sev->flags = sub->flags;
237
238 list_add(&sev->list, &fh->subscribed); 217 list_add(&sev->list, &fh->subscribed);
239 }
240
241 spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); 218 spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
242 219
243 /* v4l2_ctrl_add_fh uses a mutex, so do this outside the spin lock */ 220 /* v4l2_ctrl_add_event uses a mutex, so do this outside the spin lock */
244 if (found_ev) 221 if (found_ev)
245 kfree(sev); 222 kfree(sev);
246 else if (ctrl) 223 else if (ctrl)
@@ -250,7 +227,7 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
250} 227}
251EXPORT_SYMBOL_GPL(v4l2_event_subscribe); 228EXPORT_SYMBOL_GPL(v4l2_event_subscribe);
252 229
253static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh) 230void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
254{ 231{
255 struct v4l2_event_subscription sub; 232 struct v4l2_event_subscription sub;
256 struct v4l2_subscribed_event *sev; 233 struct v4l2_subscribed_event *sev;
@@ -271,6 +248,7 @@ static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
271 v4l2_event_unsubscribe(fh, &sub); 248 v4l2_event_unsubscribe(fh, &sub);
272 } while (sev); 249 } while (sev);
273} 250}
251EXPORT_SYMBOL_GPL(v4l2_event_unsubscribe_all);
274 252
275int v4l2_event_unsubscribe(struct v4l2_fh *fh, 253int v4l2_event_unsubscribe(struct v4l2_fh *fh,
276 struct v4l2_event_subscription *sub) 254 struct v4l2_event_subscription *sub)
diff --git a/drivers/media/video/v4l2-fh.c b/drivers/media/video/v4l2-fh.c
index 333b8c8f40d6..122822d2b8b2 100644
--- a/drivers/media/video/v4l2-fh.c
+++ b/drivers/media/video/v4l2-fh.c
@@ -37,9 +37,7 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
37 INIT_LIST_HEAD(&fh->list); 37 INIT_LIST_HEAD(&fh->list);
38 set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags); 38 set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
39 fh->prio = V4L2_PRIORITY_UNSET; 39 fh->prio = V4L2_PRIORITY_UNSET;
40
41 init_waitqueue_head(&fh->wait); 40 init_waitqueue_head(&fh->wait);
42 INIT_LIST_HEAD(&fh->free);
43 INIT_LIST_HEAD(&fh->available); 41 INIT_LIST_HEAD(&fh->available);
44 INIT_LIST_HEAD(&fh->subscribed); 42 INIT_LIST_HEAD(&fh->subscribed);
45 fh->sequence = -1; 43 fh->sequence = -1;
@@ -88,7 +86,7 @@ void v4l2_fh_exit(struct v4l2_fh *fh)
88{ 86{
89 if (fh->vdev == NULL) 87 if (fh->vdev == NULL)
90 return; 88 return;
91 v4l2_event_free(fh); 89 v4l2_event_unsubscribe_all(fh);
92 fh->vdev = NULL; 90 fh->vdev = NULL;
93} 91}
94EXPORT_SYMBOL_GPL(v4l2_fh_exit); 92EXPORT_SYMBOL_GPL(v4l2_fh_exit);
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c
index 3b67a8584916..b7967c9dc4ae 100644
--- a/drivers/media/video/v4l2-subdev.c
+++ b/drivers/media/video/v4l2-subdev.c
@@ -76,13 +76,6 @@ static int subdev_open(struct file *file)
76 } 76 }
77 77
78 v4l2_fh_init(&subdev_fh->vfh, vdev); 78 v4l2_fh_init(&subdev_fh->vfh, vdev);
79
80 if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
81 ret = v4l2_event_alloc(&subdev_fh->vfh, sd->nevents);
82 if (ret)
83 goto err;
84 }
85
86 v4l2_fh_add(&subdev_fh->vfh); 79 v4l2_fh_add(&subdev_fh->vfh);
87 file->private_data = &subdev_fh->vfh; 80 file->private_data = &subdev_fh->vfh;
88#if defined(CONFIG_MEDIA_CONTROLLER) 81#if defined(CONFIG_MEDIA_CONTROLLER)
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 1b90713b44c5..cc1cf6b17183 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -993,7 +993,7 @@ static int vidioc_subscribe_event(struct v4l2_fh *fh,
993{ 993{
994 switch (sub->type) { 994 switch (sub->type) {
995 case V4L2_EVENT_CTRL: 995 case V4L2_EVENT_CTRL:
996 return v4l2_ctrl_subscribe_fh(fh, sub, 0); 996 return v4l2_event_subscribe(fh, sub, 0);
997 default: 997 default:
998 return -EINVAL; 998 return -EINVAL;
999 } 999 }