Commit dbd9f78e authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-fixes-2019-06-05' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes



- Allow fb changes in async commits (fixes igt failures) (Helen)
- Actually unmap the scatterlist when unmapping udmabuf (Lucas)

Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Helen Koike <helen.koike@collabora.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Sean Paul <sean@poorly.run>
Link: https://patchwork.freedesktop.org/patch/msgid/20190605210335.GA35431@art_vandelay
parents 75cb3776 283f1e38
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -77,6 +77,7 @@ static void unmap_udmabuf(struct dma_buf_attachment *at,
			  struct sg_table *sg,
			  struct sg_table *sg,
			  enum dma_data_direction direction)
			  enum dma_data_direction direction)
{
{
	dma_unmap_sg(at->dev, sg->sgl, sg->nents, direction);
	sg_free_table(sg);
	sg_free_table(sg);
	kfree(sg);
	kfree(sg);
}
}
+1 −2
Original line number Original line Diff line number Diff line
@@ -4232,8 +4232,7 @@ static void dm_plane_atomic_async_update(struct drm_plane *plane,
	struct drm_plane_state *old_state =
	struct drm_plane_state *old_state =
		drm_atomic_get_old_plane_state(new_state->state, plane);
		drm_atomic_get_old_plane_state(new_state->state, plane);


	if (plane->state->fb != new_state->fb)
	swap(plane->state->fb, new_state->fb);
		drm_atomic_set_fb_for_plane(plane->state, new_state->fb);


	plane->state->src_x = new_state->src_x;
	plane->state->src_x = new_state->src_x;
	plane->state->src_y = new_state->src_y;
	plane->state->src_y = new_state->src_y;
+12 −10
Original line number Original line Diff line number Diff line
@@ -1607,15 +1607,6 @@ int drm_atomic_helper_async_check(struct drm_device *dev,
	    old_plane_state->crtc != new_plane_state->crtc)
	    old_plane_state->crtc != new_plane_state->crtc)
		return -EINVAL;
		return -EINVAL;


	/*
	 * FIXME: Since prepare_fb and cleanup_fb are always called on
	 * the new_plane_state for async updates we need to block framebuffer
	 * changes. This prevents use of a fb that's been cleaned up and
	 * double cleanups from occuring.
	 */
	if (old_plane_state->fb != new_plane_state->fb)
		return -EINVAL;

	funcs = plane->helper_private;
	funcs = plane->helper_private;
	if (!funcs->atomic_async_update)
	if (!funcs->atomic_async_update)
		return -EINVAL;
		return -EINVAL;
@@ -1646,6 +1637,8 @@ EXPORT_SYMBOL(drm_atomic_helper_async_check);
 * drm_atomic_async_check() succeeds. Async commits are not supposed to swap
 * drm_atomic_async_check() succeeds. Async commits are not supposed to swap
 * the states like normal sync commits, but just do in-place changes on the
 * the states like normal sync commits, but just do in-place changes on the
 * current state.
 * current state.
 *
 * TODO: Implement full swap instead of doing in-place changes.
 */
 */
void drm_atomic_helper_async_commit(struct drm_device *dev,
void drm_atomic_helper_async_commit(struct drm_device *dev,
				    struct drm_atomic_state *state)
				    struct drm_atomic_state *state)
@@ -1656,6 +1649,9 @@ void drm_atomic_helper_async_commit(struct drm_device *dev,
	int i;
	int i;


	for_each_new_plane_in_state(state, plane, plane_state, i) {
	for_each_new_plane_in_state(state, plane, plane_state, i) {
		struct drm_framebuffer *new_fb = plane_state->fb;
		struct drm_framebuffer *old_fb = plane->state->fb;

		funcs = plane->helper_private;
		funcs = plane->helper_private;
		funcs->atomic_async_update(plane, plane_state);
		funcs->atomic_async_update(plane, plane_state);


@@ -1664,11 +1660,17 @@ void drm_atomic_helper_async_commit(struct drm_device *dev,
		 * plane->state in-place, make sure at least common
		 * plane->state in-place, make sure at least common
		 * properties have been properly updated.
		 * properties have been properly updated.
		 */
		 */
		WARN_ON_ONCE(plane->state->fb != plane_state->fb);
		WARN_ON_ONCE(plane->state->fb != new_fb);
		WARN_ON_ONCE(plane->state->crtc_x != plane_state->crtc_x);
		WARN_ON_ONCE(plane->state->crtc_x != plane_state->crtc_x);
		WARN_ON_ONCE(plane->state->crtc_y != plane_state->crtc_y);
		WARN_ON_ONCE(plane->state->crtc_y != plane_state->crtc_y);
		WARN_ON_ONCE(plane->state->src_x != plane_state->src_x);
		WARN_ON_ONCE(plane->state->src_x != plane_state->src_x);
		WARN_ON_ONCE(plane->state->src_y != plane_state->src_y);
		WARN_ON_ONCE(plane->state->src_y != plane_state->src_y);

		/*
		 * Make sure the FBs have been swapped so that cleanups in the
		 * new_state performs a cleanup in the old FB.
		 */
		WARN_ON_ONCE(plane_state->fb != old_fb);
	}
	}
}
}
EXPORT_SYMBOL(drm_atomic_helper_async_commit);
EXPORT_SYMBOL(drm_atomic_helper_async_commit);
+4 −0
Original line number Original line Diff line number Diff line
@@ -502,6 +502,8 @@ static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
					   struct drm_plane_state *new_state)
					   struct drm_plane_state *new_state)
{
{
	struct drm_framebuffer *old_fb = plane->state->fb;

	plane->state->src_x = new_state->src_x;
	plane->state->src_x = new_state->src_x;
	plane->state->src_y = new_state->src_y;
	plane->state->src_y = new_state->src_y;
	plane->state->crtc_x = new_state->crtc_x;
	plane->state->crtc_x = new_state->crtc_x;
@@ -524,6 +526,8 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane,


	*to_mdp5_plane_state(plane->state) =
	*to_mdp5_plane_state(plane->state) =
		*to_mdp5_plane_state(new_state);
		*to_mdp5_plane_state(new_state);

	new_state->fb = old_fb;
}
}


