12 Nov, 2011

1 commit

  • * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
    [media] v4l2-ctrl: Send change events to all fh for auto cluster slave controls
    [media] v4l2-event: Don't set sev->fh to NULL on unsubscribe
    [media] v4l2-event: Remove pending events from fh event queue when unsubscribing
    [media] v4l2-event: Deny subscribing with a type of V4L2_EVENT_ALL
    [media] MAINTAINERS: add a maintainer for s5p-mfc driver
    [media] v4l: s5p-mfc: fix reported capabilities
    [media] media: vb2: reset queued list on REQBUFS(0) call
    [media] media: vb2: set buffer length correctly for all buffer types
    [media] media: vb2: add a check for uninitialized buffer
    [media] mxl111sf: fix build warning
    [media] mxl111sf: remove pointless if condition in mxl111sf_config_spi
    [media] mxl111sf: check for errors after mxl111sf_write_reg in mxl111sf_idac_config
    [media] mxl111sf: fix return value of mxl111sf_idac_config
    [media] uvcvideo: GET_RES should only be checked for BITMAP type menu controls

    Linus Torvalds
     

08 Nov, 2011

3 commits

  • Setting sev->fh to NULL causes problems for the del op added in the next
    patch of this series, since this op needs a way to get to its own data
    structures, and typically this will be done by using container_of on an
    embedded v4l2_fh struct.

    The reason the original code is setting sev->fh to NULL is to signal
    to users of the event framework that the unsubscription has happened,
    but since their is no shared lock between the event framework and users
    of it, this is inherently racy, and it also turns out to be unnecessary
    as long as both the event framework and the user of the framework do their
    own locking properly and the user guarantees that it holds no references
    to the subcribed_event structure after its del operation has been called.

    This is best explained by looking at the only code currently checking for
    sev->fh being set to NULL on unsubscribe, which is the v4l2-ctrls.c send_event
    function. Here is the relevant code from v4l2-ctrls: send_event():

    if (sev->fh && (sev->fh != fh ||
    (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
    v4l2_event_queue_fh(sev->fh, &ev);

    Now lets say that v4l2_event_unsubscribe and v4l2-ctrls: send_event() race
    on the same sev, then the following could happens:

    1) send_event checks sev->fh, finds it is not NULL

    2) v4l2_event_unsubscribe sets sev->fh NULL
    3) v4l2_event_unsubscribe calls v4l2_ctrls del_event function, this blocks
    as the thread calling send_event holds the ctrl_lock

    4) send_event calls v4l2_event_queue_fh(sev->fh, &ev) which not is equivalent
    to calling: v4l2_event_queue_fh(NULL, &ev)
    5) oops, NULL pointer deref.

    Now again without setting sev->fh to NULL in v4l2_event_unsubscribe and
    without the (now senseless since always true) sev->fh != NULL check in

    1) send_event is about to call v4l2_event_queue_fh(sev->fh, &ev)

    2) v4l2_event_unsubscribe removes sev->list from the fh->subscribed list

    3) send_event calls v4l2_event_queue_fh(sev->fh, &ev)
    4) v4l2_event_queue_fh blocks on the fh_lock spinlock

    5) v4l2_event_unsubscribe unlocks the fh_lock spinlock
    6) v4l2_event_unsubscribe calls v4l2_ctrls del_event function, this blocks
    as the thread calling send_event holds the ctrl_lock

    8) v4l2_event_queue_fh takes the fh_lock
    7) v4l2_event_queue_fh calls v4l2_event_subscribed, does not find it since
    sev->list has been removed from fh->subscribed already -> does nothing
    9) v4l2_event_queue_fh releases the fh_lock
    10) the caller of send_event releases the ctrl lock (mutex)

    11) v4l2_ctrls del_event takes the ctrl lock
    12) v4l2_ctrls del_event removes sev->node from the ev_subs list
    13) v4l2_ctrls del_event releases the ctrl lock
    14) v4l2_event_unsubscribe frees the sev, to which no references are being
    held anymore

    Signed-off-by: Hans de Goede
    Acked-by: Hans Verkuil
    Signed-off-by: Mauro Carvalho Chehab

    Hans de Goede
     
  • The kev pointers inside the pending events queue (the available queue) of the
    fh point to data inside the sev, unsubscribing frees the sev, thus making these
    pointers point to freed memory!

    This patch fixes these dangling pointers in the available queue by removing
    all matching pending events on unsubscription.

    Signed-off-by: Hans de Goede
    Acked-by: Hans Verkuil
    Signed-off-by: Mauro Carvalho Chehab

    Hans de Goede
     
  • Signed-off-by: Hans de Goede
    Acked-by: Laurent Pinchart
    Acked-by: Hans Verkuil
    Signed-off-by: Mauro Carvalho Chehab

    Hans de Goede
     

01 Nov, 2011

1 commit


28 Jul, 2011

6 commits

  • Thanks to Laurent Pinchart .

    Signed-off-by: Hans Verkuil
    Signed-off-by: Mauro Carvalho Chehab

    Hans Verkuil
     
  • When the event queue for a subscribed event is full, then the oldest
    event is dropped. It would be nice if the contents of that oldest
    event could be merged with the next-oldest. That way no information is
    lost, only intermediate steps are lost.

    This patch adds optional replace() (called when only one kevent was allocated)
    and merge() (called when more than one kevent was allocated) callbacks that
    will be called to do this job.

    These two callbacks are implemented for the V4L2_EVENT_CTRL event.

    Signed-off-by: Hans Verkuil
    Signed-off-by: Mauro Carvalho Chehab

    Hans Verkuil
     
  • 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
    Signed-off-by: Mauro Carvalho Chehab

    Hans Verkuil
     
  • The v4l2_ctrl_fh struct connected v4l2_ctrl with v4l2_fh so the control
    would know which filehandles subscribed to it. However, it is much easier
    to use struct v4l2_subscribed_event directly for that and get rid of that
    intermediate struct.

    Signed-off-by: Hans Verkuil
    Signed-off-by: Mauro Carvalho Chehab

    Hans Verkuil
     
  • 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
    Signed-off-by: Mauro Carvalho Chehab

    Hans Verkuil
     
  • Whenever a control changes value or state an event is sent to anyone
    that subscribed to it.

    This functionality is useful for control panels but also for applications
    that need to wait for (usually status) controls to change value.

    Signed-off-by: Hans Verkuil
    Signed-off-by: Mauro Carvalho Chehab

    Hans Verkuil
     

21 Oct, 2010

1 commit

  • Drivers can optionally set a pointer to a mutex in struct video_device.
    The core will use that to lock before calling open, read, write, unlocked_ioctl,
    poll, mmap or release.

    Updated the documentation as well and ensure that v4l2-event knows about the
    lock: it will unlock it before doing a blocking wait on an event and relock it
    afterwards.

    Ensure that the 'video_is_registered' check is done when the lock is held:
    a typical disconnect will take the lock as well before unregistering the
    device nodes, so to prevent race conditions the video_is_registered check
    should also be done with the lock held.

    Signed-off-by: Hans Verkuil
    Signed-off-by: Mauro Carvalho Chehab

    Hans Verkuil
     

19 May, 2010

3 commits