drm: Add functions to setup/tear down drm_events.

An attempt at not spreading out the file_priv->event_space stuff out
quite so far and wide.  And I think fixes something in ipp_get_event()
that is broken (or if they are doing something more weird/subtle, then
breaks it in a fun way).

Based upon a patch from Rob Clark, rebased and polished.

v2: Spelling fixes (Alex).

Cc: Alex Deucher <alexdeucher@gmail.com>
Acked-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Cc: Rob Clark <robdclark@gmail.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1452548477-15905-3-git-send-email-daniel.vetter@ffwll.ch
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
This commit is contained in:
Daniel Vetter
2016-01-11 22:40:56 +01:00
parent bcb877e4dc
commit 2dd500f187
4 changed files with 94 additions and 60 deletions

View File

@@ -676,3 +676,70 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
return mask;
}
EXPORT_SYMBOL(drm_poll);
/**
* drm_event_reserve_init - init a DRM event and reserve space for it
* @dev: DRM device
* @file_priv: DRM file private data
* @p: tracking structure for the pending event
* @e: actual event data to deliver to userspace
*
* This function prepares the passed in event for eventual delivery. If the event
* doesn't get delivered (because the IOCTL fails later on, before queuing up
* anything) then the even must be cancelled and freed using
* drm_event_cancel_free().
*
* If callers embedded @p into a larger structure it must be allocated with
* kmalloc and @p must be the first member element.
*
* RETURNS:
*
* 0 on success or a negative error code on failure.
*/
int drm_event_reserve_init(struct drm_device *dev,
struct drm_file *file_priv,
struct drm_pending_event *p,
struct drm_event *e)
{
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&dev->event_lock, flags);
if (file_priv->event_space < e->length) {
ret = -ENOMEM;
goto out;
}
file_priv->event_space -= e->length;
p->event = e;
p->file_priv = file_priv;
/* we *could* pass this in as arg, but everyone uses kfree: */
p->destroy = (void (*) (struct drm_pending_event *)) kfree;
out:
spin_unlock_irqrestore(&dev->event_lock, flags);
return ret;
}
EXPORT_SYMBOL(drm_event_reserve_init);
/**
* drm_event_cancel_free - free a DRM event and release it's space
* @dev: DRM device
* @p: tracking structure for the pending event
*
* This function frees the event @p initialized with drm_event_reserve_init()
* and releases any allocated space.
*/
void drm_event_cancel_free(struct drm_device *dev,
struct drm_pending_event *p)
{
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
p->file_priv->event_space += p->event->length;
spin_unlock_irqrestore(&dev->event_lock, flags);
p->destroy(p);
}
EXPORT_SYMBOL(drm_event_cancel_free);