Re: [PATCH 02/22] drm: Add functions to setup/tear down drm_events.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Daniel,

Thank you for the patch.

On Monday 11 January 2016 22:40:56 Daniel Vetter wrote:
> 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@xxxxxxxxx>
> Acked-by: Daniel Stone <daniels@xxxxxxxxxxxxx>
> Reviewed-by: Alex Deucher <alexander.deucher@xxxxxxx>
> Cc: Rob Clark <robdclark@xxxxxxxxx>
> Signed-off-by: Daniel Vetter <daniel.vetter@xxxxxxxxx>

Reviewed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx>

> ---
>  drivers/gpu/drm/drm_atomic.c | 44 ++++++++---------------------
>  drivers/gpu/drm/drm_crtc.c   | 36 +++++++-----------------
>  drivers/gpu/drm/drm_fops.c   | 67 +++++++++++++++++++++++++++++++++++++++++
>  include/drm/drmP.h           |  7 ++++-
>  4 files changed, 94 insertions(+), 60 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 3f74193885f1..8fb469c4e4b8 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1347,44 +1347,23 @@ static struct drm_pending_vblank_event
> *create_vblank_event( struct drm_device *dev, struct drm_file *file_priv,
> uint64_t user_data) {
>  	struct drm_pending_vblank_event *e = NULL;
> -	unsigned long flags;
> -
> -	spin_lock_irqsave(&dev->event_lock, flags);
> -	if (file_priv->event_space < sizeof e->event) {
> -		spin_unlock_irqrestore(&dev->event_lock, flags);
> -		goto out;
> -	}
> -	file_priv->event_space -= sizeof e->event;
> -	spin_unlock_irqrestore(&dev->event_lock, flags);
> +	int ret;
> 
>  	e = kzalloc(sizeof *e, GFP_KERNEL);
> -	if (e == NULL) {
> -		spin_lock_irqsave(&dev->event_lock, flags);
> -		file_priv->event_space += sizeof e->event;
> -		spin_unlock_irqrestore(&dev->event_lock, flags);
> -		goto out;
> -	}
> +	if (!e)
> +		return NULL;
> 
>  	e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
> -	e->event.base.length = sizeof e->event;
> +	e->event.base.length = sizeof(e->event);
>  	e->event.user_data = user_data;
> -	e->base.event = &e->event.base;
> -	e->base.file_priv = file_priv;
> -	e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
> -
> -out:
> -	return e;
> -}
> 
> -static void destroy_vblank_event(struct drm_device *dev,
> -		struct drm_file *file_priv, struct drm_pending_vblank_event *e)
> -{
> -	unsigned long flags;
> +	ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
> +	if (ret) {
> +		kfree(e);
> +		return NULL;
> +	}
> 
> -	spin_lock_irqsave(&dev->event_lock, flags);
> -	file_priv->event_space += sizeof e->event;
> -	spin_unlock_irqrestore(&dev->event_lock, flags);
> -	kfree(e);
> +	return e;
>  }
> 
>  static int atomic_set_prop(struct drm_atomic_state *state,
> @@ -1646,8 +1625,7 @@ out:
>  			if (!crtc_state->event)
>  				continue;
> 
> -			destroy_vblank_event(dev, file_priv,
> -					     crtc_state->event);
> +			drm_event_cancel_free(dev, &crtc_state->event->base);
>  		}
>  	}
> 
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 1e75a145834a..60a4184d41b7 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -5264,7 +5264,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
>  	struct drm_crtc *crtc;
>  	struct drm_framebuffer *fb = NULL;
>  	struct drm_pending_vblank_event *e = NULL;
> -	unsigned long flags;
>  	int ret = -EINVAL;
> 
>  	if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
> @@ -5315,41 +5314,26 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> }
> 
>  	if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> -		ret = -ENOMEM;
> -		spin_lock_irqsave(&dev->event_lock, flags);
> -		if (file_priv->event_space < sizeof(e->event)) {
> -			spin_unlock_irqrestore(&dev->event_lock, flags);
> -			goto out;
> -		}
> -		file_priv->event_space -= sizeof(e->event);
> -		spin_unlock_irqrestore(&dev->event_lock, flags);
> -
> -		e = kzalloc(sizeof(*e), GFP_KERNEL);
> -		if (e == NULL) {
> -			spin_lock_irqsave(&dev->event_lock, flags);
> -			file_priv->event_space += sizeof(e->event);
> -			spin_unlock_irqrestore(&dev->event_lock, flags);
> +		e = kzalloc(sizeof *e, GFP_KERNEL);
> +		if (!e) {
> +			ret = -ENOMEM;
>  			goto out;
>  		}
> -
>  		e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
>  		e->event.base.length = sizeof(e->event);
>  		e->event.user_data = page_flip->user_data;
> -		e->base.event = &e->event.base;
> -		e->base.file_priv = file_priv;
> -		e->base.destroy =
> -			(void (*) (struct drm_pending_event *)) kfree;
> +		ret = drm_event_reserve_init(dev, file_priv, &e->base, &e-
>event.base);
> +		if (ret) {
> +			kfree(e);
> +			goto out;
> +		}
>  	}
> 
>  	crtc->primary->old_fb = crtc->primary->fb;
>  	ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
>  	if (ret) {
> -		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> -			spin_lock_irqsave(&dev->event_lock, flags);
> -			file_priv->event_space += sizeof(e->event);
> -			spin_unlock_irqrestore(&dev->event_lock, flags);
> -			kfree(e);
> -		}
> +		if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
> +			drm_event_cancel_free(dev, &e->base);
>  		/* Keep the old fb, don't unref it. */
>  		crtc->primary->old_fb = NULL;
>  	} else {
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index 73075a1fa380..476408b638e3 100644
> --- a/drivers/gpu/drm/drm_fops.c
> +++ b/drivers/gpu/drm/drm_fops.c
> @@ -672,3 +672,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);
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index fc9b9ad5b089..ad4d0a31294d 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -925,8 +925,13 @@ ssize_t drm_read(struct file *filp, char __user
> *buffer, size_t count, loff_t *offset);
>  int drm_release(struct inode *inode, struct file *filp);
>  int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv);
> -
>  unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
> +int drm_event_reserve_init(struct drm_device *dev,
> +			   struct drm_file *file_priv,
> +			   struct drm_pending_event *p,
> +			   struct drm_event *e);
> +void drm_event_cancel_free(struct drm_device *dev,
> +			   struct drm_pending_event *p);
> 
>  /* Misc. IOCTL support (drm_ioctl.c) */
>  int drm_noop(struct drm_device *dev, void *data,

-- 
Regards,

Laurent Pinchart

_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux