All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel@ffwll.ch>
To: Brian Starkey <brian.starkey@arm.com>
Cc: liviu.dudau@arm.com, linux-kernel@vger.kernel.org,
	dri-devel@lists.freedesktop.org, hverkuil@xs4all.nl,
	linux-media@vger.kernel.org
Subject: Re: [RFC PATCH 04/11] drm: Add __drm_framebuffer_remove_atomic
Date: Tue, 11 Oct 2016 17:51:36 +0200	[thread overview]
Message-ID: <20161011155136.GG20761@phenom.ffwll.local> (raw)
In-Reply-To: <1476197648-24918-5-git-send-email-brian.starkey@arm.com>

On Tue, Oct 11, 2016 at 03:54:01PM +0100, Brian Starkey wrote:
> Implement the CRTC/Plane disable functionality of drm_framebuffer_remove
> using the atomic API, and use it if possible.
> 
> For atomic drivers, this removes the possibility of several commits when
> a framebuffer is in use by more than one CRTC/plane.
> 
> Additionally, this will provide a suitable place to support the removal
> of a framebuffer from a writeback connector, in the case that a
> writeback connector is still actively using a framebuffer when it is
> removed by userspace.
> 
> Signed-off-by: Brian Starkey <brian.starkey@arm.com>

Just the small comment here: Last time around I wanted toland an atomic
disable function for fb remove code it blew up. Need to check out git
history to make sure we've addressed those isses.  Caveat emperor ;-)
-Daniel

> ---
>  drivers/gpu/drm/drm_framebuffer.c |  154 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 152 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
> index 528f75d..b02cf73 100644
> --- a/drivers/gpu/drm/drm_framebuffer.c
> +++ b/drivers/gpu/drm/drm_framebuffer.c
> @@ -22,6 +22,7 @@
>  
>  #include <linux/export.h>
>  #include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
>  #include <drm/drm_auth.h>
>  #include <drm/drm_framebuffer.h>
>  
> @@ -795,6 +796,148 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
>  EXPORT_SYMBOL(drm_framebuffer_cleanup);
>  
>  /**
> + * __drm_framebuffer_remove_atomic - atomic version of __drm_framebuffer_remove
> + * @dev: drm device
> + * @fb: framebuffer to remove
> + *
> + * If the driver implements the atomic API, we can handle the disabling of all
> + * CRTCs/planes which use a framebuffer which is going away in a single atomic
> + * commit.
> + *
> + * This scans all CRTCs and planes in @dev's mode_config. If they're using @fb,
> + * it is removed and the CRTC/plane disabled.
> + * The legacy references are dropped and the ->fb pointers set to NULL
> + * accordingly.
> + *
> + * Returns:
> + * true if the framebuffer was successfully removed from use
> + */
> +static bool __drm_framebuffer_remove_atomic(struct drm_device *dev,
> +		struct drm_framebuffer *fb)
> +{
> +	struct drm_modeset_acquire_ctx ctx;
> +	struct drm_atomic_state *state;
> +	struct drm_connector_state *conn_state;
> +	struct drm_connector *connector;
> +	struct drm_plane *plane;
> +	struct drm_crtc *crtc;
> +	unsigned plane_mask;
> +	int i, ret;
> +
> +	drm_modeset_acquire_init(&ctx, 0);
> +
> +	state = drm_atomic_state_alloc(dev);
> +	if (!state)
> +		return false;
> +
> +	state->acquire_ctx = &ctx;
> +
> +retry:
> +	drm_for_each_crtc(crtc, dev) {
> +		struct drm_plane_state *primary_state;
> +		struct drm_crtc_state *crtc_state;
> +
> +		primary_state = drm_atomic_get_plane_state(state, crtc->primary);
> +		if (IS_ERR(primary_state)) {
> +			ret = PTR_ERR(primary_state);
> +			goto fail;
> +		}
> +
> +		if (primary_state->fb != fb)
> +			continue;
> +
> +		crtc_state = drm_atomic_get_crtc_state(state, crtc);
> +		if (IS_ERR(crtc_state)) {
> +			ret = PTR_ERR(crtc_state);
> +			goto fail;
> +		}
> +
> +		/* Only handle the CRTC itself here, handle the plane later */
> +		ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
> +		if (ret != 0)
> +			goto fail;
> +
> +		crtc_state->active = false;
> +
> +		/* Get the connectors in order to disable them */
> +		ret = drm_atomic_add_affected_connectors(state, crtc);
> +		if (ret)
> +			goto fail;
> +	}
> +
> +	plane_mask = 0;
> +	drm_for_each_plane(plane, dev) {
> +		struct drm_plane_state *plane_state;
> +
> +		plane_state = drm_atomic_get_plane_state(state, plane);
> +		if (IS_ERR(plane_state)) {
> +			ret = PTR_ERR(plane_state);
> +			goto fail;
> +		}
> +
> +		if (plane_state->fb != fb)
> +			continue;
> +
> +		plane->old_fb = plane->fb;
> +		plane_mask |= 1 << drm_plane_index(plane);
> +
> +		/*
> +		 * Open-coded copy of __drm_atomic_helper_disable_plane to avoid
> +		 * a dependency on atomic-helper
> +		 */
> +		ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
> +		if (ret != 0)
> +			goto fail;
> +
> +		drm_atomic_set_fb_for_plane(plane_state, NULL);
> +		plane_state->crtc_x = 0;
> +		plane_state->crtc_y = 0;
> +		plane_state->crtc_w = 0;
> +		plane_state->crtc_h = 0;
> +		plane_state->src_x = 0;
> +		plane_state->src_y = 0;
> +		plane_state->src_w = 0;
> +		plane_state->src_h = 0;
> +	}
> +
> +	/* All of the connectors in state need disabling */
> +	for_each_connector_in_state(state, connector, conn_state, i) {
> +		ret = drm_atomic_set_crtc_for_connector(conn_state,
> +							NULL);
> +		if (ret)
> +			goto fail;
> +	}
> +
> +	if (WARN_ON(!plane_mask)) {
> +		DRM_ERROR("Couldn't find any usage of [FB:%d]\n", fb->base.id);
> +		ret = -ENOENT;
> +		goto fail;
> +	}
> +
> +	ret = drm_atomic_commit(state);
> +
> +fail:
> +	drm_atomic_clean_old_fb(dev, plane_mask, ret);
> +
> +	if (ret == -EDEADLK)
> +		goto backoff;
> +
> +	if (ret != 0)
> +		drm_atomic_state_free(state);
> +
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +
> +	return ret ? false : true;
> +
> +backoff:
> +	drm_atomic_state_clear(state);
> +	drm_modeset_backoff(&ctx);
> +
> +	goto retry;
> +}
> +
> +/**
>   * __drm_framebuffer_remove - remove all usage of a framebuffer object
>   * @dev: drm device
>   * @fb: framebuffer to remove
> @@ -869,9 +1012,16 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
>  	 * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
>  	 * in this manner.
>  	 */
> -	if (drm_framebuffer_read_refcount(fb) > 1)
> -		if (!__drm_framebuffer_remove(dev, fb))
> +	if (drm_framebuffer_read_refcount(fb) > 1) {
> +		bool removed;
> +		if (dev->mode_config.funcs->atomic_commit)
> +			removed = __drm_framebuffer_remove_atomic(dev, fb);
> +		else
> +			removed = __drm_framebuffer_remove(dev, fb);
> +
> +		if (!removed)
>  			DRM_ERROR("failed to remove fb from active usage\n");
> +	}
>  
>  	drm_framebuffer_unreference(fb);
>  }
> -- 
> 1.7.9.5
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

WARNING: multiple messages have this Message-ID (diff)
From: Daniel Vetter <daniel@ffwll.ch>
To: Brian Starkey <brian.starkey@arm.com>
Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
	linux-media@vger.kernel.org, liviu.dudau@arm.com,
	robdclark@gmail.com, hverkuil@xs4all.nl, eric@anholt.net,
	ville.syrjala@linux.intel.com, daniel@ffwll.ch
Subject: Re: [RFC PATCH 04/11] drm: Add __drm_framebuffer_remove_atomic
Date: Tue, 11 Oct 2016 17:51:36 +0200	[thread overview]
Message-ID: <20161011155136.GG20761@phenom.ffwll.local> (raw)
In-Reply-To: <1476197648-24918-5-git-send-email-brian.starkey@arm.com>

