[Intel-gfx] [PATCH] drm/i915: Ensure plane->state->fb stays in sync with plane->fb

Xi Ruoyao xry111 at outlook.com
Thu Mar 12 05:16:32 PDT 2015


plane->state->fb and plane->fb should always reference the same FB so
that atomic and legacy codepaths have the same view of display state.
However, there are some places in kernel code that directly set
plane->fb and neglect to update plane->state->fb. If we never do a
successful update through the atomic pipeline, the RmFB cleanup code
will look at the plane->state->fb pointer, which has never actually
been set to a legitimate value, and try to clean it up, leading to
BUG's.

Add a quick helper function to synchronize plane->state->fb with
plane->fb and call it everywhere the driver tries to manually set
plane->fb outside of the atomic pipeline. In this function, use
drm_atomic_set_fb_for_plane instead of writing plane->state->fb
directly to keep the reference count right.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=88909
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=93711
Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
Signed-off-by: Xi Ruoyao <xry111 at outlook.com>
---
 This is modified from Matt Roper's patch to drm-intel-nightly with 
 commit id

 	afd65eb4cc0578a9c07d621acdb8a570e2782bf7

 However this bug exists in mainline kernel too, so I created this to
 fix it in mainline kernel.

 A minor change is to use drm_atomic_set_fb_for_plane instead of
 update reference count manually.

 drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e730789..c483f2f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -37,6 +37,7 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include "i915_trace.h"
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_crtc_helper.h>
@@ -2416,6 +2417,14 @@ out_unref_obj:
 	return false;
 }
 
+/* Update plane->state->fb to match plane->fb after driver-internal updates */
+static void
+update_state_fb(struct drm_plane *plane)
+{
+	if (plane->fb != plane->state->fb)
+		drm_atomic_set_fb_for_plane(plane->state, plane->fb);
+}
+
 static void
 intel_find_plane_obj(struct intel_crtc *intel_crtc,
 		     struct intel_initial_plane_config *plane_config)
@@ -2462,6 +2471,8 @@ intel_find_plane_obj(struct intel_crtc *intel_crtc,
 			break;
 		}
 	}
+
+	update_state_fb(intel_crtc->base.primary);
 }
 
 static void i9xx_update_primary_plane(struct drm_crtc *crtc,
@@ -6650,6 +6661,7 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
 		      plane_config->size);
 
 	crtc->base.primary->fb = fb;
+	update_state_fb(crtc->base.primary);
 }
 
 static void chv_crtc_clock_get(struct intel_crtc *crtc,
@@ -7687,6 +7699,7 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
 		      plane_config->size);
 
 	crtc->base.primary->fb = fb;
+	update_state_fb(crtc->base.primary);
 	return;
 
 error:
@@ -7778,6 +7791,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc,
 		      plane_config->size);
 
 	crtc->base.primary->fb = fb;
+	update_state_fb(crtc->base.primary);
 }
 
 static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
@@ -9816,6 +9830,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 	drm_gem_object_reference(&obj->base);
 
 	crtc->primary->fb = fb;
+	update_state_fb(crtc->primary);
 
 	work->pending_flip_obj = obj;
 
@@ -9884,6 +9899,7 @@ cleanup_unpin:
 cleanup_pending:
 	atomic_dec(&intel_crtc->unpin_work_count);
 	crtc->primary->fb = old_fb;
+	update_state_fb(crtc->primary);
 	drm_gem_object_unreference(&work->old_fb_obj->base);
 	drm_gem_object_unreference(&obj->base);
 	mutex_unlock(&dev->struct_mutex);
@@ -13718,6 +13734,7 @@ void intel_modeset_gem_init(struct drm_device *dev)
 				  to_intel_crtc(c)->pipe);
 			drm_framebuffer_unreference(c->primary->fb);
 			c->primary->fb = NULL;
+			update_state_fb(c->primary);
 		}
 	}
 	mutex_unlock(&dev->struct_mutex);
-- 
1.9.1



More information about the Intel-gfx mailing list