[PATCH 46/55] drm: Track framebuffer references at the point of assignment

Chris Wilson chris at chris-wilson.co.uk
Mon Sep 19 10:37:00 UTC 2016


Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_display.c |  2 +-
 drivers/gpu/drm/armada/armada_crtc.c        |  9 +--
 drivers/gpu/drm/bochs/bochs_kms.c           |  2 +-
 drivers/gpu/drm/drm_atomic.c                | 42 --------------
 drivers/gpu/drm/drm_atomic_helper.c         | 35 +-----------
 drivers/gpu/drm/drm_crtc.c                  | 89 ++++++++---------------------
 drivers/gpu/drm/drm_crtc_helper.c           | 18 +++---
 drivers/gpu/drm/drm_fb_helper.c             | 17 +++---
 drivers/gpu/drm/i915/intel_display.c        | 16 +++---
 drivers/gpu/drm/mgag200/mgag200_mode.c      |  2 +-
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c   |  2 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c   |  2 +-
 drivers/gpu/drm/nouveau/nouveau_display.c   |  2 +-
 drivers/gpu/drm/qxl/qxl_display.c           |  4 +-
 drivers/gpu/drm/radeon/radeon_display.c     |  3 +-
 drivers/gpu/drm/shmobile/shmob_drm_crtc.c   |  2 +-
 drivers/gpu/drm/tilcdc/tilcdc_crtc.c        |  4 +-
 drivers/gpu/drm/udl/udl_modeset.c           |  2 +-
 drivers/gpu/drm/vc4/vc4_crtc.c              |  2 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c         |  4 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c        | 10 ++--
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c        |  4 +-
 include/drm/drm_atomic.h                    |  3 -
 include/drm/drm_crtc.h                      | 20 +++++--
 24 files changed, 92 insertions(+), 204 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 9af8d3c7ae8b..0d324b955008 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -225,7 +225,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
 	DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n",
 					 amdgpu_crtc->crtc_id, amdgpu_crtc, work);
 	/* update crtc fb */
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 	amdgpu_flip_work_func(&work->flip_work.work);
 	return 0;
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index 2f58e9e2a59c..03464dd46174 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1023,13 +1023,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
 		return ret;
 	}
 
-	/*
-	 * Don't take a reference on the new framebuffer;
-	 * drm_mode_page_flip_ioctl() has already grabbed a reference and
-	 * will _not_ drop that reference on successful return from this
-	 * function.  Simply mark this new framebuffer as the current one.
-	 */
-	dcrtc->crtc.primary->fb = fb;
+	drm_plane_set_fb(dcrtc->crtc.primary, fb);
 
 	/*
 	 * Finally, if the display is blanked, we won't receive an
@@ -1038,6 +1032,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
 	if (dpms_blanked(dcrtc->dpms))
 		armada_drm_plane_work_run(dcrtc, drm_to_armada_plane(dcrtc->crtc.primary));
 
+	drm_framebuffer_unreference(fb);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 207a2cbcc113..8d6789e745ff 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -103,7 +103,7 @@ static int bochs_crtc_page_flip(struct drm_crtc *crtc,
 	struct drm_framebuffer *old_fb = crtc->primary->fb;
 	unsigned long irqflags;
 
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 	bochs_crtc_mode_set_base(crtc, 0, 0, old_fb);
 	if (event) {
 		spin_lock_irqsave(&bochs->dev->event_lock, irqflags);
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index f06418c91abe..c29df30f4d8f 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1552,45 +1552,6 @@ static int atomic_set_prop(struct drm_atomic_state *state,
 	return ret;
 }
 
-/**
- * drm_atomic_clean_old_fb -- Unset old_fb pointers and set plane->fb pointers.
- *
- * @dev: drm device to check.
- * @plane_mask: plane mask for planes that were updated.
- * @ret: return value, can be -EDEADLK for a retry.
- *
- * Before doing an update plane->old_fb is set to plane->fb,
- * but before dropping the locks old_fb needs to be set to NULL
- * and plane->fb updated. This is a common operation for each
- * atomic update, so this call is split off as a helper.
- */
-void drm_atomic_clean_old_fb(struct drm_device *dev,
-			     unsigned plane_mask,
-			     int ret)
-{
-	struct drm_plane *plane;
-
-	/* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
-	 * locks (ie. while it is still safe to deref plane->state).  We
-	 * need to do this here because the driver entry points cannot
-	 * distinguish between legacy and atomic ioctls.
-	 */
-	drm_for_each_plane_mask(plane, dev, plane_mask) {
-		if (ret == 0) {
-			struct drm_framebuffer *new_fb = plane->state->fb;
-			if (new_fb)
-				drm_framebuffer_reference(new_fb);
-			plane->fb = new_fb;
-			plane->crtc = plane->state->crtc;
-
-			if (plane->old_fb)
-				drm_framebuffer_unreference(plane->old_fb);
-		}
-		plane->old_fb = NULL;
-	}
-}
-EXPORT_SYMBOL(drm_atomic_clean_old_fb);
-
 int drm_mode_atomic_ioctl(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv)
 {
@@ -1717,7 +1678,6 @@ retry:
 		    !(arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
 			plane = obj_to_plane(obj);
 			plane_mask |= (1 << drm_plane_index(plane));
-			plane->old_fb = plane->fb;
 		}
 		drm_mode_object_unreference(obj);
 	}
@@ -1750,8 +1710,6 @@ retry:
 	}
 
 out:
-	drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
 	if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
 		/*
 		 * TEST_ONLY and PAGE_FLIP_EVENT are mutually exclusive,
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 35a6f841c385..d2ce5d1593b0 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2043,6 +2043,9 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 	}
 
 	for_each_plane_in_state(state, plane, plane_state, i) {
+		drm_plane_set_fb(plane, plane_state->fb);
+		plane->crtc = plane_state->crtc;
+
 		plane->state->state = state;
 		swap(state->planes[i].state, plane->state);
 		plane->state->state = NULL;
@@ -2120,14 +2123,6 @@ fail:
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
-
-	/*
-	 * Someone might have exchanged the framebuffer while we dropped locks
-	 * in the backoff code. We need to fix up the fb refcount tracking the
-	 * core does for us.
-	 */
-	plane->old_fb = plane->fb;
-
 	goto retry;
 }
 EXPORT_SYMBOL(drm_atomic_helper_update_plane);
@@ -2188,14 +2183,6 @@ fail:
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
-
-	/*
-	 * Someone might have exchanged the framebuffer while we dropped locks
-	 * in the backoff code. We need to fix up the fb refcount tracking the
-	 * core does for us.
-	 */
-	plane->old_fb = plane->fb;
-
 	goto retry;
 }
 EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
@@ -2323,14 +2310,6 @@ fail:
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
-
-	/*
-	 * Someone might have exchanged the framebuffer while we dropped locks
-	 * in the backoff code. We need to fix up the fb refcount tracking the
-	 * core does for us.
-	 */
-	crtc->primary->old_fb = crtc->primary->fb;
-
 	goto retry;
 }
 EXPORT_SYMBOL(drm_atomic_helper_set_config);
@@ -2801,14 +2780,6 @@ fail:
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
-
-	/*
-	 * Someone might have exchanged the framebuffer while we dropped locks
-	 * in the backoff code. We need to fix up the fb refcount tracking the
-	 * core does for us.
-	 */
-	plane->old_fb = plane->fb;
-
 	goto retry;
 }
 EXPORT_SYMBOL(drm_atomic_helper_page_flip);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 4af6a7525587..dd62b1e05c40 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -485,17 +485,13 @@ void drm_plane_force_disable(struct drm_plane *plane)
 	if (!plane->fb)
 		return;
 
-	plane->old_fb = plane->fb;
 	ret = plane->funcs->disable_plane(plane);
 	if (ret) {
 		DRM_ERROR("failed to disable plane with busy fb\n");
-		plane->old_fb = NULL;
 		return;
 	}
 	/* disconnect the plane from the fb and crtc: */
-	drm_framebuffer_unreference(plane->old_fb);
-	plane->old_fb = NULL;
-	plane->fb = NULL;
+	drm_plane_set_fb(plane, NULL);
 	plane->crtc = NULL;
 }
 EXPORT_SYMBOL(drm_plane_force_disable);
@@ -1045,13 +1041,10 @@ static int __setplane_internal(struct drm_plane *plane,
 
 	/* No fb means shut it down */
 	if (!fb) {
-		plane->old_fb = plane->fb;
 		ret = plane->funcs->disable_plane(plane);
 		if (!ret) {
+			drm_plane_set_fb(plane, NULL);
 			plane->crtc = NULL;
-			plane->fb = NULL;
-		} else {
-			plane->old_fb = NULL;
 		}
 		goto out;
 	}
@@ -1087,25 +1080,15 @@ static int __setplane_internal(struct drm_plane *plane,
 	if (ret)
 		goto out;
 
-	plane->old_fb = plane->fb;
 	ret = plane->funcs->update_plane(plane, crtc, fb,
 					 crtc_x, crtc_y, crtc_w, crtc_h,
 					 src_x, src_y, src_w, src_h);
 	if (!ret) {
 		plane->crtc = crtc;
-		plane->fb = fb;
-		fb = NULL;
-	} else {
-		plane->old_fb = NULL;
+		drm_plane_set_fb(plane, fb);
 	}
 
 out:
-	if (fb)
-		drm_framebuffer_unreference(fb);
-	if (plane->old_fb)
-		drm_framebuffer_unreference(plane->old_fb);
-	plane->old_fb = NULL;
-
 	return ret;
 }
 
@@ -1149,6 +1132,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 	struct drm_plane *plane;
 	struct drm_crtc *crtc = NULL;
 	struct drm_framebuffer *fb = NULL;
+	int ret;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -1184,11 +1168,16 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 	 * setplane_internal will take care of deref'ing either the old or new
 	 * framebuffer depending on success.
 	 */
-	return setplane_internal(plane, crtc, fb,
-				 plane_req->crtc_x, plane_req->crtc_y,
-				 plane_req->crtc_w, plane_req->crtc_h,
-				 plane_req->src_x, plane_req->src_y,
-				 plane_req->src_w, plane_req->src_h);
+	ret = setplane_internal(plane, crtc, fb,
+				plane_req->crtc_x, plane_req->crtc_y,
+				plane_req->crtc_w, plane_req->crtc_h,
+				plane_req->src_x, plane_req->src_y,
+				plane_req->src_w, plane_req->src_h);
+
+	if (fb)
+		drm_framebuffer_unreference(fb);
+
+	return ret;
 }
 
 /**
@@ -1204,32 +1193,13 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
 int drm_mode_set_config_internal(struct drm_mode_set *set)
 {
 	struct drm_crtc *crtc = set->crtc;
-	struct drm_framebuffer *fb;
-	struct drm_crtc *tmp;
+	struct drm_framebuffer *fb = set->fb;
 	int ret;
 
-	/*
-	 * NOTE: ->set_config can also disable other crtcs (if we steal all
-	 * connectors from it), hence we need to refcount the fbs across all
-	 * crtcs. Atomic modeset will have saner semantics ...
-	 */
-	drm_for_each_crtc(tmp, crtc->dev)
-		tmp->primary->old_fb = tmp->primary->fb;
-
-	fb = set->fb;
-
 	ret = crtc->funcs->set_config(set);
 	if (ret == 0) {
 		crtc->primary->crtc = crtc;
-		crtc->primary->fb = fb;
-	}
-
-	drm_for_each_crtc(tmp, crtc->dev) {
-		if (tmp->primary->fb)
-			drm_framebuffer_reference(tmp->primary->fb);
-		if (tmp->primary->old_fb)
-			drm_framebuffer_unreference(tmp->primary->old_fb);
-		tmp->primary->old_fb = NULL;
+		drm_plane_set_fb(crtc->primary, fb);
 	}
 
 	return ret;
@@ -1336,14 +1306,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
 		/* If we have a mode we need a framebuffer. */
 		/* If we pass -1, set the mode with the currently bound fb */
 		if (crtc_req->fb_id == -1) {
-			if (!crtc->primary->fb) {
+			/* Make refcounting symmetric with the lookup path. */
+			fb = drm_plane_get_fb(crtc->primary);
+			if (!fb) {
 				DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
 				ret = -EINVAL;
 				goto out;
 			}
-			fb = crtc->primary->fb;
-			/* Make refcounting symmetric with the lookup path. */
-			drm_framebuffer_reference(fb);
 		} else {
 			fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
 			if (!fb) {
@@ -1527,9 +1496,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
 			fb = NULL;
 		}
 	} else {
-		fb = crtc->cursor->fb;
-		if (fb)
-			drm_framebuffer_reference(fb);
+		fb = drm_plane_get_fb(crtc->cursor);
 	}
 
 	if (req->flags & DRM_MODE_CURSOR_MOVE) {
@@ -1561,6 +1528,9 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
 		crtc->cursor_y = req->y;
 	}
 
+	if (fb)
+		drm_framebuffer_unreference(fb);
+
 	return ret;
 }
 