static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = {
static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = {
+26 −25
Original line number Original line Diff line number Diff line
@@ -924,29 +924,17 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane,
					  struct drm_plane_state *new_state)
					  struct drm_plane_state *new_state)
{
{
	struct vop *vop = to_vop(plane->state->crtc);
	struct vop *vop = to_vop(plane->state->crtc);
	struct drm_plane_state *plane_state;
	struct drm_framebuffer *old_fb = plane->state->fb;


	plane_state = plane->funcs->atomic_duplicate_state(plane);
	plane->state->crtc_x = new_state->crtc_x;
	plane_state->crtc_x = new_state->crtc_x;
	plane->state->crtc_y = new_state->crtc_y;
	plane_state->crtc_y = new_state->crtc_y;
	plane->state->crtc_h = new_state->crtc_h;
	plane_state->crtc_h = new_state->crtc_h;
	plane->state->crtc_w = new_state->crtc_w;
	plane_state->crtc_w = new_state->crtc_w;
	plane->state->src_x = new_state->src_x;
	plane_state->src_x = new_state->src_x;
	plane->state->src_y = new_state->src_y;
	plane_state->src_y = new_state->src_y;
	plane->state->src_h = new_state->src_h;
	plane_state->src_h = new_state->src_h;
	plane->state->src_w = new_state->src_w;
	plane_state->src_w = new_state->src_w;
	swap(plane->state->fb, new_state->fb);

	if (plane_state->fb != new_state->fb)
		drm_atomic_set_fb_for_plane(plane_state, new_state->fb);

	swap(plane_state, plane->state);

	if (plane->state->fb && plane->state->fb != new_state->fb) {
		drm_framebuffer_get(plane->state->fb);
		WARN_ON(drm_crtc_vblank_get(plane->state->crtc) != 0);
		drm_flip_work_queue(&vop->fb_unref_work, plane->state->fb);
		set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
	}


	if (vop->is_enabled) {
	if (vop->is_enabled) {
		rockchip_drm_psr_inhibit_get_state(new_state->state);
		rockchip_drm_psr_inhibit_get_state(new_state->state);
@@ -955,9 +943,22 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane,
		vop_cfg_done(vop);
		vop_cfg_done(vop);
		spin_unlock(&vop->reg_lock);
		spin_unlock(&vop->reg_lock);
		rockchip_drm_psr_inhibit_put_state(new_state->state);
		rockchip_drm_psr_inhibit_put_state(new_state->state);
	}


	plane->funcs->atomic_destroy_state(plane, plane_state);
		/*
		 * A scanout can still be occurring, so we can't drop the
		 * reference to the old framebuffer. To solve this we get a
		 * reference to old_fb and set a worker to release it later.
		 * FIXME: if we perform 500 async_update calls before the
		 * vblank, then we can have 500 different framebuffers waiting
		 * to be released.
		 */
		if (old_fb && plane->state->fb != old_fb) {
			drm_framebuffer_get(old_fb);
			WARN_ON(drm_crtc_vblank_get(plane->state->crtc) != 0);
			drm_flip_work_queue(&vop->fb_unref_work, old_fb);
			set_bit(VOP_PENDING_FB_UNREF, &vop->pending);
		}
	}
}
}


static const struct drm_plane_helper_funcs plane_helper_funcs = {
static const struct drm_plane_helper_funcs plane_helper_funcs = {
Loading