All of lore.kernel.org
 help / color / mirror / Atom feed
* [DPU PATCH 00/11] drm/msm: Use atomic helper functions for msm
@ 2018-02-28 19:18 Sean Paul
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:18 UTC (permalink / raw)
  To: freedreno, linux-arm-msm, dri-devel; +Cc: hoegsberg, abhinavk

Hey!
This set converts msm to using the atomic helper functions for commit. 
In order to do this, I needed to do the following:

Relocate/remove the copied atomic helper code from msm_atomic:
  Most of this was to deal with seamless modesets introduced in the dpu.
  I'll need to revisit the seamless code soon, but for the purpose of this
  set, moving it down into the driver was fine.

Remove the kthread commit code to do nonblock:
  I think this is an artifact of dpu being forward-ported since 4.4. Now
  that the core has a commit worker, we can use that.

Remove the dpu fences:
  Core has these as well, so we can just nuke them.

Convert mdp5 to use atomic_private_obj:
  By using the private_obj, I could remove the kms->funcs->swap_state()
  hook in atomic commit.


I think this could apply to msm-next pretty easily by taking the
private_obj + event clearing + atomic_helper_commit patches, but I
haven't tried to do that atm.

I think I'll tackle the build warnings next, to ensure I'm not
introducing more.

Sean


Sean Paul (11):
  drm/msm: Skip seamless disables in crtc/encoder
  drm/msm: Don't duplicate modeset_enables atomic helper
  drm/msm: Refactor complete_commit() to look more the helpers
  drm/msm: Move implicit sync fence handling to prepare_fb
  drm/msm: Mark the crtc->state->event consumed
  drm/msm: Remove msm_commit/kthread, use atomic helper commit
  drm/msm: Use atomic private_obj instead of subclassing
  drm/msm: Remove hand-rolled out fences
  drm/msm: Remove prepare_fence kms_function
  drm/msm: Switch to atomic_helper_commit()
  drm/msm: Remove dpu input fences

 drivers/gpu/drm/msm/Makefile                  |   1 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c |  66 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h |  23 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      | 281 ++------
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h      |  28 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |  16 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   4 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 -
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |  73 +--
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |  19 -
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   |  12 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c     | 404 ------------
 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h     | 190 ------
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c       |  61 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h       |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c     | 112 +---
 drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c     |   1 +
 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c     |   1 +
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c      |  37 +-
 drivers/gpu/drm/msm/msm_atomic.c              | 616 +-----------------
 drivers/gpu/drm/msm/msm_drv.c                 |  73 ++-
 drivers/gpu/drm/msm/msm_drv.h                 |  18 +-
 drivers/gpu/drm/msm/msm_kms.h                 |  30 +-
 23 files changed, 219 insertions(+), 1857 deletions(-)
 delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c
 delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h

-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [DPU PATCH 01/11] drm/msm: Skip seamless disables in crtc/encoder
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-02-28 19:18   ` Sean Paul
  2018-03-03  0:04     ` jsanka
  2018-02-28 19:18   ` [DPU PATCH 02/11] drm/msm: Don't duplicate modeset_enables atomic helper Sean Paul
                     ` (9 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:18 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Instead of duplicating whole swaths of atomic helper functions (which
are already out-of-date), just skip the encoder/crtc disables in the
.disable hooks.

Change-Id: I7bd9183ae60624204fb1de9550656b776efc7202
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   8 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   8 +
 drivers/gpu/drm/msm/msm_atomic.c            | 185 +-------------------
 3 files changed, 17 insertions(+), 184 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 3cdf1e3d9d96..a3ab6ed2bf1d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -3393,6 +3393,7 @@ static void dpu_crtc_disable(struct drm_crtc *crtc)
 {
 	struct dpu_crtc *dpu_crtc;
 	struct dpu_crtc_state *cstate;
+	struct drm_display_mode *mode;
 	struct drm_encoder *encoder;
 	struct msm_drm_private *priv;
 	unsigned long flags;
@@ -3407,8 +3408,15 @@ static void dpu_crtc_disable(struct drm_crtc *crtc)
 	}
 	dpu_crtc = to_dpu_crtc(crtc);
 	cstate = to_dpu_crtc_state(crtc->state);
+	mode = &cstate->base.adjusted_mode;
 	priv = crtc->dev->dev_private;
 
+	if (msm_is_mode_seamless(mode) || msm_is_mode_seamless_vrr(mode) ||
+	    msm_is_mode_seamless_dms(mode)) {
+		DPU_DEBUG("Seamless mode is being applied, skip disable\n");
+		return;
+	}
+
 	DPU_DEBUG("crtc%d\n", crtc->base.id);
 
 	if (dpu_kms_is_suspend_state(crtc->dev))
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 3d168fa09f3f..28ceb589ee40 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2183,6 +2183,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
 	struct dpu_encoder_virt *dpu_enc = NULL;
 	struct msm_drm_private *priv;
 	struct dpu_kms *dpu_kms;
+	struct drm_display_mode *mode;
 	int i = 0;
 
 	if (!drm_enc) {
@@ -2196,6 +2197,13 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
 		return;
 	}
 
+	mode = &drm_enc->crtc->state->adjusted_mode;
+	if (msm_is_mode_seamless(mode) || msm_is_mode_seamless_vrr(mode) ||
+	    msm_is_mode_seamless_dms(mode)) {
+		DPU_DEBUG("Seamless mode is being applied, skip disable\n");
+		return;
+	}
+
 	dpu_enc = to_dpu_encoder_virt(drm_enc);
 	DPU_DEBUG_ENC(dpu_enc, "\n");
 
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 46536edb72ee..5cfb80345052 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -84,189 +84,6 @@ static void msm_atomic_wait_for_commit_done(
 	}
 }
 
-static void
-msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
-{
-	struct drm_connector *connector;
-	struct drm_connector_state *old_conn_state, *new_conn_state;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
-	int i;
-
-	for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) {
-		const struct drm_encoder_helper_funcs *funcs;
-		struct drm_encoder *encoder;
-		struct drm_crtc_state *old_crtc_state;
-		unsigned int crtc_idx;
-
-		/*
-		 * Shut down everything that's in the changeset and currently
-		 * still on. So need to check the old, saved state.
-		 */
-		if (!old_conn_state->crtc)
-			continue;
-
-		crtc_idx = drm_crtc_index(old_conn_state->crtc);
-		old_crtc_state = drm_atomic_get_old_crtc_state(old_state,
-							old_conn_state->crtc);
-
-		if (!old_crtc_state->active ||
-		    !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
-			continue;
-
-		encoder = old_conn_state->best_encoder;
-
-		/* We shouldn't get this far if we didn't previously have
-		 * an encoder.. but WARN_ON() rather than explode.
-		 */
-		if (WARN_ON(!encoder))
-			continue;
-
-		if (msm_is_mode_seamless(
-			&connector->encoder->crtc->state->mode) ||
-			msm_is_mode_seamless_vrr(
-			&connector->encoder->crtc->state->adjusted_mode))
-			continue;
-
-		if (msm_is_mode_seamless_dms(
-			&connector->encoder->crtc->state->adjusted_mode))
-			continue;
-
-		funcs = encoder->helper_private;
-
-		DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n",
-				 encoder->base.id, encoder->name);
-
-		/*
-		 * Each encoder has at most one connector (since we always steal
-		 * it away), so we won't call disable hooks twice.
-		 */
-		drm_bridge_disable(encoder->bridge);
-
-		/* Right function depends upon target state. */
-		if (new_conn_state->crtc && funcs->prepare)
-			funcs->prepare(encoder);
-		else if (funcs->disable)
-			funcs->disable(encoder);
-		else
-			funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
-
-		drm_bridge_post_disable(encoder->bridge);
-	}
-
-	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
-		const struct drm_crtc_helper_funcs *funcs;
-
-		/* Shut down everything that needs a full modeset. */
-		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
-			continue;
-
-		if (!old_crtc_state->active)
-			continue;
-
-		if (msm_is_mode_seamless(&crtc->state->mode) ||
-			msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode))
-			continue;
-
-		if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode))
-			continue;
-
-		funcs = crtc->helper_private;
-
-		DRM_DEBUG_ATOMIC("disabling [CRTC:%d]\n",
-				 crtc->base.id);
-
-		/* Right function depends upon target state. */
-		if (new_crtc_state->enable && funcs->prepare)
-			funcs->prepare(crtc);
-		else if (funcs->disable)
-			funcs->disable(crtc);
-		else
-			funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-	}
-}
-
-static void
-msm_crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
-{
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *new_crtc_state;
-	struct drm_connector *connector;
-	struct drm_connector_state *new_conn_state;
-	int i;
-
-	for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
-		const struct drm_crtc_helper_funcs *funcs;
-
-		if (!new_crtc_state->mode_changed)
-			continue;
-
-		funcs = crtc->helper_private;
-
-		if (new_crtc_state->enable && funcs->mode_set_nofb) {
-			DRM_DEBUG_ATOMIC("modeset on [CRTC:%d]\n",
-					 crtc->base.id);
-
-			funcs->mode_set_nofb(crtc);
-		}
-	}
-
-	for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
-		const struct drm_encoder_helper_funcs *funcs;
-		struct drm_crtc_state *new_crtc_state;
-		struct drm_encoder *encoder;
-		struct drm_display_mode *mode, *adjusted_mode;
-
-		if (!new_conn_state->best_encoder)
-			continue;
-
-		encoder = new_conn_state->best_encoder;
-		funcs = encoder->helper_private;
-		new_crtc_state = new_conn_state->crtc->state;
-		mode = &new_crtc_state->mode;
-		adjusted_mode = &new_crtc_state->adjusted_mode;
-
-		if (!new_crtc_state->mode_changed)
-			continue;
-
-		DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n",
-				 encoder->base.id, encoder->name);
-
-		/*
-		 * Each encoder has at most one connector (since we always steal
-		 * it away), so we won't call mode_set hooks twice.
-		 */
-		if (funcs->mode_set)
-			funcs->mode_set(encoder, mode, adjusted_mode);
-
-		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
-	}
-}
-
-/**
- * msm_atomic_helper_commit_modeset_disables - modeset commit to disable outputs
- * @dev: DRM device
- * @old_state: atomic state object with old state structures
- *
- * This function shuts down all the outputs that need to be shut down and
- * prepares them (if required) with the new mode.
- *
- * For compatibility with legacy crtc helpers this should be called before
- * drm_atomic_helper_commit_planes(), which is what the default commit function
- * does. But drivers with different needs can group the modeset commits together
- * and do the plane commits at the end. This is useful for drivers doing runtime
- * PM since planes updates then only happen when the CRTC is actually enabled.
- */
-void msm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
-		struct drm_atomic_state *old_state)
-{
-	msm_disable_outputs(dev, old_state);
-
-	drm_atomic_helper_update_legacy_modeset_state(dev, old_state);
-
-	msm_crtc_set_mode(dev, old_state);
-}
-
 /**
  * msm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs
  * @dev: DRM device
@@ -406,7 +223,7 @@ static void complete_commit(struct msm_commit *c)
 
 	kms->funcs->prepare_commit(kms, state);
 
-	msm_atomic_helper_commit_modeset_disables(dev, state);
+	drm_atomic_helper_commit_modeset_disables(dev, state);
 
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 02/11] drm/msm: Don't duplicate modeset_enables atomic helper
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:18   ` [DPU PATCH 01/11] drm/msm: Skip seamless disables in crtc/encoder Sean Paul
@ 2018-02-28 19:18   ` Sean Paul
       [not found]     ` <20180228191906.185417-3-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:18   ` [DPU PATCH 03/11] drm/msm: Refactor complete_commit() to look more the helpers Sean Paul
                     ` (8 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:18 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Instead, shuffle things around so we kickoff crtc after enabling encoder
during modesets. Also moves the vblank wait to after the frame.

Change-Id: I16c7b7f9390d04f6050aa20e17a5335fbf49eba3
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   9 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   5 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c     |  31 ++++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |   2 +
 drivers/gpu/drm/msm/msm_atomic.c            | 132 +-------------------
 5 files changed, 48 insertions(+), 131 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index a3ab6ed2bf1d..94fab2dcca5b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -3525,6 +3525,12 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
 	DPU_EVT32_VERBOSE(DRMID(crtc));
 	dpu_crtc = to_dpu_crtc(crtc);
 
+	if (msm_is_mode_seamless(&crtc->state->adjusted_mode) ||
+	    msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode)) {
+		DPU_DEBUG("Skipping crtc enable, seamless mode\n");
+		return;
+	}
+
 	pm_runtime_get_sync(crtc->dev->dev);
 
 	drm_for_each_encoder(encoder, crtc->dev) {
@@ -3572,6 +3578,9 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
 		DPU_POWER_EVENT_POST_ENABLE | DPU_POWER_EVENT_POST_DISABLE |
 		DPU_POWER_EVENT_PRE_DISABLE,
 		dpu_crtc_handle_power_event, crtc, dpu_crtc->name);
+
+	if (msm_needs_vblank_pre_modeset(&crtc->state->adjusted_mode))
+		drm_crtc_wait_one_vblank(crtc);
 }
 
 struct plane_state {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 28ceb589ee40..4d1e3652dbf4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -3693,8 +3693,11 @@ static void dpu_encoder_frame_done_timeout(struct timer_list *t)
 static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
 	.mode_set = dpu_encoder_virt_mode_set,
 	.disable = dpu_encoder_virt_disable,
-	.enable = dpu_encoder_virt_enable,
+	.enable = dpu_kms_encoder_enable,
 	.atomic_check = dpu_encoder_virt_atomic_check,
+
+	/* This is called by dpu_kms_encoder_enable */
+	.commit = dpu_encoder_virt_enable,
 };
 
 static const struct drm_encoder_funcs dpu_encoder_funcs = {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 81fd3a429e9f..3d83037e8305 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -425,14 +425,37 @@ static void dpu_kms_prepare_commit(struct msm_kms *kms,
 			dpu_encoder_prepare_commit(encoder);
 }
 
-static void dpu_kms_commit(struct msm_kms *kms,
-		struct drm_atomic_state *old_state)
+/*
+ * Override the encoder enable since we need to setup the inline rotator and do
+ * some crtc magic before enabling any bridge that might be present.
+ */
+void dpu_kms_encoder_enable(struct drm_encoder *encoder)
+{
+	const struct drm_encoder_helper_funcs *funcs = encoder->helper_private;
+	struct drm_crtc *crtc = encoder->crtc;
+
+	/* Forward this enable call to the commit hook */
+	if (funcs && funcs->commit)
+		funcs->commit(encoder);
+
+	if (crtc && crtc->state->active) {
+		DPU_EVT32(DRMID(crtc));
+		dpu_crtc_commit_kickoff(crtc);
+	}
+}
+
+static void dpu_kms_commit(struct msm_kms *kms, struct drm_atomic_state *state)
 {
 	struct drm_crtc *crtc;
-	struct drm_crtc_state *old_crtc_state;
+	struct drm_crtc_state *crtc_state;
+	struct dpu_crtc_state *cstate;
 	int i;
 
-	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+		/* If modeset is required, kickoff is run in encoder_enable */
+		if (drm_atomic_crtc_needs_modeset(crtc_state))
+			continue;
+
 		if (crtc->state->active) {
 			DPU_EVT32(DRMID(crtc));
 			dpu_crtc_commit_kickoff(crtc);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 8cadd29a48b1..42c809ed9467 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -529,4 +529,6 @@ int dpu_kms_fbo_reference(struct dpu_kms_fbo *fbo);
  */
 void dpu_kms_fbo_unreference(struct dpu_kms_fbo *fbo);
 
+void dpu_kms_encoder_enable(struct drm_encoder *encoder);
+
 #endif /* __dpu_kms_H__ */
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 5cfb80345052..f5794dce25dd 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -84,131 +84,6 @@ static void msm_atomic_wait_for_commit_done(
 	}
 }
 
-/**
- * msm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs
- * @dev: DRM device
- * @old_state: atomic state object with old state structures
- *
- * This function enables all the outputs with the new configuration which had to
- * be turned off for the update.
- *
- * For compatibility with legacy crtc helpers this should be called after
- * drm_atomic_helper_commit_planes(), which is what the default commit function
- * does. But drivers with different needs can group the modeset commits together
- * and do the plane commits at the end. This is useful for drivers doing runtime
- * PM since planes updates then only happen when the CRTC is actually enabled.
- */
-static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
-		struct drm_atomic_state *old_state)
-{
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *old_crtc_state;
-	struct drm_crtc_state *new_crtc_state;
-	struct drm_connector *connector;
-	struct drm_connector_state *new_conn_state;
-	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_kms *kms = priv->kms;
-	int bridge_enable_count = 0;
-	int i;
-
-	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
-			new_crtc_state, i) {
-		const struct drm_crtc_helper_funcs *funcs;
-
-		/* Need to filter out CRTCs where only planes change. */
-		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
-			continue;
-
-		if (!new_crtc_state->active)
-			continue;
-
-		if (msm_is_mode_seamless(&new_crtc_state->mode) ||
-				msm_is_mode_seamless_vrr(
-				&new_crtc_state->adjusted_mode))
-			continue;
-
-		funcs = crtc->helper_private;
-
-		if (crtc->state->enable) {
-			DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n",
-					 crtc->base.id);
-
-			if (funcs->atomic_enable)
-				funcs->atomic_enable(crtc, old_crtc_state);
-			else
-				funcs->commit(crtc);
-		}
-
-		if (msm_needs_vblank_pre_modeset(
-					&new_crtc_state->adjusted_mode))
-			drm_crtc_wait_one_vblank(crtc);
-	}
-
-	/* ensure bridge/encoder updates happen on same vblank */
-	msm_atomic_wait_for_commit_done(dev, old_state);
-
-	for_each_new_connector_in_state(old_state, connector,
-			new_conn_state, i) {
-		const struct drm_encoder_helper_funcs *funcs;
-		struct drm_encoder *encoder;
-
-		if (!new_conn_state->best_encoder)
-			continue;
-
-		if (!new_conn_state->crtc->state->active ||
-		    !drm_atomic_crtc_needs_modeset(
-			    new_conn_state->crtc->state))
-			continue;
-
-		encoder = new_conn_state->best_encoder;
-		funcs = encoder->helper_private;
-
-		DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
-				 encoder->base.id, encoder->name);
-
-		/*
-		 * Each encoder has at most one connector (since we always steal
-		 * it away), so we won't call enable hooks twice.
-		 */
-		drm_bridge_pre_enable(encoder->bridge);
-		++bridge_enable_count;
-
-		if (funcs->enable)
-			funcs->enable(encoder);
-		else
-			funcs->commit(encoder);
-	}
-
-	if (kms->funcs->commit) {
-		DRM_DEBUG_ATOMIC("triggering commit\n");
-		kms->funcs->commit(kms, old_state);
-	}
-
-	/* If no bridges were pre_enabled, skip iterating over them again */
-	if (bridge_enable_count == 0)
-		return;
-
-	for_each_new_connector_in_state(old_state, connector,
-			new_conn_state, i) {
-		struct drm_encoder *encoder;
-
-		if (!new_conn_state->best_encoder)
-			continue;
-
-		if (!new_conn_state->crtc->state->active ||
-		    !drm_atomic_crtc_needs_modeset(
-				    new_conn_state->crtc->state))
-			continue;
-
-		encoder = new_conn_state->best_encoder;
-
-		DRM_DEBUG_ATOMIC("bridge enable enabling [ENCODER:%d:%s]\n",
-				 encoder->base.id, encoder->name);
-
-		drm_bridge_enable(encoder->bridge);
-	}
-}
-
 /* The (potentially) asynchronous part of the commit.  At this point
  * nothing can fail short of armageddon.
  */
@@ -227,7 +102,12 @@ static void complete_commit(struct msm_commit *c)
 
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
-	msm_atomic_helper_commit_modeset_enables(dev, state);
+	drm_atomic_helper_commit_modeset_enables(dev, state);
+
+	if (kms->funcs->commit) {
+		DRM_DEBUG_ATOMIC("triggering commit\n");
+		kms->funcs->commit(kms, state);
+	}
 
 	/* NOTE: _wait_for_vblanks() only waits for vblank on
 	 * enabled CRTCs.  So we end up faulting when disabling
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 03/11] drm/msm: Refactor complete_commit() to look more the helpers
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:18   ` [DPU PATCH 01/11] drm/msm: Skip seamless disables in crtc/encoder Sean Paul
  2018-02-28 19:18   ` [DPU PATCH 02/11] drm/msm: Don't duplicate modeset_enables atomic helper Sean Paul
@ 2018-02-28 19:18   ` Sean Paul
       [not found]     ` <20180228191906.185417-4-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:18   ` [DPU PATCH 04/11] drm/msm: Move implicit sync fence handling to prepare_fb Sean Paul
                     ` (7 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:18 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Factor out the commit_tail() portions of complete_commit() into a
separate function to facilitate moving to the atomic helpers in future
patches.

Change-Id: I4b858ad9fe356b31ed0ed9eecdb394a61048e39c
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/msm_atomic.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index f5794dce25dd..eb2ccda5da0f 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -84,18 +84,12 @@ static void msm_atomic_wait_for_commit_done(
 	}
 }
 
-/* The (potentially) asynchronous part of the commit.  At this point
- * nothing can fail short of armageddon.
- */
-static void complete_commit(struct msm_commit *c)
+static void msm_atomic_commit_tail(struct drm_atomic_state *state)
 {
-	struct drm_atomic_state *state = c->state;
 	struct drm_device *dev = state->dev;
 	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_kms *kms = priv->kms;
 
-	drm_atomic_helper_wait_for_fences(dev, state, false);
-
 	kms->funcs->prepare_commit(kms, state);
 
 	drm_atomic_helper_commit_modeset_disables(dev, state);
@@ -127,10 +121,21 @@ static void complete_commit(struct msm_commit *c)
 	drm_atomic_helper_cleanup_planes(dev, state);
 
 	kms->funcs->complete_commit(kms, state);
+}
 
-	drm_atomic_state_put(state);
+/* The (potentially) asynchronous part of the commit.  At this point
+ * nothing can fail short of armageddon.
+ */
+static void complete_commit(struct msm_commit *c)
+{
+	struct drm_atomic_state *state = c->state;
+	struct drm_device *dev = state->dev;
 
-	commit_destroy(c);
+	drm_atomic_helper_wait_for_fences(dev, state, false);
+
+	msm_atomic_commit_tail(state);
+
+	drm_atomic_state_put(state);
 }
 
 static void _msm_drm_commit_work_cb(struct kthread_work *work)
@@ -145,6 +150,8 @@ static void _msm_drm_commit_work_cb(struct kthread_work *work)
 	commit = container_of(work, struct msm_commit, commit_work);
 
 	complete_commit(commit);
+
+	commit_destroy(commit);
 }
 
 static struct msm_commit *commit_init(struct drm_atomic_state *state,
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 04/11] drm/msm: Move implicit sync fence handling to prepare_fb
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                     ` (2 preceding siblings ...)
  2018-02-28 19:18   ` [DPU PATCH 03/11] drm/msm: Refactor complete_commit() to look more the helpers Sean Paul
@ 2018-02-28 19:18   ` Sean Paul
       [not found]     ` <20180228191906.185417-5-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:19   ` [DPU PATCH 05/11] drm/msm: Mark the crtc->state->event consumed Sean Paul
                     ` (6 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:18 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

This is another piece that can be moved out of atomic to facilitate using
the atomic helpers.

Change-Id: I6dc3c4e5df508942bbc378c73a44e46e511b8469
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c |  8 ++++++++
 drivers/gpu/drm/msm/msm_atomic.c          | 13 -------------
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 834dcc0bfefd..29e72b39fd72 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -2720,6 +2720,8 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
 	struct dpu_plane_rot_state *new_rstate;
 	struct dpu_hw_fmt_layout layout;
 	struct msm_gem_address_space *aspace;
+	struct msm_gem_object *msm_obj;
+	struct dma_fence *fence;
 	int ret;
 
 	if (!new_state->fb)
@@ -2761,6 +2763,12 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
 		return ret;
 	}
 
+	/* To support implicit sync, set a fence on the plane if appropriate */
+	msm_obj = to_msm_bo(msm_framebuffer_bo(fb, 0));
+	fence = reservation_object_get_excl_rcu(msm_obj->resv);
+	if (fence)
+		drm_atomic_set_fence_for_plane(new_state, fence);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index eb2ccda5da0f..3a18bd3dc215 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -282,19 +282,6 @@ int msm_atomic_commit(struct drm_device *dev,
 	for_each_new_crtc_in_state(state, crtc, crtc_state, i)
 		c->crtc_mask |= drm_crtc_mask(crtc);
 
-	/*
-	 * Figure out what fence to wait for:
-	 */
-	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
-		if ((new_plane_state->fb != old_plane_state->fb) && new_plane_state->fb) {
-			struct drm_gem_object *obj = msm_framebuffer_bo(new_plane_state->fb, 0);
-			struct msm_gem_object *msm_obj = to_msm_bo(obj);
-			struct dma_fence *fence = reservation_object_get_excl_rcu(msm_obj->resv);
-
-			drm_atomic_set_fence_for_plane(new_plane_state, fence);
-		}
-	}
-
 	/*
 	 * Wait for pending updates on any of the same crtc's and then
 	 * mark our set of crtc's as busy:
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 05/11] drm/msm: Mark the crtc->state->event consumed
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                     ` (3 preceding siblings ...)
  2018-02-28 19:18   ` [DPU PATCH 04/11] drm/msm: Move implicit sync fence handling to prepare_fb Sean Paul
@ 2018-02-28 19:19   ` Sean Paul
  2018-03-06  1:53     ` Jeykumar Sankaran
  2018-02-28 19:19   ` [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit Sean Paul
                     ` (5 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:19 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Don't leave the event != NULL once it's consumed, this is used a signal
to the atomic helpers that the event will be handled by the driver.

Change-Id: Ib934fb2e97bacbb4a1f9c780cc7369c2bb98ed50
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  | 2 ++
 drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c | 1 +
 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 1 +
 3 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 94fab2dcca5b..a261021e5deb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -2714,6 +2714,7 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
 	} else {
 		spin_lock_irqsave(&dev->event_lock, flags);
 		dpu_crtc->event = crtc->state->event;
+		crtc->state->event = NULL;
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
 
@@ -2798,6 +2799,7 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
 	} else {
 		spin_lock_irqsave(&dev->event_lock, flags);
 		dpu_crtc->event = crtc->state->event;
+		crtc->state->event = NULL;
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
 
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
index 6e5e1aa54ce1..b001699297c4 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
@@ -351,6 +351,7 @@ static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	spin_lock_irqsave(&dev->event_lock, flags);
 	mdp4_crtc->event = crtc->state->event;
+	crtc->state->event = NULL;
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
 	blend_setup(crtc);
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
index 8c5ed0b59e46..5cb490a58f20 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -704,6 +704,7 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc,
 
 	spin_lock_irqsave(&dev->event_lock, flags);
 	mdp5_crtc->event = crtc->state->event;
+	crtc->state->event = NULL;
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
 	/*
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                     ` (4 preceding siblings ...)
  2018-02-28 19:19   ` [DPU PATCH 05/11] drm/msm: Mark the crtc->state->event consumed Sean Paul
@ 2018-02-28 19:19   ` Sean Paul
       [not found]     ` <20180228191906.185417-7-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:19   ` [DPU PATCH 07/11] drm/msm: Use atomic private_obj instead of subclassing Sean Paul
                     ` (4 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:19 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Moving further towards switching fully to the the atomic helpers, this
patch removes the hand-rolled kthread nonblock commit code and uses the
atomic helpers commit_work model.

There's still a lot of copypasta here, but it's still needed to
facilitate the swap_state and prepare_fence private functions. These
will be sorted out in a follow-on patch.

Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/msm_atomic.c | 199 ++++++-------------------------
 drivers/gpu/drm/msm/msm_drv.c    |   1 -
 drivers/gpu/drm/msm/msm_drv.h    |   4 -
 3 files changed, 35 insertions(+), 169 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 3a18bd3dc215..7e54eb65d096 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -21,51 +21,6 @@
 #include "msm_gem.h"
 #include "msm_fence.h"
 
-struct msm_commit {
-	struct drm_device *dev;
-	struct drm_atomic_state *state;
-	uint32_t crtc_mask;
-	bool nonblock;
-	struct kthread_work commit_work;
-};
-
-/* block until specified crtcs are no longer pending update, and
- * atomically mark them as pending update
- */
-static int start_atomic(struct msm_drm_private *priv, uint32_t crtc_mask)
-{
-	int ret;
-
-	spin_lock(&priv->pending_crtcs_event.lock);
-	ret = wait_event_interruptible_locked(priv->pending_crtcs_event,
-			!(priv->pending_crtcs & crtc_mask));
-	if (ret == 0) {
-		DBG("start: %08x", crtc_mask);
-		priv->pending_crtcs |= crtc_mask;
-	}
-	spin_unlock(&priv->pending_crtcs_event.lock);
-
-	return ret;
-}
-
-/* clear specified crtcs (no longer pending update)
- */
-static void end_atomic(struct msm_drm_private *priv, uint32_t crtc_mask)
-{
-	spin_lock(&priv->pending_crtcs_event.lock);
-	DBG("end: %08x", crtc_mask);
-	priv->pending_crtcs &= ~crtc_mask;
-	wake_up_all_locked(&priv->pending_crtcs_event);
-	spin_unlock(&priv->pending_crtcs_event.lock);
-}
-
-static void commit_destroy(struct msm_commit *c)
-{
-	end_atomic(c->dev->dev_private, c->crtc_mask);
-	if (c->nonblock)
-		kfree(c);
-}
-
 static void msm_atomic_wait_for_commit_done(
 		struct drm_device *dev,
 		struct drm_atomic_state *old_state)
@@ -118,6 +73,10 @@ static void msm_atomic_commit_tail(struct drm_atomic_state *state)
 
 	msm_atomic_wait_for_commit_done(dev, state);
 
+	drm_atomic_helper_commit_hw_done(state);
+
+	drm_atomic_helper_wait_for_vblanks(dev, state);
+
 	drm_atomic_helper_cleanup_planes(dev, state);
 
 	kms->funcs->complete_commit(kms, state);
@@ -126,109 +85,25 @@ static void msm_atomic_commit_tail(struct drm_atomic_state *state)
 /* The (potentially) asynchronous part of the commit.  At this point
  * nothing can fail short of armageddon.
  */
-static void complete_commit(struct msm_commit *c)
+static void commit_tail(struct drm_atomic_state *state)
 {
-	struct drm_atomic_state *state = c->state;
-	struct drm_device *dev = state->dev;
+	drm_atomic_helper_wait_for_fences(state->dev, state, false);
 
-	drm_atomic_helper_wait_for_fences(dev, state, false);
+	drm_atomic_helper_wait_for_dependencies(state);
 
 	msm_atomic_commit_tail(state);
 
-	drm_atomic_state_put(state);
-}
-
-static void _msm_drm_commit_work_cb(struct kthread_work *work)
-{
-	struct msm_commit *commit =  NULL;
-
-	if (!work) {
-		DRM_ERROR("%s: Invalid commit work data!\n", __func__);
-		return;
-	}
-
-	commit = container_of(work, struct msm_commit, commit_work);
-
-	complete_commit(commit);
-
-	commit_destroy(commit);
-}
-
-static struct msm_commit *commit_init(struct drm_atomic_state *state,
-		bool nonblock)
-{
-	struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
+	drm_atomic_helper_commit_cleanup_done(state);
 
-	if (!c)
-		return NULL;
-
-	c->dev = state->dev;
-	c->state = state;
-	c->nonblock = nonblock;
-
-	kthread_init_work(&c->commit_work, _msm_drm_commit_work_cb);
-
-	return c;
+	drm_atomic_state_put(state);
 }
 
-/* Start display thread function */
-static void msm_atomic_commit_dispatch(struct drm_device *dev,
-		struct drm_atomic_state *state, struct msm_commit *commit)
+static void commit_work(struct work_struct *work)
 {
-	struct msm_drm_private *priv = dev->dev_private;
-	struct drm_crtc *crtc = NULL;
-	struct drm_crtc_state *new_crtc_state = NULL;
-	int ret = -EINVAL, i = 0, j = 0;
-	bool nonblock;
-
-	/* cache since work will kfree commit in non-blocking case */
-	nonblock = commit->nonblock;
-
-	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
-		for (j = 0; j < priv->num_crtcs; j++) {
-			if (priv->disp_thread[j].crtc_id ==
-						crtc->base.id) {
-				if (priv->disp_thread[j].thread) {
-					kthread_queue_work(
-						&priv->disp_thread[j].worker,
-							&commit->commit_work);
-					/* only return zero if work is
-					 * queued successfully.
-					 */
-					ret = 0;
-				} else {
-					DRM_ERROR(" Error for crtc_id: %d\n",
-						priv->disp_thread[j].crtc_id);
-				}
-				break;
-			}
-		}
-		/*
-		 * TODO: handle cases where there will be more than
-		 * one crtc per commit cycle. Remove this check then.
-		 * Current assumption is there will be only one crtc
-		 * per commit cycle.
-		 */
-		if (j < priv->num_crtcs)
-			break;
-	}
-
-	if (ret) {
-		/**
-		 * this is not expected to happen, but at this point the state
-		 * has been swapped, but we couldn't dispatch to a crtc thread.
-		 * fallback now to a synchronous complete_commit to try and
-		 * ensure that SW and HW state don't get out of sync.
-		 */
-		DRM_ERROR("failed to dispatch commit to any CRTC\n");
-		complete_commit(commit);
-	} else if (!nonblock) {
-		kthread_flush_work(&commit->commit_work);
-	}
-
-	/* free nonblocking commits in this context, after processing */
-	if (!nonblock)
-		kfree(commit);
+	struct drm_atomic_state *state = container_of(work,
+						      struct drm_atomic_state,
+						      commit_work);
+	commit_tail(state);
 }
 
 /**
@@ -247,17 +122,12 @@ int msm_atomic_commit(struct drm_device *dev,
 		struct drm_atomic_state *state, bool nonblock)
 {
 	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_commit *c;
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *crtc_state;
 	struct drm_plane *plane;
 	struct drm_plane_state *old_plane_state, *new_plane_state;
 	int i, ret;
 
-	ret = drm_atomic_helper_prepare_planes(dev, state);
-	if (ret)
-		return ret;
-
 	/*
 	 * Note that plane->atomic_async_check() should fail if we need
 	 * to re-assign hwpipe or anything that touches global atomic
@@ -265,32 +135,30 @@ int msm_atomic_commit(struct drm_device *dev,
 	 * cases.
 	 */
 	if (state->async_update) {
+		ret = drm_atomic_helper_prepare_planes(dev, state);
+		if (ret)
+			return ret;
+
 		drm_atomic_helper_async_commit(dev, state);
 		drm_atomic_helper_cleanup_planes(dev, state);
 		return 0;
 	}
 
-	c = commit_init(state, nonblock);
-	if (!c) {
-		ret = -ENOMEM;
-		goto error;
-	}
+	ret = drm_atomic_helper_setup_commit(state, nonblock);
+	if (ret)
+		return ret;
 
-	/*
-	 * Figure out what crtcs we have:
-	 */
-	for_each_new_crtc_in_state(state, crtc, crtc_state, i)
-		c->crtc_mask |= drm_crtc_mask(crtc);
+	INIT_WORK(&state->commit_work, commit_work);
 
-	/*
-	 * Wait for pending updates on any of the same crtc's and then
-	 * mark our set of crtc's as busy:
-	 */
-	ret = start_atomic(dev->dev_private, c->crtc_mask);
+	ret = drm_atomic_helper_prepare_planes(dev, state);
 	if (ret)
-		goto err_free;
+		return ret;
 
-	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
+	if (!nonblock) {
+		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
+		if (ret)
+			goto error;
+	}
 
 	/*
 	 * This is the point of no return - everything below never fails except
@@ -299,6 +167,8 @@ int msm_atomic_commit(struct drm_device *dev,
 	 *
 	 * swap driver private state while still holding state_lock
 	 */
+	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
+
 	if (to_kms_state(state)->state)
 		priv->kms->funcs->swap_state(priv->kms, state);
 
@@ -329,12 +199,13 @@ int msm_atomic_commit(struct drm_device *dev,
 	 */
 
 	drm_atomic_state_get(state);
-	msm_atomic_commit_dispatch(dev, state, c);
+	if (nonblock)
+		queue_work(system_unbound_wq, &state->commit_work);
+	else
+		commit_tail(state);
 
 	return 0;
 
-err_free:
-	kfree(c);
 error:
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index eda4a2340f93..b354424cccb5 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -549,7 +549,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
 		goto mdss_init_fail;
 
 	priv->wq = alloc_ordered_workqueue("msm_drm", 0);
-	init_waitqueue_head(&priv->pending_crtcs_event);
 
 	INIT_LIST_HEAD(&priv->client_event_list);
 	INIT_LIST_HEAD(&priv->inactive_list);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index cf96a85f4b55..292496b682e8 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -536,10 +536,6 @@ struct msm_drm_private {
 
 	struct workqueue_struct *wq;
 
-	/* crtcs pending async atomic updates: */
-	uint32_t pending_crtcs;
-	wait_queue_head_t pending_crtcs_event;
-
 	unsigned int num_planes;
 	struct drm_plane *planes[MAX_PLANES];
 
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 07/11] drm/msm: Use atomic private_obj instead of subclassing
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                     ` (5 preceding siblings ...)
  2018-02-28 19:19   ` [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit Sean Paul
@ 2018-02-28 19:19   ` Sean Paul
       [not found]     ` <20180228191906.185417-8-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:19   ` [DPU PATCH 08/11] drm/msm: Remove hand-rolled out fences Sean Paul
                     ` (3 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:19 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Instead of subclassing atomic state, store driver private data in
private_obj/state. This allows us to remove the swap_state driver hook
for mdp5 and get closer to using the atomic helpers entirely.

Change-Id: I65a4a2887593ae257d584e00b352b5daf00e4e61
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 37 ++++++--------
 drivers/gpu/drm/msm/msm_atomic.c         | 30 -----------
 drivers/gpu/drm/msm/msm_drv.c            | 65 ++++++++++++++++++++++--
 drivers/gpu/drm/msm/msm_drv.h            |  4 +-
 drivers/gpu/drm/msm/msm_kms.h            | 28 +++++-----
 5 files changed, 95 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 6d8e3a9a6fc0..f1a248419655 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -74,36 +74,32 @@ struct mdp5_state *mdp5_get_state(struct drm_atomic_state *s)
 {
 	struct msm_drm_private *priv = s->dev->dev_private;
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
-	struct msm_kms_state *state = to_kms_state(s);
-	struct mdp5_state *new_state;
+	struct msm_kms_state *kms_state;
 	int ret;
 
-	if (state->state)
-		return state->state;
-
 	ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
 	if (ret)
 		return ERR_PTR(ret);
 
-	new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
-	if (!new_state)
-		return ERR_PTR(-ENOMEM);
+	kms_state = msm_kms_get_state(s);
+	if (IS_ERR_OR_NULL(kms_state))
+		return (struct mdp5_state *)kms_state; /* casting ERR_PTR */
 
-	/* Copy state: */
-	new_state->hwpipe = mdp5_kms->state->hwpipe;
-	new_state->hwmixer = mdp5_kms->state->hwmixer;
-	if (mdp5_kms->smp)
-		new_state->smp = mdp5_kms->state->smp;
+	return kms_state->state;
+}
 
-	state->state = new_state;
+static void *mdp5_duplicate_state(void *state)
+{
+	if (!state)
+		return kzalloc(sizeof(struct mdp5_state), GFP_KERNEL);
 
-	return new_state;
+	return kmemdup(state, sizeof(struct mdp5_state), GFP_KERNEL);
 }
 
-static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)
+static void mdp5_destroy_state(void *state)
 {
-	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
-	swap(to_kms_state(state)->state, mdp5_kms->state);
+	struct mdp5_state *mdp_state = state;
+	kfree(mdp_state);
 }
 
 static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
@@ -229,7 +225,8 @@ static const struct mdp_kms_funcs kms_funcs = {
 		.irq             = mdp5_irq,
 		.enable_vblank   = mdp5_enable_vblank,
 		.disable_vblank  = mdp5_disable_vblank,
-		.swap_state      = mdp5_swap_state,
+		.duplicate_state = mdp5_duplicate_state,
+		.destroy_state	 = mdp5_destroy_state,
 		.prepare_commit  = mdp5_prepare_commit,
 		.complete_commit = mdp5_complete_commit,
 		.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
@@ -726,8 +723,6 @@ static void mdp5_destroy(struct platform_device *pdev)
 
 	if (mdp5_kms->rpm_enabled)
 		pm_runtime_disable(&pdev->dev);
-
-	kfree(mdp5_kms->state);
 }
 
 static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 7e54eb65d096..1f53262ea46b 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -169,9 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
 	 */
 	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
 
-	if (to_kms_state(state)->state)
-		priv->kms->funcs->swap_state(priv->kms, state);
-
 	/*
 	 * Provide the driver a chance to prepare for output fences. This is
 	 * done after the point of no return, but before asynchronous commits
@@ -210,30 +207,3 @@ int msm_atomic_commit(struct drm_device *dev,
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
 }
-
-struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev)
-{
-	struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
-
-	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
-		kfree(state);
-		return NULL;
-	}
-
-	return &state->base;
-}
-
-void msm_atomic_state_clear(struct drm_atomic_state *s)
-{
-	struct msm_kms_state *state = to_kms_state(s);
-	drm_atomic_state_default_clear(&state->base);
-	kfree(state->state);
-	state->state = NULL;
-}
-
-void msm_atomic_state_free(struct drm_atomic_state *state)
-{
-	kfree(to_kms_state(state)->state);
-	drm_atomic_state_default_release(state);
-	kfree(state);
-}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index b354424cccb5..e582d5889b66 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -121,9 +121,62 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
 	.output_poll_changed = msm_fb_output_poll_changed,
 	.atomic_check = msm_atomic_check,
 	.atomic_commit = msm_atomic_commit,
-	.atomic_state_alloc = msm_atomic_state_alloc,
-	.atomic_state_clear = msm_atomic_state_clear,
-	.atomic_state_free = msm_atomic_state_free,
+};
+
+static inline
+struct msm_kms *obj_to_kms(struct drm_private_obj *obj)
+{
+	return container_of(obj, struct msm_kms, base);
+}
+
+static inline
+struct msm_kms_state *state_to_kms_state(struct drm_private_state *state)
+{
+	return container_of(state, struct msm_kms_state, base);
+}
+
+struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *s)
+{
+	struct msm_drm_private *priv = s->dev->dev_private;
+	struct drm_private_obj *obj = &priv->kms->base;
+	struct drm_private_state *state;
+
+	state = drm_atomic_get_private_obj_state(s, obj);
+	if (IS_ERR_OR_NULL(state))
+		return (struct msm_kms_state *)state; /* casting ERR_PTR */
+
+	return state_to_kms_state(state);
+}
+
+static struct drm_private_state *
+msm_kms_duplicate_state(struct drm_private_obj *obj)
+{
+	struct msm_kms *kms = obj_to_kms(obj);
+	struct msm_kms_state *state = state_to_kms_state(obj->state);
+	struct msm_kms_state *new_state;
+
+	if (kms->funcs->duplicate_state)
+		new_state = kms->funcs->duplicate_state(state);
+
+	__drm_atomic_helper_private_obj_duplicate_state(obj, &new_state->base);
+
+	return &new_state->base;
+}
+
+static void msm_kms_destroy_state(struct drm_private_obj *obj,
+				  struct drm_private_state *state)
+{
+	struct msm_kms *kms = obj_to_kms(obj);
+	struct msm_kms_state *kms_state = state_to_kms_state(obj->state);
+
+	if (kms->funcs->destroy_state)
+		kms->funcs->destroy_state(kms_state->state);
+	kfree(kms_state);
+}
+
+static const struct drm_private_state_funcs kms_state_funcs = {
+	.atomic_duplicate_state = msm_kms_duplicate_state,
+	.atomic_destroy_state = msm_kms_destroy_state,
 };
 
 #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
@@ -341,6 +394,8 @@ static int msm_drm_uninit(struct device *dev)
 		}
 	}
 
+	drm_atomic_private_obj_fini(&kms->base);
+
 	msm_gem_shrinker_cleanup(ddev);
 
 	drm_kms_helper_poll_fini(ddev);
@@ -770,6 +825,10 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
 	}
 #endif
 
+	drm_atomic_private_obj_init(&kms->base,
+				    &kms->state.base,
+				    &kms_state_funcs);
+
 	/* perform subdriver post initialization */
 	if (kms && kms->funcs && kms->funcs->postinit) {
 		ret = kms->funcs->postinit(kms);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 292496b682e8..8cab333df717 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -598,9 +598,7 @@ struct msm_format {
 
 int msm_atomic_commit(struct drm_device *dev,
 		struct drm_atomic_state *state, bool nonblock);
-struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
-void msm_atomic_state_clear(struct drm_atomic_state *state);
-void msm_atomic_state_free(struct drm_atomic_state *state);
+struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *state);
 
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
 		struct msm_gem_vma *vma, struct sg_table *sgt);
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 09ba1e79db50..4c5a69258c42 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -57,6 +57,8 @@ struct msm_kms_funcs {
 	void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
 	/* swap global atomic state: */
 	void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state *state);
+	void *(*duplicate_state)(void *state);
+	void (*destroy_state)(void *state);
 	/* modeset, bracketing atomic_commit(): */
 	void (*prepare_fence)(struct msm_kms *kms,
 			struct drm_atomic_state *state);
@@ -114,16 +116,6 @@ struct msm_kms_funcs {
 #endif
 };
 
-struct msm_kms {
-	const struct msm_kms_funcs *funcs;
-
-	/* irq number to be passed on to drm_irq_install */
-	int irq;
-
-	/* mapper-id used to request GEM buffer mapped for scanout: */
-	struct msm_gem_address_space *aspace;
-};
-
 /**
  * Subclass of drm_atomic_state, to allow kms backend to have driver
  * private global state.  The kms backend can do whatever it wants
@@ -131,10 +123,22 @@ struct msm_kms {
  * is kfree'd and set back to NULL.
  */
 struct msm_kms_state {
-	struct drm_atomic_state base;
+	struct drm_private_state base;
 	void *state;
 };
-#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
+
+struct msm_kms {
+	struct drm_private_obj base;
+	struct msm_kms_state state;
+
+	const struct msm_kms_funcs *funcs;
+
+	/* irq number to be passed on to drm_irq_install */
+	int irq;
+
+	/* mapper-id used to request GEM buffer mapped for scanout: */
+	struct msm_gem_address_space *aspace;
+};
 
 static inline void msm_kms_init(struct msm_kms *kms,
 		const struct msm_kms_funcs *funcs)
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 08/11] drm/msm: Remove hand-rolled out fences
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                     ` (6 preceding siblings ...)
  2018-02-28 19:19   ` [DPU PATCH 07/11] drm/msm: Use atomic private_obj instead of subclassing Sean Paul
@ 2018-02-28 19:19   ` Sean Paul
       [not found]     ` <20180228191906.185417-9-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:19   ` [DPU PATCH 09/11] drm/msm: Remove prepare_fence kms_function Sean Paul
                     ` (2 subsequent siblings)
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:19 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Remove release/output/retire fences from the dpu driver. These are
already available via drm core's OUT_FENCE property.

Change-Id: Id4238d0b5457f2c8ee2e87bb7814e1850a573623
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c |  66 +------
 drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h |  23 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      | 178 +++---------------
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h      |  28 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |   3 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   4 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 -
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |  73 +------
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |  19 --
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   |  12 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c       |  30 ---
 drivers/gpu/drm/msm/msm_drv.h                 |   3 -
 12 files changed, 36 insertions(+), 411 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
index 57b8627ef418..cc5bfa862cb7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
@@ -521,7 +521,6 @@ static void dpu_connector_destroy(struct drm_connector *connector)
 		backlight_device_unregister(c_conn->bl_device);
 	drm_connector_unregister(connector);
 	mutex_destroy(&c_conn->lock);
-	dpu_fence_deinit(&c_conn->retire_fence);
 	drm_connector_cleanup(connector);
 	kfree(c_conn);
 }
@@ -906,12 +905,9 @@ static int dpu_connector_atomic_get_property(struct drm_connector *connector,
 	c_state = to_dpu_connector_state(state);
 
 	idx = msm_property_index(&c_conn->property_info, property);
-	if (idx == CONNECTOR_PROP_RETIRE_FENCE)
-		rc = dpu_fence_create(&c_conn->retire_fence, val, 0);
-	else
-		/* get cached property value */
-		rc = msm_property_atomic_get(&c_conn->property_info,
-				&c_state->property_state, property, val);
+	/* get cached property value */
+	rc = msm_property_atomic_get(&c_conn->property_info,
+			&c_state->property_state, property, val);
 
 	/* allow for custom override */
 	if (c_conn->ops.get_property)
@@ -923,39 +919,6 @@ static int dpu_connector_atomic_get_property(struct drm_connector *connector,
 	return rc;
 }
 
-void dpu_connector_prepare_fence(struct drm_connector *connector)
-{
-	if (!connector) {
-		DPU_ERROR("invalid connector\n");
-		return;
-	}
-
-	dpu_fence_prepare(&to_dpu_connector(connector)->retire_fence);
-}
-
-void dpu_connector_complete_commit(struct drm_connector *connector,
-		ktime_t ts)
-{
-	if (!connector) {
-		DPU_ERROR("invalid connector\n");
-		return;
-	}
-
-	/* signal connector's retire fence */
-	dpu_fence_signal(&to_dpu_connector(connector)->retire_fence, ts, false);
-}
-
-void dpu_connector_commit_reset(struct drm_connector *connector, ktime_t ts)
-{
-	if (!connector) {
-		DPU_ERROR("invalid connector\n");
-		return;
-	}
-
-	/* signal connector's retire fence */
-	dpu_fence_signal(&to_dpu_connector(connector)->retire_fence, ts, true);
-}
-
 static enum drm_connector_status
 dpu_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -1214,26 +1177,19 @@ struct drm_connector *dpu_connector_init(struct drm_device *dev,
 			"conn%u",
 			c_conn->base.base.id);
 
-	rc = dpu_fence_init(&c_conn->retire_fence, c_conn->name,
-			c_conn->base.base.id);
-	if (rc) {
-		DPU_ERROR("failed to init fence, %d\n", rc);
-		goto error_cleanup_conn;
-	}
-
 	mutex_init(&c_conn->lock);
 
 	rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder);
 	if (rc) {
 		DPU_ERROR("failed to attach encoder to connector, %d\n", rc);
-		goto error_cleanup_fence;
+		goto error_cleanup_conn;
 	}
 
 #ifdef CONFIG_DRM_MSM_DSI_STAGING
 	rc = dpu_backlight_setup(c_conn, dev);
 	if (rc) {
 		DPU_ERROR("failed to setup backlight, rc=%d\n", rc);
-		goto error_cleanup_fence;
+		goto error_cleanup_conn;
 	}
 #endif
 
@@ -1248,7 +1204,7 @@ struct drm_connector *dpu_connector_init(struct drm_device *dev,
 		if (!info) {
 			DPU_ERROR("failed to allocate info buffer\n");
 			rc = -ENOMEM;
-			goto error_cleanup_fence;
+			goto error_cleanup_conn;
 		}
 
 		dpu_kms_info_reset(info);
@@ -1256,7 +1212,7 @@ struct drm_connector *dpu_connector_init(struct drm_device *dev,
 		if (rc) {
 			DPU_ERROR("post-init failed, %d\n", rc);
 			kfree(info);
-			goto error_cleanup_fence;
+			goto error_cleanup_conn;
 		}
 
 		msm_property_install_blob(&c_conn->property_info,
@@ -1310,10 +1266,6 @@ struct drm_connector *dpu_connector_init(struct drm_device *dev,
 				&c_conn->property_info, "dpu_drm_roi_v1", 0x0,
 				0, ~0, 0, CONNECTOR_PROP_ROI_V1);
 	}
-
-	msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
-			0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
-
 	msm_property_install_range(&c_conn->property_info, "autorefresh",
 			0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0,
 			CONNECTOR_PROP_AUTOREFRESH);
@@ -1354,10 +1306,8 @@ struct drm_connector *dpu_connector_init(struct drm_device *dev,
 		drm_property_blob_put(c_conn->blob_dither);
 
 	msm_property_destroy(&c_conn->property_info);
-error_cleanup_fence:
-	mutex_destroy(&c_conn->lock);
-	dpu_fence_deinit(&c_conn->retire_fence);
 error_cleanup_conn:
+	mutex_destroy(&c_conn->lock);
 	drm_connector_cleanup(&c_conn->base);
 error_free_conn:
 	kfree(c_conn);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
index f6f4837d1359..fdb4d8766549 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
@@ -21,7 +21,6 @@
 #include "msm_drv.h"
 #include "msm_prop.h"
 #include "dpu_kms.h"
-#include "dpu_fence.h"
 
 #define DPU_CONNECTOR_NAME_SIZE	16
 
@@ -247,7 +246,6 @@ struct dpu_connector_evt {
  * @mmu_unsecure: MMU id for unsecure buffers
  * @name: ASCII name of connector
  * @lock: Mutex lock object for this structure
- * @retire_fence: Retire fence context reference
  * @ops: Local callback function pointer table
  * @dpms_mode: DPMS property setting from user space
  * @lp_mode: LP property setting from user space
@@ -274,7 +272,6 @@ struct dpu_connector {
 	char name[DPU_CONNECTOR_NAME_SIZE];
 
 	struct mutex lock;
-	struct dpu_fence_context retire_fence;
 	struct dpu_connector_ops ops;
 	int dpms_mode;
 	int lp_mode;
@@ -447,26 +444,6 @@ struct drm_connector *dpu_connector_init(struct drm_device *dev,
 		int connector_poll,
 		int connector_type);
 
-/**
- * dpu_connector_prepare_fence - prepare fence support for current commit
- * @connector: Pointer to drm connector object
- */
-void dpu_connector_prepare_fence(struct drm_connector *connector);
-
-/**
- * dpu_connector_complete_commit - signal completion of current commit
- * @connector: Pointer to drm connector object
- * @ts: timestamp to be updated in the fence signalling
- */
-void dpu_connector_complete_commit(struct drm_connector *connector, ktime_t ts);
-
-/**
- * dpu_connector_commit_reset - reset the completion signal
- * @connector: Pointer to drm connector object
- * @ts: timestamp to be updated in the fence signalling
- */
-void dpu_connector_commit_reset(struct drm_connector *connector, ktime_t ts);
-
 /**
  * dpu_connector_get_info - query display specific information
  * @connector: Pointer to drm connector object
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index a261021e5deb..2d44989ade7a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -629,7 +629,6 @@ static void dpu_crtc_destroy(struct drm_crtc *crtc)
 	dpu_cp_crtc_destroy_properties(crtc);
 	_dpu_crtc_destroy_dest_scaler(dpu_crtc);
 
-	dpu_fence_deinit(&dpu_crtc->output_fence);
 	_dpu_crtc_deinit_events(dpu_crtc);
 
 	drm_crtc_cleanup(crtc);
@@ -1671,65 +1670,6 @@ static void _dpu_crtc_dest_scaler_setup(struct drm_crtc *crtc)
 	}
 }
 
-void dpu_crtc_prepare_commit(struct drm_crtc *crtc,
-		struct drm_crtc_state *old_state)
-{
-	struct drm_device *dev;
-	struct dpu_crtc *dpu_crtc;
-	struct dpu_crtc_state *cstate;
-	struct drm_connector *conn;
-	struct drm_connector_list_iter conn_iter;
-	struct dpu_crtc_retire_event *retire_event = NULL;
-	unsigned long flags;
-	int i;
-
-	if (!crtc || !crtc->state) {
-		DPU_ERROR("invalid crtc\n");
-		return;
-	}
-
-	dev = crtc->dev;
-	dpu_crtc = to_dpu_crtc(crtc);
-	cstate = to_dpu_crtc_state(crtc->state);
-	DPU_EVT32_VERBOSE(DRMID(crtc));
-
-	/* identify connectors attached to this crtc */
-	cstate->num_connectors = 0;
-
-	drm_connector_list_iter_begin(dev, &conn_iter);
-	drm_for_each_connector_iter(conn, &conn_iter)
-		if (conn->state && conn->state->crtc == crtc &&
-				cstate->num_connectors < MAX_CONNECTORS) {
-			cstate->connectors[cstate->num_connectors++] = conn;
-			dpu_connector_prepare_fence(conn);
-		}
-	drm_connector_list_iter_end(&conn_iter);
-
-	for (i = 0; i < DPU_CRTC_FRAME_EVENT_SIZE; i++) {
-		retire_event = &dpu_crtc->retire_events[i];
-		if (list_empty(&retire_event->list))
-			break;
-		retire_event = NULL;
-	}
-
-	if (retire_event) {
-		retire_event->num_connectors = cstate->num_connectors;
-		for (i = 0; i < cstate->num_connectors; i++)
-			retire_event->connectors[i] = cstate->connectors[i];
-
-		spin_lock_irqsave(&dpu_crtc->spin_lock, flags);
-		list_add_tail(&retire_event->list,
-						&dpu_crtc->retire_event_list);
-		spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
-	} else {
-		DPU_ERROR("crtc%d retire event overflow\n", crtc->base.id);
-		DPU_EVT32(DRMID(crtc), DPU_EVTLOG_ERROR);
-	}
-
-	/* prepare main output fence */
-	dpu_fence_prepare(&dpu_crtc->output_fence);
-}
-
 /**
  *  _dpu_crtc_complete_flip - signal pending page_flip events
  * Any pending vblank events are added to the vblank_event_list
@@ -1799,41 +1739,6 @@ static void dpu_crtc_vblank_cb(void *data)
 	DPU_EVT32_VERBOSE(DRMID(crtc));
 }
 
-static void _dpu_crtc_retire_event(struct drm_crtc *crtc, ktime_t ts)
-{
-	struct dpu_crtc_retire_event *retire_event;
-	struct dpu_crtc *dpu_crtc;
-	unsigned long flags;
-	int i;
-
-	if (!crtc) {
-		DPU_ERROR("invalid param\n");
-		return;
-	}
-
-	dpu_crtc = to_dpu_crtc(crtc);
-	spin_lock_irqsave(&dpu_crtc->spin_lock, flags);
-	retire_event = list_first_entry_or_null(&dpu_crtc->retire_event_list,
-				struct dpu_crtc_retire_event, list);
-	if (retire_event)
-		list_del_init(&retire_event->list);
-	spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
-
-	if (!retire_event) {
-		DPU_ERROR("crtc%d retire event without kickoff\n",
-								crtc->base.id);
-		DPU_EVT32(DRMID(crtc), DPU_EVTLOG_ERROR);
-		return;
-	}
-
-	DPU_ATRACE_BEGIN("signal_retire_fence");
-	for (i = 0; (i < retire_event->num_connectors) &&
-					retire_event->connectors[i]; ++i)
-		dpu_connector_complete_commit(
-					retire_event->connectors[i], ts);
-	DPU_ATRACE_END("signal_retire_fence");
-}
-
 /* _dpu_crtc_idle_notify - signal idle timeout to client */
 static void _dpu_crtc_idle_notify(struct dpu_crtc *dpu_crtc)
 {
@@ -1945,16 +1850,6 @@ static void dpu_crtc_frame_event_work(struct kthread_work *work)
 			frame_done = true;
 	}
 
-	if (fevent->event & DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE) {
-		DPU_ATRACE_BEGIN("signal_release_fence");
-		dpu_fence_signal(&dpu_crtc->output_fence, fevent->ts, false);
-		DPU_ATRACE_END("signal_release_fence");
-	}
-
-	if (fevent->event & DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE)
-		/* this api should be called without spin_lock */
-		_dpu_crtc_retire_event(crtc, fevent->ts);
-
 	if (fevent->event & DPU_ENCODER_FRAME_EVENT_PANEL_DEAD)
 		DPU_ERROR("crtc%d ts:%lld received panel dead event\n",
 				crtc->base.id, ktime_to_ns(fevent->ts));
@@ -1971,11 +1866,11 @@ static void dpu_crtc_frame_event_work(struct kthread_work *work)
 /*
  * dpu_crtc_frame_event_cb - crtc frame event callback API. CRTC module
  * registers this API to encoder for all frame event callbacks like
- * release_fence, retire_fence, frame_error, frame_done, idle_timeout,
- * etc. Encoder may call different events from different context - IRQ,
- * user thread, commit_thread, etc. Each event should be carefully
- * reviewed and should be processed in proper task context to avoid scheduling
- * delay or properly manage the irq context's bottom half processing.
+ * frame_error, frame_done, idle_timeout, etc. Encoder may call different events
+ * from different context - IRQ, user thread, commit_thread, etc. Each event
+ * should be carefully reviewed and should be processed in proper task context
+ * to avoid schedulin delay or properly manage the irq context's bottom half
+ * processing.
  */
 static void dpu_crtc_frame_event_cb(void *data, u32 event)
 {
@@ -3484,14 +3379,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc)
 		dpu_power_handle_unregister_event(&priv->phandle,
 				dpu_crtc->power_event);
 
-	/**
-	 * All callbacks are unregistered and frame done waits are complete
-	 * at this point. No buffers are accessed by hardware.
-	 * reset the fence timeline if there is any issue.
-	 */
-	dpu_fence_signal(&dpu_crtc->output_fence, ktime_get(), true);
-	for (i = 0; i < cstate->num_connectors; ++i)
-		dpu_connector_commit_reset(cstate->connectors[i], ktime_get());
 
 	memset(dpu_crtc->mixers, 0, sizeof(dpu_crtc->mixers));
 	dpu_crtc->num_mixers = 0;
@@ -3703,6 +3590,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 	int multirect_count = 0;
 	const struct drm_plane_state *pipe_staged[SSPP_MAX];
 	int left_zpos_cnt = 0, right_zpos_cnt = 0;
+	struct drm_connector_list_iter conn_iter;
+	struct drm_connector *conn;
 
 	if (!crtc) {
 		DPU_ERROR("invalid crtc\n");
@@ -3956,6 +3845,16 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 		goto end;
 	}
 
+	/* identify connectors attached to this crtc */
+	cstate->num_connectors = 0;
+	drm_connector_list_iter_begin(crtc->dev, &conn_iter);
+	drm_for_each_connector_iter(conn, &conn_iter)
+		if (conn->state && conn->state->crtc == crtc &&
+				cstate->num_connectors < MAX_CONNECTORS) {
+			cstate->connectors[cstate->num_connectors++] = conn;
+		}
+	drm_connector_list_iter_end(&conn_iter);
+
 end:
 	_dpu_crtc_rp_free_unused(&cstate->rp);
 	return rc;
@@ -4034,13 +3933,6 @@ static void dpu_crtc_install_properties(struct drm_crtc *crtc,
 		"input_fence_timeout", 0x0, 0, DPU_CRTC_MAX_INPUT_FENCE_TIMEOUT,
 		DPU_CRTC_INPUT_FENCE_TIMEOUT, CRTC_PROP_INPUT_FENCE_TIMEOUT);
 
-	msm_property_install_range(&dpu_crtc->property_info, "output_fence",
-			0x0, 0, INR_OPEN_MAX, 0x0, CRTC_PROP_OUTPUT_FENCE);
-
-	msm_property_install_range(&dpu_crtc->property_info,
-			"output_fence_offset", 0x0, 0, 1, 0,
-			CRTC_PROP_OUTPUT_FENCE_OFFSET);
-
 	msm_property_install_range(&dpu_crtc->property_info,
 			"core_clk", 0x0, 0, U64_MAX,
 			dpu_kms->perf.max_core_clk_rate,
@@ -4342,29 +4234,12 @@ static int dpu_crtc_atomic_get_property(struct drm_crtc *crtc,
 		}
 
 		i = msm_property_index(&dpu_crtc->property_info, property);
-		if (i == CRTC_PROP_OUTPUT_FENCE) {
-			uint32_t offset = dpu_crtc_get_property(cstate,
-					CRTC_PROP_OUTPUT_FENCE_OFFSET);
-
-			/**
-			 * set the offset to 0 only for cmd mode panels, so
-			 * the release fence for the current frame can be
-			 * triggered right after PP_DONE interrupt.
-			 */
-			offset = is_cmd ? 0 : (offset + conn_offset);
-
-			ret = dpu_fence_create(&dpu_crtc->output_fence, val,
-								offset);
-			if (ret)
-				DPU_ERROR("fence create failed\n");
-		} else {
-			ret = msm_property_atomic_get(&dpu_crtc->property_info,
-					&cstate->property_state,
-					property, val);
-			if (ret)
-				ret = dpu_cp_crtc_get_property(crtc,
-					property, val);
-		}
+		ret = msm_property_atomic_get(&dpu_crtc->property_info,
+				&cstate->property_state,
+				property, val);
+		if (ret)
+			ret = dpu_cp_crtc_get_property(crtc,
+				property, val);
 		if (ret)
 			DRM_ERROR("get property failed\n");
 	}
@@ -4858,10 +4733,6 @@ static int _dpu_crtc_init_events(struct dpu_crtc *dpu_crtc)
 		list_add_tail(&dpu_crtc->event_cache[i].list,
 				&dpu_crtc->event_free_list);
 
-	INIT_LIST_HEAD(&dpu_crtc->retire_event_list);
-	for (i = 0; i < ARRAY_SIZE(dpu_crtc->retire_events); i++)
-		INIT_LIST_HEAD(&dpu_crtc->retire_events[i].list);
-
 	return rc;
 }
 
@@ -4920,9 +4791,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane)
 		return ERR_PTR(rc);
 	}
 
-	/* initialize output fence support */
-	dpu_fence_init(&dpu_crtc->output_fence, dpu_crtc->name, crtc->base.id);
-
 	/* create CRTC properties */
 	msm_property_init(&dpu_crtc->property_info, &crtc->base, dev,
 			priv->crtc_property, dpu_crtc->property_data,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index b63df243be33..727a3434a4f6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -22,7 +22,6 @@
 #include <linux/kthread.h>
 #include <drm/drm_crtc.h>
 #include "msm_prop.h"
-#include "dpu_fence.h"
 #include "dpu_kms.h"
 #include "dpu_core_perf.h"
 #include "dpu_hw_blk.h"
@@ -85,17 +84,6 @@ struct dpu_crtc_smmu_state_data {
 	uint32_t transition_error;
 };
 
-/**
- * @connectors    : Currently associated drm connectors for retire event
- * @num_connectors: Number of associated drm connectors for retire event
- * @list:	event list
- */
-struct dpu_crtc_retire_event {
-	struct drm_connector *connectors[MAX_CONNECTORS];
-	int num_connectors;
-	struct list_head list;
-};
-
 /**
  * struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC
  * @hw_lm:	LM HW Driver context
@@ -169,7 +157,6 @@ struct dpu_crtc_event {
  * @drm_requested_vblank : Whether vblanks have been enabled in the encoder
  * @property_info : Opaque structure for generic property support
  * @property_defaults : Array of default values for generic property support
- * @output_fence  : output release fence context
  * @stage_cfg     : H/w mixer stage configuration
  * @debugfs_root  : Parent of debugfs node
  * @vblank_cb_count : count of vblank callback since last reset
@@ -190,8 +177,6 @@ struct dpu_crtc_event {
  * @frame_events  : static allocation of in-flight frame events
  * @frame_event_list : available frame event list
  * @spin_lock     : spin lock for frame event, transaction status, etc...
- * @retire_events  : static allocation of retire fence connector
- * @retire_event_list : available retire fence connector list
  * @frame_done_comp    : for frame_event_done synchronization
  * @event_thread  : Pointer to event handler thread
  * @event_worker  : Event worker queue
@@ -227,9 +212,6 @@ struct dpu_crtc {
 	struct msm_property_data property_data[CRTC_PROP_COUNT];
 	struct drm_property_blob *blob_info;
 
-	/* output fence support */
-	struct dpu_fence_context output_fence;
-
 	struct dpu_hw_stage_cfg stage_cfg;
 	struct dentry *debugfs_root;
 
@@ -253,8 +235,6 @@ struct dpu_crtc {
 	struct dpu_crtc_frame_event frame_events[DPU_CRTC_FRAME_EVENT_SIZE];
 	struct list_head frame_event_list;
 	spinlock_t spin_lock;
-	struct dpu_crtc_retire_event retire_events[DPU_CRTC_FRAME_EVENT_SIZE];
-	struct list_head retire_event_list;
 	struct completion frame_done_comp;
 
 	/* for handling internal event thread */
@@ -475,14 +455,6 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en);
  */
 void dpu_crtc_commit_kickoff(struct drm_crtc *crtc);
 
-/**
- * dpu_crtc_prepare_commit - callback to prepare for output fences
- * @crtc: Pointer to drm crtc object
- * @old_state: Pointer to drm crtc old state object
- */
-void dpu_crtc_prepare_commit(struct drm_crtc *crtc,
-		struct drm_crtc_state *old_state);
-
 /**
  * dpu_crtc_complete_commit - callback signalling completion of current commit
  * @crtc: Pointer to drm crtc object
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 4d1e3652dbf4..a54ad2cd5856 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2465,9 +2465,6 @@ static inline void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc,
 
 	pending_kickoff_cnt = dpu_encoder_phys_inc_pending(phys);
 
-	if (phys->ops.is_master && phys->ops.is_master(phys))
-		atomic_inc(&phys->pending_retire_fence_cnt);
-
 	if (extra_flush_bits && ctl->ops.update_pending_flush)
 		ctl->ops.update_pending_flush(ctl, extra_flush_bits);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 69fb26cb43ab..86a3800af673 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -27,9 +27,7 @@
 #define DPU_ENCODER_FRAME_EVENT_DONE			BIT(0)
 #define DPU_ENCODER_FRAME_EVENT_ERROR			BIT(1)
 #define DPU_ENCODER_FRAME_EVENT_PANEL_DEAD		BIT(2)
-#define DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE	BIT(3)
-#define DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE	BIT(4)
-#define DPU_ENCODER_FRAME_EVENT_IDLE			BIT(5)
+#define DPU_ENCODER_FRAME_EVENT_IDLE			BIT(3)
 
 #define IDLE_TIMEOUT	(66 - 16/2)
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 3b05569007d2..71cd2f258994 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -245,8 +245,6 @@ struct dpu_encoder_irq {
  *				scheduled. Decremented in irq handler
  * @pending_ctlstart_cnt:	Atomic counter tracking the number of ctl start
  *                              pending.
- * @pending_retire_fence_cnt:   Atomic counter tracking the pending retire
- *                              fences that have to be signalled.
  * @pending_kickoff_wq:		Wait queue for blocking until kickoff completes
  * @irq:			IRQ tracking structures
  */
@@ -273,7 +271,6 @@ struct dpu_encoder_phys {
 	atomic_t underrun_cnt;
 	atomic_t pending_ctlstart_cnt;
 	atomic_t pending_kickoff_cnt;
-	atomic_t pending_retire_fence_cnt;
 	wait_queue_head_t pending_kickoff_wq;
 	struct dpu_encoder_irq irq[INTR_IDX_MAX];
 };
@@ -323,9 +320,6 @@ struct dpu_encoder_phys_cmd_autorefresh {
  *			after ctl_start instead of before next frame kickoff
  * @pp_timeout_report_cnt: number of pingpong done irq timeout errors
  * @autorefresh: autorefresh feature state
- * @pending_rd_ptr_cnt: atomic counter to indicate if retire fence can be
- *                      signaled at the next rd_ptr_irq
- * @rd_ptr_timestamp: last rd_ptr_irq timestamp
  * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK
  * @pending_vblank_wq: Wait queue for blocking until VBLANK received
  */
@@ -335,8 +329,6 @@ struct dpu_encoder_phys_cmd {
 	bool serialize_wait4pp;
 	int pp_timeout_report_cnt;
 	struct dpu_encoder_phys_cmd_autorefresh autorefresh;
-	atomic_t pending_rd_ptr_cnt;
-	ktime_t rd_ptr_timestamp;
 	atomic_t pending_vblank_cnt;
 	wait_queue_head_t pending_vblank_wq;
 };
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index e92380a1d5a4..6ccf37820aa2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -44,12 +44,6 @@
 
 #define DPU_ENC_WR_PTR_START_TIMEOUT_US 20000
 
-/*
- * Threshold for signalling retire fences in cases where
- * CTL_START_IRQ is received just after RD_PTR_IRQ
- */
-#define DPU_ENC_CTL_START_THRESHOLD_US 500
-
 static inline int _dpu_encoder_phys_cmd_get_idle_timeout(
 		struct dpu_encoder_phys_cmd *cmd_enc)
 {
@@ -170,8 +164,7 @@ static void dpu_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
 	struct dpu_encoder_phys *phys_enc = arg;
 	unsigned long lock_flags;
 	int new_cnt;
-	u32 event = DPU_ENCODER_FRAME_EVENT_DONE |
-			DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
+	u32 event = DPU_ENCODER_FRAME_EVENT_DONE;
 
 	if (!phys_enc || !phys_enc->hw_pp)
 		return;
@@ -221,7 +214,6 @@ static void dpu_encoder_phys_cmd_pp_rd_ptr_irq(void *arg, int irq_idx)
 {
 	struct dpu_encoder_phys *phys_enc = arg;
 	struct dpu_encoder_phys_cmd *cmd_enc;
-	u32 event = 0;
 
 	if (!phys_enc || !phys_enc->hw_pp)
 		return;
@@ -229,30 +221,10 @@ static void dpu_encoder_phys_cmd_pp_rd_ptr_irq(void *arg, int irq_idx)
 	DPU_ATRACE_BEGIN("rd_ptr_irq");
 	cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
 
-	/**
-	 * signal only for master, when the ctl_start irq is
-	 * done and incremented the pending_rd_ptr_cnt.
-	 */
-	if (dpu_encoder_phys_cmd_is_master(phys_enc)
-		    && atomic_add_unless(&cmd_enc->pending_rd_ptr_cnt, -1, 0)
-		    && atomic_add_unless(
-				&phys_enc->pending_retire_fence_cnt, -1, 0)) {
-
-		event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
-		if (phys_enc->parent_ops.handle_frame_done)
-			phys_enc->parent_ops.handle_frame_done(
-				phys_enc->parent, phys_enc, event);
-	}
-
-	DPU_EVT32_IRQ(DRMID(phys_enc->parent),
-			phys_enc->hw_pp->idx - PINGPONG_0, event, 0xfff);
-
 	if (phys_enc->parent_ops.handle_vblank_virt)
 		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
 			phys_enc);
 
-	cmd_enc->rd_ptr_timestamp = ktime_get();
-
 	atomic_add_unless(&cmd_enc->pending_vblank_cnt, -1, 0);
 	wake_up_all(&cmd_enc->pending_vblank_wq);
 	DPU_ATRACE_END("rd_ptr_irq");
@@ -262,9 +234,6 @@ static void dpu_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx)
 {
 	struct dpu_encoder_phys *phys_enc = arg;
 	struct dpu_encoder_phys_cmd *cmd_enc;
-	struct dpu_hw_ctl *ctl;
-	u32 event = 0;
-	s64 time_diff_us;
 
 	if (!phys_enc || !phys_enc->hw_ctl)
 		return;
@@ -272,43 +241,8 @@ static void dpu_encoder_phys_cmd_ctl_start_irq(void *arg, int irq_idx)
 	DPU_ATRACE_BEGIN("ctl_start_irq");
 	cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
 
-	ctl = phys_enc->hw_ctl;
 	atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
 
-	time_diff_us = ktime_us_delta(ktime_get(), cmd_enc->rd_ptr_timestamp);
-
-	/* handle retire fence based on only master */
-	if (dpu_encoder_phys_cmd_is_master(phys_enc)
-			&& atomic_read(&phys_enc->pending_retire_fence_cnt)) {
-		/**
-		 * Handle rare cases where the ctl_start_irq is received
-		 * after rd_ptr_irq. If it falls within a threshold, it is
-		 * guaranteed the frame would be picked up in the current TE.
-		 * Signal retire fence immediately in such case.
-		 */
-		if ((time_diff_us <= DPU_ENC_CTL_START_THRESHOLD_US)
-			    && atomic_add_unless(
-				&phys_enc->pending_retire_fence_cnt, -1, 0)) {
-
-			event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
-
-			if (phys_enc->parent_ops.handle_frame_done)
-				phys_enc->parent_ops.handle_frame_done(
-					phys_enc->parent, phys_enc, event);
-
-		/**
-		 * In ideal cases, ctl_start_irq is received before the
-		 * rd_ptr_irq, so set the atomic flag to indicate the event
-		 * and rd_ptr_irq will handle signalling the retire fence
-		 */
-		} else {
-			atomic_inc(&cmd_enc->pending_rd_ptr_cnt);
-		}
-	}
-
-	DPU_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0,
-				time_diff_us, event, 0xfff);
-
 	/* Signal any waiting ctl start interrupt */
 	wake_up_all(&phys_enc->pending_kickoff_wq);
 	DPU_ATRACE_END("ctl_start_irq");
@@ -409,8 +343,7 @@ static int _dpu_encoder_phys_cmd_handle_ppdone_timeout(
 {
 	struct dpu_encoder_phys_cmd *cmd_enc =
 			to_dpu_encoder_phys_cmd(phys_enc);
-	u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR
-				| DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
+	u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR;
 	bool do_log = false;
 
 	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_ctl)
@@ -1346,8 +1279,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
 	atomic_set(&phys_enc->vblank_refcount, 0);
 	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
 	atomic_set(&phys_enc->pending_ctlstart_cnt, 0);
-	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
-	atomic_set(&cmd_enc->pending_rd_ptr_cnt, 0);
 	atomic_set(&cmd_enc->pending_vblank_cnt, 0);
 	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
 	init_waitqueue_head(&cmd_enc->pending_vblank_wq);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 62c6f5c3547a..edaad0413987 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -373,13 +373,10 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
 static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
 {
 	struct dpu_encoder_phys *phys_enc = arg;
-	struct dpu_encoder_phys_vid *vid_enc =
-			to_dpu_encoder_phys_vid(phys_enc);
 	struct dpu_hw_ctl *hw_ctl;
 	unsigned long lock_flags;
 	u32 flush_register = 0;
 	int new_cnt = -1, old_cnt = -1;
-	u32 event = 0;
 
 	if (!phys_enc)
 		return;
@@ -390,18 +387,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
 
 	DPU_ATRACE_BEGIN("vblank_irq");
 
-	/* signal only for master, where there is a pending kickoff */
-	if (dpu_encoder_phys_vid_is_master(phys_enc)
-			&& atomic_add_unless(
-				&phys_enc->pending_retire_fence_cnt, -1, 0)) {
-		event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
-				| DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
-
-		if (phys_enc->parent_ops.handle_frame_done)
-			phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
-				phys_enc, event);
-	}
-
 	if (phys_enc->parent_ops.handle_vblank_virt)
 		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
 				phys_enc);
@@ -422,9 +407,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
 				-1, 0);
 	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
 
-	DPU_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx - INTF_0,
-			old_cnt, new_cnt, flush_register, event);
-
 	/* Signal any waiting atomic commit thread */
 	wake_up_all(&phys_enc->pending_kickoff_wq);
 	DPU_ATRACE_END("vblank_irq");
@@ -1028,7 +1010,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
 
 	atomic_set(&phys_enc->vblank_refcount, 0);
 	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
-	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
 	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
 	phys_enc->enable_state = DPU_ENC_DISABLED;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 9a6fa3e1e8b4..2bc5894839c4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -680,11 +680,8 @@ static void dpu_encoder_phys_wb_done_irq(void *arg, int irq_idx)
 	if (phys_enc->enable_state == DPU_ENC_DISABLING)
 		goto complete;
 
-	event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
-			| DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE
-			| DPU_ENCODER_FRAME_EVENT_DONE;
+	event = DPU_ENCODER_FRAME_EVENT_DONE;
 
-	atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0);
 	if (phys_enc->parent_ops.handle_frame_done)
 		phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
 				phys_enc, event);
@@ -847,12 +844,8 @@ static int dpu_encoder_phys_wb_wait_for_commit_done(
 		} else {
 			DPU_ERROR("wb:%d kickoff timed out\n",
 					wb_enc->wb_dev->wb_idx - WB_0);
-			atomic_add_unless(
-				&phys_enc->pending_retire_fence_cnt, -1, 0);
 
-			event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
-				| DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE
-				| DPU_ENCODER_FRAME_EVENT_ERROR;
+			event = DPU_ENCODER_FRAME_EVENT_ERROR;
 			if (phys_enc->parent_ops.handle_frame_done)
 				phys_enc->parent_ops.handle_frame_done(
 					phys_enc->parent, phys_enc, event);
@@ -1333,7 +1326,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_wb_init(
 	phys_enc->intf_mode = INTF_MODE_WB_LINE;
 	phys_enc->intf_idx = p->intf_idx;
 	phys_enc->enc_spinlock = p->enc_spinlock;
-	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
 	INIT_LIST_HEAD(&wb_enc->irq_cb.list);
 
 	/* create internal buffer for disable logic */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 3d83037e8305..9d68030378a7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -545,35 +545,6 @@ static void dpu_kms_wait_for_commit_done(struct msm_kms *kms,
 	}
 }
 
-static void dpu_kms_prepare_fence(struct msm_kms *kms,
-		struct drm_atomic_state *old_state)
-{
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *old_crtc_state;
-	int i, rc;
-
-	if (!kms || !old_state || !old_state->dev || !old_state->acquire_ctx) {
-		DPU_ERROR("invalid argument(s)\n");
-		return;
-	}
-
-retry:
-	/* attempt to acquire ww mutex for connection */
-	rc = drm_modeset_lock(&old_state->dev->mode_config.connection_mutex,
-			       old_state->acquire_ctx);
-
-	if (rc == -EDEADLK) {
-		drm_modeset_backoff(old_state->acquire_ctx);
-		goto retry;
-	}
-
-	/* old_state actually contains updated crtc pointers */
-	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
-		if (crtc->state->active)
-			dpu_crtc_prepare_commit(crtc, old_crtc_state);
-	}
-}
-
 /**
  * _dpu_kms_get_displays - query for underlying display handles and cache them
  * @dpu_kms:    Pointer to dpu kms structure
@@ -1734,7 +1705,6 @@ static const struct msm_kms_funcs kms_funcs = {
 	.irq_uninstall   = dpu_irq_uninstall,
 	.irq             = dpu_irq,
 	.preclose        = dpu_kms_preclose,
-	.prepare_fence   = dpu_kms_prepare_fence,
 	.prepare_commit  = dpu_kms_prepare_commit,
 	.commit          = dpu_kms_commit,
 	.complete_commit = dpu_kms_complete_commit,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 8cab333df717..e92376acbcfe 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -132,8 +132,6 @@ enum msm_mdp_crtc_property {
 
 	/* range properties */
 	CRTC_PROP_INPUT_FENCE_TIMEOUT = CRTC_PROP_BLOBCOUNT,
-	CRTC_PROP_OUTPUT_FENCE,
-	CRTC_PROP_OUTPUT_FENCE_OFFSET,
 	CRTC_PROP_DIM_LAYER_V1,
 	CRTC_PROP_CORE_CLK,
 	CRTC_PROP_CORE_AB,
@@ -163,7 +161,6 @@ enum msm_mdp_conn_property {
 
 	/* range properties */
 	CONNECTOR_PROP_OUT_FB = CONNECTOR_PROP_BLOBCOUNT,
-	CONNECTOR_PROP_RETIRE_FENCE,
 	CONNECTOR_PROP_DST_X,
 	CONNECTOR_PROP_DST_Y,
 	CONNECTOR_PROP_DST_W,
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 09/11] drm/msm: Remove prepare_fence kms_function
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                     ` (7 preceding siblings ...)
  2018-02-28 19:19   ` [DPU PATCH 08/11] drm/msm: Remove hand-rolled out fences Sean Paul
@ 2018-02-28 19:19   ` Sean Paul
       [not found]     ` <20180228191906.185417-10-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:19   ` [DPU PATCH 10/11] drm/msm: Switch to atomic_helper_commit() Sean Paul
  2018-02-28 19:19   ` [DPU PATCH 11/11] drm/msm: Remove dpu input fences Sean Paul
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:19 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

This is the last piece that is keeping us from matching the atomic
helper commit function. By removing this (now unused) hook, we can
switch to drm_atomic_helper_commit()

Change-Id: I081056a6e1689807871f5deedc76499bb91b6969
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/msm_atomic.c | 10 ----------
 drivers/gpu/drm/msm/msm_kms.h    |  2 --
 2 files changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 1f53262ea46b..204c66cbfd31 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -169,16 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
 	 */
 	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
 
-	/*
-	 * Provide the driver a chance to prepare for output fences. This is
-	 * done after the point of no return, but before asynchronous commits
-	 * are dispatched to work queues, so that the fence preparation is
-	 * finished before the .atomic_commit returns.
-	 */
-	if (priv && priv->kms && priv->kms->funcs &&
-			priv->kms->funcs->prepare_fence)
-		priv->kms->funcs->prepare_fence(priv->kms, state);
-
 	/*
 	 * Everything below can be run asynchronously without the need to grab
 	 * any modeset locks at all under one conditions: It must be guaranteed
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 4c5a69258c42..25800c046bd1 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -60,8 +60,6 @@ struct msm_kms_funcs {
 	void *(*duplicate_state)(void *state);
 	void (*destroy_state)(void *state);
 	/* modeset, bracketing atomic_commit(): */
-	void (*prepare_fence)(struct msm_kms *kms,
-			struct drm_atomic_state *state);
 	void (*prepare_commit)(struct msm_kms *kms,
 			struct drm_atomic_state *state);
 	void (*commit)(struct msm_kms *kms, struct drm_atomic_state *state);
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 10/11] drm/msm: Switch to atomic_helper_commit()
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                     ` (8 preceding siblings ...)
  2018-02-28 19:19   ` [DPU PATCH 09/11] drm/msm: Remove prepare_fence kms_function Sean Paul
@ 2018-02-28 19:19   ` Sean Paul
       [not found]     ` <20180228191906.185417-11-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  2018-02-28 19:19   ` [DPU PATCH 11/11] drm/msm: Remove dpu input fences Sean Paul
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:19 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Now that all of the msm-specific goo is tucked safely away we can switch
over to using the atomic helper commit directly. \o/

Change-Id: Ieab0bd0c526b2a9d3b3345eeba402ac4857fe418
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/msm_atomic.c | 120 +------------------------------
 drivers/gpu/drm/msm/msm_drv.c    |   7 +-
 drivers/gpu/drm/msm/msm_drv.h    |   3 +-
 3 files changed, 8 insertions(+), 122 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 204c66cbfd31..91ffded576d8 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -18,8 +18,6 @@
 
 #include "msm_drv.h"
 #include "msm_kms.h"
-#include "msm_gem.h"
-#include "msm_fence.h"
 
 static void msm_atomic_wait_for_commit_done(
 		struct drm_device *dev,
@@ -39,7 +37,7 @@ static void msm_atomic_wait_for_commit_done(
 	}
 }
 
-static void msm_atomic_commit_tail(struct drm_atomic_state *state)
+void msm_atomic_commit_tail(struct drm_atomic_state *state)
 {
 	struct drm_device *dev = state->dev;
 	struct msm_drm_private *priv = dev->dev_private;
@@ -81,119 +79,3 @@ static void msm_atomic_commit_tail(struct drm_atomic_state *state)
 
 	kms->funcs->complete_commit(kms, state);
 }
-
-/* The (potentially) asynchronous part of the commit.  At this point
- * nothing can fail short of armageddon.
- */
-static void commit_tail(struct drm_atomic_state *state)
-{
-	drm_atomic_helper_wait_for_fences(state->dev, state, false);
-
-	drm_atomic_helper_wait_for_dependencies(state);
-
-	msm_atomic_commit_tail(state);
-
-	drm_atomic_helper_commit_cleanup_done(state);
-
-	drm_atomic_state_put(state);
-}
-
-static void commit_work(struct work_struct *work)
-{
-	struct drm_atomic_state *state = container_of(work,
-						      struct drm_atomic_state,
-						      commit_work);
-	commit_tail(state);
-}
-
-/**
- * drm_atomic_helper_commit - commit validated state object
- * @dev: DRM device
- * @state: the driver state object
- * @nonblock: nonblocking commit
- *
- * This function commits a with drm_atomic_helper_check() pre-validated state
- * object. This can still fail when e.g. the framebuffer reservation fails.
- *
- * RETURNS
- * Zero for success or -errno.
- */
-int msm_atomic_commit(struct drm_device *dev,
-		struct drm_atomic_state *state, bool nonblock)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-	struct drm_plane *plane;
-	struct drm_plane_state *old_plane_state, *new_plane_state;
-	int i, ret;
-
-	/*
-	 * Note that plane->atomic_async_check() should fail if we need
-	 * to re-assign hwpipe or anything that touches global atomic
-	 * state, so we'll never go down the async update path in those
-	 * cases.
-	 */
-	if (state->async_update) {
-		ret = drm_atomic_helper_prepare_planes(dev, state);
-		if (ret)
-			return ret;
-
-		drm_atomic_helper_async_commit(dev, state);
-		drm_atomic_helper_cleanup_planes(dev, state);
-		return 0;
-	}
-
-	ret = drm_atomic_helper_setup_commit(state, nonblock);
-	if (ret)
-		return ret;
-
-	INIT_WORK(&state->commit_work, commit_work);
-
-	ret = drm_atomic_helper_prepare_planes(dev, state);
-	if (ret)
-		return ret;
-
-	if (!nonblock) {
-		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
-		if (ret)
-			goto error;
-	}
-
-	/*
-	 * This is the point of no return - everything below never fails except
-	 * when the hw goes bonghits. Which means we can commit the new state on
-	 * the software side now.
-	 *
-	 * swap driver private state while still holding state_lock
-	 */
-	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
-
-	/*
-	 * Everything below can be run asynchronously without the need to grab
-	 * any modeset locks at all under one conditions: It must be guaranteed
-	 * that the asynchronous work has either been cancelled (if the driver
-	 * supports it, which at least requires that the framebuffers get
-	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
-	 * before the new state gets committed on the software side with
-	 * drm_atomic_helper_swap_state().
-	 *
-	 * This scheme allows new atomic state updates to be prepared and
-	 * checked in parallel to the asynchronous completion of the previous
-	 * update. Which is important since compositors need to figure out the
-	 * composition of the next frame right after having submitted the
-	 * current layout.
-	 */
-
-	drm_atomic_state_get(state);
-	if (nonblock)
-		queue_work(system_unbound_wq, &state->commit_work);
-	else
-		commit_tail(state);
-
-	return 0;
-
-error:
-	drm_atomic_helper_cleanup_planes(dev, state);
-	return ret;
-}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index e582d5889b66..fd9a7d0825cd 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -120,7 +120,11 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
 	.fb_create = msm_framebuffer_create,
 	.output_poll_changed = msm_fb_output_poll_changed,
 	.atomic_check = msm_atomic_check,
-	.atomic_commit = msm_atomic_commit,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = {
+	.atomic_commit_tail = msm_atomic_commit_tail,
 };
 
 static inline
@@ -694,6 +698,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
 	 * an unset value during call to drm_drv_uses_atomic_modeset()
 	 */
 	ddev->mode_config.funcs = &mode_config_funcs;
+	ddev->mode_config.helper_private = &mode_config_helper_funcs;
 
 	if (kms) {
 		ret = kms->funcs->hw_init(kms);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index e92376acbcfe..657ea052a1ee 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -593,8 +593,7 @@ struct msm_format {
 	uint32_t pixel_format;
 };
 
-int msm_atomic_commit(struct drm_device *dev,
-		struct drm_atomic_state *state, bool nonblock);
+void msm_atomic_commit_tail(struct drm_atomic_state *state);
 struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *state);
 
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [DPU PATCH 11/11] drm/msm: Remove dpu input fences
       [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                     ` (9 preceding siblings ...)
  2018-02-28 19:19   ` [DPU PATCH 10/11] drm/msm: Switch to atomic_helper_commit() Sean Paul
@ 2018-02-28 19:19   ` Sean Paul
       [not found]     ` <20180228191906.185417-12-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  10 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-02-28 19:19 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

These are already provided by drm atomic core.

In conjunction with the output fences removed earlier, this obsoletes
dpu_fence, and it can be entirely removed as well.

Change-Id: Ida4924a09c455d7a84bfee569bd0d2fb436418de
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/Makefile              |   1 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  84 -----
 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c | 404 ----------------------
 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h | 190 ----------
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 104 ------
 drivers/gpu/drm/msm/msm_drv.h             |   4 +-
 6 files changed, 1 insertion(+), 786 deletions(-)
 delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c
 delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 2fb9ba11df19..b47ef5267e19 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -55,7 +55,6 @@ msm-y := \
 	disp/dpu1/dpu_encoder.o \
 	disp/dpu1/dpu_encoder_phys_cmd.o \
 	disp/dpu1/dpu_encoder_phys_vid.o \
-	disp/dpu1/dpu_fence.o \
 	disp/dpu1/dpu_formats.o \
 	disp/dpu1/dpu_hw_ad4.o \
 	disp/dpu1/dpu_hw_blk.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 2d44989ade7a..8dd986e476bd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -64,16 +64,6 @@ static struct dpu_crtc_custom_events custom_events[] = {
 	{DRM_EVENT_IDLE_NOTIFY, dpu_crtc_idle_interrupt_handler}
 };
 
-/* default input fence timeout, in ms */
-#define DPU_CRTC_INPUT_FENCE_TIMEOUT    10000
-
-/*
- * The default input fence timeout is 2 seconds while max allowed
- * range is 10 seconds. Any value above 10 seconds adds glitches beyond
- * tolerance limit.
- */
-#define DPU_CRTC_MAX_INPUT_FENCE_TIMEOUT 10000
-
 /* layer mixer index on dpu_crtc */
 #define LEFT_MIXER 0
 #define RIGHT_MIXER 1
@@ -1946,21 +1936,6 @@ static void _dpu_crtc_set_idle_timeout(struct drm_crtc *crtc, u64 val)
 	}
 }
 
-/**
- * _dpu_crtc_set_input_fence_timeout - update ns version of in fence timeout
- * @cstate: Pointer to dpu crtc state
- */
-static void _dpu_crtc_set_input_fence_timeout(struct dpu_crtc_state *cstate)
-{
-	if (!cstate) {
-		DPU_ERROR("invalid cstate\n");
-		return;
-	}
-	cstate->input_fence_timeout_ns =
-		dpu_crtc_get_property(cstate, CRTC_PROP_INPUT_FENCE_TIMEOUT);
-	cstate->input_fence_timeout_ns *= NSEC_PER_MSEC;
-}
-
 /**
  * _dpu_crtc_set_dim_layer_v1 - copy dim layer settings from userspace
  * @cstate:      Pointer to dpu crtc state
@@ -2385,53 +2360,6 @@ static int _dpu_crtc_check_dest_scaler_data(struct drm_crtc *crtc,
 	return ret;
 }
 
-/**
- * _dpu_crtc_wait_for_fences - wait for incoming framebuffer sync fences
- * @crtc: Pointer to CRTC object
- */
-static void _dpu_crtc_wait_for_fences(struct drm_crtc *crtc)
-{
-	struct drm_plane *plane = NULL;
-	uint32_t wait_ms = 1;
-	ktime_t kt_end, kt_wait;
-	int rc = 0;
-
-	DPU_DEBUG("\n");
-
-	if (!crtc || !crtc->state) {
-		DPU_ERROR("invalid crtc/state %pK\n", crtc);
-		return;
-	}
-
-	/* use monotonic timer to limit total fence wait time */
-	kt_end = ktime_add_ns(ktime_get(),
-		to_dpu_crtc_state(crtc->state)->input_fence_timeout_ns);
-
-	/*
-	 * Wait for fences sequentially, as all of them need to be signalled
-	 * before we can proceed.
-	 *
-	 * Limit total wait time to INPUT_FENCE_TIMEOUT, but still call
-	 * dpu_plane_wait_input_fence with wait_ms == 0 after the timeout so
-	 * that each plane can check its fence status and react appropriately
-	 * if its fence has timed out. Call input fence wait multiple times if
-	 * fence wait is interrupted due to interrupt call.
-	 */
-	DPU_ATRACE_BEGIN("plane_wait_input_fence");
-	drm_atomic_crtc_for_each_plane(plane, crtc) {
-		do {
-			kt_wait = ktime_sub(kt_end, ktime_get());
-			if (ktime_compare(kt_wait, ktime_set(0, 0)) >= 0)
-				wait_ms = ktime_to_ms(kt_wait);
-			else
-				wait_ms = 0;
-
-			rc = dpu_plane_wait_input_fence(plane, wait_ms);
-		} while (wait_ms && rc == -ERESTARTSYS);
-	}
-	DPU_ATRACE_END("plane_wait_input_fence");
-}
-
 static void _dpu_crtc_setup_mixer_for_encoder(
 		struct drm_crtc *crtc,
 		struct drm_encoder *enc)
@@ -2716,9 +2644,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
 	drm_atomic_crtc_for_each_plane(plane, crtc)
 		dpu_plane_restore(plane);
 
-	/* wait for acquire fences before anything else is done */
-	_dpu_crtc_wait_for_fences(crtc);
-
 	if (!cstate->rsc_update) {
 		drm_for_each_encoder(encoder, dev) {
 			if (encoder->crtc != crtc)
@@ -3178,8 +3103,6 @@ static void dpu_crtc_reset(struct drm_crtc *crtc)
 			&cstate->property_state,
 			cstate->property_values);
 
-	_dpu_crtc_set_input_fence_timeout(cstate);
-
 	_dpu_crtc_rp_reset(&cstate->rp, &dpu_crtc->rp_lock,
 			&dpu_crtc->rp_head);
 
@@ -3929,10 +3852,6 @@ static void dpu_crtc_install_properties(struct drm_crtc *crtc,
 	}
 
 	/* range properties */
-	msm_property_install_range(&dpu_crtc->property_info,
-		"input_fence_timeout", 0x0, 0, DPU_CRTC_MAX_INPUT_FENCE_TIMEOUT,
-		DPU_CRTC_INPUT_FENCE_TIMEOUT, CRTC_PROP_INPUT_FENCE_TIMEOUT);
-
 	msm_property_install_range(&dpu_crtc->property_info,
 			"core_clk", 0x0, 0, U64_MAX,
 			dpu_kms->perf.max_core_clk_rate,
@@ -4121,9 +4040,6 @@ static int dpu_crtc_atomic_set_property(struct drm_crtc *crtc,
 			idx = msm_property_index(&dpu_crtc->property_info,
 					property);
 			switch (idx) {
-			case CRTC_PROP_INPUT_FENCE_TIMEOUT:
-				_dpu_crtc_set_input_fence_timeout(cstate);
-				break;
 			case CRTC_PROP_DIM_LAYER_V1:
 				_dpu_crtc_set_dim_layer_v1(cstate,
 							(void __user *)val);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c
deleted file mode 100644
index 49ffd7138eba..000000000000
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/sync_file.h>
-#include <linux/dma-fence.h>
-#include "msm_drv.h"
-#include "dpu_kms.h"
-#include "dpu_fence.h"
-
-#define TIMELINE_VAL_LENGTH		128
-
-void *dpu_sync_get(uint64_t fd)
-{
-	/* force signed compare, fdget accepts an int argument */
-	return (signed int)fd >= 0 ? sync_file_get_fence(fd) : NULL;
-}
-
-void dpu_sync_put(void *fence)
-{
-	if (fence)
-		dma_fence_put(fence);
-}
-
-signed long dpu_sync_wait(void *fnc, long timeout_ms)
-{
-	struct dma_fence *fence = fnc;
-	int rc;
-	char timeline_str[TIMELINE_VAL_LENGTH];
-
-	if (!fence)
-		return -EINVAL;
-	else if (dma_fence_is_signaled(fence))
-		return timeout_ms ? msecs_to_jiffies(timeout_ms) : 1;
-
-	rc = dma_fence_wait_timeout(fence, true,
-				msecs_to_jiffies(timeout_ms));
-	if (!rc || (rc == -EINVAL)) {
-		if (fence->ops->timeline_value_str)
-			fence->ops->timeline_value_str(fence,
-					timeline_str, TIMELINE_VAL_LENGTH);
-
-		DPU_ERROR(
-			"fence driver name:%s timeline name:%s seqno:0x%x timeline:%s signaled:0x%x\n",
-			fence->ops->get_driver_name(fence),
-			fence->ops->get_timeline_name(fence),
-			fence->seqno, timeline_str,
-			fence->ops->signaled ?
-				fence->ops->signaled(fence) : 0xffffffff);
-	}
-
-	return rc;
-}
-
-uint32_t dpu_sync_get_name_prefix(void *fence)
-{
-	const char *name;
-	uint32_t i, prefix;
-	struct dma_fence *f = fence;
-
-	if (!fence)
-		return 0;
-
-	name = f->ops->get_driver_name(f);
-	if (!name)
-		return 0;
-
-	prefix = 0x0;
-	for (i = 0; i < sizeof(uint32_t) && name[i]; ++i)
-		prefix = (prefix << CHAR_BIT) | name[i];
-
-	return prefix;
-}
-
-/**
- * struct dpu_fence - release/retire fence structure
- * @fence: base fence structure
- * @name: name of each fence- it is fence timeline + commit_count
- * @fence_list: list to associated this fence on timeline/context
- * @fd: fd attached to this fence - debugging purpose.
- */
-struct dpu_fence {
-	struct dma_fence base;
-	struct dpu_fence_context *ctx;
-	char name[DPU_FENCE_NAME_SIZE];
-	struct list_head	fence_list;
-	int fd;
-};
-
-static void dpu_fence_destroy(struct kref *kref)
-{
-}
-
-static inline struct dpu_fence *to_dpu_fence(struct dma_fence *fence)
-{
-	return container_of(fence, struct dpu_fence, base);
-}
-
-static const char *dpu_fence_get_driver_name(struct dma_fence *fence)
-{
-	struct dpu_fence *f = to_dpu_fence(fence);
-
-	return f->name;
-}
-
-static const char *dpu_fence_get_timeline_name(struct dma_fence *fence)
-{
-	struct dpu_fence *f = to_dpu_fence(fence);
-
-	return f->ctx->name;
-}
-
-static bool dpu_fence_enable_signaling(struct dma_fence *fence)
-{
-	return true;
-}
-
-static bool dpu_fence_signaled(struct dma_fence *fence)
-{
-	struct dpu_fence *f = to_dpu_fence(fence);
-	bool status;
-
-	status = (int)(fence->seqno - f->ctx->done_count) <= 0 ? true : false;
-	DPU_DEBUG("status:%d fence seq:%d and timeline:%d\n",
-			status, fence->seqno, f->ctx->done_count);
-	return status;
-}
-
-static void dpu_fence_release(struct dma_fence *fence)
-{
-	struct dpu_fence *f;
-
-	if (fence) {
-		f = to_dpu_fence(fence);
-		kfree(f);
-	}
-}
-
-static void dpu_fence_value_str(struct dma_fence *fence, char *str, int size)
-{
-	if (!fence || !str)
-		return;
-
-	snprintf(str, size, "%d", fence->seqno);
-}
-
-static void dpu_fence_timeline_value_str(struct dma_fence *fence, char *str,
-		int size)
-{
-	struct dpu_fence *f = to_dpu_fence(fence);
-
-	if (!fence || !f->ctx || !str)
-		return;
-
-	snprintf(str, size, "%d", f->ctx->done_count);
-}
-
-static struct dma_fence_ops dpu_fence_ops = {
-	.get_driver_name = dpu_fence_get_driver_name,
-	.get_timeline_name = dpu_fence_get_timeline_name,
-	.enable_signaling = dpu_fence_enable_signaling,
-	.signaled = dpu_fence_signaled,
-	.wait = dma_fence_default_wait,
-	.release = dpu_fence_release,
-	.fence_value_str = dpu_fence_value_str,
-	.timeline_value_str = dpu_fence_timeline_value_str,
-};
-
-/**
- * _dpu_fence_create_fd - create fence object and return an fd for it
- * This function is NOT thread-safe.
- * @timeline: Timeline to associate with fence
- * @val: Timeline value at which to signal the fence
- * Return: File descriptor on success, or error code on error
- */
-static int _dpu_fence_create_fd(void *fence_ctx, uint32_t val)
-{
-	struct dpu_fence *dpu_fence;
-	struct sync_file *sync_file;
-	signed int fd = -EINVAL;
-	struct dpu_fence_context *ctx = fence_ctx;
-
-	if (!ctx) {
-		DPU_ERROR("invalid context\n");
-		goto exit;
-	}
-
-	dpu_fence = kzalloc(sizeof(*dpu_fence), GFP_KERNEL);
-	if (!dpu_fence)
-		return -ENOMEM;
-
-	dpu_fence->ctx = fence_ctx;
-	snprintf(dpu_fence->name, DPU_FENCE_NAME_SIZE, "dpu_fence:%s:%u",
-						dpu_fence->ctx->name, val);
-	dma_fence_init(&dpu_fence->base, &dpu_fence_ops, &ctx->lock,
-		ctx->context, val);
-
-	/* create fd */
-	fd = get_unused_fd_flags(0);
-	if (fd < 0) {
-		dma_fence_put(&dpu_fence->base);
-		DPU_ERROR("failed to get_unused_fd_flags(), %s\n",
-							dpu_fence->name);
-		goto exit;
-	}
-
-	/* create fence */
-	sync_file = sync_file_create(&dpu_fence->base);
-	if (sync_file == NULL) {
-		put_unused_fd(fd);
-		fd = -EINVAL;
-		dma_fence_put(&dpu_fence->base);
-		DPU_ERROR("couldn't create fence, %s\n", dpu_fence->name);
-		goto exit;
-	}
-
-	fd_install(fd, sync_file->file);
-	dpu_fence->fd = fd;
-	kref_get(&ctx->kref);
-
-	spin_lock(&ctx->list_lock);
-	list_add_tail(&dpu_fence->fence_list, &ctx->fence_list_head);
-	spin_unlock(&ctx->list_lock);
-
-exit:
-	return fd;
-}
-
-int dpu_fence_init(struct dpu_fence_context *ctx,
-		const char *name, uint32_t drm_id)
-{
-	if (!ctx || !name) {
-		DPU_ERROR("invalid argument(s)\n");
-		return -EINVAL;
-	}
-	memset(ctx, 0, sizeof(*ctx));
-
-	strlcpy(ctx->name, name, ARRAY_SIZE(ctx->name));
-	ctx->drm_id = drm_id;
-	kref_init(&ctx->kref);
-	ctx->context = dma_fence_context_alloc(1);
-
-	spin_lock_init(&ctx->lock);
-	spin_lock_init(&ctx->list_lock);
-	INIT_LIST_HEAD(&ctx->fence_list_head);
-
-	return 0;
-}
-
-void dpu_fence_deinit(struct dpu_fence_context *ctx)
-{
-	if (!ctx) {
-		DPU_ERROR("invalid fence\n");
-		return;
-	}
-
-	kref_put(&ctx->kref, dpu_fence_destroy);
-}
-
-void dpu_fence_prepare(struct dpu_fence_context *ctx)
-{
-	unsigned long flags;
-
-	if (!ctx) {
-		DPU_ERROR("invalid argument(s), fence %pK\n", ctx);
-	} else {
-		spin_lock_irqsave(&ctx->lock, flags);
-		++ctx->commit_count;
-		spin_unlock_irqrestore(&ctx->lock, flags);
-	}
-}
-
-static void _dpu_fence_trigger(struct dpu_fence_context *ctx, ktime_t ts)
-{
-	unsigned long flags;
-	struct dpu_fence *fc, *next;
-	bool is_signaled = false;
-	struct list_head local_list_head;
-
-	INIT_LIST_HEAD(&local_list_head);
-
-	spin_lock(&ctx->list_lock);
-	if (list_empty(&ctx->fence_list_head)) {
-		DPU_DEBUG("nothing to trigger!\n");
-		spin_unlock(&ctx->list_lock);
-		return;
-	}
-
-	list_for_each_entry_safe(fc, next, &ctx->fence_list_head, fence_list)
-		list_move(&fc->fence_list, &local_list_head);
-	spin_unlock(&ctx->list_lock);
-
-	list_for_each_entry_safe(fc, next, &local_list_head, fence_list) {
-		spin_lock_irqsave(&ctx->lock, flags);
-		fc->base.timestamp = ts;
-		is_signaled = dma_fence_is_signaled_locked(&fc->base);
-		spin_unlock_irqrestore(&ctx->lock, flags);
-
-		if (is_signaled) {
-			list_del_init(&fc->fence_list);
-			dma_fence_put(&fc->base);
-			kref_put(&ctx->kref, dpu_fence_destroy);
-		} else {
-			spin_lock(&ctx->list_lock);
-			list_move(&fc->fence_list, &ctx->fence_list_head);
-			spin_unlock(&ctx->list_lock);
-		}
-	}
-}
-
-int dpu_fence_create(struct dpu_fence_context *ctx, uint64_t *val,
-							uint32_t offset)
-{
-	uint32_t trigger_value;
-	int fd, rc = -EINVAL;
-	unsigned long flags;
-
-	if (!ctx || !val) {
-		DPU_ERROR("invalid argument(s), fence %d, pval %d\n",
-				ctx != NULL, val != NULL);
-		return rc;
-	}
-
-	/*
-	 * Allow created fences to have a constant offset with respect
-	 * to the timeline. This allows us to delay the fence signalling
-	 * w.r.t. the commit completion (e.g., an offset of +1 would
-	 * cause fences returned during a particular commit to signal
-	 * after an additional delay of one commit, rather than at the
-	 * end of the current one.
-	 */
-	spin_lock_irqsave(&ctx->lock, flags);
-	trigger_value = ctx->commit_count + offset;
-
-	spin_unlock_irqrestore(&ctx->lock, flags);
-
-	fd = _dpu_fence_create_fd(ctx, trigger_value);
-	*val = fd;
-	DPU_DEBUG("fence_create::fd:%d trigger:%d commit:%d offset:%d\n",
-				fd, trigger_value, ctx->commit_count, offset);
-
-	DPU_EVT32(ctx->drm_id, trigger_value, fd);
-
-	if (fd >= 0) {
-		rc = 0;
-		_dpu_fence_trigger(ctx, ktime_get());
-	} else {
-		rc = fd;
-	}
-
-	return rc;
-}
-
-void dpu_fence_signal(struct dpu_fence_context *ctx, ktime_t ts,
-							bool reset_timeline)
-{
-	unsigned long flags;
-
-	if (!ctx) {
-		DPU_ERROR("invalid ctx, %pK\n", ctx);
-		return;
-	}
-
-	spin_lock_irqsave(&ctx->lock, flags);
-	if (reset_timeline) {
-		if ((int)(ctx->done_count - ctx->commit_count) < 0) {
-			DPU_ERROR(
-				"timeline reset attempt! done count:%d commit:%d\n",
-				ctx->done_count, ctx->commit_count);
-			ctx->done_count = ctx->commit_count;
-			DPU_EVT32(ctx->drm_id, ctx->done_count,
-				ctx->commit_count, ktime_to_us(ts),
-				reset_timeline, DPU_EVTLOG_FATAL);
-		} else {
-			spin_unlock_irqrestore(&ctx->lock, flags);
-			return;
-		}
-	} else if ((int)(ctx->done_count - ctx->commit_count) < 0) {
-		++ctx->done_count;
-		DPU_DEBUG("fence_signal:done count:%d commit count:%d\n",
-					ctx->done_count, ctx->commit_count);
-	} else {
-		DPU_ERROR("extra signal attempt! done count:%d commit:%d\n",
-					ctx->done_count, ctx->commit_count);
-		DPU_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count,
-			ktime_to_us(ts), reset_timeline, DPU_EVTLOG_FATAL);
-		spin_unlock_irqrestore(&ctx->lock, flags);
-		return;
-	}
-	spin_unlock_irqrestore(&ctx->lock, flags);
-
-	DPU_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count,
-			ktime_to_us(ts));
-
-	_dpu_fence_trigger(ctx, ts);
-}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h
deleted file mode 100644
index f943046d96b8..000000000000
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _DPU_FENCE_H_
-#define _DPU_FENCE_H_
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-
-#ifndef CHAR_BIT
-#define CHAR_BIT 8 /* define this if limits.h not available */
-#endif
-
-#define DPU_FENCE_NAME_SIZE	24
-
-/**
- * struct dpu_fence_context - release/retire fence context/timeline structure
- * @commit_count: Number of detected commits since bootup
- * @done_count: Number of completed commits since bootup
- * @drm_id: ID number of owning DRM Object
- * @ref: kref counter on timeline
- * @lock: spinlock for fence counter protection
- * @list_lock: spinlock for timeline protection
- * @context: fence context
- * @list_head: fence list to hold all the fence created on this context
- * @name: name of fence context/timeline
- */
-struct dpu_fence_context {
-	unsigned int commit_count;
-	unsigned int done_count;
-	uint32_t drm_id;
-	struct kref kref;
-	spinlock_t lock;
-	spinlock_t list_lock;
-	u64 context;
-	struct list_head fence_list_head;
-	char name[DPU_FENCE_NAME_SIZE];
-};
-
-#if IS_ENABLED(CONFIG_SYNC_FILE)
-/**
- * dpu_sync_get - Query sync fence object from a file handle
- *
- * On success, this function also increments the refcount of the sync fence
- *
- * @fd: Integer sync fence handle
- *
- * Return: Pointer to sync fence object, or NULL
- */
-void *dpu_sync_get(uint64_t fd);
-
-/**
- * dpu_sync_put - Releases a sync fence object acquired by @dpu_sync_get
- *
- * This function decrements the sync fence's reference count; the object will
- * be released if the reference count goes to zero.
- *
- * @fence: Pointer to sync fence
- */
-void dpu_sync_put(void *fence);
-
-/**
- * dpu_sync_wait - Query sync fence object from a file handle
- *
- * @fence: Pointer to sync fence
- * @timeout_ms: Time to wait, in milliseconds. Waits forever if timeout_ms < 0
- *
- * Return:
- * Zero if timed out
- * -ERESTARTSYS if wait interrupted
- * remaining jiffies in all other success cases.
- */
-signed long dpu_sync_wait(void *fence, long timeout_ms);
-
-/**
- * dpu_sync_get_name_prefix - get integer representation of fence name prefix
- * @fence: Pointer to opaque fence structure
- *
- * Return: 32-bit integer containing first 4 characters of fence name,
- *         big-endian notation
- */
-uint32_t dpu_sync_get_name_prefix(void *fence);
-
-/**
- * dpu_fence_init - initialize fence object
- * @fence: Pointer to crtc fence object
- * @drm_id: ID number of owning DRM Object
- * @name: Timeline name
- * Returns: Zero on success
- */
-int dpu_fence_init(struct dpu_fence_context *fence,
-		const char *name,
-		uint32_t drm_id);
-
-/**
- * dpu_fence_deinit - deinit fence container
- * @fence: Pointer fence container
- */
-void dpu_fence_deinit(struct dpu_fence_context *fence);
-
-/**
- * dpu_fence_prepare - prepare to return fences for current commit
- * @fence: Pointer fence container
- * Returns: Zero on success
- */
-void dpu_fence_prepare(struct dpu_fence_context *fence);
-/**
- * dpu_fence_create - create output fence object
- * @fence: Pointer fence container
- * @val: Pointer to output value variable, fence fd will be placed here
- * @offset: Fence signal commit offset, e.g., +1 to signal on next commit
- * Returns: Zero on success
- */
-int dpu_fence_create(struct dpu_fence_context *fence, uint64_t *val,
-							uint32_t offset);
-
-/**
- * dpu_fence_signal - advance fence timeline to signal outstanding fences
- * @fence: Pointer fence container
- * @ts: fence timestamp
- * @reset_timeline: reset the fence timeline to done count equal to commit count
- */
-void dpu_fence_signal(struct dpu_fence_context *fence, ktime_t ts,
-		bool reset_timeline);
-#else
-static inline void *dpu_sync_get(uint64_t fd)
-{
-	return NULL;
-}
-
-static inline void dpu_sync_put(void *fence)
-{
-}
-
-static inline signed long dpu_sync_wait(void *fence, long timeout_ms)
-{
-	return 0;
-}
-
-static inline uint32_t dpu_sync_get_name_prefix(void *fence)
-{
-	return 0x0;
-}
-static inline int dpu_fence_init(struct dpu_fence_context *fence,
-		const char *name,
-		uint32_t drm_id)
-{
-	/* do nothing */
-	return 0;
-}
-
-static inline void dpu_fence_deinit(struct dpu_fence_context *fence)
-{
-	/* do nothing */
-}
-
-static inline int dpu_fence_get(struct dpu_fence_context *fence, uint64_t *val)
-{
-	return -EINVAL;
-}
-
-static inline void dpu_fence_signal(struct dpu_fence_context *fence,
-						ktime_t ts, bool reset_timeline)
-{
-	/* do nothing */
-}
-
-static inline void dpu_fence_prepare(struct dpu_fence_context *fence)
-{
-	/* do nothing */
-}
-
-static inline int dpu_fence_create(struct dpu_fence_context *fence,
-						uint64_t *val, uint32_t offset)
-{
-	return 0;
-}
-#endif /* IS_ENABLED(CONFIG_SW_SYNC) */
-
-#endif /* _DPU_FENCE_H_ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 29e72b39fd72..610e616f2e74 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -27,7 +27,6 @@
 #include "msm_drv.h"
 
 #include "dpu_kms.h"
-#include "dpu_fence.h"
 #include "dpu_formats.h"
 #include "dpu_hw_sspp.h"
 #include "dpu_hw_catalog_format.h"
@@ -676,26 +675,6 @@ static void _dpu_plane_set_ts_prefill(struct drm_plane *plane,
 			pstate->multirect_index);
 }
 
-/* helper to update a state's input fence pointer from the property */
-static void _dpu_plane_set_input_fence(struct dpu_plane *pdpu,
-		struct dpu_plane_state *pstate, uint64_t fd)
-{
-	if (!pdpu || !pstate) {
-		DPU_ERROR("invalid arg(s), plane %d state %d\n",
-				pdpu != 0, pstate != 0);
-		return;
-	}
-
-	/* clear previous reference */
-	if (pstate->input_fence)
-		dpu_sync_put(pstate->input_fence);
-
-	/* get fence pointer for later */
-	pstate->input_fence = dpu_sync_get(fd);
-
-	DPU_DEBUG_PLANE(pdpu, "0x%llX\n", fd);
-}
-
 /**
  * _dpu_plane_inline_rot_set_ot_limit - set OT limit for the given inline
  * rotation xin client
@@ -780,64 +759,6 @@ static void _dpu_plane_inline_rot_set_qos_remap(struct drm_plane *plane,
 	dpu_vbif_set_qos_remap(dpu_kms, &qos_params);
 }
 
-int dpu_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms)
-{
-	struct dpu_plane *pdpu;
-	struct dpu_plane_state *pstate;
-	uint32_t prefix;
-	void *input_fence;
-	int ret = -EINVAL;
-	signed long rc;
-
-	if (!plane) {
-		DPU_ERROR("invalid plane\n");
-	} else if (!plane->state) {
-		DPU_ERROR_PLANE(to_dpu_plane(plane), "invalid state\n");
-	} else {
-		pdpu = to_dpu_plane(plane);
-		pstate = to_dpu_plane_state(plane->state);
-		input_fence = pstate->input_fence;
-
-		if (input_fence) {
-			pdpu->is_error = false;
-			prefix = dpu_sync_get_name_prefix(input_fence);
-			rc = dpu_sync_wait(input_fence, wait_ms);
-
-			switch (rc) {
-			case 0:
-				DPU_ERROR_PLANE(pdpu, "%ums timeout on %08X\n",
-						wait_ms, prefix);
-				pdpu->is_error = true;
-				ret = -ETIMEDOUT;
-				break;
-			case -ERESTARTSYS:
-				DPU_ERROR_PLANE(pdpu,
-					"%ums wait interrupted on %08X\n",
-					wait_ms, prefix);
-				pdpu->is_error = true;
-				ret = -ERESTARTSYS;
-				break;
-			case -EINVAL:
-				DPU_ERROR_PLANE(pdpu,
-					"invalid fence param for %08X\n",
-						prefix);
-				pdpu->is_error = true;
-				ret = -EINVAL;
-				break;
-			default:
-				DPU_DEBUG_PLANE(pdpu, "signaled\n");
-				ret = 0;
-				break;
-			}
-
-			DPU_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
-		} else {
-			ret = 0;
-		}
-	}
-	return ret;
-}
-
 /**
  * _dpu_plane_get_aspace: gets the address space
  */
@@ -3332,7 +3253,6 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
 			break;
 		case PLANE_PROP_INFO:
 		case PLANE_PROP_ALPHA:
-		case PLANE_PROP_INPUT_FENCE:
 		case PLANE_PROP_BLEND_OP:
 			/* no special action required */
 			break;
@@ -3703,10 +3623,6 @@ static void _dpu_plane_install_properties(struct drm_plane *plane,
 	msm_property_install_range(&pdpu->property_info, "alpha",
 		0x0, 0, 255, 255, PLANE_PROP_ALPHA);
 
-	/* linux default file descriptor range on each process */
-	msm_property_install_range(&pdpu->property_info, "input_fence",
-		0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
-
 	if (!master_plane_id) {
 		if (pdpu->pipe_sblk->maxhdeciexp) {
 			msm_property_install_range(&pdpu->property_info,
@@ -4076,9 +3992,6 @@ static int dpu_plane_atomic_set_property(struct drm_plane *plane,
 			idx = msm_property_index(&pdpu->property_info,
 					property);
 			switch (idx) {
-			case PLANE_PROP_INPUT_FENCE:
-				_dpu_plane_set_input_fence(pdpu, pstate, val);
-				break;
 			case PLANE_PROP_CSC_V1:
 				_dpu_plane_set_csc_v1(pdpu, (void *)val);
 				break;
@@ -4190,10 +4103,6 @@ static void dpu_plane_destroy_state(struct drm_plane *plane,
 	if (state->fb)
 		drm_framebuffer_put(state->fb);
 
-	/* remove ref count for fence */
-	if (pstate->input_fence)
-		dpu_sync_put(pstate->input_fence);
-
 	/* destroy value helper */
 	msm_property_destroy_state(&pdpu->property_info, pstate,
 			&pstate->property_state);
@@ -4206,7 +4115,6 @@ dpu_plane_duplicate_state(struct drm_plane *plane)
 	struct dpu_plane_state *pstate;
 	struct dpu_plane_state *old_state;
 	struct drm_property *drm_prop;
-	uint64_t input_fence_default;
 
 	if (!plane) {
 		DPU_ERROR("invalid plane\n");
@@ -4230,18 +4138,6 @@ dpu_plane_duplicate_state(struct drm_plane *plane)
 	msm_property_duplicate_state(&pdpu->property_info, old_state, pstate,
 			&pstate->property_state, pstate->property_values);
 
-	/* clear out any input fence */
-	pstate->input_fence = 0;
-	input_fence_default = msm_property_get_default(
-			&pdpu->property_info, PLANE_PROP_INPUT_FENCE);
-	drm_prop = msm_property_index_to_drm_property(
-				&pdpu->property_info, PLANE_PROP_INPUT_FENCE);
-	if (msm_property_atomic_set(&pdpu->property_info,
-				&pstate->property_state, drm_prop,
-				input_fence_default))
-		DPU_DEBUG_PLANE(pdpu,
-				"error clearing duplicated input fence\n");
-
 	pstate->dirty = 0x0;
 	pstate->pending = false;
 
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 657ea052a1ee..75a24b81c89a 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -99,7 +99,6 @@ enum msm_mdp_plane_property {
 	PLANE_PROP_COLOR_FILL,
 	PLANE_PROP_H_DECIMATE,
 	PLANE_PROP_V_DECIMATE,
-	PLANE_PROP_INPUT_FENCE,
 	PLANE_PROP_HUE_ADJUST,
 	PLANE_PROP_SATURATION_ADJUST,
 	PLANE_PROP_VALUE_ADJUST,
@@ -131,8 +130,7 @@ enum msm_mdp_crtc_property {
 	CRTC_PROP_BLOBCOUNT,
 
 	/* range properties */
-	CRTC_PROP_INPUT_FENCE_TIMEOUT = CRTC_PROP_BLOBCOUNT,
-	CRTC_PROP_DIM_LAYER_V1,
+	CRTC_PROP_DIM_LAYER_V1 = CRTC_PROP_BLOBCOUNT,
 	CRTC_PROP_CORE_CLK,
 	CRTC_PROP_CORE_AB,
 	CRTC_PROP_CORE_IB,
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
       [not found]     ` <20180228191906.185417-7-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-01  4:07       ` jsanka-sgV2jX0FEOL9JmXXK+q4OQ
  2018-03-01 15:27         ` Sean Paul
  0 siblings, 1 reply; 49+ messages in thread
From: jsanka-sgV2jX0FEOL9JmXXK+q4OQ @ 2018-03-01  4:07 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-02-28 11:19, Sean Paul wrote:
> Moving further towards switching fully to the the atomic helpers, this
> patch removes the hand-rolled kthread nonblock commit code and uses the
> atomic helpers commit_work model.
> 
> There's still a lot of copypasta here, but it's still needed to
> facilitate the swap_state and prepare_fence private functions. These
> will be sorted out in a follow-on patch.
> 
> Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>  drivers/gpu/drm/msm/msm_atomic.c | 199 ++++++-------------------------
>  drivers/gpu/drm/msm/msm_drv.c    |   1 -
>  drivers/gpu/drm/msm/msm_drv.h    |   4 -
>  3 files changed, 35 insertions(+), 169 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> b/drivers/gpu/drm/msm/msm_atomic.c
> index 3a18bd3dc215..7e54eb65d096 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -21,51 +21,6 @@
>  #include "msm_gem.h"
>  #include "msm_fence.h"
> 
> -struct msm_commit {
> -	struct drm_device *dev;
> -	struct drm_atomic_state *state;
> -	uint32_t crtc_mask;
> -	bool nonblock;
> -	struct kthread_work commit_work;
> -};
> -
> -/* block until specified crtcs are no longer pending update, and
> - * atomically mark them as pending update
> - */
> -static int start_atomic(struct msm_drm_private *priv, uint32_t 
> crtc_mask)
> -{
> -	int ret;
> -
> -	spin_lock(&priv->pending_crtcs_event.lock);
> -	ret = wait_event_interruptible_locked(priv->pending_crtcs_event,
> -			!(priv->pending_crtcs & crtc_mask));
> -	if (ret == 0) {
> -		DBG("start: %08x", crtc_mask);
> -		priv->pending_crtcs |= crtc_mask;
> -	}
> -	spin_unlock(&priv->pending_crtcs_event.lock);
> -
> -	return ret;
> -}
> -
> -/* clear specified crtcs (no longer pending update)
> - */
> -static void end_atomic(struct msm_drm_private *priv, uint32_t 
> crtc_mask)
> -{
> -	spin_lock(&priv->pending_crtcs_event.lock);
> -	DBG("end: %08x", crtc_mask);
> -	priv->pending_crtcs &= ~crtc_mask;
> -	wake_up_all_locked(&priv->pending_crtcs_event);
> -	spin_unlock(&priv->pending_crtcs_event.lock);
> -}
> -
> -static void commit_destroy(struct msm_commit *c)
> -{
> -	end_atomic(c->dev->dev_private, c->crtc_mask);
> -	if (c->nonblock)
> -		kfree(c);
> -}
> -
>  static void msm_atomic_wait_for_commit_done(
>  		struct drm_device *dev,
>  		struct drm_atomic_state *old_state)
> @@ -118,6 +73,10 @@ static void msm_atomic_commit_tail(struct
> drm_atomic_state *state)
> 
>  	msm_atomic_wait_for_commit_done(dev, state);
> 
> +	drm_atomic_helper_commit_hw_done(state);
> +
> +	drm_atomic_helper_wait_for_vblanks(dev, state);
> +
>  	drm_atomic_helper_cleanup_planes(dev, state);
> 
>  	kms->funcs->complete_commit(kms, state);
> @@ -126,109 +85,25 @@ static void msm_atomic_commit_tail(struct
> drm_atomic_state *state)
>  /* The (potentially) asynchronous part of the commit.  At this point
>   * nothing can fail short of armageddon.
>   */
> -static void complete_commit(struct msm_commit *c)
> +static void commit_tail(struct drm_atomic_state *state)
>  {
> -	struct drm_atomic_state *state = c->state;
> -	struct drm_device *dev = state->dev;
> +	drm_atomic_helper_wait_for_fences(state->dev, state, false);
> 
> -	drm_atomic_helper_wait_for_fences(dev, state, false);
> +	drm_atomic_helper_wait_for_dependencies(state);
> 
>  	msm_atomic_commit_tail(state);
> 
> -	drm_atomic_state_put(state);
> -}
> -
> -static void _msm_drm_commit_work_cb(struct kthread_work *work)
> -{
> -	struct msm_commit *commit =  NULL;
> -
> -	if (!work) {
> -		DRM_ERROR("%s: Invalid commit work data!\n", __func__);
> -		return;
> -	}
> -
> -	commit = container_of(work, struct msm_commit, commit_work);
> -
> -	complete_commit(commit);
> -
> -	commit_destroy(commit);
> -}
> -
> -static struct msm_commit *commit_init(struct drm_atomic_state *state,
> -		bool nonblock)
> -{
> -	struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
> +	drm_atomic_helper_commit_cleanup_done(state);
> 
> -	if (!c)
> -		return NULL;
> -
> -	c->dev = state->dev;
> -	c->state = state;
> -	c->nonblock = nonblock;
> -
> -	kthread_init_work(&c->commit_work, _msm_drm_commit_work_cb);
> -
> -	return c;
> +	drm_atomic_state_put(state);
>  }
> 
> -/* Start display thread function */
> -static void msm_atomic_commit_dispatch(struct drm_device *dev,
> -		struct drm_atomic_state *state, struct msm_commit *commit)
> +static void commit_work(struct work_struct *work)
>  {
> -	struct msm_drm_private *priv = dev->dev_private;
> -	struct drm_crtc *crtc = NULL;
> -	struct drm_crtc_state *new_crtc_state = NULL;
> -	int ret = -EINVAL, i = 0, j = 0;
> -	bool nonblock;
> -
> -	/* cache since work will kfree commit in non-blocking case */
> -	nonblock = commit->nonblock;
> -
> -	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> -		for (j = 0; j < priv->num_crtcs; j++) {
> -			if (priv->disp_thread[j].crtc_id ==
> -						crtc->base.id) {
> -				if (priv->disp_thread[j].thread) {
> -					kthread_queue_work(
> -
> &priv->disp_thread[j].worker,
> -
> &commit->commit_work);
Are there any known proposals floating around to support ASYNC commits 
for concurrent displays rendering at different FPS? The above kthread 
model is introduced when we faced some performance road blockers when a 
display has to wait for an ongoing display commit to complete.
> -					/* only return zero if work is
> -					 * queued successfully.
> -					 */
> -					ret = 0;
> -				} else {
> -					DRM_ERROR(" Error for crtc_id:
> %d\n",
> -
> priv->disp_thread[j].crtc_id);
> -				}
> -				break;
> -			}
> -		}
> -		/*
> -		 * TODO: handle cases where there will be more than
> -		 * one crtc per commit cycle. Remove this check then.
> -		 * Current assumption is there will be only one crtc
> -		 * per commit cycle.
> -		 */
> -		if (j < priv->num_crtcs)
> -			break;
> -	}
> -
> -	if (ret) {
> -		/**
> -		 * this is not expected to happen, but at this point the
> state
> -		 * has been swapped, but we couldn't dispatch to a crtc
> thread.
> -		 * fallback now to a synchronous complete_commit to try
> and
> -		 * ensure that SW and HW state don't get out of sync.
> -		 */
> -		DRM_ERROR("failed to dispatch commit to any CRTC\n");
> -		complete_commit(commit);
> -	} else if (!nonblock) {
> -		kthread_flush_work(&commit->commit_work);
> -	}
> -
> -	/* free nonblocking commits in this context, after processing */
> -	if (!nonblock)
> -		kfree(commit);
> +	struct drm_atomic_state *state = container_of(work,
> +						      struct
> drm_atomic_state,
> +						      commit_work);
> +	commit_tail(state);
>  }
> 
>  /**
> @@ -247,17 +122,12 @@ int msm_atomic_commit(struct drm_device *dev,
>  		struct drm_atomic_state *state, bool nonblock)
>  {
>  	struct msm_drm_private *priv = dev->dev_private;
> -	struct msm_commit *c;
>  	struct drm_crtc *crtc;
>  	struct drm_crtc_state *crtc_state;
>  	struct drm_plane *plane;
>  	struct drm_plane_state *old_plane_state, *new_plane_state;
>  	int i, ret;
> 
> -	ret = drm_atomic_helper_prepare_planes(dev, state);
> -	if (ret)
> -		return ret;
> -
>  	/*
>  	 * Note that plane->atomic_async_check() should fail if we need
>  	 * to re-assign hwpipe or anything that touches global atomic
> @@ -265,32 +135,30 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 * cases.
>  	 */
>  	if (state->async_update) {
> +		ret = drm_atomic_helper_prepare_planes(dev, state);
> +		if (ret)
> +			return ret;
> +
>  		drm_atomic_helper_async_commit(dev, state);
>  		drm_atomic_helper_cleanup_planes(dev, state);
>  		return 0;
>  	}
> 
> -	c = commit_init(state, nonblock);
> -	if (!c) {
> -		ret = -ENOMEM;
> -		goto error;
> -	}
> +	ret = drm_atomic_helper_setup_commit(state, nonblock);
> +	if (ret)
> +		return ret;
> 
> -	/*
> -	 * Figure out what crtcs we have:
> -	 */
> -	for_each_new_crtc_in_state(state, crtc, crtc_state, i)
> -		c->crtc_mask |= drm_crtc_mask(crtc);
> +	INIT_WORK(&state->commit_work, commit_work);
> 
> -	/*
> -	 * Wait for pending updates on any of the same crtc's and then
> -	 * mark our set of crtc's as busy:
> -	 */
> -	ret = start_atomic(dev->dev_private, c->crtc_mask);
> +	ret = drm_atomic_helper_prepare_planes(dev, state);
>  	if (ret)
> -		goto err_free;
> +		return ret;
> 
> -	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> +	if (!nonblock) {
> +		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> +		if (ret)
> +			goto error;
> +	}
> 
>  	/*
>  	 * This is the point of no return - everything below never fails
> except
> @@ -299,6 +167,8 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 *
>  	 * swap driver private state while still holding state_lock
>  	 */
> +	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> +
>  	if (to_kms_state(state)->state)
>  		priv->kms->funcs->swap_state(priv->kms, state);
> 
> @@ -329,12 +199,13 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 */
> 
>  	drm_atomic_state_get(state);
> -	msm_atomic_commit_dispatch(dev, state, c);
> +	if (nonblock)
> +		queue_work(system_unbound_wq, &state->commit_work);
> +	else
> +		commit_tail(state);
> 
>  	return 0;
> 
> -err_free:
> -	kfree(c);
>  error:
>  	drm_atomic_helper_cleanup_planes(dev, state);
>  	return ret;
> diff --git a/drivers/gpu/drm/msm/msm_drv.c 
> b/drivers/gpu/drm/msm/msm_drv.c
> index eda4a2340f93..b354424cccb5 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -549,7 +549,6 @@ static int msm_drm_init(struct device *dev, struct
> drm_driver *drv)
>  		goto mdss_init_fail;
> 
>  	priv->wq = alloc_ordered_workqueue("msm_drm", 0);
> -	init_waitqueue_head(&priv->pending_crtcs_event);
> 
>  	INIT_LIST_HEAD(&priv->client_event_list);
>  	INIT_LIST_HEAD(&priv->inactive_list);
> diff --git a/drivers/gpu/drm/msm/msm_drv.h 
> b/drivers/gpu/drm/msm/msm_drv.h
> index cf96a85f4b55..292496b682e8 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -536,10 +536,6 @@ struct msm_drm_private {
> 
>  	struct workqueue_struct *wq;
> 
> -	/* crtcs pending async atomic updates: */
> -	uint32_t pending_crtcs;
> -	wait_queue_head_t pending_crtcs_event;
> -
>  	unsigned int num_planes;
>  	struct drm_plane *planes[MAX_PLANES];
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
  2018-03-01  4:07       ` jsanka-sgV2jX0FEOL9JmXXK+q4OQ
@ 2018-03-01 15:27         ` Sean Paul
  2018-03-01 20:37           ` jsanka-sgV2jX0FEOL9JmXXK+q4OQ
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-01 15:27 UTC (permalink / raw)
  To: jsanka; +Cc: linux-arm-msm, dri-devel, abhinavk, hoegsberg, freedreno

On Wed, Feb 28, 2018 at 08:07:00PM -0800, jsanka@codeaurora.org wrote:
> On 2018-02-28 11:19, Sean Paul wrote:
> > Moving further towards switching fully to the the atomic helpers, this
> > patch removes the hand-rolled kthread nonblock commit code and uses the
> > atomic helpers commit_work model.
> > 
> > There's still a lot of copypasta here, but it's still needed to
> > facilitate the swap_state and prepare_fence private functions. These
> > will be sorted out in a follow-on patch.
> > 
> > Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > ---
> >  drivers/gpu/drm/msm/msm_atomic.c | 199 ++++++-------------------------
> >  drivers/gpu/drm/msm/msm_drv.c    |   1 -
> >  drivers/gpu/drm/msm/msm_drv.h    |   4 -
> >  3 files changed, 35 insertions(+), 169 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> > b/drivers/gpu/drm/msm/msm_atomic.c
> > index 3a18bd3dc215..7e54eb65d096 100644
> > --- a/drivers/gpu/drm/msm/msm_atomic.c
> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> > @@ -21,51 +21,6 @@
> >  #include "msm_gem.h"
> >  #include "msm_fence.h"
> > 
> > -struct msm_commit {
> > -	struct drm_device *dev;
> > -	struct drm_atomic_state *state;
> > -	uint32_t crtc_mask;
> > -	bool nonblock;
> > -	struct kthread_work commit_work;
> > -};
> > -
> > -/* block until specified crtcs are no longer pending update, and
> > - * atomically mark them as pending update
> > - */
> > -static int start_atomic(struct msm_drm_private *priv, uint32_t
> > crtc_mask)
> > -{
> > -	int ret;
> > -
> > -	spin_lock(&priv->pending_crtcs_event.lock);
> > -	ret = wait_event_interruptible_locked(priv->pending_crtcs_event,
> > -			!(priv->pending_crtcs & crtc_mask));
> > -	if (ret == 0) {
> > -		DBG("start: %08x", crtc_mask);
> > -		priv->pending_crtcs |= crtc_mask;
> > -	}
> > -	spin_unlock(&priv->pending_crtcs_event.lock);
> > -
> > -	return ret;
> > -}
> > -
> > -/* clear specified crtcs (no longer pending update)
> > - */
> > -static void end_atomic(struct msm_drm_private *priv, uint32_t
> > crtc_mask)
> > -{
> > -	spin_lock(&priv->pending_crtcs_event.lock);
> > -	DBG("end: %08x", crtc_mask);
> > -	priv->pending_crtcs &= ~crtc_mask;
> > -	wake_up_all_locked(&priv->pending_crtcs_event);
> > -	spin_unlock(&priv->pending_crtcs_event.lock);
> > -}
> > -
> > -static void commit_destroy(struct msm_commit *c)
> > -{
> > -	end_atomic(c->dev->dev_private, c->crtc_mask);
> > -	if (c->nonblock)
> > -		kfree(c);
> > -}
> > -
> >  static void msm_atomic_wait_for_commit_done(
> >  		struct drm_device *dev,
> >  		struct drm_atomic_state *old_state)
> > @@ -118,6 +73,10 @@ static void msm_atomic_commit_tail(struct
> > drm_atomic_state *state)
> > 
> >  	msm_atomic_wait_for_commit_done(dev, state);
> > 
> > +	drm_atomic_helper_commit_hw_done(state);
> > +
> > +	drm_atomic_helper_wait_for_vblanks(dev, state);
> > +
> >  	drm_atomic_helper_cleanup_planes(dev, state);
> > 
> >  	kms->funcs->complete_commit(kms, state);
> > @@ -126,109 +85,25 @@ static void msm_atomic_commit_tail(struct
> > drm_atomic_state *state)
> >  /* The (potentially) asynchronous part of the commit.  At this point
> >   * nothing can fail short of armageddon.
> >   */
> > -static void complete_commit(struct msm_commit *c)
> > +static void commit_tail(struct drm_atomic_state *state)
> >  {
> > -	struct drm_atomic_state *state = c->state;
> > -	struct drm_device *dev = state->dev;
> > +	drm_atomic_helper_wait_for_fences(state->dev, state, false);
> > 
> > -	drm_atomic_helper_wait_for_fences(dev, state, false);
> > +	drm_atomic_helper_wait_for_dependencies(state);
> > 
> >  	msm_atomic_commit_tail(state);
> > 
> > -	drm_atomic_state_put(state);
> > -}
> > -
> > -static void _msm_drm_commit_work_cb(struct kthread_work *work)
> > -{
> > -	struct msm_commit *commit =  NULL;
> > -
> > -	if (!work) {
> > -		DRM_ERROR("%s: Invalid commit work data!\n", __func__);
> > -		return;
> > -	}
> > -
> > -	commit = container_of(work, struct msm_commit, commit_work);
> > -
> > -	complete_commit(commit);
> > -
> > -	commit_destroy(commit);
> > -}
> > -
> > -static struct msm_commit *commit_init(struct drm_atomic_state *state,
> > -		bool nonblock)
> > -{
> > -	struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
> > +	drm_atomic_helper_commit_cleanup_done(state);
> > 
> > -	if (!c)
> > -		return NULL;
> > -
> > -	c->dev = state->dev;
> > -	c->state = state;
> > -	c->nonblock = nonblock;
> > -
> > -	kthread_init_work(&c->commit_work, _msm_drm_commit_work_cb);
> > -
> > -	return c;
> > +	drm_atomic_state_put(state);
> >  }
> > 
> > -/* Start display thread function */
> > -static void msm_atomic_commit_dispatch(struct drm_device *dev,
> > -		struct drm_atomic_state *state, struct msm_commit *commit)
> > +static void commit_work(struct work_struct *work)
> >  {
> > -	struct msm_drm_private *priv = dev->dev_private;
> > -	struct drm_crtc *crtc = NULL;
> > -	struct drm_crtc_state *new_crtc_state = NULL;
> > -	int ret = -EINVAL, i = 0, j = 0;
> > -	bool nonblock;
> > -
> > -	/* cache since work will kfree commit in non-blocking case */
> > -	nonblock = commit->nonblock;
> > -
> > -	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> > -		for (j = 0; j < priv->num_crtcs; j++) {
> > -			if (priv->disp_thread[j].crtc_id ==
> > -						crtc->base.id) {
> > -				if (priv->disp_thread[j].thread) {
> > -					kthread_queue_work(
> > -
> > &priv->disp_thread[j].worker,
> > -
> > &commit->commit_work);
> Are there any known proposals floating around to support ASYNC commits for
> concurrent displays rendering at different FPS? The above kthread model is
> introduced when we faced some performance road blockers when a display has
> to wait for an ongoing display commit to complete.

I think people have discussed it, I'm not sure if there are any patches floating
around. On the surface, it seems easy to just push the commit_work into the crtc
commit and have one work item per crtc. However I think the problem is that there
could be resources switching between crtcs for a given commit, or from one commit
to the next, and synchronizing that becomes a Hard Problem.

Perhaps I'm misunderstanding, but the start/end atomic functions serialize the
incoming commits, right? So the only benefit the kthread provides is to mitigate
any blocking calls made on one crtc from blocking a second crtc in the same
commit?

Sean

> > -					/* only return zero if work is
> > -					 * queued successfully.
> > -					 */
> > -					ret = 0;
> > -				} else {
> > -					DRM_ERROR(" Error for crtc_id:
> > %d\n",
> > -
> > priv->disp_thread[j].crtc_id);
> > -				}
> > -				break;
> > -			}
> > -		}
> > -		/*
> > -		 * TODO: handle cases where there will be more than
> > -		 * one crtc per commit cycle. Remove this check then.
> > -		 * Current assumption is there will be only one crtc
> > -		 * per commit cycle.
> > -		 */
> > -		if (j < priv->num_crtcs)
> > -			break;
> > -	}
> > -
> > -	if (ret) {
> > -		/**
> > -		 * this is not expected to happen, but at this point the
> > state
> > -		 * has been swapped, but we couldn't dispatch to a crtc
> > thread.
> > -		 * fallback now to a synchronous complete_commit to try
> > and
> > -		 * ensure that SW and HW state don't get out of sync.
> > -		 */
> > -		DRM_ERROR("failed to dispatch commit to any CRTC\n");
> > -		complete_commit(commit);
> > -	} else if (!nonblock) {
> > -		kthread_flush_work(&commit->commit_work);
> > -	}
> > -
> > -	/* free nonblocking commits in this context, after processing */
> > -	if (!nonblock)
> > -		kfree(commit);
> > +	struct drm_atomic_state *state = container_of(work,
> > +						      struct
> > drm_atomic_state,
> > +						      commit_work);
> > +	commit_tail(state);
> >  }
> > 
> >  /**
> > @@ -247,17 +122,12 @@ int msm_atomic_commit(struct drm_device *dev,
> >  		struct drm_atomic_state *state, bool nonblock)
> >  {
> >  	struct msm_drm_private *priv = dev->dev_private;
> > -	struct msm_commit *c;
> >  	struct drm_crtc *crtc;
> >  	struct drm_crtc_state *crtc_state;
> >  	struct drm_plane *plane;
> >  	struct drm_plane_state *old_plane_state, *new_plane_state;
> >  	int i, ret;
> > 
> > -	ret = drm_atomic_helper_prepare_planes(dev, state);
> > -	if (ret)
> > -		return ret;
> > -
> >  	/*
> >  	 * Note that plane->atomic_async_check() should fail if we need
> >  	 * to re-assign hwpipe or anything that touches global atomic
> > @@ -265,32 +135,30 @@ int msm_atomic_commit(struct drm_device *dev,
> >  	 * cases.
> >  	 */
> >  	if (state->async_update) {
> > +		ret = drm_atomic_helper_prepare_planes(dev, state);
> > +		if (ret)
> > +			return ret;
> > +
> >  		drm_atomic_helper_async_commit(dev, state);
> >  		drm_atomic_helper_cleanup_planes(dev, state);
> >  		return 0;
> >  	}
> > 
> > -	c = commit_init(state, nonblock);
> > -	if (!c) {
> > -		ret = -ENOMEM;
> > -		goto error;
> > -	}
> > +	ret = drm_atomic_helper_setup_commit(state, nonblock);
> > +	if (ret)
> > +		return ret;
> > 
> > -	/*
> > -	 * Figure out what crtcs we have:
> > -	 */
> > -	for_each_new_crtc_in_state(state, crtc, crtc_state, i)
> > -		c->crtc_mask |= drm_crtc_mask(crtc);
> > +	INIT_WORK(&state->commit_work, commit_work);
> > 
> > -	/*
> > -	 * Wait for pending updates on any of the same crtc's and then
> > -	 * mark our set of crtc's as busy:
> > -	 */
> > -	ret = start_atomic(dev->dev_private, c->crtc_mask);
> > +	ret = drm_atomic_helper_prepare_planes(dev, state);
> >  	if (ret)
> > -		goto err_free;
> > +		return ret;
> > 
> > -	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> > +	if (!nonblock) {
> > +		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> > +		if (ret)
> > +			goto error;
> > +	}
> > 
> >  	/*
> >  	 * This is the point of no return - everything below never fails
> > except
> > @@ -299,6 +167,8 @@ int msm_atomic_commit(struct drm_device *dev,
> >  	 *
> >  	 * swap driver private state while still holding state_lock
> >  	 */
> > +	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> > +
> >  	if (to_kms_state(state)->state)
> >  		priv->kms->funcs->swap_state(priv->kms, state);
> > 
> > @@ -329,12 +199,13 @@ int msm_atomic_commit(struct drm_device *dev,
> >  	 */
> > 
> >  	drm_atomic_state_get(state);
> > -	msm_atomic_commit_dispatch(dev, state, c);
> > +	if (nonblock)
> > +		queue_work(system_unbound_wq, &state->commit_work);
> > +	else
> > +		commit_tail(state);
> > 
> >  	return 0;
> > 
> > -err_free:
> > -	kfree(c);
> >  error:
> >  	drm_atomic_helper_cleanup_planes(dev, state);
> >  	return ret;
> > diff --git a/drivers/gpu/drm/msm/msm_drv.c
> > b/drivers/gpu/drm/msm/msm_drv.c
> > index eda4a2340f93..b354424cccb5 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.c
> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > @@ -549,7 +549,6 @@ static int msm_drm_init(struct device *dev, struct
> > drm_driver *drv)
> >  		goto mdss_init_fail;
> > 
> >  	priv->wq = alloc_ordered_workqueue("msm_drm", 0);
> > -	init_waitqueue_head(&priv->pending_crtcs_event);
> > 
> >  	INIT_LIST_HEAD(&priv->client_event_list);
> >  	INIT_LIST_HEAD(&priv->inactive_list);
> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
> > b/drivers/gpu/drm/msm/msm_drv.h
> > index cf96a85f4b55..292496b682e8 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > @@ -536,10 +536,6 @@ struct msm_drm_private {
> > 
> >  	struct workqueue_struct *wq;
> > 
> > -	/* crtcs pending async atomic updates: */
> > -	uint32_t pending_crtcs;
> > -	wait_queue_head_t pending_crtcs_event;
> > -
> >  	unsigned int num_planes;
> >  	struct drm_plane *planes[MAX_PLANES];

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
  2018-03-01 15:27         ` Sean Paul
@ 2018-03-01 20:37           ` jsanka-sgV2jX0FEOL9JmXXK+q4OQ
       [not found]             ` <156ab33c41d436c79cc661e84bebc353-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: jsanka-sgV2jX0FEOL9JmXXK+q4OQ @ 2018-03-01 20:37 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-03-01 07:27, Sean Paul wrote:
> On Wed, Feb 28, 2018 at 08:07:00PM -0800, jsanka@codeaurora.org wrote:
>> On 2018-02-28 11:19, Sean Paul wrote:
>> > Moving further towards switching fully to the the atomic helpers, this
>> > patch removes the hand-rolled kthread nonblock commit code and uses
> the
>> > atomic helpers commit_work model.
>> >
>> > There's still a lot of copypasta here, but it's still needed to
>> > facilitate the swap_state and prepare_fence private functions. These
>> > will be sorted out in a follow-on patch.
>> >
>> > Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> > ---
>> >  drivers/gpu/drm/msm/msm_atomic.c | 199
> ++++++-------------------------
>> >  drivers/gpu/drm/msm/msm_drv.c    |   1 -
>> >  drivers/gpu/drm/msm/msm_drv.h    |   4 -
>> >  3 files changed, 35 insertions(+), 169 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
>> > b/drivers/gpu/drm/msm/msm_atomic.c
>> > index 3a18bd3dc215..7e54eb65d096 100644
>> > --- a/drivers/gpu/drm/msm/msm_atomic.c
>> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> > @@ -21,51 +21,6 @@
>> >  #include "msm_gem.h"
>> >  #include "msm_fence.h"
>> >
>> > -struct msm_commit {
>> > -	struct drm_device *dev;
>> > -	struct drm_atomic_state *state;
>> > -	uint32_t crtc_mask;
>> > -	bool nonblock;
>> > -	struct kthread_work commit_work;
>> > -};
>> > -
>> > -/* block until specified crtcs are no longer pending update, and
>> > - * atomically mark them as pending update
>> > - */
>> > -static int start_atomic(struct msm_drm_private *priv, uint32_t
>> > crtc_mask)
>> > -{
>> > -	int ret;
>> > -
>> > -	spin_lock(&priv->pending_crtcs_event.lock);
>> > -	ret = wait_event_interruptible_locked(priv->pending_crtcs_event,
>> > -			!(priv->pending_crtcs & crtc_mask));
>> > -	if (ret == 0) {
>> > -		DBG("start: %08x", crtc_mask);
>> > -		priv->pending_crtcs |= crtc_mask;
>> > -	}
>> > -	spin_unlock(&priv->pending_crtcs_event.lock);
>> > -
>> > -	return ret;
>> > -}
>> > -
>> > -/* clear specified crtcs (no longer pending update)
>> > - */
>> > -static void end_atomic(struct msm_drm_private *priv, uint32_t
>> > crtc_mask)
>> > -{
>> > -	spin_lock(&priv->pending_crtcs_event.lock);
>> > -	DBG("end: %08x", crtc_mask);
>> > -	priv->pending_crtcs &= ~crtc_mask;
>> > -	wake_up_all_locked(&priv->pending_crtcs_event);
>> > -	spin_unlock(&priv->pending_crtcs_event.lock);
>> > -}
>> > -
>> > -static void commit_destroy(struct msm_commit *c)
>> > -{
>> > -	end_atomic(c->dev->dev_private, c->crtc_mask);
>> > -	if (c->nonblock)
>> > -		kfree(c);
>> > -}
>> > -
>> >  static void msm_atomic_wait_for_commit_done(
>> >  		struct drm_device *dev,
>> >  		struct drm_atomic_state *old_state)
>> > @@ -118,6 +73,10 @@ static void msm_atomic_commit_tail(struct
>> > drm_atomic_state *state)
>> >
>> >  	msm_atomic_wait_for_commit_done(dev, state);
>> >
>> > +	drm_atomic_helper_commit_hw_done(state);
>> > +
>> > +	drm_atomic_helper_wait_for_vblanks(dev, state);
>> > +
>> >  	drm_atomic_helper_cleanup_planes(dev, state);
>> >
>> >  	kms->funcs->complete_commit(kms, state);
>> > @@ -126,109 +85,25 @@ static void msm_atomic_commit_tail(struct
>> > drm_atomic_state *state)
>> >  /* The (potentially) asynchronous part of the commit.  At this point
>> >   * nothing can fail short of armageddon.
>> >   */
>> > -static void complete_commit(struct msm_commit *c)
>> > +static void commit_tail(struct drm_atomic_state *state)
>> >  {
>> > -	struct drm_atomic_state *state = c->state;
>> > -	struct drm_device *dev = state->dev;
>> > +	drm_atomic_helper_wait_for_fences(state->dev, state, false);
>> >
>> > -	drm_atomic_helper_wait_for_fences(dev, state, false);
>> > +	drm_atomic_helper_wait_for_dependencies(state);
>> >
>> >  	msm_atomic_commit_tail(state);
>> >
>> > -	drm_atomic_state_put(state);
>> > -}
>> > -
>> > -static void _msm_drm_commit_work_cb(struct kthread_work *work)
>> > -{
>> > -	struct msm_commit *commit =  NULL;
>> > -
>> > -	if (!work) {
>> > -		DRM_ERROR("%s: Invalid commit work data!\n", __func__);
>> > -		return;
>> > -	}
>> > -
>> > -	commit = container_of(work, struct msm_commit, commit_work);
>> > -
>> > -	complete_commit(commit);
>> > -
>> > -	commit_destroy(commit);
>> > -}
>> > -
>> > -static struct msm_commit *commit_init(struct drm_atomic_state *state,
>> > -		bool nonblock)
>> > -{
>> > -	struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
>> > +	drm_atomic_helper_commit_cleanup_done(state);
>> >
>> > -	if (!c)
>> > -		return NULL;
>> > -
>> > -	c->dev = state->dev;
>> > -	c->state = state;
>> > -	c->nonblock = nonblock;
>> > -
>> > -	kthread_init_work(&c->commit_work, _msm_drm_commit_work_cb);
>> > -
>> > -	return c;
>> > +	drm_atomic_state_put(state);
>> >  }
>> >
>> > -/* Start display thread function */
>> > -static void msm_atomic_commit_dispatch(struct drm_device *dev,
>> > -		struct drm_atomic_state *state, struct msm_commit *commit)
>> > +static void commit_work(struct work_struct *work)
>> >  {
>> > -	struct msm_drm_private *priv = dev->dev_private;
>> > -	struct drm_crtc *crtc = NULL;
>> > -	struct drm_crtc_state *new_crtc_state = NULL;
>> > -	int ret = -EINVAL, i = 0, j = 0;
>> > -	bool nonblock;
>> > -
>> > -	/* cache since work will kfree commit in non-blocking case */
>> > -	nonblock = commit->nonblock;
>> > -
>> > -	for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
>> > -		for (j = 0; j < priv->num_crtcs; j++) {
>> > -			if (priv->disp_thread[j].crtc_id ==
>> > -						crtc->base.id) {
>> > -				if (priv->disp_thread[j].thread) {
>> > -					kthread_queue_work(
>> > -
>> > &priv->disp_thread[j].worker,
>> > -
>> > &commit->commit_work);
>> Are there any known proposals floating around to support ASYNC commits
> for
>> concurrent displays rendering at different FPS? The above kthread 
>> model
> is
>> introduced when we faced some performance road blockers when a display
> has
>> to wait for an ongoing display commit to complete.
> 
> I think people have discussed it, I'm not sure if there are any patches
> floating
> around. On the surface, it seems easy to just push the commit_work into
> the crtc
> commit and have one work item per crtc. However I think the problem is
> that there
> could be resources switching between crtcs for a given commit, or from 
> one
> commit
> to the next, and synchronizing that becomes a Hard Problem.
> 
> Perhaps I'm misunderstanding, but the start/end atomic functions 
> serialize
> the
> incoming commits, right? So the only benefit the kthread provides is to
> mitigate
> any blocking calls made on one crtc from blocking a second crtc in the
> same
> commit?
> 
> Sean
I am not sure what level of resource (I assume hw blocks) switching we 
can expect between
two active CRTC's on successive commits. With virtualization in play, 
the resources allocated to
CRTC / encoder / Connector will remain attached to the components as 
long as the display is active.
Planes (HW pipes) are one such entity which can move between the CRTC's 
frequently. Even
with them planes, the hw assignment should remain valid until the plane 
is detached from
a CRTC before attaching to the next one.

"Start atomic" synchronizes the commit cycle for all the CRTC's by 
waiting for commit complete
of all the previous frames. But per crtc kthreads allows the current 
frame commits to happen
independently. For android, we needed this model as each commit thread 
need to wait for input
plane fences before programming the hardware.

Jeykumar S.
> 
>> > -					/* only return zero if work is
>> > -					 * queued successfully.
>> > -					 */
>> > -					ret = 0;
>> > -				} else {
>> > -					DRM_ERROR(" Error for crtc_id:
>> > %d\n",
>> > -
>> > priv->disp_thread[j].crtc_id);
>> > -				}
>> > -				break;
>> > -			}
>> > -		}
>> > -		/*
>> > -		 * TODO: handle cases where there will be more than
>> > -		 * one crtc per commit cycle. Remove this check then.
>> > -		 * Current assumption is there will be only one crtc
>> > -		 * per commit cycle.
>> > -		 */
>> > -		if (j < priv->num_crtcs)
>> > -			break;
>> > -	}
>> > -
>> > -	if (ret) {
>> > -		/**
>> > -		 * this is not expected to happen, but at this point the
>> > state
>> > -		 * has been swapped, but we couldn't dispatch to a crtc
>> > thread.
>> > -		 * fallback now to a synchronous complete_commit to try
>> > and
>> > -		 * ensure that SW and HW state don't get out of sync.
>> > -		 */
>> > -		DRM_ERROR("failed to dispatch commit to any CRTC\n");
>> > -		complete_commit(commit);
>> > -	} else if (!nonblock) {
>> > -		kthread_flush_work(&commit->commit_work);
>> > -	}
>> > -
>> > -	/* free nonblocking commits in this context, after processing */
>> > -	if (!nonblock)
>> > -		kfree(commit);
>> > +	struct drm_atomic_state *state = container_of(work,
>> > +						      struct
>> > drm_atomic_state,
>> > +						      commit_work);
>> > +	commit_tail(state);
>> >  }
>> >
>> >  /**
>> > @@ -247,17 +122,12 @@ int msm_atomic_commit(struct drm_device *dev,
>> >  		struct drm_atomic_state *state, bool nonblock)
>> >  {
>> >  	struct msm_drm_private *priv = dev->dev_private;
>> > -	struct msm_commit *c;
>> >  	struct drm_crtc *crtc;
>> >  	struct drm_crtc_state *crtc_state;
>> >  	struct drm_plane *plane;
>> >  	struct drm_plane_state *old_plane_state, *new_plane_state;
>> >  	int i, ret;
>> >
>> > -	ret = drm_atomic_helper_prepare_planes(dev, state);
>> > -	if (ret)
>> > -		return ret;
>> > -
>> >  	/*
>> >  	 * Note that plane->atomic_async_check() should fail if we need
>> >  	 * to re-assign hwpipe or anything that touches global atomic
>> > @@ -265,32 +135,30 @@ int msm_atomic_commit(struct drm_device *dev,
>> >  	 * cases.
>> >  	 */
>> >  	if (state->async_update) {
>> > +		ret = drm_atomic_helper_prepare_planes(dev, state);
>> > +		if (ret)
>> > +			return ret;
>> > +
>> >  		drm_atomic_helper_async_commit(dev, state);
>> >  		drm_atomic_helper_cleanup_planes(dev, state);
>> >  		return 0;
>> >  	}
>> >
>> > -	c = commit_init(state, nonblock);
>> > -	if (!c) {
>> > -		ret = -ENOMEM;
>> > -		goto error;
>> > -	}
>> > +	ret = drm_atomic_helper_setup_commit(state, nonblock);
>> > +	if (ret)
>> > +		return ret;
>> >
>> > -	/*
>> > -	 * Figure out what crtcs we have:
>> > -	 */
>> > -	for_each_new_crtc_in_state(state, crtc, crtc_state, i)
>> > -		c->crtc_mask |= drm_crtc_mask(crtc);
>> > +	INIT_WORK(&state->commit_work, commit_work);
>> >
>> > -	/*
>> > -	 * Wait for pending updates on any of the same crtc's and then
>> > -	 * mark our set of crtc's as busy:
>> > -	 */
>> > -	ret = start_atomic(dev->dev_private, c->crtc_mask);
>> > +	ret = drm_atomic_helper_prepare_planes(dev, state);
>> >  	if (ret)
>> > -		goto err_free;
>> > +		return ret;
>> >
>> > -	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
>> > +	if (!nonblock) {
>> > +		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>> > +		if (ret)
>> > +			goto error;
>> > +	}
>> >
>> >  	/*
>> >  	 * This is the point of no return - everything below never fails
>> > except
>> > @@ -299,6 +167,8 @@ int msm_atomic_commit(struct drm_device *dev,
>> >  	 *
>> >  	 * swap driver private state while still holding state_lock
>> >  	 */
>> > +	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
>> > +
>> >  	if (to_kms_state(state)->state)
>> >  		priv->kms->funcs->swap_state(priv->kms, state);
>> >
>> > @@ -329,12 +199,13 @@ int msm_atomic_commit(struct drm_device *dev,
>> >  	 */
>> >
>> >  	drm_atomic_state_get(state);
>> > -	msm_atomic_commit_dispatch(dev, state, c);
>> > +	if (nonblock)
>> > +		queue_work(system_unbound_wq, &state->commit_work);
>> > +	else
>> > +		commit_tail(state);
>> >
>> >  	return 0;
>> >
>> > -err_free:
>> > -	kfree(c);
>> >  error:
>> >  	drm_atomic_helper_cleanup_planes(dev, state);
>> >  	return ret;
>> > diff --git a/drivers/gpu/drm/msm/msm_drv.c
>> > b/drivers/gpu/drm/msm/msm_drv.c
>> > index eda4a2340f93..b354424cccb5 100644
>> > --- a/drivers/gpu/drm/msm/msm_drv.c
>> > +++ b/drivers/gpu/drm/msm/msm_drv.c
>> > @@ -549,7 +549,6 @@ static int msm_drm_init(struct device *dev, struct
>> > drm_driver *drv)
>> >  		goto mdss_init_fail;
>> >
>> >  	priv->wq = alloc_ordered_workqueue("msm_drm", 0);
>> > -	init_waitqueue_head(&priv->pending_crtcs_event);
>> >
>> >  	INIT_LIST_HEAD(&priv->client_event_list);
>> >  	INIT_LIST_HEAD(&priv->inactive_list);
>> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
>> > b/drivers/gpu/drm/msm/msm_drv.h
>> > index cf96a85f4b55..292496b682e8 100644
>> > --- a/drivers/gpu/drm/msm/msm_drv.h
>> > +++ b/drivers/gpu/drm/msm/msm_drv.h
>> > @@ -536,10 +536,6 @@ struct msm_drm_private {
>> >
>> >  	struct workqueue_struct *wq;
>> >
>> > -	/* crtcs pending async atomic updates: */
>> > -	uint32_t pending_crtcs;
>> > -	wait_queue_head_t pending_crtcs_event;
>> > -
>> >  	unsigned int num_planes;
>> >  	struct drm_plane *planes[MAX_PLANES];
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
       [not found]             ` <156ab33c41d436c79cc661e84bebc353-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-03-02  0:37               ` Rob Clark
       [not found]                 ` <CAF6AEGvDZ8sWYwwbyPYcQZN6Ba01Gc7db724GeehF3cLY6d-XQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Rob Clark @ 2018-03-02  0:37 UTC (permalink / raw)
  To: Jeykumar Sankaran
  Cc: linux-arm-msm, abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, Sean Paul,
	dri-devel, Kristian H. Kristensen, freedreno

On Thu, Mar 1, 2018 at 3:37 PM,  <jsanka@codeaurora.org> wrote:
> On 2018-03-01 07:27, Sean Paul wrote:
>>
>> On Wed, Feb 28, 2018 at 08:07:00PM -0800, jsanka@codeaurora.org wrote:
>>>
>>> On 2018-02-28 11:19, Sean Paul wrote:
>>> > Moving further towards switching fully to the the atomic helpers, this
>>> > patch removes the hand-rolled kthread nonblock commit code and uses
>>
>> the
>>>
>>> > atomic helpers commit_work model.
>>> >
>>> > There's still a lot of copypasta here, but it's still needed to
>>> > facilitate the swap_state and prepare_fence private functions. These
>>> > will be sorted out in a follow-on patch.
>>> >
>>> > Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
>>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
>>> > ---
>>> >  drivers/gpu/drm/msm/msm_atomic.c | 199
>>
>> ++++++-------------------------
>>>
>>> >  drivers/gpu/drm/msm/msm_drv.c    |   1 -
>>> >  drivers/gpu/drm/msm/msm_drv.h    |   4 -
>>> >  3 files changed, 35 insertions(+), 169 deletions(-)
>>> >
>>> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
>>> > b/drivers/gpu/drm/msm/msm_atomic.c
>>> > index 3a18bd3dc215..7e54eb65d096 100644
>>> > --- a/drivers/gpu/drm/msm/msm_atomic.c
>>> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
>>> > @@ -21,51 +21,6 @@
>>> >  #include "msm_gem.h"
>>> >  #include "msm_fence.h"
>>> >
>>> > -struct msm_commit {
>>> > -     struct drm_device *dev;
>>> > -     struct drm_atomic_state *state;
>>> > -     uint32_t crtc_mask;
>>> > -     bool nonblock;
>>> > -     struct kthread_work commit_work;
>>> > -};
>>> > -
>>> > -/* block until specified crtcs are no longer pending update, and
>>> > - * atomically mark them as pending update
>>> > - */
>>> > -static int start_atomic(struct msm_drm_private *priv, uint32_t
>>> > crtc_mask)
>>> > -{
>>> > -     int ret;
>>> > -
>>> > -     spin_lock(&priv->pending_crtcs_event.lock);
>>> > -     ret = wait_event_interruptible_locked(priv->pending_crtcs_event,
>>> > -                     !(priv->pending_crtcs & crtc_mask));
>>> > -     if (ret == 0) {
>>> > -             DBG("start: %08x", crtc_mask);
>>> > -             priv->pending_crtcs |= crtc_mask;
>>> > -     }
>>> > -     spin_unlock(&priv->pending_crtcs_event.lock);
>>> > -
>>> > -     return ret;
>>> > -}
>>> > -
>>> > -/* clear specified crtcs (no longer pending update)
>>> > - */
>>> > -static void end_atomic(struct msm_drm_private *priv, uint32_t
>>> > crtc_mask)
>>> > -{
>>> > -     spin_lock(&priv->pending_crtcs_event.lock);
>>> > -     DBG("end: %08x", crtc_mask);
>>> > -     priv->pending_crtcs &= ~crtc_mask;
>>> > -     wake_up_all_locked(&priv->pending_crtcs_event);
>>> > -     spin_unlock(&priv->pending_crtcs_event.lock);
>>> > -}
>>> > -
>>> > -static void commit_destroy(struct msm_commit *c)
>>> > -{
>>> > -     end_atomic(c->dev->dev_private, c->crtc_mask);
>>> > -     if (c->nonblock)
>>> > -             kfree(c);
>>> > -}
>>> > -
>>> >  static void msm_atomic_wait_for_commit_done(
>>> >               struct drm_device *dev,
>>> >               struct drm_atomic_state *old_state)
>>> > @@ -118,6 +73,10 @@ static void msm_atomic_commit_tail(struct
>>> > drm_atomic_state *state)
>>> >
>>> >       msm_atomic_wait_for_commit_done(dev, state);
>>> >
>>> > +     drm_atomic_helper_commit_hw_done(state);
>>> > +
>>> > +     drm_atomic_helper_wait_for_vblanks(dev, state);
>>> > +
>>> >       drm_atomic_helper_cleanup_planes(dev, state);
>>> >
>>> >       kms->funcs->complete_commit(kms, state);
>>> > @@ -126,109 +85,25 @@ static void msm_atomic_commit_tail(struct
>>> > drm_atomic_state *state)
>>> >  /* The (potentially) asynchronous part of the commit.  At this point
>>> >   * nothing can fail short of armageddon.
>>> >   */
>>> > -static void complete_commit(struct msm_commit *c)
>>> > +static void commit_tail(struct drm_atomic_state *state)
>>> >  {
>>> > -     struct drm_atomic_state *state = c->state;
>>> > -     struct drm_device *dev = state->dev;
>>> > +     drm_atomic_helper_wait_for_fences(state->dev, state, false);
>>> >
>>> > -     drm_atomic_helper_wait_for_fences(dev, state, false);
>>> > +     drm_atomic_helper_wait_for_dependencies(state);
>>> >
>>> >       msm_atomic_commit_tail(state);
>>> >
>>> > -     drm_atomic_state_put(state);
>>> > -}
>>> > -
>>> > -static void _msm_drm_commit_work_cb(struct kthread_work *work)
>>> > -{
>>> > -     struct msm_commit *commit =  NULL;
>>> > -
>>> > -     if (!work) {
>>> > -             DRM_ERROR("%s: Invalid commit work data!\n", __func__);
>>> > -             return;
>>> > -     }
>>> > -
>>> > -     commit = container_of(work, struct msm_commit, commit_work);
>>> > -
>>> > -     complete_commit(commit);
>>> > -
>>> > -     commit_destroy(commit);
>>> > -}
>>> > -
>>> > -static struct msm_commit *commit_init(struct drm_atomic_state *state,
>>> > -             bool nonblock)
>>> > -{
>>> > -     struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
>>> > +     drm_atomic_helper_commit_cleanup_done(state);
>>> >
>>> > -     if (!c)
>>> > -             return NULL;
>>> > -
>>> > -     c->dev = state->dev;
>>> > -     c->state = state;
>>> > -     c->nonblock = nonblock;
>>> > -
>>> > -     kthread_init_work(&c->commit_work, _msm_drm_commit_work_cb);
>>> > -
>>> > -     return c;
>>> > +     drm_atomic_state_put(state);
>>> >  }
>>> >
>>> > -/* Start display thread function */
>>> > -static void msm_atomic_commit_dispatch(struct drm_device *dev,
>>> > -             struct drm_atomic_state *state, struct msm_commit
>>> > *commit)
>>> > +static void commit_work(struct work_struct *work)
>>> >  {
>>> > -     struct msm_drm_private *priv = dev->dev_private;
>>> > -     struct drm_crtc *crtc = NULL;
>>> > -     struct drm_crtc_state *new_crtc_state = NULL;
>>> > -     int ret = -EINVAL, i = 0, j = 0;
>>> > -     bool nonblock;
>>> > -
>>> > -     /* cache since work will kfree commit in non-blocking case */
>>> > -     nonblock = commit->nonblock;
>>> > -
>>> > -     for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
>>> > -             for (j = 0; j < priv->num_crtcs; j++) {
>>> > -                     if (priv->disp_thread[j].crtc_id ==
>>> > -                                             crtc->base.id) {
>>> > -                             if (priv->disp_thread[j].thread) {
>>> > -                                     kthread_queue_work(
>>> > -
>>> > &priv->disp_thread[j].worker,
>>> > -
>>> > &commit->commit_work);
>>> Are there any known proposals floating around to support ASYNC commits
>>
>> for
>>>
>>> concurrent displays rendering at different FPS? The above kthread model
>>
>> is
>>>
>>> introduced when we faced some performance road blockers when a display
>>
>> has
>>>
>>> to wait for an ongoing display commit to complete.
>>
>>
>> I think people have discussed it, I'm not sure if there are any patches
>> floating
>> around. On the surface, it seems easy to just push the commit_work into
>> the crtc
>> commit and have one work item per crtc. However I think the problem is
>> that there
>> could be resources switching between crtcs for a given commit, or from one
>> commit
>> to the next, and synchronizing that becomes a Hard Problem.
>>
>> Perhaps I'm misunderstanding, but the start/end atomic functions serialize
>> the
>> incoming commits, right? So the only benefit the kthread provides is to
>> mitigate
>> any blocking calls made on one crtc from blocking a second crtc in the
>> same
>> commit?
>>
>> Sean
>
> I am not sure what level of resource (I assume hw blocks) switching we can
> expect between
> two active CRTC's on successive commits. With virtualization in play, the
> resources allocated to
> CRTC / encoder / Connector will remain attached to the components as long as
> the display is active.
> Planes (HW pipes) are one such entity which can move between the CRTC's
> frequently. Even
> with them planes, the hw assignment should remain valid until the plane is
> detached from
> a CRTC before attaching to the next one.

I think a good example to think about is virtualizing hwpipe<->plane
mapping, for example, when you need to re-assign hwpipes for the next
frame according to what capabilities are needed (yuv, scaling) or gang
up two hwpipes for wide buffer scanout (or re-use one hwpipe for two
planes).. in mdp5 we keep track of what hwpipes are in use by which
planes in driver global atomic state (I have some revived patches from
architt to convert this to driver private objs)..

With the atomic model we have serialization in the (to abuse some
terms) "top half" (ie. userspace calling into ioctl) by virtue of the
modeset locks.  But there is a second half to this.  Because we update
the new incoming global state object about what hwpipes are released
in atomic_check, if the incoming state is committed/swapped in the
"top half" we rely on this state being valid in the "bottom half" (in
this case the wq) before pushing the new state to the hw.. which
essentially forces us to serialize committing the state in the "bottom
half" so things happen in the same order as the "top half" intended.
Otherwise we could try to assign a hwpipe to a different crtc while it
is still scanning out for it's previous crtc.  If you have a 30Hz
display plus a 120Hz display, I guess this is a bit sub-optimal.

Maybe the answer is per-crtc wq's for commits plus some sort of
fencing scheme to stall things when there are cross-crtc dependencies
(ie. commit on crtc B depends on hwpipe released by commit on crtc A)?
 This way we don't block updates on the faster display when it isn't
required.  I'm not quite sure how that would work.  But perhaps at
least we could somehow allow out-of-order commits when two updates
don't touch any of the same state obj's.

(But I do think this is something we should discuss on dri-devel, and
I'd prefer do solve this in the atomic helpers, rather than having
userspace workaround different sets of bugs/quirks for each different
driver.  It really isn't something that is hw specific, so it doesn't
belong in the driver.)

BR,
-R


> "Start atomic" synchronizes the commit cycle for all the CRTC's by waiting
> for commit complete
> of all the previous frames. But per crtc kthreads allows the current frame
> commits to happen
> independently. For android, we needed this model as each commit thread need
> to wait for input
> plane fences before programming the hardware.
>
> Jeykumar S.
>
>>
>>> > -                                     /* only return zero if work is
>>> > -                                      * queued successfully.
>>> > -                                      */
>>> > -                                     ret = 0;
>>> > -                             } else {
>>> > -                                     DRM_ERROR(" Error for crtc_id:
>>> > %d\n",
>>> > -
>>> > priv->disp_thread[j].crtc_id);
>>> > -                             }
>>> > -                             break;
>>> > -                     }
>>> > -             }
>>> > -             /*
>>> > -              * TODO: handle cases where there will be more than
>>> > -              * one crtc per commit cycle. Remove this check then.
>>> > -              * Current assumption is there will be only one crtc
>>> > -              * per commit cycle.
>>> > -              */
>>> > -             if (j < priv->num_crtcs)
>>> > -                     break;
>>> > -     }
>>> > -
>>> > -     if (ret) {
>>> > -             /**
>>> > -              * this is not expected to happen, but at this point the
>>> > state
>>> > -              * has been swapped, but we couldn't dispatch to a crtc
>>> > thread.
>>> > -              * fallback now to a synchronous complete_commit to try
>>> > and
>>> > -              * ensure that SW and HW state don't get out of sync.
>>> > -              */
>>> > -             DRM_ERROR("failed to dispatch commit to any CRTC\n");
>>> > -             complete_commit(commit);
>>> > -     } else if (!nonblock) {
>>> > -             kthread_flush_work(&commit->commit_work);
>>> > -     }
>>> > -
>>> > -     /* free nonblocking commits in this context, after processing */
>>> > -     if (!nonblock)
>>> > -             kfree(commit);
>>> > +     struct drm_atomic_state *state = container_of(work,
>>> > +                                                   struct
>>> > drm_atomic_state,
>>> > +                                                   commit_work);
>>> > +     commit_tail(state);
>>> >  }
>>> >
>>> >  /**
>>> > @@ -247,17 +122,12 @@ int msm_atomic_commit(struct drm_device *dev,
>>> >               struct drm_atomic_state *state, bool nonblock)
>>> >  {
>>> >       struct msm_drm_private *priv = dev->dev_private;
>>> > -     struct msm_commit *c;
>>> >       struct drm_crtc *crtc;
>>> >       struct drm_crtc_state *crtc_state;
>>> >       struct drm_plane *plane;
>>> >       struct drm_plane_state *old_plane_state, *new_plane_state;
>>> >       int i, ret;
>>> >
>>> > -     ret = drm_atomic_helper_prepare_planes(dev, state);
>>> > -     if (ret)
>>> > -             return ret;
>>> > -
>>> >       /*
>>> >        * Note that plane->atomic_async_check() should fail if we need
>>> >        * to re-assign hwpipe or anything that touches global atomic
>>> > @@ -265,32 +135,30 @@ int msm_atomic_commit(struct drm_device *dev,
>>> >        * cases.
>>> >        */
>>> >       if (state->async_update) {
>>> > +             ret = drm_atomic_helper_prepare_planes(dev, state);
>>> > +             if (ret)
>>> > +                     return ret;
>>> > +
>>> >               drm_atomic_helper_async_commit(dev, state);
>>> >               drm_atomic_helper_cleanup_planes(dev, state);
>>> >               return 0;
>>> >       }
>>> >
>>> > -     c = commit_init(state, nonblock);
>>> > -     if (!c) {
>>> > -             ret = -ENOMEM;
>>> > -             goto error;
>>> > -     }
>>> > +     ret = drm_atomic_helper_setup_commit(state, nonblock);
>>> > +     if (ret)
>>> > +             return ret;
>>> >
>>> > -     /*
>>> > -      * Figure out what crtcs we have:
>>> > -      */
>>> > -     for_each_new_crtc_in_state(state, crtc, crtc_state, i)
>>> > -             c->crtc_mask |= drm_crtc_mask(crtc);
>>> > +     INIT_WORK(&state->commit_work, commit_work);
>>> >
>>> > -     /*
>>> > -      * Wait for pending updates on any of the same crtc's and then
>>> > -      * mark our set of crtc's as busy:
>>> > -      */
>>> > -     ret = start_atomic(dev->dev_private, c->crtc_mask);
>>> > +     ret = drm_atomic_helper_prepare_planes(dev, state);
>>> >       if (ret)
>>> > -             goto err_free;
>>> > +             return ret;
>>> >
>>> > -     BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
>>> > +     if (!nonblock) {
>>> > +             ret = drm_atomic_helper_wait_for_fences(dev, state,
>>> > true);
>>> > +             if (ret)
>>> > +                     goto error;
>>> > +     }
>>> >
>>> >       /*
>>> >        * This is the point of no return - everything below never fails
>>> > except
>>> > @@ -299,6 +167,8 @@ int msm_atomic_commit(struct drm_device *dev,
>>> >        *
>>> >        * swap driver private state while still holding state_lock
>>> >        */
>>> > +     BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
>>> > +
>>> >       if (to_kms_state(state)->state)
>>> >               priv->kms->funcs->swap_state(priv->kms, state);
>>> >
>>> > @@ -329,12 +199,13 @@ int msm_atomic_commit(struct drm_device *dev,
>>> >        */
>>> >
>>> >       drm_atomic_state_get(state);
>>> > -     msm_atomic_commit_dispatch(dev, state, c);
>>> > +     if (nonblock)
>>> > +             queue_work(system_unbound_wq, &state->commit_work);
>>> > +     else
>>> > +             commit_tail(state);
>>> >
>>> >       return 0;
>>> >
>>> > -err_free:
>>> > -     kfree(c);
>>> >  error:
>>> >       drm_atomic_helper_cleanup_planes(dev, state);
>>> >       return ret;
>>> > diff --git a/drivers/gpu/drm/msm/msm_drv.c
>>> > b/drivers/gpu/drm/msm/msm_drv.c
>>> > index eda4a2340f93..b354424cccb5 100644
>>> > --- a/drivers/gpu/drm/msm/msm_drv.c
>>> > +++ b/drivers/gpu/drm/msm/msm_drv.c
>>> > @@ -549,7 +549,6 @@ static int msm_drm_init(struct device *dev, struct
>>> > drm_driver *drv)
>>> >               goto mdss_init_fail;
>>> >
>>> >       priv->wq = alloc_ordered_workqueue("msm_drm", 0);
>>> > -     init_waitqueue_head(&priv->pending_crtcs_event);
>>> >
>>> >       INIT_LIST_HEAD(&priv->client_event_list);
>>> >       INIT_LIST_HEAD(&priv->inactive_list);
>>> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
>>> > b/drivers/gpu/drm/msm/msm_drv.h
>>> > index cf96a85f4b55..292496b682e8 100644
>>> > --- a/drivers/gpu/drm/msm/msm_drv.h
>>> > +++ b/drivers/gpu/drm/msm/msm_drv.h
>>> > @@ -536,10 +536,6 @@ struct msm_drm_private {
>>> >
>>> >       struct workqueue_struct *wq;
>>> >
>>> > -     /* crtcs pending async atomic updates: */
>>> > -     uint32_t pending_crtcs;
>>> > -     wait_queue_head_t pending_crtcs_event;
>>> > -
>>> >       unsigned int num_planes;
>>> >       struct drm_plane *planes[MAX_PLANES];
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
       [not found]                 ` <CAF6AEGvDZ8sWYwwbyPYcQZN6Ba01Gc7db724GeehF3cLY6d-XQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2018-03-02 14:56                   ` Sean Paul
  2018-03-09  1:08                     ` Jeykumar Sankaran
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-02 14:56 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, dri-devel, Sean Paul,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, Jeykumar Sankaran, freedreno,
	Kristian H. Kristensen

On Thu, Mar 01, 2018 at 07:37:10PM -0500, Rob Clark wrote:
> On Thu, Mar 1, 2018 at 3:37 PM,  <jsanka@codeaurora.org> wrote:
> > On 2018-03-01 07:27, Sean Paul wrote:
> >>
> >> On Wed, Feb 28, 2018 at 08:07:00PM -0800, jsanka@codeaurora.org wrote:
> >>>
> >>> On 2018-02-28 11:19, Sean Paul wrote:
> >>> > Moving further towards switching fully to the the atomic helpers, this
> >>> > patch removes the hand-rolled kthread nonblock commit code and uses
> >>
> >> the
> >>>
> >>> > atomic helpers commit_work model.
> >>> >
> >>> > There's still a lot of copypasta here, but it's still needed to
> >>> > facilitate the swap_state and prepare_fence private functions. These
> >>> > will be sorted out in a follow-on patch.
> >>> >
> >>> > Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
> >>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> >>> > ---
> >>> >  drivers/gpu/drm/msm/msm_atomic.c | 199
> >>
> >> ++++++-------------------------
> >>>
> >>> >  drivers/gpu/drm/msm/msm_drv.c    |   1 -
> >>> >  drivers/gpu/drm/msm/msm_drv.h    |   4 -
> >>> >  3 files changed, 35 insertions(+), 169 deletions(-)
> >>> >
> >>> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> >>> > b/drivers/gpu/drm/msm/msm_atomic.c
> >>> > index 3a18bd3dc215..7e54eb65d096 100644
> >>> > --- a/drivers/gpu/drm/msm/msm_atomic.c
> >>> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> >>> > @@ -21,51 +21,6 @@
> >>> >  #include "msm_gem.h"
> >>> >  #include "msm_fence.h"
> >>> >
> >>> > -struct msm_commit {
> >>> > -     struct drm_device *dev;
> >>> > -     struct drm_atomic_state *state;
> >>> > -     uint32_t crtc_mask;
> >>> > -     bool nonblock;
> >>> > -     struct kthread_work commit_work;
> >>> > -};
> >>> > -
> >>> > -/* block until specified crtcs are no longer pending update, and
> >>> > - * atomically mark them as pending update
> >>> > - */
> >>> > -static int start_atomic(struct msm_drm_private *priv, uint32_t
> >>> > crtc_mask)
> >>> > -{
> >>> > -     int ret;
> >>> > -
> >>> > -     spin_lock(&priv->pending_crtcs_event.lock);
> >>> > -     ret = wait_event_interruptible_locked(priv->pending_crtcs_event,
> >>> > -                     !(priv->pending_crtcs & crtc_mask));
> >>> > -     if (ret == 0) {
> >>> > -             DBG("start: %08x", crtc_mask);
> >>> > -             priv->pending_crtcs |= crtc_mask;
> >>> > -     }
> >>> > -     spin_unlock(&priv->pending_crtcs_event.lock);
> >>> > -
> >>> > -     return ret;
> >>> > -}
> >>> > -
> >>> > -/* clear specified crtcs (no longer pending update)
> >>> > - */
> >>> > -static void end_atomic(struct msm_drm_private *priv, uint32_t
> >>> > crtc_mask)
> >>> > -{
> >>> > -     spin_lock(&priv->pending_crtcs_event.lock);
> >>> > -     DBG("end: %08x", crtc_mask);
> >>> > -     priv->pending_crtcs &= ~crtc_mask;
> >>> > -     wake_up_all_locked(&priv->pending_crtcs_event);
> >>> > -     spin_unlock(&priv->pending_crtcs_event.lock);
> >>> > -}
> >>> > -
> >>> > -static void commit_destroy(struct msm_commit *c)
> >>> > -{
> >>> > -     end_atomic(c->dev->dev_private, c->crtc_mask);
> >>> > -     if (c->nonblock)
> >>> > -             kfree(c);
> >>> > -}
> >>> > -
> >>> >  static void msm_atomic_wait_for_commit_done(
> >>> >               struct drm_device *dev,
> >>> >               struct drm_atomic_state *old_state)
> >>> > @@ -118,6 +73,10 @@ static void msm_atomic_commit_tail(struct
> >>> > drm_atomic_state *state)
> >>> >
> >>> >       msm_atomic_wait_for_commit_done(dev, state);
> >>> >
> >>> > +     drm_atomic_helper_commit_hw_done(state);
> >>> > +
> >>> > +     drm_atomic_helper_wait_for_vblanks(dev, state);
> >>> > +
> >>> >       drm_atomic_helper_cleanup_planes(dev, state);
> >>> >
> >>> >       kms->funcs->complete_commit(kms, state);
> >>> > @@ -126,109 +85,25 @@ static void msm_atomic_commit_tail(struct
> >>> > drm_atomic_state *state)
> >>> >  /* The (potentially) asynchronous part of the commit.  At this point
> >>> >   * nothing can fail short of armageddon.
> >>> >   */
> >>> > -static void complete_commit(struct msm_commit *c)
> >>> > +static void commit_tail(struct drm_atomic_state *state)
> >>> >  {
> >>> > -     struct drm_atomic_state *state = c->state;
> >>> > -     struct drm_device *dev = state->dev;
> >>> > +     drm_atomic_helper_wait_for_fences(state->dev, state, false);
> >>> >
> >>> > -     drm_atomic_helper_wait_for_fences(dev, state, false);
> >>> > +     drm_atomic_helper_wait_for_dependencies(state);
> >>> >
> >>> >       msm_atomic_commit_tail(state);
> >>> >
> >>> > -     drm_atomic_state_put(state);
> >>> > -}
> >>> > -
> >>> > -static void _msm_drm_commit_work_cb(struct kthread_work *work)
> >>> > -{
> >>> > -     struct msm_commit *commit =  NULL;
> >>> > -
> >>> > -     if (!work) {
> >>> > -             DRM_ERROR("%s: Invalid commit work data!\n", __func__);
> >>> > -             return;
> >>> > -     }
> >>> > -
> >>> > -     commit = container_of(work, struct msm_commit, commit_work);
> >>> > -
> >>> > -     complete_commit(commit);
> >>> > -
> >>> > -     commit_destroy(commit);
> >>> > -}
> >>> > -
> >>> > -static struct msm_commit *commit_init(struct drm_atomic_state *state,
> >>> > -             bool nonblock)
> >>> > -{
> >>> > -     struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
> >>> > +     drm_atomic_helper_commit_cleanup_done(state);
> >>> >
> >>> > -     if (!c)
> >>> > -             return NULL;
> >>> > -
> >>> > -     c->dev = state->dev;
> >>> > -     c->state = state;
> >>> > -     c->nonblock = nonblock;
> >>> > -
> >>> > -     kthread_init_work(&c->commit_work, _msm_drm_commit_work_cb);
> >>> > -
> >>> > -     return c;
> >>> > +     drm_atomic_state_put(state);
> >>> >  }
> >>> >
> >>> > -/* Start display thread function */
> >>> > -static void msm_atomic_commit_dispatch(struct drm_device *dev,
> >>> > -             struct drm_atomic_state *state, struct msm_commit
> >>> > *commit)
> >>> > +static void commit_work(struct work_struct *work)
> >>> >  {
> >>> > -     struct msm_drm_private *priv = dev->dev_private;
> >>> > -     struct drm_crtc *crtc = NULL;
> >>> > -     struct drm_crtc_state *new_crtc_state = NULL;
> >>> > -     int ret = -EINVAL, i = 0, j = 0;
> >>> > -     bool nonblock;
> >>> > -
> >>> > -     /* cache since work will kfree commit in non-blocking case */
> >>> > -     nonblock = commit->nonblock;
> >>> > -
> >>> > -     for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> >>> > -             for (j = 0; j < priv->num_crtcs; j++) {
> >>> > -                     if (priv->disp_thread[j].crtc_id ==
> >>> > -                                             crtc->base.id) {
> >>> > -                             if (priv->disp_thread[j].thread) {
> >>> > -                                     kthread_queue_work(
> >>> > -
> >>> > &priv->disp_thread[j].worker,
> >>> > -
> >>> > &commit->commit_work);
> >>> Are there any known proposals floating around to support ASYNC commits
> >>
> >> for
> >>>
> >>> concurrent displays rendering at different FPS? The above kthread model
> >>
> >> is
> >>>
> >>> introduced when we faced some performance road blockers when a display
> >>
> >> has
> >>>
> >>> to wait for an ongoing display commit to complete.
> >>
> >>
> >> I think people have discussed it, I'm not sure if there are any patches
> >> floating
> >> around. On the surface, it seems easy to just push the commit_work into
> >> the crtc
> >> commit and have one work item per crtc. However I think the problem is
> >> that there
> >> could be resources switching between crtcs for a given commit, or from one
> >> commit
> >> to the next, and synchronizing that becomes a Hard Problem.
> >>
> >> Perhaps I'm misunderstanding, but the start/end atomic functions serialize
> >> the
> >> incoming commits, right? So the only benefit the kthread provides is to
> >> mitigate
> >> any blocking calls made on one crtc from blocking a second crtc in the
> >> same
> >> commit?
> >>
> >> Sean
> >
> > I am not sure what level of resource (I assume hw blocks) switching we can
> > expect between
> > two active CRTC's on successive commits. With virtualization in play, the
> > resources allocated to
> > CRTC / encoder / Connector will remain attached to the components as long as
> > the display is active.
> > Planes (HW pipes) are one such entity which can move between the CRTC's
> > frequently. Even
> > with them planes, the hw assignment should remain valid until the plane is
> > detached from
> > a CRTC before attaching to the next one.
> 
> I think a good example to think about is virtualizing hwpipe<->plane
> mapping, for example, when you need to re-assign hwpipes for the next
> frame according to what capabilities are needed (yuv, scaling) or gang
> up two hwpipes for wide buffer scanout (or re-use one hwpipe for two
> planes).. in mdp5 we keep track of what hwpipes are in use by which
> planes in driver global atomic state (I have some revived patches from
> architt to convert this to driver private objs)..
> 
> With the atomic model we have serialization in the (to abuse some
> terms) "top half" (ie. userspace calling into ioctl) by virtue of the
> modeset locks.  But there is a second half to this.  Because we update
> the new incoming global state object about what hwpipes are released
> in atomic_check, if the incoming state is committed/swapped in the
> "top half" we rely on this state being valid in the "bottom half" (in
> this case the wq) before pushing the new state to the hw.. which
> essentially forces us to serialize committing the state in the "bottom
> half" so things happen in the same order as the "top half" intended.
> Otherwise we could try to assign a hwpipe to a different crtc while it
> is still scanning out for it's previous crtc.  If you have a 30Hz
> display plus a 120Hz display, I guess this is a bit sub-optimal.

It's still bad even with displays refreshing at the same rate, the worst case
could halve the refresh rate if vblanks aren't in sync.

> 
> Maybe the answer is per-crtc wq's for commits plus some sort of
> fencing scheme to stall things when there are cross-crtc dependencies
> (ie. commit on crtc B depends on hwpipe released by commit on crtc A)?
>  This way we don't block updates on the faster display when it isn't
> required.  I'm not quite sure how that would work.  But perhaps at
> least we could somehow allow out-of-order commits when two updates
> don't touch any of the same state obj's.

Right, for "normal" updates, you could use the fast path. We already have
needs_modeset, so adding needs_sync wouldn't be too bad. I think I ran into this
with tegra back in Pixel C days and hacked in a per-crtc worker since the
resources were statically mapped. We'll probably run into this in CrOS as we
expand our explicit sync support in the compositor.

> 
> (But I do think this is something we should discuss on dri-devel, and
> I'd prefer do solve this in the atomic helpers, rather than having
> userspace workaround different sets of bugs/quirks for each different
> driver.  It really isn't something that is hw specific, so it doesn't
> belong in the driver.)

Agreed, this is a tricky bit of code and it would benefit from being used across
all drivers (as well as all drivers benefiting from it). At any rate, I can't
use multi-display on my development device right now, so I think we'll need to
defer for now.

Sean

> 
> BR,
> -R
> 
> 
> > "Start atomic" synchronizes the commit cycle for all the CRTC's by waiting
> > for commit complete
> > of all the previous frames. But per crtc kthreads allows the current frame
> > commits to happen
> > independently. For android, we needed this model as each commit thread need
> > to wait for input
> > plane fences before programming the hardware.
> >
> > Jeykumar S.
> >
> >>
> >>> > -                                     /* only return zero if work is
> >>> > -                                      * queued successfully.
> >>> > -                                      */
> >>> > -                                     ret = 0;
> >>> > -                             } else {
> >>> > -                                     DRM_ERROR(" Error for crtc_id:
> >>> > %d\n",
> >>> > -
> >>> > priv->disp_thread[j].crtc_id);
> >>> > -                             }
> >>> > -                             break;
> >>> > -                     }
> >>> > -             }
> >>> > -             /*
> >>> > -              * TODO: handle cases where there will be more than
> >>> > -              * one crtc per commit cycle. Remove this check then.
> >>> > -              * Current assumption is there will be only one crtc
> >>> > -              * per commit cycle.
> >>> > -              */
> >>> > -             if (j < priv->num_crtcs)
> >>> > -                     break;
> >>> > -     }
> >>> > -
> >>> > -     if (ret) {
> >>> > -             /**
> >>> > -              * this is not expected to happen, but at this point the
> >>> > state
> >>> > -              * has been swapped, but we couldn't dispatch to a crtc
> >>> > thread.
> >>> > -              * fallback now to a synchronous complete_commit to try
> >>> > and
> >>> > -              * ensure that SW and HW state don't get out of sync.
> >>> > -              */
> >>> > -             DRM_ERROR("failed to dispatch commit to any CRTC\n");
> >>> > -             complete_commit(commit);
> >>> > -     } else if (!nonblock) {
> >>> > -             kthread_flush_work(&commit->commit_work);
> >>> > -     }
> >>> > -
> >>> > -     /* free nonblocking commits in this context, after processing */
> >>> > -     if (!nonblock)
> >>> > -             kfree(commit);
> >>> > +     struct drm_atomic_state *state = container_of(work,
> >>> > +                                                   struct
> >>> > drm_atomic_state,
> >>> > +                                                   commit_work);
> >>> > +     commit_tail(state);
> >>> >  }
> >>> >
> >>> >  /**
> >>> > @@ -247,17 +122,12 @@ int msm_atomic_commit(struct drm_device *dev,
> >>> >               struct drm_atomic_state *state, bool nonblock)
> >>> >  {
> >>> >       struct msm_drm_private *priv = dev->dev_private;
> >>> > -     struct msm_commit *c;
> >>> >       struct drm_crtc *crtc;
> >>> >       struct drm_crtc_state *crtc_state;
> >>> >       struct drm_plane *plane;
> >>> >       struct drm_plane_state *old_plane_state, *new_plane_state;
> >>> >       int i, ret;
> >>> >
> >>> > -     ret = drm_atomic_helper_prepare_planes(dev, state);
> >>> > -     if (ret)
> >>> > -             return ret;
> >>> > -
> >>> >       /*
> >>> >        * Note that plane->atomic_async_check() should fail if we need
> >>> >        * to re-assign hwpipe or anything that touches global atomic
> >>> > @@ -265,32 +135,30 @@ int msm_atomic_commit(struct drm_device *dev,
> >>> >        * cases.
> >>> >        */
> >>> >       if (state->async_update) {
> >>> > +             ret = drm_atomic_helper_prepare_planes(dev, state);
> >>> > +             if (ret)
> >>> > +                     return ret;
> >>> > +
> >>> >               drm_atomic_helper_async_commit(dev, state);
> >>> >               drm_atomic_helper_cleanup_planes(dev, state);
> >>> >               return 0;
> >>> >       }
> >>> >
> >>> > -     c = commit_init(state, nonblock);
> >>> > -     if (!c) {
> >>> > -             ret = -ENOMEM;
> >>> > -             goto error;
> >>> > -     }
> >>> > +     ret = drm_atomic_helper_setup_commit(state, nonblock);
> >>> > +     if (ret)
> >>> > +             return ret;
> >>> >
> >>> > -     /*
> >>> > -      * Figure out what crtcs we have:
> >>> > -      */
> >>> > -     for_each_new_crtc_in_state(state, crtc, crtc_state, i)
> >>> > -             c->crtc_mask |= drm_crtc_mask(crtc);
> >>> > +     INIT_WORK(&state->commit_work, commit_work);
> >>> >
> >>> > -     /*
> >>> > -      * Wait for pending updates on any of the same crtc's and then
> >>> > -      * mark our set of crtc's as busy:
> >>> > -      */
> >>> > -     ret = start_atomic(dev->dev_private, c->crtc_mask);
> >>> > +     ret = drm_atomic_helper_prepare_planes(dev, state);
> >>> >       if (ret)
> >>> > -             goto err_free;
> >>> > +             return ret;
> >>> >
> >>> > -     BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> >>> > +     if (!nonblock) {
> >>> > +             ret = drm_atomic_helper_wait_for_fences(dev, state,
> >>> > true);
> >>> > +             if (ret)
> >>> > +                     goto error;
> >>> > +     }
> >>> >
> >>> >       /*
> >>> >        * This is the point of no return - everything below never fails
> >>> > except
> >>> > @@ -299,6 +167,8 @@ int msm_atomic_commit(struct drm_device *dev,
> >>> >        *
> >>> >        * swap driver private state while still holding state_lock
> >>> >        */
> >>> > +     BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> >>> > +
> >>> >       if (to_kms_state(state)->state)
> >>> >               priv->kms->funcs->swap_state(priv->kms, state);
> >>> >
> >>> > @@ -329,12 +199,13 @@ int msm_atomic_commit(struct drm_device *dev,
> >>> >        */
> >>> >
> >>> >       drm_atomic_state_get(state);
> >>> > -     msm_atomic_commit_dispatch(dev, state, c);
> >>> > +     if (nonblock)
> >>> > +             queue_work(system_unbound_wq, &state->commit_work);
> >>> > +     else
> >>> > +             commit_tail(state);
> >>> >
> >>> >       return 0;
> >>> >
> >>> > -err_free:
> >>> > -     kfree(c);
> >>> >  error:
> >>> >       drm_atomic_helper_cleanup_planes(dev, state);
> >>> >       return ret;
> >>> > diff --git a/drivers/gpu/drm/msm/msm_drv.c
> >>> > b/drivers/gpu/drm/msm/msm_drv.c
> >>> > index eda4a2340f93..b354424cccb5 100644
> >>> > --- a/drivers/gpu/drm/msm/msm_drv.c
> >>> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> >>> > @@ -549,7 +549,6 @@ static int msm_drm_init(struct device *dev, struct
> >>> > drm_driver *drv)
> >>> >               goto mdss_init_fail;
> >>> >
> >>> >       priv->wq = alloc_ordered_workqueue("msm_drm", 0);
> >>> > -     init_waitqueue_head(&priv->pending_crtcs_event);
> >>> >
> >>> >       INIT_LIST_HEAD(&priv->client_event_list);
> >>> >       INIT_LIST_HEAD(&priv->inactive_list);
> >>> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
> >>> > b/drivers/gpu/drm/msm/msm_drv.h
> >>> > index cf96a85f4b55..292496b682e8 100644
> >>> > --- a/drivers/gpu/drm/msm/msm_drv.h
> >>> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> >>> > @@ -536,10 +536,6 @@ struct msm_drm_private {
> >>> >
> >>> >       struct workqueue_struct *wq;
> >>> >
> >>> > -     /* crtcs pending async atomic updates: */
> >>> > -     uint32_t pending_crtcs;
> >>> > -     wait_queue_head_t pending_crtcs_event;
> >>> > -
> >>> >       unsigned int num_planes;
> >>> >       struct drm_plane *planes[MAX_PLANES];

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 01/11] drm/msm: Skip seamless disables in crtc/encoder
  2018-02-28 19:18   ` [DPU PATCH 01/11] drm/msm: Skip seamless disables in crtc/encoder Sean Paul
@ 2018-03-03  0:04     ` jsanka
       [not found]       ` <d51bfdafccd143ee258fc995a7cafecc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: jsanka @ 2018-03-03  0:04 UTC (permalink / raw)
  To: Sean Paul; +Cc: linux-arm-msm, abhinavk, dri-devel, hoegsberg, freedreno

On 2018-02-28 11:18, Sean Paul wrote:
> Instead of duplicating whole swaths of atomic helper functions (which
> are already out-of-date), just skip the encoder/crtc disables in the
> .disable hooks.
> 
> Change-Id: I7bd9183ae60624204fb1de9550656b776efc7202
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Can you consider getting rid of these checks?

> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   8 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   8 +
>  drivers/gpu/drm/msm/msm_atomic.c            | 185 +-------------------
>  3 files changed, 17 insertions(+), 184 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 3cdf1e3d9d96..a3ab6ed2bf1d 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -3393,6 +3393,7 @@ static void dpu_crtc_disable(struct drm_crtc 
> *crtc)
>  {
>  	struct dpu_crtc *dpu_crtc;
>  	struct dpu_crtc_state *cstate;
> +	struct drm_display_mode *mode;
>  	struct drm_encoder *encoder;
>  	struct msm_drm_private *priv;
>  	unsigned long flags;
> @@ -3407,8 +3408,15 @@ static void dpu_crtc_disable(struct drm_crtc 
> *crtc)
>  	}
>  	dpu_crtc = to_dpu_crtc(crtc);
>  	cstate = to_dpu_crtc_state(crtc->state);
> +	mode = &cstate->base.adjusted_mode;
>  	priv = crtc->dev->dev_private;
> 
> +	if (msm_is_mode_seamless(mode) || msm_is_mode_seamless_vrr(mode)
> ||
> +	    msm_is_mode_seamless_dms(mode)) {
> +		DPU_DEBUG("Seamless mode is being applied, skip
> disable\n");
> +		return;
> +	}
> +
Another topic of discussion which should be brought up with dri-devel.

May not be common in PC world, but there are a handful of mobile OEM's
using panels which supports more than one resolution. Primary use cases
involve "seamless" switching to optimized display resolution when
streaming content changes resolutions or rendering lossless data.

Jeykumar S.

>  	DPU_DEBUG("crtc%d\n", crtc->base.id);
> 
>  	if (dpu_kms_is_suspend_state(crtc->dev))
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 3d168fa09f3f..28ceb589ee40 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -2183,6 +2183,7 @@ static void dpu_encoder_virt_disable(struct
> drm_encoder *drm_enc)
>  	struct dpu_encoder_virt *dpu_enc = NULL;
>  	struct msm_drm_private *priv;
>  	struct dpu_kms *dpu_kms;
> +	struct drm_display_mode *mode;
>  	int i = 0;
> 
>  	if (!drm_enc) {
> @@ -2196,6 +2197,13 @@ static void dpu_encoder_virt_disable(struct
> drm_encoder *drm_enc)
>  		return;
>  	}
> 
> +	mode = &drm_enc->crtc->state->adjusted_mode;
> +	if (msm_is_mode_seamless(mode) || msm_is_mode_seamless_vrr(mode)
> ||
> +	    msm_is_mode_seamless_dms(mode)) {
> +		DPU_DEBUG("Seamless mode is being applied, skip
> disable\n");
> +		return;
> +	}
> +
>  	dpu_enc = to_dpu_encoder_virt(drm_enc);
>  	DPU_DEBUG_ENC(dpu_enc, "\n");
> 
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> b/drivers/gpu/drm/msm/msm_atomic.c
> index 46536edb72ee..5cfb80345052 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -84,189 +84,6 @@ static void msm_atomic_wait_for_commit_done(
>  	}
>  }
> 
> -static void
> -msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state
> *old_state)
> -{
> -	struct drm_connector *connector;
> -	struct drm_connector_state *old_conn_state, *new_conn_state;
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
> -	int i;
> -
> -	for_each_oldnew_connector_in_state(old_state, connector,
> old_conn_state, new_conn_state, i) {
> -		const struct drm_encoder_helper_funcs *funcs;
> -		struct drm_encoder *encoder;
> -		struct drm_crtc_state *old_crtc_state;
> -		unsigned int crtc_idx;
> -
> -		/*
> -		 * Shut down everything that's in the changeset and
> currently
> -		 * still on. So need to check the old, saved state.
> -		 */
> -		if (!old_conn_state->crtc)
> -			continue;
> -
> -		crtc_idx = drm_crtc_index(old_conn_state->crtc);
> -		old_crtc_state = drm_atomic_get_old_crtc_state(old_state,
> -
> old_conn_state->crtc);
> -
> -		if (!old_crtc_state->active ||
> -
> !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
> -			continue;
> -
> -		encoder = old_conn_state->best_encoder;
> -
> -		/* We shouldn't get this far if we didn't previously have
> -		 * an encoder.. but WARN_ON() rather than explode.
> -		 */
> -		if (WARN_ON(!encoder))
> -			continue;
> -
> -		if (msm_is_mode_seamless(
> -			&connector->encoder->crtc->state->mode) ||
> -			msm_is_mode_seamless_vrr(
> -			&connector->encoder->crtc->state->adjusted_mode))
> -			continue;
> -
> -		if (msm_is_mode_seamless_dms(
> -			&connector->encoder->crtc->state->adjusted_mode))
> -			continue;
> -
> -		funcs = encoder->helper_private;
> -
> -		DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n",
> -				 encoder->base.id, encoder->name);
> -
> -		/*
> -		 * Each encoder has at most one connector (since we always
> steal
> -		 * it away), so we won't call disable hooks twice.
> -		 */
> -		drm_bridge_disable(encoder->bridge);
> -
> -		/* Right function depends upon target state. */
> -		if (new_conn_state->crtc && funcs->prepare)
> -			funcs->prepare(encoder);
> -		else if (funcs->disable)
> -			funcs->disable(encoder);
> -		else
> -			funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
> -
> -		drm_bridge_post_disable(encoder->bridge);
> -	}
> -
> -	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
> new_crtc_state, i) {
> -		const struct drm_crtc_helper_funcs *funcs;
> -
> -		/* Shut down everything that needs a full modeset. */
> -		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
> -			continue;
> -
> -		if (!old_crtc_state->active)
> -			continue;
> -
> -		if (msm_is_mode_seamless(&crtc->state->mode) ||
> -
> msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode))
> -			continue;
> -
> -		if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode))
> -			continue;
> -
> -		funcs = crtc->helper_private;
> -
> -		DRM_DEBUG_ATOMIC("disabling [CRTC:%d]\n",
> -				 crtc->base.id);
> -
> -		/* Right function depends upon target state. */
> -		if (new_crtc_state->enable && funcs->prepare)
> -			funcs->prepare(crtc);
> -		else if (funcs->disable)
> -			funcs->disable(crtc);
> -		else
> -			funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
> -	}
> -}
> -
> -static void
> -msm_crtc_set_mode(struct drm_device *dev, struct drm_atomic_state
> *old_state)
> -{
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *new_crtc_state;
> -	struct drm_connector *connector;
> -	struct drm_connector_state *new_conn_state;
> -	int i;
> -
> -	for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
> -		const struct drm_crtc_helper_funcs *funcs;
> -
> -		if (!new_crtc_state->mode_changed)
> -			continue;
> -
> -		funcs = crtc->helper_private;
> -
> -		if (new_crtc_state->enable && funcs->mode_set_nofb) {
> -			DRM_DEBUG_ATOMIC("modeset on [CRTC:%d]\n",
> -					 crtc->base.id);
> -
> -			funcs->mode_set_nofb(crtc);
> -		}
> -	}
> -
> -	for_each_new_connector_in_state(old_state, connector,
> new_conn_state, i) {
> -		const struct drm_encoder_helper_funcs *funcs;
> -		struct drm_crtc_state *new_crtc_state;
> -		struct drm_encoder *encoder;
> -		struct drm_display_mode *mode, *adjusted_mode;
> -
> -		if (!new_conn_state->best_encoder)
> -			continue;
> -
> -		encoder = new_conn_state->best_encoder;
> -		funcs = encoder->helper_private;
> -		new_crtc_state = new_conn_state->crtc->state;
> -		mode = &new_crtc_state->mode;
> -		adjusted_mode = &new_crtc_state->adjusted_mode;
> -
> -		if (!new_crtc_state->mode_changed)
> -			continue;
> -
> -		DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n",
> -				 encoder->base.id, encoder->name);
> -
> -		/*
> -		 * Each encoder has at most one connector (since we always
> steal
> -		 * it away), so we won't call mode_set hooks twice.
> -		 */
> -		if (funcs->mode_set)
> -			funcs->mode_set(encoder, mode, adjusted_mode);
> -
> -		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
> -	}
> -}
> -
> -/**
> - * msm_atomic_helper_commit_modeset_disables - modeset commit to 
> disable
> outputs
> - * @dev: DRM device
> - * @old_state: atomic state object with old state structures
> - *
> - * This function shuts down all the outputs that need to be shut down 
> and
> - * prepares them (if required) with the new mode.
> - *
> - * For compatibility with legacy crtc helpers this should be called
> before
> - * drm_atomic_helper_commit_planes(), which is what the default commit
> function
> - * does. But drivers with different needs can group the modeset 
> commits
> together
> - * and do the plane commits at the end. This is useful for drivers 
> doing
> runtime
> - * PM since planes updates then only happen when the CRTC is actually
> enabled.
> - */
> -void msm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
> -		struct drm_atomic_state *old_state)
> -{
> -	msm_disable_outputs(dev, old_state);
> -
> -	drm_atomic_helper_update_legacy_modeset_state(dev, old_state);
> -
> -	msm_crtc_set_mode(dev, old_state);
> -}
> -
>  /**
>   * msm_atomic_helper_commit_modeset_enables - modeset commit to enable
> outputs
>   * @dev: DRM device
> @@ -406,7 +223,7 @@ static void complete_commit(struct msm_commit *c)
> 
>  	kms->funcs->prepare_commit(kms, state);
> 
> -	msm_atomic_helper_commit_modeset_disables(dev, state);
> +	drm_atomic_helper_commit_modeset_disables(dev, state);
> 
>  	drm_atomic_helper_commit_planes(dev, state, 0);
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 04/11] drm/msm: Move implicit sync fence handling to prepare_fb
       [not found]     ` <20180228191906.185417-5-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-03  0:20       ` jsanka-sgV2jX0FEOL9JmXXK+q4OQ
  0 siblings, 0 replies; 49+ messages in thread
From: jsanka-sgV2jX0FEOL9JmXXK+q4OQ @ 2018-03-03  0:20 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-02-28 11:18, Sean Paul wrote:
> This is another piece that can be moved out of atomic to facilitate 
> using
> the atomic helpers.
> 
> Change-Id: I6dc3c4e5df508942bbc378c73a44e46e511b8469
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>

> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c |  8 ++++++++
>  drivers/gpu/drm/msm/msm_atomic.c          | 13 -------------
>  2 files changed, 8 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> index 834dcc0bfefd..29e72b39fd72 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> @@ -2720,6 +2720,8 @@ static int dpu_plane_prepare_fb(struct drm_plane
> *plane,
>  	struct dpu_plane_rot_state *new_rstate;
>  	struct dpu_hw_fmt_layout layout;
>  	struct msm_gem_address_space *aspace;
> +	struct msm_gem_object *msm_obj;
> +	struct dma_fence *fence;
>  	int ret;
> 
>  	if (!new_state->fb)
> @@ -2761,6 +2763,12 @@ static int dpu_plane_prepare_fb(struct drm_plane
> *plane,
>  		return ret;
>  	}
> 
> +	/* To support implicit sync, set a fence on the plane if
> appropriate */
> +	msm_obj = to_msm_bo(msm_framebuffer_bo(fb, 0));
> +	fence = reservation_object_get_excl_rcu(msm_obj->resv);
> +	if (fence)
> +		drm_atomic_set_fence_for_plane(new_state, fence);
> +
>  	return 0;
>  }
> 
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> b/drivers/gpu/drm/msm/msm_atomic.c
> index eb2ccda5da0f..3a18bd3dc215 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -282,19 +282,6 @@ int msm_atomic_commit(struct drm_device *dev,
>  	for_each_new_crtc_in_state(state, crtc, crtc_state, i)
>  		c->crtc_mask |= drm_crtc_mask(crtc);
> 
> -	/*
> -	 * Figure out what fence to wait for:
> -	 */
> -	for_each_oldnew_plane_in_state(state, plane, old_plane_state,
> new_plane_state, i) {
> -		if ((new_plane_state->fb != old_plane_state->fb) &&
> new_plane_state->fb) {
> -			struct drm_gem_object *obj =
> msm_framebuffer_bo(new_plane_state->fb, 0);
> -			struct msm_gem_object *msm_obj = to_msm_bo(obj);
> -			struct dma_fence *fence =
> reservation_object_get_excl_rcu(msm_obj->resv);
> -
> -			drm_atomic_set_fence_for_plane(new_plane_state,
> fence);
> -		}
> -	}
> -
>  	/*
>  	 * Wait for pending updates on any of the same crtc's and then
>  	 * mark our set of crtc's as busy:
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 08/11] drm/msm: Remove hand-rolled out fences
       [not found]     ` <20180228191906.185417-9-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-03  0:44       ` Jeykumar Sankaran
       [not found]         ` <1a1c79ddb6ddabbc72e4624b53460188-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-03  0:44 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-02-28 11:19, Sean Paul wrote:
> Remove release/output/retire fences from the dpu driver. These are
> already available via drm core's OUT_FENCE property.
> 
> Change-Id: Id4238d0b5457f2c8ee2e87bb7814e1850a573623
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c |  66 +------
>  drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h |  23 ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      | 178 +++---------------
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h      |  28 ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |   3 -
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   4 +-
>  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 -
>  .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |  73 +------
>  .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |  19 --
>  .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   |  12 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c       |  30 ---
>  drivers/gpu/drm/msm/msm_drv.h                 |   3 -
>  12 files changed, 36 insertions(+), 411 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> index 57b8627ef418..cc5bfa862cb7 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> @@ -521,7 +521,6 @@ static void dpu_connector_destroy(struct 
> drm_connector
> *connector)
>  		backlight_device_unregister(c_conn->bl_device);
>  	drm_connector_unregister(connector);
>  	mutex_destroy(&c_conn->lock);
> -	dpu_fence_deinit(&c_conn->retire_fence);
>  	drm_connector_cleanup(connector);
>  	kfree(c_conn);
>  }
> @@ -906,12 +905,9 @@ static int 
> dpu_connector_atomic_get_property(struct
> drm_connector *connector,
>  	c_state = to_dpu_connector_state(state);
> 
>  	idx = msm_property_index(&c_conn->property_info, property);
> -	if (idx == CONNECTOR_PROP_RETIRE_FENCE)
> -		rc = dpu_fence_create(&c_conn->retire_fence, val, 0);
> -	else
> -		/* get cached property value */
> -		rc = msm_property_atomic_get(&c_conn->property_info,
> -				&c_state->property_state, property, val);
> +	/* get cached property value */
> +	rc = msm_property_atomic_get(&c_conn->property_info,
> +			&c_state->property_state, property, val);
> 
>  	/* allow for custom override */
>  	if (c_conn->ops.get_property)
> @@ -923,39 +919,6 @@ static int 
> dpu_connector_atomic_get_property(struct
> drm_connector *connector,
>  	return rc;
>  }
> 
> -void dpu_connector_prepare_fence(struct drm_connector *connector)
> -{
> -	if (!connector) {
> -		DPU_ERROR("invalid connector\n");
> -		return;
> -	}
> -
> -	dpu_fence_prepare(&to_dpu_connector(connector)->retire_fence);
> -}
> -
> -void dpu_connector_complete_commit(struct drm_connector *connector,
> -		ktime_t ts)
> -{
> -	if (!connector) {
> -		DPU_ERROR("invalid connector\n");
> -		return;
> -	}
> -
> -	/* signal connector's retire fence */
> -	dpu_fence_signal(&to_dpu_connector(connector)->retire_fence, ts,
> false);
> -}
> -
> -void dpu_connector_commit_reset(struct drm_connector *connector, 
> ktime_t
> ts)
> -{
> -	if (!connector) {
> -		DPU_ERROR("invalid connector\n");
> -		return;
> -	}
> -
> -	/* signal connector's retire fence */
> -	dpu_fence_signal(&to_dpu_connector(connector)->retire_fence, ts,
> true);
> -}
> -
>  static enum drm_connector_status
>  dpu_connector_detect(struct drm_connector *connector, bool force)
>  {
> @@ -1214,26 +1177,19 @@ struct drm_connector *dpu_connector_init(struct
> drm_device *dev,
>  			"conn%u",
>  			c_conn->base.base.id);
> 
> -	rc = dpu_fence_init(&c_conn->retire_fence, c_conn->name,
> -			c_conn->base.base.id);
> -	if (rc) {
> -		DPU_ERROR("failed to init fence, %d\n", rc);
> -		goto error_cleanup_conn;
> -	}
> -
>  	mutex_init(&c_conn->lock);
> 
>  	rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder);
>  	if (rc) {
>  		DPU_ERROR("failed to attach encoder to connector, %d\n",
> rc);
> -		goto error_cleanup_fence;
> +		goto error_cleanup_conn;
>  	}
> 
>  #ifdef CONFIG_DRM_MSM_DSI_STAGING
>  	rc = dpu_backlight_setup(c_conn, dev);
>  	if (rc) {
>  		DPU_ERROR("failed to setup backlight, rc=%d\n", rc);
> -		goto error_cleanup_fence;
> +		goto error_cleanup_conn;
>  	}
>  #endif
> 
> @@ -1248,7 +1204,7 @@ struct drm_connector *dpu_connector_init(struct
> drm_device *dev,
>  		if (!info) {
>  			DPU_ERROR("failed to allocate info buffer\n");
>  			rc = -ENOMEM;
> -			goto error_cleanup_fence;
> +			goto error_cleanup_conn;
>  		}
> 
>  		dpu_kms_info_reset(info);
> @@ -1256,7 +1212,7 @@ struct drm_connector *dpu_connector_init(struct
> drm_device *dev,
>  		if (rc) {
>  			DPU_ERROR("post-init failed, %d\n", rc);
>  			kfree(info);
> -			goto error_cleanup_fence;
> +			goto error_cleanup_conn;
>  		}
> 
>  		msm_property_install_blob(&c_conn->property_info,
> @@ -1310,10 +1266,6 @@ struct drm_connector *dpu_connector_init(struct
> drm_device *dev,
>  				&c_conn->property_info, "dpu_drm_roi_v1",
> 0x0,
>  				0, ~0, 0, CONNECTOR_PROP_ROI_V1);
>  	}
> -
> -	msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
> -			0x0, 0, INR_OPEN_MAX, 0,
> CONNECTOR_PROP_RETIRE_FENCE);
> -
>  	msm_property_install_range(&c_conn->property_info, "autorefresh",
>  			0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0,
>  			CONNECTOR_PROP_AUTOREFRESH);
> @@ -1354,10 +1306,8 @@ struct drm_connector *dpu_connector_init(struct
> drm_device *dev,
>  		drm_property_blob_put(c_conn->blob_dither);
> 
>  	msm_property_destroy(&c_conn->property_info);
> -error_cleanup_fence:
> -	mutex_destroy(&c_conn->lock);
> -	dpu_fence_deinit(&c_conn->retire_fence);
>  error_cleanup_conn:
> +	mutex_destroy(&c_conn->lock);
>  	drm_connector_cleanup(&c_conn->base);
>  error_free_conn:
>  	kfree(c_conn);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> index f6f4837d1359..fdb4d8766549 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> @@ -21,7 +21,6 @@
>  #include "msm_drv.h"
>  #include "msm_prop.h"
>  #include "dpu_kms.h"
> -#include "dpu_fence.h"
> 
>  #define DPU_CONNECTOR_NAME_SIZE	16
> 
> @@ -247,7 +246,6 @@ struct dpu_connector_evt {
>   * @mmu_unsecure: MMU id for unsecure buffers
>   * @name: ASCII name of connector
>   * @lock: Mutex lock object for this structure
> - * @retire_fence: Retire fence context reference
>   * @ops: Local callback function pointer table
>   * @dpms_mode: DPMS property setting from user space
>   * @lp_mode: LP property setting from user space
> @@ -274,7 +272,6 @@ struct dpu_connector {
>  	char name[DPU_CONNECTOR_NAME_SIZE];
> 
>  	struct mutex lock;
> -	struct dpu_fence_context retire_fence;
>  	struct dpu_connector_ops ops;
>  	int dpms_mode;
>  	int lp_mode;
> @@ -447,26 +444,6 @@ struct drm_connector *dpu_connector_init(struct
> drm_device *dev,
>  		int connector_poll,
>  		int connector_type);
> 
> -/**
> - * dpu_connector_prepare_fence - prepare fence support for current 
> commit
> - * @connector: Pointer to drm connector object
> - */
> -void dpu_connector_prepare_fence(struct drm_connector *connector);
> -
> -/**
> - * dpu_connector_complete_commit - signal completion of current commit
> - * @connector: Pointer to drm connector object
> - * @ts: timestamp to be updated in the fence signalling
> - */
> -void dpu_connector_complete_commit(struct drm_connector *connector,
> ktime_t ts);
> -
> -/**
> - * dpu_connector_commit_reset - reset the completion signal
> - * @connector: Pointer to drm connector object
> - * @ts: timestamp to be updated in the fence signalling
> - */
> -void dpu_connector_commit_reset(struct drm_connector *connector, 
> ktime_t
> ts);
> -
>  /**
>   * dpu_connector_get_info - query display specific information
>   * @connector: Pointer to drm connector object
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index a261021e5deb..2d44989ade7a 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -629,7 +629,6 @@ static void dpu_crtc_destroy(struct drm_crtc *crtc)
>  	dpu_cp_crtc_destroy_properties(crtc);
>  	_dpu_crtc_destroy_dest_scaler(dpu_crtc);
> 
> -	dpu_fence_deinit(&dpu_crtc->output_fence);
>  	_dpu_crtc_deinit_events(dpu_crtc);
> 
>  	drm_crtc_cleanup(crtc);
> @@ -1671,65 +1670,6 @@ static void _dpu_crtc_dest_scaler_setup(struct
> drm_crtc *crtc)
>  	}
>  }
> 
> -void dpu_crtc_prepare_commit(struct drm_crtc *crtc,
> -		struct drm_crtc_state *old_state)
> -{
> -	struct drm_device *dev;
> -	struct dpu_crtc *dpu_crtc;
> -	struct dpu_crtc_state *cstate;
> -	struct drm_connector *conn;
> -	struct drm_connector_list_iter conn_iter;
> -	struct dpu_crtc_retire_event *retire_event = NULL;
> -	unsigned long flags;
> -	int i;
> -
> -	if (!crtc || !crtc->state) {
> -		DPU_ERROR("invalid crtc\n");
> -		return;
> -	}
> -
> -	dev = crtc->dev;
> -	dpu_crtc = to_dpu_crtc(crtc);
> -	cstate = to_dpu_crtc_state(crtc->state);
> -	DPU_EVT32_VERBOSE(DRMID(crtc));
> -
> -	/* identify connectors attached to this crtc */
> -	cstate->num_connectors = 0;
> -
> -	drm_connector_list_iter_begin(dev, &conn_iter);
> -	drm_for_each_connector_iter(conn, &conn_iter)
> -		if (conn->state && conn->state->crtc == crtc &&
> -				cstate->num_connectors < MAX_CONNECTORS) {
> -			cstate->connectors[cstate->num_connectors++] =
> conn;
> -			dpu_connector_prepare_fence(conn);
> -		}
> -	drm_connector_list_iter_end(&conn_iter);
> -
> -	for (i = 0; i < DPU_CRTC_FRAME_EVENT_SIZE; i++) {
> -		retire_event = &dpu_crtc->retire_events[i];
> -		if (list_empty(&retire_event->list))
> -			break;
> -		retire_event = NULL;
> -	}
> -
> -	if (retire_event) {
> -		retire_event->num_connectors = cstate->num_connectors;
> -		for (i = 0; i < cstate->num_connectors; i++)
> -			retire_event->connectors[i] =
> cstate->connectors[i];
> -
> -		spin_lock_irqsave(&dpu_crtc->spin_lock, flags);
> -		list_add_tail(&retire_event->list,
> -
> &dpu_crtc->retire_event_list);
> -		spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
> -	} else {
> -		DPU_ERROR("crtc%d retire event overflow\n",
> crtc->base.id);
> -		DPU_EVT32(DRMID(crtc), DPU_EVTLOG_ERROR);
> -	}
> -
> -	/* prepare main output fence */
> -	dpu_fence_prepare(&dpu_crtc->output_fence);
> -}
> -
>  /**
>   *  _dpu_crtc_complete_flip - signal pending page_flip events
>   * Any pending vblank events are added to the vblank_event_list
> @@ -1799,41 +1739,6 @@ static void dpu_crtc_vblank_cb(void *data)
>  	DPU_EVT32_VERBOSE(DRMID(crtc));
>  }
> 
> -static void _dpu_crtc_retire_event(struct drm_crtc *crtc, ktime_t ts)
> -{
> -	struct dpu_crtc_retire_event *retire_event;
> -	struct dpu_crtc *dpu_crtc;
> -	unsigned long flags;
> -	int i;
> -
> -	if (!crtc) {
> -		DPU_ERROR("invalid param\n");
> -		return;
> -	}
> -
> -	dpu_crtc = to_dpu_crtc(crtc);
> -	spin_lock_irqsave(&dpu_crtc->spin_lock, flags);
> -	retire_event =
> list_first_entry_or_null(&dpu_crtc->retire_event_list,
> -				struct dpu_crtc_retire_event, list);
> -	if (retire_event)
> -		list_del_init(&retire_event->list);
> -	spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
> -
> -	if (!retire_event) {
> -		DPU_ERROR("crtc%d retire event without kickoff\n",
> -
> crtc->base.id);
> -		DPU_EVT32(DRMID(crtc), DPU_EVTLOG_ERROR);
> -		return;
> -	}
> -
> -	DPU_ATRACE_BEGIN("signal_retire_fence");
> -	for (i = 0; (i < retire_event->num_connectors) &&
> -					retire_event->connectors[i]; ++i)
> -		dpu_connector_complete_commit(
> -					retire_event->connectors[i], ts);
> -	DPU_ATRACE_END("signal_retire_fence");
> -}
> -
>  /* _dpu_crtc_idle_notify - signal idle timeout to client */
>  static void _dpu_crtc_idle_notify(struct dpu_crtc *dpu_crtc)
>  {
> @@ -1945,16 +1850,6 @@ static void dpu_crtc_frame_event_work(struct
> kthread_work *work)
>  			frame_done = true;
>  	}
> 
> -	if (fevent->event & DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE)
> {
> -		DPU_ATRACE_BEGIN("signal_release_fence");
> -		dpu_fence_signal(&dpu_crtc->output_fence, fevent->ts,
> false);
> -		DPU_ATRACE_END("signal_release_fence");
> -	}
> -
> -	if (fevent->event & DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE)
> -		/* this api should be called without spin_lock */
> -		_dpu_crtc_retire_event(crtc, fevent->ts);
> -
>  	if (fevent->event & DPU_ENCODER_FRAME_EVENT_PANEL_DEAD)
>  		DPU_ERROR("crtc%d ts:%lld received panel dead event\n",
>  				crtc->base.id, ktime_to_ns(fevent->ts));
> @@ -1971,11 +1866,11 @@ static void dpu_crtc_frame_event_work(struct
> kthread_work *work)
>  /*
>   * dpu_crtc_frame_event_cb - crtc frame event callback API. CRTC 
> module
>   * registers this API to encoder for all frame event callbacks like
> - * release_fence, retire_fence, frame_error, frame_done, idle_timeout,
> - * etc. Encoder may call different events from different context - 
> IRQ,
> - * user thread, commit_thread, etc. Each event should be carefully
> - * reviewed and should be processed in proper task context to avoid
> scheduling
> - * delay or properly manage the irq context's bottom half processing.
> + * frame_error, frame_done, idle_timeout, etc. Encoder may call 
> different
> events
> + * from different context - IRQ, user thread, commit_thread, etc. Each
> event
> + * should be carefully reviewed and should be processed in proper task
> context
> + * to avoid schedulin delay or properly manage the irq context's 
> bottom
> half
> + * processing.
>   */
>  static void dpu_crtc_frame_event_cb(void *data, u32 event)
>  {
> @@ -3484,14 +3379,6 @@ static void dpu_crtc_disable(struct drm_crtc 
> *crtc)
>  		dpu_power_handle_unregister_event(&priv->phandle,
>  				dpu_crtc->power_event);
> 
> -	/**
> -	 * All callbacks are unregistered and frame done waits are
> complete
> -	 * at this point. No buffers are accessed by hardware.
> -	 * reset the fence timeline if there is any issue.
> -	 */
> -	dpu_fence_signal(&dpu_crtc->output_fence, ktime_get(), true);
> -	for (i = 0; i < cstate->num_connectors; ++i)
> -		dpu_connector_commit_reset(cstate->connectors[i],
> ktime_get());
> 
>  	memset(dpu_crtc->mixers, 0, sizeof(dpu_crtc->mixers));
>  	dpu_crtc->num_mixers = 0;
> @@ -3703,6 +3590,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc
> *crtc,
>  	int multirect_count = 0;
>  	const struct drm_plane_state *pipe_staged[SSPP_MAX];
>  	int left_zpos_cnt = 0, right_zpos_cnt = 0;
> +	struct drm_connector_list_iter conn_iter;
> +	struct drm_connector *conn;
> 
>  	if (!crtc) {
>  		DPU_ERROR("invalid crtc\n");
> @@ -3956,6 +3845,16 @@ static int dpu_crtc_atomic_check(struct drm_crtc
> *crtc,
>  		goto end;
>  	}
> 
> +	/* identify connectors attached to this crtc */
> +	cstate->num_connectors = 0;
> +	drm_connector_list_iter_begin(crtc->dev, &conn_iter);
> +	drm_for_each_connector_iter(conn, &conn_iter)
> +		if (conn->state && conn->state->crtc == crtc &&
> +				cstate->num_connectors < MAX_CONNECTORS) {
> +			cstate->connectors[cstate->num_connectors++] =
> conn;
> +		}
> +	drm_connector_list_iter_end(&conn_iter);
> +

Is this hunk related to this change?

>  end:
>  	_dpu_crtc_rp_free_unused(&cstate->rp);
>  	return rc;
> @@ -4034,13 +3933,6 @@ static void dpu_crtc_install_properties(struct
> drm_crtc *crtc,
>  		"input_fence_timeout", 0x0, 0,
> DPU_CRTC_MAX_INPUT_FENCE_TIMEOUT,
>  		DPU_CRTC_INPUT_FENCE_TIMEOUT,
> CRTC_PROP_INPUT_FENCE_TIMEOUT);
> 
> -	msm_property_install_range(&dpu_crtc->property_info,
> "output_fence",
> -			0x0, 0, INR_OPEN_MAX, 0x0,
> CRTC_PROP_OUTPUT_FENCE);
> -
> -	msm_property_install_range(&dpu_crtc->property_info,
> -			"output_fence_offset", 0x0, 0, 1, 0,
> -			CRTC_PROP_OUTPUT_FENCE_OFFSET);
> -
>  	msm_property_install_range(&dpu_crtc->property_info,
>  			"core_clk", 0x0, 0, U64_MAX,
>  			dpu_kms->perf.max_core_clk_rate,
> @@ -4342,29 +4234,12 @@ static int dpu_crtc_atomic_get_property(struct
> drm_crtc *crtc,
>  		}
> 
>  		i = msm_property_index(&dpu_crtc->property_info,
> property);
> -		if (i == CRTC_PROP_OUTPUT_FENCE) {
> -			uint32_t offset = dpu_crtc_get_property(cstate,
> -					CRTC_PROP_OUTPUT_FENCE_OFFSET);
> -
> -			/**
> -			 * set the offset to 0 only for cmd mode panels,
> so
> -			 * the release fence for the current frame can be
> -			 * triggered right after PP_DONE interrupt.
> -			 */
> -			offset = is_cmd ? 0 : (offset + conn_offset);
> -
> -			ret = dpu_fence_create(&dpu_crtc->output_fence,
> val,
> -								offset);
> -			if (ret)
> -				DPU_ERROR("fence create failed\n");
> -		} else {
> -			ret =
> msm_property_atomic_get(&dpu_crtc->property_info,
> -					&cstate->property_state,
> -					property, val);
> -			if (ret)
> -				ret = dpu_cp_crtc_get_property(crtc,
> -					property, val);
> -		}
> +		ret = msm_property_atomic_get(&dpu_crtc->property_info,
> +				&cstate->property_state,
> +				property, val);
> +		if (ret)
> +			ret = dpu_cp_crtc_get_property(crtc,
> +				property, val);
>  		if (ret)
>  			DRM_ERROR("get property failed\n");
>  	}
> @@ -4858,10 +4733,6 @@ static int _dpu_crtc_init_events(struct dpu_crtc
> *dpu_crtc)
>  		list_add_tail(&dpu_crtc->event_cache[i].list,
>  				&dpu_crtc->event_free_list);
> 
> -	INIT_LIST_HEAD(&dpu_crtc->retire_event_list);
> -	for (i = 0; i < ARRAY_SIZE(dpu_crtc->retire_events); i++)
> -		INIT_LIST_HEAD(&dpu_crtc->retire_events[i].list);
> -
>  	return rc;
>  }
> 
> @@ -4920,9 +4791,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device
> *dev, struct drm_plane *plane)
>  		return ERR_PTR(rc);
>  	}
> 
> -	/* initialize output fence support */
> -	dpu_fence_init(&dpu_crtc->output_fence, dpu_crtc->name,
> crtc->base.id);
> -
>  	/* create CRTC properties */
>  	msm_property_init(&dpu_crtc->property_info, &crtc->base, dev,
>  			priv->crtc_property, dpu_crtc->property_data,
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> index b63df243be33..727a3434a4f6 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> @@ -22,7 +22,6 @@
>  #include <linux/kthread.h>
>  #include <drm/drm_crtc.h>
>  #include "msm_prop.h"
> -#include "dpu_fence.h"
>  #include "dpu_kms.h"
>  #include "dpu_core_perf.h"
>  #include "dpu_hw_blk.h"
> @@ -85,17 +84,6 @@ struct dpu_crtc_smmu_state_data {
>  	uint32_t transition_error;
>  };
> 
> -/**
> - * @connectors    : Currently associated drm connectors for retire 
> event
> - * @num_connectors: Number of associated drm connectors for retire 
> event
> - * @list:	event list
> - */
> -struct dpu_crtc_retire_event {
> -	struct drm_connector *connectors[MAX_CONNECTORS];
> -	int num_connectors;
> -	struct list_head list;
> -};
> -
>  /**
>   * struct dpu_crtc_mixer: stores the map for each virtual pipeline in 
> the
> CRTC
>   * @hw_lm:	LM HW Driver context
> @@ -169,7 +157,6 @@ struct dpu_crtc_event {
>   * @drm_requested_vblank : Whether vblanks have been enabled in the
> encoder
>   * @property_info : Opaque structure for generic property support
>   * @property_defaults : Array of default values for generic property
> support
> - * @output_fence  : output release fence context
>   * @stage_cfg     : H/w mixer stage configuration
>   * @debugfs_root  : Parent of debugfs node
>   * @vblank_cb_count : count of vblank callback since last reset
> @@ -190,8 +177,6 @@ struct dpu_crtc_event {
>   * @frame_events  : static allocation of in-flight frame events
>   * @frame_event_list : available frame event list
>   * @spin_lock     : spin lock for frame event, transaction status, 
> etc...
> - * @retire_events  : static allocation of retire fence connector
> - * @retire_event_list : available retire fence connector list
>   * @frame_done_comp    : for frame_event_done synchronization
>   * @event_thread  : Pointer to event handler thread
>   * @event_worker  : Event worker queue
> @@ -227,9 +212,6 @@ struct dpu_crtc {
>  	struct msm_property_data property_data[CRTC_PROP_COUNT];
>  	struct drm_property_blob *blob_info;
> 
> -	/* output fence support */
> -	struct dpu_fence_context output_fence;
> -
>  	struct dpu_hw_stage_cfg stage_cfg;
>  	struct dentry *debugfs_root;
> 
> @@ -253,8 +235,6 @@ struct dpu_crtc {
>  	struct dpu_crtc_frame_event
> frame_events[DPU_CRTC_FRAME_EVENT_SIZE];
>  	struct list_head frame_event_list;
>  	spinlock_t spin_lock;
> -	struct dpu_crtc_retire_event
> retire_events[DPU_CRTC_FRAME_EVENT_SIZE];
> -	struct list_head retire_event_list;
>  	struct completion frame_done_comp;
> 
>  	/* for handling internal event thread */
> @@ -475,14 +455,6 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool 
> en);
>   */
>  void dpu_crtc_commit_kickoff(struct drm_crtc *crtc);
> 
> -/**
> - * dpu_crtc_prepare_commit - callback to prepare for output fences
> - * @crtc: Pointer to drm crtc object
> - * @old_state: Pointer to drm crtc old state object
> - */
> -void dpu_crtc_prepare_commit(struct drm_crtc *crtc,
> -		struct drm_crtc_state *old_state);
> -
>  /**
>   * dpu_crtc_complete_commit - callback signalling completion of 
> current
> commit
>   * @crtc: Pointer to drm crtc object
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 4d1e3652dbf4..a54ad2cd5856 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -2465,9 +2465,6 @@ static inline void 
> _dpu_encoder_trigger_flush(struct
> drm_encoder *drm_enc,
> 
>  	pending_kickoff_cnt = dpu_encoder_phys_inc_pending(phys);
> 
> -	if (phys->ops.is_master && phys->ops.is_master(phys))
> -		atomic_inc(&phys->pending_retire_fence_cnt);
> -
>  	if (extra_flush_bits && ctl->ops.update_pending_flush)
>  		ctl->ops.update_pending_flush(ctl, extra_flush_bits);
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> index 69fb26cb43ab..86a3800af673 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> @@ -27,9 +27,7 @@
>  #define DPU_ENCODER_FRAME_EVENT_DONE			BIT(0)
>  #define DPU_ENCODER_FRAME_EVENT_ERROR			BIT(1)
>  #define DPU_ENCODER_FRAME_EVENT_PANEL_DEAD		BIT(2)
> -#define DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE	BIT(3)
> -#define DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE	BIT(4)
> -#define DPU_ENCODER_FRAME_EVENT_IDLE			BIT(5)
> +#define DPU_ENCODER_FRAME_EVENT_IDLE			BIT(3)
> 
>  #define IDLE_TIMEOUT	(66 - 16/2)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> index 3b05569007d2..71cd2f258994 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -245,8 +245,6 @@ struct dpu_encoder_irq {
>   *				scheduled. Decremented in irq handler
>   * @pending_ctlstart_cnt:	Atomic counter tracking the number of ctl
> start
>   *                              pending.
> - * @pending_retire_fence_cnt:   Atomic counter tracking the pending
> retire
> - *                              fences that have to be signalled.
>   * @pending_kickoff_wq:		Wait queue for blocking until
> kickoff completes
>   * @irq:			IRQ tracking structures
>   */
> @@ -273,7 +271,6 @@ struct dpu_encoder_phys {
>  	atomic_t underrun_cnt;
>  	atomic_t pending_ctlstart_cnt;
>  	atomic_t pending_kickoff_cnt;
> -	atomic_t pending_retire_fence_cnt;
>  	wait_queue_head_t pending_kickoff_wq;
>  	struct dpu_encoder_irq irq[INTR_IDX_MAX];
>  };
> @@ -323,9 +320,6 @@ struct dpu_encoder_phys_cmd_autorefresh {
>   *			after ctl_start instead of before next frame
> kickoff
>   * @pp_timeout_report_cnt: number of pingpong done irq timeout errors
>   * @autorefresh: autorefresh feature state
> - * @pending_rd_ptr_cnt: atomic counter to indicate if retire fence can 
> be
> - *                      signaled at the next rd_ptr_irq
> - * @rd_ptr_timestamp: last rd_ptr_irq timestamp
>   * @pending_vblank_cnt: Atomic counter tracking pending wait for 
> VBLANK
>   * @pending_vblank_wq: Wait queue for blocking until VBLANK received
>   */
> @@ -335,8 +329,6 @@ struct dpu_encoder_phys_cmd {
>  	bool serialize_wait4pp;
>  	int pp_timeout_report_cnt;
>  	struct dpu_encoder_phys_cmd_autorefresh autorefresh;
> -	atomic_t pending_rd_ptr_cnt;
> -	ktime_t rd_ptr_timestamp;
>  	atomic_t pending_vblank_cnt;
>  	wait_queue_head_t pending_vblank_wq;
>  };
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> index e92380a1d5a4..6ccf37820aa2 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> @@ -44,12 +44,6 @@
> 
>  #define DPU_ENC_WR_PTR_START_TIMEOUT_US 20000
> 
> -/*
> - * Threshold for signalling retire fences in cases where
> - * CTL_START_IRQ is received just after RD_PTR_IRQ
> - */
> -#define DPU_ENC_CTL_START_THRESHOLD_US 500
> -
>  static inline int _dpu_encoder_phys_cmd_get_idle_timeout(
>  		struct dpu_encoder_phys_cmd *cmd_enc)
>  {
> @@ -170,8 +164,7 @@ static void 
> dpu_encoder_phys_cmd_pp_tx_done_irq(void
> *arg, int irq_idx)
>  	struct dpu_encoder_phys *phys_enc = arg;
>  	unsigned long lock_flags;
>  	int new_cnt;
> -	u32 event = DPU_ENCODER_FRAME_EVENT_DONE |
> -			DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
> +	u32 event = DPU_ENCODER_FRAME_EVENT_DONE;
> 
>  	if (!phys_enc || !phys_enc->hw_pp)
>  		return;
> @@ -221,7 +214,6 @@ static void dpu_encoder_phys_cmd_pp_rd_ptr_irq(void
> *arg, int irq_idx)
>  {
>  	struct dpu_encoder_phys *phys_enc = arg;
>  	struct dpu_encoder_phys_cmd *cmd_enc;
> -	u32 event = 0;
> 
>  	if (!phys_enc || !phys_enc->hw_pp)
>  		return;
> @@ -229,30 +221,10 @@ static void 
> dpu_encoder_phys_cmd_pp_rd_ptr_irq(void
> *arg, int irq_idx)
>  	DPU_ATRACE_BEGIN("rd_ptr_irq");
>  	cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
> 
> -	/**
> -	 * signal only for master, when the ctl_start irq is
> -	 * done and incremented the pending_rd_ptr_cnt.
> -	 */
> -	if (dpu_encoder_phys_cmd_is_master(phys_enc)
> -		    && atomic_add_unless(&cmd_enc->pending_rd_ptr_cnt, -1,
> 0)
> -		    && atomic_add_unless(
> -				&phys_enc->pending_retire_fence_cnt, -1,
> 0)) {
> -
> -		event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
> -		if (phys_enc->parent_ops.handle_frame_done)
> -			phys_enc->parent_ops.handle_frame_done(
> -				phys_enc->parent, phys_enc, event);
> -	}
> -
> -	DPU_EVT32_IRQ(DRMID(phys_enc->parent),
> -			phys_enc->hw_pp->idx - PINGPONG_0, event, 0xfff);
> -
>  	if (phys_enc->parent_ops.handle_vblank_virt)
>  		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
>  			phys_enc);
> 
> -	cmd_enc->rd_ptr_timestamp = ktime_get();
> -
>  	atomic_add_unless(&cmd_enc->pending_vblank_cnt, -1, 0);
>  	wake_up_all(&cmd_enc->pending_vblank_wq);
>  	DPU_ATRACE_END("rd_ptr_irq");
> @@ -262,9 +234,6 @@ static void dpu_encoder_phys_cmd_ctl_start_irq(void
> *arg, int irq_idx)
>  {
>  	struct dpu_encoder_phys *phys_enc = arg;
>  	struct dpu_encoder_phys_cmd *cmd_enc;
> -	struct dpu_hw_ctl *ctl;
> -	u32 event = 0;
> -	s64 time_diff_us;
> 
>  	if (!phys_enc || !phys_enc->hw_ctl)
>  		return;
> @@ -272,43 +241,8 @@ static void 
> dpu_encoder_phys_cmd_ctl_start_irq(void
> *arg, int irq_idx)
>  	DPU_ATRACE_BEGIN("ctl_start_irq");
>  	cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
> 
> -	ctl = phys_enc->hw_ctl;
>  	atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
> 
> -	time_diff_us = ktime_us_delta(ktime_get(),
> cmd_enc->rd_ptr_timestamp);
> -
> -	/* handle retire fence based on only master */
> -	if (dpu_encoder_phys_cmd_is_master(phys_enc)
> -			&&
> atomic_read(&phys_enc->pending_retire_fence_cnt)) {
> -		/**
> -		 * Handle rare cases where the ctl_start_irq is received
> -		 * after rd_ptr_irq. If it falls within a threshold, it is
> -		 * guaranteed the frame would be picked up in the current
> TE.
> -		 * Signal retire fence immediately in such case.
> -		 */
> -		if ((time_diff_us <= DPU_ENC_CTL_START_THRESHOLD_US)
> -			    && atomic_add_unless(
> -				&phys_enc->pending_retire_fence_cnt, -1,
> 0)) {
> -
> -			event =
> DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
> -
> -			if (phys_enc->parent_ops.handle_frame_done)
> -				phys_enc->parent_ops.handle_frame_done(
> -					phys_enc->parent, phys_enc,
> event);
> -
> -		/**
> -		 * In ideal cases, ctl_start_irq is received before the
> -		 * rd_ptr_irq, so set the atomic flag to indicate the
> event
> -		 * and rd_ptr_irq will handle signalling the retire fence
> -		 */
> -		} else {
> -			atomic_inc(&cmd_enc->pending_rd_ptr_cnt);
> -		}
> -	}
> -
> -	DPU_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0,
> -				time_diff_us, event, 0xfff);
> -
>  	/* Signal any waiting ctl start interrupt */
>  	wake_up_all(&phys_enc->pending_kickoff_wq);
>  	DPU_ATRACE_END("ctl_start_irq");
> @@ -409,8 +343,7 @@ static int
> _dpu_encoder_phys_cmd_handle_ppdone_timeout(
>  {
>  	struct dpu_encoder_phys_cmd *cmd_enc =
>  			to_dpu_encoder_phys_cmd(phys_enc);
> -	u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR
> -				|
> DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
> +	u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR;
>  	bool do_log = false;
> 
>  	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_ctl)
> @@ -1346,8 +1279,6 @@ struct dpu_encoder_phys 
> *dpu_encoder_phys_cmd_init(
>  	atomic_set(&phys_enc->vblank_refcount, 0);
>  	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
>  	atomic_set(&phys_enc->pending_ctlstart_cnt, 0);
> -	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
> -	atomic_set(&cmd_enc->pending_rd_ptr_cnt, 0);
>  	atomic_set(&cmd_enc->pending_vblank_cnt, 0);
>  	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
>  	init_waitqueue_head(&cmd_enc->pending_vblank_wq);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> index 62c6f5c3547a..edaad0413987 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> @@ -373,13 +373,10 @@ static void
> dpu_encoder_phys_vid_setup_timing_engine(
>  static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
>  {
>  	struct dpu_encoder_phys *phys_enc = arg;
> -	struct dpu_encoder_phys_vid *vid_enc =
> -			to_dpu_encoder_phys_vid(phys_enc);
>  	struct dpu_hw_ctl *hw_ctl;
>  	unsigned long lock_flags;
>  	u32 flush_register = 0;
>  	int new_cnt = -1, old_cnt = -1;
> -	u32 event = 0;
> 
>  	if (!phys_enc)
>  		return;
> @@ -390,18 +387,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void
> *arg, int irq_idx)
> 
>  	DPU_ATRACE_BEGIN("vblank_irq");
> 
> -	/* signal only for master, where there is a pending kickoff */
> -	if (dpu_encoder_phys_vid_is_master(phys_enc)
> -			&& atomic_add_unless(
> -				&phys_enc->pending_retire_fence_cnt, -1,
> 0)) {
> -		event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
> -				|
> DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
> -
> -		if (phys_enc->parent_ops.handle_frame_done)
> -
> phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
> -				phys_enc, event);
> -	}
> -
>  	if (phys_enc->parent_ops.handle_vblank_virt)
>  		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
>  				phys_enc);
> @@ -422,9 +407,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void 
> *arg,
> int irq_idx)
>  				-1, 0);
>  	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
> 
> -	DPU_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx -
> INTF_0,
> -			old_cnt, new_cnt, flush_register, event);
> -
>  	/* Signal any waiting atomic commit thread */
>  	wake_up_all(&phys_enc->pending_kickoff_wq);
>  	DPU_ATRACE_END("vblank_irq");
> @@ -1028,7 +1010,6 @@ struct dpu_encoder_phys 
> *dpu_encoder_phys_vid_init(
> 
>  	atomic_set(&phys_enc->vblank_refcount, 0);
>  	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
> -	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
>  	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
>  	phys_enc->enable_state = DPU_ENC_DISABLED;
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> index 9a6fa3e1e8b4..2bc5894839c4 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> @@ -680,11 +680,8 @@ static void dpu_encoder_phys_wb_done_irq(void 
> *arg,
> int irq_idx)
>  	if (phys_enc->enable_state == DPU_ENC_DISABLING)
>  		goto complete;
> 
> -	event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
> -			| DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE
> -			| DPU_ENCODER_FRAME_EVENT_DONE;
> +	event = DPU_ENCODER_FRAME_EVENT_DONE;
> 
> -	atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0);
>  	if (phys_enc->parent_ops.handle_frame_done)
>  		phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
>  				phys_enc, event);
> @@ -847,12 +844,8 @@ static int 
> dpu_encoder_phys_wb_wait_for_commit_done(
>  		} else {
>  			DPU_ERROR("wb:%d kickoff timed out\n",
>  					wb_enc->wb_dev->wb_idx - WB_0);
> -			atomic_add_unless(
> -				&phys_enc->pending_retire_fence_cnt, -1,
> 0);
> 
> -			event =
> DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
> -				|
> DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE
> -				| DPU_ENCODER_FRAME_EVENT_ERROR;
> +			event = DPU_ENCODER_FRAME_EVENT_ERROR;
>  			if (phys_enc->parent_ops.handle_frame_done)
>  				phys_enc->parent_ops.handle_frame_done(
>  					phys_enc->parent, phys_enc,
> event);
> @@ -1333,7 +1326,6 @@ struct dpu_encoder_phys 
> *dpu_encoder_phys_wb_init(
>  	phys_enc->intf_mode = INTF_MODE_WB_LINE;
>  	phys_enc->intf_idx = p->intf_idx;
>  	phys_enc->enc_spinlock = p->enc_spinlock;
> -	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
>  	INIT_LIST_HEAD(&wb_enc->irq_cb.list);
> 
>  	/* create internal buffer for disable logic */
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> index 3d83037e8305..9d68030378a7 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> @@ -545,35 +545,6 @@ static void dpu_kms_wait_for_commit_done(struct
> msm_kms *kms,
>  	}
>  }
> 
> -static void dpu_kms_prepare_fence(struct msm_kms *kms,
> -		struct drm_atomic_state *old_state)
> -{
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *old_crtc_state;
> -	int i, rc;
> -
> -	if (!kms || !old_state || !old_state->dev ||
> !old_state->acquire_ctx) {
> -		DPU_ERROR("invalid argument(s)\n");
> -		return;
> -	}
> -
> -retry:
> -	/* attempt to acquire ww mutex for connection */
> -	rc =
> drm_modeset_lock(&old_state->dev->mode_config.connection_mutex,
> -			       old_state->acquire_ctx);
> -
> -	if (rc == -EDEADLK) {
> -		drm_modeset_backoff(old_state->acquire_ctx);
> -		goto retry;
> -	}
> -
> -	/* old_state actually contains updated crtc pointers */
> -	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
> -		if (crtc->state->active)
> -			dpu_crtc_prepare_commit(crtc, old_crtc_state);
> -	}
> -}
> -
>  /**
>   * _dpu_kms_get_displays - query for underlying display handles and 
> cache
> them
>   * @dpu_kms:    Pointer to dpu kms structure
> @@ -1734,7 +1705,6 @@ static const struct msm_kms_funcs kms_funcs = {
>  	.irq_uninstall   = dpu_irq_uninstall,
>  	.irq             = dpu_irq,
>  	.preclose        = dpu_kms_preclose,
> -	.prepare_fence   = dpu_kms_prepare_fence,
>  	.prepare_commit  = dpu_kms_prepare_commit,
>  	.commit          = dpu_kms_commit,
>  	.complete_commit = dpu_kms_complete_commit,
> diff --git a/drivers/gpu/drm/msm/msm_drv.h 
> b/drivers/gpu/drm/msm/msm_drv.h
> index 8cab333df717..e92376acbcfe 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -132,8 +132,6 @@ enum msm_mdp_crtc_property {
> 
>  	/* range properties */
>  	CRTC_PROP_INPUT_FENCE_TIMEOUT = CRTC_PROP_BLOBCOUNT,
> -	CRTC_PROP_OUTPUT_FENCE,
> -	CRTC_PROP_OUTPUT_FENCE_OFFSET,
>  	CRTC_PROP_DIM_LAYER_V1,
>  	CRTC_PROP_CORE_CLK,
>  	CRTC_PROP_CORE_AB,
> @@ -163,7 +161,6 @@ enum msm_mdp_conn_property {
> 
>  	/* range properties */
>  	CONNECTOR_PROP_OUT_FB = CONNECTOR_PROP_BLOBCOUNT,
> -	CONNECTOR_PROP_RETIRE_FENCE,
>  	CONNECTOR_PROP_DST_X,
>  	CONNECTOR_PROP_DST_Y,
>  	CONNECTOR_PROP_DST_W,

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 11/11] drm/msm: Remove dpu input fences
       [not found]     ` <20180228191906.185417-12-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-03  0:50       ` Jeykumar Sankaran
  0 siblings, 0 replies; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-03  0:50 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-02-28 11:19, Sean Paul wrote:
> These are already provided by drm atomic core.
> 
> In conjunction with the output fences removed earlier, this obsoletes
> dpu_fence, and it can be entirely removed as well.
> 
> Change-Id: Ida4924a09c455d7a84bfee569bd0d2fb436418de
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>

> ---
>  drivers/gpu/drm/msm/Makefile              |   1 -
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  84 -----
>  drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c | 404 ----------------------
>  drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h | 190 ----------
>  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 104 ------
>  drivers/gpu/drm/msm/msm_drv.h             |   4 +-
>  6 files changed, 1 insertion(+), 786 deletions(-)
>  delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c
>  delete mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h
> 
> diff --git a/drivers/gpu/drm/msm/Makefile 
> b/drivers/gpu/drm/msm/Makefile
> index 2fb9ba11df19..b47ef5267e19 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -55,7 +55,6 @@ msm-y := \
>  	disp/dpu1/dpu_encoder.o \
>  	disp/dpu1/dpu_encoder_phys_cmd.o \
>  	disp/dpu1/dpu_encoder_phys_vid.o \
> -	disp/dpu1/dpu_fence.o \
>  	disp/dpu1/dpu_formats.o \
>  	disp/dpu1/dpu_hw_ad4.o \
>  	disp/dpu1/dpu_hw_blk.o \
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 2d44989ade7a..8dd986e476bd 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -64,16 +64,6 @@ static struct dpu_crtc_custom_events custom_events[] 
> =
> {
>  	{DRM_EVENT_IDLE_NOTIFY, dpu_crtc_idle_interrupt_handler}
>  };
> 
> -/* default input fence timeout, in ms */
> -#define DPU_CRTC_INPUT_FENCE_TIMEOUT    10000
> -
> -/*
> - * The default input fence timeout is 2 seconds while max allowed
> - * range is 10 seconds. Any value above 10 seconds adds glitches 
> beyond
> - * tolerance limit.
> - */
> -#define DPU_CRTC_MAX_INPUT_FENCE_TIMEOUT 10000
> -
>  /* layer mixer index on dpu_crtc */
>  #define LEFT_MIXER 0
>  #define RIGHT_MIXER 1
> @@ -1946,21 +1936,6 @@ static void _dpu_crtc_set_idle_timeout(struct
> drm_crtc *crtc, u64 val)
>  	}
>  }
> 
> -/**
> - * _dpu_crtc_set_input_fence_timeout - update ns version of in fence
> timeout
> - * @cstate: Pointer to dpu crtc state
> - */
> -static void _dpu_crtc_set_input_fence_timeout(struct dpu_crtc_state
> *cstate)
> -{
> -	if (!cstate) {
> -		DPU_ERROR("invalid cstate\n");
> -		return;
> -	}
> -	cstate->input_fence_timeout_ns =
> -		dpu_crtc_get_property(cstate,
> CRTC_PROP_INPUT_FENCE_TIMEOUT);
> -	cstate->input_fence_timeout_ns *= NSEC_PER_MSEC;
> -}
> -
>  /**
>   * _dpu_crtc_set_dim_layer_v1 - copy dim layer settings from userspace
>   * @cstate:      Pointer to dpu crtc state
> @@ -2385,53 +2360,6 @@ static int 
> _dpu_crtc_check_dest_scaler_data(struct
> drm_crtc *crtc,
>  	return ret;
>  }
> 
> -/**
> - * _dpu_crtc_wait_for_fences - wait for incoming framebuffer sync 
> fences
> - * @crtc: Pointer to CRTC object
> - */
> -static void _dpu_crtc_wait_for_fences(struct drm_crtc *crtc)
> -{
> -	struct drm_plane *plane = NULL;
> -	uint32_t wait_ms = 1;
> -	ktime_t kt_end, kt_wait;
> -	int rc = 0;
> -
> -	DPU_DEBUG("\n");
> -
> -	if (!crtc || !crtc->state) {
> -		DPU_ERROR("invalid crtc/state %pK\n", crtc);
> -		return;
> -	}
> -
> -	/* use monotonic timer to limit total fence wait time */
> -	kt_end = ktime_add_ns(ktime_get(),
> -		to_dpu_crtc_state(crtc->state)->input_fence_timeout_ns);
> -
> -	/*
> -	 * Wait for fences sequentially, as all of them need to be
> signalled
> -	 * before we can proceed.
> -	 *
> -	 * Limit total wait time to INPUT_FENCE_TIMEOUT, but still call
> -	 * dpu_plane_wait_input_fence with wait_ms == 0 after the timeout
> so
> -	 * that each plane can check its fence status and react
> appropriately
> -	 * if its fence has timed out. Call input fence wait multiple
> times if
> -	 * fence wait is interrupted due to interrupt call.
> -	 */
> -	DPU_ATRACE_BEGIN("plane_wait_input_fence");
> -	drm_atomic_crtc_for_each_plane(plane, crtc) {
> -		do {
> -			kt_wait = ktime_sub(kt_end, ktime_get());
> -			if (ktime_compare(kt_wait, ktime_set(0, 0)) >= 0)
> -				wait_ms = ktime_to_ms(kt_wait);
> -			else
> -				wait_ms = 0;
> -
> -			rc = dpu_plane_wait_input_fence(plane, wait_ms);
> -		} while (wait_ms && rc == -ERESTARTSYS);
> -	}
> -	DPU_ATRACE_END("plane_wait_input_fence");
> -}
> -
>  static void _dpu_crtc_setup_mixer_for_encoder(
>  		struct drm_crtc *crtc,
>  		struct drm_encoder *enc)
> @@ -2716,9 +2644,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc
> *crtc,
>  	drm_atomic_crtc_for_each_plane(plane, crtc)
>  		dpu_plane_restore(plane);
> 
> -	/* wait for acquire fences before anything else is done */
> -	_dpu_crtc_wait_for_fences(crtc);
> -
>  	if (!cstate->rsc_update) {
>  		drm_for_each_encoder(encoder, dev) {
>  			if (encoder->crtc != crtc)
> @@ -3178,8 +3103,6 @@ static void dpu_crtc_reset(struct drm_crtc *crtc)
>  			&cstate->property_state,
>  			cstate->property_values);
> 
> -	_dpu_crtc_set_input_fence_timeout(cstate);
> -
>  	_dpu_crtc_rp_reset(&cstate->rp, &dpu_crtc->rp_lock,
>  			&dpu_crtc->rp_head);
> 
> @@ -3929,10 +3852,6 @@ static void dpu_crtc_install_properties(struct
> drm_crtc *crtc,
>  	}
> 
>  	/* range properties */
> -	msm_property_install_range(&dpu_crtc->property_info,
> -		"input_fence_timeout", 0x0, 0,
> DPU_CRTC_MAX_INPUT_FENCE_TIMEOUT,
> -		DPU_CRTC_INPUT_FENCE_TIMEOUT,
> CRTC_PROP_INPUT_FENCE_TIMEOUT);
> -
>  	msm_property_install_range(&dpu_crtc->property_info,
>  			"core_clk", 0x0, 0, U64_MAX,
>  			dpu_kms->perf.max_core_clk_rate,
> @@ -4121,9 +4040,6 @@ static int dpu_crtc_atomic_set_property(struct
> drm_crtc *crtc,
>  			idx = msm_property_index(&dpu_crtc->property_info,
>  					property);
>  			switch (idx) {
> -			case CRTC_PROP_INPUT_FENCE_TIMEOUT:
> -				_dpu_crtc_set_input_fence_timeout(cstate);
> -				break;
>  			case CRTC_PROP_DIM_LAYER_V1:
>  				_dpu_crtc_set_dim_layer_v1(cstate,
>  							(void __user
> *)val);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c
> deleted file mode 100644
> index 49ffd7138eba..000000000000
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.c
> +++ /dev/null
> @@ -1,404 +0,0 @@
> -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or 
> modify
> - * it under the terms of the GNU General Public License version 2 and
> - * only version 2 as published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - */
> -
> -#include <linux/sync_file.h>
> -#include <linux/dma-fence.h>
> -#include "msm_drv.h"
> -#include "dpu_kms.h"
> -#include "dpu_fence.h"
> -
> -#define TIMELINE_VAL_LENGTH		128
> -
> -void *dpu_sync_get(uint64_t fd)
> -{
> -	/* force signed compare, fdget accepts an int argument */
> -	return (signed int)fd >= 0 ? sync_file_get_fence(fd) : NULL;
> -}
> -
> -void dpu_sync_put(void *fence)
> -{
> -	if (fence)
> -		dma_fence_put(fence);
> -}
> -
> -signed long dpu_sync_wait(void *fnc, long timeout_ms)
> -{
> -	struct dma_fence *fence = fnc;
> -	int rc;
> -	char timeline_str[TIMELINE_VAL_LENGTH];
> -
> -	if (!fence)
> -		return -EINVAL;
> -	else if (dma_fence_is_signaled(fence))
> -		return timeout_ms ? msecs_to_jiffies(timeout_ms) : 1;
> -
> -	rc = dma_fence_wait_timeout(fence, true,
> -				msecs_to_jiffies(timeout_ms));
> -	if (!rc || (rc == -EINVAL)) {
> -		if (fence->ops->timeline_value_str)
> -			fence->ops->timeline_value_str(fence,
> -					timeline_str,
> TIMELINE_VAL_LENGTH);
> -
> -		DPU_ERROR(
> -			"fence driver name:%s timeline name:%s seqno:0x%x
> timeline:%s signaled:0x%x\n",
> -			fence->ops->get_driver_name(fence),
> -			fence->ops->get_timeline_name(fence),
> -			fence->seqno, timeline_str,
> -			fence->ops->signaled ?
> -				fence->ops->signaled(fence) : 0xffffffff);
> -	}
> -
> -	return rc;
> -}
> -
> -uint32_t dpu_sync_get_name_prefix(void *fence)
> -{
> -	const char *name;
> -	uint32_t i, prefix;
> -	struct dma_fence *f = fence;
> -
> -	if (!fence)
> -		return 0;
> -
> -	name = f->ops->get_driver_name(f);
> -	if (!name)
> -		return 0;
> -
> -	prefix = 0x0;
> -	for (i = 0; i < sizeof(uint32_t) && name[i]; ++i)
> -		prefix = (prefix << CHAR_BIT) | name[i];
> -
> -	return prefix;
> -}
> -
> -/**
> - * struct dpu_fence - release/retire fence structure
> - * @fence: base fence structure
> - * @name: name of each fence- it is fence timeline + commit_count
> - * @fence_list: list to associated this fence on timeline/context
> - * @fd: fd attached to this fence - debugging purpose.
> - */
> -struct dpu_fence {
> -	struct dma_fence base;
> -	struct dpu_fence_context *ctx;
> -	char name[DPU_FENCE_NAME_SIZE];
> -	struct list_head	fence_list;
> -	int fd;
> -};
> -
> -static void dpu_fence_destroy(struct kref *kref)
> -{
> -}
> -
> -static inline struct dpu_fence *to_dpu_fence(struct dma_fence *fence)
> -{
> -	return container_of(fence, struct dpu_fence, base);
> -}
> -
> -static const char *dpu_fence_get_driver_name(struct dma_fence *fence)
> -{
> -	struct dpu_fence *f = to_dpu_fence(fence);
> -
> -	return f->name;
> -}
> -
> -static const char *dpu_fence_get_timeline_name(struct dma_fence 
> *fence)
> -{
> -	struct dpu_fence *f = to_dpu_fence(fence);
> -
> -	return f->ctx->name;
> -}
> -
> -static bool dpu_fence_enable_signaling(struct dma_fence *fence)
> -{
> -	return true;
> -}
> -
> -static bool dpu_fence_signaled(struct dma_fence *fence)
> -{
> -	struct dpu_fence *f = to_dpu_fence(fence);
> -	bool status;
> -
> -	status = (int)(fence->seqno - f->ctx->done_count) <= 0 ? true :
> false;
> -	DPU_DEBUG("status:%d fence seq:%d and timeline:%d\n",
> -			status, fence->seqno, f->ctx->done_count);
> -	return status;
> -}
> -
> -static void dpu_fence_release(struct dma_fence *fence)
> -{
> -	struct dpu_fence *f;
> -
> -	if (fence) {
> -		f = to_dpu_fence(fence);
> -		kfree(f);
> -	}
> -}
> -
> -static void dpu_fence_value_str(struct dma_fence *fence, char *str, 
> int
> size)
> -{
> -	if (!fence || !str)
> -		return;
> -
> -	snprintf(str, size, "%d", fence->seqno);
> -}
> -
> -static void dpu_fence_timeline_value_str(struct dma_fence *fence, char
> *str,
> -		int size)
> -{
> -	struct dpu_fence *f = to_dpu_fence(fence);
> -
> -	if (!fence || !f->ctx || !str)
> -		return;
> -
> -	snprintf(str, size, "%d", f->ctx->done_count);
> -}
> -
> -static struct dma_fence_ops dpu_fence_ops = {
> -	.get_driver_name = dpu_fence_get_driver_name,
> -	.get_timeline_name = dpu_fence_get_timeline_name,
> -	.enable_signaling = dpu_fence_enable_signaling,
> -	.signaled = dpu_fence_signaled,
> -	.wait = dma_fence_default_wait,
> -	.release = dpu_fence_release,
> -	.fence_value_str = dpu_fence_value_str,
> -	.timeline_value_str = dpu_fence_timeline_value_str,
> -};
> -
> -/**
> - * _dpu_fence_create_fd - create fence object and return an fd for it
> - * This function is NOT thread-safe.
> - * @timeline: Timeline to associate with fence
> - * @val: Timeline value at which to signal the fence
> - * Return: File descriptor on success, or error code on error
> - */
> -static int _dpu_fence_create_fd(void *fence_ctx, uint32_t val)
> -{
> -	struct dpu_fence *dpu_fence;
> -	struct sync_file *sync_file;
> -	signed int fd = -EINVAL;
> -	struct dpu_fence_context *ctx = fence_ctx;
> -
> -	if (!ctx) {
> -		DPU_ERROR("invalid context\n");
> -		goto exit;
> -	}
> -
> -	dpu_fence = kzalloc(sizeof(*dpu_fence), GFP_KERNEL);
> -	if (!dpu_fence)
> -		return -ENOMEM;
> -
> -	dpu_fence->ctx = fence_ctx;
> -	snprintf(dpu_fence->name, DPU_FENCE_NAME_SIZE, "dpu_fence:%s:%u",
> -						dpu_fence->ctx->name,
> val);
> -	dma_fence_init(&dpu_fence->base, &dpu_fence_ops, &ctx->lock,
> -		ctx->context, val);
> -
> -	/* create fd */
> -	fd = get_unused_fd_flags(0);
> -	if (fd < 0) {
> -		dma_fence_put(&dpu_fence->base);
> -		DPU_ERROR("failed to get_unused_fd_flags(), %s\n",
> -							dpu_fence->name);
> -		goto exit;
> -	}
> -
> -	/* create fence */
> -	sync_file = sync_file_create(&dpu_fence->base);
> -	if (sync_file == NULL) {
> -		put_unused_fd(fd);
> -		fd = -EINVAL;
> -		dma_fence_put(&dpu_fence->base);
> -		DPU_ERROR("couldn't create fence, %s\n", dpu_fence->name);
> -		goto exit;
> -	}
> -
> -	fd_install(fd, sync_file->file);
> -	dpu_fence->fd = fd;
> -	kref_get(&ctx->kref);
> -
> -	spin_lock(&ctx->list_lock);
> -	list_add_tail(&dpu_fence->fence_list, &ctx->fence_list_head);
> -	spin_unlock(&ctx->list_lock);
> -
> -exit:
> -	return fd;
> -}
> -
> -int dpu_fence_init(struct dpu_fence_context *ctx,
> -		const char *name, uint32_t drm_id)
> -{
> -	if (!ctx || !name) {
> -		DPU_ERROR("invalid argument(s)\n");
> -		return -EINVAL;
> -	}
> -	memset(ctx, 0, sizeof(*ctx));
> -
> -	strlcpy(ctx->name, name, ARRAY_SIZE(ctx->name));
> -	ctx->drm_id = drm_id;
> -	kref_init(&ctx->kref);
> -	ctx->context = dma_fence_context_alloc(1);
> -
> -	spin_lock_init(&ctx->lock);
> -	spin_lock_init(&ctx->list_lock);
> -	INIT_LIST_HEAD(&ctx->fence_list_head);
> -
> -	return 0;
> -}
> -
> -void dpu_fence_deinit(struct dpu_fence_context *ctx)
> -{
> -	if (!ctx) {
> -		DPU_ERROR("invalid fence\n");
> -		return;
> -	}
> -
> -	kref_put(&ctx->kref, dpu_fence_destroy);
> -}
> -
> -void dpu_fence_prepare(struct dpu_fence_context *ctx)
> -{
> -	unsigned long flags;
> -
> -	if (!ctx) {
> -		DPU_ERROR("invalid argument(s), fence %pK\n", ctx);
> -	} else {
> -		spin_lock_irqsave(&ctx->lock, flags);
> -		++ctx->commit_count;
> -		spin_unlock_irqrestore(&ctx->lock, flags);
> -	}
> -}
> -
> -static void _dpu_fence_trigger(struct dpu_fence_context *ctx, ktime_t 
> ts)
> -{
> -	unsigned long flags;
> -	struct dpu_fence *fc, *next;
> -	bool is_signaled = false;
> -	struct list_head local_list_head;
> -
> -	INIT_LIST_HEAD(&local_list_head);
> -
> -	spin_lock(&ctx->list_lock);
> -	if (list_empty(&ctx->fence_list_head)) {
> -		DPU_DEBUG("nothing to trigger!\n");
> -		spin_unlock(&ctx->list_lock);
> -		return;
> -	}
> -
> -	list_for_each_entry_safe(fc, next, &ctx->fence_list_head,
> fence_list)
> -		list_move(&fc->fence_list, &local_list_head);
> -	spin_unlock(&ctx->list_lock);
> -
> -	list_for_each_entry_safe(fc, next, &local_list_head, fence_list) {
> -		spin_lock_irqsave(&ctx->lock, flags);
> -		fc->base.timestamp = ts;
> -		is_signaled = dma_fence_is_signaled_locked(&fc->base);
> -		spin_unlock_irqrestore(&ctx->lock, flags);
> -
> -		if (is_signaled) {
> -			list_del_init(&fc->fence_list);
> -			dma_fence_put(&fc->base);
> -			kref_put(&ctx->kref, dpu_fence_destroy);
> -		} else {
> -			spin_lock(&ctx->list_lock);
> -			list_move(&fc->fence_list, &ctx->fence_list_head);
> -			spin_unlock(&ctx->list_lock);
> -		}
> -	}
> -}
> -
> -int dpu_fence_create(struct dpu_fence_context *ctx, uint64_t *val,
> -							uint32_t offset)
> -{
> -	uint32_t trigger_value;
> -	int fd, rc = -EINVAL;
> -	unsigned long flags;
> -
> -	if (!ctx || !val) {
> -		DPU_ERROR("invalid argument(s), fence %d, pval %d\n",
> -				ctx != NULL, val != NULL);
> -		return rc;
> -	}
> -
> -	/*
> -	 * Allow created fences to have a constant offset with respect
> -	 * to the timeline. This allows us to delay the fence signalling
> -	 * w.r.t. the commit completion (e.g., an offset of +1 would
> -	 * cause fences returned during a particular commit to signal
> -	 * after an additional delay of one commit, rather than at the
> -	 * end of the current one.
> -	 */
> -	spin_lock_irqsave(&ctx->lock, flags);
> -	trigger_value = ctx->commit_count + offset;
> -
> -	spin_unlock_irqrestore(&ctx->lock, flags);
> -
> -	fd = _dpu_fence_create_fd(ctx, trigger_value);
> -	*val = fd;
> -	DPU_DEBUG("fence_create::fd:%d trigger:%d commit:%d offset:%d\n",
> -				fd, trigger_value, ctx->commit_count,
> offset);
> -
> -	DPU_EVT32(ctx->drm_id, trigger_value, fd);
> -
> -	if (fd >= 0) {
> -		rc = 0;
> -		_dpu_fence_trigger(ctx, ktime_get());
> -	} else {
> -		rc = fd;
> -	}
> -
> -	return rc;
> -}
> -
> -void dpu_fence_signal(struct dpu_fence_context *ctx, ktime_t ts,
> -							bool
> reset_timeline)
> -{
> -	unsigned long flags;
> -
> -	if (!ctx) {
> -		DPU_ERROR("invalid ctx, %pK\n", ctx);
> -		return;
> -	}
> -
> -	spin_lock_irqsave(&ctx->lock, flags);
> -	if (reset_timeline) {
> -		if ((int)(ctx->done_count - ctx->commit_count) < 0) {
> -			DPU_ERROR(
> -				"timeline reset attempt! done count:%d
> commit:%d\n",
> -				ctx->done_count, ctx->commit_count);
> -			ctx->done_count = ctx->commit_count;
> -			DPU_EVT32(ctx->drm_id, ctx->done_count,
> -				ctx->commit_count, ktime_to_us(ts),
> -				reset_timeline, DPU_EVTLOG_FATAL);
> -		} else {
> -			spin_unlock_irqrestore(&ctx->lock, flags);
> -			return;
> -		}
> -	} else if ((int)(ctx->done_count - ctx->commit_count) < 0) {
> -		++ctx->done_count;
> -		DPU_DEBUG("fence_signal:done count:%d commit count:%d\n",
> -					ctx->done_count,
> ctx->commit_count);
> -	} else {
> -		DPU_ERROR("extra signal attempt! done count:%d
> commit:%d\n",
> -					ctx->done_count,
> ctx->commit_count);
> -		DPU_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count,
> -			ktime_to_us(ts), reset_timeline,
> DPU_EVTLOG_FATAL);
> -		spin_unlock_irqrestore(&ctx->lock, flags);
> -		return;
> -	}
> -	spin_unlock_irqrestore(&ctx->lock, flags);
> -
> -	DPU_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count,
> -			ktime_to_us(ts));
> -
> -	_dpu_fence_trigger(ctx, ts);
> -}
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h
> deleted file mode 100644
> index f943046d96b8..000000000000
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_fence.h
> +++ /dev/null
> @@ -1,190 +0,0 @@
> -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
> - *
> - * This program is free software; you can redistribute it and/or 
> modify
> - * it under the terms of the GNU General Public License version 2 and
> - * only version 2 as published by the Free Software Foundation.
> - *
> - * This program is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - */
> -
> -#ifndef _DPU_FENCE_H_
> -#define _DPU_FENCE_H_
> -
> -#include <linux/kernel.h>
> -#include <linux/errno.h>
> -#include <linux/mutex.h>
> -
> -#ifndef CHAR_BIT
> -#define CHAR_BIT 8 /* define this if limits.h not available */
> -#endif
> -
> -#define DPU_FENCE_NAME_SIZE	24
> -
> -/**
> - * struct dpu_fence_context - release/retire fence context/timeline
> structure
> - * @commit_count: Number of detected commits since bootup
> - * @done_count: Number of completed commits since bootup
> - * @drm_id: ID number of owning DRM Object
> - * @ref: kref counter on timeline
> - * @lock: spinlock for fence counter protection
> - * @list_lock: spinlock for timeline protection
> - * @context: fence context
> - * @list_head: fence list to hold all the fence created on this 
> context
> - * @name: name of fence context/timeline
> - */
> -struct dpu_fence_context {
> -	unsigned int commit_count;
> -	unsigned int done_count;
> -	uint32_t drm_id;
> -	struct kref kref;
> -	spinlock_t lock;
> -	spinlock_t list_lock;
> -	u64 context;
> -	struct list_head fence_list_head;
> -	char name[DPU_FENCE_NAME_SIZE];
> -};
> -
> -#if IS_ENABLED(CONFIG_SYNC_FILE)
> -/**
> - * dpu_sync_get - Query sync fence object from a file handle
> - *
> - * On success, this function also increments the refcount of the sync
> fence
> - *
> - * @fd: Integer sync fence handle
> - *
> - * Return: Pointer to sync fence object, or NULL
> - */
> -void *dpu_sync_get(uint64_t fd);
> -
> -/**
> - * dpu_sync_put - Releases a sync fence object acquired by 
> @dpu_sync_get
> - *
> - * This function decrements the sync fence's reference count; the 
> object
> will
> - * be released if the reference count goes to zero.
> - *
> - * @fence: Pointer to sync fence
> - */
> -void dpu_sync_put(void *fence);
> -
> -/**
> - * dpu_sync_wait - Query sync fence object from a file handle
> - *
> - * @fence: Pointer to sync fence
> - * @timeout_ms: Time to wait, in milliseconds. Waits forever if
> timeout_ms < 0
> - *
> - * Return:
> - * Zero if timed out
> - * -ERESTARTSYS if wait interrupted
> - * remaining jiffies in all other success cases.
> - */
> -signed long dpu_sync_wait(void *fence, long timeout_ms);
> -
> -/**
> - * dpu_sync_get_name_prefix - get integer representation of fence name
> prefix
> - * @fence: Pointer to opaque fence structure
> - *
> - * Return: 32-bit integer containing first 4 characters of fence name,
> - *         big-endian notation
> - */
> -uint32_t dpu_sync_get_name_prefix(void *fence);
> -
> -/**
> - * dpu_fence_init - initialize fence object
> - * @fence: Pointer to crtc fence object
> - * @drm_id: ID number of owning DRM Object
> - * @name: Timeline name
> - * Returns: Zero on success
> - */
> -int dpu_fence_init(struct dpu_fence_context *fence,
> -		const char *name,
> -		uint32_t drm_id);
> -
> -/**
> - * dpu_fence_deinit - deinit fence container
> - * @fence: Pointer fence container
> - */
> -void dpu_fence_deinit(struct dpu_fence_context *fence);
> -
> -/**
> - * dpu_fence_prepare - prepare to return fences for current commit
> - * @fence: Pointer fence container
> - * Returns: Zero on success
> - */
> -void dpu_fence_prepare(struct dpu_fence_context *fence);
> -/**
> - * dpu_fence_create - create output fence object
> - * @fence: Pointer fence container
> - * @val: Pointer to output value variable, fence fd will be placed 
> here
> - * @offset: Fence signal commit offset, e.g., +1 to signal on next 
> commit
> - * Returns: Zero on success
> - */
> -int dpu_fence_create(struct dpu_fence_context *fence, uint64_t *val,
> -							uint32_t offset);
> -
> -/**
> - * dpu_fence_signal - advance fence timeline to signal outstanding 
> fences
> - * @fence: Pointer fence container
> - * @ts: fence timestamp
> - * @reset_timeline: reset the fence timeline to done count equal to
> commit count
> - */
> -void dpu_fence_signal(struct dpu_fence_context *fence, ktime_t ts,
> -		bool reset_timeline);
> -#else
> -static inline void *dpu_sync_get(uint64_t fd)
> -{
> -	return NULL;
> -}
> -
> -static inline void dpu_sync_put(void *fence)
> -{
> -}
> -
> -static inline signed long dpu_sync_wait(void *fence, long timeout_ms)
> -{
> -	return 0;
> -}
> -
> -static inline uint32_t dpu_sync_get_name_prefix(void *fence)
> -{
> -	return 0x0;
> -}
> -static inline int dpu_fence_init(struct dpu_fence_context *fence,
> -		const char *name,
> -		uint32_t drm_id)
> -{
> -	/* do nothing */
> -	return 0;
> -}
> -
> -static inline void dpu_fence_deinit(struct dpu_fence_context *fence)
> -{
> -	/* do nothing */
> -}
> -
> -static inline int dpu_fence_get(struct dpu_fence_context *fence, 
> uint64_t
> *val)
> -{
> -	return -EINVAL;
> -}
> -
> -static inline void dpu_fence_signal(struct dpu_fence_context *fence,
> -						ktime_t ts, bool
> reset_timeline)
> -{
> -	/* do nothing */
> -}
> -
> -static inline void dpu_fence_prepare(struct dpu_fence_context *fence)
> -{
> -	/* do nothing */
> -}
> -
> -static inline int dpu_fence_create(struct dpu_fence_context *fence,
> -						uint64_t *val, uint32_t
> offset)
> -{
> -	return 0;
> -}
> -#endif /* IS_ENABLED(CONFIG_SW_SYNC) */
> -
> -#endif /* _DPU_FENCE_H_ */
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> index 29e72b39fd72..610e616f2e74 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> @@ -27,7 +27,6 @@
>  #include "msm_drv.h"
> 
>  #include "dpu_kms.h"
> -#include "dpu_fence.h"
>  #include "dpu_formats.h"
>  #include "dpu_hw_sspp.h"
>  #include "dpu_hw_catalog_format.h"
> @@ -676,26 +675,6 @@ static void _dpu_plane_set_ts_prefill(struct
> drm_plane *plane,
>  			pstate->multirect_index);
>  }
> 
> -/* helper to update a state's input fence pointer from the property */
> -static void _dpu_plane_set_input_fence(struct dpu_plane *pdpu,
> -		struct dpu_plane_state *pstate, uint64_t fd)
> -{
> -	if (!pdpu || !pstate) {
> -		DPU_ERROR("invalid arg(s), plane %d state %d\n",
> -				pdpu != 0, pstate != 0);
> -		return;
> -	}
> -
> -	/* clear previous reference */
> -	if (pstate->input_fence)
> -		dpu_sync_put(pstate->input_fence);
> -
> -	/* get fence pointer for later */
> -	pstate->input_fence = dpu_sync_get(fd);
> -
> -	DPU_DEBUG_PLANE(pdpu, "0x%llX\n", fd);
> -}
> -
>  /**
>   * _dpu_plane_inline_rot_set_ot_limit - set OT limit for the given 
> inline
>   * rotation xin client
> @@ -780,64 +759,6 @@ static void
> _dpu_plane_inline_rot_set_qos_remap(struct drm_plane *plane,
>  	dpu_vbif_set_qos_remap(dpu_kms, &qos_params);
>  }
> 
> -int dpu_plane_wait_input_fence(struct drm_plane *plane, uint32_t 
> wait_ms)
> -{
> -	struct dpu_plane *pdpu;
> -	struct dpu_plane_state *pstate;
> -	uint32_t prefix;
> -	void *input_fence;
> -	int ret = -EINVAL;
> -	signed long rc;
> -
> -	if (!plane) {
> -		DPU_ERROR("invalid plane\n");
> -	} else if (!plane->state) {
> -		DPU_ERROR_PLANE(to_dpu_plane(plane), "invalid state\n");
> -	} else {
> -		pdpu = to_dpu_plane(plane);
> -		pstate = to_dpu_plane_state(plane->state);
> -		input_fence = pstate->input_fence;
> -
> -		if (input_fence) {
> -			pdpu->is_error = false;
> -			prefix = dpu_sync_get_name_prefix(input_fence);
> -			rc = dpu_sync_wait(input_fence, wait_ms);
> -
> -			switch (rc) {
> -			case 0:
> -				DPU_ERROR_PLANE(pdpu, "%ums timeout on
> %08X\n",
> -						wait_ms, prefix);
> -				pdpu->is_error = true;
> -				ret = -ETIMEDOUT;
> -				break;
> -			case -ERESTARTSYS:
> -				DPU_ERROR_PLANE(pdpu,
> -					"%ums wait interrupted on %08X\n",
> -					wait_ms, prefix);
> -				pdpu->is_error = true;
> -				ret = -ERESTARTSYS;
> -				break;
> -			case -EINVAL:
> -				DPU_ERROR_PLANE(pdpu,
> -					"invalid fence param for %08X\n",
> -						prefix);
> -				pdpu->is_error = true;
> -				ret = -EINVAL;
> -				break;
> -			default:
> -				DPU_DEBUG_PLANE(pdpu, "signaled\n");
> -				ret = 0;
> -				break;
> -			}
> -
> -			DPU_EVT32_VERBOSE(DRMID(plane), -ret, prefix);
> -		} else {
> -			ret = 0;
> -		}
> -	}
> -	return ret;
> -}
> -
>  /**
>   * _dpu_plane_get_aspace: gets the address space
>   */
> @@ -3332,7 +3253,6 @@ static int dpu_plane_sspp_atomic_update(struct
> drm_plane *plane,
>  			break;
>  		case PLANE_PROP_INFO:
>  		case PLANE_PROP_ALPHA:
> -		case PLANE_PROP_INPUT_FENCE:
>  		case PLANE_PROP_BLEND_OP:
>  			/* no special action required */
>  			break;
> @@ -3703,10 +3623,6 @@ static void _dpu_plane_install_properties(struct
> drm_plane *plane,
>  	msm_property_install_range(&pdpu->property_info, "alpha",
>  		0x0, 0, 255, 255, PLANE_PROP_ALPHA);
> 
> -	/* linux default file descriptor range on each process */
> -	msm_property_install_range(&pdpu->property_info, "input_fence",
> -		0x0, 0, INR_OPEN_MAX, 0, PLANE_PROP_INPUT_FENCE);
> -
>  	if (!master_plane_id) {
>  		if (pdpu->pipe_sblk->maxhdeciexp) {
>  			msm_property_install_range(&pdpu->property_info,
> @@ -4076,9 +3992,6 @@ static int dpu_plane_atomic_set_property(struct
> drm_plane *plane,
>  			idx = msm_property_index(&pdpu->property_info,
>  					property);
>  			switch (idx) {
> -			case PLANE_PROP_INPUT_FENCE:
> -				_dpu_plane_set_input_fence(pdpu, pstate,
> val);
> -				break;
>  			case PLANE_PROP_CSC_V1:
>  				_dpu_plane_set_csc_v1(pdpu, (void *)val);
>  				break;
> @@ -4190,10 +4103,6 @@ static void dpu_plane_destroy_state(struct
> drm_plane *plane,
>  	if (state->fb)
>  		drm_framebuffer_put(state->fb);
> 
> -	/* remove ref count for fence */
> -	if (pstate->input_fence)
> -		dpu_sync_put(pstate->input_fence);
> -
>  	/* destroy value helper */
>  	msm_property_destroy_state(&pdpu->property_info, pstate,
>  			&pstate->property_state);
> @@ -4206,7 +4115,6 @@ dpu_plane_duplicate_state(struct drm_plane 
> *plane)
>  	struct dpu_plane_state *pstate;
>  	struct dpu_plane_state *old_state;
>  	struct drm_property *drm_prop;
> -	uint64_t input_fence_default;
> 
>  	if (!plane) {
>  		DPU_ERROR("invalid plane\n");
> @@ -4230,18 +4138,6 @@ dpu_plane_duplicate_state(struct drm_plane 
> *plane)
>  	msm_property_duplicate_state(&pdpu->property_info, old_state,
> pstate,
>  			&pstate->property_state, pstate->property_values);
> 
> -	/* clear out any input fence */
> -	pstate->input_fence = 0;
> -	input_fence_default = msm_property_get_default(
> -			&pdpu->property_info, PLANE_PROP_INPUT_FENCE);
> -	drm_prop = msm_property_index_to_drm_property(
> -				&pdpu->property_info,
> PLANE_PROP_INPUT_FENCE);
> -	if (msm_property_atomic_set(&pdpu->property_info,
> -				&pstate->property_state, drm_prop,
> -				input_fence_default))
> -		DPU_DEBUG_PLANE(pdpu,
> -				"error clearing duplicated input
> fence\n");
> -
>  	pstate->dirty = 0x0;
>  	pstate->pending = false;
> 
> diff --git a/drivers/gpu/drm/msm/msm_drv.h 
> b/drivers/gpu/drm/msm/msm_drv.h
> index 657ea052a1ee..75a24b81c89a 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -99,7 +99,6 @@ enum msm_mdp_plane_property {
>  	PLANE_PROP_COLOR_FILL,
>  	PLANE_PROP_H_DECIMATE,
>  	PLANE_PROP_V_DECIMATE,
> -	PLANE_PROP_INPUT_FENCE,
>  	PLANE_PROP_HUE_ADJUST,
>  	PLANE_PROP_SATURATION_ADJUST,
>  	PLANE_PROP_VALUE_ADJUST,
> @@ -131,8 +130,7 @@ enum msm_mdp_crtc_property {
>  	CRTC_PROP_BLOBCOUNT,
> 
>  	/* range properties */
> -	CRTC_PROP_INPUT_FENCE_TIMEOUT = CRTC_PROP_BLOBCOUNT,
> -	CRTC_PROP_DIM_LAYER_V1,
> +	CRTC_PROP_DIM_LAYER_V1 = CRTC_PROP_BLOBCOUNT,
>  	CRTC_PROP_CORE_CLK,
>  	CRTC_PROP_CORE_AB,
>  	CRTC_PROP_CORE_IB,

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 05/11] drm/msm: Mark the crtc->state->event consumed
  2018-02-28 19:19   ` [DPU PATCH 05/11] drm/msm: Mark the crtc->state->event consumed Sean Paul
@ 2018-03-06  1:53     ` Jeykumar Sankaran
  0 siblings, 0 replies; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-06  1:53 UTC (permalink / raw)
  To: Sean Paul; +Cc: linux-arm-msm, abhinavk, dri-devel, hoegsberg, freedreno

On 2018-02-28 11:19, Sean Paul wrote:
> Don't leave the event != NULL once it's consumed, this is used a signal
> to the atomic helpers that the event will be handled by the driver.
> 
> Change-Id: Ib934fb2e97bacbb4a1f9c780cc7369c2bb98ed50
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>

> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  | 2 ++
>  drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c | 1 +
>  drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 1 +
>  3 files changed, 4 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 94fab2dcca5b..a261021e5deb 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -2714,6 +2714,7 @@ static void dpu_crtc_atomic_begin(struct drm_crtc
> *crtc,
>  	} else {
>  		spin_lock_irqsave(&dev->event_lock, flags);
>  		dpu_crtc->event = crtc->state->event;
> +		crtc->state->event = NULL;
>  		spin_unlock_irqrestore(&dev->event_lock, flags);
>  	}
> 
> @@ -2798,6 +2799,7 @@ static void dpu_crtc_atomic_flush(struct drm_crtc
> *crtc,
>  	} else {
>  		spin_lock_irqsave(&dev->event_lock, flags);
>  		dpu_crtc->event = crtc->state->event;
> +		crtc->state->event = NULL;
>  		spin_unlock_irqrestore(&dev->event_lock, flags);
>  	}
> 
> diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
> b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
> index 6e5e1aa54ce1..b001699297c4 100644
> --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
> @@ -351,6 +351,7 @@ static void mdp4_crtc_atomic_flush(struct drm_crtc
> *crtc,
> 
>  	spin_lock_irqsave(&dev->event_lock, flags);
>  	mdp4_crtc->event = crtc->state->event;
> +	crtc->state->event = NULL;
>  	spin_unlock_irqrestore(&dev->event_lock, flags);
> 
>  	blend_setup(crtc);
> diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
> b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
> index 8c5ed0b59e46..5cb490a58f20 100644
> --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
> @@ -704,6 +704,7 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc
> *crtc,
> 
>  	spin_lock_irqsave(&dev->event_lock, flags);
>  	mdp5_crtc->event = crtc->state->event;
> +	crtc->state->event = NULL;
>  	spin_unlock_irqrestore(&dev->event_lock, flags);
> 
>  	/*

-- 
Jeykumar S
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 02/11] drm/msm: Don't duplicate modeset_enables atomic helper
       [not found]     ` <20180228191906.185417-3-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-09  0:56       ` Jeykumar Sankaran
       [not found]         ` <aaf8f07e18801c60cdf7eb30b0cac123-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-09  0:56 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-02-28 11:18, Sean Paul wrote:
> Instead, shuffle things around so we kickoff crtc after enabling 
> encoder
> during modesets. Also moves the vblank wait to after the frame.
> 
> Change-Id: I16c7b7f9390d04f6050aa20e17a5335fbf49eba3
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   9 ++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   5 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c     |  31 ++++-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |   2 +
>  drivers/gpu/drm/msm/msm_atomic.c            | 132 +-------------------
>  5 files changed, 48 insertions(+), 131 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index a3ab6ed2bf1d..94fab2dcca5b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -3525,6 +3525,12 @@ static void dpu_crtc_enable(struct drm_crtc 
> *crtc,
>  	DPU_EVT32_VERBOSE(DRMID(crtc));
>  	dpu_crtc = to_dpu_crtc(crtc);
> 
> +	if (msm_is_mode_seamless(&crtc->state->adjusted_mode) ||
> +	    msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode)) {
> +		DPU_DEBUG("Skipping crtc enable, seamless mode\n");
> +		return;
> +	}
> +
>  	pm_runtime_get_sync(crtc->dev->dev);
> 
>  	drm_for_each_encoder(encoder, crtc->dev) {
> @@ -3572,6 +3578,9 @@ static void dpu_crtc_enable(struct drm_crtc 
> *crtc,
>  		DPU_POWER_EVENT_POST_ENABLE | DPU_POWER_EVENT_POST_DISABLE
> |
>  		DPU_POWER_EVENT_PRE_DISABLE,
>  		dpu_crtc_handle_power_event, crtc, dpu_crtc->name);
> +
> +	if (msm_needs_vblank_pre_modeset(&crtc->state->adjusted_mode))
> +		drm_crtc_wait_one_vblank(crtc);
>  }
> 
>  struct plane_state {
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 28ceb589ee40..4d1e3652dbf4 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -3693,8 +3693,11 @@ static void 
> dpu_encoder_frame_done_timeout(struct
> timer_list *t)
>  static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs 
> = {
>  	.mode_set = dpu_encoder_virt_mode_set,
>  	.disable = dpu_encoder_virt_disable,
> -	.enable = dpu_encoder_virt_enable,
> +	.enable = dpu_kms_encoder_enable,
>  	.atomic_check = dpu_encoder_virt_atomic_check,
> +
> +	/* This is called by dpu_kms_encoder_enable */
> +	.commit = dpu_encoder_virt_enable,
>  };
> 
>  static const struct drm_encoder_funcs dpu_encoder_funcs = {
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> index 81fd3a429e9f..3d83037e8305 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> @@ -425,14 +425,37 @@ static void dpu_kms_prepare_commit(struct msm_kms
> *kms,
>  			dpu_encoder_prepare_commit(encoder);
>  }
> 
> -static void dpu_kms_commit(struct msm_kms *kms,
> -		struct drm_atomic_state *old_state)
> +/*
> + * Override the encoder enable since we need to setup the inline 
> rotator
> and do
> + * some crtc magic before enabling any bridge that might be present.
> + */
> +void dpu_kms_encoder_enable(struct drm_encoder *encoder)
> +{
> +	const struct drm_encoder_helper_funcs *funcs =
> encoder->helper_private;
> +	struct drm_crtc *crtc = encoder->crtc;
> +
> +	/* Forward this enable call to the commit hook */
> +	if (funcs && funcs->commit)
> +		funcs->commit(encoder);

The purpose of this function is not clear. Where are we setting up the 
inline rotator?
Why do we need a kickoff here?
> +
> +	if (crtc && crtc->state->active) {
> +		DPU_EVT32(DRMID(crtc));
> +		dpu_crtc_commit_kickoff(crtc);
> +	}
> +}
> +
> +static void dpu_kms_commit(struct msm_kms *kms, struct 
> drm_atomic_state
> *state)
>  {
>  	struct drm_crtc *crtc;
> -	struct drm_crtc_state *old_crtc_state;
> +	struct drm_crtc_state *crtc_state;
> +	struct dpu_crtc_state *cstate;
>  	int i;
> 
> -	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
> +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +		/* If modeset is required, kickoff is run in
> encoder_enable */
> +		if (drm_atomic_crtc_needs_modeset(crtc_state))
> +			continue;
> +
>  		if (crtc->state->active) {
>  			DPU_EVT32(DRMID(crtc));
>  			dpu_crtc_commit_kickoff(crtc);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index 8cadd29a48b1..42c809ed9467 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -529,4 +529,6 @@ int dpu_kms_fbo_reference(struct dpu_kms_fbo *fbo);
>   */
>  void dpu_kms_fbo_unreference(struct dpu_kms_fbo *fbo);
> 
> +void dpu_kms_encoder_enable(struct drm_encoder *encoder);
> +
>  #endif /* __dpu_kms_H__ */
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> b/drivers/gpu/drm/msm/msm_atomic.c
> index 5cfb80345052..f5794dce25dd 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -84,131 +84,6 @@ static void msm_atomic_wait_for_commit_done(
>  	}
>  }
> 
> -/**
> - * msm_atomic_helper_commit_modeset_enables - modeset commit to enable
> outputs
> - * @dev: DRM device
> - * @old_state: atomic state object with old state structures
> - *
> - * This function enables all the outputs with the new configuration 
> which
> had to
> - * be turned off for the update.
> - *
> - * For compatibility with legacy crtc helpers this should be called 
> after
> - * drm_atomic_helper_commit_planes(), which is what the default commit
> function
> - * does. But drivers with different needs can group the modeset 
> commits
> together
> - * and do the plane commits at the end. This is useful for drivers 
> doing
> runtime
> - * PM since planes updates then only happen when the CRTC is actually
> enabled.
> - */
> -static void msm_atomic_helper_commit_modeset_enables(struct drm_device
> *dev,
> -		struct drm_atomic_state *old_state)
> -{
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *old_crtc_state;
> -	struct drm_crtc_state *new_crtc_state;
> -	struct drm_connector *connector;
> -	struct drm_connector_state *new_conn_state;
> -	struct msm_drm_private *priv = dev->dev_private;
> -	struct msm_kms *kms = priv->kms;
> -	int bridge_enable_count = 0;
> -	int i;
> -
> -	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
> -			new_crtc_state, i) {
> -		const struct drm_crtc_helper_funcs *funcs;
> -
> -		/* Need to filter out CRTCs where only planes change. */
> -		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
> -			continue;
> -
> -		if (!new_crtc_state->active)
> -			continue;
> -
> -		if (msm_is_mode_seamless(&new_crtc_state->mode) ||
> -				msm_is_mode_seamless_vrr(
> -				&new_crtc_state->adjusted_mode))
> -			continue;
> -
> -		funcs = crtc->helper_private;
> -
> -		if (crtc->state->enable) {
> -			DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n",
> -					 crtc->base.id);
> -
> -			if (funcs->atomic_enable)
> -				funcs->atomic_enable(crtc,
> old_crtc_state);
> -			else
> -				funcs->commit(crtc);
> -		}
> -
> -		if (msm_needs_vblank_pre_modeset(
> -					&new_crtc_state->adjusted_mode))
> -			drm_crtc_wait_one_vblank(crtc);
> -	}
> -
> -	/* ensure bridge/encoder updates happen on same vblank */
> -	msm_atomic_wait_for_commit_done(dev, old_state);
> -
> -	for_each_new_connector_in_state(old_state, connector,
> -			new_conn_state, i) {
> -		const struct drm_encoder_helper_funcs *funcs;
> -		struct drm_encoder *encoder;
> -
> -		if (!new_conn_state->best_encoder)
> -			continue;
> -
> -		if (!new_conn_state->crtc->state->active ||
> -		    !drm_atomic_crtc_needs_modeset(
> -			    new_conn_state->crtc->state))
> -			continue;
> -
> -		encoder = new_conn_state->best_encoder;
> -		funcs = encoder->helper_private;
> -
> -		DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
> -				 encoder->base.id, encoder->name);
> -
> -		/*
> -		 * Each encoder has at most one connector (since we always
> steal
> -		 * it away), so we won't call enable hooks twice.
> -		 */
> -		drm_bridge_pre_enable(encoder->bridge);
> -		++bridge_enable_count;
> -
> -		if (funcs->enable)
> -			funcs->enable(encoder);
> -		else
> -			funcs->commit(encoder);
> -	}
> -
> -	if (kms->funcs->commit) {
> -		DRM_DEBUG_ATOMIC("triggering commit\n");
> -		kms->funcs->commit(kms, old_state);
> -	}
> -
> -	/* If no bridges were pre_enabled, skip iterating over them again
> */
> -	if (bridge_enable_count == 0)
> -		return;
> -
> -	for_each_new_connector_in_state(old_state, connector,
> -			new_conn_state, i) {
> -		struct drm_encoder *encoder;
> -
> -		if (!new_conn_state->best_encoder)
> -			continue;
> -
> -		if (!new_conn_state->crtc->state->active ||
> -		    !drm_atomic_crtc_needs_modeset(
> -				    new_conn_state->crtc->state))
> -			continue;
> -
> -		encoder = new_conn_state->best_encoder;
> -
> -		DRM_DEBUG_ATOMIC("bridge enable enabling
> [ENCODER:%d:%s]\n",
> -				 encoder->base.id, encoder->name);
> -
> -		drm_bridge_enable(encoder->bridge);
> -	}
> -}
> -
>  /* The (potentially) asynchronous part of the commit.  At this point
>   * nothing can fail short of armageddon.
>   */
> @@ -227,7 +102,12 @@ static void complete_commit(struct msm_commit *c)
> 
>  	drm_atomic_helper_commit_planes(dev, state, 0);
> 
> -	msm_atomic_helper_commit_modeset_enables(dev, state);
> +	drm_atomic_helper_commit_modeset_enables(dev, state);
> +
> +	if (kms->funcs->commit) {
> +		DRM_DEBUG_ATOMIC("triggering commit\n");
> +		kms->funcs->commit(kms, state);
> +	}
> 
>  	/* NOTE: _wait_for_vblanks() only waits for vblank on
>  	 * enabled CRTCs.  So we end up faulting when disabling

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 03/11] drm/msm: Refactor complete_commit() to look more the helpers
       [not found]     ` <20180228191906.185417-4-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-09  1:01       ` Jeykumar Sankaran
  0 siblings, 0 replies; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-09  1:01 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-02-28 11:18, Sean Paul wrote:
> Factor out the commit_tail() portions of complete_commit() into a
> separate function to facilitate moving to the atomic helpers in future
> patches.
> 
> Change-Id: I4b858ad9fe356b31ed0ed9eecdb394a61048e39c
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>

> ---
>  drivers/gpu/drm/msm/msm_atomic.c | 25 ++++++++++++++++---------
>  1 file changed, 16 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> b/drivers/gpu/drm/msm/msm_atomic.c
> index f5794dce25dd..eb2ccda5da0f 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -84,18 +84,12 @@ static void msm_atomic_wait_for_commit_done(
>  	}
>  }
> 
> -/* The (potentially) asynchronous part of the commit.  At this point
> - * nothing can fail short of armageddon.
> - */
> -static void complete_commit(struct msm_commit *c)
> +static void msm_atomic_commit_tail(struct drm_atomic_state *state)
>  {
> -	struct drm_atomic_state *state = c->state;
>  	struct drm_device *dev = state->dev;
>  	struct msm_drm_private *priv = dev->dev_private;
>  	struct msm_kms *kms = priv->kms;
> 
> -	drm_atomic_helper_wait_for_fences(dev, state, false);
> -
>  	kms->funcs->prepare_commit(kms, state);
> 
>  	drm_atomic_helper_commit_modeset_disables(dev, state);
> @@ -127,10 +121,21 @@ static void complete_commit(struct msm_commit *c)
>  	drm_atomic_helper_cleanup_planes(dev, state);
> 
>  	kms->funcs->complete_commit(kms, state);
> +}
> 
> -	drm_atomic_state_put(state);
> +/* The (potentially) asynchronous part of the commit.  At this point
> + * nothing can fail short of armageddon.
> + */
> +static void complete_commit(struct msm_commit *c)
> +{
> +	struct drm_atomic_state *state = c->state;
> +	struct drm_device *dev = state->dev;
> 
> -	commit_destroy(c);
> +	drm_atomic_helper_wait_for_fences(dev, state, false);
> +
> +	msm_atomic_commit_tail(state);
> +
> +	drm_atomic_state_put(state);
>  }
> 
>  static void _msm_drm_commit_work_cb(struct kthread_work *work)
> @@ -145,6 +150,8 @@ static void _msm_drm_commit_work_cb(struct
> kthread_work *work)
>  	commit = container_of(work, struct msm_commit, commit_work);
> 
>  	complete_commit(commit);
> +
> +	commit_destroy(commit);
>  }
> 
>  static struct msm_commit *commit_init(struct drm_atomic_state *state,

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
  2018-03-02 14:56                   ` Sean Paul
@ 2018-03-09  1:08                     ` Jeykumar Sankaran
  2018-03-12 20:23                       ` Sean Paul
  0 siblings, 1 reply; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-09  1:08 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm, abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, Rob Clark,
	dri-devel, Kristian H. Kristensen, freedreno

On 2018-03-02 06:56, Sean Paul wrote:
> On Thu, Mar 01, 2018 at 07:37:10PM -0500, Rob Clark wrote:
>> On Thu, Mar 1, 2018 at 3:37 PM,  <jsanka@codeaurora.org> wrote:
>> > On 2018-03-01 07:27, Sean Paul wrote:
>> >>
>> >> On Wed, Feb 28, 2018 at 08:07:00PM -0800, jsanka@codeaurora.org
> wrote:
>> >>>
>> >>> On 2018-02-28 11:19, Sean Paul wrote:
>> >>> > Moving further towards switching fully to the the atomic helpers,
> this
>> >>> > patch removes the hand-rolled kthread nonblock commit code and
> uses
>> >>
>> >> the
>> >>>
>> >>> > atomic helpers commit_work model.
>> >>> >
>> >>> > There's still a lot of copypasta here, but it's still needed to
>> >>> > facilitate the swap_state and prepare_fence private functions.
> These
>> >>> > will be sorted out in a follow-on patch.
>> >>> >
>> >>> > Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
>> >>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> >>> > ---
>> >>> >  drivers/gpu/drm/msm/msm_atomic.c | 199
>> >>
>> >> ++++++-------------------------
>> >>>
>> >>> >  drivers/gpu/drm/msm/msm_drv.c    |   1 -
>> >>> >  drivers/gpu/drm/msm/msm_drv.h    |   4 -
>> >>> >  3 files changed, 35 insertions(+), 169 deletions(-)
>> >>> >
>> >>> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
>> >>> > b/drivers/gpu/drm/msm/msm_atomic.c
>> >>> > index 3a18bd3dc215..7e54eb65d096 100644
>> >>> > --- a/drivers/gpu/drm/msm/msm_atomic.c
>> >>> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> >>> > @@ -21,51 +21,6 @@
>> >>> >  #include "msm_gem.h"
>> >>> >  #include "msm_fence.h"
>> >>> >
>> >>> > -struct msm_commit {
>> >>> > -     struct drm_device *dev;
>> >>> > -     struct drm_atomic_state *state;
>> >>> > -     uint32_t crtc_mask;
>> >>> > -     bool nonblock;
>> >>> > -     struct kthread_work commit_work;
>> >>> > -};
>> >>> > -
>> >>> > -/* block until specified crtcs are no longer pending update, and
>> >>> > - * atomically mark them as pending update
>> >>> > - */
>> >>> > -static int start_atomic(struct msm_drm_private *priv, uint32_t
>> >>> > crtc_mask)
>> >>> > -{
>> >>> > -     int ret;
>> >>> > -
>> >>> > -     spin_lock(&priv->pending_crtcs_event.lock);
>> >>> > -     ret =
> wait_event_interruptible_locked(priv->pending_crtcs_event,
>> >>> > -                     !(priv->pending_crtcs & crtc_mask));
>> >>> > -     if (ret == 0) {
>> >>> > -             DBG("start: %08x", crtc_mask);
>> >>> > -             priv->pending_crtcs |= crtc_mask;
>> >>> > -     }
>> >>> > -     spin_unlock(&priv->pending_crtcs_event.lock);
>> >>> > -
>> >>> > -     return ret;
>> >>> > -}
>> >>> > -
>> >>> > -/* clear specified crtcs (no longer pending update)
>> >>> > - */
>> >>> > -static void end_atomic(struct msm_drm_private *priv, uint32_t
>> >>> > crtc_mask)
>> >>> > -{
>> >>> > -     spin_lock(&priv->pending_crtcs_event.lock);
>> >>> > -     DBG("end: %08x", crtc_mask);
>> >>> > -     priv->pending_crtcs &= ~crtc_mask;
>> >>> > -     wake_up_all_locked(&priv->pending_crtcs_event);
>> >>> > -     spin_unlock(&priv->pending_crtcs_event.lock);
>> >>> > -}
>> >>> > -
>> >>> > -static void commit_destroy(struct msm_commit *c)
>> >>> > -{
>> >>> > -     end_atomic(c->dev->dev_private, c->crtc_mask);
>> >>> > -     if (c->nonblock)
>> >>> > -             kfree(c);
>> >>> > -}
>> >>> > -
>> >>> >  static void msm_atomic_wait_for_commit_done(
>> >>> >               struct drm_device *dev,
>> >>> >               struct drm_atomic_state *old_state)
>> >>> > @@ -118,6 +73,10 @@ static void msm_atomic_commit_tail(struct
>> >>> > drm_atomic_state *state)
>> >>> >
>> >>> >       msm_atomic_wait_for_commit_done(dev, state);
>> >>> >
>> >>> > +     drm_atomic_helper_commit_hw_done(state);
>> >>> > +
>> >>> > +     drm_atomic_helper_wait_for_vblanks(dev, state);
>> >>> > +
>> >>> >       drm_atomic_helper_cleanup_planes(dev, state);
>> >>> >
>> >>> >       kms->funcs->complete_commit(kms, state);
>> >>> > @@ -126,109 +85,25 @@ static void msm_atomic_commit_tail(struct
>> >>> > drm_atomic_state *state)
>> >>> >  /* The (potentially) asynchronous part of the commit.  At this
> point
>> >>> >   * nothing can fail short of armageddon.
>> >>> >   */
>> >>> > -static void complete_commit(struct msm_commit *c)
>> >>> > +static void commit_tail(struct drm_atomic_state *state)
>> >>> >  {
>> >>> > -     struct drm_atomic_state *state = c->state;
>> >>> > -     struct drm_device *dev = state->dev;
>> >>> > +     drm_atomic_helper_wait_for_fences(state->dev, state, false);
>> >>> >
>> >>> > -     drm_atomic_helper_wait_for_fences(dev, state, false);
>> >>> > +     drm_atomic_helper_wait_for_dependencies(state);
>> >>> >
>> >>> >       msm_atomic_commit_tail(state);
>> >>> >
>> >>> > -     drm_atomic_state_put(state);
>> >>> > -}
>> >>> > -
>> >>> > -static void _msm_drm_commit_work_cb(struct kthread_work *work)
>> >>> > -{
>> >>> > -     struct msm_commit *commit =  NULL;
>> >>> > -
>> >>> > -     if (!work) {
>> >>> > -             DRM_ERROR("%s: Invalid commit work data!\n",
> __func__);
>> >>> > -             return;
>> >>> > -     }
>> >>> > -
>> >>> > -     commit = container_of(work, struct msm_commit, commit_work);
>> >>> > -
>> >>> > -     complete_commit(commit);
>> >>> > -
>> >>> > -     commit_destroy(commit);
>> >>> > -}
>> >>> > -
>> >>> > -static struct msm_commit *commit_init(struct drm_atomic_state
> *state,
>> >>> > -             bool nonblock)
>> >>> > -{
>> >>> > -     struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
>> >>> > +     drm_atomic_helper_commit_cleanup_done(state);
>> >>> >
>> >>> > -     if (!c)
>> >>> > -             return NULL;
>> >>> > -
>> >>> > -     c->dev = state->dev;
>> >>> > -     c->state = state;
>> >>> > -     c->nonblock = nonblock;
>> >>> > -
>> >>> > -     kthread_init_work(&c->commit_work, _msm_drm_commit_work_cb);
>> >>> > -
>> >>> > -     return c;
>> >>> > +     drm_atomic_state_put(state);
>> >>> >  }
>> >>> >
>> >>> > -/* Start display thread function */
>> >>> > -static void msm_atomic_commit_dispatch(struct drm_device *dev,
>> >>> > -             struct drm_atomic_state *state, struct msm_commit
>> >>> > *commit)
>> >>> > +static void commit_work(struct work_struct *work)
>> >>> >  {
>> >>> > -     struct msm_drm_private *priv = dev->dev_private;
>> >>> > -     struct drm_crtc *crtc = NULL;
>> >>> > -     struct drm_crtc_state *new_crtc_state = NULL;
>> >>> > -     int ret = -EINVAL, i = 0, j = 0;
>> >>> > -     bool nonblock;
>> >>> > -
>> >>> > -     /* cache since work will kfree commit in non-blocking case
> */
>> >>> > -     nonblock = commit->nonblock;
>> >>> > -
>> >>> > -     for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
>> >>> > -             for (j = 0; j < priv->num_crtcs; j++) {
>> >>> > -                     if (priv->disp_thread[j].crtc_id ==
>> >>> > -                                             crtc->base.id) {
>> >>> > -                             if (priv->disp_thread[j].thread) {
>> >>> > -                                     kthread_queue_work(
>> >>> > -
>> >>> > &priv->disp_thread[j].worker,
>> >>> > -
>> >>> > &commit->commit_work);
>> >>> Are there any known proposals floating around to support ASYNC
> commits
>> >>
>> >> for
>> >>>
>> >>> concurrent displays rendering at different FPS? The above kthread
> model
>> >>
>> >> is
>> >>>
>> >>> introduced when we faced some performance road blockers when a
> display
>> >>
>> >> has
>> >>>
>> >>> to wait for an ongoing display commit to complete.
>> >>
>> >>
>> >> I think people have discussed it, I'm not sure if there are any
> patches
>> >> floating
>> >> around. On the surface, it seems easy to just push the commit_work
> into
>> >> the crtc
>> >> commit and have one work item per crtc. However I think the problem
> is
>> >> that there
>> >> could be resources switching between crtcs for a given commit, or
> from one
>> >> commit
>> >> to the next, and synchronizing that becomes a Hard Problem.
>> >>
>> >> Perhaps I'm misunderstanding, but the start/end atomic functions
> serialize
>> >> the
>> >> incoming commits, right? So the only benefit the kthread provides is
> to
>> >> mitigate
>> >> any blocking calls made on one crtc from blocking a second crtc in
> the
>> >> same
>> >> commit?
>> >>
>> >> Sean
>> >
>> > I am not sure what level of resource (I assume hw blocks) switching we
> can
>> > expect between
>> > two active CRTC's on successive commits. With virtualization in play,
> the
>> > resources allocated to
>> > CRTC / encoder / Connector will remain attached to the components as
> long as
>> > the display is active.
>> > Planes (HW pipes) are one such entity which can move between the
> CRTC's
>> > frequently. Even
>> > with them planes, the hw assignment should remain valid until the
> plane is
>> > detached from
>> > a CRTC before attaching to the next one.
>> 
>> I think a good example to think about is virtualizing hwpipe<->plane
>> mapping, for example, when you need to re-assign hwpipes for the next
>> frame according to what capabilities are needed (yuv, scaling) or gang
>> up two hwpipes for wide buffer scanout (or re-use one hwpipe for two
>> planes).. in mdp5 we keep track of what hwpipes are in use by which
>> planes in driver global atomic state (I have some revived patches from
>> architt to convert this to driver private objs)..
>> 
>> With the atomic model we have serialization in the (to abuse some
>> terms) "top half" (ie. userspace calling into ioctl) by virtue of the
>> modeset locks.  But there is a second half to this.  Because we update
>> the new incoming global state object about what hwpipes are released
>> in atomic_check, if the incoming state is committed/swapped in the
>> "top half" we rely on this state being valid in the "bottom half" (in
>> this case the wq) before pushing the new state to the hw.. which
>> essentially forces us to serialize committing the state in the "bottom
>> half" so things happen in the same order as the "top half" intended.
>> Otherwise we could try to assign a hwpipe to a different crtc while it
>> is still scanning out for it's previous crtc.  If you have a 30Hz
>> display plus a 120Hz display, I guess this is a bit sub-optimal.
> 
> It's still bad even with displays refreshing at the same rate, the 
> worst
> case
> could halve the refresh rate if vblanks aren't in sync.
> 
>> 
>> Maybe the answer is per-crtc wq's for commits plus some sort of
>> fencing scheme to stall things when there are cross-crtc dependencies
>> (ie. commit on crtc B depends on hwpipe released by commit on crtc A)?
>>  This way we don't block updates on the faster display when it isn't
>> required.  I'm not quite sure how that would work.  But perhaps at
>> least we could somehow allow out-of-order commits when two updates
>> don't touch any of the same state obj's.
> 
> Right, for "normal" updates, you could use the fast path. We already 
> have
> needs_modeset, so adding needs_sync wouldn't be too bad. I think I ran
> into this
> with tegra back in Pixel C days and hacked in a per-crtc worker since 
> the
> resources were statically mapped. We'll probably run into this in CrOS 
> as
> we
> expand our explicit sync support in the compositor.
> 
>> 
>> (But I do think this is something we should discuss on dri-devel, and
>> I'd prefer do solve this in the atomic helpers, rather than having
>> userspace workaround different sets of bugs/quirks for each different
>> driver.  It really isn't something that is hw specific, so it doesn't
>> belong in the driver.)
> 
> Agreed, this is a tricky bit of code and it would benefit from being 
> used
> across
> all drivers (as well as all drivers benefiting from it). At any rate, I
> can't
> use multi-display on my development device right now, so I think we'll
> need to
> defer for now.
> 
> Sean
> 
>> 
>> BR,
>> -R
>> 
>> 
>> > "Start atomic" synchronizes the commit cycle for all the CRTC's by
> waiting
>> > for commit complete
>> > of all the previous frames. But per crtc kthreads allows the current
> frame
>> > commits to happen
>> > independently. For android, we needed this model as each commit thread
> need
>> > to wait for input
>> > plane fences before programming the hardware.
>> >
>> > Jeykumar S.
>> >
>> >>
>> >>> > -                                     /* only return zero if work
> is
>> >>> > -                                      * queued successfully.
>> >>> > -                                      */
>> >>> > -                                     ret = 0;
>> >>> > -                             } else {
>> >>> > -                                     DRM_ERROR(" Error for
> crtc_id:
>> >>> > %d\n",
>> >>> > -
>> >>> > priv->disp_thread[j].crtc_id);
>> >>> > -                             }
>> >>> > -                             break;
>> >>> > -                     }
>> >>> > -             }

Care to remove priv->disp_thread and all its references as a part of 
this change?

- Jeykumar S
>> >>> > -             /*
>> >>> > -              * TODO: handle cases where there will be more than
>> >>> > -              * one crtc per commit cycle. Remove this check
> then.
>> >>> > -              * Current assumption is there will be only one crtc
>> >>> > -              * per commit cycle.
>> >>> > -              */
>> >>> > -             if (j < priv->num_crtcs)
>> >>> > -                     break;
>> >>> > -     }
>> >>> > -
>> >>> > -     if (ret) {
>> >>> > -             /**
>> >>> > -              * this is not expected to happen, but at this point
> the
>> >>> > state
>> >>> > -              * has been swapped, but we couldn't dispatch to a
> crtc
>> >>> > thread.
>> >>> > -              * fallback now to a synchronous complete_commit to
> try
>> >>> > and
>> >>> > -              * ensure that SW and HW state don't get out of
> sync.
>> >>> > -              */
>> >>> > -             DRM_ERROR("failed to dispatch commit to any
> CRTC\n");
>> >>> > -             complete_commit(commit);
>> >>> > -     } else if (!nonblock) {
>> >>> > -             kthread_flush_work(&commit->commit_work);
>> >>> > -     }
>> >>> > -
>> >>> > -     /* free nonblocking commits in this context, after
> processing */
>> >>> > -     if (!nonblock)
>> >>> > -             kfree(commit);
>> >>> > +     struct drm_atomic_state *state = container_of(work,
>> >>> > +                                                   struct
>> >>> > drm_atomic_state,
>> >>> > +                                                   commit_work);
>> >>> > +     commit_tail(state);
>> >>> >  }
>> >>> >
>> >>> >  /**
>> >>> > @@ -247,17 +122,12 @@ int msm_atomic_commit(struct drm_device
> *dev,
>> >>> >               struct drm_atomic_state *state, bool nonblock)
>> >>> >  {
>> >>> >       struct msm_drm_private *priv = dev->dev_private;
>> >>> > -     struct msm_commit *c;
>> >>> >       struct drm_crtc *crtc;
>> >>> >       struct drm_crtc_state *crtc_state;
>> >>> >       struct drm_plane *plane;
>> >>> >       struct drm_plane_state *old_plane_state, *new_plane_state;
>> >>> >       int i, ret;
>> >>> >
>> >>> > -     ret = drm_atomic_helper_prepare_planes(dev, state);
>> >>> > -     if (ret)
>> >>> > -             return ret;
>> >>> > -
>> >>> >       /*
>> >>> >        * Note that plane->atomic_async_check() should fail if we
> need
>> >>> >        * to re-assign hwpipe or anything that touches global
> atomic
>> >>> > @@ -265,32 +135,30 @@ int msm_atomic_commit(struct drm_device
> *dev,
>> >>> >        * cases.
>> >>> >        */
>> >>> >       if (state->async_update) {
>> >>> > +             ret = drm_atomic_helper_prepare_planes(dev, state);
>> >>> > +             if (ret)
>> >>> > +                     return ret;
>> >>> > +
>> >>> >               drm_atomic_helper_async_commit(dev, state);
>> >>> >               drm_atomic_helper_cleanup_planes(dev, state);
>> >>> >               return 0;
>> >>> >       }
>> >>> >
>> >>> > -     c = commit_init(state, nonblock);
>> >>> > -     if (!c) {
>> >>> > -             ret = -ENOMEM;
>> >>> > -             goto error;
>> >>> > -     }
>> >>> > +     ret = drm_atomic_helper_setup_commit(state, nonblock);
>> >>> > +     if (ret)
>> >>> > +             return ret;
>> >>> >
>> >>> > -     /*
>> >>> > -      * Figure out what crtcs we have:
>> >>> > -      */
>> >>> > -     for_each_new_crtc_in_state(state, crtc, crtc_state, i)
>> >>> > -             c->crtc_mask |= drm_crtc_mask(crtc);
>> >>> > +     INIT_WORK(&state->commit_work, commit_work);
>> >>> >
>> >>> > -     /*
>> >>> > -      * Wait for pending updates on any of the same crtc's and
> then
>> >>> > -      * mark our set of crtc's as busy:
>> >>> > -      */
>> >>> > -     ret = start_atomic(dev->dev_private, c->crtc_mask);
>> >>> > +     ret = drm_atomic_helper_prepare_planes(dev, state);
>> >>> >       if (ret)
>> >>> > -             goto err_free;
>> >>> > +             return ret;
>> >>> >
>> >>> > -     BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
>> >>> > +     if (!nonblock) {
>> >>> > +             ret = drm_atomic_helper_wait_for_fences(dev, state,
>> >>> > true);
>> >>> > +             if (ret)
>> >>> > +                     goto error;
>> >>> > +     }
>> >>> >
>> >>> >       /*
>> >>> >        * This is the point of no return - everything below never
> fails
>> >>> > except
>> >>> > @@ -299,6 +167,8 @@ int msm_atomic_commit(struct drm_device *dev,
>> >>> >        *
>> >>> >        * swap driver private state while still holding state_lock
>> >>> >        */
>> >>> > +     BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
>> >>> > +
>> >>> >       if (to_kms_state(state)->state)
>> >>> >               priv->kms->funcs->swap_state(priv->kms, state);
>> >>> >
>> >>> > @@ -329,12 +199,13 @@ int msm_atomic_commit(struct drm_device
> *dev,
>> >>> >        */
>> >>> >
>> >>> >       drm_atomic_state_get(state);
>> >>> > -     msm_atomic_commit_dispatch(dev, state, c);
>> >>> > +     if (nonblock)
>> >>> > +             queue_work(system_unbound_wq, &state->commit_work);
>> >>> > +     else
>> >>> > +             commit_tail(state);
>> >>> >
>> >>> >       return 0;
>> >>> >
>> >>> > -err_free:
>> >>> > -     kfree(c);
>> >>> >  error:
>> >>> >       drm_atomic_helper_cleanup_planes(dev, state);
>> >>> >       return ret;
>> >>> > diff --git a/drivers/gpu/drm/msm/msm_drv.c
>> >>> > b/drivers/gpu/drm/msm/msm_drv.c
>> >>> > index eda4a2340f93..b354424cccb5 100644
>> >>> > --- a/drivers/gpu/drm/msm/msm_drv.c
>> >>> > +++ b/drivers/gpu/drm/msm/msm_drv.c
>> >>> > @@ -549,7 +549,6 @@ static int msm_drm_init(struct device *dev,
> struct
>> >>> > drm_driver *drv)
>> >>> >               goto mdss_init_fail;
>> >>> >
>> >>> >       priv->wq = alloc_ordered_workqueue("msm_drm", 0);
>> >>> > -     init_waitqueue_head(&priv->pending_crtcs_event);
>> >>> >
>> >>> >       INIT_LIST_HEAD(&priv->client_event_list);
>> >>> >       INIT_LIST_HEAD(&priv->inactive_list);
>> >>> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
>> >>> > b/drivers/gpu/drm/msm/msm_drv.h
>> >>> > index cf96a85f4b55..292496b682e8 100644
>> >>> > --- a/drivers/gpu/drm/msm/msm_drv.h
>> >>> > +++ b/drivers/gpu/drm/msm/msm_drv.h
>> >>> > @@ -536,10 +536,6 @@ struct msm_drm_private {
>> >>> >
>> >>> >       struct workqueue_struct *wq;
>> >>> >
>> >>> > -     /* crtcs pending async atomic updates: */
>> >>> > -     uint32_t pending_crtcs;
>> >>> > -     wait_queue_head_t pending_crtcs_event;
>> >>> > -
>> >>> >       unsigned int num_planes;
>> >>> >       struct drm_plane *planes[MAX_PLANES];

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 09/11] drm/msm: Remove prepare_fence kms_function
       [not found]     ` <20180228191906.185417-10-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-09  1:28       ` abhinavk-sgV2jX0FEOL9JmXXK+q4OQ
  0 siblings, 0 replies; 49+ messages in thread
From: abhinavk-sgV2jX0FEOL9JmXXK+q4OQ @ 2018-03-09  1:28 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-02-28 11:19, Sean Paul wrote:
> This is the last piece that is keeping us from matching the atomic
> helper commit function. By removing this (now unused) hook, we can
> switch to drm_atomic_helper_commit()
> 
> Change-Id: I081056a6e1689807871f5deedc76499bb91b6969
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Abhinav Kumar <abhinavk@codeaurora.org>
> ---
>  drivers/gpu/drm/msm/msm_atomic.c | 10 ----------
>  drivers/gpu/drm/msm/msm_kms.h    |  2 --
>  2 files changed, 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c 
> b/drivers/gpu/drm/msm/msm_atomic.c
> index 1f53262ea46b..204c66cbfd31 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -169,16 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 */
>  	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> 
> -	/*
> -	 * Provide the driver a chance to prepare for output fences. This is
> -	 * done after the point of no return, but before asynchronous commits
> -	 * are dispatched to work queues, so that the fence preparation is
> -	 * finished before the .atomic_commit returns.
> -	 */
> -	if (priv && priv->kms && priv->kms->funcs &&
> -			priv->kms->funcs->prepare_fence)
> -		priv->kms->funcs->prepare_fence(priv->kms, state);
> -
>  	/*
>  	 * Everything below can be run asynchronously without the need to 
> grab
>  	 * any modeset locks at all under one conditions: It must be 
> guaranteed
> diff --git a/drivers/gpu/drm/msm/msm_kms.h 
> b/drivers/gpu/drm/msm/msm_kms.h
> index 4c5a69258c42..25800c046bd1 100644
> --- a/drivers/gpu/drm/msm/msm_kms.h
> +++ b/drivers/gpu/drm/msm/msm_kms.h
> @@ -60,8 +60,6 @@ struct msm_kms_funcs {
>  	void *(*duplicate_state)(void *state);
>  	void (*destroy_state)(void *state);
>  	/* modeset, bracketing atomic_commit(): */
> -	void (*prepare_fence)(struct msm_kms *kms,
> -			struct drm_atomic_state *state);
>  	void (*prepare_commit)(struct msm_kms *kms,
>  			struct drm_atomic_state *state);
>  	void (*commit)(struct msm_kms *kms, struct drm_atomic_state *state);
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 07/11] drm/msm: Use atomic private_obj instead of subclassing
       [not found]     ` <20180228191906.185417-8-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-09  1:59       ` Jeykumar Sankaran
       [not found]         ` <7fb92416ee99990f6a1280a617736051-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-09  1:59 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-02-28 11:19, Sean Paul wrote:
> Instead of subclassing atomic state, store driver private data in
> private_obj/state. This allows us to remove the swap_state driver hook
> for mdp5 and get closer to using the atomic helpers entirely.
> 
> Change-Id: I65a4a2887593ae257d584e00b352b5daf00e4e61
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>  drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 37 ++++++--------
>  drivers/gpu/drm/msm/msm_atomic.c         | 30 -----------
>  drivers/gpu/drm/msm/msm_drv.c            | 65 ++++++++++++++++++++++--
>  drivers/gpu/drm/msm/msm_drv.h            |  4 +-
>  drivers/gpu/drm/msm/msm_kms.h            | 28 +++++-----
>  5 files changed, 95 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> index 6d8e3a9a6fc0..f1a248419655 100644
> --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> @@ -74,36 +74,32 @@ struct mdp5_state *mdp5_get_state(struct
> drm_atomic_state *s)
>  {
>  	struct msm_drm_private *priv = s->dev->dev_private;
>  	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
> -	struct msm_kms_state *state = to_kms_state(s);
> -	struct mdp5_state *new_state;
> +	struct msm_kms_state *kms_state;
>  	int ret;
> 
> -	if (state->state)
> -		return state->state;
> -
>  	ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
>  	if (ret)
>  		return ERR_PTR(ret);
> 
> -	new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
> -	if (!new_state)
> -		return ERR_PTR(-ENOMEM);
> +	kms_state = msm_kms_get_state(s);
> +	if (IS_ERR_OR_NULL(kms_state))
> +		return (struct mdp5_state *)kms_state; /* casting ERR_PTR
> */
> 
> -	/* Copy state: */
> -	new_state->hwpipe = mdp5_kms->state->hwpipe;
> -	new_state->hwmixer = mdp5_kms->state->hwmixer;
> -	if (mdp5_kms->smp)
> -		new_state->smp = mdp5_kms->state->smp;
> +	return kms_state->state;
> +}
> 
> -	state->state = new_state;
> +static void *mdp5_duplicate_state(void *state)
> +{
> +	if (!state)
> +		return kzalloc(sizeof(struct mdp5_state), GFP_KERNEL);
> 
> -	return new_state;
> +	return kmemdup(state, sizeof(struct mdp5_state), GFP_KERNEL);
>  }
> 
> -static void mdp5_swap_state(struct msm_kms *kms, struct 
> drm_atomic_state
> *state)
> +static void mdp5_destroy_state(void *state)
>  {
> -	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
> -	swap(to_kms_state(state)->state, mdp5_kms->state);
> +	struct mdp5_state *mdp_state = state;
> +	kfree(mdp_state);
>  }
> 
>  static void mdp5_prepare_commit(struct msm_kms *kms, struct
> drm_atomic_state *state)
> @@ -229,7 +225,8 @@ static const struct mdp_kms_funcs kms_funcs = {
>  		.irq             = mdp5_irq,
>  		.enable_vblank   = mdp5_enable_vblank,
>  		.disable_vblank  = mdp5_disable_vblank,
> -		.swap_state      = mdp5_swap_state,
> +		.duplicate_state = mdp5_duplicate_state,
> +		.destroy_state	 = mdp5_destroy_state,
>  		.prepare_commit  = mdp5_prepare_commit,
>  		.complete_commit = mdp5_complete_commit,
>  		.wait_for_crtc_commit_done =
> mdp5_wait_for_crtc_commit_done,
> @@ -726,8 +723,6 @@ static void mdp5_destroy(struct platform_device 
> *pdev)
> 
>  	if (mdp5_kms->rpm_enabled)
>  		pm_runtime_disable(&pdev->dev);
> -
> -	kfree(mdp5_kms->state);
>  }
> 
>  static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> b/drivers/gpu/drm/msm/msm_atomic.c
> index 7e54eb65d096..1f53262ea46b 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -169,9 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 */
>  	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> 
> -	if (to_kms_state(state)->state)
> -		priv->kms->funcs->swap_state(priv->kms, state);
> -
>  	/*
>  	 * Provide the driver a chance to prepare for output fences. This
> is
>  	 * done after the point of no return, but before asynchronous
> commits
> @@ -210,30 +207,3 @@ int msm_atomic_commit(struct drm_device *dev,
>  	drm_atomic_helper_cleanup_planes(dev, state);
>  	return ret;
>  }
> -
> -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device 
> *dev)
> -{
> -	struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
> -
> -	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
> -		kfree(state);
> -		return NULL;
> -	}
> -
> -	return &state->base;
> -}
> -
> -void msm_atomic_state_clear(struct drm_atomic_state *s)
> -{
> -	struct msm_kms_state *state = to_kms_state(s);
> -	drm_atomic_state_default_clear(&state->base);
> -	kfree(state->state);
> -	state->state = NULL;
> -}
> -
> -void msm_atomic_state_free(struct drm_atomic_state *state)
> -{
> -	kfree(to_kms_state(state)->state);
> -	drm_atomic_state_default_release(state);
> -	kfree(state);
> -}
> diff --git a/drivers/gpu/drm/msm/msm_drv.c 
> b/drivers/gpu/drm/msm/msm_drv.c
> index b354424cccb5..e582d5889b66 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -121,9 +121,62 @@ static const struct drm_mode_config_funcs
> mode_config_funcs = {
>  	.output_poll_changed = msm_fb_output_poll_changed,
>  	.atomic_check = msm_atomic_check,
>  	.atomic_commit = msm_atomic_commit,
> -	.atomic_state_alloc = msm_atomic_state_alloc,
> -	.atomic_state_clear = msm_atomic_state_clear,
> -	.atomic_state_free = msm_atomic_state_free,
> +};
> +
> +static inline
> +struct msm_kms *obj_to_kms(struct drm_private_obj *obj)
> +{
> +	return container_of(obj, struct msm_kms, base);
> +}
> +
> +static inline
> +struct msm_kms_state *state_to_kms_state(struct drm_private_state 
> *state)
> +{
> +	return container_of(state, struct msm_kms_state, base);
> +}
> +
> +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *s)
> +{
> +	struct msm_drm_private *priv = s->dev->dev_private;
> +	struct drm_private_obj *obj = &priv->kms->base;
> +	struct drm_private_state *state;
> +
> +	state = drm_atomic_get_private_obj_state(s, obj);
> +	if (IS_ERR_OR_NULL(state))
> +		return (struct msm_kms_state *)state; /* casting ERR_PTR
> */
> +
> +	return state_to_kms_state(state);
> +}
> +
> +static struct drm_private_state *
> +msm_kms_duplicate_state(struct drm_private_obj *obj)
> +{
> +	struct msm_kms *kms = obj_to_kms(obj);
> +	struct msm_kms_state *state = state_to_kms_state(obj->state);
> +	struct msm_kms_state *new_state;
> +
> +	if (kms->funcs->duplicate_state)
> +		new_state = kms->funcs->duplicate_state(state);

Shouldn't this be state->state? I believe we are trying to duplicate 
mdp5_state here.

> +
> +	__drm_atomic_helper_private_obj_duplicate_state(obj,
> &new_state->base);
> +
> +	return &new_state->base;
> +}
> +
> +static void msm_kms_destroy_state(struct drm_private_obj *obj,
> +				  struct drm_private_state *state)
> +{
> +	struct msm_kms *kms = obj_to_kms(obj);
> +	struct msm_kms_state *kms_state = state_to_kms_state(obj->state);
> +
> +	if (kms->funcs->destroy_state)
> +		kms->funcs->destroy_state(kms_state->state);
> +	kfree(kms_state);
> +}
> +
> +static const struct drm_private_state_funcs kms_state_funcs = {
> +	.atomic_duplicate_state = msm_kms_duplicate_state,
> +	.atomic_destroy_state = msm_kms_destroy_state,
>  };
> 
>  #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
> @@ -341,6 +394,8 @@ static int msm_drm_uninit(struct device *dev)
>  		}
>  	}
> 
> +	drm_atomic_private_obj_fini(&kms->base);
> +
>  	msm_gem_shrinker_cleanup(ddev);
> 
>  	drm_kms_helper_poll_fini(ddev);
> @@ -770,6 +825,10 @@ static int msm_drm_init(struct device *dev, struct
> drm_driver *drv)
>  	}
>  #endif
> 
> +	drm_atomic_private_obj_init(&kms->base,
> +				    &kms->state.base,
> +				    &kms_state_funcs);
> +
>  	/* perform subdriver post initialization */
>  	if (kms && kms->funcs && kms->funcs->postinit) {
>  		ret = kms->funcs->postinit(kms);
> diff --git a/drivers/gpu/drm/msm/msm_drv.h 
> b/drivers/gpu/drm/msm/msm_drv.h
> index 292496b682e8..8cab333df717 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -598,9 +598,7 @@ struct msm_format {
> 
>  int msm_atomic_commit(struct drm_device *dev,
>  		struct drm_atomic_state *state, bool nonblock);
> -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device 
> *dev);
> -void msm_atomic_state_clear(struct drm_atomic_state *state);
> -void msm_atomic_state_free(struct drm_atomic_state *state);
> +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state 
> *state);
> 
>  void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
>  		struct msm_gem_vma *vma, struct sg_table *sgt);
> diff --git a/drivers/gpu/drm/msm/msm_kms.h 
> b/drivers/gpu/drm/msm/msm_kms.h
> index 09ba1e79db50..4c5a69258c42 100644
> --- a/drivers/gpu/drm/msm/msm_kms.h
> +++ b/drivers/gpu/drm/msm/msm_kms.h
> @@ -57,6 +57,8 @@ struct msm_kms_funcs {
>  	void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc
> *crtc);
>  	/* swap global atomic state: */
>  	void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state
> *state);
> +	void *(*duplicate_state)(void *state);
> +	void (*destroy_state)(void *state);
>  	/* modeset, bracketing atomic_commit(): */
>  	void (*prepare_fence)(struct msm_kms *kms,
>  			struct drm_atomic_state *state);
> @@ -114,16 +116,6 @@ struct msm_kms_funcs {
>  #endif
>  };
> 
> -struct msm_kms {
> -	const struct msm_kms_funcs *funcs;
> -
> -	/* irq number to be passed on to drm_irq_install */
> -	int irq;
> -
> -	/* mapper-id used to request GEM buffer mapped for scanout: */
> -	struct msm_gem_address_space *aspace;
> -};
> -
>  /**
>   * Subclass of drm_atomic_state, to allow kms backend to have driver
Update comments
>   * private global state.  The kms backend can do whatever it wants
> @@ -131,10 +123,22 @@ struct msm_kms {
>   * is kfree'd and set back to NULL.
>   */
>  struct msm_kms_state {
> -	struct drm_atomic_state base;
> +	struct drm_private_state base;
>  	void *state;
>  };
> -#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
> +
> +struct msm_kms {
> +	struct drm_private_obj base;
> +	struct msm_kms_state state;
> +
> +	const struct msm_kms_funcs *funcs;
> +
> +	/* irq number to be passed on to drm_irq_install */
> +	int irq;
> +
> +	/* mapper-id used to request GEM buffer mapped for scanout: */
> +	struct msm_gem_address_space *aspace;
> +};
> 
>  static inline void msm_kms_init(struct msm_kms *kms,
>  		const struct msm_kms_funcs *funcs)

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 10/11] drm/msm: Switch to atomic_helper_commit()
       [not found]     ` <20180228191906.185417-11-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-09  3:28       ` abhinavk-sgV2jX0FEOL9JmXXK+q4OQ
       [not found]         ` <bf44a79fc08d00245640694c364b8b03-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: abhinavk-sgV2jX0FEOL9JmXXK+q4OQ @ 2018-03-09  3:28 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-owner-u79uwXL29TY76Z2rM5mHXA,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, jsanka-sgV2jX0FEOL9JmXXK+q4OQ,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw

On 2018-02-28 11:19, Sean Paul wrote:
> Now that all of the msm-specific goo is tucked safely away we can 
> switch
> over to using the atomic helper commit directly. \o/
> 
[Abhinav] Can we say something like "Move remaining msm-specific 
operations to private handles and switch to atomic helper commit for the 
rest.

> Change-Id: Ieab0bd0c526b2a9d3b3345eeba402ac4857fe418
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>  drivers/gpu/drm/msm/msm_atomic.c | 120 +------------------------------
>  drivers/gpu/drm/msm/msm_drv.c    |   7 +-
>  drivers/gpu/drm/msm/msm_drv.h    |   3 +-
>  3 files changed, 8 insertions(+), 122 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c 
> b/drivers/gpu/drm/msm/msm_atomic.c
> index 204c66cbfd31..91ffded576d8 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -18,8 +18,6 @@
> 
>  #include "msm_drv.h"
>  #include "msm_kms.h"
> -#include "msm_gem.h"
> -#include "msm_fence.h"
> 
>  static void msm_atomic_wait_for_commit_done(
>  		struct drm_device *dev,
> @@ -39,7 +37,7 @@ static void msm_atomic_wait_for_commit_done(
>  	}
>  }
> 
> -static void msm_atomic_commit_tail(struct drm_atomic_state *state)
> +void msm_atomic_commit_tail(struct drm_atomic_state *state)
>  {
>  	struct drm_device *dev = state->dev;
>  	struct msm_drm_private *priv = dev->dev_private;
> @@ -81,119 +79,3 @@ static void msm_atomic_commit_tail(struct
> drm_atomic_state *state)
> 
>  	kms->funcs->complete_commit(kms, state);
>  }
> -
> -/* The (potentially) asynchronous part of the commit.  At this point
> - * nothing can fail short of armageddon.
> - */
> -static void commit_tail(struct drm_atomic_state *state)
> -{
> -	drm_atomic_helper_wait_for_fences(state->dev, state, false);
> -
> -	drm_atomic_helper_wait_for_dependencies(state);
> -
> -	msm_atomic_commit_tail(state);
> -
> -	drm_atomic_helper_commit_cleanup_done(state);
> -
> -	drm_atomic_state_put(state);
> -}
> -
> -static void commit_work(struct work_struct *work)
> -{
> -	struct drm_atomic_state *state = container_of(work,
> -						      struct drm_atomic_state,
> -						      commit_work);
> -	commit_tail(state);
> -}
> -
> -/**
> - * drm_atomic_helper_commit - commit validated state object
> - * @dev: DRM device
> - * @state: the driver state object
> - * @nonblock: nonblocking commit
> - *
> - * This function commits a with drm_atomic_helper_check() 
> pre-validated state
> - * object. This can still fail when e.g. the framebuffer reservation 
> fails.
> - *
> - * RETURNS
> - * Zero for success or -errno.
> - */
> -int msm_atomic_commit(struct drm_device *dev,
> -		struct drm_atomic_state *state, bool nonblock)
> -{
> -	struct msm_drm_private *priv = dev->dev_private;
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *crtc_state;
> -	struct drm_plane *plane;
> -	struct drm_plane_state *old_plane_state, *new_plane_state;
> -	int i, ret;
> -
> -	/*
> -	 * Note that plane->atomic_async_check() should fail if we need
> -	 * to re-assign hwpipe or anything that touches global atomic
> -	 * state, so we'll never go down the async update path in those
> -	 * cases.
> -	 */
> -	if (state->async_update) {
> -		ret = drm_atomic_helper_prepare_planes(dev, state);
> -		if (ret)
> -			return ret;
> -
> -		drm_atomic_helper_async_commit(dev, state);
> -		drm_atomic_helper_cleanup_planes(dev, state);
> -		return 0;
> -	}
> -
> -	ret = drm_atomic_helper_setup_commit(state, nonblock);
> -	if (ret)
> -		return ret;
> -
> -	INIT_WORK(&state->commit_work, commit_work);
> -
> -	ret = drm_atomic_helper_prepare_planes(dev, state);
> -	if (ret)
> -		return ret;
> -
> -	if (!nonblock) {
> -		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> -		if (ret)
> -			goto error;
> -	}
> -
> -	/*
> -	 * This is the point of no return - everything below never fails 
> except
> -	 * when the hw goes bonghits. Which means we can commit the new state 
> on
> -	 * the software side now.
> -	 *
> -	 * swap driver private state while still holding state_lock
> -	 */
> -	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> -
> -	/*
> -	 * Everything below can be run asynchronously without the need to 
> grab
> -	 * any modeset locks at all under one conditions: It must be 
> guaranteed
> -	 * that the asynchronous work has either been cancelled (if the 
> driver
> -	 * supports it, which at least requires that the framebuffers get
> -	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
> -	 * before the new state gets committed on the software side with
> -	 * drm_atomic_helper_swap_state().
> -	 *
> -	 * This scheme allows new atomic state updates to be prepared and
> -	 * checked in parallel to the asynchronous completion of the previous
> -	 * update. Which is important since compositors need to figure out 
> the
> -	 * composition of the next frame right after having submitted the
> -	 * current layout.
> -	 */
> -
> -	drm_atomic_state_get(state);
> -	if (nonblock)
> -		queue_work(system_unbound_wq, &state->commit_work);
> -	else
> -		commit_tail(state);
> -
> -	return 0;
> -
> -error:
> -	drm_atomic_helper_cleanup_planes(dev, state);
> -	return ret;
> -}
> diff --git a/drivers/gpu/drm/msm/msm_drv.c 
> b/drivers/gpu/drm/msm/msm_drv.c
> index e582d5889b66..fd9a7d0825cd 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -120,7 +120,11 @@ static const struct drm_mode_config_funcs
> mode_config_funcs = {
>  	.fb_create = msm_framebuffer_create,
>  	.output_poll_changed = msm_fb_output_poll_changed,
>  	.atomic_check = msm_atomic_check,
> -	.atomic_commit = msm_atomic_commit,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +static const struct drm_mode_config_helper_funcs 
> mode_config_helper_funcs = {
> +	.atomic_commit_tail = msm_atomic_commit_tail,
>  };
> 
>  static inline
> @@ -694,6 +698,7 @@ static int msm_drm_init(struct device *dev, struct
> drm_driver *drv)
>  	 * an unset value during call to drm_drv_uses_atomic_modeset()
>  	 */
>  	ddev->mode_config.funcs = &mode_config_funcs;
> +	ddev->mode_config.helper_private = &mode_config_helper_funcs;
> 
>  	if (kms) {
>  		ret = kms->funcs->hw_init(kms);
> diff --git a/drivers/gpu/drm/msm/msm_drv.h 
> b/drivers/gpu/drm/msm/msm_drv.h
> index e92376acbcfe..657ea052a1ee 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -593,8 +593,7 @@ struct msm_format {
>  	uint32_t pixel_format;
>  };
> 
> -int msm_atomic_commit(struct drm_device *dev,
> -		struct drm_atomic_state *state, bool nonblock);
> +void msm_atomic_commit_tail(struct drm_atomic_state *state);
>  struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state 
> *state);
> 
>  void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 01/11] drm/msm: Skip seamless disables in crtc/encoder
       [not found]       ` <d51bfdafccd143ee258fc995a7cafecc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-03-12 20:14         ` Sean Paul
  2018-03-13 18:10           ` Jeykumar Sankaran
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-12 20:14 UTC (permalink / raw)
  To: jsanka-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, Sean Paul,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On Fri, Mar 02, 2018 at 04:04:24PM -0800, jsanka@codeaurora.org wrote:
> On 2018-02-28 11:18, Sean Paul wrote:
> > Instead of duplicating whole swaths of atomic helper functions (which
> > are already out-of-date), just skip the encoder/crtc disables in the
> > .disable hooks.
> > 
> > Change-Id: I7bd9183ae60624204fb1de9550656b776efc7202
> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> 
> Can you consider getting rid of these checks?

Do you mean the Change-Id? Yeah, I forgot to strip them out before sending, I'll
make sure I clean it up before I apply.

> 
> > ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   8 +
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   8 +
> >  drivers/gpu/drm/msm/msm_atomic.c            | 185 +-------------------
> >  3 files changed, 17 insertions(+), 184 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index 3cdf1e3d9d96..a3ab6ed2bf1d 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -3393,6 +3393,7 @@ static void dpu_crtc_disable(struct drm_crtc
> > *crtc)
> >  {
> >  	struct dpu_crtc *dpu_crtc;
> >  	struct dpu_crtc_state *cstate;
> > +	struct drm_display_mode *mode;
> >  	struct drm_encoder *encoder;
> >  	struct msm_drm_private *priv;
> >  	unsigned long flags;
> > @@ -3407,8 +3408,15 @@ static void dpu_crtc_disable(struct drm_crtc
> > *crtc)
> >  	}
> >  	dpu_crtc = to_dpu_crtc(crtc);
> >  	cstate = to_dpu_crtc_state(crtc->state);
> > +	mode = &cstate->base.adjusted_mode;
> >  	priv = crtc->dev->dev_private;
> > 
> > +	if (msm_is_mode_seamless(mode) || msm_is_mode_seamless_vrr(mode)
> > ||
> > +	    msm_is_mode_seamless_dms(mode)) {
> > +		DPU_DEBUG("Seamless mode is being applied, skip
> > disable\n");
> > +		return;
> > +	}
> > +
> Another topic of discussion which should be brought up with dri-devel.
> 
> May not be common in PC world, but there are a handful of mobile OEM's
> using panels which supports more than one resolution. Primary use cases
> involve "seamless" switching to optimized display resolution when
> streaming content changes resolutions or rendering lossless data.

Yeah, I think we can do this under the covers if the hardware supports it such
as this patch. We could probably do a better job of making this useful for other
drivers, but I was really just trying to get the seamless stuff out of the way
so we don't need to roll our own atomic commit.

Sean

> 
> Jeykumar S.
> 
> >  	DPU_DEBUG("crtc%d\n", crtc->base.id);
> > 
> >  	if (dpu_kms_is_suspend_state(crtc->dev))
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 3d168fa09f3f..28ceb589ee40 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -2183,6 +2183,7 @@ static void dpu_encoder_virt_disable(struct
> > drm_encoder *drm_enc)
> >  	struct dpu_encoder_virt *dpu_enc = NULL;
> >  	struct msm_drm_private *priv;
> >  	struct dpu_kms *dpu_kms;
> > +	struct drm_display_mode *mode;
> >  	int i = 0;
> > 
> >  	if (!drm_enc) {
> > @@ -2196,6 +2197,13 @@ static void dpu_encoder_virt_disable(struct
> > drm_encoder *drm_enc)
> >  		return;
> >  	}
> > 
> > +	mode = &drm_enc->crtc->state->adjusted_mode;
> > +	if (msm_is_mode_seamless(mode) || msm_is_mode_seamless_vrr(mode)
> > ||
> > +	    msm_is_mode_seamless_dms(mode)) {
> > +		DPU_DEBUG("Seamless mode is being applied, skip
> > disable\n");
> > +		return;
> > +	}
> > +
> >  	dpu_enc = to_dpu_encoder_virt(drm_enc);
> >  	DPU_DEBUG_ENC(dpu_enc, "\n");
> > 
> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> > b/drivers/gpu/drm/msm/msm_atomic.c
> > index 46536edb72ee..5cfb80345052 100644
> > --- a/drivers/gpu/drm/msm/msm_atomic.c
> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> > @@ -84,189 +84,6 @@ static void msm_atomic_wait_for_commit_done(
> >  	}
> >  }
> > 
> > -static void
> > -msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state
> > *old_state)
> > -{
> > -	struct drm_connector *connector;
> > -	struct drm_connector_state *old_conn_state, *new_conn_state;
> > -	struct drm_crtc *crtc;
> > -	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
> > -	int i;
> > -
> > -	for_each_oldnew_connector_in_state(old_state, connector,
> > old_conn_state, new_conn_state, i) {
> > -		const struct drm_encoder_helper_funcs *funcs;
> > -		struct drm_encoder *encoder;
> > -		struct drm_crtc_state *old_crtc_state;
> > -		unsigned int crtc_idx;
> > -
> > -		/*
> > -		 * Shut down everything that's in the changeset and
> > currently
> > -		 * still on. So need to check the old, saved state.
> > -		 */
> > -		if (!old_conn_state->crtc)
> > -			continue;
> > -
> > -		crtc_idx = drm_crtc_index(old_conn_state->crtc);
> > -		old_crtc_state = drm_atomic_get_old_crtc_state(old_state,
> > -
> > old_conn_state->crtc);
> > -
> > -		if (!old_crtc_state->active ||
> > -
> > !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
> > -			continue;
> > -
> > -		encoder = old_conn_state->best_encoder;
> > -
> > -		/* We shouldn't get this far if we didn't previously have
> > -		 * an encoder.. but WARN_ON() rather than explode.
> > -		 */
> > -		if (WARN_ON(!encoder))
> > -			continue;
> > -
> > -		if (msm_is_mode_seamless(
> > -			&connector->encoder->crtc->state->mode) ||
> > -			msm_is_mode_seamless_vrr(
> > -			&connector->encoder->crtc->state->adjusted_mode))
> > -			continue;
> > -
> > -		if (msm_is_mode_seamless_dms(
> > -			&connector->encoder->crtc->state->adjusted_mode))
> > -			continue;
> > -
> > -		funcs = encoder->helper_private;
> > -
> > -		DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n",
> > -				 encoder->base.id, encoder->name);
> > -
> > -		/*
> > -		 * Each encoder has at most one connector (since we always
> > steal
> > -		 * it away), so we won't call disable hooks twice.
> > -		 */
> > -		drm_bridge_disable(encoder->bridge);
> > -
> > -		/* Right function depends upon target state. */
> > -		if (new_conn_state->crtc && funcs->prepare)
> > -			funcs->prepare(encoder);
> > -		else if (funcs->disable)
> > -			funcs->disable(encoder);
> > -		else
> > -			funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
> > -
> > -		drm_bridge_post_disable(encoder->bridge);
> > -	}
> > -
> > -	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
> > new_crtc_state, i) {
> > -		const struct drm_crtc_helper_funcs *funcs;
> > -
> > -		/* Shut down everything that needs a full modeset. */
> > -		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
> > -			continue;
> > -
> > -		if (!old_crtc_state->active)
> > -			continue;
> > -
> > -		if (msm_is_mode_seamless(&crtc->state->mode) ||
> > -
> > msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode))
> > -			continue;
> > -
> > -		if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode))
> > -			continue;
> > -
> > -		funcs = crtc->helper_private;
> > -
> > -		DRM_DEBUG_ATOMIC("disabling [CRTC:%d]\n",
> > -				 crtc->base.id);
> > -
> > -		/* Right function depends upon target state. */
> > -		if (new_crtc_state->enable && funcs->prepare)
> > -			funcs->prepare(crtc);
> > -		else if (funcs->disable)
> > -			funcs->disable(crtc);
> > -		else
> > -			funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
> > -	}
> > -}
> > -
> > -static void
> > -msm_crtc_set_mode(struct drm_device *dev, struct drm_atomic_state
> > *old_state)
> > -{
> > -	struct drm_crtc *crtc;
> > -	struct drm_crtc_state *new_crtc_state;
> > -	struct drm_connector *connector;
> > -	struct drm_connector_state *new_conn_state;
> > -	int i;
> > -
> > -	for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
> > -		const struct drm_crtc_helper_funcs *funcs;
> > -
> > -		if (!new_crtc_state->mode_changed)
> > -			continue;
> > -
> > -		funcs = crtc->helper_private;
> > -
> > -		if (new_crtc_state->enable && funcs->mode_set_nofb) {
> > -			DRM_DEBUG_ATOMIC("modeset on [CRTC:%d]\n",
> > -					 crtc->base.id);
> > -
> > -			funcs->mode_set_nofb(crtc);
> > -		}
> > -	}
> > -
> > -	for_each_new_connector_in_state(old_state, connector,
> > new_conn_state, i) {
> > -		const struct drm_encoder_helper_funcs *funcs;
> > -		struct drm_crtc_state *new_crtc_state;
> > -		struct drm_encoder *encoder;
> > -		struct drm_display_mode *mode, *adjusted_mode;
> > -
> > -		if (!new_conn_state->best_encoder)
> > -			continue;
> > -
> > -		encoder = new_conn_state->best_encoder;
> > -		funcs = encoder->helper_private;
> > -		new_crtc_state = new_conn_state->crtc->state;
> > -		mode = &new_crtc_state->mode;
> > -		adjusted_mode = &new_crtc_state->adjusted_mode;
> > -
> > -		if (!new_crtc_state->mode_changed)
> > -			continue;
> > -
> > -		DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n",
> > -				 encoder->base.id, encoder->name);
> > -
> > -		/*
> > -		 * Each encoder has at most one connector (since we always
> > steal
> > -		 * it away), so we won't call mode_set hooks twice.
> > -		 */
> > -		if (funcs->mode_set)
> > -			funcs->mode_set(encoder, mode, adjusted_mode);
> > -
> > -		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
> > -	}
> > -}
> > -
> > -/**
> > - * msm_atomic_helper_commit_modeset_disables - modeset commit to
> > disable
> > outputs
> > - * @dev: DRM device
> > - * @old_state: atomic state object with old state structures
> > - *
> > - * This function shuts down all the outputs that need to be shut down
> > and
> > - * prepares them (if required) with the new mode.
> > - *
> > - * For compatibility with legacy crtc helpers this should be called
> > before
> > - * drm_atomic_helper_commit_planes(), which is what the default commit
> > function
> > - * does. But drivers with different needs can group the modeset commits
> > together
> > - * and do the plane commits at the end. This is useful for drivers
> > doing
> > runtime
> > - * PM since planes updates then only happen when the CRTC is actually
> > enabled.
> > - */
> > -void msm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
> > -		struct drm_atomic_state *old_state)
> > -{
> > -	msm_disable_outputs(dev, old_state);
> > -
> > -	drm_atomic_helper_update_legacy_modeset_state(dev, old_state);
> > -
> > -	msm_crtc_set_mode(dev, old_state);
> > -}
> > -
> >  /**
> >   * msm_atomic_helper_commit_modeset_enables - modeset commit to enable
> > outputs
> >   * @dev: DRM device
> > @@ -406,7 +223,7 @@ static void complete_commit(struct msm_commit *c)
> > 
> >  	kms->funcs->prepare_commit(kms, state);
> > 
> > -	msm_atomic_helper_commit_modeset_disables(dev, state);
> > +	drm_atomic_helper_commit_modeset_disables(dev, state);
> > 
> >  	drm_atomic_helper_commit_planes(dev, state, 0);

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 02/11] drm/msm: Don't duplicate modeset_enables atomic helper
       [not found]         ` <aaf8f07e18801c60cdf7eb30b0cac123-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-03-12 20:21           ` Sean Paul
  2018-03-13 23:57             ` Jeykumar Sankaran
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-12 20:21 UTC (permalink / raw)
  To: Jeykumar Sankaran
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, Sean Paul,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On Thu, Mar 08, 2018 at 04:56:01PM -0800, Jeykumar Sankaran wrote:
> On 2018-02-28 11:18, Sean Paul wrote:
> > Instead, shuffle things around so we kickoff crtc after enabling encoder
> > during modesets. Also moves the vblank wait to after the frame.
> > 
> > Change-Id: I16c7b7f9390d04f6050aa20e17a5335fbf49eba3
> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   9 ++
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   5 +-
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c     |  31 ++++-
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |   2 +
> >  drivers/gpu/drm/msm/msm_atomic.c            | 132 +-------------------
> >  5 files changed, 48 insertions(+), 131 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index a3ab6ed2bf1d..94fab2dcca5b 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -3525,6 +3525,12 @@ static void dpu_crtc_enable(struct drm_crtc
> > *crtc,
> >  	DPU_EVT32_VERBOSE(DRMID(crtc));
> >  	dpu_crtc = to_dpu_crtc(crtc);
> > 
> > +	if (msm_is_mode_seamless(&crtc->state->adjusted_mode) ||
> > +	    msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode)) {
> > +		DPU_DEBUG("Skipping crtc enable, seamless mode\n");
> > +		return;
> > +	}
> > +
> >  	pm_runtime_get_sync(crtc->dev->dev);
> > 
> >  	drm_for_each_encoder(encoder, crtc->dev) {
> > @@ -3572,6 +3578,9 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
> >  		DPU_POWER_EVENT_POST_ENABLE | DPU_POWER_EVENT_POST_DISABLE
> > |
> >  		DPU_POWER_EVENT_PRE_DISABLE,
> >  		dpu_crtc_handle_power_event, crtc, dpu_crtc->name);
> > +
> > +	if (msm_needs_vblank_pre_modeset(&crtc->state->adjusted_mode))
> > +		drm_crtc_wait_one_vblank(crtc);
> >  }
> > 
> >  struct plane_state {
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 28ceb589ee40..4d1e3652dbf4 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -3693,8 +3693,11 @@ static void dpu_encoder_frame_done_timeout(struct
> > timer_list *t)
> >  static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs =
> > {
> >  	.mode_set = dpu_encoder_virt_mode_set,
> >  	.disable = dpu_encoder_virt_disable,
> > -	.enable = dpu_encoder_virt_enable,
> > +	.enable = dpu_kms_encoder_enable,
> >  	.atomic_check = dpu_encoder_virt_atomic_check,
> > +
> > +	/* This is called by dpu_kms_encoder_enable */
> > +	.commit = dpu_encoder_virt_enable,
> >  };
> > 
> >  static const struct drm_encoder_funcs dpu_encoder_funcs = {
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > index 81fd3a429e9f..3d83037e8305 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > @@ -425,14 +425,37 @@ static void dpu_kms_prepare_commit(struct msm_kms
> > *kms,
> >  			dpu_encoder_prepare_commit(encoder);
> >  }
> > 
> > -static void dpu_kms_commit(struct msm_kms *kms,
> > -		struct drm_atomic_state *old_state)
> > +/*
> > + * Override the encoder enable since we need to setup the inline
> > rotator
> > and do
> > + * some crtc magic before enabling any bridge that might be present.
> > + */
> > +void dpu_kms_encoder_enable(struct drm_encoder *encoder)
> > +{
> > +	const struct drm_encoder_helper_funcs *funcs =
> > encoder->helper_private;
> > +	struct drm_crtc *crtc = encoder->crtc;
> > +
> > +	/* Forward this enable call to the commit hook */
> > +	if (funcs && funcs->commit)
> > +		funcs->commit(encoder);
> 
> The purpose of this function is not clear. Where are we setting up the
> inline rotator?
> Why do we need a kickoff here?

The reason the code is shuffled is to avoid duplicating the entire atomic helper
function. By moving calls into the ->enable hooks, we can avoid having to hand
roll the helpers.

The kickoff is preserved from the helper copy when you call kms->funcs->commit
in between the encoder enable and bridge enable. If this can be removed, that'd
be even better. I was simply trying to preserve the call order of everything.

Sean

> > +
> > +	if (crtc && crtc->state->active) {
> > +		DPU_EVT32(DRMID(crtc));
> > +		dpu_crtc_commit_kickoff(crtc);
> > +	}
> > +}
> > +
> > +static void dpu_kms_commit(struct msm_kms *kms, struct drm_atomic_state
> > *state)
> >  {
> >  	struct drm_crtc *crtc;
> > -	struct drm_crtc_state *old_crtc_state;
> > +	struct drm_crtc_state *crtc_state;
> > +	struct dpu_crtc_state *cstate;
> >  	int i;
> > 
> > -	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
> > +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> > +		/* If modeset is required, kickoff is run in
> > encoder_enable */
> > +		if (drm_atomic_crtc_needs_modeset(crtc_state))
> > +			continue;
> > +
> >  		if (crtc->state->active) {
> >  			DPU_EVT32(DRMID(crtc));
> >  			dpu_crtc_commit_kickoff(crtc);
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > index 8cadd29a48b1..42c809ed9467 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > @@ -529,4 +529,6 @@ int dpu_kms_fbo_reference(struct dpu_kms_fbo *fbo);
> >   */
> >  void dpu_kms_fbo_unreference(struct dpu_kms_fbo *fbo);
> > 
> > +void dpu_kms_encoder_enable(struct drm_encoder *encoder);
> > +
> >  #endif /* __dpu_kms_H__ */
> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> > b/drivers/gpu/drm/msm/msm_atomic.c
> > index 5cfb80345052..f5794dce25dd 100644
> > --- a/drivers/gpu/drm/msm/msm_atomic.c
> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> > @@ -84,131 +84,6 @@ static void msm_atomic_wait_for_commit_done(
> >  	}
> >  }
> > 
> > -/**
> > - * msm_atomic_helper_commit_modeset_enables - modeset commit to enable
> > outputs
> > - * @dev: DRM device
> > - * @old_state: atomic state object with old state structures
> > - *
> > - * This function enables all the outputs with the new configuration
> > which
> > had to
> > - * be turned off for the update.
> > - *
> > - * For compatibility with legacy crtc helpers this should be called
> > after
> > - * drm_atomic_helper_commit_planes(), which is what the default commit
> > function
> > - * does. But drivers with different needs can group the modeset commits
> > together
> > - * and do the plane commits at the end. This is useful for drivers
> > doing
> > runtime
> > - * PM since planes updates then only happen when the CRTC is actually
> > enabled.
> > - */
> > -static void msm_atomic_helper_commit_modeset_enables(struct drm_device
> > *dev,
> > -		struct drm_atomic_state *old_state)
> > -{
> > -	struct drm_crtc *crtc;
> > -	struct drm_crtc_state *old_crtc_state;
> > -	struct drm_crtc_state *new_crtc_state;
> > -	struct drm_connector *connector;
> > -	struct drm_connector_state *new_conn_state;
> > -	struct msm_drm_private *priv = dev->dev_private;
> > -	struct msm_kms *kms = priv->kms;
> > -	int bridge_enable_count = 0;
> > -	int i;
> > -
> > -	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
> > -			new_crtc_state, i) {
> > -		const struct drm_crtc_helper_funcs *funcs;
> > -
> > -		/* Need to filter out CRTCs where only planes change. */
> > -		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
> > -			continue;
> > -
> > -		if (!new_crtc_state->active)
> > -			continue;
> > -
> > -		if (msm_is_mode_seamless(&new_crtc_state->mode) ||
> > -				msm_is_mode_seamless_vrr(
> > -				&new_crtc_state->adjusted_mode))
> > -			continue;
> > -
> > -		funcs = crtc->helper_private;
> > -
> > -		if (crtc->state->enable) {
> > -			DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n",
> > -					 crtc->base.id);
> > -
> > -			if (funcs->atomic_enable)
> > -				funcs->atomic_enable(crtc,
> > old_crtc_state);
> > -			else
> > -				funcs->commit(crtc);
> > -		}
> > -
> > -		if (msm_needs_vblank_pre_modeset(
> > -					&new_crtc_state->adjusted_mode))
> > -			drm_crtc_wait_one_vblank(crtc);
> > -	}
> > -
> > -	/* ensure bridge/encoder updates happen on same vblank */
> > -	msm_atomic_wait_for_commit_done(dev, old_state);
> > -
> > -	for_each_new_connector_in_state(old_state, connector,
> > -			new_conn_state, i) {
> > -		const struct drm_encoder_helper_funcs *funcs;
> > -		struct drm_encoder *encoder;
> > -
> > -		if (!new_conn_state->best_encoder)
> > -			continue;
> > -
> > -		if (!new_conn_state->crtc->state->active ||
> > -		    !drm_atomic_crtc_needs_modeset(
> > -			    new_conn_state->crtc->state))
> > -			continue;
> > -
> > -		encoder = new_conn_state->best_encoder;
> > -		funcs = encoder->helper_private;
> > -
> > -		DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
> > -				 encoder->base.id, encoder->name);
> > -
> > -		/*
> > -		 * Each encoder has at most one connector (since we always
> > steal
> > -		 * it away), so we won't call enable hooks twice.
> > -		 */
> > -		drm_bridge_pre_enable(encoder->bridge);
> > -		++bridge_enable_count;
> > -
> > -		if (funcs->enable)
> > -			funcs->enable(encoder);
> > -		else
> > -			funcs->commit(encoder);
> > -	}
> > -
> > -	if (kms->funcs->commit) {
> > -		DRM_DEBUG_ATOMIC("triggering commit\n");
> > -		kms->funcs->commit(kms, old_state);
> > -	}
> > -
> > -	/* If no bridges were pre_enabled, skip iterating over them again
> > */
> > -	if (bridge_enable_count == 0)
> > -		return;
> > -
> > -	for_each_new_connector_in_state(old_state, connector,
> > -			new_conn_state, i) {
> > -		struct drm_encoder *encoder;
> > -
> > -		if (!new_conn_state->best_encoder)
> > -			continue;
> > -
> > -		if (!new_conn_state->crtc->state->active ||
> > -		    !drm_atomic_crtc_needs_modeset(
> > -				    new_conn_state->crtc->state))
> > -			continue;
> > -
> > -		encoder = new_conn_state->best_encoder;
> > -
> > -		DRM_DEBUG_ATOMIC("bridge enable enabling
> > [ENCODER:%d:%s]\n",
> > -				 encoder->base.id, encoder->name);
> > -
> > -		drm_bridge_enable(encoder->bridge);
> > -	}
> > -}
> > -
> >  /* The (potentially) asynchronous part of the commit.  At this point
> >   * nothing can fail short of armageddon.
> >   */
> > @@ -227,7 +102,12 @@ static void complete_commit(struct msm_commit *c)
> > 
> >  	drm_atomic_helper_commit_planes(dev, state, 0);
> > 
> > -	msm_atomic_helper_commit_modeset_enables(dev, state);
> > +	drm_atomic_helper_commit_modeset_enables(dev, state);
> > +
> > +	if (kms->funcs->commit) {
> > +		DRM_DEBUG_ATOMIC("triggering commit\n");
> > +		kms->funcs->commit(kms, state);
> > +	}
> > 
> >  	/* NOTE: _wait_for_vblanks() only waits for vblank on
> >  	 * enabled CRTCs.  So we end up faulting when disabling
> 
> -- 
> Jeykumar S

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
  2018-03-09  1:08                     ` Jeykumar Sankaran
@ 2018-03-12 20:23                       ` Sean Paul
  2018-03-19 15:01                         ` Sean Paul
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-12 20:23 UTC (permalink / raw)
  To: Jeykumar Sankaran
  Cc: linux-arm-msm, dri-devel, abhinavk, Kristian H. Kristensen, freedreno

On Thu, Mar 08, 2018 at 05:08:03PM -0800, Jeykumar Sankaran wrote:
> On 2018-03-02 06:56, Sean Paul wrote:
> > On Thu, Mar 01, 2018 at 07:37:10PM -0500, Rob Clark wrote:
> > > On Thu, Mar 1, 2018 at 3:37 PM,  <jsanka@codeaurora.org> wrote:
> > > > On 2018-03-01 07:27, Sean Paul wrote:
> > > >>
> > > >> On Wed, Feb 28, 2018 at 08:07:00PM -0800, jsanka@codeaurora.org
> > wrote:
> > > >>>
> > > >>> On 2018-02-28 11:19, Sean Paul wrote:
> > > >>> > Moving further towards switching fully to the the atomic helpers,
> > this
> > > >>> > patch removes the hand-rolled kthread nonblock commit code and
> > uses
> > > >>
> > > >> the
> > > >>>
> > > >>> > atomic helpers commit_work model.
> > > >>> >
> > > >>> > There's still a lot of copypasta here, but it's still needed to
> > > >>> > facilitate the swap_state and prepare_fence private functions.
> > These
> > > >>> > will be sorted out in a follow-on patch.
> > > >>> >
> > > >>> > Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
> > > >>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > > >>> > ---
> > > >>> >  drivers/gpu/drm/msm/msm_atomic.c | 199
> > > >>
> > > >> ++++++-------------------------
> > > >>>
> > > >>> >  drivers/gpu/drm/msm/msm_drv.c    |   1 -
> > > >>> >  drivers/gpu/drm/msm/msm_drv.h    |   4 -
> > > >>> >  3 files changed, 35 insertions(+), 169 deletions(-)
> > > >>> >
> > > >>> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> > > >>> > b/drivers/gpu/drm/msm/msm_atomic.c
> > > >>> > index 3a18bd3dc215..7e54eb65d096 100644
> > > >>> > --- a/drivers/gpu/drm/msm/msm_atomic.c
> > > >>> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> > > >>> > @@ -21,51 +21,6 @@
> > > >>> >  #include "msm_gem.h"
> > > >>> >  #include "msm_fence.h"
> > > >>> >
> > > >>> > -struct msm_commit {
> > > >>> > -     struct drm_device *dev;
> > > >>> > -     struct drm_atomic_state *state;
> > > >>> > -     uint32_t crtc_mask;
> > > >>> > -     bool nonblock;
> > > >>> > -     struct kthread_work commit_work;
> > > >>> > -};
> > > >>> > -
> > > >>> > -/* block until specified crtcs are no longer pending update, and
> > > >>> > - * atomically mark them as pending update
> > > >>> > - */
> > > >>> > -static int start_atomic(struct msm_drm_private *priv, uint32_t
> > > >>> > crtc_mask)
> > > >>> > -{
> > > >>> > -     int ret;
> > > >>> > -
> > > >>> > -     spin_lock(&priv->pending_crtcs_event.lock);
> > > >>> > -     ret =
> > wait_event_interruptible_locked(priv->pending_crtcs_event,
> > > >>> > -                     !(priv->pending_crtcs & crtc_mask));
> > > >>> > -     if (ret == 0) {
> > > >>> > -             DBG("start: %08x", crtc_mask);
> > > >>> > -             priv->pending_crtcs |= crtc_mask;
> > > >>> > -     }
> > > >>> > -     spin_unlock(&priv->pending_crtcs_event.lock);
> > > >>> > -
> > > >>> > -     return ret;
> > > >>> > -}
> > > >>> > -
> > > >>> > -/* clear specified crtcs (no longer pending update)
> > > >>> > - */
> > > >>> > -static void end_atomic(struct msm_drm_private *priv, uint32_t
> > > >>> > crtc_mask)
> > > >>> > -{
> > > >>> > -     spin_lock(&priv->pending_crtcs_event.lock);
> > > >>> > -     DBG("end: %08x", crtc_mask);
> > > >>> > -     priv->pending_crtcs &= ~crtc_mask;
> > > >>> > -     wake_up_all_locked(&priv->pending_crtcs_event);
> > > >>> > -     spin_unlock(&priv->pending_crtcs_event.lock);
> > > >>> > -}
> > > >>> > -
> > > >>> > -static void commit_destroy(struct msm_commit *c)
> > > >>> > -{
> > > >>> > -     end_atomic(c->dev->dev_private, c->crtc_mask);
> > > >>> > -     if (c->nonblock)
> > > >>> > -             kfree(c);
> > > >>> > -}
> > > >>> > -
> > > >>> >  static void msm_atomic_wait_for_commit_done(
> > > >>> >               struct drm_device *dev,
> > > >>> >               struct drm_atomic_state *old_state)
> > > >>> > @@ -118,6 +73,10 @@ static void msm_atomic_commit_tail(struct
> > > >>> > drm_atomic_state *state)
> > > >>> >
> > > >>> >       msm_atomic_wait_for_commit_done(dev, state);
> > > >>> >
> > > >>> > +     drm_atomic_helper_commit_hw_done(state);
> > > >>> > +
> > > >>> > +     drm_atomic_helper_wait_for_vblanks(dev, state);
> > > >>> > +
> > > >>> >       drm_atomic_helper_cleanup_planes(dev, state);
> > > >>> >
> > > >>> >       kms->funcs->complete_commit(kms, state);
> > > >>> > @@ -126,109 +85,25 @@ static void msm_atomic_commit_tail(struct
> > > >>> > drm_atomic_state *state)
> > > >>> >  /* The (potentially) asynchronous part of the commit.  At this
> > point
> > > >>> >   * nothing can fail short of armageddon.
> > > >>> >   */
> > > >>> > -static void complete_commit(struct msm_commit *c)
> > > >>> > +static void commit_tail(struct drm_atomic_state *state)
> > > >>> >  {
> > > >>> > -     struct drm_atomic_state *state = c->state;
> > > >>> > -     struct drm_device *dev = state->dev;
> > > >>> > +     drm_atomic_helper_wait_for_fences(state->dev, state, false);
> > > >>> >
> > > >>> > -     drm_atomic_helper_wait_for_fences(dev, state, false);
> > > >>> > +     drm_atomic_helper_wait_for_dependencies(state);
> > > >>> >
> > > >>> >       msm_atomic_commit_tail(state);
> > > >>> >
> > > >>> > -     drm_atomic_state_put(state);
> > > >>> > -}
> > > >>> > -
> > > >>> > -static void _msm_drm_commit_work_cb(struct kthread_work *work)
> > > >>> > -{
> > > >>> > -     struct msm_commit *commit =  NULL;
> > > >>> > -
> > > >>> > -     if (!work) {
> > > >>> > -             DRM_ERROR("%s: Invalid commit work data!\n",
> > __func__);
> > > >>> > -             return;
> > > >>> > -     }
> > > >>> > -
> > > >>> > -     commit = container_of(work, struct msm_commit, commit_work);
> > > >>> > -
> > > >>> > -     complete_commit(commit);
> > > >>> > -
> > > >>> > -     commit_destroy(commit);
> > > >>> > -}
> > > >>> > -
> > > >>> > -static struct msm_commit *commit_init(struct drm_atomic_state
> > *state,
> > > >>> > -             bool nonblock)
> > > >>> > -{
> > > >>> > -     struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
> > > >>> > +     drm_atomic_helper_commit_cleanup_done(state);
> > > >>> >
> > > >>> > -     if (!c)
> > > >>> > -             return NULL;
> > > >>> > -
> > > >>> > -     c->dev = state->dev;
> > > >>> > -     c->state = state;
> > > >>> > -     c->nonblock = nonblock;
> > > >>> > -
> > > >>> > -     kthread_init_work(&c->commit_work, _msm_drm_commit_work_cb);
> > > >>> > -
> > > >>> > -     return c;
> > > >>> > +     drm_atomic_state_put(state);
> > > >>> >  }
> > > >>> >
> > > >>> > -/* Start display thread function */
> > > >>> > -static void msm_atomic_commit_dispatch(struct drm_device *dev,
> > > >>> > -             struct drm_atomic_state *state, struct msm_commit
> > > >>> > *commit)
> > > >>> > +static void commit_work(struct work_struct *work)
> > > >>> >  {
> > > >>> > -     struct msm_drm_private *priv = dev->dev_private;
> > > >>> > -     struct drm_crtc *crtc = NULL;
> > > >>> > -     struct drm_crtc_state *new_crtc_state = NULL;
> > > >>> > -     int ret = -EINVAL, i = 0, j = 0;
> > > >>> > -     bool nonblock;
> > > >>> > -
> > > >>> > -     /* cache since work will kfree commit in non-blocking case
> > */
> > > >>> > -     nonblock = commit->nonblock;
> > > >>> > -
> > > >>> > -     for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
> > > >>> > -             for (j = 0; j < priv->num_crtcs; j++) {
> > > >>> > -                     if (priv->disp_thread[j].crtc_id ==
> > > >>> > -                                             crtc->base.id) {
> > > >>> > -                             if (priv->disp_thread[j].thread) {
> > > >>> > -                                     kthread_queue_work(
> > > >>> > -
> > > >>> > &priv->disp_thread[j].worker,
> > > >>> > -
> > > >>> > &commit->commit_work);
> > > >>> Are there any known proposals floating around to support ASYNC
> > commits
> > > >>
> > > >> for
> > > >>>
> > > >>> concurrent displays rendering at different FPS? The above kthread
> > model
> > > >>
> > > >> is
> > > >>>
> > > >>> introduced when we faced some performance road blockers when a
> > display
> > > >>
> > > >> has
> > > >>>
> > > >>> to wait for an ongoing display commit to complete.
> > > >>
> > > >>
> > > >> I think people have discussed it, I'm not sure if there are any
> > patches
> > > >> floating
> > > >> around. On the surface, it seems easy to just push the commit_work
> > into
> > > >> the crtc
> > > >> commit and have one work item per crtc. However I think the problem
> > is
> > > >> that there
> > > >> could be resources switching between crtcs for a given commit, or
> > from one
> > > >> commit
> > > >> to the next, and synchronizing that becomes a Hard Problem.
> > > >>
> > > >> Perhaps I'm misunderstanding, but the start/end atomic functions
> > serialize
> > > >> the
> > > >> incoming commits, right? So the only benefit the kthread provides is
> > to
> > > >> mitigate
> > > >> any blocking calls made on one crtc from blocking a second crtc in
> > the
> > > >> same
> > > >> commit?
> > > >>
> > > >> Sean
> > > >
> > > > I am not sure what level of resource (I assume hw blocks) switching we
> > can
> > > > expect between
> > > > two active CRTC's on successive commits. With virtualization in play,
> > the
> > > > resources allocated to
> > > > CRTC / encoder / Connector will remain attached to the components as
> > long as
> > > > the display is active.
> > > > Planes (HW pipes) are one such entity which can move between the
> > CRTC's
> > > > frequently. Even
> > > > with them planes, the hw assignment should remain valid until the
> > plane is
> > > > detached from
> > > > a CRTC before attaching to the next one.
> > > 
> > > I think a good example to think about is virtualizing hwpipe<->plane
> > > mapping, for example, when you need to re-assign hwpipes for the next
> > > frame according to what capabilities are needed (yuv, scaling) or gang
> > > up two hwpipes for wide buffer scanout (or re-use one hwpipe for two
> > > planes).. in mdp5 we keep track of what hwpipes are in use by which
> > > planes in driver global atomic state (I have some revived patches from
> > > architt to convert this to driver private objs)..
> > > 
> > > With the atomic model we have serialization in the (to abuse some
> > > terms) "top half" (ie. userspace calling into ioctl) by virtue of the
> > > modeset locks.  But there is a second half to this.  Because we update
> > > the new incoming global state object about what hwpipes are released
> > > in atomic_check, if the incoming state is committed/swapped in the
> > > "top half" we rely on this state being valid in the "bottom half" (in
> > > this case the wq) before pushing the new state to the hw.. which
> > > essentially forces us to serialize committing the state in the "bottom
> > > half" so things happen in the same order as the "top half" intended.
> > > Otherwise we could try to assign a hwpipe to a different crtc while it
> > > is still scanning out for it's previous crtc.  If you have a 30Hz
> > > display plus a 120Hz display, I guess this is a bit sub-optimal.
> > 
> > It's still bad even with displays refreshing at the same rate, the worst
> > case
> > could halve the refresh rate if vblanks aren't in sync.
> > 
> > > 
> > > Maybe the answer is per-crtc wq's for commits plus some sort of
> > > fencing scheme to stall things when there are cross-crtc dependencies
> > > (ie. commit on crtc B depends on hwpipe released by commit on crtc A)?
> > >  This way we don't block updates on the faster display when it isn't
> > > required.  I'm not quite sure how that would work.  But perhaps at
> > > least we could somehow allow out-of-order commits when two updates
> > > don't touch any of the same state obj's.
> > 
> > Right, for "normal" updates, you could use the fast path. We already
> > have
> > needs_modeset, so adding needs_sync wouldn't be too bad. I think I ran
> > into this
> > with tegra back in Pixel C days and hacked in a per-crtc worker since
> > the
> > resources were statically mapped. We'll probably run into this in CrOS
> > as
> > we
> > expand our explicit sync support in the compositor.
> > 
> > > 
> > > (But I do think this is something we should discuss on dri-devel, and
> > > I'd prefer do solve this in the atomic helpers, rather than having
> > > userspace workaround different sets of bugs/quirks for each different
> > > driver.  It really isn't something that is hw specific, so it doesn't
> > > belong in the driver.)
> > 
> > Agreed, this is a tricky bit of code and it would benefit from being
> > used
> > across
> > all drivers (as well as all drivers benefiting from it). At any rate, I
> > can't
> > use multi-display on my development device right now, so I think we'll
> > need to
> > defer for now.
> > 
> > Sean
> > 
> > > 
> > > BR,
> > > -R
> > > 
> > > 
> > > > "Start atomic" synchronizes the commit cycle for all the CRTC's by
> > waiting
> > > > for commit complete
> > > > of all the previous frames. But per crtc kthreads allows the current
> > frame
> > > > commits to happen
> > > > independently. For android, we needed this model as each commit thread
> > need
> > > > to wait for input
> > > > plane fences before programming the hardware.
> > > >
> > > > Jeykumar S.
> > > >
> > > >>
> > > >>> > -                                     /* only return zero if work
> > is
> > > >>> > -                                      * queued successfully.
> > > >>> > -                                      */
> > > >>> > -                                     ret = 0;
> > > >>> > -                             } else {
> > > >>> > -                                     DRM_ERROR(" Error for
> > crtc_id:
> > > >>> > %d\n",
> > > >>> > -
> > > >>> > priv->disp_thread[j].crtc_id);
> > > >>> > -                             }
> > > >>> > -                             break;
> > > >>> > -                     }
> > > >>> > -             }
> 
> Care to remove priv->disp_thread and all its references as a part of this
> change?

Definitely! Will revise.

Sean

> 
> - Jeykumar S
> > > >>> > -             /*
> > > >>> > -              * TODO: handle cases where there will be more than
> > > >>> > -              * one crtc per commit cycle. Remove this check
> > then.
> > > >>> > -              * Current assumption is there will be only one crtc
> > > >>> > -              * per commit cycle.
> > > >>> > -              */
> > > >>> > -             if (j < priv->num_crtcs)
> > > >>> > -                     break;
> > > >>> > -     }
> > > >>> > -
> > > >>> > -     if (ret) {
> > > >>> > -             /**
> > > >>> > -              * this is not expected to happen, but at this point
> > the
> > > >>> > state
> > > >>> > -              * has been swapped, but we couldn't dispatch to a
> > crtc
> > > >>> > thread.
> > > >>> > -              * fallback now to a synchronous complete_commit to
> > try
> > > >>> > and
> > > >>> > -              * ensure that SW and HW state don't get out of
> > sync.
> > > >>> > -              */
> > > >>> > -             DRM_ERROR("failed to dispatch commit to any
> > CRTC\n");
> > > >>> > -             complete_commit(commit);
> > > >>> > -     } else if (!nonblock) {
> > > >>> > -             kthread_flush_work(&commit->commit_work);
> > > >>> > -     }
> > > >>> > -
> > > >>> > -     /* free nonblocking commits in this context, after
> > processing */
> > > >>> > -     if (!nonblock)
> > > >>> > -             kfree(commit);
> > > >>> > +     struct drm_atomic_state *state = container_of(work,
> > > >>> > +                                                   struct
> > > >>> > drm_atomic_state,
> > > >>> > +                                                   commit_work);
> > > >>> > +     commit_tail(state);
> > > >>> >  }
> > > >>> >
> > > >>> >  /**
> > > >>> > @@ -247,17 +122,12 @@ int msm_atomic_commit(struct drm_device
> > *dev,
> > > >>> >               struct drm_atomic_state *state, bool nonblock)
> > > >>> >  {
> > > >>> >       struct msm_drm_private *priv = dev->dev_private;
> > > >>> > -     struct msm_commit *c;
> > > >>> >       struct drm_crtc *crtc;
> > > >>> >       struct drm_crtc_state *crtc_state;
> > > >>> >       struct drm_plane *plane;
> > > >>> >       struct drm_plane_state *old_plane_state, *new_plane_state;
> > > >>> >       int i, ret;
> > > >>> >
> > > >>> > -     ret = drm_atomic_helper_prepare_planes(dev, state);
> > > >>> > -     if (ret)
> > > >>> > -             return ret;
> > > >>> > -
> > > >>> >       /*
> > > >>> >        * Note that plane->atomic_async_check() should fail if we
> > need
> > > >>> >        * to re-assign hwpipe or anything that touches global
> > atomic
> > > >>> > @@ -265,32 +135,30 @@ int msm_atomic_commit(struct drm_device
> > *dev,
> > > >>> >        * cases.
> > > >>> >        */
> > > >>> >       if (state->async_update) {
> > > >>> > +             ret = drm_atomic_helper_prepare_planes(dev, state);
> > > >>> > +             if (ret)
> > > >>> > +                     return ret;
> > > >>> > +
> > > >>> >               drm_atomic_helper_async_commit(dev, state);
> > > >>> >               drm_atomic_helper_cleanup_planes(dev, state);
> > > >>> >               return 0;
> > > >>> >       }
> > > >>> >
> > > >>> > -     c = commit_init(state, nonblock);
> > > >>> > -     if (!c) {
> > > >>> > -             ret = -ENOMEM;
> > > >>> > -             goto error;
> > > >>> > -     }
> > > >>> > +     ret = drm_atomic_helper_setup_commit(state, nonblock);
> > > >>> > +     if (ret)
> > > >>> > +             return ret;
> > > >>> >
> > > >>> > -     /*
> > > >>> > -      * Figure out what crtcs we have:
> > > >>> > -      */
> > > >>> > -     for_each_new_crtc_in_state(state, crtc, crtc_state, i)
> > > >>> > -             c->crtc_mask |= drm_crtc_mask(crtc);
> > > >>> > +     INIT_WORK(&state->commit_work, commit_work);
> > > >>> >
> > > >>> > -     /*
> > > >>> > -      * Wait for pending updates on any of the same crtc's and
> > then
> > > >>> > -      * mark our set of crtc's as busy:
> > > >>> > -      */
> > > >>> > -     ret = start_atomic(dev->dev_private, c->crtc_mask);
> > > >>> > +     ret = drm_atomic_helper_prepare_planes(dev, state);
> > > >>> >       if (ret)
> > > >>> > -             goto err_free;
> > > >>> > +             return ret;
> > > >>> >
> > > >>> > -     BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> > > >>> > +     if (!nonblock) {
> > > >>> > +             ret = drm_atomic_helper_wait_for_fences(dev, state,
> > > >>> > true);
> > > >>> > +             if (ret)
> > > >>> > +                     goto error;
> > > >>> > +     }
> > > >>> >
> > > >>> >       /*
> > > >>> >        * This is the point of no return - everything below never
> > fails
> > > >>> > except
> > > >>> > @@ -299,6 +167,8 @@ int msm_atomic_commit(struct drm_device *dev,
> > > >>> >        *
> > > >>> >        * swap driver private state while still holding state_lock
> > > >>> >        */
> > > >>> > +     BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> > > >>> > +
> > > >>> >       if (to_kms_state(state)->state)
> > > >>> >               priv->kms->funcs->swap_state(priv->kms, state);
> > > >>> >
> > > >>> > @@ -329,12 +199,13 @@ int msm_atomic_commit(struct drm_device
> > *dev,
> > > >>> >        */
> > > >>> >
> > > >>> >       drm_atomic_state_get(state);
> > > >>> > -     msm_atomic_commit_dispatch(dev, state, c);
> > > >>> > +     if (nonblock)
> > > >>> > +             queue_work(system_unbound_wq, &state->commit_work);
> > > >>> > +     else
> > > >>> > +             commit_tail(state);
> > > >>> >
> > > >>> >       return 0;
> > > >>> >
> > > >>> > -err_free:
> > > >>> > -     kfree(c);
> > > >>> >  error:
> > > >>> >       drm_atomic_helper_cleanup_planes(dev, state);
> > > >>> >       return ret;
> > > >>> > diff --git a/drivers/gpu/drm/msm/msm_drv.c
> > > >>> > b/drivers/gpu/drm/msm/msm_drv.c
> > > >>> > index eda4a2340f93..b354424cccb5 100644
> > > >>> > --- a/drivers/gpu/drm/msm/msm_drv.c
> > > >>> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > > >>> > @@ -549,7 +549,6 @@ static int msm_drm_init(struct device *dev,
> > struct
> > > >>> > drm_driver *drv)
> > > >>> >               goto mdss_init_fail;
> > > >>> >
> > > >>> >       priv->wq = alloc_ordered_workqueue("msm_drm", 0);
> > > >>> > -     init_waitqueue_head(&priv->pending_crtcs_event);
> > > >>> >
> > > >>> >       INIT_LIST_HEAD(&priv->client_event_list);
> > > >>> >       INIT_LIST_HEAD(&priv->inactive_list);
> > > >>> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
> > > >>> > b/drivers/gpu/drm/msm/msm_drv.h
> > > >>> > index cf96a85f4b55..292496b682e8 100644
> > > >>> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > > >>> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > > >>> > @@ -536,10 +536,6 @@ struct msm_drm_private {
> > > >>> >
> > > >>> >       struct workqueue_struct *wq;
> > > >>> >
> > > >>> > -     /* crtcs pending async atomic updates: */
> > > >>> > -     uint32_t pending_crtcs;
> > > >>> > -     wait_queue_head_t pending_crtcs_event;
> > > >>> > -
> > > >>> >       unsigned int num_planes;
> > > >>> >       struct drm_plane *planes[MAX_PLANES];
> 
> -- 
> Jeykumar S

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 07/11] drm/msm: Use atomic private_obj instead of subclassing
       [not found]         ` <7fb92416ee99990f6a1280a617736051-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-03-12 20:28           ` Sean Paul
  2018-03-19 17:31             ` [DPU PATCH v2] " Sean Paul
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-12 20:28 UTC (permalink / raw)
  To: Jeykumar Sankaran
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, Sean Paul,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On Thu, Mar 08, 2018 at 05:59:11PM -0800, Jeykumar Sankaran wrote:
> On 2018-02-28 11:19, Sean Paul wrote:
> > Instead of subclassing atomic state, store driver private data in
> > private_obj/state. This allows us to remove the swap_state driver hook
> > for mdp5 and get closer to using the atomic helpers entirely.
> > 
> > Change-Id: I65a4a2887593ae257d584e00b352b5daf00e4e61
> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > ---
> >  drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 37 ++++++--------
> >  drivers/gpu/drm/msm/msm_atomic.c         | 30 -----------
> >  drivers/gpu/drm/msm/msm_drv.c            | 65 ++++++++++++++++++++++--
> >  drivers/gpu/drm/msm/msm_drv.h            |  4 +-
> >  drivers/gpu/drm/msm/msm_kms.h            | 28 +++++-----
> >  5 files changed, 95 insertions(+), 69 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> > b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> > index 6d8e3a9a6fc0..f1a248419655 100644
> > --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> > +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> > @@ -74,36 +74,32 @@ struct mdp5_state *mdp5_get_state(struct
> > drm_atomic_state *s)
> >  {
> >  	struct msm_drm_private *priv = s->dev->dev_private;
> >  	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
> > -	struct msm_kms_state *state = to_kms_state(s);
> > -	struct mdp5_state *new_state;
> > +	struct msm_kms_state *kms_state;
> >  	int ret;
> > 
> > -	if (state->state)
> > -		return state->state;
> > -
> >  	ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
> >  	if (ret)
> >  		return ERR_PTR(ret);
> > 
> > -	new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
> > -	if (!new_state)
> > -		return ERR_PTR(-ENOMEM);
> > +	kms_state = msm_kms_get_state(s);
> > +	if (IS_ERR_OR_NULL(kms_state))
> > +		return (struct mdp5_state *)kms_state; /* casting ERR_PTR
> > */
> > 
> > -	/* Copy state: */
> > -	new_state->hwpipe = mdp5_kms->state->hwpipe;
> > -	new_state->hwmixer = mdp5_kms->state->hwmixer;
> > -	if (mdp5_kms->smp)
> > -		new_state->smp = mdp5_kms->state->smp;
> > +	return kms_state->state;
> > +}
> > 
> > -	state->state = new_state;
> > +static void *mdp5_duplicate_state(void *state)
> > +{
> > +	if (!state)
> > +		return kzalloc(sizeof(struct mdp5_state), GFP_KERNEL);
> > 
> > -	return new_state;
> > +	return kmemdup(state, sizeof(struct mdp5_state), GFP_KERNEL);
> >  }
> > 
> > -static void mdp5_swap_state(struct msm_kms *kms, struct
> > drm_atomic_state
> > *state)
> > +static void mdp5_destroy_state(void *state)
> >  {
> > -	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
> > -	swap(to_kms_state(state)->state, mdp5_kms->state);
> > +	struct mdp5_state *mdp_state = state;
> > +	kfree(mdp_state);
> >  }
> > 
> >  static void mdp5_prepare_commit(struct msm_kms *kms, struct
> > drm_atomic_state *state)
> > @@ -229,7 +225,8 @@ static const struct mdp_kms_funcs kms_funcs = {
> >  		.irq             = mdp5_irq,
> >  		.enable_vblank   = mdp5_enable_vblank,
> >  		.disable_vblank  = mdp5_disable_vblank,
> > -		.swap_state      = mdp5_swap_state,
> > +		.duplicate_state = mdp5_duplicate_state,
> > +		.destroy_state	 = mdp5_destroy_state,
> >  		.prepare_commit  = mdp5_prepare_commit,
> >  		.complete_commit = mdp5_complete_commit,
> >  		.wait_for_crtc_commit_done =
> > mdp5_wait_for_crtc_commit_done,
> > @@ -726,8 +723,6 @@ static void mdp5_destroy(struct platform_device
> > *pdev)
> > 
> >  	if (mdp5_kms->rpm_enabled)
> >  		pm_runtime_disable(&pdev->dev);
> > -
> > -	kfree(mdp5_kms->state);
> >  }
> > 
> >  static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> > b/drivers/gpu/drm/msm/msm_atomic.c
> > index 7e54eb65d096..1f53262ea46b 100644
> > --- a/drivers/gpu/drm/msm/msm_atomic.c
> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> > @@ -169,9 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
> >  	 */
> >  	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> > 
> > -	if (to_kms_state(state)->state)
> > -		priv->kms->funcs->swap_state(priv->kms, state);
> > -
> >  	/*
> >  	 * Provide the driver a chance to prepare for output fences. This
> > is
> >  	 * done after the point of no return, but before asynchronous
> > commits
> > @@ -210,30 +207,3 @@ int msm_atomic_commit(struct drm_device *dev,
> >  	drm_atomic_helper_cleanup_planes(dev, state);
> >  	return ret;
> >  }
> > -
> > -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev)
> > -{
> > -	struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
> > -
> > -	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
> > -		kfree(state);
> > -		return NULL;
> > -	}
> > -
> > -	return &state->base;
> > -}
> > -
> > -void msm_atomic_state_clear(struct drm_atomic_state *s)
> > -{
> > -	struct msm_kms_state *state = to_kms_state(s);
> > -	drm_atomic_state_default_clear(&state->base);
> > -	kfree(state->state);
> > -	state->state = NULL;
> > -}
> > -
> > -void msm_atomic_state_free(struct drm_atomic_state *state)
> > -{
> > -	kfree(to_kms_state(state)->state);
> > -	drm_atomic_state_default_release(state);
> > -	kfree(state);
> > -}
> > diff --git a/drivers/gpu/drm/msm/msm_drv.c
> > b/drivers/gpu/drm/msm/msm_drv.c
> > index b354424cccb5..e582d5889b66 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.c
> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > @@ -121,9 +121,62 @@ static const struct drm_mode_config_funcs
> > mode_config_funcs = {
> >  	.output_poll_changed = msm_fb_output_poll_changed,
> >  	.atomic_check = msm_atomic_check,
> >  	.atomic_commit = msm_atomic_commit,
> > -	.atomic_state_alloc = msm_atomic_state_alloc,
> > -	.atomic_state_clear = msm_atomic_state_clear,
> > -	.atomic_state_free = msm_atomic_state_free,
> > +};
> > +
> > +static inline
> > +struct msm_kms *obj_to_kms(struct drm_private_obj *obj)
> > +{
> > +	return container_of(obj, struct msm_kms, base);
> > +}
> > +
> > +static inline
> > +struct msm_kms_state *state_to_kms_state(struct drm_private_state
> > *state)
> > +{
> > +	return container_of(state, struct msm_kms_state, base);
> > +}
> > +
> > +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *s)
> > +{
> > +	struct msm_drm_private *priv = s->dev->dev_private;
> > +	struct drm_private_obj *obj = &priv->kms->base;
> > +	struct drm_private_state *state;
> > +
> > +	state = drm_atomic_get_private_obj_state(s, obj);
> > +	if (IS_ERR_OR_NULL(state))
> > +		return (struct msm_kms_state *)state; /* casting ERR_PTR
> > */
> > +
> > +	return state_to_kms_state(state);
> > +}
> > +
> > +static struct drm_private_state *
> > +msm_kms_duplicate_state(struct drm_private_obj *obj)
> > +{
> > +	struct msm_kms *kms = obj_to_kms(obj);
> > +	struct msm_kms_state *state = state_to_kms_state(obj->state);
> > +	struct msm_kms_state *new_state;
> > +
> > +	if (kms->funcs->duplicate_state)
> > +		new_state = kms->funcs->duplicate_state(state);
> 
> Shouldn't this be state->state? I believe we are trying to duplicate
> mdp5_state here.

Ahh, yeah, good catch! It might be nice to refactor these hook args to
take something more precise than void * :)

Sean

> 
> > +
> > +	__drm_atomic_helper_private_obj_duplicate_state(obj,
> > &new_state->base);
> > +
> > +	return &new_state->base;
> > +}
> > +
> > +static void msm_kms_destroy_state(struct drm_private_obj *obj,
> > +				  struct drm_private_state *state)
> > +{
> > +	struct msm_kms *kms = obj_to_kms(obj);
> > +	struct msm_kms_state *kms_state = state_to_kms_state(obj->state);
> > +
> > +	if (kms->funcs->destroy_state)
> > +		kms->funcs->destroy_state(kms_state->state);
> > +	kfree(kms_state);
> > +}
> > +
> > +static const struct drm_private_state_funcs kms_state_funcs = {
> > +	.atomic_duplicate_state = msm_kms_duplicate_state,
> > +	.atomic_destroy_state = msm_kms_destroy_state,
> >  };
> > 
> >  #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
> > @@ -341,6 +394,8 @@ static int msm_drm_uninit(struct device *dev)
> >  		}
> >  	}
> > 
> > +	drm_atomic_private_obj_fini(&kms->base);
> > +
> >  	msm_gem_shrinker_cleanup(ddev);
> > 
> >  	drm_kms_helper_poll_fini(ddev);
> > @@ -770,6 +825,10 @@ static int msm_drm_init(struct device *dev, struct
> > drm_driver *drv)
> >  	}
> >  #endif
> > 
> > +	drm_atomic_private_obj_init(&kms->base,
> > +				    &kms->state.base,
> > +				    &kms_state_funcs);
> > +
> >  	/* perform subdriver post initialization */
> >  	if (kms && kms->funcs && kms->funcs->postinit) {
> >  		ret = kms->funcs->postinit(kms);
> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
> > b/drivers/gpu/drm/msm/msm_drv.h
> > index 292496b682e8..8cab333df717 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > @@ -598,9 +598,7 @@ struct msm_format {
> > 
> >  int msm_atomic_commit(struct drm_device *dev,
> >  		struct drm_atomic_state *state, bool nonblock);
> > -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device
> > *dev);
> > -void msm_atomic_state_clear(struct drm_atomic_state *state);
> > -void msm_atomic_state_free(struct drm_atomic_state *state);
> > +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state
> > *state);
> > 
> >  void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
> >  		struct msm_gem_vma *vma, struct sg_table *sgt);
> > diff --git a/drivers/gpu/drm/msm/msm_kms.h
> > b/drivers/gpu/drm/msm/msm_kms.h
> > index 09ba1e79db50..4c5a69258c42 100644
> > --- a/drivers/gpu/drm/msm/msm_kms.h
> > +++ b/drivers/gpu/drm/msm/msm_kms.h
> > @@ -57,6 +57,8 @@ struct msm_kms_funcs {
> >  	void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc
> > *crtc);
> >  	/* swap global atomic state: */
> >  	void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state
> > *state);
> > +	void *(*duplicate_state)(void *state);
> > +	void (*destroy_state)(void *state);
> >  	/* modeset, bracketing atomic_commit(): */
> >  	void (*prepare_fence)(struct msm_kms *kms,
> >  			struct drm_atomic_state *state);
> > @@ -114,16 +116,6 @@ struct msm_kms_funcs {
> >  #endif
> >  };
> > 
> > -struct msm_kms {
> > -	const struct msm_kms_funcs *funcs;
> > -
> > -	/* irq number to be passed on to drm_irq_install */
> > -	int irq;
> > -
> > -	/* mapper-id used to request GEM buffer mapped for scanout: */
> > -	struct msm_gem_address_space *aspace;
> > -};
> > -
> >  /**
> >   * Subclass of drm_atomic_state, to allow kms backend to have driver
> Update comments
> >   * private global state.  The kms backend can do whatever it wants
> > @@ -131,10 +123,22 @@ struct msm_kms {
> >   * is kfree'd and set back to NULL.
> >   */
> >  struct msm_kms_state {
> > -	struct drm_atomic_state base;
> > +	struct drm_private_state base;
> >  	void *state;
> >  };
> > -#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
> > +
> > +struct msm_kms {
> > +	struct drm_private_obj base;
> > +	struct msm_kms_state state;
> > +
> > +	const struct msm_kms_funcs *funcs;
> > +
> > +	/* irq number to be passed on to drm_irq_install */
> > +	int irq;
> > +
> > +	/* mapper-id used to request GEM buffer mapped for scanout: */
> > +	struct msm_gem_address_space *aspace;
> > +};
> > 
> >  static inline void msm_kms_init(struct msm_kms *kms,
> >  		const struct msm_kms_funcs *funcs)
> 
> -- 
> Jeykumar S

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 08/11] drm/msm: Remove hand-rolled out fences
       [not found]         ` <1a1c79ddb6ddabbc72e4624b53460188-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-03-12 20:30           ` Sean Paul
  2018-03-13 18:11             ` Jeykumar Sankaran
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-12 20:30 UTC (permalink / raw)
  To: Jeykumar Sankaran
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, Sean Paul,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On Fri, Mar 02, 2018 at 04:44:55PM -0800, Jeykumar Sankaran wrote:
> On 2018-02-28 11:19, Sean Paul wrote:
> > Remove release/output/retire fences from the dpu driver. These are
> > already available via drm core's OUT_FENCE property.
> > 
> > Change-Id: Id4238d0b5457f2c8ee2e87bb7814e1850a573623
> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c |  66 +------
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h |  23 ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      | 178 +++---------------
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h      |  28 ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |   3 -
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   4 +-
> >  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 -
> >  .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |  73 +------
> >  .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |  19 --
> >  .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   |  12 +-
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c       |  30 ---
> >  drivers/gpu/drm/msm/msm_drv.h                 |   3 -
> >  12 files changed, 36 insertions(+), 411 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> > index 57b8627ef418..cc5bfa862cb7 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
> > @@ -521,7 +521,6 @@ static void dpu_connector_destroy(struct
> > drm_connector
> > *connector)
> >  		backlight_device_unregister(c_conn->bl_device);
> >  	drm_connector_unregister(connector);
> >  	mutex_destroy(&c_conn->lock);
> > -	dpu_fence_deinit(&c_conn->retire_fence);
> >  	drm_connector_cleanup(connector);
> >  	kfree(c_conn);
> >  }
> > @@ -906,12 +905,9 @@ static int dpu_connector_atomic_get_property(struct
> > drm_connector *connector,
> >  	c_state = to_dpu_connector_state(state);
> > 
> >  	idx = msm_property_index(&c_conn->property_info, property);
> > -	if (idx == CONNECTOR_PROP_RETIRE_FENCE)
> > -		rc = dpu_fence_create(&c_conn->retire_fence, val, 0);
> > -	else
> > -		/* get cached property value */
> > -		rc = msm_property_atomic_get(&c_conn->property_info,
> > -				&c_state->property_state, property, val);
> > +	/* get cached property value */
> > +	rc = msm_property_atomic_get(&c_conn->property_info,
> > +			&c_state->property_state, property, val);
> > 
> >  	/* allow for custom override */
> >  	if (c_conn->ops.get_property)
> > @@ -923,39 +919,6 @@ static int dpu_connector_atomic_get_property(struct
> > drm_connector *connector,
> >  	return rc;
> >  }
> > 
> > -void dpu_connector_prepare_fence(struct drm_connector *connector)
> > -{
> > -	if (!connector) {
> > -		DPU_ERROR("invalid connector\n");
> > -		return;
> > -	}
> > -
> > -	dpu_fence_prepare(&to_dpu_connector(connector)->retire_fence);
> > -}
> > -
> > -void dpu_connector_complete_commit(struct drm_connector *connector,
> > -		ktime_t ts)
> > -{
> > -	if (!connector) {
> > -		DPU_ERROR("invalid connector\n");
> > -		return;
> > -	}
> > -
> > -	/* signal connector's retire fence */
> > -	dpu_fence_signal(&to_dpu_connector(connector)->retire_fence, ts,
> > false);
> > -}
> > -
> > -void dpu_connector_commit_reset(struct drm_connector *connector,
> > ktime_t
> > ts)
> > -{
> > -	if (!connector) {
> > -		DPU_ERROR("invalid connector\n");
> > -		return;
> > -	}
> > -
> > -	/* signal connector's retire fence */
> > -	dpu_fence_signal(&to_dpu_connector(connector)->retire_fence, ts,
> > true);
> > -}
> > -
> >  static enum drm_connector_status
> >  dpu_connector_detect(struct drm_connector *connector, bool force)
> >  {
> > @@ -1214,26 +1177,19 @@ struct drm_connector *dpu_connector_init(struct
> > drm_device *dev,
> >  			"conn%u",
> >  			c_conn->base.base.id);
> > 
> > -	rc = dpu_fence_init(&c_conn->retire_fence, c_conn->name,
> > -			c_conn->base.base.id);
> > -	if (rc) {
> > -		DPU_ERROR("failed to init fence, %d\n", rc);
> > -		goto error_cleanup_conn;
> > -	}
> > -
> >  	mutex_init(&c_conn->lock);
> > 
> >  	rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder);
> >  	if (rc) {
> >  		DPU_ERROR("failed to attach encoder to connector, %d\n",
> > rc);
> > -		goto error_cleanup_fence;
> > +		goto error_cleanup_conn;
> >  	}
> > 
> >  #ifdef CONFIG_DRM_MSM_DSI_STAGING
> >  	rc = dpu_backlight_setup(c_conn, dev);
> >  	if (rc) {
> >  		DPU_ERROR("failed to setup backlight, rc=%d\n", rc);
> > -		goto error_cleanup_fence;
> > +		goto error_cleanup_conn;
> >  	}
> >  #endif
> > 
> > @@ -1248,7 +1204,7 @@ struct drm_connector *dpu_connector_init(struct
> > drm_device *dev,
> >  		if (!info) {
> >  			DPU_ERROR("failed to allocate info buffer\n");
> >  			rc = -ENOMEM;
> > -			goto error_cleanup_fence;
> > +			goto error_cleanup_conn;
> >  		}
> > 
> >  		dpu_kms_info_reset(info);
> > @@ -1256,7 +1212,7 @@ struct drm_connector *dpu_connector_init(struct
> > drm_device *dev,
> >  		if (rc) {
> >  			DPU_ERROR("post-init failed, %d\n", rc);
> >  			kfree(info);
> > -			goto error_cleanup_fence;
> > +			goto error_cleanup_conn;
> >  		}
> > 
> >  		msm_property_install_blob(&c_conn->property_info,
> > @@ -1310,10 +1266,6 @@ struct drm_connector *dpu_connector_init(struct
> > drm_device *dev,
> >  				&c_conn->property_info, "dpu_drm_roi_v1",
> > 0x0,
> >  				0, ~0, 0, CONNECTOR_PROP_ROI_V1);
> >  	}
> > -
> > -	msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
> > -			0x0, 0, INR_OPEN_MAX, 0,
> > CONNECTOR_PROP_RETIRE_FENCE);
> > -
> >  	msm_property_install_range(&c_conn->property_info, "autorefresh",
> >  			0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0,
> >  			CONNECTOR_PROP_AUTOREFRESH);
> > @@ -1354,10 +1306,8 @@ struct drm_connector *dpu_connector_init(struct
> > drm_device *dev,
> >  		drm_property_blob_put(c_conn->blob_dither);
> > 
> >  	msm_property_destroy(&c_conn->property_info);
> > -error_cleanup_fence:
> > -	mutex_destroy(&c_conn->lock);
> > -	dpu_fence_deinit(&c_conn->retire_fence);
> >  error_cleanup_conn:
> > +	mutex_destroy(&c_conn->lock);
> >  	drm_connector_cleanup(&c_conn->base);
> >  error_free_conn:
> >  	kfree(c_conn);
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> > index f6f4837d1359..fdb4d8766549 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
> > @@ -21,7 +21,6 @@
> >  #include "msm_drv.h"
> >  #include "msm_prop.h"
> >  #include "dpu_kms.h"
> > -#include "dpu_fence.h"
> > 
> >  #define DPU_CONNECTOR_NAME_SIZE	16
> > 
> > @@ -247,7 +246,6 @@ struct dpu_connector_evt {
> >   * @mmu_unsecure: MMU id for unsecure buffers
> >   * @name: ASCII name of connector
> >   * @lock: Mutex lock object for this structure
> > - * @retire_fence: Retire fence context reference
> >   * @ops: Local callback function pointer table
> >   * @dpms_mode: DPMS property setting from user space
> >   * @lp_mode: LP property setting from user space
> > @@ -274,7 +272,6 @@ struct dpu_connector {
> >  	char name[DPU_CONNECTOR_NAME_SIZE];
> > 
> >  	struct mutex lock;
> > -	struct dpu_fence_context retire_fence;
> >  	struct dpu_connector_ops ops;
> >  	int dpms_mode;
> >  	int lp_mode;
> > @@ -447,26 +444,6 @@ struct drm_connector *dpu_connector_init(struct
> > drm_device *dev,
> >  		int connector_poll,
> >  		int connector_type);
> > 
> > -/**
> > - * dpu_connector_prepare_fence - prepare fence support for current
> > commit
> > - * @connector: Pointer to drm connector object
> > - */
> > -void dpu_connector_prepare_fence(struct drm_connector *connector);
> > -
> > -/**
> > - * dpu_connector_complete_commit - signal completion of current commit
> > - * @connector: Pointer to drm connector object
> > - * @ts: timestamp to be updated in the fence signalling
> > - */
> > -void dpu_connector_complete_commit(struct drm_connector *connector,
> > ktime_t ts);
> > -
> > -/**
> > - * dpu_connector_commit_reset - reset the completion signal
> > - * @connector: Pointer to drm connector object
> > - * @ts: timestamp to be updated in the fence signalling
> > - */
> > -void dpu_connector_commit_reset(struct drm_connector *connector,
> > ktime_t
> > ts);
> > -
> >  /**
> >   * dpu_connector_get_info - query display specific information
> >   * @connector: Pointer to drm connector object
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index a261021e5deb..2d44989ade7a 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -629,7 +629,6 @@ static void dpu_crtc_destroy(struct drm_crtc *crtc)
> >  	dpu_cp_crtc_destroy_properties(crtc);
> >  	_dpu_crtc_destroy_dest_scaler(dpu_crtc);
> > 
> > -	dpu_fence_deinit(&dpu_crtc->output_fence);
> >  	_dpu_crtc_deinit_events(dpu_crtc);
> > 
> >  	drm_crtc_cleanup(crtc);
> > @@ -1671,65 +1670,6 @@ static void _dpu_crtc_dest_scaler_setup(struct
> > drm_crtc *crtc)
> >  	}
> >  }
> > 
> > -void dpu_crtc_prepare_commit(struct drm_crtc *crtc,
> > -		struct drm_crtc_state *old_state)
> > -{
> > -	struct drm_device *dev;
> > -	struct dpu_crtc *dpu_crtc;
> > -	struct dpu_crtc_state *cstate;
> > -	struct drm_connector *conn;
> > -	struct drm_connector_list_iter conn_iter;
> > -	struct dpu_crtc_retire_event *retire_event = NULL;
> > -	unsigned long flags;
> > -	int i;
> > -
> > -	if (!crtc || !crtc->state) {
> > -		DPU_ERROR("invalid crtc\n");
> > -		return;
> > -	}
> > -
> > -	dev = crtc->dev;
> > -	dpu_crtc = to_dpu_crtc(crtc);
> > -	cstate = to_dpu_crtc_state(crtc->state);
> > -	DPU_EVT32_VERBOSE(DRMID(crtc));
> > -
> > -	/* identify connectors attached to this crtc */
> > -	cstate->num_connectors = 0;
> > -
> > -	drm_connector_list_iter_begin(dev, &conn_iter);
> > -	drm_for_each_connector_iter(conn, &conn_iter)
> > -		if (conn->state && conn->state->crtc == crtc &&
> > -				cstate->num_connectors < MAX_CONNECTORS) {
> > -			cstate->connectors[cstate->num_connectors++] =
> > conn;
> > -			dpu_connector_prepare_fence(conn);
> > -		}
> > -	drm_connector_list_iter_end(&conn_iter);
> > -
> > -	for (i = 0; i < DPU_CRTC_FRAME_EVENT_SIZE; i++) {
> > -		retire_event = &dpu_crtc->retire_events[i];
> > -		if (list_empty(&retire_event->list))
> > -			break;
> > -		retire_event = NULL;
> > -	}
> > -
> > -	if (retire_event) {
> > -		retire_event->num_connectors = cstate->num_connectors;
> > -		for (i = 0; i < cstate->num_connectors; i++)
> > -			retire_event->connectors[i] =
> > cstate->connectors[i];
> > -
> > -		spin_lock_irqsave(&dpu_crtc->spin_lock, flags);
> > -		list_add_tail(&retire_event->list,
> > -
> > &dpu_crtc->retire_event_list);
> > -		spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
> > -	} else {
> > -		DPU_ERROR("crtc%d retire event overflow\n",
> > crtc->base.id);
> > -		DPU_EVT32(DRMID(crtc), DPU_EVTLOG_ERROR);
> > -	}
> > -
> > -	/* prepare main output fence */
> > -	dpu_fence_prepare(&dpu_crtc->output_fence);
> > -}
> > -
> >  /**
> >   *  _dpu_crtc_complete_flip - signal pending page_flip events
> >   * Any pending vblank events are added to the vblank_event_list
> > @@ -1799,41 +1739,6 @@ static void dpu_crtc_vblank_cb(void *data)
> >  	DPU_EVT32_VERBOSE(DRMID(crtc));
> >  }
> > 
> > -static void _dpu_crtc_retire_event(struct drm_crtc *crtc, ktime_t ts)
> > -{
> > -	struct dpu_crtc_retire_event *retire_event;
> > -	struct dpu_crtc *dpu_crtc;
> > -	unsigned long flags;
> > -	int i;
> > -
> > -	if (!crtc) {
> > -		DPU_ERROR("invalid param\n");
> > -		return;
> > -	}
> > -
> > -	dpu_crtc = to_dpu_crtc(crtc);
> > -	spin_lock_irqsave(&dpu_crtc->spin_lock, flags);
> > -	retire_event =
> > list_first_entry_or_null(&dpu_crtc->retire_event_list,
> > -				struct dpu_crtc_retire_event, list);
> > -	if (retire_event)
> > -		list_del_init(&retire_event->list);
> > -	spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
> > -
> > -	if (!retire_event) {
> > -		DPU_ERROR("crtc%d retire event without kickoff\n",
> > -
> > crtc->base.id);
> > -		DPU_EVT32(DRMID(crtc), DPU_EVTLOG_ERROR);
> > -		return;
> > -	}
> > -
> > -	DPU_ATRACE_BEGIN("signal_retire_fence");
> > -	for (i = 0; (i < retire_event->num_connectors) &&
> > -					retire_event->connectors[i]; ++i)
> > -		dpu_connector_complete_commit(
> > -					retire_event->connectors[i], ts);
> > -	DPU_ATRACE_END("signal_retire_fence");
> > -}
> > -
> >  /* _dpu_crtc_idle_notify - signal idle timeout to client */
> >  static void _dpu_crtc_idle_notify(struct dpu_crtc *dpu_crtc)
> >  {
> > @@ -1945,16 +1850,6 @@ static void dpu_crtc_frame_event_work(struct
> > kthread_work *work)
> >  			frame_done = true;
> >  	}
> > 
> > -	if (fevent->event & DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE)
> > {
> > -		DPU_ATRACE_BEGIN("signal_release_fence");
> > -		dpu_fence_signal(&dpu_crtc->output_fence, fevent->ts,
> > false);
> > -		DPU_ATRACE_END("signal_release_fence");
> > -	}
> > -
> > -	if (fevent->event & DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE)
> > -		/* this api should be called without spin_lock */
> > -		_dpu_crtc_retire_event(crtc, fevent->ts);
> > -
> >  	if (fevent->event & DPU_ENCODER_FRAME_EVENT_PANEL_DEAD)
> >  		DPU_ERROR("crtc%d ts:%lld received panel dead event\n",
> >  				crtc->base.id, ktime_to_ns(fevent->ts));
> > @@ -1971,11 +1866,11 @@ static void dpu_crtc_frame_event_work(struct
> > kthread_work *work)
> >  /*
> >   * dpu_crtc_frame_event_cb - crtc frame event callback API. CRTC module
> >   * registers this API to encoder for all frame event callbacks like
> > - * release_fence, retire_fence, frame_error, frame_done, idle_timeout,
> > - * etc. Encoder may call different events from different context - IRQ,
> > - * user thread, commit_thread, etc. Each event should be carefully
> > - * reviewed and should be processed in proper task context to avoid
> > scheduling
> > - * delay or properly manage the irq context's bottom half processing.
> > + * frame_error, frame_done, idle_timeout, etc. Encoder may call
> > different
> > events
> > + * from different context - IRQ, user thread, commit_thread, etc. Each
> > event
> > + * should be carefully reviewed and should be processed in proper task
> > context
> > + * to avoid schedulin delay or properly manage the irq context's bottom
> > half
> > + * processing.
> >   */
> >  static void dpu_crtc_frame_event_cb(void *data, u32 event)
> >  {
> > @@ -3484,14 +3379,6 @@ static void dpu_crtc_disable(struct drm_crtc
> > *crtc)
> >  		dpu_power_handle_unregister_event(&priv->phandle,
> >  				dpu_crtc->power_event);
> > 
> > -	/**
> > -	 * All callbacks are unregistered and frame done waits are
> > complete
> > -	 * at this point. No buffers are accessed by hardware.
> > -	 * reset the fence timeline if there is any issue.
> > -	 */
> > -	dpu_fence_signal(&dpu_crtc->output_fence, ktime_get(), true);
> > -	for (i = 0; i < cstate->num_connectors; ++i)
> > -		dpu_connector_commit_reset(cstate->connectors[i],
> > ktime_get());
> > 
> >  	memset(dpu_crtc->mixers, 0, sizeof(dpu_crtc->mixers));
> >  	dpu_crtc->num_mixers = 0;
> > @@ -3703,6 +3590,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc
> > *crtc,
> >  	int multirect_count = 0;
> >  	const struct drm_plane_state *pipe_staged[SSPP_MAX];
> >  	int left_zpos_cnt = 0, right_zpos_cnt = 0;
> > +	struct drm_connector_list_iter conn_iter;
> > +	struct drm_connector *conn;
> > 
> >  	if (!crtc) {
> >  		DPU_ERROR("invalid crtc\n");
> > @@ -3956,6 +3845,16 @@ static int dpu_crtc_atomic_check(struct drm_crtc
> > *crtc,
> >  		goto end;
> >  	}
> > 
> > +	/* identify connectors attached to this crtc */
> > +	cstate->num_connectors = 0;
> > +	drm_connector_list_iter_begin(crtc->dev, &conn_iter);
> > +	drm_for_each_connector_iter(conn, &conn_iter)
> > +		if (conn->state && conn->state->crtc == crtc &&
> > +				cstate->num_connectors < MAX_CONNECTORS) {
> > +			cstate->connectors[cstate->num_connectors++] =
> > conn;
> > +		}
> > +	drm_connector_list_iter_end(&conn_iter);
> > +
> 
> Is this hunk related to this change?
> 

This code came from dpu_crtc_prepare_commit. We use cstate->num_connectors
elsewhere, so it needed to be preserved.

Sean

> >  end:
> >  	_dpu_crtc_rp_free_unused(&cstate->rp);
> >  	return rc;
> > @@ -4034,13 +3933,6 @@ static void dpu_crtc_install_properties(struct
> > drm_crtc *crtc,
> >  		"input_fence_timeout", 0x0, 0,
> > DPU_CRTC_MAX_INPUT_FENCE_TIMEOUT,
> >  		DPU_CRTC_INPUT_FENCE_TIMEOUT,
> > CRTC_PROP_INPUT_FENCE_TIMEOUT);
> > 
> > -	msm_property_install_range(&dpu_crtc->property_info,
> > "output_fence",
> > -			0x0, 0, INR_OPEN_MAX, 0x0,
> > CRTC_PROP_OUTPUT_FENCE);
> > -
> > -	msm_property_install_range(&dpu_crtc->property_info,
> > -			"output_fence_offset", 0x0, 0, 1, 0,
> > -			CRTC_PROP_OUTPUT_FENCE_OFFSET);
> > -
> >  	msm_property_install_range(&dpu_crtc->property_info,
> >  			"core_clk", 0x0, 0, U64_MAX,
> >  			dpu_kms->perf.max_core_clk_rate,
> > @@ -4342,29 +4234,12 @@ static int dpu_crtc_atomic_get_property(struct
> > drm_crtc *crtc,
> >  		}
> > 
> >  		i = msm_property_index(&dpu_crtc->property_info,
> > property);
> > -		if (i == CRTC_PROP_OUTPUT_FENCE) {
> > -			uint32_t offset = dpu_crtc_get_property(cstate,
> > -					CRTC_PROP_OUTPUT_FENCE_OFFSET);
> > -
> > -			/**
> > -			 * set the offset to 0 only for cmd mode panels,
> > so
> > -			 * the release fence for the current frame can be
> > -			 * triggered right after PP_DONE interrupt.
> > -			 */
> > -			offset = is_cmd ? 0 : (offset + conn_offset);
> > -
> > -			ret = dpu_fence_create(&dpu_crtc->output_fence,
> > val,
> > -								offset);
> > -			if (ret)
> > -				DPU_ERROR("fence create failed\n");
> > -		} else {
> > -			ret =
> > msm_property_atomic_get(&dpu_crtc->property_info,
> > -					&cstate->property_state,
> > -					property, val);
> > -			if (ret)
> > -				ret = dpu_cp_crtc_get_property(crtc,
> > -					property, val);
> > -		}
> > +		ret = msm_property_atomic_get(&dpu_crtc->property_info,
> > +				&cstate->property_state,
> > +				property, val);
> > +		if (ret)
> > +			ret = dpu_cp_crtc_get_property(crtc,
> > +				property, val);
> >  		if (ret)
> >  			DRM_ERROR("get property failed\n");
> >  	}
> > @@ -4858,10 +4733,6 @@ static int _dpu_crtc_init_events(struct dpu_crtc
> > *dpu_crtc)
> >  		list_add_tail(&dpu_crtc->event_cache[i].list,
> >  				&dpu_crtc->event_free_list);
> > 
> > -	INIT_LIST_HEAD(&dpu_crtc->retire_event_list);
> > -	for (i = 0; i < ARRAY_SIZE(dpu_crtc->retire_events); i++)
> > -		INIT_LIST_HEAD(&dpu_crtc->retire_events[i].list);
> > -
> >  	return rc;
> >  }
> > 
> > @@ -4920,9 +4791,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device
> > *dev, struct drm_plane *plane)
> >  		return ERR_PTR(rc);
> >  	}
> > 
> > -	/* initialize output fence support */
> > -	dpu_fence_init(&dpu_crtc->output_fence, dpu_crtc->name,
> > crtc->base.id);
> > -
> >  	/* create CRTC properties */
> >  	msm_property_init(&dpu_crtc->property_info, &crtc->base, dev,
> >  			priv->crtc_property, dpu_crtc->property_data,
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> > index b63df243be33..727a3434a4f6 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> > @@ -22,7 +22,6 @@
> >  #include <linux/kthread.h>
> >  #include <drm/drm_crtc.h>
> >  #include "msm_prop.h"
> > -#include "dpu_fence.h"
> >  #include "dpu_kms.h"
> >  #include "dpu_core_perf.h"
> >  #include "dpu_hw_blk.h"
> > @@ -85,17 +84,6 @@ struct dpu_crtc_smmu_state_data {
> >  	uint32_t transition_error;
> >  };
> > 
> > -/**
> > - * @connectors    : Currently associated drm connectors for retire
> > event
> > - * @num_connectors: Number of associated drm connectors for retire
> > event
> > - * @list:	event list
> > - */
> > -struct dpu_crtc_retire_event {
> > -	struct drm_connector *connectors[MAX_CONNECTORS];
> > -	int num_connectors;
> > -	struct list_head list;
> > -};
> > -
> >  /**
> >   * struct dpu_crtc_mixer: stores the map for each virtual pipeline in
> > the
> > CRTC
> >   * @hw_lm:	LM HW Driver context
> > @@ -169,7 +157,6 @@ struct dpu_crtc_event {
> >   * @drm_requested_vblank : Whether vblanks have been enabled in the
> > encoder
> >   * @property_info : Opaque structure for generic property support
> >   * @property_defaults : Array of default values for generic property
> > support
> > - * @output_fence  : output release fence context
> >   * @stage_cfg     : H/w mixer stage configuration
> >   * @debugfs_root  : Parent of debugfs node
> >   * @vblank_cb_count : count of vblank callback since last reset
> > @@ -190,8 +177,6 @@ struct dpu_crtc_event {
> >   * @frame_events  : static allocation of in-flight frame events
> >   * @frame_event_list : available frame event list
> >   * @spin_lock     : spin lock for frame event, transaction status,
> > etc...
> > - * @retire_events  : static allocation of retire fence connector
> > - * @retire_event_list : available retire fence connector list
> >   * @frame_done_comp    : for frame_event_done synchronization
> >   * @event_thread  : Pointer to event handler thread
> >   * @event_worker  : Event worker queue
> > @@ -227,9 +212,6 @@ struct dpu_crtc {
> >  	struct msm_property_data property_data[CRTC_PROP_COUNT];
> >  	struct drm_property_blob *blob_info;
> > 
> > -	/* output fence support */
> > -	struct dpu_fence_context output_fence;
> > -
> >  	struct dpu_hw_stage_cfg stage_cfg;
> >  	struct dentry *debugfs_root;
> > 
> > @@ -253,8 +235,6 @@ struct dpu_crtc {
> >  	struct dpu_crtc_frame_event
> > frame_events[DPU_CRTC_FRAME_EVENT_SIZE];
> >  	struct list_head frame_event_list;
> >  	spinlock_t spin_lock;
> > -	struct dpu_crtc_retire_event
> > retire_events[DPU_CRTC_FRAME_EVENT_SIZE];
> > -	struct list_head retire_event_list;
> >  	struct completion frame_done_comp;
> > 
> >  	/* for handling internal event thread */
> > @@ -475,14 +455,6 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool
> > en);
> >   */
> >  void dpu_crtc_commit_kickoff(struct drm_crtc *crtc);
> > 
> > -/**
> > - * dpu_crtc_prepare_commit - callback to prepare for output fences
> > - * @crtc: Pointer to drm crtc object
> > - * @old_state: Pointer to drm crtc old state object
> > - */
> > -void dpu_crtc_prepare_commit(struct drm_crtc *crtc,
> > -		struct drm_crtc_state *old_state);
> > -
> >  /**
> >   * dpu_crtc_complete_commit - callback signalling completion of current
> > commit
> >   * @crtc: Pointer to drm crtc object
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 4d1e3652dbf4..a54ad2cd5856 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -2465,9 +2465,6 @@ static inline void
> > _dpu_encoder_trigger_flush(struct
> > drm_encoder *drm_enc,
> > 
> >  	pending_kickoff_cnt = dpu_encoder_phys_inc_pending(phys);
> > 
> > -	if (phys->ops.is_master && phys->ops.is_master(phys))
> > -		atomic_inc(&phys->pending_retire_fence_cnt);
> > -
> >  	if (extra_flush_bits && ctl->ops.update_pending_flush)
> >  		ctl->ops.update_pending_flush(ctl, extra_flush_bits);
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> > index 69fb26cb43ab..86a3800af673 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> > @@ -27,9 +27,7 @@
> >  #define DPU_ENCODER_FRAME_EVENT_DONE			BIT(0)
> >  #define DPU_ENCODER_FRAME_EVENT_ERROR			BIT(1)
> >  #define DPU_ENCODER_FRAME_EVENT_PANEL_DEAD		BIT(2)
> > -#define DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE	BIT(3)
> > -#define DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE	BIT(4)
> > -#define DPU_ENCODER_FRAME_EVENT_IDLE			BIT(5)
> > +#define DPU_ENCODER_FRAME_EVENT_IDLE			BIT(3)
> > 
> >  #define IDLE_TIMEOUT	(66 - 16/2)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> > index 3b05569007d2..71cd2f258994 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> > @@ -245,8 +245,6 @@ struct dpu_encoder_irq {
> >   *				scheduled. Decremented in irq handler
> >   * @pending_ctlstart_cnt:	Atomic counter tracking the number of ctl
> > start
> >   *                              pending.
> > - * @pending_retire_fence_cnt:   Atomic counter tracking the pending
> > retire
> > - *                              fences that have to be signalled.
> >   * @pending_kickoff_wq:		Wait queue for blocking until
> > kickoff completes
> >   * @irq:			IRQ tracking structures
> >   */
> > @@ -273,7 +271,6 @@ struct dpu_encoder_phys {
> >  	atomic_t underrun_cnt;
> >  	atomic_t pending_ctlstart_cnt;
> >  	atomic_t pending_kickoff_cnt;
> > -	atomic_t pending_retire_fence_cnt;
> >  	wait_queue_head_t pending_kickoff_wq;
> >  	struct dpu_encoder_irq irq[INTR_IDX_MAX];
> >  };
> > @@ -323,9 +320,6 @@ struct dpu_encoder_phys_cmd_autorefresh {
> >   *			after ctl_start instead of before next frame
> > kickoff
> >   * @pp_timeout_report_cnt: number of pingpong done irq timeout errors
> >   * @autorefresh: autorefresh feature state
> > - * @pending_rd_ptr_cnt: atomic counter to indicate if retire fence can
> > be
> > - *                      signaled at the next rd_ptr_irq
> > - * @rd_ptr_timestamp: last rd_ptr_irq timestamp
> >   * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK
> >   * @pending_vblank_wq: Wait queue for blocking until VBLANK received
> >   */
> > @@ -335,8 +329,6 @@ struct dpu_encoder_phys_cmd {
> >  	bool serialize_wait4pp;
> >  	int pp_timeout_report_cnt;
> >  	struct dpu_encoder_phys_cmd_autorefresh autorefresh;
> > -	atomic_t pending_rd_ptr_cnt;
> > -	ktime_t rd_ptr_timestamp;
> >  	atomic_t pending_vblank_cnt;
> >  	wait_queue_head_t pending_vblank_wq;
> >  };
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> > index e92380a1d5a4..6ccf37820aa2 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> > @@ -44,12 +44,6 @@
> > 
> >  #define DPU_ENC_WR_PTR_START_TIMEOUT_US 20000
> > 
> > -/*
> > - * Threshold for signalling retire fences in cases where
> > - * CTL_START_IRQ is received just after RD_PTR_IRQ
> > - */
> > -#define DPU_ENC_CTL_START_THRESHOLD_US 500
> > -
> >  static inline int _dpu_encoder_phys_cmd_get_idle_timeout(
> >  		struct dpu_encoder_phys_cmd *cmd_enc)
> >  {
> > @@ -170,8 +164,7 @@ static void dpu_encoder_phys_cmd_pp_tx_done_irq(void
> > *arg, int irq_idx)
> >  	struct dpu_encoder_phys *phys_enc = arg;
> >  	unsigned long lock_flags;
> >  	int new_cnt;
> > -	u32 event = DPU_ENCODER_FRAME_EVENT_DONE |
> > -			DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
> > +	u32 event = DPU_ENCODER_FRAME_EVENT_DONE;
> > 
> >  	if (!phys_enc || !phys_enc->hw_pp)
> >  		return;
> > @@ -221,7 +214,6 @@ static void dpu_encoder_phys_cmd_pp_rd_ptr_irq(void
> > *arg, int irq_idx)
> >  {
> >  	struct dpu_encoder_phys *phys_enc = arg;
> >  	struct dpu_encoder_phys_cmd *cmd_enc;
> > -	u32 event = 0;
> > 
> >  	if (!phys_enc || !phys_enc->hw_pp)
> >  		return;
> > @@ -229,30 +221,10 @@ static void
> > dpu_encoder_phys_cmd_pp_rd_ptr_irq(void
> > *arg, int irq_idx)
> >  	DPU_ATRACE_BEGIN("rd_ptr_irq");
> >  	cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
> > 
> > -	/**
> > -	 * signal only for master, when the ctl_start irq is
> > -	 * done and incremented the pending_rd_ptr_cnt.
> > -	 */
> > -	if (dpu_encoder_phys_cmd_is_master(phys_enc)
> > -		    && atomic_add_unless(&cmd_enc->pending_rd_ptr_cnt, -1,
> > 0)
> > -		    && atomic_add_unless(
> > -				&phys_enc->pending_retire_fence_cnt, -1,
> > 0)) {
> > -
> > -		event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
> > -		if (phys_enc->parent_ops.handle_frame_done)
> > -			phys_enc->parent_ops.handle_frame_done(
> > -				phys_enc->parent, phys_enc, event);
> > -	}
> > -
> > -	DPU_EVT32_IRQ(DRMID(phys_enc->parent),
> > -			phys_enc->hw_pp->idx - PINGPONG_0, event, 0xfff);
> > -
> >  	if (phys_enc->parent_ops.handle_vblank_virt)
> >  		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
> >  			phys_enc);
> > 
> > -	cmd_enc->rd_ptr_timestamp = ktime_get();
> > -
> >  	atomic_add_unless(&cmd_enc->pending_vblank_cnt, -1, 0);
> >  	wake_up_all(&cmd_enc->pending_vblank_wq);
> >  	DPU_ATRACE_END("rd_ptr_irq");
> > @@ -262,9 +234,6 @@ static void dpu_encoder_phys_cmd_ctl_start_irq(void
> > *arg, int irq_idx)
> >  {
> >  	struct dpu_encoder_phys *phys_enc = arg;
> >  	struct dpu_encoder_phys_cmd *cmd_enc;
> > -	struct dpu_hw_ctl *ctl;
> > -	u32 event = 0;
> > -	s64 time_diff_us;
> > 
> >  	if (!phys_enc || !phys_enc->hw_ctl)
> >  		return;
> > @@ -272,43 +241,8 @@ static void dpu_encoder_phys_cmd_ctl_start_irq(void
> > *arg, int irq_idx)
> >  	DPU_ATRACE_BEGIN("ctl_start_irq");
> >  	cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
> > 
> > -	ctl = phys_enc->hw_ctl;
> >  	atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
> > 
> > -	time_diff_us = ktime_us_delta(ktime_get(),
> > cmd_enc->rd_ptr_timestamp);
> > -
> > -	/* handle retire fence based on only master */
> > -	if (dpu_encoder_phys_cmd_is_master(phys_enc)
> > -			&&
> > atomic_read(&phys_enc->pending_retire_fence_cnt)) {
> > -		/**
> > -		 * Handle rare cases where the ctl_start_irq is received
> > -		 * after rd_ptr_irq. If it falls within a threshold, it is
> > -		 * guaranteed the frame would be picked up in the current
> > TE.
> > -		 * Signal retire fence immediately in such case.
> > -		 */
> > -		if ((time_diff_us <= DPU_ENC_CTL_START_THRESHOLD_US)
> > -			    && atomic_add_unless(
> > -				&phys_enc->pending_retire_fence_cnt, -1,
> > 0)) {
> > -
> > -			event =
> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
> > -
> > -			if (phys_enc->parent_ops.handle_frame_done)
> > -				phys_enc->parent_ops.handle_frame_done(
> > -					phys_enc->parent, phys_enc,
> > event);
> > -
> > -		/**
> > -		 * In ideal cases, ctl_start_irq is received before the
> > -		 * rd_ptr_irq, so set the atomic flag to indicate the
> > event
> > -		 * and rd_ptr_irq will handle signalling the retire fence
> > -		 */
> > -		} else {
> > -			atomic_inc(&cmd_enc->pending_rd_ptr_cnt);
> > -		}
> > -	}
> > -
> > -	DPU_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0,
> > -				time_diff_us, event, 0xfff);
> > -
> >  	/* Signal any waiting ctl start interrupt */
> >  	wake_up_all(&phys_enc->pending_kickoff_wq);
> >  	DPU_ATRACE_END("ctl_start_irq");
> > @@ -409,8 +343,7 @@ static int
> > _dpu_encoder_phys_cmd_handle_ppdone_timeout(
> >  {
> >  	struct dpu_encoder_phys_cmd *cmd_enc =
> >  			to_dpu_encoder_phys_cmd(phys_enc);
> > -	u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR
> > -				|
> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
> > +	u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR;
> >  	bool do_log = false;
> > 
> >  	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_ctl)
> > @@ -1346,8 +1279,6 @@ struct dpu_encoder_phys
> > *dpu_encoder_phys_cmd_init(
> >  	atomic_set(&phys_enc->vblank_refcount, 0);
> >  	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
> >  	atomic_set(&phys_enc->pending_ctlstart_cnt, 0);
> > -	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
> > -	atomic_set(&cmd_enc->pending_rd_ptr_cnt, 0);
> >  	atomic_set(&cmd_enc->pending_vblank_cnt, 0);
> >  	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
> >  	init_waitqueue_head(&cmd_enc->pending_vblank_wq);
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> > index 62c6f5c3547a..edaad0413987 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> > @@ -373,13 +373,10 @@ static void
> > dpu_encoder_phys_vid_setup_timing_engine(
> >  static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
> >  {
> >  	struct dpu_encoder_phys *phys_enc = arg;
> > -	struct dpu_encoder_phys_vid *vid_enc =
> > -			to_dpu_encoder_phys_vid(phys_enc);
> >  	struct dpu_hw_ctl *hw_ctl;
> >  	unsigned long lock_flags;
> >  	u32 flush_register = 0;
> >  	int new_cnt = -1, old_cnt = -1;
> > -	u32 event = 0;
> > 
> >  	if (!phys_enc)
> >  		return;
> > @@ -390,18 +387,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void
> > *arg, int irq_idx)
> > 
> >  	DPU_ATRACE_BEGIN("vblank_irq");
> > 
> > -	/* signal only for master, where there is a pending kickoff */
> > -	if (dpu_encoder_phys_vid_is_master(phys_enc)
> > -			&& atomic_add_unless(
> > -				&phys_enc->pending_retire_fence_cnt, -1,
> > 0)) {
> > -		event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
> > -				|
> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
> > -
> > -		if (phys_enc->parent_ops.handle_frame_done)
> > -
> > phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
> > -				phys_enc, event);
> > -	}
> > -
> >  	if (phys_enc->parent_ops.handle_vblank_virt)
> >  		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
> >  				phys_enc);
> > @@ -422,9 +407,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void
> > *arg,
> > int irq_idx)
> >  				-1, 0);
> >  	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
> > 
> > -	DPU_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx -
> > INTF_0,
> > -			old_cnt, new_cnt, flush_register, event);
> > -
> >  	/* Signal any waiting atomic commit thread */
> >  	wake_up_all(&phys_enc->pending_kickoff_wq);
> >  	DPU_ATRACE_END("vblank_irq");
> > @@ -1028,7 +1010,6 @@ struct dpu_encoder_phys
> > *dpu_encoder_phys_vid_init(
> > 
> >  	atomic_set(&phys_enc->vblank_refcount, 0);
> >  	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
> > -	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
> >  	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
> >  	phys_enc->enable_state = DPU_ENC_DISABLED;
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> > index 9a6fa3e1e8b4..2bc5894839c4 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> > @@ -680,11 +680,8 @@ static void dpu_encoder_phys_wb_done_irq(void *arg,
> > int irq_idx)
> >  	if (phys_enc->enable_state == DPU_ENC_DISABLING)
> >  		goto complete;
> > 
> > -	event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
> > -			| DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE
> > -			| DPU_ENCODER_FRAME_EVENT_DONE;
> > +	event = DPU_ENCODER_FRAME_EVENT_DONE;
> > 
> > -	atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0);
> >  	if (phys_enc->parent_ops.handle_frame_done)
> >  		phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
> >  				phys_enc, event);
> > @@ -847,12 +844,8 @@ static int
> > dpu_encoder_phys_wb_wait_for_commit_done(
> >  		} else {
> >  			DPU_ERROR("wb:%d kickoff timed out\n",
> >  					wb_enc->wb_dev->wb_idx - WB_0);
> > -			atomic_add_unless(
> > -				&phys_enc->pending_retire_fence_cnt, -1,
> > 0);
> > 
> > -			event =
> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
> > -				|
> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE
> > -				| DPU_ENCODER_FRAME_EVENT_ERROR;
> > +			event = DPU_ENCODER_FRAME_EVENT_ERROR;
> >  			if (phys_enc->parent_ops.handle_frame_done)
> >  				phys_enc->parent_ops.handle_frame_done(
> >  					phys_enc->parent, phys_enc,
> > event);
> > @@ -1333,7 +1326,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_wb_init(
> >  	phys_enc->intf_mode = INTF_MODE_WB_LINE;
> >  	phys_enc->intf_idx = p->intf_idx;
> >  	phys_enc->enc_spinlock = p->enc_spinlock;
> > -	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
> >  	INIT_LIST_HEAD(&wb_enc->irq_cb.list);
> > 
> >  	/* create internal buffer for disable logic */
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > index 3d83037e8305..9d68030378a7 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > @@ -545,35 +545,6 @@ static void dpu_kms_wait_for_commit_done(struct
> > msm_kms *kms,
> >  	}
> >  }
> > 
> > -static void dpu_kms_prepare_fence(struct msm_kms *kms,
> > -		struct drm_atomic_state *old_state)
> > -{
> > -	struct drm_crtc *crtc;
> > -	struct drm_crtc_state *old_crtc_state;
> > -	int i, rc;
> > -
> > -	if (!kms || !old_state || !old_state->dev ||
> > !old_state->acquire_ctx) {
> > -		DPU_ERROR("invalid argument(s)\n");
> > -		return;
> > -	}
> > -
> > -retry:
> > -	/* attempt to acquire ww mutex for connection */
> > -	rc =
> > drm_modeset_lock(&old_state->dev->mode_config.connection_mutex,
> > -			       old_state->acquire_ctx);
> > -
> > -	if (rc == -EDEADLK) {
> > -		drm_modeset_backoff(old_state->acquire_ctx);
> > -		goto retry;
> > -	}
> > -
> > -	/* old_state actually contains updated crtc pointers */
> > -	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
> > -		if (crtc->state->active)
> > -			dpu_crtc_prepare_commit(crtc, old_crtc_state);
> > -	}
> > -}
> > -
> >  /**
> >   * _dpu_kms_get_displays - query for underlying display handles and
> > cache
> > them
> >   * @dpu_kms:    Pointer to dpu kms structure
> > @@ -1734,7 +1705,6 @@ static const struct msm_kms_funcs kms_funcs = {
> >  	.irq_uninstall   = dpu_irq_uninstall,
> >  	.irq             = dpu_irq,
> >  	.preclose        = dpu_kms_preclose,
> > -	.prepare_fence   = dpu_kms_prepare_fence,
> >  	.prepare_commit  = dpu_kms_prepare_commit,
> >  	.commit          = dpu_kms_commit,
> >  	.complete_commit = dpu_kms_complete_commit,
> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
> > b/drivers/gpu/drm/msm/msm_drv.h
> > index 8cab333df717..e92376acbcfe 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > @@ -132,8 +132,6 @@ enum msm_mdp_crtc_property {
> > 
> >  	/* range properties */
> >  	CRTC_PROP_INPUT_FENCE_TIMEOUT = CRTC_PROP_BLOBCOUNT,
> > -	CRTC_PROP_OUTPUT_FENCE,
> > -	CRTC_PROP_OUTPUT_FENCE_OFFSET,
> >  	CRTC_PROP_DIM_LAYER_V1,
> >  	CRTC_PROP_CORE_CLK,
> >  	CRTC_PROP_CORE_AB,
> > @@ -163,7 +161,6 @@ enum msm_mdp_conn_property {
> > 
> >  	/* range properties */
> >  	CONNECTOR_PROP_OUT_FB = CONNECTOR_PROP_BLOBCOUNT,
> > -	CONNECTOR_PROP_RETIRE_FENCE,
> >  	CONNECTOR_PROP_DST_X,
> >  	CONNECTOR_PROP_DST_Y,
> >  	CONNECTOR_PROP_DST_W,
> 
> -- 
> Jeykumar S

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 10/11] drm/msm: Switch to atomic_helper_commit()
       [not found]         ` <bf44a79fc08d00245640694c364b8b03-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-03-12 20:32           ` Sean Paul
  2018-03-13  2:08             ` abhinavk-sgV2jX0FEOL9JmXXK+q4OQ
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-12 20:32 UTC (permalink / raw)
  To: abhinavk-sgV2jX0FEOL9JmXXK+q4OQ
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-owner-u79uwXL29TY76Z2rM5mHXA,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, Sean Paul,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	jsanka-sgV2jX0FEOL9JmXXK+q4OQ

On Thu, Mar 08, 2018 at 07:28:08PM -0800, abhinavk@codeaurora.org wrote:
> On 2018-02-28 11:19, Sean Paul wrote:
> > Now that all of the msm-specific goo is tucked safely away we can switch
> > over to using the atomic helper commit directly. \o/
> > 
> [Abhinav] Can we say something like "Move remaining msm-specific operations
> to private handles and switch to atomic helper commit for the rest.

Well, to be pedantic, that's not what's happening in this change. This change
simply replaces the msm atomic ops with the generic helper ops, which are
now identical due to the preceding 9 patches.

Sean

> 
> > Change-Id: Ieab0bd0c526b2a9d3b3345eeba402ac4857fe418
> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > ---
> >  drivers/gpu/drm/msm/msm_atomic.c | 120 +------------------------------
> >  drivers/gpu/drm/msm/msm_drv.c    |   7 +-
> >  drivers/gpu/drm/msm/msm_drv.h    |   3 +-
> >  3 files changed, 8 insertions(+), 122 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> > b/drivers/gpu/drm/msm/msm_atomic.c
> > index 204c66cbfd31..91ffded576d8 100644
> > --- a/drivers/gpu/drm/msm/msm_atomic.c
> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> > @@ -18,8 +18,6 @@
> > 
> >  #include "msm_drv.h"
> >  #include "msm_kms.h"
> > -#include "msm_gem.h"
> > -#include "msm_fence.h"
> > 
> >  static void msm_atomic_wait_for_commit_done(
> >  		struct drm_device *dev,
> > @@ -39,7 +37,7 @@ static void msm_atomic_wait_for_commit_done(
> >  	}
> >  }
> > 
> > -static void msm_atomic_commit_tail(struct drm_atomic_state *state)
> > +void msm_atomic_commit_tail(struct drm_atomic_state *state)
> >  {
> >  	struct drm_device *dev = state->dev;
> >  	struct msm_drm_private *priv = dev->dev_private;
> > @@ -81,119 +79,3 @@ static void msm_atomic_commit_tail(struct
> > drm_atomic_state *state)
> > 
> >  	kms->funcs->complete_commit(kms, state);
> >  }
> > -
> > -/* The (potentially) asynchronous part of the commit.  At this point
> > - * nothing can fail short of armageddon.
> > - */
> > -static void commit_tail(struct drm_atomic_state *state)
> > -{
> > -	drm_atomic_helper_wait_for_fences(state->dev, state, false);
> > -
> > -	drm_atomic_helper_wait_for_dependencies(state);
> > -
> > -	msm_atomic_commit_tail(state);
> > -
> > -	drm_atomic_helper_commit_cleanup_done(state);
> > -
> > -	drm_atomic_state_put(state);
> > -}
> > -
> > -static void commit_work(struct work_struct *work)
> > -{
> > -	struct drm_atomic_state *state = container_of(work,
> > -						      struct drm_atomic_state,
> > -						      commit_work);
> > -	commit_tail(state);
> > -}
> > -
> > -/**
> > - * drm_atomic_helper_commit - commit validated state object
> > - * @dev: DRM device
> > - * @state: the driver state object
> > - * @nonblock: nonblocking commit
> > - *
> > - * This function commits a with drm_atomic_helper_check() pre-validated
> > state
> > - * object. This can still fail when e.g. the framebuffer reservation
> > fails.
> > - *
> > - * RETURNS
> > - * Zero for success or -errno.
> > - */
> > -int msm_atomic_commit(struct drm_device *dev,
> > -		struct drm_atomic_state *state, bool nonblock)
> > -{
> > -	struct msm_drm_private *priv = dev->dev_private;
> > -	struct drm_crtc *crtc;
> > -	struct drm_crtc_state *crtc_state;
> > -	struct drm_plane *plane;
> > -	struct drm_plane_state *old_plane_state, *new_plane_state;
> > -	int i, ret;
> > -
> > -	/*
> > -	 * Note that plane->atomic_async_check() should fail if we need
> > -	 * to re-assign hwpipe or anything that touches global atomic
> > -	 * state, so we'll never go down the async update path in those
> > -	 * cases.
> > -	 */
> > -	if (state->async_update) {
> > -		ret = drm_atomic_helper_prepare_planes(dev, state);
> > -		if (ret)
> > -			return ret;
> > -
> > -		drm_atomic_helper_async_commit(dev, state);
> > -		drm_atomic_helper_cleanup_planes(dev, state);
> > -		return 0;
> > -	}
> > -
> > -	ret = drm_atomic_helper_setup_commit(state, nonblock);
> > -	if (ret)
> > -		return ret;
> > -
> > -	INIT_WORK(&state->commit_work, commit_work);
> > -
> > -	ret = drm_atomic_helper_prepare_planes(dev, state);
> > -	if (ret)
> > -		return ret;
> > -
> > -	if (!nonblock) {
> > -		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> > -		if (ret)
> > -			goto error;
> > -	}
> > -
> > -	/*
> > -	 * This is the point of no return - everything below never fails
> > except
> > -	 * when the hw goes bonghits. Which means we can commit the new state
> > on
> > -	 * the software side now.
> > -	 *
> > -	 * swap driver private state while still holding state_lock
> > -	 */
> > -	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> > -
> > -	/*
> > -	 * Everything below can be run asynchronously without the need to grab
> > -	 * any modeset locks at all under one conditions: It must be
> > guaranteed
> > -	 * that the asynchronous work has either been cancelled (if the driver
> > -	 * supports it, which at least requires that the framebuffers get
> > -	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
> > -	 * before the new state gets committed on the software side with
> > -	 * drm_atomic_helper_swap_state().
> > -	 *
> > -	 * This scheme allows new atomic state updates to be prepared and
> > -	 * checked in parallel to the asynchronous completion of the previous
> > -	 * update. Which is important since compositors need to figure out the
> > -	 * composition of the next frame right after having submitted the
> > -	 * current layout.
> > -	 */
> > -
> > -	drm_atomic_state_get(state);
> > -	if (nonblock)
> > -		queue_work(system_unbound_wq, &state->commit_work);
> > -	else
> > -		commit_tail(state);
> > -
> > -	return 0;
> > -
> > -error:
> > -	drm_atomic_helper_cleanup_planes(dev, state);
> > -	return ret;
> > -}
> > diff --git a/drivers/gpu/drm/msm/msm_drv.c
> > b/drivers/gpu/drm/msm/msm_drv.c
> > index e582d5889b66..fd9a7d0825cd 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.c
> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > @@ -120,7 +120,11 @@ static const struct drm_mode_config_funcs
> > mode_config_funcs = {
> >  	.fb_create = msm_framebuffer_create,
> >  	.output_poll_changed = msm_fb_output_poll_changed,
> >  	.atomic_check = msm_atomic_check,
> > -	.atomic_commit = msm_atomic_commit,
> > +	.atomic_commit = drm_atomic_helper_commit,
> > +};
> > +
> > +static const struct drm_mode_config_helper_funcs
> > mode_config_helper_funcs = {
> > +	.atomic_commit_tail = msm_atomic_commit_tail,
> >  };
> > 
> >  static inline
> > @@ -694,6 +698,7 @@ static int msm_drm_init(struct device *dev, struct
> > drm_driver *drv)
> >  	 * an unset value during call to drm_drv_uses_atomic_modeset()
> >  	 */
> >  	ddev->mode_config.funcs = &mode_config_funcs;
> > +	ddev->mode_config.helper_private = &mode_config_helper_funcs;
> > 
> >  	if (kms) {
> >  		ret = kms->funcs->hw_init(kms);
> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
> > b/drivers/gpu/drm/msm/msm_drv.h
> > index e92376acbcfe..657ea052a1ee 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > @@ -593,8 +593,7 @@ struct msm_format {
> >  	uint32_t pixel_format;
> >  };
> > 
> > -int msm_atomic_commit(struct drm_device *dev,
> > -		struct drm_atomic_state *state, bool nonblock);
> > +void msm_atomic_commit_tail(struct drm_atomic_state *state);
> >  struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state
> > *state);
> > 
> >  void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 10/11] drm/msm: Switch to atomic_helper_commit()
  2018-03-12 20:32           ` Sean Paul
@ 2018-03-13  2:08             ` abhinavk-sgV2jX0FEOL9JmXXK+q4OQ
  0 siblings, 0 replies; 49+ messages in thread
From: abhinavk-sgV2jX0FEOL9JmXXK+q4OQ @ 2018-03-13  2:08 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-owner-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-03-12 13:32, Sean Paul wrote:
> On Thu, Mar 08, 2018 at 07:28:08PM -0800, abhinavk@codeaurora.org 
> wrote:
>> On 2018-02-28 11:19, Sean Paul wrote:
>> > Now that all of the msm-specific goo is tucked safely away we can switch
>> > over to using the atomic helper commit directly. \o/
>> >
>> [Abhinav] Can we say something like "Move remaining msm-specific 
>> operations
>> to private handles and switch to atomic helper commit for the rest.
> 
> Well, to be pedantic, that's not what's happening in this change. This 
> change
> simply replaces the msm atomic ops with the generic helper ops, which 
> are
> now identical due to the preceding 9 patches.
> 
> Sean
> 
[Abhinav] Ok, I commented "remaining" because of msm_atomic_commit_tail
So something like this would be better "Replace the msm atomic ops with 
the generic helper ones
and move any exceptions to private handles" ?
But this is just trivial comment. So approving this.


>> 
>> > Change-Id: Ieab0bd0c526b2a9d3b3345eeba402ac4857fe418
>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Abhinav Kumar <abhinavk@codeaurora.org>
>> > ---
>> >  drivers/gpu/drm/msm/msm_atomic.c | 120 +------------------------------
>> >  drivers/gpu/drm/msm/msm_drv.c    |   7 +-
>> >  drivers/gpu/drm/msm/msm_drv.h    |   3 +-
>> >  3 files changed, 8 insertions(+), 122 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
>> > b/drivers/gpu/drm/msm/msm_atomic.c
>> > index 204c66cbfd31..91ffded576d8 100644
>> > --- a/drivers/gpu/drm/msm/msm_atomic.c
>> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> > @@ -18,8 +18,6 @@
>> >
>> >  #include "msm_drv.h"
>> >  #include "msm_kms.h"
>> > -#include "msm_gem.h"
>> > -#include "msm_fence.h"
>> >
>> >  static void msm_atomic_wait_for_commit_done(
>> >  		struct drm_device *dev,
>> > @@ -39,7 +37,7 @@ static void msm_atomic_wait_for_commit_done(
>> >  	}
>> >  }
>> >
>> > -static void msm_atomic_commit_tail(struct drm_atomic_state *state)
>> > +void msm_atomic_commit_tail(struct drm_atomic_state *state)
>> >  {
>> >  	struct drm_device *dev = state->dev;
>> >  	struct msm_drm_private *priv = dev->dev_private;
>> > @@ -81,119 +79,3 @@ static void msm_atomic_commit_tail(struct
>> > drm_atomic_state *state)
>> >
>> >  	kms->funcs->complete_commit(kms, state);
>> >  }
>> > -
>> > -/* The (potentially) asynchronous part of the commit.  At this point
>> > - * nothing can fail short of armageddon.
>> > - */
>> > -static void commit_tail(struct drm_atomic_state *state)
>> > -{
>> > -	drm_atomic_helper_wait_for_fences(state->dev, state, false);
>> > -
>> > -	drm_atomic_helper_wait_for_dependencies(state);
>> > -
>> > -	msm_atomic_commit_tail(state);
>> > -
>> > -	drm_atomic_helper_commit_cleanup_done(state);
>> > -
>> > -	drm_atomic_state_put(state);
>> > -}
>> > -
>> > -static void commit_work(struct work_struct *work)
>> > -{
>> > -	struct drm_atomic_state *state = container_of(work,
>> > -						      struct drm_atomic_state,
>> > -						      commit_work);
>> > -	commit_tail(state);
>> > -}
>> > -
>> > -/**
>> > - * drm_atomic_helper_commit - commit validated state object
>> > - * @dev: DRM device
>> > - * @state: the driver state object
>> > - * @nonblock: nonblocking commit
>> > - *
>> > - * This function commits a with drm_atomic_helper_check() pre-validated
>> > state
>> > - * object. This can still fail when e.g. the framebuffer reservation
>> > fails.
>> > - *
>> > - * RETURNS
>> > - * Zero for success or -errno.
>> > - */
>> > -int msm_atomic_commit(struct drm_device *dev,
>> > -		struct drm_atomic_state *state, bool nonblock)
>> > -{
>> > -	struct msm_drm_private *priv = dev->dev_private;
>> > -	struct drm_crtc *crtc;
>> > -	struct drm_crtc_state *crtc_state;
>> > -	struct drm_plane *plane;
>> > -	struct drm_plane_state *old_plane_state, *new_plane_state;
>> > -	int i, ret;
>> > -
>> > -	/*
>> > -	 * Note that plane->atomic_async_check() should fail if we need
>> > -	 * to re-assign hwpipe or anything that touches global atomic
>> > -	 * state, so we'll never go down the async update path in those
>> > -	 * cases.
>> > -	 */
>> > -	if (state->async_update) {
>> > -		ret = drm_atomic_helper_prepare_planes(dev, state);
>> > -		if (ret)
>> > -			return ret;
>> > -
>> > -		drm_atomic_helper_async_commit(dev, state);
>> > -		drm_atomic_helper_cleanup_planes(dev, state);
>> > -		return 0;
>> > -	}
>> > -
>> > -	ret = drm_atomic_helper_setup_commit(state, nonblock);
>> > -	if (ret)
>> > -		return ret;
>> > -
>> > -	INIT_WORK(&state->commit_work, commit_work);
>> > -
>> > -	ret = drm_atomic_helper_prepare_planes(dev, state);
>> > -	if (ret)
>> > -		return ret;
>> > -
>> > -	if (!nonblock) {
>> > -		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>> > -		if (ret)
>> > -			goto error;
>> > -	}
>> > -
>> > -	/*
>> > -	 * This is the point of no return - everything below never fails
>> > except
>> > -	 * when the hw goes bonghits. Which means we can commit the new state
>> > on
>> > -	 * the software side now.
>> > -	 *
>> > -	 * swap driver private state while still holding state_lock
>> > -	 */
>> > -	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
>> > -
>> > -	/*
>> > -	 * Everything below can be run asynchronously without the need to grab
>> > -	 * any modeset locks at all under one conditions: It must be
>> > guaranteed
>> > -	 * that the asynchronous work has either been cancelled (if the driver
>> > -	 * supports it, which at least requires that the framebuffers get
>> > -	 * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
>> > -	 * before the new state gets committed on the software side with
>> > -	 * drm_atomic_helper_swap_state().
>> > -	 *
>> > -	 * This scheme allows new atomic state updates to be prepared and
>> > -	 * checked in parallel to the asynchronous completion of the previous
>> > -	 * update. Which is important since compositors need to figure out the
>> > -	 * composition of the next frame right after having submitted the
>> > -	 * current layout.
>> > -	 */
>> > -
>> > -	drm_atomic_state_get(state);
>> > -	if (nonblock)
>> > -		queue_work(system_unbound_wq, &state->commit_work);
>> > -	else
>> > -		commit_tail(state);
>> > -
>> > -	return 0;
>> > -
>> > -error:
>> > -	drm_atomic_helper_cleanup_planes(dev, state);
>> > -	return ret;
>> > -}
>> > diff --git a/drivers/gpu/drm/msm/msm_drv.c
>> > b/drivers/gpu/drm/msm/msm_drv.c
>> > index e582d5889b66..fd9a7d0825cd 100644
>> > --- a/drivers/gpu/drm/msm/msm_drv.c
>> > +++ b/drivers/gpu/drm/msm/msm_drv.c
>> > @@ -120,7 +120,11 @@ static const struct drm_mode_config_funcs
>> > mode_config_funcs = {
>> >  	.fb_create = msm_framebuffer_create,
>> >  	.output_poll_changed = msm_fb_output_poll_changed,
>> >  	.atomic_check = msm_atomic_check,
>> > -	.atomic_commit = msm_atomic_commit,
>> > +	.atomic_commit = drm_atomic_helper_commit,
>> > +};
>> > +
>> > +static const struct drm_mode_config_helper_funcs
>> > mode_config_helper_funcs = {
>> > +	.atomic_commit_tail = msm_atomic_commit_tail,
>> >  };
>> >
>> >  static inline
>> > @@ -694,6 +698,7 @@ static int msm_drm_init(struct device *dev, struct
>> > drm_driver *drv)
>> >  	 * an unset value during call to drm_drv_uses_atomic_modeset()
>> >  	 */
>> >  	ddev->mode_config.funcs = &mode_config_funcs;
>> > +	ddev->mode_config.helper_private = &mode_config_helper_funcs;
>> >
>> >  	if (kms) {
>> >  		ret = kms->funcs->hw_init(kms);
>> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
>> > b/drivers/gpu/drm/msm/msm_drv.h
>> > index e92376acbcfe..657ea052a1ee 100644
>> > --- a/drivers/gpu/drm/msm/msm_drv.h
>> > +++ b/drivers/gpu/drm/msm/msm_drv.h
>> > @@ -593,8 +593,7 @@ struct msm_format {
>> >  	uint32_t pixel_format;
>> >  };
>> >
>> > -int msm_atomic_commit(struct drm_device *dev,
>> > -		struct drm_atomic_state *state, bool nonblock);
>> > +void msm_atomic_commit_tail(struct drm_atomic_state *state);
>> >  struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state
>> > *state);
>> >
>> >  void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 01/11] drm/msm: Skip seamless disables in crtc/encoder
  2018-03-12 20:14         ` Sean Paul
@ 2018-03-13 18:10           ` Jeykumar Sankaran
  0 siblings, 0 replies; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-13 18:10 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-03-12 13:14, Sean Paul wrote:
> On Fri, Mar 02, 2018 at 04:04:24PM -0800, jsanka@codeaurora.org wrote:
>> On 2018-02-28 11:18, Sean Paul wrote:
>> > Instead of duplicating whole swaths of atomic helper functions (which
>> > are already out-of-date), just skip the encoder/crtc disables in the
>> > .disable hooks.
>> >
>> > Change-Id: I7bd9183ae60624204fb1de9550656b776efc7202
>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>

Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>

>> 
>> Can you consider getting rid of these checks?
> 
> Do you mean the Change-Id? Yeah, I forgot to strip them out before
> sending, I'll
> make sure I clean it up before I apply.
> 
Actually, I meant removing the seamless check flags that you are moving 
to
encode/crtc. But you can ignore that, I am planning to submit a seperate
change to remove the support from the whole pipeline.
>> 
>> > ---
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   8 +
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   8 +
>> >  drivers/gpu/drm/msm/msm_atomic.c            | 185
> +-------------------
>> >  3 files changed, 17 insertions(+), 184 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > index 3cdf1e3d9d96..a3ab6ed2bf1d 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > @@ -3393,6 +3393,7 @@ static void dpu_crtc_disable(struct drm_crtc
>> > *crtc)
>> >  {
>> >  	struct dpu_crtc *dpu_crtc;
>> >  	struct dpu_crtc_state *cstate;
>> > +	struct drm_display_mode *mode;
>> >  	struct drm_encoder *encoder;
>> >  	struct msm_drm_private *priv;
>> >  	unsigned long flags;
>> > @@ -3407,8 +3408,15 @@ static void dpu_crtc_disable(struct drm_crtc
>> > *crtc)
>> >  	}
>> >  	dpu_crtc = to_dpu_crtc(crtc);
>> >  	cstate = to_dpu_crtc_state(crtc->state);
>> > +	mode = &cstate->base.adjusted_mode;
>> >  	priv = crtc->dev->dev_private;
>> >
>> > +	if (msm_is_mode_seamless(mode) || msm_is_mode_seamless_vrr(mode)
>> > ||
>> > +	    msm_is_mode_seamless_dms(mode)) {
>> > +		DPU_DEBUG("Seamless mode is being applied, skip
>> > disable\n");
>> > +		return;
>> > +	}
>> > +
>> Another topic of discussion which should be brought up with dri-devel.
>> 
>> May not be common in PC world, but there are a handful of mobile OEM's
>> using panels which supports more than one resolution. Primary use 
>> cases
>> involve "seamless" switching to optimized display resolution when
>> streaming content changes resolutions or rendering lossless data.
> 
> Yeah, I think we can do this under the covers if the hardware supports 
> it
> such
> as this patch. We could probably do a better job of making this useful 
> for
> other
> drivers, but I was really just trying to get the seamless stuff out of 
> the
> way
> so we don't need to roll our own atomic commit.
> 
> Sean
> 
>> 
>> Jeykumar S.
>> 
>> >  	DPU_DEBUG("crtc%d\n", crtc->base.id);
>> >
>> >  	if (dpu_kms_is_suspend_state(crtc->dev))
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > index 3d168fa09f3f..28ceb589ee40 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > @@ -2183,6 +2183,7 @@ static void dpu_encoder_virt_disable(struct
>> > drm_encoder *drm_enc)
>> >  	struct dpu_encoder_virt *dpu_enc = NULL;
>> >  	struct msm_drm_private *priv;
>> >  	struct dpu_kms *dpu_kms;
>> > +	struct drm_display_mode *mode;
>> >  	int i = 0;
>> >
>> >  	if (!drm_enc) {
>> > @@ -2196,6 +2197,13 @@ static void dpu_encoder_virt_disable(struct
>> > drm_encoder *drm_enc)
>> >  		return;
>> >  	}
>> >
>> > +	mode = &drm_enc->crtc->state->adjusted_mode;
>> > +	if (msm_is_mode_seamless(mode) || msm_is_mode_seamless_vrr(mode)
>> > ||
>> > +	    msm_is_mode_seamless_dms(mode)) {
>> > +		DPU_DEBUG("Seamless mode is being applied, skip
>> > disable\n");
>> > +		return;
>> > +	}
>> > +
>> >  	dpu_enc = to_dpu_encoder_virt(drm_enc);
>> >  	DPU_DEBUG_ENC(dpu_enc, "\n");
>> >
>> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
>> > b/drivers/gpu/drm/msm/msm_atomic.c
>> > index 46536edb72ee..5cfb80345052 100644
>> > --- a/drivers/gpu/drm/msm/msm_atomic.c
>> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> > @@ -84,189 +84,6 @@ static void msm_atomic_wait_for_commit_done(
>> >  	}
>> >  }
>> >
>> > -static void
>> > -msm_disable_outputs(struct drm_device *dev, struct drm_atomic_state
>> > *old_state)
>> > -{
>> > -	struct drm_connector *connector;
>> > -	struct drm_connector_state *old_conn_state, *new_conn_state;
>> > -	struct drm_crtc *crtc;
>> > -	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>> > -	int i;
>> > -
>> > -	for_each_oldnew_connector_in_state(old_state, connector,
>> > old_conn_state, new_conn_state, i) {
>> > -		const struct drm_encoder_helper_funcs *funcs;
>> > -		struct drm_encoder *encoder;
>> > -		struct drm_crtc_state *old_crtc_state;
>> > -		unsigned int crtc_idx;
>> > -
>> > -		/*
>> > -		 * Shut down everything that's in the changeset and
>> > currently
>> > -		 * still on. So need to check the old, saved state.
>> > -		 */
>> > -		if (!old_conn_state->crtc)
>> > -			continue;
>> > -
>> > -		crtc_idx = drm_crtc_index(old_conn_state->crtc);
>> > -		old_crtc_state = drm_atomic_get_old_crtc_state(old_state,
>> > -
>> > old_conn_state->crtc);
>> > -
>> > -		if (!old_crtc_state->active ||
>> > -
>> > !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state))
>> > -			continue;
>> > -
>> > -		encoder = old_conn_state->best_encoder;
>> > -
>> > -		/* We shouldn't get this far if we didn't previously have
>> > -		 * an encoder.. but WARN_ON() rather than explode.
>> > -		 */
>> > -		if (WARN_ON(!encoder))
>> > -			continue;
>> > -
>> > -		if (msm_is_mode_seamless(
>> > -			&connector->encoder->crtc->state->mode) ||
>> > -			msm_is_mode_seamless_vrr(
>> > -			&connector->encoder->crtc->state->adjusted_mode))
>> > -			continue;
>> > -
>> > -		if (msm_is_mode_seamless_dms(
>> > -			&connector->encoder->crtc->state->adjusted_mode))
>> > -			continue;
>> > -
>> > -		funcs = encoder->helper_private;
>> > -
>> > -		DRM_DEBUG_ATOMIC("disabling [ENCODER:%d:%s]\n",
>> > -				 encoder->base.id, encoder->name);
>> > -
>> > -		/*
>> > -		 * Each encoder has at most one connector (since we always
>> > steal
>> > -		 * it away), so we won't call disable hooks twice.
>> > -		 */
>> > -		drm_bridge_disable(encoder->bridge);
>> > -
>> > -		/* Right function depends upon target state. */
>> > -		if (new_conn_state->crtc && funcs->prepare)
>> > -			funcs->prepare(encoder);
>> > -		else if (funcs->disable)
>> > -			funcs->disable(encoder);
>> > -		else
>> > -			funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
>> > -
>> > -		drm_bridge_post_disable(encoder->bridge);
>> > -	}
>> > -
>> > -	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
>> > new_crtc_state, i) {
>> > -		const struct drm_crtc_helper_funcs *funcs;
>> > -
>> > -		/* Shut down everything that needs a full modeset. */
>> > -		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
>> > -			continue;
>> > -
>> > -		if (!old_crtc_state->active)
>> > -			continue;
>> > -
>> > -		if (msm_is_mode_seamless(&crtc->state->mode) ||
>> > -
>> > msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode))
>> > -			continue;
>> > -
>> > -		if (msm_is_mode_seamless_dms(&crtc->state->adjusted_mode))
>> > -			continue;
>> > -
>> > -		funcs = crtc->helper_private;
>> > -
>> > -		DRM_DEBUG_ATOMIC("disabling [CRTC:%d]\n",
>> > -				 crtc->base.id);
>> > -
>> > -		/* Right function depends upon target state. */
>> > -		if (new_crtc_state->enable && funcs->prepare)
>> > -			funcs->prepare(crtc);
>> > -		else if (funcs->disable)
>> > -			funcs->disable(crtc);
>> > -		else
>> > -			funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
>> > -	}
>> > -}
>> > -
>> > -static void
>> > -msm_crtc_set_mode(struct drm_device *dev, struct drm_atomic_state
>> > *old_state)
>> > -{
>> > -	struct drm_crtc *crtc;
>> > -	struct drm_crtc_state *new_crtc_state;
>> > -	struct drm_connector *connector;
>> > -	struct drm_connector_state *new_conn_state;
>> > -	int i;
>> > -
>> > -	for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
>> > -		const struct drm_crtc_helper_funcs *funcs;
>> > -
>> > -		if (!new_crtc_state->mode_changed)
>> > -			continue;
>> > -
>> > -		funcs = crtc->helper_private;
>> > -
>> > -		if (new_crtc_state->enable && funcs->mode_set_nofb) {
>> > -			DRM_DEBUG_ATOMIC("modeset on [CRTC:%d]\n",
>> > -					 crtc->base.id);
>> > -
>> > -			funcs->mode_set_nofb(crtc);
>> > -		}
>> > -	}
>> > -
>> > -	for_each_new_connector_in_state(old_state, connector,
>> > new_conn_state, i) {
>> > -		const struct drm_encoder_helper_funcs *funcs;
>> > -		struct drm_crtc_state *new_crtc_state;
>> > -		struct drm_encoder *encoder;
>> > -		struct drm_display_mode *mode, *adjusted_mode;
>> > -
>> > -		if (!new_conn_state->best_encoder)
>> > -			continue;
>> > -
>> > -		encoder = new_conn_state->best_encoder;
>> > -		funcs = encoder->helper_private;
>> > -		new_crtc_state = new_conn_state->crtc->state;
>> > -		mode = &new_crtc_state->mode;
>> > -		adjusted_mode = &new_crtc_state->adjusted_mode;
>> > -
>> > -		if (!new_crtc_state->mode_changed)
>> > -			continue;
>> > -
>> > -		DRM_DEBUG_ATOMIC("modeset on [ENCODER:%d:%s]\n",
>> > -				 encoder->base.id, encoder->name);
>> > -
>> > -		/*
>> > -		 * Each encoder has at most one connector (since we always
>> > steal
>> > -		 * it away), so we won't call mode_set hooks twice.
>> > -		 */
>> > -		if (funcs->mode_set)
>> > -			funcs->mode_set(encoder, mode, adjusted_mode);
>> > -
>> > -		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
>> > -	}
>> > -}
>> > -
>> > -/**
>> > - * msm_atomic_helper_commit_modeset_disables - modeset commit to
>> > disable
>> > outputs
>> > - * @dev: DRM device
>> > - * @old_state: atomic state object with old state structures
>> > - *
>> > - * This function shuts down all the outputs that need to be shut down
>> > and
>> > - * prepares them (if required) with the new mode.
>> > - *
>> > - * For compatibility with legacy crtc helpers this should be called
>> > before
>> > - * drm_atomic_helper_commit_planes(), which is what the default
> commit
>> > function
>> > - * does. But drivers with different needs can group the modeset
> commits
>> > together
>> > - * and do the plane commits at the end. This is useful for drivers
>> > doing
>> > runtime
>> > - * PM since planes updates then only happen when the CRTC is actually
>> > enabled.
>> > - */
>> > -void msm_atomic_helper_commit_modeset_disables(struct drm_device
> *dev,
>> > -		struct drm_atomic_state *old_state)
>> > -{
>> > -	msm_disable_outputs(dev, old_state);
>> > -
>> > -	drm_atomic_helper_update_legacy_modeset_state(dev, old_state);
>> > -
>> > -	msm_crtc_set_mode(dev, old_state);
>> > -}
>> > -
>> >  /**
>> >   * msm_atomic_helper_commit_modeset_enables - modeset commit to
> enable
>> > outputs
>> >   * @dev: DRM device
>> > @@ -406,7 +223,7 @@ static void complete_commit(struct msm_commit *c)
>> >
>> >  	kms->funcs->prepare_commit(kms, state);
>> >
>> > -	msm_atomic_helper_commit_modeset_disables(dev, state);
>> > +	drm_atomic_helper_commit_modeset_disables(dev, state);
>> >
>> >  	drm_atomic_helper_commit_planes(dev, state, 0);

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 08/11] drm/msm: Remove hand-rolled out fences
  2018-03-12 20:30           ` Sean Paul
@ 2018-03-13 18:11             ` Jeykumar Sankaran
  0 siblings, 0 replies; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-13 18:11 UTC (permalink / raw)
  To: Sean Paul; +Cc: linux-arm-msm, abhinavk, dri-devel, hoegsberg, freedreno

On 2018-03-12 13:30, Sean Paul wrote:
> On Fri, Mar 02, 2018 at 04:44:55PM -0800, Jeykumar Sankaran wrote:
>> On 2018-02-28 11:19, Sean Paul wrote:
>> > Remove release/output/retire fences from the dpu driver. These are
>> > already available via drm core's OUT_FENCE property.
>> >
>> > Change-Id: Id4238d0b5457f2c8ee2e87bb7814e1850a573623
>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>

Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>

>> > ---
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c |  66 +------
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h |  23 ---
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      | 178
> +++---------------
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h      |  28 ---
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |   3 -
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   4 +-
>> >  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   8 -
>> >  .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |  73 +------
>> >  .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |  19 --
>> >  .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   |  12 +-
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c       |  30 ---
>> >  drivers/gpu/drm/msm/msm_drv.h                 |   3 -
>> >  12 files changed, 36 insertions(+), 411 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
>> > index 57b8627ef418..cc5bfa862cb7 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.c
>> > @@ -521,7 +521,6 @@ static void dpu_connector_destroy(struct
>> > drm_connector
>> > *connector)
>> >  		backlight_device_unregister(c_conn->bl_device);
>> >  	drm_connector_unregister(connector);
>> >  	mutex_destroy(&c_conn->lock);
>> > -	dpu_fence_deinit(&c_conn->retire_fence);
>> >  	drm_connector_cleanup(connector);
>> >  	kfree(c_conn);
>> >  }
>> > @@ -906,12 +905,9 @@ static int
> dpu_connector_atomic_get_property(struct
>> > drm_connector *connector,
>> >  	c_state = to_dpu_connector_state(state);
>> >
>> >  	idx = msm_property_index(&c_conn->property_info, property);
>> > -	if (idx == CONNECTOR_PROP_RETIRE_FENCE)
>> > -		rc = dpu_fence_create(&c_conn->retire_fence, val, 0);
>> > -	else
>> > -		/* get cached property value */
>> > -		rc = msm_property_atomic_get(&c_conn->property_info,
>> > -				&c_state->property_state, property, val);
>> > +	/* get cached property value */
>> > +	rc = msm_property_atomic_get(&c_conn->property_info,
>> > +			&c_state->property_state, property, val);
>> >
>> >  	/* allow for custom override */
>> >  	if (c_conn->ops.get_property)
>> > @@ -923,39 +919,6 @@ static int
> dpu_connector_atomic_get_property(struct
>> > drm_connector *connector,
>> >  	return rc;
>> >  }
>> >
>> > -void dpu_connector_prepare_fence(struct drm_connector *connector)
>> > -{
>> > -	if (!connector) {
>> > -		DPU_ERROR("invalid connector\n");
>> > -		return;
>> > -	}
>> > -
>> > -	dpu_fence_prepare(&to_dpu_connector(connector)->retire_fence);
>> > -}
>> > -
>> > -void dpu_connector_complete_commit(struct drm_connector *connector,
>> > -		ktime_t ts)
>> > -{
>> > -	if (!connector) {
>> > -		DPU_ERROR("invalid connector\n");
>> > -		return;
>> > -	}
>> > -
>> > -	/* signal connector's retire fence */
>> > -	dpu_fence_signal(&to_dpu_connector(connector)->retire_fence, ts,
>> > false);
>> > -}
>> > -
>> > -void dpu_connector_commit_reset(struct drm_connector *connector,
>> > ktime_t
>> > ts)
>> > -{
>> > -	if (!connector) {
>> > -		DPU_ERROR("invalid connector\n");
>> > -		return;
>> > -	}
>> > -
>> > -	/* signal connector's retire fence */
>> > -	dpu_fence_signal(&to_dpu_connector(connector)->retire_fence, ts,
>> > true);
>> > -}
>> > -
>> >  static enum drm_connector_status
>> >  dpu_connector_detect(struct drm_connector *connector, bool force)
>> >  {
>> > @@ -1214,26 +1177,19 @@ struct drm_connector
> *dpu_connector_init(struct
>> > drm_device *dev,
>> >  			"conn%u",
>> >  			c_conn->base.base.id);
>> >
>> > -	rc = dpu_fence_init(&c_conn->retire_fence, c_conn->name,
>> > -			c_conn->base.base.id);
>> > -	if (rc) {
>> > -		DPU_ERROR("failed to init fence, %d\n", rc);
>> > -		goto error_cleanup_conn;
>> > -	}
>> > -
>> >  	mutex_init(&c_conn->lock);
>> >
>> >  	rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder);
>> >  	if (rc) {
>> >  		DPU_ERROR("failed to attach encoder to connector, %d\n",
>> > rc);
>> > -		goto error_cleanup_fence;
>> > +		goto error_cleanup_conn;
>> >  	}
>> >
>> >  #ifdef CONFIG_DRM_MSM_DSI_STAGING
>> >  	rc = dpu_backlight_setup(c_conn, dev);
>> >  	if (rc) {
>> >  		DPU_ERROR("failed to setup backlight, rc=%d\n", rc);
>> > -		goto error_cleanup_fence;
>> > +		goto error_cleanup_conn;
>> >  	}
>> >  #endif
>> >
>> > @@ -1248,7 +1204,7 @@ struct drm_connector *dpu_connector_init(struct
>> > drm_device *dev,
>> >  		if (!info) {
>> >  			DPU_ERROR("failed to allocate info buffer\n");
>> >  			rc = -ENOMEM;
>> > -			goto error_cleanup_fence;
>> > +			goto error_cleanup_conn;
>> >  		}
>> >
>> >  		dpu_kms_info_reset(info);
>> > @@ -1256,7 +1212,7 @@ struct drm_connector *dpu_connector_init(struct
>> > drm_device *dev,
>> >  		if (rc) {
>> >  			DPU_ERROR("post-init failed, %d\n", rc);
>> >  			kfree(info);
>> > -			goto error_cleanup_fence;
>> > +			goto error_cleanup_conn;
>> >  		}
>> >
>> >  		msm_property_install_blob(&c_conn->property_info,
>> > @@ -1310,10 +1266,6 @@ struct drm_connector *dpu_connector_init(struct
>> > drm_device *dev,
>> >  				&c_conn->property_info, "dpu_drm_roi_v1",
>> > 0x0,
>> >  				0, ~0, 0, CONNECTOR_PROP_ROI_V1);
>> >  	}
>> > -
>> > -	msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
>> > -			0x0, 0, INR_OPEN_MAX, 0,
>> > CONNECTOR_PROP_RETIRE_FENCE);
>> > -
>> >  	msm_property_install_range(&c_conn->property_info, "autorefresh",
>> >  			0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0,
>> >  			CONNECTOR_PROP_AUTOREFRESH);
>> > @@ -1354,10 +1306,8 @@ struct drm_connector *dpu_connector_init(struct
>> > drm_device *dev,
>> >  		drm_property_blob_put(c_conn->blob_dither);
>> >
>> >  	msm_property_destroy(&c_conn->property_info);
>> > -error_cleanup_fence:
>> > -	mutex_destroy(&c_conn->lock);
>> > -	dpu_fence_deinit(&c_conn->retire_fence);
>> >  error_cleanup_conn:
>> > +	mutex_destroy(&c_conn->lock);
>> >  	drm_connector_cleanup(&c_conn->base);
>> >  error_free_conn:
>> >  	kfree(c_conn);
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
>> > index f6f4837d1359..fdb4d8766549 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_connector.h
>> > @@ -21,7 +21,6 @@
>> >  #include "msm_drv.h"
>> >  #include "msm_prop.h"
>> >  #include "dpu_kms.h"
>> > -#include "dpu_fence.h"
>> >
>> >  #define DPU_CONNECTOR_NAME_SIZE	16
>> >
>> > @@ -247,7 +246,6 @@ struct dpu_connector_evt {
>> >   * @mmu_unsecure: MMU id for unsecure buffers
>> >   * @name: ASCII name of connector
>> >   * @lock: Mutex lock object for this structure
>> > - * @retire_fence: Retire fence context reference
>> >   * @ops: Local callback function pointer table
>> >   * @dpms_mode: DPMS property setting from user space
>> >   * @lp_mode: LP property setting from user space
>> > @@ -274,7 +272,6 @@ struct dpu_connector {
>> >  	char name[DPU_CONNECTOR_NAME_SIZE];
>> >
>> >  	struct mutex lock;
>> > -	struct dpu_fence_context retire_fence;
>> >  	struct dpu_connector_ops ops;
>> >  	int dpms_mode;
>> >  	int lp_mode;
>> > @@ -447,26 +444,6 @@ struct drm_connector *dpu_connector_init(struct
>> > drm_device *dev,
>> >  		int connector_poll,
>> >  		int connector_type);
>> >
>> > -/**
>> > - * dpu_connector_prepare_fence - prepare fence support for current
>> > commit
>> > - * @connector: Pointer to drm connector object
>> > - */
>> > -void dpu_connector_prepare_fence(struct drm_connector *connector);
>> > -
>> > -/**
>> > - * dpu_connector_complete_commit - signal completion of current
> commit
>> > - * @connector: Pointer to drm connector object
>> > - * @ts: timestamp to be updated in the fence signalling
>> > - */
>> > -void dpu_connector_complete_commit(struct drm_connector *connector,
>> > ktime_t ts);
>> > -
>> > -/**
>> > - * dpu_connector_commit_reset - reset the completion signal
>> > - * @connector: Pointer to drm connector object
>> > - * @ts: timestamp to be updated in the fence signalling
>> > - */
>> > -void dpu_connector_commit_reset(struct drm_connector *connector,
>> > ktime_t
>> > ts);
>> > -
>> >  /**
>> >   * dpu_connector_get_info - query display specific information
>> >   * @connector: Pointer to drm connector object
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > index a261021e5deb..2d44989ade7a 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > @@ -629,7 +629,6 @@ static void dpu_crtc_destroy(struct drm_crtc
> *crtc)
>> >  	dpu_cp_crtc_destroy_properties(crtc);
>> >  	_dpu_crtc_destroy_dest_scaler(dpu_crtc);
>> >
>> > -	dpu_fence_deinit(&dpu_crtc->output_fence);
>> >  	_dpu_crtc_deinit_events(dpu_crtc);
>> >
>> >  	drm_crtc_cleanup(crtc);
>> > @@ -1671,65 +1670,6 @@ static void _dpu_crtc_dest_scaler_setup(struct
>> > drm_crtc *crtc)
>> >  	}
>> >  }
>> >
>> > -void dpu_crtc_prepare_commit(struct drm_crtc *crtc,
>> > -		struct drm_crtc_state *old_state)
>> > -{
>> > -	struct drm_device *dev;
>> > -	struct dpu_crtc *dpu_crtc;
>> > -	struct dpu_crtc_state *cstate;
>> > -	struct drm_connector *conn;
>> > -	struct drm_connector_list_iter conn_iter;
>> > -	struct dpu_crtc_retire_event *retire_event = NULL;
>> > -	unsigned long flags;
>> > -	int i;
>> > -
>> > -	if (!crtc || !crtc->state) {
>> > -		DPU_ERROR("invalid crtc\n");
>> > -		return;
>> > -	}
>> > -
>> > -	dev = crtc->dev;
>> > -	dpu_crtc = to_dpu_crtc(crtc);
>> > -	cstate = to_dpu_crtc_state(crtc->state);
>> > -	DPU_EVT32_VERBOSE(DRMID(crtc));
>> > -
>> > -	/* identify connectors attached to this crtc */
>> > -	cstate->num_connectors = 0;
>> > -
>> > -	drm_connector_list_iter_begin(dev, &conn_iter);
>> > -	drm_for_each_connector_iter(conn, &conn_iter)
>> > -		if (conn->state && conn->state->crtc == crtc &&
>> > -				cstate->num_connectors < MAX_CONNECTORS) {
>> > -			cstate->connectors[cstate->num_connectors++] =
>> > conn;
>> > -			dpu_connector_prepare_fence(conn);
>> > -		}
>> > -	drm_connector_list_iter_end(&conn_iter);
>> > -
>> > -	for (i = 0; i < DPU_CRTC_FRAME_EVENT_SIZE; i++) {
>> > -		retire_event = &dpu_crtc->retire_events[i];
>> > -		if (list_empty(&retire_event->list))
>> > -			break;
>> > -		retire_event = NULL;
>> > -	}
>> > -
>> > -	if (retire_event) {
>> > -		retire_event->num_connectors = cstate->num_connectors;
>> > -		for (i = 0; i < cstate->num_connectors; i++)
>> > -			retire_event->connectors[i] =
>> > cstate->connectors[i];
>> > -
>> > -		spin_lock_irqsave(&dpu_crtc->spin_lock, flags);
>> > -		list_add_tail(&retire_event->list,
>> > -
>> > &dpu_crtc->retire_event_list);
>> > -		spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
>> > -	} else {
>> > -		DPU_ERROR("crtc%d retire event overflow\n",
>> > crtc->base.id);
>> > -		DPU_EVT32(DRMID(crtc), DPU_EVTLOG_ERROR);
>> > -	}
>> > -
>> > -	/* prepare main output fence */
>> > -	dpu_fence_prepare(&dpu_crtc->output_fence);
>> > -}
>> > -
>> >  /**
>> >   *  _dpu_crtc_complete_flip - signal pending page_flip events
>> >   * Any pending vblank events are added to the vblank_event_list
>> > @@ -1799,41 +1739,6 @@ static void dpu_crtc_vblank_cb(void *data)
>> >  	DPU_EVT32_VERBOSE(DRMID(crtc));
>> >  }
>> >
>> > -static void _dpu_crtc_retire_event(struct drm_crtc *crtc, ktime_t ts)
>> > -{
>> > -	struct dpu_crtc_retire_event *retire_event;
>> > -	struct dpu_crtc *dpu_crtc;
>> > -	unsigned long flags;
>> > -	int i;
>> > -
>> > -	if (!crtc) {
>> > -		DPU_ERROR("invalid param\n");
>> > -		return;
>> > -	}
>> > -
>> > -	dpu_crtc = to_dpu_crtc(crtc);
>> > -	spin_lock_irqsave(&dpu_crtc->spin_lock, flags);
>> > -	retire_event =
>> > list_first_entry_or_null(&dpu_crtc->retire_event_list,
>> > -				struct dpu_crtc_retire_event, list);
>> > -	if (retire_event)
>> > -		list_del_init(&retire_event->list);
>> > -	spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
>> > -
>> > -	if (!retire_event) {
>> > -		DPU_ERROR("crtc%d retire event without kickoff\n",
>> > -
>> > crtc->base.id);
>> > -		DPU_EVT32(DRMID(crtc), DPU_EVTLOG_ERROR);
>> > -		return;
>> > -	}
>> > -
>> > -	DPU_ATRACE_BEGIN("signal_retire_fence");
>> > -	for (i = 0; (i < retire_event->num_connectors) &&
>> > -					retire_event->connectors[i]; ++i)
>> > -		dpu_connector_complete_commit(
>> > -					retire_event->connectors[i], ts);
>> > -	DPU_ATRACE_END("signal_retire_fence");
>> > -}
>> > -
>> >  /* _dpu_crtc_idle_notify - signal idle timeout to client */
>> >  static void _dpu_crtc_idle_notify(struct dpu_crtc *dpu_crtc)
>> >  {
>> > @@ -1945,16 +1850,6 @@ static void dpu_crtc_frame_event_work(struct
>> > kthread_work *work)
>> >  			frame_done = true;
>> >  	}
>> >
>> > -	if (fevent->event & DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE)
>> > {
>> > -		DPU_ATRACE_BEGIN("signal_release_fence");
>> > -		dpu_fence_signal(&dpu_crtc->output_fence, fevent->ts,
>> > false);
>> > -		DPU_ATRACE_END("signal_release_fence");
>> > -	}
>> > -
>> > -	if (fevent->event & DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE)
>> > -		/* this api should be called without spin_lock */
>> > -		_dpu_crtc_retire_event(crtc, fevent->ts);
>> > -
>> >  	if (fevent->event & DPU_ENCODER_FRAME_EVENT_PANEL_DEAD)
>> >  		DPU_ERROR("crtc%d ts:%lld received panel dead event\n",
>> >  				crtc->base.id, ktime_to_ns(fevent->ts));
>> > @@ -1971,11 +1866,11 @@ static void dpu_crtc_frame_event_work(struct
>> > kthread_work *work)
>> >  /*
>> >   * dpu_crtc_frame_event_cb - crtc frame event callback API. CRTC
> module
>> >   * registers this API to encoder for all frame event callbacks like
>> > - * release_fence, retire_fence, frame_error, frame_done,
> idle_timeout,
>> > - * etc. Encoder may call different events from different context -
> IRQ,
>> > - * user thread, commit_thread, etc. Each event should be carefully
>> > - * reviewed and should be processed in proper task context to avoid
>> > scheduling
>> > - * delay or properly manage the irq context's bottom half processing.
>> > + * frame_error, frame_done, idle_timeout, etc. Encoder may call
>> > different
>> > events
>> > + * from different context - IRQ, user thread, commit_thread, etc.
> Each
>> > event
>> > + * should be carefully reviewed and should be processed in proper
> task
>> > context
>> > + * to avoid schedulin delay or properly manage the irq context's
> bottom
>> > half
>> > + * processing.
>> >   */
>> >  static void dpu_crtc_frame_event_cb(void *data, u32 event)
>> >  {
>> > @@ -3484,14 +3379,6 @@ static void dpu_crtc_disable(struct drm_crtc
>> > *crtc)
>> >  		dpu_power_handle_unregister_event(&priv->phandle,
>> >  				dpu_crtc->power_event);
>> >
>> > -	/**
>> > -	 * All callbacks are unregistered and frame done waits are
>> > complete
>> > -	 * at this point. No buffers are accessed by hardware.
>> > -	 * reset the fence timeline if there is any issue.
>> > -	 */
>> > -	dpu_fence_signal(&dpu_crtc->output_fence, ktime_get(), true);
>> > -	for (i = 0; i < cstate->num_connectors; ++i)
>> > -		dpu_connector_commit_reset(cstate->connectors[i],
>> > ktime_get());
>> >
>> >  	memset(dpu_crtc->mixers, 0, sizeof(dpu_crtc->mixers));
>> >  	dpu_crtc->num_mixers = 0;
>> > @@ -3703,6 +3590,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc
>> > *crtc,
>> >  	int multirect_count = 0;
>> >  	const struct drm_plane_state *pipe_staged[SSPP_MAX];
>> >  	int left_zpos_cnt = 0, right_zpos_cnt = 0;
>> > +	struct drm_connector_list_iter conn_iter;
>> > +	struct drm_connector *conn;
>> >
>> >  	if (!crtc) {
>> >  		DPU_ERROR("invalid crtc\n");
>> > @@ -3956,6 +3845,16 @@ static int dpu_crtc_atomic_check(struct
> drm_crtc
>> > *crtc,
>> >  		goto end;
>> >  	}
>> >
>> > +	/* identify connectors attached to this crtc */
>> > +	cstate->num_connectors = 0;
>> > +	drm_connector_list_iter_begin(crtc->dev, &conn_iter);
>> > +	drm_for_each_connector_iter(conn, &conn_iter)
>> > +		if (conn->state && conn->state->crtc == crtc &&
>> > +				cstate->num_connectors < MAX_CONNECTORS) {
>> > +			cstate->connectors[cstate->num_connectors++] =
>> > conn;
>> > +		}
>> > +	drm_connector_list_iter_end(&conn_iter);
>> > +
>> 
>> Is this hunk related to this change?
>> 
> 
> This code came from dpu_crtc_prepare_commit. We use 
> cstate->num_connectors
> elsewhere, so it needed to be preserved.
> 
> Sean
> 
>> >  end:
>> >  	_dpu_crtc_rp_free_unused(&cstate->rp);
>> >  	return rc;
>> > @@ -4034,13 +3933,6 @@ static void dpu_crtc_install_properties(struct
>> > drm_crtc *crtc,
>> >  		"input_fence_timeout", 0x0, 0,
>> > DPU_CRTC_MAX_INPUT_FENCE_TIMEOUT,
>> >  		DPU_CRTC_INPUT_FENCE_TIMEOUT,
>> > CRTC_PROP_INPUT_FENCE_TIMEOUT);
>> >
>> > -	msm_property_install_range(&dpu_crtc->property_info,
>> > "output_fence",
>> > -			0x0, 0, INR_OPEN_MAX, 0x0,
>> > CRTC_PROP_OUTPUT_FENCE);
>> > -
>> > -	msm_property_install_range(&dpu_crtc->property_info,
>> > -			"output_fence_offset", 0x0, 0, 1, 0,
>> > -			CRTC_PROP_OUTPUT_FENCE_OFFSET);
>> > -
>> >  	msm_property_install_range(&dpu_crtc->property_info,
>> >  			"core_clk", 0x0, 0, U64_MAX,
>> >  			dpu_kms->perf.max_core_clk_rate,
>> > @@ -4342,29 +4234,12 @@ static int dpu_crtc_atomic_get_property(struct
>> > drm_crtc *crtc,
>> >  		}
>> >
>> >  		i = msm_property_index(&dpu_crtc->property_info,
>> > property);
>> > -		if (i == CRTC_PROP_OUTPUT_FENCE) {
>> > -			uint32_t offset = dpu_crtc_get_property(cstate,
>> > -					CRTC_PROP_OUTPUT_FENCE_OFFSET);
>> > -
>> > -			/**
>> > -			 * set the offset to 0 only for cmd mode panels,
>> > so
>> > -			 * the release fence for the current frame can be
>> > -			 * triggered right after PP_DONE interrupt.
>> > -			 */
>> > -			offset = is_cmd ? 0 : (offset + conn_offset);
>> > -
>> > -			ret = dpu_fence_create(&dpu_crtc->output_fence,
>> > val,
>> > -								offset);
>> > -			if (ret)
>> > -				DPU_ERROR("fence create failed\n");
>> > -		} else {
>> > -			ret =
>> > msm_property_atomic_get(&dpu_crtc->property_info,
>> > -					&cstate->property_state,
>> > -					property, val);
>> > -			if (ret)
>> > -				ret = dpu_cp_crtc_get_property(crtc,
>> > -					property, val);
>> > -		}
>> > +		ret = msm_property_atomic_get(&dpu_crtc->property_info,
>> > +				&cstate->property_state,
>> > +				property, val);
>> > +		if (ret)
>> > +			ret = dpu_cp_crtc_get_property(crtc,
>> > +				property, val);
>> >  		if (ret)
>> >  			DRM_ERROR("get property failed\n");
>> >  	}
>> > @@ -4858,10 +4733,6 @@ static int _dpu_crtc_init_events(struct
> dpu_crtc
>> > *dpu_crtc)
>> >  		list_add_tail(&dpu_crtc->event_cache[i].list,
>> >  				&dpu_crtc->event_free_list);
>> >
>> > -	INIT_LIST_HEAD(&dpu_crtc->retire_event_list);
>> > -	for (i = 0; i < ARRAY_SIZE(dpu_crtc->retire_events); i++)
>> > -		INIT_LIST_HEAD(&dpu_crtc->retire_events[i].list);
>> > -
>> >  	return rc;
>> >  }
>> >
>> > @@ -4920,9 +4791,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device
>> > *dev, struct drm_plane *plane)
>> >  		return ERR_PTR(rc);
>> >  	}
>> >
>> > -	/* initialize output fence support */
>> > -	dpu_fence_init(&dpu_crtc->output_fence, dpu_crtc->name,
>> > crtc->base.id);
>> > -
>> >  	/* create CRTC properties */
>> >  	msm_property_init(&dpu_crtc->property_info, &crtc->base, dev,
>> >  			priv->crtc_property, dpu_crtc->property_data,
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
>> > index b63df243be33..727a3434a4f6 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
>> > @@ -22,7 +22,6 @@
>> >  #include <linux/kthread.h>
>> >  #include <drm/drm_crtc.h>
>> >  #include "msm_prop.h"
>> > -#include "dpu_fence.h"
>> >  #include "dpu_kms.h"
>> >  #include "dpu_core_perf.h"
>> >  #include "dpu_hw_blk.h"
>> > @@ -85,17 +84,6 @@ struct dpu_crtc_smmu_state_data {
>> >  	uint32_t transition_error;
>> >  };
>> >
>> > -/**
>> > - * @connectors    : Currently associated drm connectors for retire
>> > event
>> > - * @num_connectors: Number of associated drm connectors for retire
>> > event
>> > - * @list:	event list
>> > - */
>> > -struct dpu_crtc_retire_event {
>> > -	struct drm_connector *connectors[MAX_CONNECTORS];
>> > -	int num_connectors;
>> > -	struct list_head list;
>> > -};
>> > -
>> >  /**
>> >   * struct dpu_crtc_mixer: stores the map for each virtual pipeline in
>> > the
>> > CRTC
>> >   * @hw_lm:	LM HW Driver context
>> > @@ -169,7 +157,6 @@ struct dpu_crtc_event {
>> >   * @drm_requested_vblank : Whether vblanks have been enabled in the
>> > encoder
>> >   * @property_info : Opaque structure for generic property support
>> >   * @property_defaults : Array of default values for generic property
>> > support
>> > - * @output_fence  : output release fence context
>> >   * @stage_cfg     : H/w mixer stage configuration
>> >   * @debugfs_root  : Parent of debugfs node
>> >   * @vblank_cb_count : count of vblank callback since last reset
>> > @@ -190,8 +177,6 @@ struct dpu_crtc_event {
>> >   * @frame_events  : static allocation of in-flight frame events
>> >   * @frame_event_list : available frame event list
>> >   * @spin_lock     : spin lock for frame event, transaction status,
>> > etc...
>> > - * @retire_events  : static allocation of retire fence connector
>> > - * @retire_event_list : available retire fence connector list
>> >   * @frame_done_comp    : for frame_event_done synchronization
>> >   * @event_thread  : Pointer to event handler thread
>> >   * @event_worker  : Event worker queue
>> > @@ -227,9 +212,6 @@ struct dpu_crtc {
>> >  	struct msm_property_data property_data[CRTC_PROP_COUNT];
>> >  	struct drm_property_blob *blob_info;
>> >
>> > -	/* output fence support */
>> > -	struct dpu_fence_context output_fence;
>> > -
>> >  	struct dpu_hw_stage_cfg stage_cfg;
>> >  	struct dentry *debugfs_root;
>> >
>> > @@ -253,8 +235,6 @@ struct dpu_crtc {
>> >  	struct dpu_crtc_frame_event
>> > frame_events[DPU_CRTC_FRAME_EVENT_SIZE];
>> >  	struct list_head frame_event_list;
>> >  	spinlock_t spin_lock;
>> > -	struct dpu_crtc_retire_event
>> > retire_events[DPU_CRTC_FRAME_EVENT_SIZE];
>> > -	struct list_head retire_event_list;
>> >  	struct completion frame_done_comp;
>> >
>> >  	/* for handling internal event thread */
>> > @@ -475,14 +455,6 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool
>> > en);
>> >   */
>> >  void dpu_crtc_commit_kickoff(struct drm_crtc *crtc);
>> >
>> > -/**
>> > - * dpu_crtc_prepare_commit - callback to prepare for output fences
>> > - * @crtc: Pointer to drm crtc object
>> > - * @old_state: Pointer to drm crtc old state object
>> > - */
>> > -void dpu_crtc_prepare_commit(struct drm_crtc *crtc,
>> > -		struct drm_crtc_state *old_state);
>> > -
>> >  /**
>> >   * dpu_crtc_complete_commit - callback signalling completion of
> current
>> > commit
>> >   * @crtc: Pointer to drm crtc object
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > index 4d1e3652dbf4..a54ad2cd5856 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > @@ -2465,9 +2465,6 @@ static inline void
>> > _dpu_encoder_trigger_flush(struct
>> > drm_encoder *drm_enc,
>> >
>> >  	pending_kickoff_cnt = dpu_encoder_phys_inc_pending(phys);
>> >
>> > -	if (phys->ops.is_master && phys->ops.is_master(phys))
>> > -		atomic_inc(&phys->pending_retire_fence_cnt);
>> > -
>> >  	if (extra_flush_bits && ctl->ops.update_pending_flush)
>> >  		ctl->ops.update_pending_flush(ctl, extra_flush_bits);
>> >
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> > index 69fb26cb43ab..86a3800af673 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> > @@ -27,9 +27,7 @@
>> >  #define DPU_ENCODER_FRAME_EVENT_DONE			BIT(0)
>> >  #define DPU_ENCODER_FRAME_EVENT_ERROR			BIT(1)
>> >  #define DPU_ENCODER_FRAME_EVENT_PANEL_DEAD		BIT(2)
>> > -#define DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE	BIT(3)
>> > -#define DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE	BIT(4)
>> > -#define DPU_ENCODER_FRAME_EVENT_IDLE			BIT(5)
>> > +#define DPU_ENCODER_FRAME_EVENT_IDLE			BIT(3)
>> >
>> >  #define IDLE_TIMEOUT	(66 - 16/2)
>> >
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> > index 3b05569007d2..71cd2f258994 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> > @@ -245,8 +245,6 @@ struct dpu_encoder_irq {
>> >   *				scheduled. Decremented in irq handler
>> >   * @pending_ctlstart_cnt:	Atomic counter tracking the number of ctl
>> > start
>> >   *                              pending.
>> > - * @pending_retire_fence_cnt:   Atomic counter tracking the pending
>> > retire
>> > - *                              fences that have to be signalled.
>> >   * @pending_kickoff_wq:		Wait queue for blocking until
>> > kickoff completes
>> >   * @irq:			IRQ tracking structures
>> >   */
>> > @@ -273,7 +271,6 @@ struct dpu_encoder_phys {
>> >  	atomic_t underrun_cnt;
>> >  	atomic_t pending_ctlstart_cnt;
>> >  	atomic_t pending_kickoff_cnt;
>> > -	atomic_t pending_retire_fence_cnt;
>> >  	wait_queue_head_t pending_kickoff_wq;
>> >  	struct dpu_encoder_irq irq[INTR_IDX_MAX];
>> >  };
>> > @@ -323,9 +320,6 @@ struct dpu_encoder_phys_cmd_autorefresh {
>> >   *			after ctl_start instead of before next frame
>> > kickoff
>> >   * @pp_timeout_report_cnt: number of pingpong done irq timeout errors
>> >   * @autorefresh: autorefresh feature state
>> > - * @pending_rd_ptr_cnt: atomic counter to indicate if retire fence
> can
>> > be
>> > - *                      signaled at the next rd_ptr_irq
>> > - * @rd_ptr_timestamp: last rd_ptr_irq timestamp
>> >   * @pending_vblank_cnt: Atomic counter tracking pending wait for
> VBLANK
>> >   * @pending_vblank_wq: Wait queue for blocking until VBLANK received
>> >   */
>> > @@ -335,8 +329,6 @@ struct dpu_encoder_phys_cmd {
>> >  	bool serialize_wait4pp;
>> >  	int pp_timeout_report_cnt;
>> >  	struct dpu_encoder_phys_cmd_autorefresh autorefresh;
>> > -	atomic_t pending_rd_ptr_cnt;
>> > -	ktime_t rd_ptr_timestamp;
>> >  	atomic_t pending_vblank_cnt;
>> >  	wait_queue_head_t pending_vblank_wq;
>> >  };
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
>> > index e92380a1d5a4..6ccf37820aa2 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
>> > @@ -44,12 +44,6 @@
>> >
>> >  #define DPU_ENC_WR_PTR_START_TIMEOUT_US 20000
>> >
>> > -/*
>> > - * Threshold for signalling retire fences in cases where
>> > - * CTL_START_IRQ is received just after RD_PTR_IRQ
>> > - */
>> > -#define DPU_ENC_CTL_START_THRESHOLD_US 500
>> > -
>> >  static inline int _dpu_encoder_phys_cmd_get_idle_timeout(
>> >  		struct dpu_encoder_phys_cmd *cmd_enc)
>> >  {
>> > @@ -170,8 +164,7 @@ static void
> dpu_encoder_phys_cmd_pp_tx_done_irq(void
>> > *arg, int irq_idx)
>> >  	struct dpu_encoder_phys *phys_enc = arg;
>> >  	unsigned long lock_flags;
>> >  	int new_cnt;
>> > -	u32 event = DPU_ENCODER_FRAME_EVENT_DONE |
>> > -			DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
>> > +	u32 event = DPU_ENCODER_FRAME_EVENT_DONE;
>> >
>> >  	if (!phys_enc || !phys_enc->hw_pp)
>> >  		return;
>> > @@ -221,7 +214,6 @@ static void
> dpu_encoder_phys_cmd_pp_rd_ptr_irq(void
>> > *arg, int irq_idx)
>> >  {
>> >  	struct dpu_encoder_phys *phys_enc = arg;
>> >  	struct dpu_encoder_phys_cmd *cmd_enc;
>> > -	u32 event = 0;
>> >
>> >  	if (!phys_enc || !phys_enc->hw_pp)
>> >  		return;
>> > @@ -229,30 +221,10 @@ static void
>> > dpu_encoder_phys_cmd_pp_rd_ptr_irq(void
>> > *arg, int irq_idx)
>> >  	DPU_ATRACE_BEGIN("rd_ptr_irq");
>> >  	cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
>> >
>> > -	/**
>> > -	 * signal only for master, when the ctl_start irq is
>> > -	 * done and incremented the pending_rd_ptr_cnt.
>> > -	 */
>> > -	if (dpu_encoder_phys_cmd_is_master(phys_enc)
>> > -		    && atomic_add_unless(&cmd_enc->pending_rd_ptr_cnt, -1,
>> > 0)
>> > -		    && atomic_add_unless(
>> > -				&phys_enc->pending_retire_fence_cnt, -1,
>> > 0)) {
>> > -
>> > -		event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
>> > -		if (phys_enc->parent_ops.handle_frame_done)
>> > -			phys_enc->parent_ops.handle_frame_done(
>> > -				phys_enc->parent, phys_enc, event);
>> > -	}
>> > -
>> > -	DPU_EVT32_IRQ(DRMID(phys_enc->parent),
>> > -			phys_enc->hw_pp->idx - PINGPONG_0, event, 0xfff);
>> > -
>> >  	if (phys_enc->parent_ops.handle_vblank_virt)
>> >  		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
>> >  			phys_enc);
>> >
>> > -	cmd_enc->rd_ptr_timestamp = ktime_get();
>> > -
>> >  	atomic_add_unless(&cmd_enc->pending_vblank_cnt, -1, 0);
>> >  	wake_up_all(&cmd_enc->pending_vblank_wq);
>> >  	DPU_ATRACE_END("rd_ptr_irq");
>> > @@ -262,9 +234,6 @@ static void
> dpu_encoder_phys_cmd_ctl_start_irq(void
>> > *arg, int irq_idx)
>> >  {
>> >  	struct dpu_encoder_phys *phys_enc = arg;
>> >  	struct dpu_encoder_phys_cmd *cmd_enc;
>> > -	struct dpu_hw_ctl *ctl;
>> > -	u32 event = 0;
>> > -	s64 time_diff_us;
>> >
>> >  	if (!phys_enc || !phys_enc->hw_ctl)
>> >  		return;
>> > @@ -272,43 +241,8 @@ static void
> dpu_encoder_phys_cmd_ctl_start_irq(void
>> > *arg, int irq_idx)
>> >  	DPU_ATRACE_BEGIN("ctl_start_irq");
>> >  	cmd_enc = to_dpu_encoder_phys_cmd(phys_enc);
>> >
>> > -	ctl = phys_enc->hw_ctl;
>> >  	atomic_add_unless(&phys_enc->pending_ctlstart_cnt, -1, 0);
>> >
>> > -	time_diff_us = ktime_us_delta(ktime_get(),
>> > cmd_enc->rd_ptr_timestamp);
>> > -
>> > -	/* handle retire fence based on only master */
>> > -	if (dpu_encoder_phys_cmd_is_master(phys_enc)
>> > -			&&
>> > atomic_read(&phys_enc->pending_retire_fence_cnt)) {
>> > -		/**
>> > -		 * Handle rare cases where the ctl_start_irq is received
>> > -		 * after rd_ptr_irq. If it falls within a threshold, it is
>> > -		 * guaranteed the frame would be picked up in the current
>> > TE.
>> > -		 * Signal retire fence immediately in such case.
>> > -		 */
>> > -		if ((time_diff_us <= DPU_ENC_CTL_START_THRESHOLD_US)
>> > -			    && atomic_add_unless(
>> > -				&phys_enc->pending_retire_fence_cnt, -1,
>> > 0)) {
>> > -
>> > -			event =
>> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
>> > -
>> > -			if (phys_enc->parent_ops.handle_frame_done)
>> > -				phys_enc->parent_ops.handle_frame_done(
>> > -					phys_enc->parent, phys_enc,
>> > event);
>> > -
>> > -		/**
>> > -		 * In ideal cases, ctl_start_irq is received before the
>> > -		 * rd_ptr_irq, so set the atomic flag to indicate the
>> > event
>> > -		 * and rd_ptr_irq will handle signalling the retire fence
>> > -		 */
>> > -		} else {
>> > -			atomic_inc(&cmd_enc->pending_rd_ptr_cnt);
>> > -		}
>> > -	}
>> > -
>> > -	DPU_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0,
>> > -				time_diff_us, event, 0xfff);
>> > -
>> >  	/* Signal any waiting ctl start interrupt */
>> >  	wake_up_all(&phys_enc->pending_kickoff_wq);
>> >  	DPU_ATRACE_END("ctl_start_irq");
>> > @@ -409,8 +343,7 @@ static int
>> > _dpu_encoder_phys_cmd_handle_ppdone_timeout(
>> >  {
>> >  	struct dpu_encoder_phys_cmd *cmd_enc =
>> >  			to_dpu_encoder_phys_cmd(phys_enc);
>> > -	u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR
>> > -				|
>> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
>> > +	u32 frame_event = DPU_ENCODER_FRAME_EVENT_ERROR;
>> >  	bool do_log = false;
>> >
>> >  	if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_ctl)
>> > @@ -1346,8 +1279,6 @@ struct dpu_encoder_phys
>> > *dpu_encoder_phys_cmd_init(
>> >  	atomic_set(&phys_enc->vblank_refcount, 0);
>> >  	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
>> >  	atomic_set(&phys_enc->pending_ctlstart_cnt, 0);
>> > -	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
>> > -	atomic_set(&cmd_enc->pending_rd_ptr_cnt, 0);
>> >  	atomic_set(&cmd_enc->pending_vblank_cnt, 0);
>> >  	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
>> >  	init_waitqueue_head(&cmd_enc->pending_vblank_wq);
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> > index 62c6f5c3547a..edaad0413987 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> > @@ -373,13 +373,10 @@ static void
>> > dpu_encoder_phys_vid_setup_timing_engine(
>> >  static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
>> >  {
>> >  	struct dpu_encoder_phys *phys_enc = arg;
>> > -	struct dpu_encoder_phys_vid *vid_enc =
>> > -			to_dpu_encoder_phys_vid(phys_enc);
>> >  	struct dpu_hw_ctl *hw_ctl;
>> >  	unsigned long lock_flags;
>> >  	u32 flush_register = 0;
>> >  	int new_cnt = -1, old_cnt = -1;
>> > -	u32 event = 0;
>> >
>> >  	if (!phys_enc)
>> >  		return;
>> > @@ -390,18 +387,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void
>> > *arg, int irq_idx)
>> >
>> >  	DPU_ATRACE_BEGIN("vblank_irq");
>> >
>> > -	/* signal only for master, where there is a pending kickoff */
>> > -	if (dpu_encoder_phys_vid_is_master(phys_enc)
>> > -			&& atomic_add_unless(
>> > -				&phys_enc->pending_retire_fence_cnt, -1,
>> > 0)) {
>> > -		event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
>> > -				|
>> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
>> > -
>> > -		if (phys_enc->parent_ops.handle_frame_done)
>> > -
>> > phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
>> > -				phys_enc, event);
>> > -	}
>> > -
>> >  	if (phys_enc->parent_ops.handle_vblank_virt)
>> >  		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
>> >  				phys_enc);
>> > @@ -422,9 +407,6 @@ static void dpu_encoder_phys_vid_vblank_irq(void
>> > *arg,
>> > int irq_idx)
>> >  				-1, 0);
>> >  	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
>> >
>> > -	DPU_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx -
>> > INTF_0,
>> > -			old_cnt, new_cnt, flush_register, event);
>> > -
>> >  	/* Signal any waiting atomic commit thread */
>> >  	wake_up_all(&phys_enc->pending_kickoff_wq);
>> >  	DPU_ATRACE_END("vblank_irq");
>> > @@ -1028,7 +1010,6 @@ struct dpu_encoder_phys
>> > *dpu_encoder_phys_vid_init(
>> >
>> >  	atomic_set(&phys_enc->vblank_refcount, 0);
>> >  	atomic_set(&phys_enc->pending_kickoff_cnt, 0);
>> > -	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
>> >  	init_waitqueue_head(&phys_enc->pending_kickoff_wq);
>> >  	phys_enc->enable_state = DPU_ENC_DISABLED;
>> >
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> > index 9a6fa3e1e8b4..2bc5894839c4 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> > @@ -680,11 +680,8 @@ static void dpu_encoder_phys_wb_done_irq(void
> *arg,
>> > int irq_idx)
>> >  	if (phys_enc->enable_state == DPU_ENC_DISABLING)
>> >  		goto complete;
>> >
>> > -	event = DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
>> > -			| DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE
>> > -			| DPU_ENCODER_FRAME_EVENT_DONE;
>> > +	event = DPU_ENCODER_FRAME_EVENT_DONE;
>> >
>> > -	atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0);
>> >  	if (phys_enc->parent_ops.handle_frame_done)
>> >  		phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
>> >  				phys_enc, event);
>> > @@ -847,12 +844,8 @@ static int
>> > dpu_encoder_phys_wb_wait_for_commit_done(
>> >  		} else {
>> >  			DPU_ERROR("wb:%d kickoff timed out\n",
>> >  					wb_enc->wb_dev->wb_idx - WB_0);
>> > -			atomic_add_unless(
>> > -				&phys_enc->pending_retire_fence_cnt, -1,
>> > 0);
>> >
>> > -			event =
>> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
>> > -				|
>> > DPU_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE
>> > -				| DPU_ENCODER_FRAME_EVENT_ERROR;
>> > +			event = DPU_ENCODER_FRAME_EVENT_ERROR;
>> >  			if (phys_enc->parent_ops.handle_frame_done)
>> >  				phys_enc->parent_ops.handle_frame_done(
>> >  					phys_enc->parent, phys_enc,
>> > event);
>> > @@ -1333,7 +1326,6 @@ struct dpu_encoder_phys
> *dpu_encoder_phys_wb_init(
>> >  	phys_enc->intf_mode = INTF_MODE_WB_LINE;
>> >  	phys_enc->intf_idx = p->intf_idx;
>> >  	phys_enc->enc_spinlock = p->enc_spinlock;
>> > -	atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
>> >  	INIT_LIST_HEAD(&wb_enc->irq_cb.list);
>> >
>> >  	/* create internal buffer for disable logic */
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > index 3d83037e8305..9d68030378a7 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > @@ -545,35 +545,6 @@ static void dpu_kms_wait_for_commit_done(struct
>> > msm_kms *kms,
>> >  	}
>> >  }
>> >
>> > -static void dpu_kms_prepare_fence(struct msm_kms *kms,
>> > -		struct drm_atomic_state *old_state)
>> > -{
>> > -	struct drm_crtc *crtc;
>> > -	struct drm_crtc_state *old_crtc_state;
>> > -	int i, rc;
>> > -
>> > -	if (!kms || !old_state || !old_state->dev ||
>> > !old_state->acquire_ctx) {
>> > -		DPU_ERROR("invalid argument(s)\n");
>> > -		return;
>> > -	}
>> > -
>> > -retry:
>> > -	/* attempt to acquire ww mutex for connection */
>> > -	rc =
>> > drm_modeset_lock(&old_state->dev->mode_config.connection_mutex,
>> > -			       old_state->acquire_ctx);
>> > -
>> > -	if (rc == -EDEADLK) {
>> > -		drm_modeset_backoff(old_state->acquire_ctx);
>> > -		goto retry;
>> > -	}
>> > -
>> > -	/* old_state actually contains updated crtc pointers */
>> > -	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
>> > -		if (crtc->state->active)
>> > -			dpu_crtc_prepare_commit(crtc, old_crtc_state);
>> > -	}
>> > -}
>> > -
>> >  /**
>> >   * _dpu_kms_get_displays - query for underlying display handles and
>> > cache
>> > them
>> >   * @dpu_kms:    Pointer to dpu kms structure
>> > @@ -1734,7 +1705,6 @@ static const struct msm_kms_funcs kms_funcs = {
>> >  	.irq_uninstall   = dpu_irq_uninstall,
>> >  	.irq             = dpu_irq,
>> >  	.preclose        = dpu_kms_preclose,
>> > -	.prepare_fence   = dpu_kms_prepare_fence,
>> >  	.prepare_commit  = dpu_kms_prepare_commit,
>> >  	.commit          = dpu_kms_commit,
>> >  	.complete_commit = dpu_kms_complete_commit,
>> > diff --git a/drivers/gpu/drm/msm/msm_drv.h
>> > b/drivers/gpu/drm/msm/msm_drv.h
>> > index 8cab333df717..e92376acbcfe 100644
>> > --- a/drivers/gpu/drm/msm/msm_drv.h
>> > +++ b/drivers/gpu/drm/msm/msm_drv.h
>> > @@ -132,8 +132,6 @@ enum msm_mdp_crtc_property {
>> >
>> >  	/* range properties */
>> >  	CRTC_PROP_INPUT_FENCE_TIMEOUT = CRTC_PROP_BLOBCOUNT,
>> > -	CRTC_PROP_OUTPUT_FENCE,
>> > -	CRTC_PROP_OUTPUT_FENCE_OFFSET,
>> >  	CRTC_PROP_DIM_LAYER_V1,
>> >  	CRTC_PROP_CORE_CLK,
>> >  	CRTC_PROP_CORE_AB,
>> > @@ -163,7 +161,6 @@ enum msm_mdp_conn_property {
>> >
>> >  	/* range properties */
>> >  	CONNECTOR_PROP_OUT_FB = CONNECTOR_PROP_BLOBCOUNT,
>> > -	CONNECTOR_PROP_RETIRE_FENCE,
>> >  	CONNECTOR_PROP_DST_X,
>> >  	CONNECTOR_PROP_DST_Y,
>> >  	CONNECTOR_PROP_DST_W,
>> 
>> --
>> Jeykumar S

-- 
Jeykumar S
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 02/11] drm/msm: Don't duplicate modeset_enables atomic helper
  2018-03-12 20:21           ` Sean Paul
@ 2018-03-13 23:57             ` Jeykumar Sankaran
       [not found]               ` <677c8c29a788a147aa45bc1e9768527e-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-13 23:57 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-03-12 13:21, Sean Paul wrote:
> On Thu, Mar 08, 2018 at 04:56:01PM -0800, Jeykumar Sankaran wrote:
>> On 2018-02-28 11:18, Sean Paul wrote:
>> > Instead, shuffle things around so we kickoff crtc after enabling
> encoder
>> > during modesets. Also moves the vblank wait to after the frame.
>> >
>> > Change-Id: I16c7b7f9390d04f6050aa20e17a5335fbf49eba3
>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> > ---
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   9 ++
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   5 +-
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c     |  31 ++++-
>> >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |   2 +
>> >  drivers/gpu/drm/msm/msm_atomic.c            | 132
> +-------------------
>> >  5 files changed, 48 insertions(+), 131 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > index a3ab6ed2bf1d..94fab2dcca5b 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > @@ -3525,6 +3525,12 @@ static void dpu_crtc_enable(struct drm_crtc
>> > *crtc,
>> >  	DPU_EVT32_VERBOSE(DRMID(crtc));
>> >  	dpu_crtc = to_dpu_crtc(crtc);
>> >
>> > +	if (msm_is_mode_seamless(&crtc->state->adjusted_mode) ||
>> > +	    msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode)) {
>> > +		DPU_DEBUG("Skipping crtc enable, seamless mode\n");
>> > +		return;
>> > +	}
>> > +
>> >  	pm_runtime_get_sync(crtc->dev->dev);
>> >
>> >  	drm_for_each_encoder(encoder, crtc->dev) {
>> > @@ -3572,6 +3578,9 @@ static void dpu_crtc_enable(struct drm_crtc
> *crtc,
>> >  		DPU_POWER_EVENT_POST_ENABLE | DPU_POWER_EVENT_POST_DISABLE
>> > |
>> >  		DPU_POWER_EVENT_PRE_DISABLE,
>> >  		dpu_crtc_handle_power_event, crtc, dpu_crtc->name);
>> > +
>> > +	if (msm_needs_vblank_pre_modeset(&crtc->state->adjusted_mode))
>> > +		drm_crtc_wait_one_vblank(crtc);
>> >  }
>> >
>> >  struct plane_state {
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > index 28ceb589ee40..4d1e3652dbf4 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > @@ -3693,8 +3693,11 @@ static void
> dpu_encoder_frame_done_timeout(struct
>> > timer_list *t)
>> >  static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs
> =
>> > {
>> >  	.mode_set = dpu_encoder_virt_mode_set,
>> >  	.disable = dpu_encoder_virt_disable,
>> > -	.enable = dpu_encoder_virt_enable,
>> > +	.enable = dpu_kms_encoder_enable,
>> >  	.atomic_check = dpu_encoder_virt_atomic_check,
>> > +
>> > +	/* This is called by dpu_kms_encoder_enable */
>> > +	.commit = dpu_encoder_virt_enable,
>> >  };
>> >
>> >  static const struct drm_encoder_funcs dpu_encoder_funcs = {
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > index 81fd3a429e9f..3d83037e8305 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > @@ -425,14 +425,37 @@ static void dpu_kms_prepare_commit(struct
> msm_kms
>> > *kms,
>> >  			dpu_encoder_prepare_commit(encoder);
>> >  }
>> >
>> > -static void dpu_kms_commit(struct msm_kms *kms,
>> > -		struct drm_atomic_state *old_state)
>> > +/*
>> > + * Override the encoder enable since we need to setup the inline
>> > rotator
>> > and do
>> > + * some crtc magic before enabling any bridge that might be present.
>> > + */
>> > +void dpu_kms_encoder_enable(struct drm_encoder *encoder)
>> > +{
>> > +	const struct drm_encoder_helper_funcs *funcs =
>> > encoder->helper_private;
>> > +	struct drm_crtc *crtc = encoder->crtc;
>> > +
>> > +	/* Forward this enable call to the commit hook */
>> > +	if (funcs && funcs->commit)
>> > +		funcs->commit(encoder);
>> 
>> The purpose of this function is not clear. Where are we setting up the
>> inline rotator?
>> Why do we need a kickoff here?
> 
> The reason the code is shuffled is to avoid duplicating the entire 
> atomic
> helper
> function. By moving calls into the ->enable hooks, we can avoid having 
> to
> hand
> roll the helpers.
> 
> The kickoff is preserved from the helper copy when you call
> kms->funcs->commit
> in between the encoder enable and bridge enable. If this can be 
> removed,
> that'd
> be even better. I was simply trying to preserve the call order of
> everything.
> 
> Sean
I am with you on cleaning up the atomic helper copy. But using 
enc->commit helper
to call into encoder_enable doesn't look valid to me.

Also, I verified removing the kms->funcs->commit call between encoder 
enable and
bridge enable. It works fine with your newly placed kms->funcs->commit 
after
drm_atomic_helper_commit_modeset_enables. So can you revisit this 
function?

Jeykumar S
> 
>> > +
>> > +	if (crtc && crtc->state->active) {
>> > +		DPU_EVT32(DRMID(crtc));
>> > +		dpu_crtc_commit_kickoff(crtc);
>> > +	}
>> > +}
>> > +
>> > +static void dpu_kms_commit(struct msm_kms *kms, struct
> drm_atomic_state
>> > *state)
>> >  {
>> >  	struct drm_crtc *crtc;
>> > -	struct drm_crtc_state *old_crtc_state;
>> > +	struct drm_crtc_state *crtc_state;
>> > +	struct dpu_crtc_state *cstate;
>> >  	int i;
>> >
>> > -	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
>> > +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
>> > +		/* If modeset is required, kickoff is run in
>> > encoder_enable */
>> > +		if (drm_atomic_crtc_needs_modeset(crtc_state))
>> > +			continue;
>> > +
>> >  		if (crtc->state->active) {
>> >  			DPU_EVT32(DRMID(crtc));
>> >  			dpu_crtc_commit_kickoff(crtc);
>> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> > index 8cadd29a48b1..42c809ed9467 100644
>> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> > @@ -529,4 +529,6 @@ int dpu_kms_fbo_reference(struct dpu_kms_fbo
> *fbo);
>> >   */
>> >  void dpu_kms_fbo_unreference(struct dpu_kms_fbo *fbo);
>> >
>> > +void dpu_kms_encoder_enable(struct drm_encoder *encoder);
>> > +
>> >  #endif /* __dpu_kms_H__ */
>> > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
>> > b/drivers/gpu/drm/msm/msm_atomic.c
>> > index 5cfb80345052..f5794dce25dd 100644
>> > --- a/drivers/gpu/drm/msm/msm_atomic.c
>> > +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> > @@ -84,131 +84,6 @@ static void msm_atomic_wait_for_commit_done(
>> >  	}
>> >  }
>> >
>> > -/**
>> > - * msm_atomic_helper_commit_modeset_enables - modeset commit to
> enable
>> > outputs
>> > - * @dev: DRM device
>> > - * @old_state: atomic state object with old state structures
>> > - *
>> > - * This function enables all the outputs with the new configuration
>> > which
>> > had to
>> > - * be turned off for the update.
>> > - *
>> > - * For compatibility with legacy crtc helpers this should be called
>> > after
>> > - * drm_atomic_helper_commit_planes(), which is what the default
> commit
>> > function
>> > - * does. But drivers with different needs can group the modeset
> commits
>> > together
>> > - * and do the plane commits at the end. This is useful for drivers
>> > doing
>> > runtime
>> > - * PM since planes updates then only happen when the CRTC is actually
>> > enabled.
>> > - */
>> > -static void msm_atomic_helper_commit_modeset_enables(struct
> drm_device
>> > *dev,
>> > -		struct drm_atomic_state *old_state)
>> > -{
>> > -	struct drm_crtc *crtc;
>> > -	struct drm_crtc_state *old_crtc_state;
>> > -	struct drm_crtc_state *new_crtc_state;
>> > -	struct drm_connector *connector;
>> > -	struct drm_connector_state *new_conn_state;
>> > -	struct msm_drm_private *priv = dev->dev_private;
>> > -	struct msm_kms *kms = priv->kms;
>> > -	int bridge_enable_count = 0;
>> > -	int i;
>> > -
>> > -	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
>> > -			new_crtc_state, i) {
>> > -		const struct drm_crtc_helper_funcs *funcs;
>> > -
>> > -		/* Need to filter out CRTCs where only planes change. */
>> > -		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
>> > -			continue;
>> > -
>> > -		if (!new_crtc_state->active)
>> > -			continue;
>> > -
>> > -		if (msm_is_mode_seamless(&new_crtc_state->mode) ||
>> > -				msm_is_mode_seamless_vrr(
>> > -				&new_crtc_state->adjusted_mode))
>> > -			continue;
>> > -
>> > -		funcs = crtc->helper_private;
>> > -
>> > -		if (crtc->state->enable) {
>> > -			DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n",
>> > -					 crtc->base.id);
>> > -
>> > -			if (funcs->atomic_enable)
>> > -				funcs->atomic_enable(crtc,
>> > old_crtc_state);
>> > -			else
>> > -				funcs->commit(crtc);
>> > -		}
>> > -
>> > -		if (msm_needs_vblank_pre_modeset(
>> > -					&new_crtc_state->adjusted_mode))
>> > -			drm_crtc_wait_one_vblank(crtc);
>> > -	}
>> > -
>> > -	/* ensure bridge/encoder updates happen on same vblank */
>> > -	msm_atomic_wait_for_commit_done(dev, old_state);
>> > -
>> > -	for_each_new_connector_in_state(old_state, connector,
>> > -			new_conn_state, i) {
>> > -		const struct drm_encoder_helper_funcs *funcs;
>> > -		struct drm_encoder *encoder;
>> > -
>> > -		if (!new_conn_state->best_encoder)
>> > -			continue;
>> > -
>> > -		if (!new_conn_state->crtc->state->active ||
>> > -		    !drm_atomic_crtc_needs_modeset(
>> > -			    new_conn_state->crtc->state))
>> > -			continue;
>> > -
>> > -		encoder = new_conn_state->best_encoder;
>> > -		funcs = encoder->helper_private;
>> > -
>> > -		DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
>> > -				 encoder->base.id, encoder->name);
>> > -
>> > -		/*
>> > -		 * Each encoder has at most one connector (since we always
>> > steal
>> > -		 * it away), so we won't call enable hooks twice.
>> > -		 */
>> > -		drm_bridge_pre_enable(encoder->bridge);
>> > -		++bridge_enable_count;
>> > -
>> > -		if (funcs->enable)
>> > -			funcs->enable(encoder);
>> > -		else
>> > -			funcs->commit(encoder);
>> > -	}
>> > -
>> > -	if (kms->funcs->commit) {
>> > -		DRM_DEBUG_ATOMIC("triggering commit\n");
>> > -		kms->funcs->commit(kms, old_state);
>> > -	}
>> > -
>> > -	/* If no bridges were pre_enabled, skip iterating over them again
>> > */
>> > -	if (bridge_enable_count == 0)
>> > -		return;
>> > -
>> > -	for_each_new_connector_in_state(old_state, connector,
>> > -			new_conn_state, i) {
>> > -		struct drm_encoder *encoder;
>> > -
>> > -		if (!new_conn_state->best_encoder)
>> > -			continue;
>> > -
>> > -		if (!new_conn_state->crtc->state->active ||
>> > -		    !drm_atomic_crtc_needs_modeset(
>> > -				    new_conn_state->crtc->state))
>> > -			continue;
>> > -
>> > -		encoder = new_conn_state->best_encoder;
>> > -
>> > -		DRM_DEBUG_ATOMIC("bridge enable enabling
>> > [ENCODER:%d:%s]\n",
>> > -				 encoder->base.id, encoder->name);
>> > -
>> > -		drm_bridge_enable(encoder->bridge);
>> > -	}
>> > -}
>> > -
>> >  /* The (potentially) asynchronous part of the commit.  At this point
>> >   * nothing can fail short of armageddon.
>> >   */
>> > @@ -227,7 +102,12 @@ static void complete_commit(struct msm_commit *c)
>> >
>> >  	drm_atomic_helper_commit_planes(dev, state, 0);
>> >
>> > -	msm_atomic_helper_commit_modeset_enables(dev, state);
>> > +	drm_atomic_helper_commit_modeset_enables(dev, state);
>> > +
>> > +	if (kms->funcs->commit) {
>> > +		DRM_DEBUG_ATOMIC("triggering commit\n");
>> > +		kms->funcs->commit(kms, state);
>> > +	}
>> >
>> >  	/* NOTE: _wait_for_vblanks() only waits for vblank on
>> >  	 * enabled CRTCs.  So we end up faulting when disabling
>> 
>> --
>> Jeykumar S

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 02/11] drm/msm: Don't duplicate modeset_enables atomic helper
       [not found]               ` <677c8c29a788a147aa45bc1e9768527e-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-03-14 15:14                 ` Sean Paul
  2018-03-15  1:39                   ` Jeykumar Sankaran
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-14 15:14 UTC (permalink / raw)
  To: Jeykumar Sankaran
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, Sean Paul,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On Tue, Mar 13, 2018 at 04:57:35PM -0700, Jeykumar Sankaran wrote:
> On 2018-03-12 13:21, Sean Paul wrote:
> > On Thu, Mar 08, 2018 at 04:56:01PM -0800, Jeykumar Sankaran wrote:
> > > On 2018-02-28 11:18, Sean Paul wrote:
> > > > Instead, shuffle things around so we kickoff crtc after enabling
> > encoder
> > > > during modesets. Also moves the vblank wait to after the frame.
> > > >
> > > > Change-Id: I16c7b7f9390d04f6050aa20e17a5335fbf49eba3
> > > > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > > > ---
> > > >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   9 ++
> > > >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   5 +-
> > > >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c     |  31 ++++-
> > > >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |   2 +
> > > >  drivers/gpu/drm/msm/msm_atomic.c            | 132
> > +-------------------
> > > >  5 files changed, 48 insertions(+), 131 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > index a3ab6ed2bf1d..94fab2dcca5b 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > @@ -3525,6 +3525,12 @@ static void dpu_crtc_enable(struct drm_crtc
> > > > *crtc,
> > > >  	DPU_EVT32_VERBOSE(DRMID(crtc));
> > > >  	dpu_crtc = to_dpu_crtc(crtc);
> > > >
> > > > +	if (msm_is_mode_seamless(&crtc->state->adjusted_mode) ||
> > > > +	    msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode)) {
> > > > +		DPU_DEBUG("Skipping crtc enable, seamless mode\n");
> > > > +		return;
> > > > +	}
> > > > +
> > > >  	pm_runtime_get_sync(crtc->dev->dev);
> > > >
> > > >  	drm_for_each_encoder(encoder, crtc->dev) {
> > > > @@ -3572,6 +3578,9 @@ static void dpu_crtc_enable(struct drm_crtc
> > *crtc,
> > > >  		DPU_POWER_EVENT_POST_ENABLE | DPU_POWER_EVENT_POST_DISABLE
> > > > |
> > > >  		DPU_POWER_EVENT_PRE_DISABLE,
> > > >  		dpu_crtc_handle_power_event, crtc, dpu_crtc->name);
> > > > +
> > > > +	if (msm_needs_vblank_pre_modeset(&crtc->state->adjusted_mode))
> > > > +		drm_crtc_wait_one_vblank(crtc);
> > > >  }
> > > >
> > > >  struct plane_state {
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > index 28ceb589ee40..4d1e3652dbf4 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > @@ -3693,8 +3693,11 @@ static void
> > dpu_encoder_frame_done_timeout(struct
> > > > timer_list *t)
> > > >  static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs
> > =
> > > > {
> > > >  	.mode_set = dpu_encoder_virt_mode_set,
> > > >  	.disable = dpu_encoder_virt_disable,
> > > > -	.enable = dpu_encoder_virt_enable,
> > > > +	.enable = dpu_kms_encoder_enable,
> > > >  	.atomic_check = dpu_encoder_virt_atomic_check,
> > > > +
> > > > +	/* This is called by dpu_kms_encoder_enable */
> > > > +	.commit = dpu_encoder_virt_enable,
> > > >  };
> > > >
> > > >  static const struct drm_encoder_funcs dpu_encoder_funcs = {
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > > > index 81fd3a429e9f..3d83037e8305 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> > > > @@ -425,14 +425,37 @@ static void dpu_kms_prepare_commit(struct
> > msm_kms
> > > > *kms,
> > > >  			dpu_encoder_prepare_commit(encoder);
> > > >  }
> > > >
> > > > -static void dpu_kms_commit(struct msm_kms *kms,
> > > > -		struct drm_atomic_state *old_state)
> > > > +/*
> > > > + * Override the encoder enable since we need to setup the inline
> > > > rotator
> > > > and do
> > > > + * some crtc magic before enabling any bridge that might be present.
> > > > + */
> > > > +void dpu_kms_encoder_enable(struct drm_encoder *encoder)
> > > > +{
> > > > +	const struct drm_encoder_helper_funcs *funcs =
> > > > encoder->helper_private;
> > > > +	struct drm_crtc *crtc = encoder->crtc;
> > > > +
> > > > +	/* Forward this enable call to the commit hook */
> > > > +	if (funcs && funcs->commit)
> > > > +		funcs->commit(encoder);
> > > 
> > > The purpose of this function is not clear. Where are we setting up the
> > > inline rotator?
> > > Why do we need a kickoff here?
> > 
> > The reason the code is shuffled is to avoid duplicating the entire
> > atomic
> > helper
> > function. By moving calls into the ->enable hooks, we can avoid having
> > to
> > hand
> > roll the helpers.
> > 
> > The kickoff is preserved from the helper copy when you call
> > kms->funcs->commit
> > in between the encoder enable and bridge enable. If this can be removed,
> > that'd
> > be even better. I was simply trying to preserve the call order of
> > everything.
> > 
> > Sean
> I am with you on cleaning up the atomic helper copy. But using enc->commit
> helper
> to call into encoder_enable doesn't look valid to me.

"doesn't look valid to me" doesn't give me much to go on. Could you please
explain why it doesn't look valid to you?

> 
> Also, I verified removing the kms->funcs->commit call between encoder enable
> and
> bridge enable. It works fine with your newly placed kms->funcs->commit after
> drm_atomic_helper_commit_modeset_enables. So can you revisit this function?

Hmm, do you know why it was there in the first place? It seems like this was the
primary reason for copy/pasting the whole function, so it probably wasn't done
for nothing, it'd be nice to have some history on that.

Presumably you needed to remove the needs_modeset check as well?

Sean

> 
> Jeykumar S
> > 
> > > > +
> > > > +	if (crtc && crtc->state->active) {
> > > > +		DPU_EVT32(DRMID(crtc));
> > > > +		dpu_crtc_commit_kickoff(crtc);
> > > > +	}
> > > > +}
> > > > +
> > > > +static void dpu_kms_commit(struct msm_kms *kms, struct
> > drm_atomic_state
> > > > *state)
> > > >  {
> > > >  	struct drm_crtc *crtc;
> > > > -	struct drm_crtc_state *old_crtc_state;
> > > > +	struct drm_crtc_state *crtc_state;
> > > > +	struct dpu_crtc_state *cstate;
> > > >  	int i;
> > > >
> > > > -	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
> > > > +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> > > > +		/* If modeset is required, kickoff is run in
> > > > encoder_enable */
> > > > +		if (drm_atomic_crtc_needs_modeset(crtc_state))
> > > > +			continue;
> > > > +
> > > >  		if (crtc->state->active) {
> > > >  			DPU_EVT32(DRMID(crtc));
> > > >  			dpu_crtc_commit_kickoff(crtc);
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > index 8cadd29a48b1..42c809ed9467 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > @@ -529,4 +529,6 @@ int dpu_kms_fbo_reference(struct dpu_kms_fbo
> > *fbo);
> > > >   */
> > > >  void dpu_kms_fbo_unreference(struct dpu_kms_fbo *fbo);
> > > >
> > > > +void dpu_kms_encoder_enable(struct drm_encoder *encoder);
> > > > +
> > > >  #endif /* __dpu_kms_H__ */
> > > > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> > > > b/drivers/gpu/drm/msm/msm_atomic.c
> > > > index 5cfb80345052..f5794dce25dd 100644
> > > > --- a/drivers/gpu/drm/msm/msm_atomic.c
> > > > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> > > > @@ -84,131 +84,6 @@ static void msm_atomic_wait_for_commit_done(
> > > >  	}
> > > >  }
> > > >
> > > > -/**
> > > > - * msm_atomic_helper_commit_modeset_enables - modeset commit to
> > enable
> > > > outputs
> > > > - * @dev: DRM device
> > > > - * @old_state: atomic state object with old state structures
> > > > - *
> > > > - * This function enables all the outputs with the new configuration
> > > > which
> > > > had to
> > > > - * be turned off for the update.
> > > > - *
> > > > - * For compatibility with legacy crtc helpers this should be called
> > > > after
> > > > - * drm_atomic_helper_commit_planes(), which is what the default
> > commit
> > > > function
> > > > - * does. But drivers with different needs can group the modeset
> > commits
> > > > together
> > > > - * and do the plane commits at the end. This is useful for drivers
> > > > doing
> > > > runtime
> > > > - * PM since planes updates then only happen when the CRTC is actually
> > > > enabled.
> > > > - */
> > > > -static void msm_atomic_helper_commit_modeset_enables(struct
> > drm_device
> > > > *dev,
> > > > -		struct drm_atomic_state *old_state)
> > > > -{
> > > > -	struct drm_crtc *crtc;
> > > > -	struct drm_crtc_state *old_crtc_state;
> > > > -	struct drm_crtc_state *new_crtc_state;
> > > > -	struct drm_connector *connector;
> > > > -	struct drm_connector_state *new_conn_state;
> > > > -	struct msm_drm_private *priv = dev->dev_private;
> > > > -	struct msm_kms *kms = priv->kms;
> > > > -	int bridge_enable_count = 0;
> > > > -	int i;
> > > > -
> > > > -	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
> > > > -			new_crtc_state, i) {
> > > > -		const struct drm_crtc_helper_funcs *funcs;
> > > > -
> > > > -		/* Need to filter out CRTCs where only planes change. */
> > > > -		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
> > > > -			continue;
> > > > -
> > > > -		if (!new_crtc_state->active)
> > > > -			continue;
> > > > -
> > > > -		if (msm_is_mode_seamless(&new_crtc_state->mode) ||
> > > > -				msm_is_mode_seamless_vrr(
> > > > -				&new_crtc_state->adjusted_mode))
> > > > -			continue;
> > > > -
> > > > -		funcs = crtc->helper_private;
> > > > -
> > > > -		if (crtc->state->enable) {
> > > > -			DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n",
> > > > -					 crtc->base.id);
> > > > -
> > > > -			if (funcs->atomic_enable)
> > > > -				funcs->atomic_enable(crtc,
> > > > old_crtc_state);
> > > > -			else
> > > > -				funcs->commit(crtc);
> > > > -		}
> > > > -
> > > > -		if (msm_needs_vblank_pre_modeset(
> > > > -					&new_crtc_state->adjusted_mode))
> > > > -			drm_crtc_wait_one_vblank(crtc);
> > > > -	}
> > > > -
> > > > -	/* ensure bridge/encoder updates happen on same vblank */
> > > > -	msm_atomic_wait_for_commit_done(dev, old_state);
> > > > -
> > > > -	for_each_new_connector_in_state(old_state, connector,
> > > > -			new_conn_state, i) {
> > > > -		const struct drm_encoder_helper_funcs *funcs;
> > > > -		struct drm_encoder *encoder;
> > > > -
> > > > -		if (!new_conn_state->best_encoder)
> > > > -			continue;
> > > > -
> > > > -		if (!new_conn_state->crtc->state->active ||
> > > > -		    !drm_atomic_crtc_needs_modeset(
> > > > -			    new_conn_state->crtc->state))
> > > > -			continue;
> > > > -
> > > > -		encoder = new_conn_state->best_encoder;
> > > > -		funcs = encoder->helper_private;
> > > > -
> > > > -		DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
> > > > -				 encoder->base.id, encoder->name);
> > > > -
> > > > -		/*
> > > > -		 * Each encoder has at most one connector (since we always
> > > > steal
> > > > -		 * it away), so we won't call enable hooks twice.
> > > > -		 */
> > > > -		drm_bridge_pre_enable(encoder->bridge);
> > > > -		++bridge_enable_count;
> > > > -
> > > > -		if (funcs->enable)
> > > > -			funcs->enable(encoder);
> > > > -		else
> > > > -			funcs->commit(encoder);
> > > > -	}
> > > > -
> > > > -	if (kms->funcs->commit) {
> > > > -		DRM_DEBUG_ATOMIC("triggering commit\n");
> > > > -		kms->funcs->commit(kms, old_state);
> > > > -	}
> > > > -
> > > > -	/* If no bridges were pre_enabled, skip iterating over them again
> > > > */
> > > > -	if (bridge_enable_count == 0)
> > > > -		return;
> > > > -
> > > > -	for_each_new_connector_in_state(old_state, connector,
> > > > -			new_conn_state, i) {
> > > > -		struct drm_encoder *encoder;
> > > > -
> > > > -		if (!new_conn_state->best_encoder)
> > > > -			continue;
> > > > -
> > > > -		if (!new_conn_state->crtc->state->active ||
> > > > -		    !drm_atomic_crtc_needs_modeset(
> > > > -				    new_conn_state->crtc->state))
> > > > -			continue;
> > > > -
> > > > -		encoder = new_conn_state->best_encoder;
> > > > -
> > > > -		DRM_DEBUG_ATOMIC("bridge enable enabling
> > > > [ENCODER:%d:%s]\n",
> > > > -				 encoder->base.id, encoder->name);
> > > > -
> > > > -		drm_bridge_enable(encoder->bridge);
> > > > -	}
> > > > -}
> > > > -
> > > >  /* The (potentially) asynchronous part of the commit.  At this point
> > > >   * nothing can fail short of armageddon.
> > > >   */
> > > > @@ -227,7 +102,12 @@ static void complete_commit(struct msm_commit *c)
> > > >
> > > >  	drm_atomic_helper_commit_planes(dev, state, 0);
> > > >
> > > > -	msm_atomic_helper_commit_modeset_enables(dev, state);
> > > > +	drm_atomic_helper_commit_modeset_enables(dev, state);
> > > > +
> > > > +	if (kms->funcs->commit) {
> > > > +		DRM_DEBUG_ATOMIC("triggering commit\n");
> > > > +		kms->funcs->commit(kms, state);
> > > > +	}
> > > >
> > > >  	/* NOTE: _wait_for_vblanks() only waits for vblank on
> > > >  	 * enabled CRTCs.  So we end up faulting when disabling
> > > 
> > > --
> > > Jeykumar S
> 
> -- 
> Jeykumar S

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 02/11] drm/msm: Don't duplicate modeset_enables atomic helper
  2018-03-14 15:14                 ` Sean Paul
@ 2018-03-15  1:39                   ` Jeykumar Sankaran
       [not found]                     ` <645777c3f76662ce5b0b14bcf7b81acb-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-15  1:39 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-03-14 08:14, Sean Paul wrote:
> On Tue, Mar 13, 2018 at 04:57:35PM -0700, Jeykumar Sankaran wrote:
>> On 2018-03-12 13:21, Sean Paul wrote:
>> > On Thu, Mar 08, 2018 at 04:56:01PM -0800, Jeykumar Sankaran wrote:
>> > > On 2018-02-28 11:18, Sean Paul wrote:
>> > > > Instead, shuffle things around so we kickoff crtc after enabling
>> > encoder
>> > > > during modesets. Also moves the vblank wait to after the frame.
>> > > >
>> > > > Change-Id: I16c7b7f9390d04f6050aa20e17a5335fbf49eba3
>> > > > Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> > > > ---
>> > > >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    |   9 ++
>> > > >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |   5 +-
>> > > >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c     |  31 ++++-
>> > > >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |   2 +
>> > > >  drivers/gpu/drm/msm/msm_atomic.c            | 132
>> > +-------------------
>> > > >  5 files changed, 48 insertions(+), 131 deletions(-)
>> > > >
>> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > > > index a3ab6ed2bf1d..94fab2dcca5b 100644
>> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> > > > @@ -3525,6 +3525,12 @@ static void dpu_crtc_enable(struct drm_crtc
>> > > > *crtc,
>> > > >  	DPU_EVT32_VERBOSE(DRMID(crtc));
>> > > >  	dpu_crtc = to_dpu_crtc(crtc);
>> > > >
>> > > > +	if (msm_is_mode_seamless(&crtc->state->adjusted_mode) ||
>> > > > +	    msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode))
> {
>> > > > +		DPU_DEBUG("Skipping crtc enable, seamless
> mode\n");
>> > > > +		return;
>> > > > +	}
>> > > > +
>> > > >  	pm_runtime_get_sync(crtc->dev->dev);
>> > > >
>> > > >  	drm_for_each_encoder(encoder, crtc->dev) {
>> > > > @@ -3572,6 +3578,9 @@ static void dpu_crtc_enable(struct drm_crtc
>> > *crtc,
>> > > >  		DPU_POWER_EVENT_POST_ENABLE |
> DPU_POWER_EVENT_POST_DISABLE
>> > > > |
>> > > >  		DPU_POWER_EVENT_PRE_DISABLE,
>> > > >  		dpu_crtc_handle_power_event, crtc,
> dpu_crtc->name);
>> > > > +
>> > > > +	if
> (msm_needs_vblank_pre_modeset(&crtc->state->adjusted_mode))
>> > > > +		drm_crtc_wait_one_vblank(crtc);
>> > > >  }
>> > > >
>> > > >  struct plane_state {
>> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > > > index 28ceb589ee40..4d1e3652dbf4 100644
>> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> > > > @@ -3693,8 +3693,11 @@ static void
>> > dpu_encoder_frame_done_timeout(struct
>> > > > timer_list *t)
>> > > >  static const struct drm_encoder_helper_funcs
> dpu_encoder_helper_funcs
>> > =
>> > > > {
>> > > >  	.mode_set = dpu_encoder_virt_mode_set,
>> > > >  	.disable = dpu_encoder_virt_disable,
>> > > > -	.enable = dpu_encoder_virt_enable,
>> > > > +	.enable = dpu_kms_encoder_enable,
>> > > >  	.atomic_check = dpu_encoder_virt_atomic_check,
>> > > > +
>> > > > +	/* This is called by dpu_kms_encoder_enable */
>> > > > +	.commit = dpu_encoder_virt_enable,
>> > > >  };
>> > > >
>> > > >  static const struct drm_encoder_funcs dpu_encoder_funcs = {
>> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > > > index 81fd3a429e9f..3d83037e8305 100644
>> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> > > > @@ -425,14 +425,37 @@ static void dpu_kms_prepare_commit(struct
>> > msm_kms
>> > > > *kms,
>> > > >  			dpu_encoder_prepare_commit(encoder);
>> > > >  }
>> > > >
>> > > > -static void dpu_kms_commit(struct msm_kms *kms,
>> > > > -		struct drm_atomic_state *old_state)
>> > > > +/*
>> > > > + * Override the encoder enable since we need to setup the inline
>> > > > rotator
>> > > > and do
>> > > > + * some crtc magic before enabling any bridge that might be
> present.
>> > > > + */
>> > > > +void dpu_kms_encoder_enable(struct drm_encoder *encoder)
>> > > > +{
>> > > > +	const struct drm_encoder_helper_funcs *funcs =
>> > > > encoder->helper_private;
>> > > > +	struct drm_crtc *crtc = encoder->crtc;
>> > > > +
>> > > > +	/* Forward this enable call to the commit hook */
>> > > > +	if (funcs && funcs->commit)
>> > > > +		funcs->commit(encoder);
>> > >
>> > > The purpose of this function is not clear. Where are we setting up
> the
>> > > inline rotator?
>> > > Why do we need a kickoff here?
>> >
>> > The reason the code is shuffled is to avoid duplicating the entire
>> > atomic
>> > helper
>> > function. By moving calls into the ->enable hooks, we can avoid having
>> > to
>> > hand
>> > roll the helpers.
>> >
>> > The kickoff is preserved from the helper copy when you call
>> > kms->funcs->commit
>> > in between the encoder enable and bridge enable. If this can be
> removed,
>> > that'd
>> > be even better. I was simply trying to preserve the call order of
>> > everything.
>> >
>> > Sean
>> I am with you on cleaning up the atomic helper copy. But using
> enc->commit
>> helper
>> to call into encoder_enable doesn't look valid to me.
> 
> "doesn't look valid to me" doesn't give me much to go on. Could you 
> please
> explain why it doesn't look valid to you?
> 
The description in drm_modeset_helper_vtables.h says using enc->commit 
hook for enabling the
encoder is a deprecated method. Also, since we have an option to get rid 
of this
extra kms->funcs->commit (for which we needed this loop around in first 
place), we
can stick with the enc->enable hook itself.
>> 
>> Also, I verified removing the kms->funcs->commit call between encoder
> enable
>> and
>> bridge enable. It works fine with your newly placed kms->funcs->commit
> after
>> drm_atomic_helper_commit_modeset_enables. So can you revisit this
> function?
> 
> Hmm, do you know why it was there in the first place? It seems like 
> this
> was the
> primary reason for copy/pasting the whole function, so it probably 
> wasn't
> done
> for nothing, it'd be nice to have some history on that.
> 
h/w programming sequence differs between DPU and MDP5. MDP5 triggers the
frame kickoff in crtc->flush hook. But actual frame transfer starts only
in encoder->enable where we turn on the interface timing engine and 
trigger
the CTL flush again(!). In DPU, we enable all the hw blocks associated 
with
the encoder before triggering the frame kickoff. So a new hook, 
kms->commit was
introduced to kickoff the frame after all the components are enabled. 
Since you
are moving the kms->funcs->commit after modeset_enables, we are already 
taking
care of the order.

As an alternative, I see drm_atomic_helper_commit_tail_rpm changing the 
order
of crtc->flush / enc->enable helper calls for drivers using runtime_pm. 
If we
can take care of triggering frames from crtc->flush (as MDP5 does), we 
can even get
rid of kms->funcs->commit and adapt more helpers. But that's for the 
future
patches!

> Presumably you needed to remove the needs_modeset check as well?
> 
Yes.
> Sean
> 
>> 
>> Jeykumar S
>> >
>> > > > +
>> > > > +	if (crtc && crtc->state->active) {
>> > > > +		DPU_EVT32(DRMID(crtc));
>> > > > +		dpu_crtc_commit_kickoff(crtc);
>> > > > +	}
>> > > > +}
>> > > > +
>> > > > +static void dpu_kms_commit(struct msm_kms *kms, struct
>> > drm_atomic_state
>> > > > *state)
>> > > >  {
>> > > >  	struct drm_crtc *crtc;
>> > > > -	struct drm_crtc_state *old_crtc_state;
>> > > > +	struct drm_crtc_state *crtc_state;
>> > > > +	struct dpu_crtc_state *cstate;
>> > > >  	int i;
>> > > >
>> > > > -	for_each_old_crtc_in_state(old_state, crtc,
> old_crtc_state, i) {
>> > > > +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
>> > > > +		/* If modeset is required, kickoff is run in
>> > > > encoder_enable */
>> > > > +		if (drm_atomic_crtc_needs_modeset(crtc_state))
>> > > > +			continue;
>> > > > +
>> > > >  		if (crtc->state->active) {
>> > > >  			DPU_EVT32(DRMID(crtc));
>> > > >  			dpu_crtc_commit_kickoff(crtc);
>> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> > > > b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> > > > index 8cadd29a48b1..42c809ed9467 100644
>> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> > > > @@ -529,4 +529,6 @@ int dpu_kms_fbo_reference(struct dpu_kms_fbo
>> > *fbo);
>> > > >   */
>> > > >  void dpu_kms_fbo_unreference(struct dpu_kms_fbo *fbo);
>> > > >
>> > > > +void dpu_kms_encoder_enable(struct drm_encoder *encoder);
>> > > > +
>> > > >  #endif /* __dpu_kms_H__ */
>> > > > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
>> > > > b/drivers/gpu/drm/msm/msm_atomic.c
>> > > > index 5cfb80345052..f5794dce25dd 100644
>> > > > --- a/drivers/gpu/drm/msm/msm_atomic.c
>> > > > +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> > > > @@ -84,131 +84,6 @@ static void msm_atomic_wait_for_commit_done(
>> > > >  	}
>> > > >  }
>> > > >
>> > > > -/**
>> > > > - * msm_atomic_helper_commit_modeset_enables - modeset commit to
>> > enable
>> > > > outputs
>> > > > - * @dev: DRM device
>> > > > - * @old_state: atomic state object with old state structures
>> > > > - *
>> > > > - * This function enables all the outputs with the new
> configuration
>> > > > which
>> > > > had to
>> > > > - * be turned off for the update.
>> > > > - *
>> > > > - * For compatibility with legacy crtc helpers this should be
> called
>> > > > after
>> > > > - * drm_atomic_helper_commit_planes(), which is what the default
>> > commit
>> > > > function
>> > > > - * does. But drivers with different needs can group the modeset
>> > commits
>> > > > together
>> > > > - * and do the plane commits at the end. This is useful for
> drivers
>> > > > doing
>> > > > runtime
>> > > > - * PM since planes updates then only happen when the CRTC is
> actually
>> > > > enabled.
>> > > > - */
>> > > > -static void msm_atomic_helper_commit_modeset_enables(struct
>> > drm_device
>> > > > *dev,
>> > > > -		struct drm_atomic_state *old_state)
>> > > > -{
>> > > > -	struct drm_crtc *crtc;
>> > > > -	struct drm_crtc_state *old_crtc_state;
>> > > > -	struct drm_crtc_state *new_crtc_state;
>> > > > -	struct drm_connector *connector;
>> > > > -	struct drm_connector_state *new_conn_state;
>> > > > -	struct msm_drm_private *priv = dev->dev_private;
>> > > > -	struct msm_kms *kms = priv->kms;
>> > > > -	int bridge_enable_count = 0;
>> > > > -	int i;
>> > > > -
>> > > > -	for_each_oldnew_crtc_in_state(old_state, crtc,
> old_crtc_state,
>> > > > -			new_crtc_state, i) {
>> > > > -		const struct drm_crtc_helper_funcs *funcs;
>> > > > -
>> > > > -		/* Need to filter out CRTCs where only planes
> change. */
>> > > > -		if
> (!drm_atomic_crtc_needs_modeset(new_crtc_state))
>> > > > -			continue;
>> > > > -
>> > > > -		if (!new_crtc_state->active)
>> > > > -			continue;
>> > > > -
>> > > > -		if (msm_is_mode_seamless(&new_crtc_state->mode) ||
>> > > > -				msm_is_mode_seamless_vrr(
>> > > > -				&new_crtc_state->adjusted_mode))
>> > > > -			continue;
>> > > > -
>> > > > -		funcs = crtc->helper_private;
>> > > > -
>> > > > -		if (crtc->state->enable) {
>> > > > -			DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n",
>> > > > -					 crtc->base.id);
>> > > > -
>> > > > -			if (funcs->atomic_enable)
>> > > > -				funcs->atomic_enable(crtc,
>> > > > old_crtc_state);
>> > > > -			else
>> > > > -				funcs->commit(crtc);
>> > > > -		}
>> > > > -
>> > > > -		if (msm_needs_vblank_pre_modeset(
>> > > > -
> &new_crtc_state->adjusted_mode))
>> > > > -			drm_crtc_wait_one_vblank(crtc);
>> > > > -	}
>> > > > -
>> > > > -	/* ensure bridge/encoder updates happen on same vblank */
>> > > > -	msm_atomic_wait_for_commit_done(dev, old_state);
>> > > > -
>> > > > -	for_each_new_connector_in_state(old_state, connector,
>> > > > -			new_conn_state, i) {
>> > > > -		const struct drm_encoder_helper_funcs *funcs;
>> > > > -		struct drm_encoder *encoder;
>> > > > -
>> > > > -		if (!new_conn_state->best_encoder)
>> > > > -			continue;
>> > > > -
>> > > > -		if (!new_conn_state->crtc->state->active ||
>> > > > -		    !drm_atomic_crtc_needs_modeset(
>> > > > -			    new_conn_state->crtc->state))
>> > > > -			continue;
>> > > > -
>> > > > -		encoder = new_conn_state->best_encoder;
>> > > > -		funcs = encoder->helper_private;
>> > > > -
>> > > > -		DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
>> > > > -				 encoder->base.id, encoder->name);
>> > > > -
>> > > > -		/*
>> > > > -		 * Each encoder has at most one connector (since
> we always
>> > > > steal
>> > > > -		 * it away), so we won't call enable hooks twice.
>> > > > -		 */
>> > > > -		drm_bridge_pre_enable(encoder->bridge);
>> > > > -		++bridge_enable_count;
>> > > > -
>> > > > -		if (funcs->enable)
>> > > > -			funcs->enable(encoder);
>> > > > -		else
>> > > > -			funcs->commit(encoder);
>> > > > -	}
>> > > > -
>> > > > -	if (kms->funcs->commit) {
>> > > > -		DRM_DEBUG_ATOMIC("triggering commit\n");
>> > > > -		kms->funcs->commit(kms, old_state);
>> > > > -	}
>> > > > -
>> > > > -	/* If no bridges were pre_enabled, skip iterating over
> them again
>> > > > */
>> > > > -	if (bridge_enable_count == 0)
>> > > > -		return;
>> > > > -
>> > > > -	for_each_new_connector_in_state(old_state, connector,
>> > > > -			new_conn_state, i) {
>> > > > -		struct drm_encoder *encoder;
>> > > > -
>> > > > -		if (!new_conn_state->best_encoder)
>> > > > -			continue;
>> > > > -
>> > > > -		if (!new_conn_state->crtc->state->active ||
>> > > > -		    !drm_atomic_crtc_needs_modeset(
>> > > > -				    new_conn_state->crtc->state))
>> > > > -			continue;
>> > > > -
>> > > > -		encoder = new_conn_state->best_encoder;
>> > > > -
>> > > > -		DRM_DEBUG_ATOMIC("bridge enable enabling
>> > > > [ENCODER:%d:%s]\n",
>> > > > -				 encoder->base.id, encoder->name);
>> > > > -
>> > > > -		drm_bridge_enable(encoder->bridge);
>> > > > -	}
>> > > > -}
>> > > > -
>> > > >  /* The (potentially) asynchronous part of the commit.  At this
> point
>> > > >   * nothing can fail short of armageddon.
>> > > >   */
>> > > > @@ -227,7 +102,12 @@ static void complete_commit(struct msm_commit
> *c)
>> > > >
>> > > >  	drm_atomic_helper_commit_planes(dev, state, 0);
>> > > >
>> > > > -	msm_atomic_helper_commit_modeset_enables(dev, state);
>> > > > +	drm_atomic_helper_commit_modeset_enables(dev, state);
>> > > > +
>> > > > +	if (kms->funcs->commit) {
>> > > > +		DRM_DEBUG_ATOMIC("triggering commit\n");
>> > > > +		kms->funcs->commit(kms, state);
>> > > > +	}
>> > > >
>> > > >  	/* NOTE: _wait_for_vblanks() only waits for vblank on
>> > > >  	 * enabled CRTCs.  So we end up faulting when disabling
>> > >
>> > > --
>> > > Jeykumar S
>> 
>> --
>> Jeykumar S

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [DPU PATCH v2] drm/msm: Don't duplicate modeset_enables atomic helper
       [not found]                     ` <645777c3f76662ce5b0b14bcf7b81acb-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-03-16 19:45                       ` Sean Paul
  2018-03-16 20:57                         ` Jeykumar Sankaran
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-16 19:45 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Instead, shuffle things around so we kickoff crtc after enabling encoder
during modesets. Also moves the vblank wait to after the frame.

Changes in v2:
- Remove the encoder.commit hack, it's not required (Jeykumar)

Cc: Jeykumar Sankaran <jsanka@codeaurora.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c |   9 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c  |   8 +-
 drivers/gpu/drm/msm/msm_atomic.c         | 132 ++---------------------
 3 files changed, 19 insertions(+), 130 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index a3ab6ed2bf1d..94fab2dcca5b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -3525,6 +3525,12 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
 	DPU_EVT32_VERBOSE(DRMID(crtc));
 	dpu_crtc = to_dpu_crtc(crtc);
 
+	if (msm_is_mode_seamless(&crtc->state->adjusted_mode) ||
+	    msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode)) {
+		DPU_DEBUG("Skipping crtc enable, seamless mode\n");
+		return;
+	}
+
 	pm_runtime_get_sync(crtc->dev->dev);
 
 	drm_for_each_encoder(encoder, crtc->dev) {
@@ -3572,6 +3578,9 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
 		DPU_POWER_EVENT_POST_ENABLE | DPU_POWER_EVENT_POST_DISABLE |
 		DPU_POWER_EVENT_PRE_DISABLE,
 		dpu_crtc_handle_power_event, crtc, dpu_crtc->name);
+
+	if (msm_needs_vblank_pre_modeset(&crtc->state->adjusted_mode))
+		drm_crtc_wait_one_vblank(crtc);
 }
 
 struct plane_state {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 5ba345395b82..2c4c7fe1affe 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -422,14 +422,14 @@ static void dpu_kms_prepare_commit(struct msm_kms *kms,
 			dpu_encoder_prepare_commit(encoder);
 }
 
-static void dpu_kms_commit(struct msm_kms *kms,
-		struct drm_atomic_state *old_state)
+static void dpu_kms_commit(struct msm_kms *kms, struct drm_atomic_state *state)
 {
 	struct drm_crtc *crtc;
-	struct drm_crtc_state *old_crtc_state;
+	struct drm_crtc_state *crtc_state;
+	struct dpu_crtc_state *cstate;
 	int i;
 
-	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
 		if (crtc->state->active) {
 			DPU_EVT32(DRMID(crtc));
 			dpu_crtc_commit_kickoff(crtc);
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 5cfb80345052..f5794dce25dd 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -84,131 +84,6 @@ static void msm_atomic_wait_for_commit_done(
 	}
 }
 
-/**
- * msm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs
- * @dev: DRM device
- * @old_state: atomic state object with old state structures
- *
- * This function enables all the outputs with the new configuration which had to
- * be turned off for the update.
- *
- * For compatibility with legacy crtc helpers this should be called after
- * drm_atomic_helper_commit_planes(), which is what the default commit function
- * does. But drivers with different needs can group the modeset commits together
- * and do the plane commits at the end. This is useful for drivers doing runtime
- * PM since planes updates then only happen when the CRTC is actually enabled.
- */
-static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
-		struct drm_atomic_state *old_state)
-{
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *old_crtc_state;
-	struct drm_crtc_state *new_crtc_state;
-	struct drm_connector *connector;
-	struct drm_connector_state *new_conn_state;
-	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_kms *kms = priv->kms;
-	int bridge_enable_count = 0;
-	int i;
-
-	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
-			new_crtc_state, i) {
-		const struct drm_crtc_helper_funcs *funcs;
-
-		/* Need to filter out CRTCs where only planes change. */
-		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
-			continue;
-
-		if (!new_crtc_state->active)
-			continue;
-
-		if (msm_is_mode_seamless(&new_crtc_state->mode) ||
-				msm_is_mode_seamless_vrr(
-				&new_crtc_state->adjusted_mode))
-			continue;
-
-		funcs = crtc->helper_private;
-
-		if (crtc->state->enable) {
-			DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n",
-					 crtc->base.id);
-
-			if (funcs->atomic_enable)
-				funcs->atomic_enable(crtc, old_crtc_state);
-			else
-				funcs->commit(crtc);
-		}
-
-		if (msm_needs_vblank_pre_modeset(
-					&new_crtc_state->adjusted_mode))
-			drm_crtc_wait_one_vblank(crtc);
-	}
-
-	/* ensure bridge/encoder updates happen on same vblank */
-	msm_atomic_wait_for_commit_done(dev, old_state);
-
-	for_each_new_connector_in_state(old_state, connector,
-			new_conn_state, i) {
-		const struct drm_encoder_helper_funcs *funcs;
-		struct drm_encoder *encoder;
-
-		if (!new_conn_state->best_encoder)
-			continue;
-
-		if (!new_conn_state->crtc->state->active ||
-		    !drm_atomic_crtc_needs_modeset(
-			    new_conn_state->crtc->state))
-			continue;
-
-		encoder = new_conn_state->best_encoder;
-		funcs = encoder->helper_private;
-
-		DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
-				 encoder->base.id, encoder->name);
-
-		/*
-		 * Each encoder has at most one connector (since we always steal
-		 * it away), so we won't call enable hooks twice.
-		 */
-		drm_bridge_pre_enable(encoder->bridge);
-		++bridge_enable_count;
-
-		if (funcs->enable)
-			funcs->enable(encoder);
-		else
-			funcs->commit(encoder);
-	}
-
-	if (kms->funcs->commit) {
-		DRM_DEBUG_ATOMIC("triggering commit\n");
-		kms->funcs->commit(kms, old_state);
-	}
-
-	/* If no bridges were pre_enabled, skip iterating over them again */
-	if (bridge_enable_count == 0)
-		return;
-
-	for_each_new_connector_in_state(old_state, connector,
-			new_conn_state, i) {
-		struct drm_encoder *encoder;
-
-		if (!new_conn_state->best_encoder)
-			continue;
-
-		if (!new_conn_state->crtc->state->active ||
-		    !drm_atomic_crtc_needs_modeset(
-				    new_conn_state->crtc->state))
-			continue;
-
-		encoder = new_conn_state->best_encoder;
-
-		DRM_DEBUG_ATOMIC("bridge enable enabling [ENCODER:%d:%s]\n",
-				 encoder->base.id, encoder->name);
-
-		drm_bridge_enable(encoder->bridge);
-	}
-}
-
 /* The (potentially) asynchronous part of the commit.  At this point
  * nothing can fail short of armageddon.
  */
@@ -227,7 +102,12 @@ static void complete_commit(struct msm_commit *c)
 
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
-	msm_atomic_helper_commit_modeset_enables(dev, state);
+	drm_atomic_helper_commit_modeset_enables(dev, state);
+
+	if (kms->funcs->commit) {
+		DRM_DEBUG_ATOMIC("triggering commit\n");
+		kms->funcs->commit(kms, state);
+	}
 
 	/* NOTE: _wait_for_vblanks() only waits for vblank on
 	 * enabled CRTCs.  So we end up faulting when disabling
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH v2] drm/msm: Don't duplicate modeset_enables atomic helper
  2018-03-16 19:45                       ` [DPU PATCH v2] " Sean Paul
@ 2018-03-16 20:57                         ` Jeykumar Sankaran
  0 siblings, 0 replies; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-16 20:57 UTC (permalink / raw)
  To: Sean Paul; +Cc: linux-arm-msm, abhinavk, dri-devel, hoegsberg, freedreno

On 2018-03-16 12:45, Sean Paul wrote:
> Instead, shuffle things around so we kickoff crtc after enabling 
> encoder
> during modesets. Also moves the vblank wait to after the frame.
> 
> Changes in v2:
> - Remove the encoder.commit hack, it's not required (Jeykumar)
> 
> Cc: Jeykumar Sankaran <jsanka@codeaurora.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>

> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c |   9 ++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c  |   8 +-
>  drivers/gpu/drm/msm/msm_atomic.c         | 132 ++---------------------
>  3 files changed, 19 insertions(+), 130 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index a3ab6ed2bf1d..94fab2dcca5b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -3525,6 +3525,12 @@ static void dpu_crtc_enable(struct drm_crtc 
> *crtc,
>  	DPU_EVT32_VERBOSE(DRMID(crtc));
>  	dpu_crtc = to_dpu_crtc(crtc);
> 
> +	if (msm_is_mode_seamless(&crtc->state->adjusted_mode) ||
> +	    msm_is_mode_seamless_vrr(&crtc->state->adjusted_mode)) {
> +		DPU_DEBUG("Skipping crtc enable, seamless mode\n");
> +		return;
> +	}
> +
>  	pm_runtime_get_sync(crtc->dev->dev);
> 
>  	drm_for_each_encoder(encoder, crtc->dev) {
> @@ -3572,6 +3578,9 @@ static void dpu_crtc_enable(struct drm_crtc 
> *crtc,
>  		DPU_POWER_EVENT_POST_ENABLE | DPU_POWER_EVENT_POST_DISABLE
> |
>  		DPU_POWER_EVENT_PRE_DISABLE,
>  		dpu_crtc_handle_power_event, crtc, dpu_crtc->name);
> +
> +	if (msm_needs_vblank_pre_modeset(&crtc->state->adjusted_mode))
> +		drm_crtc_wait_one_vblank(crtc);
>  }
> 
>  struct plane_state {
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> index 5ba345395b82..2c4c7fe1affe 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> @@ -422,14 +422,14 @@ static void dpu_kms_prepare_commit(struct msm_kms
> *kms,
>  			dpu_encoder_prepare_commit(encoder);
>  }
> 
> -static void dpu_kms_commit(struct msm_kms *kms,
> -		struct drm_atomic_state *old_state)
> +static void dpu_kms_commit(struct msm_kms *kms, struct 
> drm_atomic_state
> *state)
>  {
>  	struct drm_crtc *crtc;
> -	struct drm_crtc_state *old_crtc_state;
> +	struct drm_crtc_state *crtc_state;
> +	struct dpu_crtc_state *cstate;
>  	int i;
> 
> -	for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
> +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
>  		if (crtc->state->active) {
>  			DPU_EVT32(DRMID(crtc));
>  			dpu_crtc_commit_kickoff(crtc);
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> b/drivers/gpu/drm/msm/msm_atomic.c
> index 5cfb80345052..f5794dce25dd 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -84,131 +84,6 @@ static void msm_atomic_wait_for_commit_done(
>  	}
>  }
> 
> -/**
> - * msm_atomic_helper_commit_modeset_enables - modeset commit to enable
> outputs
> - * @dev: DRM device
> - * @old_state: atomic state object with old state structures
> - *
> - * This function enables all the outputs with the new configuration 
> which
> had to
> - * be turned off for the update.
> - *
> - * For compatibility with legacy crtc helpers this should be called 
> after
> - * drm_atomic_helper_commit_planes(), which is what the default commit
> function
> - * does. But drivers with different needs can group the modeset 
> commits
> together
> - * and do the plane commits at the end. This is useful for drivers 
> doing
> runtime
> - * PM since planes updates then only happen when the CRTC is actually
> enabled.
> - */
> -static void msm_atomic_helper_commit_modeset_enables(struct drm_device
> *dev,
> -		struct drm_atomic_state *old_state)
> -{
> -	struct drm_crtc *crtc;
> -	struct drm_crtc_state *old_crtc_state;
> -	struct drm_crtc_state *new_crtc_state;
> -	struct drm_connector *connector;
> -	struct drm_connector_state *new_conn_state;
> -	struct msm_drm_private *priv = dev->dev_private;
> -	struct msm_kms *kms = priv->kms;
> -	int bridge_enable_count = 0;
> -	int i;
> -
> -	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state,
> -			new_crtc_state, i) {
> -		const struct drm_crtc_helper_funcs *funcs;
> -
> -		/* Need to filter out CRTCs where only planes change. */
> -		if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
> -			continue;
> -
> -		if (!new_crtc_state->active)
> -			continue;
> -
> -		if (msm_is_mode_seamless(&new_crtc_state->mode) ||
> -				msm_is_mode_seamless_vrr(
> -				&new_crtc_state->adjusted_mode))
> -			continue;
> -
> -		funcs = crtc->helper_private;
> -
> -		if (crtc->state->enable) {
> -			DRM_DEBUG_ATOMIC("enabling [CRTC:%d]\n",
> -					 crtc->base.id);
> -
> -			if (funcs->atomic_enable)
> -				funcs->atomic_enable(crtc,
> old_crtc_state);
> -			else
> -				funcs->commit(crtc);
> -		}
> -
> -		if (msm_needs_vblank_pre_modeset(
> -					&new_crtc_state->adjusted_mode))
> -			drm_crtc_wait_one_vblank(crtc);
> -	}
> -
> -	/* ensure bridge/encoder updates happen on same vblank */
> -	msm_atomic_wait_for_commit_done(dev, old_state);
> -
> -	for_each_new_connector_in_state(old_state, connector,
> -			new_conn_state, i) {
> -		const struct drm_encoder_helper_funcs *funcs;
> -		struct drm_encoder *encoder;
> -
> -		if (!new_conn_state->best_encoder)
> -			continue;
> -
> -		if (!new_conn_state->crtc->state->active ||
> -		    !drm_atomic_crtc_needs_modeset(
> -			    new_conn_state->crtc->state))
> -			continue;
> -
> -		encoder = new_conn_state->best_encoder;
> -		funcs = encoder->helper_private;
> -
> -		DRM_DEBUG_ATOMIC("enabling [ENCODER:%d:%s]\n",
> -				 encoder->base.id, encoder->name);
> -
> -		/*
> -		 * Each encoder has at most one connector (since we always
> steal
> -		 * it away), so we won't call enable hooks twice.
> -		 */
> -		drm_bridge_pre_enable(encoder->bridge);
> -		++bridge_enable_count;
> -
> -		if (funcs->enable)
> -			funcs->enable(encoder);
> -		else
> -			funcs->commit(encoder);
> -	}
> -
> -	if (kms->funcs->commit) {
> -		DRM_DEBUG_ATOMIC("triggering commit\n");
> -		kms->funcs->commit(kms, old_state);
> -	}
> -
> -	/* If no bridges were pre_enabled, skip iterating over them again
> */
> -	if (bridge_enable_count == 0)
> -		return;
> -
> -	for_each_new_connector_in_state(old_state, connector,
> -			new_conn_state, i) {
> -		struct drm_encoder *encoder;
> -
> -		if (!new_conn_state->best_encoder)
> -			continue;
> -
> -		if (!new_conn_state->crtc->state->active ||
> -		    !drm_atomic_crtc_needs_modeset(
> -				    new_conn_state->crtc->state))
> -			continue;
> -
> -		encoder = new_conn_state->best_encoder;
> -
> -		DRM_DEBUG_ATOMIC("bridge enable enabling
> [ENCODER:%d:%s]\n",
> -				 encoder->base.id, encoder->name);
> -
> -		drm_bridge_enable(encoder->bridge);
> -	}
> -}
> -
>  /* The (potentially) asynchronous part of the commit.  At this point
>   * nothing can fail short of armageddon.
>   */
> @@ -227,7 +102,12 @@ static void complete_commit(struct msm_commit *c)
> 
>  	drm_atomic_helper_commit_planes(dev, state, 0);
> 
> -	msm_atomic_helper_commit_modeset_enables(dev, state);
> +	drm_atomic_helper_commit_modeset_enables(dev, state);
> +
> +	if (kms->funcs->commit) {
> +		DRM_DEBUG_ATOMIC("triggering commit\n");
> +		kms->funcs->commit(kms, state);
> +	}
> 
>  	/* NOTE: _wait_for_vblanks() only waits for vblank on
>  	 * enabled CRTCs.  So we end up faulting when disabling

-- 
Jeykumar S
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
  2018-03-12 20:23                       ` Sean Paul
@ 2018-03-19 15:01                         ` Sean Paul
  2018-03-19 19:54                           ` Jeykumar Sankaran
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-19 15:01 UTC (permalink / raw)
  To: Jeykumar Sankaran
  Cc: linux-arm-msm, dri-devel, abhinavk, Kristian H. Kristensen, freedreno

On Mon, Mar 12, 2018 at 04:23:10PM -0400, Sean Paul wrote:
> On Thu, Mar 08, 2018 at 05:08:03PM -0800, Jeykumar Sankaran wrote:
> > On 2018-03-02 06:56, Sean Paul wrote:
> > > On Thu, Mar 01, 2018 at 07:37:10PM -0500, Rob Clark wrote:
> > > > On Thu, Mar 1, 2018 at 3:37 PM,  <jsanka@codeaurora.org> wrote:
> > > > > On 2018-03-01 07:27, Sean Paul wrote:
> > > > >>
> > > > >> On Wed, Feb 28, 2018 at 08:07:00PM -0800, jsanka@codeaurora.org
> > > wrote:
> > > > >>>
> > > > >>> On 2018-02-28 11:19, Sean Paul wrote:
> > > > >>> > Moving further towards switching fully to the the atomic helpers,
> > > this
> > > > >>> > patch removes the hand-rolled kthread nonblock commit code and
> > > uses
> > > > >>
> > > > >> the
> > > > >>>
> > > > >>> > atomic helpers commit_work model.
> > > > >>> >
> > > > >>> > There's still a lot of copypasta here, but it's still needed to
> > > > >>> > facilitate the swap_state and prepare_fence private functions.
> > > These
> > > > >>> > will be sorted out in a follow-on patch.
> > > > >>> >
> > > > >>> > Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
> > > > >>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
> > > > >>> > ---

<snip />

> > > > >>
> > > > >>> > -                                     /* only return zero if work
> > > is
> > > > >>> > -                                      * queued successfully.
> > > > >>> > -                                      */
> > > > >>> > -                                     ret = 0;
> > > > >>> > -                             } else {
> > > > >>> > -                                     DRM_ERROR(" Error for
> > > crtc_id:
> > > > >>> > %d\n",
> > > > >>> > -
> > > > >>> > priv->disp_thread[j].crtc_id);
> > > > >>> > -                             }
> > > > >>> > -                             break;
> > > > >>> > -                     }
> > > > >>> > -             }
> > 
> > Care to remove priv->disp_thread and all its references as a part of this
> > change?
> 
> Definitely! Will revise.
> 

Now that I look at it, disp_thread doesn't seem relevant to this change. It
seems like it's used for deferred cleanup. So perhaps we could get rid of it,
but IMO that would be a different patch.

> Sean
> 
> > 
> > - Jeykumar S

<snip />

-- 
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [DPU PATCH v2] drm/msm: Use atomic private_obj instead of subclassing
  2018-03-12 20:28           ` Sean Paul
@ 2018-03-19 17:31             ` Sean Paul
       [not found]               ` <20180319173113.94879-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-19 17:31 UTC (permalink / raw)
  To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	Sean Paul, hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Instead of subclassing atomic state, store driver private data in
private_obj/state. This allows us to remove the swap_state driver hook
for mdp5 and get closer to using the atomic helpers entirely.

Changes in v2:
 - Use state->state in disp duplicate_state callback (Jeykumar)

Cc: Jeykumar Sankaran <jsanka@codeaurora.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 37 ++++++--------
 drivers/gpu/drm/msm/msm_atomic.c         | 30 -----------
 drivers/gpu/drm/msm/msm_drv.c            | 65 ++++++++++++++++++++++--
 drivers/gpu/drm/msm/msm_drv.h            |  4 +-
 drivers/gpu/drm/msm/msm_kms.h            | 28 +++++-----
 5 files changed, 95 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 6d8e3a9a6fc0..f1a248419655 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -74,36 +74,32 @@ struct mdp5_state *mdp5_get_state(struct drm_atomic_state *s)
 {
 	struct msm_drm_private *priv = s->dev->dev_private;
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
-	struct msm_kms_state *state = to_kms_state(s);
-	struct mdp5_state *new_state;
+	struct msm_kms_state *kms_state;
 	int ret;
 
-	if (state->state)
-		return state->state;
-
 	ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
 	if (ret)
 		return ERR_PTR(ret);
 
-	new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
-	if (!new_state)
-		return ERR_PTR(-ENOMEM);
+	kms_state = msm_kms_get_state(s);
+	if (IS_ERR_OR_NULL(kms_state))
+		return (struct mdp5_state *)kms_state; /* casting ERR_PTR */
 
-	/* Copy state: */
-	new_state->hwpipe = mdp5_kms->state->hwpipe;
-	new_state->hwmixer = mdp5_kms->state->hwmixer;
-	if (mdp5_kms->smp)
-		new_state->smp = mdp5_kms->state->smp;
+	return kms_state->state;
+}
 
-	state->state = new_state;
+static void *mdp5_duplicate_state(void *state)
+{
+	if (!state)
+		return kzalloc(sizeof(struct mdp5_state), GFP_KERNEL);
 
-	return new_state;
+	return kmemdup(state, sizeof(struct mdp5_state), GFP_KERNEL);
 }
 
-static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)
+static void mdp5_destroy_state(void *state)
 {
-	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
-	swap(to_kms_state(state)->state, mdp5_kms->state);
+	struct mdp5_state *mdp_state = state;
+	kfree(mdp_state);
 }
 
 static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
@@ -229,7 +225,8 @@ static const struct mdp_kms_funcs kms_funcs = {
 		.irq             = mdp5_irq,
 		.enable_vblank   = mdp5_enable_vblank,
 		.disable_vblank  = mdp5_disable_vblank,
-		.swap_state      = mdp5_swap_state,
+		.duplicate_state = mdp5_duplicate_state,
+		.destroy_state	 = mdp5_destroy_state,
 		.prepare_commit  = mdp5_prepare_commit,
 		.complete_commit = mdp5_complete_commit,
 		.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
@@ -726,8 +723,6 @@ static void mdp5_destroy(struct platform_device *pdev)
 
 	if (mdp5_kms->rpm_enabled)
 		pm_runtime_disable(&pdev->dev);
-
-	kfree(mdp5_kms->state);
 }
 
 static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 7e54eb65d096..1f53262ea46b 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -169,9 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
 	 */
 	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
 
-	if (to_kms_state(state)->state)
-		priv->kms->funcs->swap_state(priv->kms, state);
-
 	/*
 	 * Provide the driver a chance to prepare for output fences. This is
 	 * done after the point of no return, but before asynchronous commits
@@ -210,30 +207,3 @@ int msm_atomic_commit(struct drm_device *dev,
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
 }
-
-struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev)
-{
-	struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
-
-	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
-		kfree(state);
-		return NULL;
-	}
-
-	return &state->base;
-}
-
-void msm_atomic_state_clear(struct drm_atomic_state *s)
-{
-	struct msm_kms_state *state = to_kms_state(s);
-	drm_atomic_state_default_clear(&state->base);
-	kfree(state->state);
-	state->state = NULL;
-}
-
-void msm_atomic_state_free(struct drm_atomic_state *state)
-{
-	kfree(to_kms_state(state)->state);
-	drm_atomic_state_default_release(state);
-	kfree(state);
-}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 5219792e93bc..4c0740dc7854 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -121,9 +121,62 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
 	.output_poll_changed = msm_fb_output_poll_changed,
 	.atomic_check = drm_atomic_helper_check,
 	.atomic_commit = msm_atomic_commit,
-	.atomic_state_alloc = msm_atomic_state_alloc,
-	.atomic_state_clear = msm_atomic_state_clear,
-	.atomic_state_free = msm_atomic_state_free,
+};
+
+static inline
+struct msm_kms *obj_to_kms(struct drm_private_obj *obj)
+{
+	return container_of(obj, struct msm_kms, base);
+}
+
+static inline
+struct msm_kms_state *state_to_kms_state(struct drm_private_state *state)
+{
+	return container_of(state, struct msm_kms_state, base);
+}
+
+struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *s)
+{
+	struct msm_drm_private *priv = s->dev->dev_private;
+	struct drm_private_obj *obj = &priv->kms->base;
+	struct drm_private_state *state;
+
+	state = drm_atomic_get_private_obj_state(s, obj);
+	if (IS_ERR_OR_NULL(state))
+		return (struct msm_kms_state *)state; /* casting ERR_PTR */
+
+	return state_to_kms_state(state);
+}
+
+static struct drm_private_state *
+msm_kms_duplicate_state(struct drm_private_obj *obj)
+{
+	struct msm_kms *kms = obj_to_kms(obj);
+	struct msm_kms_state *state = state_to_kms_state(obj->state);
+	struct msm_kms_state *new_state;
+
+	if (kms->funcs->duplicate_state)
+		new_state = kms->funcs->duplicate_state(state->state);
+
+	__drm_atomic_helper_private_obj_duplicate_state(obj, &new_state->base);
+
+	return &new_state->base;
+}
+
+static void msm_kms_destroy_state(struct drm_private_obj *obj,
+				  struct drm_private_state *state)
+{
+	struct msm_kms *kms = obj_to_kms(obj);
+	struct msm_kms_state *kms_state = state_to_kms_state(obj->state);
+
+	if (kms->funcs->destroy_state)
+		kms->funcs->destroy_state(kms_state->state);
+	kfree(kms_state);
+}
+
+static const struct drm_private_state_funcs kms_state_funcs = {
+	.atomic_duplicate_state = msm_kms_duplicate_state,
+	.atomic_destroy_state = msm_kms_destroy_state,
 };
 
 #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
@@ -341,6 +394,8 @@ static int msm_drm_uninit(struct device *dev)
 		}
 	}
 
+	drm_atomic_private_obj_fini(&kms->base);
+
 	msm_gem_shrinker_cleanup(ddev);
 
 	drm_kms_helper_poll_fini(ddev);
@@ -770,6 +825,10 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
 	}
 #endif
 
+	drm_atomic_private_obj_init(&kms->base,
+				    &kms->state.base,
+				    &kms_state_funcs);
+
 	/* perform subdriver post initialization */
 	if (kms && kms->funcs && kms->funcs->postinit) {
 		ret = kms->funcs->postinit(kms);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 292496b682e8..8cab333df717 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -598,9 +598,7 @@ struct msm_format {
 
 int msm_atomic_commit(struct drm_device *dev,
 		struct drm_atomic_state *state, bool nonblock);
-struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
-void msm_atomic_state_clear(struct drm_atomic_state *state);
-void msm_atomic_state_free(struct drm_atomic_state *state);
+struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *state);
 
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
 		struct msm_gem_vma *vma, struct sg_table *sgt);
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 09ba1e79db50..4c5a69258c42 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -57,6 +57,8 @@ struct msm_kms_funcs {
 	void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
 	/* swap global atomic state: */
 	void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state *state);
+	void *(*duplicate_state)(void *state);
+	void (*destroy_state)(void *state);
 	/* modeset, bracketing atomic_commit(): */
 	void (*prepare_fence)(struct msm_kms *kms,
 			struct drm_atomic_state *state);
@@ -114,16 +116,6 @@ struct msm_kms_funcs {
 #endif
 };
 
-struct msm_kms {
-	const struct msm_kms_funcs *funcs;
-
-	/* irq number to be passed on to drm_irq_install */
-	int irq;
-
-	/* mapper-id used to request GEM buffer mapped for scanout: */
-	struct msm_gem_address_space *aspace;
-};
-
 /**
  * Subclass of drm_atomic_state, to allow kms backend to have driver
  * private global state.  The kms backend can do whatever it wants
@@ -131,10 +123,22 @@ struct msm_kms {
  * is kfree'd and set back to NULL.
  */
 struct msm_kms_state {
-	struct drm_atomic_state base;
+	struct drm_private_state base;
 	void *state;
 };
-#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
+
+struct msm_kms {
+	struct drm_private_obj base;
+	struct msm_kms_state state;
+
+	const struct msm_kms_funcs *funcs;
+
+	/* irq number to be passed on to drm_irq_install */
+	int irq;
+
+	/* mapper-id used to request GEM buffer mapped for scanout: */
+	struct msm_gem_address_space *aspace;
+};
 
 static inline void msm_kms_init(struct msm_kms *kms,
 		const struct msm_kms_funcs *funcs)
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH v2] drm/msm: Use atomic private_obj instead of subclassing
       [not found]               ` <20180319173113.94879-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-19 19:33                 ` Jeykumar Sankaran
  2018-03-19 19:58                   ` [DPU PATCH v3] " Sean Paul
  0 siblings, 1 reply; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-19 19:33 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-03-19 10:31, Sean Paul wrote:
> Instead of subclassing atomic state, store driver private data in
> private_obj/state. This allows us to remove the swap_state driver hook
> for mdp5 and get closer to using the atomic helpers entirely.
> 
> Changes in v2:
>  - Use state->state in disp duplicate_state callback (Jeykumar)
> 
> Cc: Jeykumar Sankaran <jsanka@codeaurora.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
With the below comment updated

Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>

> ---
>  drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 37 ++++++--------
>  drivers/gpu/drm/msm/msm_atomic.c         | 30 -----------
>  drivers/gpu/drm/msm/msm_drv.c            | 65 ++++++++++++++++++++++--
>  drivers/gpu/drm/msm/msm_drv.h            |  4 +-
>  drivers/gpu/drm/msm/msm_kms.h            | 28 +++++-----
>  5 files changed, 95 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> index 6d8e3a9a6fc0..f1a248419655 100644
> --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> @@ -74,36 +74,32 @@ struct mdp5_state *mdp5_get_state(struct
> drm_atomic_state *s)
>  {
>  	struct msm_drm_private *priv = s->dev->dev_private;
>  	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
> -	struct msm_kms_state *state = to_kms_state(s);
> -	struct mdp5_state *new_state;
> +	struct msm_kms_state *kms_state;
>  	int ret;
> 
> -	if (state->state)
> -		return state->state;
> -
>  	ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
>  	if (ret)
>  		return ERR_PTR(ret);
> 
> -	new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
> -	if (!new_state)
> -		return ERR_PTR(-ENOMEM);
> +	kms_state = msm_kms_get_state(s);
> +	if (IS_ERR_OR_NULL(kms_state))
> +		return (struct mdp5_state *)kms_state; /* casting ERR_PTR
> */
> 
> -	/* Copy state: */
> -	new_state->hwpipe = mdp5_kms->state->hwpipe;
> -	new_state->hwmixer = mdp5_kms->state->hwmixer;
> -	if (mdp5_kms->smp)
> -		new_state->smp = mdp5_kms->state->smp;
> +	return kms_state->state;
> +}
> 
> -	state->state = new_state;
> +static void *mdp5_duplicate_state(void *state)
> +{
> +	if (!state)
> +		return kzalloc(sizeof(struct mdp5_state), GFP_KERNEL);
> 
> -	return new_state;
> +	return kmemdup(state, sizeof(struct mdp5_state), GFP_KERNEL);
>  }
> 
> -static void mdp5_swap_state(struct msm_kms *kms, struct 
> drm_atomic_state
> *state)
> +static void mdp5_destroy_state(void *state)
>  {
> -	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
> -	swap(to_kms_state(state)->state, mdp5_kms->state);
> +	struct mdp5_state *mdp_state = state;
> +	kfree(mdp_state);
>  }
> 
>  static void mdp5_prepare_commit(struct msm_kms *kms, struct
> drm_atomic_state *state)
> @@ -229,7 +225,8 @@ static const struct mdp_kms_funcs kms_funcs = {
>  		.irq             = mdp5_irq,
>  		.enable_vblank   = mdp5_enable_vblank,
>  		.disable_vblank  = mdp5_disable_vblank,
> -		.swap_state      = mdp5_swap_state,
> +		.duplicate_state = mdp5_duplicate_state,
> +		.destroy_state	 = mdp5_destroy_state,
>  		.prepare_commit  = mdp5_prepare_commit,
>  		.complete_commit = mdp5_complete_commit,
>  		.wait_for_crtc_commit_done =
> mdp5_wait_for_crtc_commit_done,
> @@ -726,8 +723,6 @@ static void mdp5_destroy(struct platform_device 
> *pdev)
> 
>  	if (mdp5_kms->rpm_enabled)
>  		pm_runtime_disable(&pdev->dev);
> -
> -	kfree(mdp5_kms->state);
>  }
> 
>  static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> b/drivers/gpu/drm/msm/msm_atomic.c
> index 7e54eb65d096..1f53262ea46b 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -169,9 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 */
>  	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
> 
> -	if (to_kms_state(state)->state)
> -		priv->kms->funcs->swap_state(priv->kms, state);
> -
>  	/*
>  	 * Provide the driver a chance to prepare for output fences. This
> is
>  	 * done after the point of no return, but before asynchronous
> commits
> @@ -210,30 +207,3 @@ int msm_atomic_commit(struct drm_device *dev,
>  	drm_atomic_helper_cleanup_planes(dev, state);
>  	return ret;
>  }
> -
> -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device 
> *dev)
> -{
> -	struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
> -
> -	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
> -		kfree(state);
> -		return NULL;
> -	}
> -
> -	return &state->base;
> -}
> -
> -void msm_atomic_state_clear(struct drm_atomic_state *s)
> -{
> -	struct msm_kms_state *state = to_kms_state(s);
> -	drm_atomic_state_default_clear(&state->base);
> -	kfree(state->state);
> -	state->state = NULL;
> -}
> -
> -void msm_atomic_state_free(struct drm_atomic_state *state)
> -{
> -	kfree(to_kms_state(state)->state);
> -	drm_atomic_state_default_release(state);
> -	kfree(state);
> -}
> diff --git a/drivers/gpu/drm/msm/msm_drv.c 
> b/drivers/gpu/drm/msm/msm_drv.c
> index 5219792e93bc..4c0740dc7854 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -121,9 +121,62 @@ static const struct drm_mode_config_funcs
> mode_config_funcs = {
>  	.output_poll_changed = msm_fb_output_poll_changed,
>  	.atomic_check = drm_atomic_helper_check,
>  	.atomic_commit = msm_atomic_commit,
> -	.atomic_state_alloc = msm_atomic_state_alloc,
> -	.atomic_state_clear = msm_atomic_state_clear,
> -	.atomic_state_free = msm_atomic_state_free,
> +};
> +
> +static inline
> +struct msm_kms *obj_to_kms(struct drm_private_obj *obj)
> +{
> +	return container_of(obj, struct msm_kms, base);
> +}
> +
> +static inline
> +struct msm_kms_state *state_to_kms_state(struct drm_private_state 
> *state)
> +{
> +	return container_of(state, struct msm_kms_state, base);
> +}
> +
> +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *s)
> +{
> +	struct msm_drm_private *priv = s->dev->dev_private;
> +	struct drm_private_obj *obj = &priv->kms->base;
> +	struct drm_private_state *state;
> +
> +	state = drm_atomic_get_private_obj_state(s, obj);
> +	if (IS_ERR_OR_NULL(state))
> +		return (struct msm_kms_state *)state; /* casting ERR_PTR
> */
> +
> +	return state_to_kms_state(state);
> +}
> +
> +static struct drm_private_state *
> +msm_kms_duplicate_state(struct drm_private_obj *obj)
> +{
> +	struct msm_kms *kms = obj_to_kms(obj);
> +	struct msm_kms_state *state = state_to_kms_state(obj->state);
> +	struct msm_kms_state *new_state;
> +
> +	if (kms->funcs->duplicate_state)
> +		new_state = kms->funcs->duplicate_state(state->state);
> +
> +	__drm_atomic_helper_private_obj_duplicate_state(obj,
> &new_state->base);
> +
> +	return &new_state->base;
> +}
> +
> +static void msm_kms_destroy_state(struct drm_private_obj *obj,
> +				  struct drm_private_state *state)
> +{
> +	struct msm_kms *kms = obj_to_kms(obj);
> +	struct msm_kms_state *kms_state = state_to_kms_state(obj->state);
> +
> +	if (kms->funcs->destroy_state)
> +		kms->funcs->destroy_state(kms_state->state);
> +	kfree(kms_state);
> +}
> +
> +static const struct drm_private_state_funcs kms_state_funcs = {
> +	.atomic_duplicate_state = msm_kms_duplicate_state,
> +	.atomic_destroy_state = msm_kms_destroy_state,
>  };
> 
>  #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
> @@ -341,6 +394,8 @@ static int msm_drm_uninit(struct device *dev)
>  		}
>  	}
> 
> +	drm_atomic_private_obj_fini(&kms->base);
> +
>  	msm_gem_shrinker_cleanup(ddev);
> 
>  	drm_kms_helper_poll_fini(ddev);
> @@ -770,6 +825,10 @@ static int msm_drm_init(struct device *dev, struct
> drm_driver *drv)
>  	}
>  #endif
> 
> +	drm_atomic_private_obj_init(&kms->base,
> +				    &kms->state.base,
> +				    &kms_state_funcs);
> +
>  	/* perform subdriver post initialization */
>  	if (kms && kms->funcs && kms->funcs->postinit) {
>  		ret = kms->funcs->postinit(kms);
> diff --git a/drivers/gpu/drm/msm/msm_drv.h 
> b/drivers/gpu/drm/msm/msm_drv.h
> index 292496b682e8..8cab333df717 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -598,9 +598,7 @@ struct msm_format {
> 
>  int msm_atomic_commit(struct drm_device *dev,
>  		struct drm_atomic_state *state, bool nonblock);
> -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device 
> *dev);
> -void msm_atomic_state_clear(struct drm_atomic_state *state);
> -void msm_atomic_state_free(struct drm_atomic_state *state);
> +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state 
> *state);
> 
>  void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
>  		struct msm_gem_vma *vma, struct sg_table *sgt);
> diff --git a/drivers/gpu/drm/msm/msm_kms.h 
> b/drivers/gpu/drm/msm/msm_kms.h
> index 09ba1e79db50..4c5a69258c42 100644
> --- a/drivers/gpu/drm/msm/msm_kms.h
> +++ b/drivers/gpu/drm/msm/msm_kms.h
> @@ -57,6 +57,8 @@ struct msm_kms_funcs {
>  	void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc
> *crtc);
>  	/* swap global atomic state: */
>  	void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state
> *state);
> +	void *(*duplicate_state)(void *state);
> +	void (*destroy_state)(void *state);
>  	/* modeset, bracketing atomic_commit(): */
>  	void (*prepare_fence)(struct msm_kms *kms,
>  			struct drm_atomic_state *state);
> @@ -114,16 +116,6 @@ struct msm_kms_funcs {
>  #endif
>  };
> 
> -struct msm_kms {
> -	const struct msm_kms_funcs *funcs;
> -
> -	/* irq number to be passed on to drm_irq_install */
> -	int irq;
> -
> -	/* mapper-id used to request GEM buffer mapped for scanout: */
> -	struct msm_gem_address_space *aspace;
> -};
> -
>  /**
>   * Subclass of drm_atomic_state, to allow kms backend to have driver
>   * private global state.  The kms backend can do whatever it wants
Update comments. It is not subclassing drm_atomic_state anymore.
> @@ -131,10 +123,22 @@ struct msm_kms {
>   * is kfree'd and set back to NULL.
>   */
>  struct msm_kms_state {
> -	struct drm_atomic_state base;
> +	struct drm_private_state base;
>  	void *state;
>  };
> -#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
> +
> +struct msm_kms {
> +	struct drm_private_obj base;
> +	struct msm_kms_state state;
> +
> +	const struct msm_kms_funcs *funcs;
> +
> +	/* irq number to be passed on to drm_irq_install */
> +	int irq;
> +
> +	/* mapper-id used to request GEM buffer mapped for scanout: */
> +	struct msm_gem_address_space *aspace;
> +};
> 
>  static inline void msm_kms_init(struct msm_kms *kms,
>  		const struct msm_kms_funcs *funcs)

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit
  2018-03-19 15:01                         ` Sean Paul
@ 2018-03-19 19:54                           ` Jeykumar Sankaran
  0 siblings, 0 replies; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-03-19 19:54 UTC (permalink / raw)
  To: Sean Paul
  Cc: linux-arm-msm, abhinavk-sgV2jX0FEOL9JmXXK+q4OQ, Rob Clark,
	dri-devel, Kristian H. Kristensen, freedreno

On 2018-03-19 08:01, Sean Paul wrote:
> On Mon, Mar 12, 2018 at 04:23:10PM -0400, Sean Paul wrote:
>> On Thu, Mar 08, 2018 at 05:08:03PM -0800, Jeykumar Sankaran wrote:
>> > On 2018-03-02 06:56, Sean Paul wrote:
>> > > On Thu, Mar 01, 2018 at 07:37:10PM -0500, Rob Clark wrote:
>> > > > On Thu, Mar 1, 2018 at 3:37 PM,  <jsanka@codeaurora.org> wrote:
>> > > > > On 2018-03-01 07:27, Sean Paul wrote:
>> > > > >>
>> > > > >> On Wed, Feb 28, 2018 at 08:07:00PM -0800, jsanka@codeaurora.org
>> > > wrote:
>> > > > >>>
>> > > > >>> On 2018-02-28 11:19, Sean Paul wrote:
>> > > > >>> > Moving further towards switching fully to the the atomic
> helpers,
>> > > this
>> > > > >>> > patch removes the hand-rolled kthread nonblock commit code
> and
>> > > uses
>> > > > >>
>> > > > >> the
>> > > > >>>
>> > > > >>> > atomic helpers commit_work model.
>> > > > >>> >
>> > > > >>> > There's still a lot of copypasta here, but it's still needed
> to
>> > > > >>> > facilitate the swap_state and prepare_fence private
> functions.
>> > > These
>> > > > >>> > will be sorted out in a follow-on patch.
>> > > > >>> >
>> > > > >>> > Change-Id: I9fcba27824ba63d3fab96cb2bc194bfa6f3475b7
>> > > > >>> > Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> > > > >>> > ---
> 
> <snip />
> 
>> > > > >>
>> > > > >>> > -                                     /* only return zero if
> work
>> > > is
>> > > > >>> > -                                      * queued
> successfully.
>> > > > >>> > -                                      */
>> > > > >>> > -                                     ret = 0;
>> > > > >>> > -                             } else {
>> > > > >>> > -                                     DRM_ERROR(" Error for
>> > > crtc_id:
>> > > > >>> > %d\n",
>> > > > >>> > -
>> > > > >>> > priv->disp_thread[j].crtc_id);
>> > > > >>> > -                             }
>> > > > >>> > -                             break;
>> > > > >>> > -                     }
>> > > > >>> > -             }
>> >
>> > Care to remove priv->disp_thread and all its references as a part of
> this
>> > change?
>> 
>> Definitely! Will revise.
>> 
> 
> Now that I look at it, disp_thread doesn't seem relevant to this 
> change.
> It
> seems like it's used for deferred cleanup. So perhaps we could get rid 
> of
> it,
> but IMO that would be a different patch.
> 
>> Sean
>> 
hmm.. disp_threads are created per CRTC (per display) to allow 
concurrency of
hardware programming. So its not entirely irrelevant to this chnage. But 
since
it involves more than just priv->disp_thread cleanup, I am fine with 
cleaning
that in a separate patch.

Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>

>> >
>> > - Jeykumar S
> 
> <snip />

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [DPU PATCH v3] drm/msm: Use atomic private_obj instead of subclassing
  2018-03-19 19:33                 ` Jeykumar Sankaran
@ 2018-03-19 19:58                   ` Sean Paul
       [not found]                     ` <20180319195853.49006-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Sean Paul @ 2018-03-19 19:58 UTC (permalink / raw)
  To: freedreno, linux-arm-msm, dri-devel; +Cc: hoegsberg, abhinavk

Instead of subclassing atomic state, store driver private data in
private_obj/state. This allows us to remove the swap_state driver hook
for mdp5 and get closer to using the atomic helpers entirely.

Changes in v2:
 - Use state->state in disp duplicate_state callback (Jeykumar)
Changes in v3:
 - Update comment describing msm_kms_state (Jeykumar)

Cc: Jeykumar Sankaran <jsanka@codeaurora.org>
Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 37 ++++++--------
 drivers/gpu/drm/msm/msm_atomic.c         | 30 -----------
 drivers/gpu/drm/msm/msm_drv.c            | 65 ++++++++++++++++++++++--
 drivers/gpu/drm/msm/msm_drv.h            |  4 +-
 drivers/gpu/drm/msm/msm_kms.h            | 27 +++++-----
 5 files changed, 94 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 6d8e3a9a6fc0..f1a248419655 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -74,36 +74,32 @@ struct mdp5_state *mdp5_get_state(struct drm_atomic_state *s)
 {
 	struct msm_drm_private *priv = s->dev->dev_private;
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
-	struct msm_kms_state *state = to_kms_state(s);
-	struct mdp5_state *new_state;
+	struct msm_kms_state *kms_state;
 	int ret;
 
-	if (state->state)
-		return state->state;
-
 	ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
 	if (ret)
 		return ERR_PTR(ret);
 
-	new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
-	if (!new_state)
-		return ERR_PTR(-ENOMEM);
+	kms_state = msm_kms_get_state(s);
+	if (IS_ERR_OR_NULL(kms_state))
+		return (struct mdp5_state *)kms_state; /* casting ERR_PTR */
 
-	/* Copy state: */
-	new_state->hwpipe = mdp5_kms->state->hwpipe;
-	new_state->hwmixer = mdp5_kms->state->hwmixer;
-	if (mdp5_kms->smp)
-		new_state->smp = mdp5_kms->state->smp;
+	return kms_state->state;
+}
 
-	state->state = new_state;
+static void *mdp5_duplicate_state(void *state)
+{
+	if (!state)
+		return kzalloc(sizeof(struct mdp5_state), GFP_KERNEL);
 
-	return new_state;
+	return kmemdup(state, sizeof(struct mdp5_state), GFP_KERNEL);
 }
 
-static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)
+static void mdp5_destroy_state(void *state)
 {
-	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
-	swap(to_kms_state(state)->state, mdp5_kms->state);
+	struct mdp5_state *mdp_state = state;
+	kfree(mdp_state);
 }
 
 static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
@@ -229,7 +225,8 @@ static const struct mdp_kms_funcs kms_funcs = {
 		.irq             = mdp5_irq,
 		.enable_vblank   = mdp5_enable_vblank,
 		.disable_vblank  = mdp5_disable_vblank,
-		.swap_state      = mdp5_swap_state,
+		.duplicate_state = mdp5_duplicate_state,
+		.destroy_state	 = mdp5_destroy_state,
 		.prepare_commit  = mdp5_prepare_commit,
 		.complete_commit = mdp5_complete_commit,
 		.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
@@ -726,8 +723,6 @@ static void mdp5_destroy(struct platform_device *pdev)
 
 	if (mdp5_kms->rpm_enabled)
 		pm_runtime_disable(&pdev->dev);
-
-	kfree(mdp5_kms->state);
 }
 
 static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 7e54eb65d096..1f53262ea46b 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -169,9 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
 	 */
 	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
 
-	if (to_kms_state(state)->state)
-		priv->kms->funcs->swap_state(priv->kms, state);
-
 	/*
 	 * Provide the driver a chance to prepare for output fences. This is
 	 * done after the point of no return, but before asynchronous commits
@@ -210,30 +207,3 @@ int msm_atomic_commit(struct drm_device *dev,
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
 }
-
-struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev)
-{
-	struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
-
-	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
-		kfree(state);
-		return NULL;
-	}
-
-	return &state->base;
-}
-
-void msm_atomic_state_clear(struct drm_atomic_state *s)
-{
-	struct msm_kms_state *state = to_kms_state(s);
-	drm_atomic_state_default_clear(&state->base);
-	kfree(state->state);
-	state->state = NULL;
-}
-
-void msm_atomic_state_free(struct drm_atomic_state *state)
-{
-	kfree(to_kms_state(state)->state);
-	drm_atomic_state_default_release(state);
-	kfree(state);
-}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 5219792e93bc..4c0740dc7854 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -121,9 +121,62 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
 	.output_poll_changed = msm_fb_output_poll_changed,
 	.atomic_check = drm_atomic_helper_check,
 	.atomic_commit = msm_atomic_commit,
-	.atomic_state_alloc = msm_atomic_state_alloc,
-	.atomic_state_clear = msm_atomic_state_clear,
-	.atomic_state_free = msm_atomic_state_free,
+};
+
+static inline
+struct msm_kms *obj_to_kms(struct drm_private_obj *obj)
+{
+	return container_of(obj, struct msm_kms, base);
+}
+
+static inline
+struct msm_kms_state *state_to_kms_state(struct drm_private_state *state)
+{
+	return container_of(state, struct msm_kms_state, base);
+}
+
+struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *s)
+{
+	struct msm_drm_private *priv = s->dev->dev_private;
+	struct drm_private_obj *obj = &priv->kms->base;
+	struct drm_private_state *state;
+
+	state = drm_atomic_get_private_obj_state(s, obj);
+	if (IS_ERR_OR_NULL(state))
+		return (struct msm_kms_state *)state; /* casting ERR_PTR */
+
+	return state_to_kms_state(state);
+}
+
+static struct drm_private_state *
+msm_kms_duplicate_state(struct drm_private_obj *obj)
+{
+	struct msm_kms *kms = obj_to_kms(obj);
+	struct msm_kms_state *state = state_to_kms_state(obj->state);
+	struct msm_kms_state *new_state;
+
+	if (kms->funcs->duplicate_state)
+		new_state = kms->funcs->duplicate_state(state->state);
+
+	__drm_atomic_helper_private_obj_duplicate_state(obj, &new_state->base);
+
+	return &new_state->base;
+}
+
+static void msm_kms_destroy_state(struct drm_private_obj *obj,
+				  struct drm_private_state *state)
+{
+	struct msm_kms *kms = obj_to_kms(obj);
+	struct msm_kms_state *kms_state = state_to_kms_state(obj->state);
+
+	if (kms->funcs->destroy_state)
+		kms->funcs->destroy_state(kms_state->state);
+	kfree(kms_state);
+}
+
+static const struct drm_private_state_funcs kms_state_funcs = {
+	.atomic_duplicate_state = msm_kms_duplicate_state,
+	.atomic_destroy_state = msm_kms_destroy_state,
 };
 
 #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
@@ -341,6 +394,8 @@ static int msm_drm_uninit(struct device *dev)
 		}
 	}
 
+	drm_atomic_private_obj_fini(&kms->base);
+
 	msm_gem_shrinker_cleanup(ddev);
 
 	drm_kms_helper_poll_fini(ddev);
@@ -770,6 +825,10 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
 	}
 #endif
 
+	drm_atomic_private_obj_init(&kms->base,
+				    &kms->state.base,
+				    &kms_state_funcs);
+
 	/* perform subdriver post initialization */
 	if (kms && kms->funcs && kms->funcs->postinit) {
 		ret = kms->funcs->postinit(kms);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 292496b682e8..8cab333df717 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -598,9 +598,7 @@ struct msm_format {
 
 int msm_atomic_commit(struct drm_device *dev,
 		struct drm_atomic_state *state, bool nonblock);
-struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
-void msm_atomic_state_clear(struct drm_atomic_state *state);
-void msm_atomic_state_free(struct drm_atomic_state *state);
+struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *state);
 
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
 		struct msm_gem_vma *vma, struct sg_table *sgt);
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 09ba1e79db50..5c1bcaf65fd9 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -57,6 +57,8 @@ struct msm_kms_funcs {
 	void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
 	/* swap global atomic state: */
 	void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state *state);
+	void *(*duplicate_state)(void *state);
+	void (*destroy_state)(void *state);
 	/* modeset, bracketing atomic_commit(): */
 	void (*prepare_fence)(struct msm_kms *kms,
 			struct drm_atomic_state *state);
@@ -114,7 +116,20 @@ struct msm_kms_funcs {
 #endif
 };
 
+/**
+ * Subclass of drm_private_state, to allow kms backend to have driver
+ * private global state.  The kms backend can do whatever it wants
+ * with the ->state ptr.
+ */
+struct msm_kms_state {
+	struct drm_private_state base;
+	void *state;
+};
+
 struct msm_kms {
+	struct drm_private_obj base;
+	struct msm_kms_state state;
+
 	const struct msm_kms_funcs *funcs;
 
 	/* irq number to be passed on to drm_irq_install */
@@ -124,18 +139,6 @@ struct msm_kms {
 	struct msm_gem_address_space *aspace;
 };
 
-/**
- * Subclass of drm_atomic_state, to allow kms backend to have driver
- * private global state.  The kms backend can do whatever it wants
- * with the ->state ptr.  On ->atomic_state_clear() the ->state ptr
- * is kfree'd and set back to NULL.
- */
-struct msm_kms_state {
-	struct drm_atomic_state base;
-	void *state;
-};
-#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
-
 static inline void msm_kms_init(struct msm_kms *kms,
 		const struct msm_kms_funcs *funcs)
 {
-- 
Sean Paul, Software Engineer, Google / Chromium OS

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH v3] drm/msm: Use atomic private_obj instead of subclassing
       [not found]                     ` <20180319195853.49006-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2018-03-20 11:01                       ` Archit Taneja
       [not found]                         ` <41aebf2e-48a0-a2e2-167c-70da912353f4-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
  0 siblings, 1 reply; 49+ messages in thread
From: Archit Taneja @ 2018-03-20 11:01 UTC (permalink / raw)
  To: Sean Paul, freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: jsanka-sgV2jX0FEOL9JmXXK+q4OQ, robdclark-Re5JQEeQqe8AvxtiuMwx3w,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ

Hi,

On Tuesday 20 March 2018 01:28 AM, Sean Paul wrote:
> Instead of subclassing atomic state, store driver private data in
> private_obj/state. This allows us to remove the swap_state driver hook
> for mdp5 and get closer to using the atomic helpers entirely.
> 
> Changes in v2:
>   - Use state->state in disp duplicate_state callback (Jeykumar)
> Changes in v3:
>   - Update comment describing msm_kms_state (Jeykumar)
> 

One difference w.r.t the patchset
"drm/msm/mdp5: Use the new private_obj state" is that this
adds the atomic private_obj for all kms backends, whereas the one
I'd done originally just added it for mdp5, so this patch set
is better in that respect.

The other difference is how we 'get' the private state. In this patch,
the helper drm_atomic_get_private_obj_state() is used every time to
get the private object state.

I'd tried to do the same initially, but I noticed that
drm_atomic_get_private_obj_state() doesn't return the correct
state post swapping of states. So, instead of relying on the helper,
I created a helper called mdp5_get_existing_global_state() that
returns the desired state(the state pointer in msm_kms>state->base.state 
in this patch) in all funcs that are called post-swap.


You could read about the issue on the the thread: "[RFC 1/3] 
drm/msm/mdp5: Add global state as a private atomic object"

The problem was quite apparent with db410c, where SMP blocks are
assigned to planes. If the latest SMP state isn't referred when
configuring SMP registers, we see underruns immediately.

An easy way to reproduce this is to use modset on db410c. I think
it might occur with this patch too. It might be worth trying it
out.

Thanks,
Archit

> Cc: Jeykumar Sankaran <jsanka@codeaurora.org>
> Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>
> ---
>   drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 37 ++++++--------
>   drivers/gpu/drm/msm/msm_atomic.c         | 30 -----------
>   drivers/gpu/drm/msm/msm_drv.c            | 65 ++++++++++++++++++++++--
>   drivers/gpu/drm/msm/msm_drv.h            |  4 +-
>   drivers/gpu/drm/msm/msm_kms.h            | 27 +++++-----
>   5 files changed, 94 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> index 6d8e3a9a6fc0..f1a248419655 100644
> --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
> @@ -74,36 +74,32 @@ struct mdp5_state *mdp5_get_state(struct drm_atomic_state *s)
>   {
>   	struct msm_drm_private *priv = s->dev->dev_private;
>   	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
> -	struct msm_kms_state *state = to_kms_state(s);
> -	struct mdp5_state *new_state;
> +	struct msm_kms_state *kms_state;
>   	int ret;
>   
> -	if (state->state)
> -		return state->state;
> -
>   	ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
>   	if (ret)
>   		return ERR_PTR(ret);
>   
> -	new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
> -	if (!new_state)
> -		return ERR_PTR(-ENOMEM);
> +	kms_state = msm_kms_get_state(s);
> +	if (IS_ERR_OR_NULL(kms_state))
> +		return (struct mdp5_state *)kms_state; /* casting ERR_PTR */
>   
> -	/* Copy state: */
> -	new_state->hwpipe = mdp5_kms->state->hwpipe;
> -	new_state->hwmixer = mdp5_kms->state->hwmixer;
> -	if (mdp5_kms->smp)
> -		new_state->smp = mdp5_kms->state->smp;
> +	return kms_state->state;
> +}
>   
> -	state->state = new_state;
> +static void *mdp5_duplicate_state(void *state)
> +{
> +	if (!state)
> +		return kzalloc(sizeof(struct mdp5_state), GFP_KERNEL);
>   
> -	return new_state;
> +	return kmemdup(state, sizeof(struct mdp5_state), GFP_KERNEL);
>   }
>   
> -static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)
> +static void mdp5_destroy_state(void *state)
>   {
> -	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
> -	swap(to_kms_state(state)->state, mdp5_kms->state);
> +	struct mdp5_state *mdp_state = state;
> +	kfree(mdp_state);
>   }
>   
>   static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
> @@ -229,7 +225,8 @@ static const struct mdp_kms_funcs kms_funcs = {
>   		.irq             = mdp5_irq,
>   		.enable_vblank   = mdp5_enable_vblank,
>   		.disable_vblank  = mdp5_disable_vblank,
> -		.swap_state      = mdp5_swap_state,
> +		.duplicate_state = mdp5_duplicate_state,
> +		.destroy_state	 = mdp5_destroy_state,
>   		.prepare_commit  = mdp5_prepare_commit,
>   		.complete_commit = mdp5_complete_commit,
>   		.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
> @@ -726,8 +723,6 @@ static void mdp5_destroy(struct platform_device *pdev)
>   
>   	if (mdp5_kms->rpm_enabled)
>   		pm_runtime_disable(&pdev->dev);
> -
> -	kfree(mdp5_kms->state);
>   }
>   
>   static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
> diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
> index 7e54eb65d096..1f53262ea46b 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -169,9 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
>   	 */
>   	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
>   
> -	if (to_kms_state(state)->state)
> -		priv->kms->funcs->swap_state(priv->kms, state);
> -
>   	/*
>   	 * Provide the driver a chance to prepare for output fences. This is
>   	 * done after the point of no return, but before asynchronous commits
> @@ -210,30 +207,3 @@ int msm_atomic_commit(struct drm_device *dev,
>   	drm_atomic_helper_cleanup_planes(dev, state);
>   	return ret;
>   }
> -
> -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev)
> -{
> -	struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
> -
> -	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
> -		kfree(state);
> -		return NULL;
> -	}
> -
> -	return &state->base;
> -}
> -
> -void msm_atomic_state_clear(struct drm_atomic_state *s)
> -{
> -	struct msm_kms_state *state = to_kms_state(s);
> -	drm_atomic_state_default_clear(&state->base);
> -	kfree(state->state);
> -	state->state = NULL;
> -}
> -
> -void msm_atomic_state_free(struct drm_atomic_state *state)
> -{
> -	kfree(to_kms_state(state)->state);
> -	drm_atomic_state_default_release(state);
> -	kfree(state);
> -}
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 5219792e93bc..4c0740dc7854 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -121,9 +121,62 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
>   	.output_poll_changed = msm_fb_output_poll_changed,
>   	.atomic_check = drm_atomic_helper_check,
>   	.atomic_commit = msm_atomic_commit,
> -	.atomic_state_alloc = msm_atomic_state_alloc,
> -	.atomic_state_clear = msm_atomic_state_clear,
> -	.atomic_state_free = msm_atomic_state_free,
> +};
> +
> +static inline
> +struct msm_kms *obj_to_kms(struct drm_private_obj *obj)
> +{
> +	return container_of(obj, struct msm_kms, base);
> +}
> +
> +static inline
> +struct msm_kms_state *state_to_kms_state(struct drm_private_state *state)
> +{
> +	return container_of(state, struct msm_kms_state, base);
> +}
> +
> +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *s)
> +{
> +	struct msm_drm_private *priv = s->dev->dev_private;
> +	struct drm_private_obj *obj = &priv->kms->base;
> +	struct drm_private_state *state;
> +
> +	state = drm_atomic_get_private_obj_state(s, obj);
> +	if (IS_ERR_OR_NULL(state))
> +		return (struct msm_kms_state *)state; /* casting ERR_PTR */
> +
> +	return state_to_kms_state(state);
> +}
> +
> +static struct drm_private_state *
> +msm_kms_duplicate_state(struct drm_private_obj *obj)
> +{
> +	struct msm_kms *kms = obj_to_kms(obj);
> +	struct msm_kms_state *state = state_to_kms_state(obj->state);
> +	struct msm_kms_state *new_state;
> +
> +	if (kms->funcs->duplicate_state)
> +		new_state = kms->funcs->duplicate_state(state->state);
> +
> +	__drm_atomic_helper_private_obj_duplicate_state(obj, &new_state->base);
> +
> +	return &new_state->base;
> +}
> +
> +static void msm_kms_destroy_state(struct drm_private_obj *obj,
> +				  struct drm_private_state *state)
> +{
> +	struct msm_kms *kms = obj_to_kms(obj);
> +	struct msm_kms_state *kms_state = state_to_kms_state(obj->state);
> +
> +	if (kms->funcs->destroy_state)
> +		kms->funcs->destroy_state(kms_state->state);
> +	kfree(kms_state);
> +}
> +
> +static const struct drm_private_state_funcs kms_state_funcs = {
> +	.atomic_duplicate_state = msm_kms_duplicate_state,
> +	.atomic_destroy_state = msm_kms_destroy_state,
>   };
>   
>   #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
> @@ -341,6 +394,8 @@ static int msm_drm_uninit(struct device *dev)
>   		}
>   	}
>   
> +	drm_atomic_private_obj_fini(&kms->base);
> +
>   	msm_gem_shrinker_cleanup(ddev);
>   
>   	drm_kms_helper_poll_fini(ddev);
> @@ -770,6 +825,10 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
>   	}
>   #endif
>   
> +	drm_atomic_private_obj_init(&kms->base,
> +				    &kms->state.base,
> +				    &kms_state_funcs);
> +
>   	/* perform subdriver post initialization */
>   	if (kms && kms->funcs && kms->funcs->postinit) {
>   		ret = kms->funcs->postinit(kms);
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index 292496b682e8..8cab333df717 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -598,9 +598,7 @@ struct msm_format {
>   
>   int msm_atomic_commit(struct drm_device *dev,
>   		struct drm_atomic_state *state, bool nonblock);
> -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
> -void msm_atomic_state_clear(struct drm_atomic_state *state);
> -void msm_atomic_state_free(struct drm_atomic_state *state);
> +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *state);
>   
>   void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
>   		struct msm_gem_vma *vma, struct sg_table *sgt);
> diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
> index 09ba1e79db50..5c1bcaf65fd9 100644
> --- a/drivers/gpu/drm/msm/msm_kms.h
> +++ b/drivers/gpu/drm/msm/msm_kms.h
> @@ -57,6 +57,8 @@ struct msm_kms_funcs {
>   	void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
>   	/* swap global atomic state: */
>   	void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state *state);
> +	void *(*duplicate_state)(void *state);
> +	void (*destroy_state)(void *state);
>   	/* modeset, bracketing atomic_commit(): */
>   	void (*prepare_fence)(struct msm_kms *kms,
>   			struct drm_atomic_state *state);
> @@ -114,7 +116,20 @@ struct msm_kms_funcs {
>   #endif
>   };
>   
> +/**
> + * Subclass of drm_private_state, to allow kms backend to have driver
> + * private global state.  The kms backend can do whatever it wants
> + * with the ->state ptr.
> + */
> +struct msm_kms_state {
> +	struct drm_private_state base;
> +	void *state;
> +};
> +
>   struct msm_kms {
> +	struct drm_private_obj base;
> +	struct msm_kms_state state;
> +
>   	const struct msm_kms_funcs *funcs;
>   
>   	/* irq number to be passed on to drm_irq_install */
> @@ -124,18 +139,6 @@ struct msm_kms {
>   	struct msm_gem_address_space *aspace;
>   };
>   
> -/**
> - * Subclass of drm_atomic_state, to allow kms backend to have driver
> - * private global state.  The kms backend can do whatever it wants
> - * with the ->state ptr.  On ->atomic_state_clear() the ->state ptr
> - * is kfree'd and set back to NULL.
> - */
> -struct msm_kms_state {
> -	struct drm_atomic_state base;
> -	void *state;
> -};
> -#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
> -
>   static inline void msm_kms_init(struct msm_kms *kms,
>   		const struct msm_kms_funcs *funcs)
>   {
> 
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

* Re: [DPU PATCH v3] drm/msm: Use atomic private_obj instead of subclassing
       [not found]                         ` <41aebf2e-48a0-a2e2-167c-70da912353f4-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
@ 2018-05-25  1:16                           ` Jeykumar Sankaran
  0 siblings, 0 replies; 49+ messages in thread
From: Jeykumar Sankaran @ 2018-05-25  1:16 UTC (permalink / raw)
  To: Archit Taneja
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	robdclark-Re5JQEeQqe8AvxtiuMwx3w, Sean Paul,
	abhinavk-sgV2jX0FEOL9JmXXK+q4OQ,
	hoegsberg-F7+t8E8rja9g9hUCZPvPmw,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On 2018-03-20 04:01, Archit Taneja wrote:
> Hi,
> 
> On Tuesday 20 March 2018 01:28 AM, Sean Paul wrote:
>> Instead of subclassing atomic state, store driver private data in
>> private_obj/state. This allows us to remove the swap_state driver hook
>> for mdp5 and get closer to using the atomic helpers entirely.
>> 
>> Changes in v2:
>>   - Use state->state in disp duplicate_state callback (Jeykumar)
>> Changes in v3:
>>   - Update comment describing msm_kms_state (Jeykumar)
>> 
> 
> One difference w.r.t the patchset
> "drm/msm/mdp5: Use the new private_obj state" is that this
> adds the atomic private_obj for all kms backends, whereas the one
> I'd done originally just added it for mdp5, so this patch set
> is better in that respect.
> 
> The other difference is how we 'get' the private state. In this patch,
> the helper drm_atomic_get_private_obj_state() is used every time to
> get the private object state.
> 
> I'd tried to do the same initially, but I noticed that
> drm_atomic_get_private_obj_state() doesn't return the correct
> state post swapping of states. So, instead of relying on the helper,
> I created a helper called mdp5_get_existing_global_state() that
> returns the desired state(the state pointer in 
> msm_kms>state->base.state
> in this patch) in all funcs that are called post-swap.
> 
> 
> You could read about the issue on the the thread: "[RFC 1/3]
> drm/msm/mdp5: Add global state as a private atomic object"
> 
> The problem was quite apparent with db410c, where SMP blocks are
> assigned to planes. If the latest SMP state isn't referred when
> configuring SMP registers, we see underruns immediately.
> 
> An easy way to reproduce this is to use modset on db410c. I think
> it might occur with this patch too. It might be worth trying it
> out.
> 
> Thanks,
> Archit
> 
Hello Archit, Now that I am trying to use the private obj to maintain 
resource pool in DPU, I realize the need for retrieving existing / new 
state API's. Don't you think this support is missing in the DRM core 
fwk, considering how drm_atomic_get_existing_XXXX_state, 
drm_atomic_get_old_XXXX_state, drm_atomic_get_new_XXXX_state API's are 
available for CRTC/PLANE and CONNECTORS but not for private_obj's?

Thanks,
Jeykumar S.
>> Cc: Jeykumar Sankaran <jsanka@codeaurora.org>
>> Reviewed-by: Jeykumar Sankaran <jsanka@codeaurora.org>
>> Signed-off-by: Sean Paul <seanpaul@chromium.org>
>> ---
>>   drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 37 ++++++--------
>>   drivers/gpu/drm/msm/msm_atomic.c         | 30 -----------
>>   drivers/gpu/drm/msm/msm_drv.c            | 65 
>> ++++++++++++++++++++++--
>>   drivers/gpu/drm/msm/msm_drv.h            |  4 +-
>>   drivers/gpu/drm/msm/msm_kms.h            | 27 +++++-----
>>   5 files changed, 94 insertions(+), 69 deletions(-)
>> 
>> diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c 
>> b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
>> index 6d8e3a9a6fc0..f1a248419655 100644
>> --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
>> +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
>> @@ -74,36 +74,32 @@ struct mdp5_state *mdp5_get_state(struct 
>> drm_atomic_state *s)
>>   {
>>   	struct msm_drm_private *priv = s->dev->dev_private;
>>   	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
>> -	struct msm_kms_state *state = to_kms_state(s);
>> -	struct mdp5_state *new_state;
>> +	struct msm_kms_state *kms_state;
>>   	int ret;
>> 
>> -	if (state->state)
>> -		return state->state;
>> -
>>   	ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
>>   	if (ret)
>>   		return ERR_PTR(ret);
>> 
>> -	new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
>> -	if (!new_state)
>> -		return ERR_PTR(-ENOMEM);
>> +	kms_state = msm_kms_get_state(s);
>> +	if (IS_ERR_OR_NULL(kms_state))
>> +		return (struct mdp5_state *)kms_state; /* casting ERR_PTR */
>> 
>> -	/* Copy state: */
>> -	new_state->hwpipe = mdp5_kms->state->hwpipe;
>> -	new_state->hwmixer = mdp5_kms->state->hwmixer;
>> -	if (mdp5_kms->smp)
>> -		new_state->smp = mdp5_kms->state->smp;
>> +	return kms_state->state;
>> +}
>> 
>> -	state->state = new_state;
>> +static void *mdp5_duplicate_state(void *state)
>> +{
>> +	if (!state)
>> +		return kzalloc(sizeof(struct mdp5_state), GFP_KERNEL);
>> 
>> -	return new_state;
>> +	return kmemdup(state, sizeof(struct mdp5_state), GFP_KERNEL);
>>   }
>> 
>> -static void mdp5_swap_state(struct msm_kms *kms, struct 
>> drm_atomic_state *state)
>> +static void mdp5_destroy_state(void *state)
>>   {
>> -	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
>> -	swap(to_kms_state(state)->state, mdp5_kms->state);
>> +	struct mdp5_state *mdp_state = state;
>> +	kfree(mdp_state);
>>   }
>> 
>>   static void mdp5_prepare_commit(struct msm_kms *kms, struct 
>> drm_atomic_state *state)
>> @@ -229,7 +225,8 @@ static const struct mdp_kms_funcs kms_funcs = {
>>   		.irq             = mdp5_irq,
>>   		.enable_vblank   = mdp5_enable_vblank,
>>   		.disable_vblank  = mdp5_disable_vblank,
>> -		.swap_state      = mdp5_swap_state,
>> +		.duplicate_state = mdp5_duplicate_state,
>> +		.destroy_state	 = mdp5_destroy_state,
>>   		.prepare_commit  = mdp5_prepare_commit,
>>   		.complete_commit = mdp5_complete_commit,
>>   		.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
>> @@ -726,8 +723,6 @@ static void mdp5_destroy(struct platform_device 
>> *pdev)
>> 
>>   	if (mdp5_kms->rpm_enabled)
>>   		pm_runtime_disable(&pdev->dev);
>> -
>> -	kfree(mdp5_kms->state);
>>   }
>> 
>>   static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
>> diff --git a/drivers/gpu/drm/msm/msm_atomic.c 
>> b/drivers/gpu/drm/msm/msm_atomic.c
>> index 7e54eb65d096..1f53262ea46b 100644
>> --- a/drivers/gpu/drm/msm/msm_atomic.c
>> +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> @@ -169,9 +169,6 @@ int msm_atomic_commit(struct drm_device *dev,
>>   	 */
>>   	BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
>> 
>> -	if (to_kms_state(state)->state)
>> -		priv->kms->funcs->swap_state(priv->kms, state);
>> -
>>   	/*
>>   	 * Provide the driver a chance to prepare for output fences. This 
>> is
>>   	 * done after the point of no return, but before asynchronous 
>> commits
>> @@ -210,30 +207,3 @@ int msm_atomic_commit(struct drm_device *dev,
>>   	drm_atomic_helper_cleanup_planes(dev, state);
>>   	return ret;
>>   }
>> -
>> -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device 
>> *dev)
>> -{
>> -	struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
>> -
>> -	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
>> -		kfree(state);
>> -		return NULL;
>> -	}
>> -
>> -	return &state->base;
>> -}
>> -
>> -void msm_atomic_state_clear(struct drm_atomic_state *s)
>> -{
>> -	struct msm_kms_state *state = to_kms_state(s);
>> -	drm_atomic_state_default_clear(&state->base);
>> -	kfree(state->state);
>> -	state->state = NULL;
>> -}
>> -
>> -void msm_atomic_state_free(struct drm_atomic_state *state)
>> -{
>> -	kfree(to_kms_state(state)->state);
>> -	drm_atomic_state_default_release(state);
>> -	kfree(state);
>> -}
>> diff --git a/drivers/gpu/drm/msm/msm_drv.c 
>> b/drivers/gpu/drm/msm/msm_drv.c
>> index 5219792e93bc..4c0740dc7854 100644
>> --- a/drivers/gpu/drm/msm/msm_drv.c
>> +++ b/drivers/gpu/drm/msm/msm_drv.c
>> @@ -121,9 +121,62 @@ static const struct drm_mode_config_funcs 
>> mode_config_funcs = {
>>   	.output_poll_changed = msm_fb_output_poll_changed,
>>   	.atomic_check = drm_atomic_helper_check,
>>   	.atomic_commit = msm_atomic_commit,
>> -	.atomic_state_alloc = msm_atomic_state_alloc,
>> -	.atomic_state_clear = msm_atomic_state_clear,
>> -	.atomic_state_free = msm_atomic_state_free,
>> +};
>> +
>> +static inline
>> +struct msm_kms *obj_to_kms(struct drm_private_obj *obj)
>> +{
>> +	return container_of(obj, struct msm_kms, base);
>> +}
>> +
>> +static inline
>> +struct msm_kms_state *state_to_kms_state(struct drm_private_state 
>> *state)
>> +{
>> +	return container_of(state, struct msm_kms_state, base);
>> +}
>> +
>> +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state *s)
>> +{
>> +	struct msm_drm_private *priv = s->dev->dev_private;
>> +	struct drm_private_obj *obj = &priv->kms->base;
>> +	struct drm_private_state *state;
>> +
>> +	state = drm_atomic_get_private_obj_state(s, obj);
>> +	if (IS_ERR_OR_NULL(state))
>> +		return (struct msm_kms_state *)state; /* casting ERR_PTR */
>> +
>> +	return state_to_kms_state(state);
>> +}
>> +
>> +static struct drm_private_state *
>> +msm_kms_duplicate_state(struct drm_private_obj *obj)
>> +{
>> +	struct msm_kms *kms = obj_to_kms(obj);
>> +	struct msm_kms_state *state = state_to_kms_state(obj->state);
>> +	struct msm_kms_state *new_state;
>> +
>> +	if (kms->funcs->duplicate_state)
>> +		new_state = kms->funcs->duplicate_state(state->state);
>> +
>> +	__drm_atomic_helper_private_obj_duplicate_state(obj, 
>> &new_state->base);
>> +
>> +	return &new_state->base;
>> +}
>> +
>> +static void msm_kms_destroy_state(struct drm_private_obj *obj,
>> +				  struct drm_private_state *state)
>> +{
>> +	struct msm_kms *kms = obj_to_kms(obj);
>> +	struct msm_kms_state *kms_state = state_to_kms_state(obj->state);
>> +
>> +	if (kms->funcs->destroy_state)
>> +		kms->funcs->destroy_state(kms_state->state);
>> +	kfree(kms_state);
>> +}
>> +
>> +static const struct drm_private_state_funcs kms_state_funcs = {
>> +	.atomic_duplicate_state = msm_kms_duplicate_state,
>> +	.atomic_destroy_state = msm_kms_destroy_state,
>>   };
>> 
>>   #ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
>> @@ -341,6 +394,8 @@ static int msm_drm_uninit(struct device *dev)
>>   		}
>>   	}
>> 
>> +	drm_atomic_private_obj_fini(&kms->base);
>> +
>>   	msm_gem_shrinker_cleanup(ddev);
>> 
>>   	drm_kms_helper_poll_fini(ddev);
>> @@ -770,6 +825,10 @@ static int msm_drm_init(struct device *dev, 
>> struct drm_driver *drv)
>>   	}
>>   #endif
>> 
>> +	drm_atomic_private_obj_init(&kms->base,
>> +				    &kms->state.base,
>> +				    &kms_state_funcs);
>> +
>>   	/* perform subdriver post initialization */
>>   	if (kms && kms->funcs && kms->funcs->postinit) {
>>   		ret = kms->funcs->postinit(kms);
>> diff --git a/drivers/gpu/drm/msm/msm_drv.h 
>> b/drivers/gpu/drm/msm/msm_drv.h
>> index 292496b682e8..8cab333df717 100644
>> --- a/drivers/gpu/drm/msm/msm_drv.h
>> +++ b/drivers/gpu/drm/msm/msm_drv.h
>> @@ -598,9 +598,7 @@ struct msm_format {
>> 
>>   int msm_atomic_commit(struct drm_device *dev,
>>   		struct drm_atomic_state *state, bool nonblock);
>> -struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device 
>> *dev);
>> -void msm_atomic_state_clear(struct drm_atomic_state *state);
>> -void msm_atomic_state_free(struct drm_atomic_state *state);
>> +struct msm_kms_state *msm_kms_get_state(struct drm_atomic_state 
>> *state);
>> 
>>   void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
>>   		struct msm_gem_vma *vma, struct sg_table *sgt);
>> diff --git a/drivers/gpu/drm/msm/msm_kms.h 
>> b/drivers/gpu/drm/msm/msm_kms.h
>> index 09ba1e79db50..5c1bcaf65fd9 100644
>> --- a/drivers/gpu/drm/msm/msm_kms.h
>> +++ b/drivers/gpu/drm/msm/msm_kms.h
>> @@ -57,6 +57,8 @@ struct msm_kms_funcs {
>>   	void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
>>   	/* swap global atomic state: */
>>   	void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state 
>> *state);
>> +	void *(*duplicate_state)(void *state);
>> +	void (*destroy_state)(void *state);
>>   	/* modeset, bracketing atomic_commit(): */
>>   	void (*prepare_fence)(struct msm_kms *kms,
>>   			struct drm_atomic_state *state);
>> @@ -114,7 +116,20 @@ struct msm_kms_funcs {
>>   #endif
>>   };
>> 
>> +/**
>> + * Subclass of drm_private_state, to allow kms backend to have driver
>> + * private global state.  The kms backend can do whatever it wants
>> + * with the ->state ptr.
>> + */
>> +struct msm_kms_state {
>> +	struct drm_private_state base;
>> +	void *state;
>> +};
>> +
>>   struct msm_kms {
>> +	struct drm_private_obj base;
>> +	struct msm_kms_state state;
>> +
>>   	const struct msm_kms_funcs *funcs;
>> 
>>   	/* irq number to be passed on to drm_irq_install */
>> @@ -124,18 +139,6 @@ struct msm_kms {
>>   	struct msm_gem_address_space *aspace;
>>   };
>> 
>> -/**
>> - * Subclass of drm_atomic_state, to allow kms backend to have driver
>> - * private global state.  The kms backend can do whatever it wants
>> - * with the ->state ptr.  On ->atomic_state_clear() the ->state ptr
>> - * is kfree'd and set back to NULL.
>> - */
>> -struct msm_kms_state {
>> -	struct drm_atomic_state base;
>> -	void *state;
>> -};
>> -#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
>> -
>>   static inline void msm_kms_init(struct msm_kms *kms,
>>   		const struct msm_kms_funcs *funcs)
>>   {
>> 

-- 
Jeykumar S
_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

^ permalink raw reply	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2018-05-25  1:16 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-28 19:18 [DPU PATCH 00/11] drm/msm: Use atomic helper functions for msm Sean Paul
     [not found] ` <20180228191906.185417-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-02-28 19:18   ` [DPU PATCH 01/11] drm/msm: Skip seamless disables in crtc/encoder Sean Paul
2018-03-03  0:04     ` jsanka
     [not found]       ` <d51bfdafccd143ee258fc995a7cafecc-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-03-12 20:14         ` Sean Paul
2018-03-13 18:10           ` Jeykumar Sankaran
2018-02-28 19:18   ` [DPU PATCH 02/11] drm/msm: Don't duplicate modeset_enables atomic helper Sean Paul
     [not found]     ` <20180228191906.185417-3-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-09  0:56       ` Jeykumar Sankaran
     [not found]         ` <aaf8f07e18801c60cdf7eb30b0cac123-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-03-12 20:21           ` Sean Paul
2018-03-13 23:57             ` Jeykumar Sankaran
     [not found]               ` <677c8c29a788a147aa45bc1e9768527e-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-03-14 15:14                 ` Sean Paul
2018-03-15  1:39                   ` Jeykumar Sankaran
     [not found]                     ` <645777c3f76662ce5b0b14bcf7b81acb-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-03-16 19:45                       ` [DPU PATCH v2] " Sean Paul
2018-03-16 20:57                         ` Jeykumar Sankaran
2018-02-28 19:18   ` [DPU PATCH 03/11] drm/msm: Refactor complete_commit() to look more the helpers Sean Paul
     [not found]     ` <20180228191906.185417-4-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-09  1:01       ` Jeykumar Sankaran
2018-02-28 19:18   ` [DPU PATCH 04/11] drm/msm: Move implicit sync fence handling to prepare_fb Sean Paul
     [not found]     ` <20180228191906.185417-5-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-03  0:20       ` jsanka-sgV2jX0FEOL9JmXXK+q4OQ
2018-02-28 19:19   ` [DPU PATCH 05/11] drm/msm: Mark the crtc->state->event consumed Sean Paul
2018-03-06  1:53     ` Jeykumar Sankaran
2018-02-28 19:19   ` [DPU PATCH 06/11] drm/msm: Remove msm_commit/kthread, use atomic helper commit Sean Paul
     [not found]     ` <20180228191906.185417-7-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-01  4:07       ` jsanka-sgV2jX0FEOL9JmXXK+q4OQ
2018-03-01 15:27         ` Sean Paul
2018-03-01 20:37           ` jsanka-sgV2jX0FEOL9JmXXK+q4OQ
     [not found]             ` <156ab33c41d436c79cc661e84bebc353-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-03-02  0:37               ` Rob Clark
     [not found]                 ` <CAF6AEGvDZ8sWYwwbyPYcQZN6Ba01Gc7db724GeehF3cLY6d-XQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2018-03-02 14:56                   ` Sean Paul
2018-03-09  1:08                     ` Jeykumar Sankaran
2018-03-12 20:23                       ` Sean Paul
2018-03-19 15:01                         ` Sean Paul
2018-03-19 19:54                           ` Jeykumar Sankaran
2018-02-28 19:19   ` [DPU PATCH 07/11] drm/msm: Use atomic private_obj instead of subclassing Sean Paul
     [not found]     ` <20180228191906.185417-8-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-09  1:59       ` Jeykumar Sankaran
     [not found]         ` <7fb92416ee99990f6a1280a617736051-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-03-12 20:28           ` Sean Paul
2018-03-19 17:31             ` [DPU PATCH v2] " Sean Paul
     [not found]               ` <20180319173113.94879-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-19 19:33                 ` Jeykumar Sankaran
2018-03-19 19:58                   ` [DPU PATCH v3] " Sean Paul
     [not found]                     ` <20180319195853.49006-1-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-20 11:01                       ` Archit Taneja
     [not found]                         ` <41aebf2e-48a0-a2e2-167c-70da912353f4-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-05-25  1:16                           ` Jeykumar Sankaran
2018-02-28 19:19   ` [DPU PATCH 08/11] drm/msm: Remove hand-rolled out fences Sean Paul
     [not found]     ` <20180228191906.185417-9-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-03  0:44       ` Jeykumar Sankaran
     [not found]         ` <1a1c79ddb6ddabbc72e4624b53460188-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-03-12 20:30           ` Sean Paul
2018-03-13 18:11             ` Jeykumar Sankaran
2018-02-28 19:19   ` [DPU PATCH 09/11] drm/msm: Remove prepare_fence kms_function Sean Paul
     [not found]     ` <20180228191906.185417-10-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-09  1:28       ` abhinavk-sgV2jX0FEOL9JmXXK+q4OQ
2018-02-28 19:19   ` [DPU PATCH 10/11] drm/msm: Switch to atomic_helper_commit() Sean Paul
     [not found]     ` <20180228191906.185417-11-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-09  3:28       ` abhinavk-sgV2jX0FEOL9JmXXK+q4OQ
     [not found]         ` <bf44a79fc08d00245640694c364b8b03-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2018-03-12 20:32           ` Sean Paul
2018-03-13  2:08             ` abhinavk-sgV2jX0FEOL9JmXXK+q4OQ
2018-02-28 19:19   ` [DPU PATCH 11/11] drm/msm: Remove dpu input fences Sean Paul
     [not found]     ` <20180228191906.185417-12-seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2018-03-03  0:50       ` Jeykumar Sankaran

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.