On Tue, Oct 11, 2016 at 03:54:01PM +0100, Brian Starkey wrote:
> Implement the CRTC/Plane disable functionality of drm_framebuffer_remove
> using the atomic API, and use it if possible.
> 
> For atomic drivers, this removes the possibility of several commits when
> a framebuffer is in use by more than one CRTC/plane.
> 
> Additionally, this will provide a suitable place to support the removal
> of a framebuffer from a writeback connector, in the case that a
> writeback connector is still actively using a framebuffer when it is
> removed by userspace.
> 
> Signed-off-by: Brian Starkey <brian.starkey@arm.com>

Just the small comment here: Last time around I wanted toland an atomic
disable function for fb remove code it blew up. Need to check out git
history to make sure we've addressed those isses.  Caveat emperor ;-)
-Daniel

> ---
>  drivers/gpu/drm/drm_framebuffer.c |  154 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 152 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
> index 528f75d..b02cf73 100644
> --- a/drivers/gpu/drm/drm_framebuffer.c
> +++ b/drivers/gpu/drm/drm_framebuffer.c
> @@ -22,6 +22,7 @@
>  
>  #include <linux/export.h>
>  #include <drm/drmP.h>
> +#include <drm/drm_atomic.h>
>  #include <drm/drm_auth.h>
>  #include <drm/drm_framebuffer.h>
>  
> @@ -795,6 +796,148 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
>  EXPORT_SYMBOL(drm_framebuffer_cleanup);
>  
>  /**
> + * __drm_framebuffer_remove_atomic - atomic version of __drm_framebuffer_remove
> + * @dev: drm device
> + * @fb: framebuffer to remove
> + *
> + * If the driver implements the atomic API, we can handle the disabling of all
> + * CRTCs/planes which use a framebuffer which is going away in a single atomic
> + * commit.
> + *
> + * This scans all CRTCs and planes in @dev's mode_config. If they're using @fb,
> + * it is removed and the CRTC/plane disabled.
> + * The legacy references are dropped and the ->fb pointers set to NULL
> + * accordingly.
> + *
> + * Returns:
> + * true if the framebuffer was successfully removed from use
> + */
> +static bool __drm_framebuffer_remove_atomic(struct drm_device *dev,
> +		struct drm_framebuffer *fb)
> +{
> +	struct drm_modeset_acquire_ctx ctx;
> +	struct drm_atomic_state *state;
> +	struct drm_connector_state *conn_state;
> +	struct drm_connector *connector;
> +	struct drm_plane *plane;
> +	struct drm_crtc *crtc;
> +	unsigned plane_mask;
> +	int i, ret;
> +
> +	drm_modeset_acquire_init(&ctx, 0);
> +
> +	state = drm_atomic_state_alloc(dev);
> +	if (!state)
> +		return false;
> +
> +	state->acquire_ctx = &ctx;
> +
> +retry:
> +	drm_for_each_crtc(crtc, dev) {
> +		struct drm_plane_state *primary_state;
> +		struct drm_crtc_state *crtc_state;
> +
> +		primary_state = drm_atomic_get_plane_state(state, crtc->primary);
> +		if (IS_ERR(primary_state)) {
> +			ret = PTR_ERR(primary_state);
> +			goto fail;
> +		}
> +
> +		if (primary_state->fb != fb)
> +			continue;
> +
> +		crtc_state = drm_atomic_get_crtc_state(state, crtc);
> +		if (IS_ERR(crtc_state)) {
> +			ret = PTR_ERR(crtc_state);
> +			goto fail;
> +		}
> +
> +		/* Only handle the CRTC itself here, handle the plane later */
> +		ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
> +		if (ret != 0)
> +			goto fail;
> +
> +		crtc_state->active = false;
> +
> +		/* Get the connectors in order to disable them */
> +		ret = drm_atomic_add_affected_connectors(state, crtc);
> +		if (ret)
> +			goto fail;
> +	}
> +
> +	plane_mask = 0;
> +	drm_for_each_plane(plane, dev) {
> +		struct drm_plane_state *plane_state;
> +
> +		plane_state = drm_atomic_get_plane_state(state, plane);
> +		if (IS_ERR(plane_state)) {
> +			ret = PTR_ERR(plane_state);
> +			goto fail;
> +		}
> +
> +		if (plane_state->fb != fb)
> +			continue;
> +
> +		plane->old_fb = plane->fb;
> +		plane_mask |= 1 << drm_plane_index(plane);
> +
> +		/*
> +		 * Open-coded copy of __drm_atomic_helper_disable_plane to avoid
> +		 * a dependency on atomic-helper
> +		 */
> +		ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
> +		if (ret != 0)
> +			goto fail;
> +
> +		drm_atomic_set_fb_for_plane(plane_state, NULL);
> +		plane_state->crtc_x = 0;
> +		plane_state->crtc_y = 0;
> +		plane_state->crtc_w = 0;
> +		plane_state->crtc_h = 0;
> +		plane_state->src_x = 0;
> +		plane_state->src_y = 0;
> +		plane_state->src_w = 0;
> +		plane_state->src_h = 0;
> +	}
> +
> +	/* All of the connectors in state need disabling */
> +	for_each_connector_in_state(state, connector, conn_state, i) {
> +		ret = drm_atomic_set_crtc_for_connector(conn_state,
> +							NULL);
> +		if (ret)
> +			goto fail;
> +	}
> +
> +	if (WARN_ON(!plane_mask)) {
> +		DRM_ERROR("Couldn't find any usage of [FB:%d]\n", fb->base.id);
> +		ret = -ENOENT;
> +		goto fail;
> +	}
> +
> +	ret = drm_atomic_commit(state);
> +
> +fail:
> +	drm_atomic_clean_old_fb(dev, plane_mask, ret);
> +
> +	if (ret == -EDEADLK)
> +		goto backoff;
> +
> +	if (ret != 0)
> +		drm_atomic_state_free(state);
> +
> +	drm_modeset_drop_locks(&ctx);
> +	drm_modeset_acquire_fini(&ctx);
> +
> +	return ret ? false : true;
> +
> +backoff:
> +	drm_atomic_state_clear(state);
> +	drm_modeset_backoff(&ctx);
> +
> +	goto retry;
> +}
> +
> +/**
>   * __drm_framebuffer_remove - remove all usage of a framebuffer object
>   * @dev: drm device
>   * @fb: framebuffer to remove
> @@ -869,9 +1012,16 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
>  	 * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
>  	 * in this manner.
>  	 */
> -	if (drm_framebuffer_read_refcount(fb) > 1)
> -		if (!__drm_framebuffer_remove(dev, fb))
> +	if (drm_framebuffer_read_refcount(fb) > 1) {
> +		bool removed;
> +		if (dev->mode_config.funcs->atomic_commit)
> +			removed = __drm_framebuffer_remove_atomic(dev, fb);
> +		else
> +			removed = __drm_framebuffer_remove(dev, fb);
> +
> +		if (!removed)
>  			DRM_ERROR("failed to remove fb from active usage\n");
> +	}
>  
>  	drm_framebuffer_unreference(fb);
>  }
> -- 
> 1.7.9.5
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

  reply	other threads:[~2016-10-11 15:51 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-11 14:53 [RFC PATCH 00/11] Introduce writeback connectors Brian Starkey
2016-10-11 14:53 ` Brian Starkey
2016-10-11 14:53 ` [RFC PATCH 01/11] drm: Add writeback connector type Brian Starkey
2016-10-11 14:53   ` Brian Starkey
2016-10-11 14:53 ` [RFC PATCH 02/11] drm/fb-helper: Skip writeback connectors Brian Starkey
2016-10-11 14:53   ` Brian Starkey
2016-10-11 15:44   ` Daniel Vetter
2016-10-11 15:44     ` Daniel Vetter
2016-10-11 16:47     ` Brian Starkey
2016-10-11 16:47       ` Brian Starkey
2016-10-11 16:56       ` Daniel Vetter
2016-10-11 16:56         ` Daniel Vetter
2016-10-11 14:54 ` [RFC PATCH 03/11] drm: Extract CRTC/plane disable from drm_framebuffer_remove Brian Starkey
2016-10-11 14:54   ` Brian Starkey
2016-10-11 14:54 ` [RFC PATCH 04/11] drm: Add __drm_framebuffer_remove_atomic Brian Starkey
2016-10-11 14:54   ` Brian Starkey
2016-10-11 15:51   ` Daniel Vetter [this message]
2016-10-11 15:51     ` Daniel Vetter
2016-10-11 14:54 ` [RFC PATCH 05/11] drm: Add fb to connector state Brian Starkey
2016-10-11 14:54   ` Brian Starkey
2016-10-11 14:54 ` [RFC PATCH 06/11] drm: Expose fb_id property for writeback connectors Brian Starkey
2016-10-11 14:54   ` Brian Starkey
2016-10-11 14:54 ` [RFC PATCH 07/11] drm: Add writeback-connector pixel format properties Brian Starkey
2016-10-11 14:54   ` Brian Starkey
2016-10-11 15:48   ` Daniel Vetter
2016-10-11 15:48     ` Daniel Vetter
2016-10-11 14:54 ` [RFC PATCH 08/11] drm: mali-dp: Rename malidp_input_format Brian Starkey
2016-10-11 14:54   ` Brian Starkey
2016-10-11 14:54 ` [RFC PATCH 09/11] drm: mali-dp: Add RGB writeback formats for DP550/DP650 Brian Starkey
2016-10-11 14:54   ` Brian Starkey
2016-10-11 14:54 ` [RFC PATCH 10/11] drm: mali-dp: Add support for writeback on DP550/DP650 Brian Starkey
2016-10-11 14:54   ` Brian Starkey
2016-10-11 14:54 ` [RFC PATCH 11/11] drm: mali-dp: Add writeback connector Brian Starkey
2016-10-11 14:54   ` Brian Starkey
2016-10-11 15:43 ` [RFC PATCH 00/11] Introduce writeback connectors Daniel Vetter
2016-10-11 15:43   ` Daniel Vetter
2016-10-11 16:43   ` Brian Starkey
2016-10-11 16:43     ` Brian Starkey
2016-10-11 17:01     ` Daniel Vetter
2016-10-11 17:01       ` Daniel Vetter
2016-10-11 19:44       ` Brian Starkey
2016-10-11 19:44         ` Brian Starkey
2016-10-11 20:02         ` Daniel Vetter
2016-10-11 20:02           ` Daniel Vetter
2016-10-11 21:24           ` Brian Starkey
2016-10-11 21:24             ` Brian Starkey
2016-10-12  6:56             ` Daniel Vetter
2016-10-12  6:56               ` Daniel Vetter
2016-10-13  9:47               ` [PATCH] drm: atomic: Clarify documentation around drm_atomic_crtc_needs_modeset Brian Starkey
2016-10-13 14:54                 ` Alex Deucher
2016-10-13 14:54                   ` Alex Deucher
2016-10-17  6:07                   ` Daniel Vetter
2016-10-17  6:07                     ` Daniel Vetter
2016-10-11 16:25 ` [RFC PATCH 00/11] Introduce writeback connectors Ville Syrjälä
2016-10-11 16:25   ` Ville Syrjälä
2016-10-11 16:29   ` Daniel Vetter
2016-10-11 16:29     ` Daniel Vetter
2016-10-11 19:01 ` Eric Anholt
2016-10-11 19:01   ` Eric Anholt
2016-10-12  7:30   ` Brian Starkey
2016-10-12  7:30     ` Brian Starkey
2016-10-13 17:32     ` Eric Anholt
2016-10-14 10:50 ` Archit Taneja
2016-10-14 10:50   ` Archit Taneja
2016-10-14 12:39   ` Brian Starkey
2016-10-14 12:39     ` Brian Starkey
2016-10-14 12:50     ` Ville Syrjälä
2016-10-14 12:50       ` Ville Syrjälä
2016-10-14 14:56     ` Daniel Vetter
2016-10-14 14:56       ` Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161011155136.GG20761@phenom.ffwll.local \
    --to=daniel@ffwll.ch \
    --cc=brian.starkey@arm.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hverkuil@xs4all.nl \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=liviu.dudau@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.