@@ -2028,30 +1998,17 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
 		}
 	}
 
-	crtc->primary->old_fb = crtc->primary->fb;
 	if (crtc->funcs->page_flip_target)
 		ret = crtc->funcs->page_flip_target(crtc, fb, e,
 						    page_flip->flags,
 						    target_vblank);
 	else
 		ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
-	if (ret) {
-		/* Keep the old fb, don't unref it. */
-		crtc->primary->old_fb = NULL;
-	} else {
-		crtc->primary->fb = fb;
-		/* Unref only the old framebuffer. */
-		fb = NULL;
-	}
-
 out:
 	if (ret && crtc->funcs->page_flip_target)
 		drm_crtc_vblank_put(crtc);
 	if (fb)
 		drm_framebuffer_unreference(fb);
-	if (crtc->primary->old_fb)
-		drm_framebuffer_unreference(crtc->primary->old_fb);
-	crtc->primary->old_fb = NULL;
 	drm_modeset_unlock_crtc(crtc);
 
 	return ret;
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 5d2cb138eba6..9818fd8c5988 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -177,7 +177,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev)
 				(*crtc_funcs->disable)(crtc);
 			else
 				(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
-			crtc->primary->fb = NULL;
+			drm_plane_set_fb(crtc->primary, NULL);
 		}
 	}
 }
@@ -579,7 +579,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 	save_set.mode = &set->crtc->mode;
 	save_set.x = set->crtc->x;
 	save_set.y = set->crtc->y;
-	save_set.fb = set->crtc->primary->fb;
+	save_set.fb = drm_plane_get_fb(set->crtc->primary);
 
 	/* We should be able to check here if the fb has the same properties
 	 * and then just flip_or_move it */
@@ -700,13 +700,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 			DRM_DEBUG_KMS("attempting to set mode from"
 					" userspace\n");
 			drm_mode_debug_printmodeline(set->mode);
-			set->crtc->primary->fb = set->fb;
+			drm_plane_set_fb(set->crtc->primary, set->fb);
 			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
 						      set->x, set->y,
 						      save_set.fb)) {
 				DRM_ERROR("failed to set mode on [CRTC:%d:%s]\n",
 					  set->crtc->base.id, set->crtc->name);
-				set->crtc->primary->fb = save_set.fb;
+				drm_plane_set_fb(set->crtc->primary,
+						 save_set.fb);
 				ret = -EINVAL;
 				goto fail;
 			}
@@ -721,17 +722,18 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 	} else if (fb_changed) {
 		set->crtc->x = set->x;
 		set->crtc->y = set->y;
-		set->crtc->primary->fb = set->fb;
+		drm_plane_set_fb(set->crtc->primary, set->fb);
 		ret = crtc_funcs->mode_set_base(set->crtc,
 						set->x, set->y, save_set.fb);
 		if (ret != 0) {
 			set->crtc->x = save_set.x;
 			set->crtc->y = save_set.y;
-			set->crtc->primary->fb = save_set.fb;
+			drm_plane_set_fb(set->crtc->primary, save_set.fb);
 			goto fail;
 		}
 	}
 
+	drm_framebuffer_unreference(save_set.fb);
 	kfree(save_connector_encoders);
 	kfree(save_encoder_crtcs);
 	return 0;
@@ -763,6 +765,7 @@ fail:
 				      save_set.y, save_set.fb))
 		DRM_ERROR("failed to restore config after modeset failure\n");
 
+	drm_framebuffer_unreference(save_set.fb);
 	kfree(save_connector_encoders);
 	kfree(save_encoder_crtcs);
 	return ret;
@@ -924,7 +927,8 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
 			continue;
 
 		ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
