Skip to content

Commit

Permalink
[media] v4l2-events/fh: merge v4l2_events into v4l2_fh
Browse files Browse the repository at this point in the history
Drivers that supported events used to be rare, but now that controls can also
raise events this will become much more common since almost all drivers have
controls.

This means that keeping struct v4l2_events as a separate struct make no more
sense. Merging it into struct v4l2_fh simplifies things substantially as it
is now an integral part of the filehandle struct.

Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
Hans Verkuil authored and Mauro Carvalho Chehab committed Jul 27, 2011
1 parent 95904d4 commit 523f46d
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 115 deletions.
6 changes: 3 additions & 3 deletions drivers/media/video/ivtv/ivtv-fileops.c
Original file line number Diff line number Diff line change
Expand Up @@ -722,8 +722,8 @@ unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait)

/* If there are subscribed events, then only use the new event
API instead of the old video.h based API. */
if (!list_empty(&id->fh.events->subscribed)) {
poll_wait(filp, &id->fh.events->wait, wait);
if (!list_empty(&id->fh.subscribed)) {
poll_wait(filp, &id->fh.wait, wait);
/* Turn off the old-style vsync events */
clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
if (v4l2_event_pending(&id->fh))
Expand Down Expand Up @@ -773,7 +773,7 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait)
if (v4l2_event_pending(&id->fh))
res |= POLLPRI;
else
poll_wait(filp, &id->fh.events->wait, wait);
poll_wait(filp, &id->fh.wait, wait);

if (s->q_full.length || s->q_io.length)
return res | POLLIN | POLLRDNORM;
Expand Down
2 changes: 0 additions & 2 deletions drivers/media/video/v4l2-ctrls.c
Original file line number Diff line number Diff line change
Expand Up @@ -2070,8 +2070,6 @@ int v4l2_ctrl_subscribe_fh(struct v4l2_fh *fh,
struct v4l2_ctrl_handler *hdl = fh->ctrl_handler;
int ret = 0;

if (!fh->events)
ret = v4l2_event_init(fh);
if (!ret) {
if (hdl->nr_of_refs * 2 > n)
n = hdl->nr_of_refs * 2;
Expand Down
93 changes: 25 additions & 68 deletions drivers/media/video/v4l2-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,44 +32,20 @@

static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);

int v4l2_event_init(struct v4l2_fh *fh)
{
fh->events = kzalloc(sizeof(*fh->events), GFP_KERNEL);
if (fh->events == NULL)
return -ENOMEM;

init_waitqueue_head(&fh->events->wait);

INIT_LIST_HEAD(&fh->events->free);
INIT_LIST_HEAD(&fh->events->available);
INIT_LIST_HEAD(&fh->events->subscribed);

fh->events->sequence = -1;

return 0;
}
EXPORT_SYMBOL_GPL(v4l2_event_init);

int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n)
{
struct v4l2_events *events = fh->events;
unsigned long flags;

if (!events) {
WARN_ON(1);
return -ENOMEM;
}

while (events->nallocated < n) {
while (fh->nallocated < n) {
struct v4l2_kevent *kev;

kev = kzalloc(sizeof(*kev), GFP_KERNEL);
if (kev == NULL)
return -ENOMEM;

spin_lock_irqsave(&fh->vdev->fh_lock, flags);
list_add_tail(&kev->list, &events->free);
events->nallocated++;
list_add_tail(&kev->list, &fh->free);
fh->nallocated++;
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
}

Expand All @@ -87,40 +63,31 @@ EXPORT_SYMBOL_GPL(v4l2_event_alloc);

void v4l2_event_free(struct v4l2_fh *fh)
{
struct v4l2_events *events = fh->events;

if (!events)
return;

list_kfree(&events->free, struct v4l2_kevent, list);
list_kfree(&events->available, struct v4l2_kevent, list);
list_kfree(&fh->free, struct v4l2_kevent, list);
list_kfree(&fh->available, struct v4l2_kevent, list);
v4l2_event_unsubscribe_all(fh);

kfree(events);
fh->events = NULL;
}
EXPORT_SYMBOL_GPL(v4l2_event_free);

static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
{
struct v4l2_events *events = fh->events;
struct v4l2_kevent *kev;
unsigned long flags;

spin_lock_irqsave(&fh->vdev->fh_lock, flags);

if (list_empty(&events->available)) {
if (list_empty(&fh->available)) {
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
return -ENOENT;
}

WARN_ON(events->navailable == 0);
WARN_ON(fh->navailable == 0);

kev = list_first_entry(&events->available, struct v4l2_kevent, list);
list_move(&kev->list, &events->free);
events->navailable--;
kev = list_first_entry(&fh->available, struct v4l2_kevent, list);
list_move(&kev->list, &fh->free);
fh->navailable--;

kev->event.pending = events->navailable;
kev->event.pending = fh->navailable;
*event = kev->event;

spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
Expand All @@ -131,7 +98,6 @@ static int __v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event)
int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
int nonblocking)
{
struct v4l2_events *events = fh->events;
int ret;

if (nonblocking)
Expand All @@ -142,8 +108,8 @@ int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
mutex_unlock(fh->vdev->lock);

do {
ret = wait_event_interruptible(events->wait,
events->navailable != 0);
ret = wait_event_interruptible(fh->wait,
fh->navailable != 0);
if (ret < 0)
break;

Expand All @@ -161,12 +127,11 @@ EXPORT_SYMBOL_GPL(v4l2_event_dequeue);
static struct v4l2_subscribed_event *v4l2_event_subscribed(
struct v4l2_fh *fh, u32 type, u32 id)
{
struct v4l2_events *events = fh->events;
struct v4l2_subscribed_event *sev;

assert_spin_locked(&fh->vdev->fh_lock);

list_for_each_entry(sev, &events->subscribed, list) {
list_for_each_entry(sev, &fh->subscribed, list) {
if (sev->type == type && sev->id == id)
return sev;
}
Expand All @@ -177,7 +142,6 @@ static struct v4l2_subscribed_event *v4l2_event_subscribed(
static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev,
const struct timespec *ts)
{
struct v4l2_events *events = fh->events;
struct v4l2_subscribed_event *sev;
struct v4l2_kevent *kev;

Expand All @@ -187,24 +151,24 @@ static void __v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *e
return;

/* Increase event sequence number on fh. */
events->sequence++;
fh->sequence++;

/* Do we have any free events? */
if (list_empty(&events->free))
if (list_empty(&fh->free))
return;

/* Take one and fill it. */
kev = list_first_entry(&events->free, struct v4l2_kevent, list);
kev = list_first_entry(&fh->free, struct v4l2_kevent, list);
kev->event.type = ev->type;
kev->event.u = ev->u;
kev->event.id = ev->id;
kev->event.timestamp = *ts;
kev->event.sequence = events->sequence;
list_move_tail(&kev->list, &events->available);
kev->event.sequence = fh->sequence;
list_move_tail(&kev->list, &fh->available);

events->navailable++;
fh->navailable++;

wake_up_all(&events->wait);
wake_up_all(&fh->wait);
}

void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
Expand Down Expand Up @@ -240,24 +204,18 @@ EXPORT_SYMBOL_GPL(v4l2_event_queue_fh);

int v4l2_event_pending(struct v4l2_fh *fh)
{
return fh->events->navailable;
return fh->navailable;
}
EXPORT_SYMBOL_GPL(v4l2_event_pending);

int v4l2_event_subscribe(struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
struct v4l2_events *events = fh->events;
struct v4l2_subscribed_event *sev, *found_ev;
struct v4l2_ctrl *ctrl = NULL;
struct v4l2_ctrl_fh *ctrl_fh = NULL;
unsigned long flags;

if (fh->events == NULL) {
WARN_ON(1);
return -ENOMEM;
}

if (sub->type == V4L2_EVENT_CTRL) {
ctrl = v4l2_ctrl_find(fh->ctrl_handler, sub->id);
if (ctrl == NULL)
Expand All @@ -284,7 +242,7 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
sev->type = sub->type;
sev->id = sub->id;

list_add(&sev->list, &events->subscribed);
list_add(&sev->list, &fh->subscribed);
sev = NULL;
}

Expand All @@ -306,7 +264,6 @@ EXPORT_SYMBOL_GPL(v4l2_event_subscribe);

static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
{
struct v4l2_events *events = fh->events;
struct v4l2_event_subscription sub;
struct v4l2_subscribed_event *sev;
unsigned long flags;
Expand All @@ -315,8 +272,8 @@ static void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
sev = NULL;

spin_lock_irqsave(&fh->vdev->fh_lock, flags);
if (!list_empty(&events->subscribed)) {
sev = list_first_entry(&events->subscribed,
if (!list_empty(&fh->subscribed)) {
sev = list_first_entry(&fh->subscribed,
struct v4l2_subscribed_event, list);
sub.type = sev->type;
sub.id = sev->id;
Expand Down
17 changes: 6 additions & 11 deletions drivers/media/video/v4l2-fh.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>

int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
{
fh->vdev = vdev;
/* Inherit from video_device. May be overridden by the driver. */
Expand All @@ -38,16 +38,11 @@ int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
fh->prio = V4L2_PRIORITY_UNSET;

/*
* fh->events only needs to be initialized if the driver
* supports the VIDIOC_SUBSCRIBE_EVENT ioctl.
*/
if (vdev->ioctl_ops && vdev->ioctl_ops->vidioc_subscribe_event)
return v4l2_event_init(fh);

fh->events = NULL;

return 0;
init_waitqueue_head(&fh->wait);
INIT_LIST_HEAD(&fh->free);
INIT_LIST_HEAD(&fh->available);
INIT_LIST_HEAD(&fh->subscribed);
fh->sequence = -1;
}
EXPORT_SYMBOL_GPL(v4l2_fh_init);

Expand Down
10 changes: 2 additions & 8 deletions drivers/media/video/v4l2-subdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,9 @@ static int subdev_open(struct file *file)
return ret;
}

ret = v4l2_fh_init(&subdev_fh->vfh, vdev);
if (ret)
goto err;
v4l2_fh_init(&subdev_fh->vfh, vdev);

if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
ret = v4l2_event_init(&subdev_fh->vfh);
if (ret)
goto err;

ret = v4l2_event_alloc(&subdev_fh->vfh, sd->nevents);
if (ret)
goto err;
Expand Down Expand Up @@ -297,7 +291,7 @@ static unsigned int subdev_poll(struct file *file, poll_table *wait)
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
return POLLERR;

poll_wait(file, &fh->events->wait, wait);
poll_wait(file, &fh->wait, wait);

if (v4l2_event_pending(fh))
return POLLPRI;
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/video/vivi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,7 @@ vivi_poll(struct file *file, struct poll_table_struct *wait)
if (v4l2_event_pending(fh))
res |= POLLPRI;
else
poll_wait(file, &fh->events->wait, wait);
poll_wait(file, &fh->wait, wait);
return res;
}

Expand Down
10 changes: 2 additions & 8 deletions drivers/usb/gadget/uvc_v4l2.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,7 @@ uvc_v4l2_open(struct file *file)
if (handle == NULL)
return -ENOMEM;

ret = v4l2_fh_init(&handle->vfh, vdev);
if (ret < 0)
goto error;

ret = v4l2_event_init(&handle->vfh);
if (ret < 0)
goto error;
v4l2_fh_init(&handle->vfh, vdev);

ret = v4l2_event_alloc(&handle->vfh, 8);
if (ret < 0)
Expand Down Expand Up @@ -354,7 +348,7 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
unsigned int mask = 0;

poll_wait(file, &handle->vfh.events->wait, wait);
poll_wait(file, &handle->vfh.wait, wait);
if (v4l2_event_pending(&handle->vfh))
mask |= POLLPRI;

Expand Down
11 changes: 0 additions & 11 deletions include/media/v4l2-event.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,6 @@ struct v4l2_subscribed_event {
u32 id;
};

struct v4l2_events {
wait_queue_head_t wait;
struct list_head subscribed; /* Subscribed events */
struct list_head free; /* Events ready for use */
struct list_head available; /* Dequeueable event */
unsigned int navailable;
unsigned int nallocated; /* Number of allocated events */
u32 sequence;
};

int v4l2_event_init(struct v4l2_fh *fh);
int v4l2_event_alloc(struct v4l2_fh *fh, unsigned int n);
void v4l2_event_free(struct v4l2_fh *fh);
int v4l2_event_dequeue(struct v4l2_fh *fh, struct v4l2_event *event,
Expand Down
13 changes: 10 additions & 3 deletions include/media/v4l2-fh.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,22 @@
#include <linux/list.h>

struct video_device;
struct v4l2_events;
struct v4l2_ctrl_handler;

struct v4l2_fh {
struct list_head list;
struct video_device *vdev;
struct v4l2_events *events; /* events, pending and subscribed */
struct v4l2_ctrl_handler *ctrl_handler;
enum v4l2_priority prio;

/* Events */
wait_queue_head_t wait;
struct list_head subscribed; /* Subscribed events */
struct list_head free; /* Events ready for use */
struct list_head available; /* Dequeueable event */
unsigned int navailable;
unsigned int nallocated; /* Number of allocated events */
u32 sequence;
};

/*
Expand All @@ -46,7 +53,7 @@ struct v4l2_fh {
* from driver's v4l2_file_operations->open() handler if the driver
* uses v4l2_fh.
*/
int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev);
void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev);
/*
* Add the fh to the list of file handles on a video_device. The file
* handle must be initialised first.
Expand Down

0 comments on commit 523f46d

Please sign in to comment.