-					       crtc->x, crtc->y, crtc->primary->fb);
+					       crtc->x, crtc->y,
+					       crtc->primary->fb);
 
 		/* Restoring the old config should never fail! */
 		if (ret == false)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 05a711ecf97a..c29ef878843a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -270,7 +270,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
 
 	drm_for_each_crtc(c, dev) {
 		if (crtc->base.id == c->base.id)
-			return c->primary->fb;
+			return drm_plane_get_fb(c->primary);
 	}
 
 	return NULL;
@@ -290,21 +290,24 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 
 	for (i = 0; i < helper->crtc_count; i++) {
 		struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
-		crtc = mode_set->crtc;
-		funcs = crtc->helper_private;
-		fb = drm_mode_config_fb(crtc);
 
+		crtc = mode_set->crtc;
 		if (!crtc->enabled)
 			continue;
 
+		fb = drm_mode_config_fb(crtc);
 		if (!fb) {
 			DRM_ERROR("no fb to restore??\n");
 			continue;
 		}
 
 		drm_fb_helper_restore_lut_atomic(mode_set->crtc);
+
+		funcs = crtc->helper_private;
 		funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
 					    crtc->y, LEAVE_ATOMIC_MODE_SET);
+
+		drm_framebuffer_unreference(fb);
 	}
 
 	return 0;
@@ -337,7 +340,6 @@ retry:
 
 		plane_state->rotation = DRM_ROTATE_0;
 
-		plane->old_fb = plane->fb;
 		plane_mask |= 1 << drm_plane_index(plane);
 
 		/* disable non-primary: */
@@ -360,8 +362,6 @@ retry:
 	ret = drm_atomic_commit(state);
 
 fail:
-	drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
 	if (ret == -EDEADLK)
 		goto backoff;
 
@@ -1347,7 +1347,6 @@ retry:
 
 		plane = mode_set->crtc->primary;
 		plane_mask |= (1 << drm_plane_index(plane));
-		plane->old_fb = plane->fb;
 	}
 
 	ret = drm_atomic_commit(state);
@@ -1358,8 +1357,6 @@ retry:
 	info->var.yoffset = var->yoffset;
 
 fail:
-	drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
 	if (ret == -EDEADLK)
 		goto backoff;
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e80af54c959f..4aa68602dc01 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2823,8 +2823,8 @@ valid_fb:
 	if (i915_gem_object_is_tiled(obj))
 		dev_priv->preserve_bios_swizzle = true;
 
-	drm_framebuffer_reference(fb);
-	primary->fb = primary->state->fb = fb;
+	drm_plane_set_fb(primary, fb);
+	update_state_fb(primary);
 
 	mutex_lock(&dev->struct_mutex);
 	intel_state->vma =
@@ -2835,6 +2835,8 @@ valid_fb:
 	intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
 	atomic_or(to_intel_plane(primary)->frontbuffer_bit,
 		  &obj->frontbuffer_bits);
+
+	drm_framebuffer_unreference(fb);
 }
 
 static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
@@ -12186,7 +12188,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	/* Reference the objects for the scheduled work. */
 	drm_framebuffer_reference(work->old_fb);
 
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 	update_state_fb(crtc->primary);
 
 	work->pending_flip_obj = i915_gem_object_get(obj);
@@ -12291,7 +12293,7 @@ cleanup_pending:
 	atomic_dec(&intel_crtc->unpin_work_count);
 	mutex_unlock(&dev->struct_mutex);
 cleanup:
-	crtc->primary->fb = old_fb;
+	drm_plane_set_fb(crtc->primary, old_fb);
 	update_state_fb(crtc->primary);
 
 	i915_gem_object_put(obj);
@@ -13069,7 +13071,6 @@ intel_modeset_update_crtc_state(struct drm_atomic_state *state)
 		if (drm_atomic_get_existing_plane_state(state, crtc->primary)) {
 			struct drm_plane_state *plane_state = crtc->primary->state;
 
-			crtc->primary->fb = plane_state->fb;
 			crtc->x = plane_state->src_x >> 16;
 			crtc->y = plane_state->src_y >> 16;
 		}
@@ -16976,10 +16977,9 @@ void intel_modeset_gem_init(struct drm_device *dev)
 		if (IS_ERR(vma)) {
 			DRM_ERROR("failed to pin boot fb on pipe %d\n",
 				  to_intel_crtc(c)->pipe);
-			drm_framebuffer_unreference(c->primary->fb);
-			c->primary->fb = NULL;
-			c->primary->crtc = c->primary->state->crtc = NULL;
+			drm_plane_set_fb(c->primary, NULL);
 			update_state_fb(c->primary);
+			c->primary->crtc = c->primary->state->crtc = NULL;
 			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
 		}
 
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 6b21cb27e1cc..a2d3ba237f45 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1392,7 +1392,7 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
 		mgag200_bo_push_sysram(bo);
 		mgag200_bo_unreserve(bo);
 	}
-	crtc->primary->fb = NULL;
+	drm_plane_set_fb(crtc->primary, NULL);
 }
 
 /* These provide the minimum set of functions required to handle a CRTC */
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 7c9626d92019..386fbe221401 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -180,7 +180,7 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane,
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe),
 			msm_framebuffer_iova(fb, mdp4_kms->id, 3));
 
-	plane->fb = fb;
+	drm_plane_set_fb(plane, fb);
 }
 
 static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index ba8f43278a44..d95f155248dd 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -408,7 +408,7 @@ static void set_scanout_locked(struct drm_plane *plane,
 	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC3_ADDR(pipe),
 			msm_framebuffer_iova(fb, mdp5_kms->id, 3));
 
-	plane->fb = fb;
+	drm_plane_set_fb(plane, fb);
 }
 
 /* Note: mdp5_plane->pipe_lock must be locked */
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index afbf557b23d4..d7ea64579455 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -802,7 +802,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	mutex_unlock(&cli->mutex);
 
 	/* Update the crtc struct and cleanup */
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 
 	nouveau_bo_fence(old_bo, fence, false);
 	ttm_bo_unreserve(&old_bo->bo);
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 3aef12742a53..078bb5e10501 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -236,7 +236,6 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
 	int one_clip_rect = 1;
 	int ret = 0;
 
-	crtc->primary->fb = fb;
 	bo_old->is_primary = false;
 	bo->is_primary = true;
 
@@ -248,6 +247,7 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
 	if (ret)
 		return ret;
 
+	drm_plane_set_fb(crtc->primary, fb);
 	qxl_draw_dirty_fb(qdev, qfb_src, bo, 0, 0,
 			  &norect, one_clip_rect, inc);
 
@@ -701,7 +701,7 @@ static void qxl_crtc_disable(struct drm_crtc *crtc)
 		ret = qxl_bo_reserve(bo, false);
 		qxl_bo_unpin(bo);
 		qxl_bo_unreserve(bo);
-		crtc->primary->fb = NULL;
+		drm_plane_set_fb(crtc->primary, NULL);
 	}
 
 	qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 890171f08987..97eca0583792 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -581,8 +581,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
 	radeon_crtc->flip_work = work;
 
 	/* update crtc fb */
-	crtc->primary->fb = fb;
-
+	drm_plane_set_fb(crtc->primary, fb);
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 
 	queue_work(radeon_crtc->flip_queue, &work->flip_work);
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index 6547b1db460a..fc5df59976cd 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -462,7 +462,7 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 	shmob_drm_crtc_update_base(scrtc);
 
 	if (event) {
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index 208768922030..c45140ea824d 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -246,9 +246,7 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
 		return -EBUSY;
 	}
 
-	drm_framebuffer_reference(fb);
-
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 
 	spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
 
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index f2b2481cad52..05133ef8942c 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -380,7 +380,7 @@ static int udl_crtc_page_flip(struct drm_crtc *crtc,
 	if (event)
 		drm_crtc_send_vblank_event(crtc, event);
 	spin_unlock_irqrestore(&dev->event_lock, flags);
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 2682f07d8f1e..4f0a8ffe5d90 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -777,7 +777,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
 	 * is released.
 	 */
 	drm_atomic_set_fb_for_plane(plane->state, fb);
-	plane->fb = fb;
+	drm_plane_set_fb(plane, fb);
 
 	vc4_queue_seqno_cb(dev, &flip_state->cb, bo->seqno,
 			   vc4_async_page_flip_complete);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 23ec673d5e16..61a3cce08dfe 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -260,7 +260,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 
 		connector->encoder = NULL;
 		encoder->crtc = NULL;
-		crtc->primary->fb = NULL;
+		drm_plane_set_fb(crtc->primary, NULL);
 		crtc->enabled = false;
 
 		vmw_ldu_del_active(dev_priv, ldu);
@@ -281,7 +281,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 
 	vmw_svga_enable(dev_priv);
 
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 	encoder->crtc = crtc;
 	connector->encoder = encoder;
 	crtc->x = set->x;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index f42359084adc..573c7407c32c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -310,7 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
 
 		connector->encoder = NULL;
 		encoder->crtc = NULL;
-		crtc->primary->fb = NULL;
+		drm_plane_set_fb(crtc->primary, NULL);
 		crtc->x = 0;
 		crtc->y = 0;
 		crtc->enabled = false;
@@ -371,7 +371,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
 
 		connector->encoder = NULL;
 		encoder->crtc = NULL;
-		crtc->primary->fb = NULL;
+		drm_plane_set_fb(crtc->primary, NULL);
 		crtc->x = 0;
 		crtc->y = 0;
 		crtc->enabled = false;
@@ -384,7 +384,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
 	connector->encoder = encoder;
 	encoder->crtc = crtc;
 	crtc->mode = *mode;
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 	crtc->x = set->x;
 	crtc->y = set->y;
 	crtc->enabled = true;
@@ -407,7 +407,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
 	if (!vmw_kms_crtc_flippable(dev_priv, crtc))
 		return -EINVAL;
 
-	crtc->primary->fb = fb;
+	drm_plane_set_fb(crtc->primary, fb);
 
 	/* do a full screen dirty update */
 	vclips.x = crtc->x;
@@ -454,7 +454,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
 	return ret;
 
 out_no_fence:
-	crtc->primary->fb = old_fb;
+	drm_plane_set_fb(crtc->primary, old_fb);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 94ad8d2acf9a..01c4d574fa78 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -486,7 +486,7 @@ static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
 		new_display_srf = NULL;
 	}
 
-	crtc->primary->fb = new_fb;
+	drm_plane_set_fb(crtc->primary, new_fb);
 	stdu->content_fb_type = new_content_type;
 	return 0;
 
@@ -580,7 +580,7 @@ static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
 		if (ret)
 			return ret;
 
-		crtc->primary->fb = NULL;
+		drm_plane_set_fb(crtc->primary, NULL);
 		crtc->enabled = false;
 		encoder->crtc = NULL;
 		connector->encoder = NULL;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 1c6210e7a791..d61425c28985 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -200,9 +200,6 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
 
 void drm_atomic_legacy_backoff(struct drm_atomic_state *state);
 
-void
-drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);
-
 int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
 int __must_check drm_atomic_commit(struct drm_atomic_state *state);
 int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 9ed4c5dadc74..5dafa9c3e454 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -961,8 +961,6 @@ enum drm_plane_type {
  * @format_default: driver hasn't supplied supported formats for the plane
  * @crtc: currently bound CRTC
  * @fb: currently bound fb
- * @old_fb: Temporary tracking of the old fb while a modeset is ongoing. Used by
- * 	drm_mode_set_config_internal() to implement correct refcounting.
  * @funcs: helper functions
  * @properties: property tracking for this plane
  * @type: type of plane (overlay, primary, cursor)
@@ -995,8 +993,6 @@ struct drm_plane {
 	struct drm_crtc *crtc;
 	struct drm_framebuffer *fb;
 
-	struct drm_framebuffer *old_fb;
-
 	const struct drm_plane_funcs *funcs;
 
 	struct drm_object_properties properties;
@@ -2251,4 +2247,20 @@ void drm_bridge_mode_set(struct drm_bridge *bridge,
 void drm_bridge_pre_enable(struct drm_bridge *bridge);
 void drm_bridge_enable(struct drm_bridge *bridge);
 
+static inline void drm_plane_set_fb(struct drm_plane *plane,
+				    struct drm_framebuffer *fb)
+{
+	if (plane->fb != fb)
+		drm_framebuffer_assign(&plane->fb, fb);
+}
+
+static inline struct drm_framebuffer *
+drm_plane_get_fb(struct drm_plane *plane)
+{
+	struct drm_framebuffer *fb = plane->fb;
+	if (fb)
+		drm_framebuffer_reference(fb);
+	return fb;
+}
+
 #endif /* __DRM_CRTC_H__ */
-- 
2.9.3



More information about the Intel-gfx-trybot mailing list