All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-06-28 13:28 ` Maarten Lankhorst
  0 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-06-28 13:28 UTC (permalink / raw)
  To: dri-devel
  Cc: David Airlie, nouveau, Thierry Reding, Daniel Vetter,
	Boris Brezillon, Jonathan Hunter, Tomi Valkeinen, Ben Skeggs,
	CK Hu, linux-tegra, linux-arm-msm, intel-gfx, linux-mediatek,
	Jyri Sarha, Matthias Brugger, linux-arm-kernel, linux-kernel,
	Philipp Zabel, freedreno

We want to change swap_state to wait indefinitely, but to do this
swap_state should wait interruptibly. This requires propagating
the error to each driver. All drivers have changes to deal with the
clean up. In order to allow easy reverting, the commit that changes
behavior is separate so someone only has to revert that for testing.

Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
failed cleanup_planes was not called.

Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: CK Hu <ck.hu@mediatek.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Jyri Sarha <jsarha@ti.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Cc: intel-gfx@lists.freedesktop.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-mediatek@lists.infradead.org
Cc: linux-arm-msm@vger.kernel.org
Cc: freedreno@lists.freedesktop.org
Cc: nouveau@lists.freedesktop.org
Cc: linux-tegra@vger.kernel.org
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
 drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
 drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
 drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
 drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
 drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
 drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
 drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
 drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
 include/drm/drm_atomic_helper.h              |  4 ++--
 10 files changed, 82 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 516d9547d331..d4f787bf1d4a 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
 		goto error;
 	}
 
-	/* Swap the state, this is the point of no return. */
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err_pending;
 
+	/* Swap state succeeded, this is the point of no return. */
 	drm_atomic_state_get(state);
 	if (async)
 		queue_work(dc->wq, &commit->work);
@@ -555,6 +557,14 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
 
 	return 0;
 
+err_pending:
+	/* Fail the commit, wake up any waiter. */
+	spin_lock(&dc->commit.wait.lock);
+	dc->commit.pending = false;
+	wake_up_all_locked(&dc->commit.wait);
+	spin_unlock(&dc->commit.wait.lock);
+err_free:
+	kfree(commit);
 error:
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index f1847d29ba3e..f66b6c45cdd0 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1387,10 +1387,8 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
-		if (ret) {
-			drm_atomic_helper_cleanup_planes(dev, state);
-			return ret;
-		}
+		if (ret)
+			goto err;
 	}
 
 	/*
@@ -1399,7 +1397,9 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 	 * the software side now.
 	 */
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err;
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
@@ -1428,6 +1428,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 		commit_tail(state);
 
 	return 0;
+
+err:
+	drm_atomic_helper_cleanup_planes(dev, state);
+	return ret;
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit);
 
@@ -2137,7 +2141,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
  * the current atomic helpers this is almost always the case, since the helpers
  * don't pass the right state structures to the callbacks.
  */
-void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
+int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 				  bool stall)
 {
 	int i;
@@ -2214,6 +2218,8 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 
 	__for_each_private_obj(state, obj, obj_state, i, funcs)
 		funcs->swap_state(obj, &state->private_objs[i].obj_state);
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_atomic_helper_swap_state);
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7d416428bdc1..e211d703fe2e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13183,7 +13183,15 @@ static int intel_atomic_commit(struct drm_device *dev,
 	if (INTEL_GEN(dev_priv) < 9)
 		state->legacy_cursor_update = false;
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret) {
+		i915_sw_fence_commit(&intel_state->commit_ready);
+
+		mutex_lock(&dev->struct_mutex);
+		drm_atomic_helper_cleanup_planes(dev, state);
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
 	dev_priv->wm.distrust_bios_wm = false;
 	intel_shared_dpll_swap_state(state);
 	intel_atomic_track_fbs(state);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 56f802d0a51c..9a130c84c861 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -109,7 +109,12 @@ static int mtk_atomic_commit(struct drm_device *drm,
 	mutex_lock(&private->commit.lock);
 	flush_work(&private->commit.work);
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret) {
+		mutex_unlock(&private->commit.lock);
+		drm_atomic_helper_cleanup_planes(drm, state);
+		return ret;
+	}
 
 	drm_atomic_state_get(state);
 	if (async)
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 9633a68b14d7..85dd485fdef4 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -232,8 +232,12 @@ int msm_atomic_commit(struct drm_device *dev,
 	 * mark our set of crtc's as busy:
 	 */
 	ret = start_atomic(dev->dev_private, c->crtc_mask);
+	if (ret)
+		goto err_free;
+
+	ret = drm_atomic_helper_swap_state(state, true);
 	if (ret) {
-		kfree(c);
+		commit_destroy(c);
 		goto error;
 	}
 
@@ -241,11 +245,9 @@ int msm_atomic_commit(struct drm_device *dev,
 	 * 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
 	 */
-
-	drm_atomic_helper_swap_state(state, true);
-
-	/* swap driver private state while still holding state_lock */
 	if (to_kms_state(state)->state)
 		priv->kms->funcs->swap_state(priv->kms, state);
 
@@ -275,6 +277,8 @@ int msm_atomic_commit(struct drm_device *dev,
 
 	return 0;
 
+err_free:
+	kfree(c);
 error:
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 42a85c14aea0..fb2c763c88a8 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -4119,9 +4119,13 @@ nv50_disp_atomic_commit(struct drm_device *dev,
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
 		if (ret)
-			goto done;
+			goto err_cleanup;
 	}
 
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err_cleanup;
+
 	for_each_plane_in_state(state, plane, plane_state, i) {
 		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
 		struct nv50_wndw *wndw = nv50_wndw(plane);
@@ -4135,7 +4139,6 @@ nv50_disp_atomic_commit(struct drm_device *dev,
 		}
 	}
 
-	drm_atomic_helper_swap_state(state, true);
 	drm_atomic_state_get(state);
 
 	if (nonblock)
@@ -4158,7 +4161,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
 		pm_runtime_put_autosuspend(dev->dev);
 		drm->have_disp_power_ref = false;
 	}
+	goto done;
 
+err_cleanup:
+	drm_atomic_helper_cleanup_planes(dev, state);
 done:
 	pm_runtime_put_autosuspend(dev->dev);
 	return ret;
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index ad3d124a972d..3ba659a5940d 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -100,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm,
 	 * the software side now.
 	 */
 
-	drm_atomic_helper_swap_state(state, true);
+	err = drm_atomic_helper_swap_state(state, true);
+	if (err) {
+		mutex_unlock(&tegra->commit.lock);
+		drm_atomic_helper_cleanup_planes(drm, state);
+		return err;
+	}
 
 	drm_atomic_state_get(state);
 	if (nonblock)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index d67e18983a7d..049d2f5a1ee4 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -108,7 +108,11 @@ static int tilcdc_commit(struct drm_device *dev,
 	if (ret)
 		return ret;
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret) {
+		drm_atomic_helper_cleanup_planes(dev, state);
+		return ret;
+	}
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 27edae427025..83952a4014a5 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -113,20 +113,20 @@ static int vc4_atomic_commit(struct drm_device *dev,
 
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
-		if (ret) {
-			drm_atomic_helper_cleanup_planes(dev, state);
-			up(&vc4->async_modeset);
-			return ret;
-		}
+		if (ret)
+			goto err;
 	}
 
 	/*
-	 * 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
+	 * If swap_state() succeeds, 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.
 	 */
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err;
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
@@ -151,6 +151,11 @@ static int vc4_atomic_commit(struct drm_device *dev,
 		vc4_atomic_complete_commit(state);
 
 	return 0;
+
+err:
+	drm_atomic_helper_cleanup_planes(dev, state);
+	up(&vc4->async_modeset);
+	return ret;
 }
 
 static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 3bfeb2b2f746..4f3b6b5362ec 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -80,8 +80,8 @@ void
 drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state,
 					 bool atomic);
 
-void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
-				  bool stall);
+int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
+					      bool stall);
 
 /* nonblocking commit helpers */
 int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-06-28 13:28 ` Maarten Lankhorst
  0 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-06-28 13:28 UTC (permalink / raw)
  To: dri-devel
  Cc: Maarten Lankhorst, Boris Brezillon, David Airlie, Daniel Vetter,
	Jani Nikula, Sean Paul, CK Hu, Philipp Zabel, Matthias Brugger,
	Rob Clark, Ben Skeggs, Thierry Reding, Jonathan Hunter,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, linux-kernel, intel-gfx,
	linux-arm-kernel, linux-mediatek, linux-arm-msm, freedreno,
	nouveau, linux-tegra

We want to change swap_state to wait indefinitely, but to do this
swap_state should wait interruptibly. This requires propagating
the error to each driver. All drivers have changes to deal with the
clean up. In order to allow easy reverting, the commit that changes
behavior is separate so someone only has to revert that for testing.

Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
failed cleanup_planes was not called.

Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: CK Hu <ck.hu@mediatek.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Jyri Sarha <jsarha@ti.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Cc: intel-gfx@lists.freedesktop.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-mediatek@lists.infradead.org
Cc: linux-arm-msm@vger.kernel.org
Cc: freedreno@lists.freedesktop.org
Cc: nouveau@lists.freedesktop.org
Cc: linux-tegra@vger.kernel.org
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
 drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
 drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
 drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
 drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
 drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
 drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
 drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
 drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
 include/drm/drm_atomic_helper.h              |  4 ++--
 10 files changed, 82 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 516d9547d331..d4f787bf1d4a 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
 		goto error;
 	}
 
-	/* Swap the state, this is the point of no return. */
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err_pending;
 
+	/* Swap state succeeded, this is the point of no return. */
 	drm_atomic_state_get(state);
 	if (async)
 		queue_work(dc->wq, &commit->work);
@@ -555,6 +557,14 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
 
 	return 0;
 
+err_pending:
+	/* Fail the commit, wake up any waiter. */
+	spin_lock(&dc->commit.wait.lock);
+	dc->commit.pending = false;
+	wake_up_all_locked(&dc->commit.wait);
+	spin_unlock(&dc->commit.wait.lock);
+err_free:
+	kfree(commit);
 error:
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index f1847d29ba3e..f66b6c45cdd0 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1387,10 +1387,8 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
-		if (ret) {
-			drm_atomic_helper_cleanup_planes(dev, state);
-			return ret;
-		}
+		if (ret)
+			goto err;
 	}
 
 	/*
@@ -1399,7 +1397,9 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 	 * the software side now.
 	 */
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err;
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
@@ -1428,6 +1428,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 		commit_tail(state);
 
 	return 0;
+
+err:
+	drm_atomic_helper_cleanup_planes(dev, state);
+	return ret;
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit);
 
@@ -2137,7 +2141,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
  * the current atomic helpers this is almost always the case, since the helpers
  * don't pass the right state structures to the callbacks.
  */
-void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
+int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 				  bool stall)
 {
 	int i;
@@ -2214,6 +2218,8 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 
 	__for_each_private_obj(state, obj, obj_state, i, funcs)
 		funcs->swap_state(obj, &state->private_objs[i].obj_state);
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_atomic_helper_swap_state);
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7d416428bdc1..e211d703fe2e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13183,7 +13183,15 @@ static int intel_atomic_commit(struct drm_device *dev,
 	if (INTEL_GEN(dev_priv) < 9)
 		state->legacy_cursor_update = false;
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret) {
+		i915_sw_fence_commit(&intel_state->commit_ready);
+
+		mutex_lock(&dev->struct_mutex);
+		drm_atomic_helper_cleanup_planes(dev, state);
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
 	dev_priv->wm.distrust_bios_wm = false;
 	intel_shared_dpll_swap_state(state);
 	intel_atomic_track_fbs(state);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 56f802d0a51c..9a130c84c861 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -109,7 +109,12 @@ static int mtk_atomic_commit(struct drm_device *drm,
 	mutex_lock(&private->commit.lock);
 	flush_work(&private->commit.work);
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret) {
+		mutex_unlock(&private->commit.lock);
+		drm_atomic_helper_cleanup_planes(drm, state);
+		return ret;
+	}
 
 	drm_atomic_state_get(state);
 	if (async)
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 9633a68b14d7..85dd485fdef4 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -232,8 +232,12 @@ int msm_atomic_commit(struct drm_device *dev,
 	 * mark our set of crtc's as busy:
 	 */
 	ret = start_atomic(dev->dev_private, c->crtc_mask);
+	if (ret)
+		goto err_free;
+
+	ret = drm_atomic_helper_swap_state(state, true);
 	if (ret) {
-		kfree(c);
+		commit_destroy(c);
 		goto error;
 	}
 
@@ -241,11 +245,9 @@ int msm_atomic_commit(struct drm_device *dev,
 	 * 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
 	 */
-
-	drm_atomic_helper_swap_state(state, true);
-
-	/* swap driver private state while still holding state_lock */
 	if (to_kms_state(state)->state)
 		priv->kms->funcs->swap_state(priv->kms, state);
 
@@ -275,6 +277,8 @@ int msm_atomic_commit(struct drm_device *dev,
 
 	return 0;
 
+err_free:
+	kfree(c);
 error:
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 42a85c14aea0..fb2c763c88a8 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -4119,9 +4119,13 @@ nv50_disp_atomic_commit(struct drm_device *dev,
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
 		if (ret)
-			goto done;
+			goto err_cleanup;
 	}
 
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err_cleanup;
+
 	for_each_plane_in_state(state, plane, plane_state, i) {
 		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
 		struct nv50_wndw *wndw = nv50_wndw(plane);
@@ -4135,7 +4139,6 @@ nv50_disp_atomic_commit(struct drm_device *dev,
 		}
 	}
 
-	drm_atomic_helper_swap_state(state, true);
 	drm_atomic_state_get(state);
 
 	if (nonblock)
@@ -4158,7 +4161,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
 		pm_runtime_put_autosuspend(dev->dev);
 		drm->have_disp_power_ref = false;
 	}
+	goto done;
 
+err_cleanup:
+	drm_atomic_helper_cleanup_planes(dev, state);
 done:
 	pm_runtime_put_autosuspend(dev->dev);
 	return ret;
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index ad3d124a972d..3ba659a5940d 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -100,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm,
 	 * the software side now.
 	 */
 
-	drm_atomic_helper_swap_state(state, true);
+	err = drm_atomic_helper_swap_state(state, true);
+	if (err) {
+		mutex_unlock(&tegra->commit.lock);
+		drm_atomic_helper_cleanup_planes(drm, state);
+		return err;
+	}
 
 	drm_atomic_state_get(state);
 	if (nonblock)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index d67e18983a7d..049d2f5a1ee4 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -108,7 +108,11 @@ static int tilcdc_commit(struct drm_device *dev,
 	if (ret)
 		return ret;
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret) {
+		drm_atomic_helper_cleanup_planes(dev, state);
+		return ret;
+	}
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 27edae427025..83952a4014a5 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -113,20 +113,20 @@ static int vc4_atomic_commit(struct drm_device *dev,
 
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
-		if (ret) {
-			drm_atomic_helper_cleanup_planes(dev, state);
-			up(&vc4->async_modeset);
-			return ret;
-		}
+		if (ret)
+			goto err;
 	}
 
 	/*
-	 * 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
+	 * If swap_state() succeeds, 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.
 	 */
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err;
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
@@ -151,6 +151,11 @@ static int vc4_atomic_commit(struct drm_device *dev,
 		vc4_atomic_complete_commit(state);
 
 	return 0;
+
+err:
+	drm_atomic_helper_cleanup_planes(dev, state);
+	up(&vc4->async_modeset);
+	return ret;
 }
 
 static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 3bfeb2b2f746..4f3b6b5362ec 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -80,8 +80,8 @@ void
 drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state,
 					 bool atomic);
 
-void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
-				  bool stall);
+int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
+					      bool stall);
 
 /* nonblocking commit helpers */
 int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
-- 
2.11.0

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

* [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-06-28 13:28 ` Maarten Lankhorst
  0 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-06-28 13:28 UTC (permalink / raw)
  To: linux-arm-kernel

We want to change swap_state to wait indefinitely, but to do this
swap_state should wait interruptibly. This requires propagating
the error to each driver. All drivers have changes to deal with the
clean up. In order to allow easy reverting, the commit that changes
behavior is separate so someone only has to revert that for testing.

Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
failed cleanup_planes was not called.

Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: CK Hu <ck.hu@mediatek.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Jyri Sarha <jsarha@ti.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-kernel at vger.kernel.org
Cc: intel-gfx at lists.freedesktop.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-mediatek at lists.infradead.org
Cc: linux-arm-msm at vger.kernel.org
Cc: freedreno at lists.freedesktop.org
Cc: nouveau at lists.freedesktop.org
Cc: linux-tegra at vger.kernel.org
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
 drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
 drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
 drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
 drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
 drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
 drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
 drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
 drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
 include/drm/drm_atomic_helper.h              |  4 ++--
 10 files changed, 82 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 516d9547d331..d4f787bf1d4a 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
 		goto error;
 	}
 
-	/* Swap the state, this is the point of no return. */
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err_pending;
 
+	/* Swap state succeeded, this is the point of no return. */
 	drm_atomic_state_get(state);
 	if (async)
 		queue_work(dc->wq, &commit->work);
@@ -555,6 +557,14 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
 
 	return 0;
 
+err_pending:
+	/* Fail the commit, wake up any waiter. */
+	spin_lock(&dc->commit.wait.lock);
+	dc->commit.pending = false;
+	wake_up_all_locked(&dc->commit.wait);
+	spin_unlock(&dc->commit.wait.lock);
+err_free:
+	kfree(commit);
 error:
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index f1847d29ba3e..f66b6c45cdd0 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1387,10 +1387,8 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
-		if (ret) {
-			drm_atomic_helper_cleanup_planes(dev, state);
-			return ret;
-		}
+		if (ret)
+			goto err;
 	}
 
 	/*
@@ -1399,7 +1397,9 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 	 * the software side now.
 	 */
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err;
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
@@ -1428,6 +1428,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
 		commit_tail(state);
 
 	return 0;
+
+err:
+	drm_atomic_helper_cleanup_planes(dev, state);
+	return ret;
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit);
 
@@ -2137,7 +2141,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
  * the current atomic helpers this is almost always the case, since the helpers
  * don't pass the right state structures to the callbacks.
  */
-void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
+int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 				  bool stall)
 {
 	int i;
@@ -2214,6 +2218,8 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 
 	__for_each_private_obj(state, obj, obj_state, i, funcs)
 		funcs->swap_state(obj, &state->private_objs[i].obj_state);
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_atomic_helper_swap_state);
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7d416428bdc1..e211d703fe2e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -13183,7 +13183,15 @@ static int intel_atomic_commit(struct drm_device *dev,
 	if (INTEL_GEN(dev_priv) < 9)
 		state->legacy_cursor_update = false;
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret) {
+		i915_sw_fence_commit(&intel_state->commit_ready);
+
+		mutex_lock(&dev->struct_mutex);
+		drm_atomic_helper_cleanup_planes(dev, state);
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
 	dev_priv->wm.distrust_bios_wm = false;
 	intel_shared_dpll_swap_state(state);
 	intel_atomic_track_fbs(state);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 56f802d0a51c..9a130c84c861 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -109,7 +109,12 @@ static int mtk_atomic_commit(struct drm_device *drm,
 	mutex_lock(&private->commit.lock);
 	flush_work(&private->commit.work);
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret) {
+		mutex_unlock(&private->commit.lock);
+		drm_atomic_helper_cleanup_planes(drm, state);
+		return ret;
+	}
 
 	drm_atomic_state_get(state);
 	if (async)
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 9633a68b14d7..85dd485fdef4 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -232,8 +232,12 @@ int msm_atomic_commit(struct drm_device *dev,
 	 * mark our set of crtc's as busy:
 	 */
 	ret = start_atomic(dev->dev_private, c->crtc_mask);
+	if (ret)
+		goto err_free;
+
+	ret = drm_atomic_helper_swap_state(state, true);
 	if (ret) {
-		kfree(c);
+		commit_destroy(c);
 		goto error;
 	}
 
@@ -241,11 +245,9 @@ int msm_atomic_commit(struct drm_device *dev,
 	 * 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
 	 */
-
-	drm_atomic_helper_swap_state(state, true);
-
-	/* swap driver private state while still holding state_lock */
 	if (to_kms_state(state)->state)
 		priv->kms->funcs->swap_state(priv->kms, state);
 
@@ -275,6 +277,8 @@ int msm_atomic_commit(struct drm_device *dev,
 
 	return 0;
 
+err_free:
+	kfree(c);
 error:
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 42a85c14aea0..fb2c763c88a8 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -4119,9 +4119,13 @@ nv50_disp_atomic_commit(struct drm_device *dev,
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
 		if (ret)
-			goto done;
+			goto err_cleanup;
 	}
 
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err_cleanup;
+
 	for_each_plane_in_state(state, plane, plane_state, i) {
 		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
 		struct nv50_wndw *wndw = nv50_wndw(plane);
@@ -4135,7 +4139,6 @@ nv50_disp_atomic_commit(struct drm_device *dev,
 		}
 	}
 
-	drm_atomic_helper_swap_state(state, true);
 	drm_atomic_state_get(state);
 
 	if (nonblock)
@@ -4158,7 +4161,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
 		pm_runtime_put_autosuspend(dev->dev);
 		drm->have_disp_power_ref = false;
 	}
+	goto done;
 
+err_cleanup:
+	drm_atomic_helper_cleanup_planes(dev, state);
 done:
 	pm_runtime_put_autosuspend(dev->dev);
 	return ret;
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index ad3d124a972d..3ba659a5940d 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -100,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm,
 	 * the software side now.
 	 */
 
-	drm_atomic_helper_swap_state(state, true);
+	err = drm_atomic_helper_swap_state(state, true);
+	if (err) {
+		mutex_unlock(&tegra->commit.lock);
+		drm_atomic_helper_cleanup_planes(drm, state);
+		return err;
+	}
 
 	drm_atomic_state_get(state);
 	if (nonblock)
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index d67e18983a7d..049d2f5a1ee4 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -108,7 +108,11 @@ static int tilcdc_commit(struct drm_device *dev,
 	if (ret)
 		return ret;
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret) {
+		drm_atomic_helper_cleanup_planes(dev, state);
+		return ret;
+	}
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 27edae427025..83952a4014a5 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -113,20 +113,20 @@ static int vc4_atomic_commit(struct drm_device *dev,
 
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
-		if (ret) {
-			drm_atomic_helper_cleanup_planes(dev, state);
-			up(&vc4->async_modeset);
-			return ret;
-		}
+		if (ret)
+			goto err;
 	}
 
 	/*
-	 * 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
+	 * If swap_state() succeeds, 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.
 	 */
 
-	drm_atomic_helper_swap_state(state, true);
+	ret = drm_atomic_helper_swap_state(state, true);
+	if (ret)
+		goto err;
 
 	/*
 	 * Everything below can be run asynchronously without the need to grab
@@ -151,6 +151,11 @@ static int vc4_atomic_commit(struct drm_device *dev,
 		vc4_atomic_complete_commit(state);
 
 	return 0;
+
+err:
+	drm_atomic_helper_cleanup_planes(dev, state);
+	up(&vc4->async_modeset);
+	return ret;
 }
 
 static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 3bfeb2b2f746..4f3b6b5362ec 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -80,8 +80,8 @@ void
 drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state,
 					 bool atomic);
 
-void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
-				  bool stall);
+int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
+					      bool stall);
 
 /* nonblocking commit helpers */
 int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
-- 
2.11.0

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

* [PATCH 2/2] drm/atomic: Wait indefinitely and interruptibly for hw_done.
  2017-06-28 13:28 ` Maarten Lankhorst
  (?)
@ 2017-06-28 13:28   ` Maarten Lankhorst
  -1 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-06-28 13:28 UTC (permalink / raw)
  To: dri-devel
  Cc: David Airlie, nouveau, Thierry Reding, Daniel Vetter,
	Boris Brezillon, Jonathan Hunter, Tomi Valkeinen, Ben Skeggs,
	CK Hu, linux-tegra, linux-arm-msm, intel-gfx, linux-mediatek,
	Jyri Sarha, Matthias Brugger, linux-arm-kernel, linux-kernel,
	Philipp Zabel, freedreno

Without waiting for hw_done, previous atomic updates may dereference
the wrong state and cause a lot of confusion. The real fix is fixing
all obj->state to use the accessor macros, but for now wait
indefinitely and interruptibly.

Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: CK Hu <ck.hu@mediatek.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Jyri Sarha <jsarha@ti.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Cc: intel-gfx@lists.freedesktop.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-mediatek@lists.infradead.org
Cc: linux-arm-msm@vger.kernel.org
Cc: freedreno@lists.freedesktop.org
Cc: nouveau@lists.freedesktop.org
Cc: linux-tegra@vger.kernel.org
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/drm_atomic_helper.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index f66b6c45cdd0..56e7729d993d 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2144,8 +2144,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
 int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 				  bool stall)
 {
-	int i;
-	long ret;
+	int i, ret;
 	struct drm_connector *connector;
 	struct drm_connector_state *old_conn_state, *new_conn_state;
 	struct drm_crtc *crtc;
@@ -2168,12 +2167,11 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 			if (!commit)
 				continue;
 
-			ret = wait_for_completion_timeout(&commit->hw_done,
-							  10*HZ);
-			if (ret == 0)
-				DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n",
-					  crtc->base.id, crtc->name);
+			ret = wait_for_completion_interruptible(&commit->hw_done);
 			drm_crtc_commit_put(commit);
+
+			if (ret)
+				return ret;
 		}
 	}
 
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH 2/2] drm/atomic: Wait indefinitely and interruptibly for hw_done.
@ 2017-06-28 13:28   ` Maarten Lankhorst
  0 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-06-28 13:28 UTC (permalink / raw)
  To: dri-devel
  Cc: Maarten Lankhorst, Boris Brezillon, David Airlie, Daniel Vetter,
	Jani Nikula, Sean Paul, CK Hu, Philipp Zabel, Matthias Brugger,
	Rob Clark, Ben Skeggs, Thierry Reding, Jonathan Hunter,
	Jyri Sarha, Tomi Valkeinen, Eric Anholt, linux-kernel, intel-gfx,
	linux-arm-kernel, linux-mediatek, linux-arm-msm, freedreno,
	nouveau, linux-tegra

Without waiting for hw_done, previous atomic updates may dereference
the wrong state and cause a lot of confusion. The real fix is fixing
all obj->state to use the accessor macros, but for now wait
indefinitely and interruptibly.

Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: CK Hu <ck.hu@mediatek.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Jyri Sarha <jsarha@ti.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Cc: intel-gfx@lists.freedesktop.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-mediatek@lists.infradead.org
Cc: linux-arm-msm@vger.kernel.org
Cc: freedreno@lists.freedesktop.org
Cc: nouveau@lists.freedesktop.org
Cc: linux-tegra@vger.kernel.org
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/drm_atomic_helper.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index f66b6c45cdd0..56e7729d993d 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2144,8 +2144,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
 int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 				  bool stall)
 {
-	int i;
-	long ret;
+	int i, ret;
 	struct drm_connector *connector;
 	struct drm_connector_state *old_conn_state, *new_conn_state;
 	struct drm_crtc *crtc;
@@ -2168,12 +2167,11 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 			if (!commit)
 				continue;
 
-			ret = wait_for_completion_timeout(&commit->hw_done,
-							  10*HZ);
-			if (ret == 0)
-				DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n",
-					  crtc->base.id, crtc->name);
+			ret = wait_for_completion_interruptible(&commit->hw_done);
 			drm_crtc_commit_put(commit);
+
+			if (ret)
+				return ret;
 		}
 	}
 
-- 
2.11.0

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

* [PATCH 2/2] drm/atomic: Wait indefinitely and interruptibly for hw_done.
@ 2017-06-28 13:28   ` Maarten Lankhorst
  0 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-06-28 13:28 UTC (permalink / raw)
  To: linux-arm-kernel

Without waiting for hw_done, previous atomic updates may dereference
the wrong state and cause a lot of confusion. The real fix is fixing
all obj->state to use the accessor macros, but for now wait
indefinitely and interruptibly.

Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: CK Hu <ck.hu@mediatek.com>
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Jyri Sarha <jsarha@ti.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Eric Anholt <eric@anholt.net>
Cc: dri-devel at lists.freedesktop.org
Cc: linux-kernel at vger.kernel.org
Cc: intel-gfx at lists.freedesktop.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-mediatek at lists.infradead.org
Cc: linux-arm-msm at vger.kernel.org
Cc: freedreno at lists.freedesktop.org
Cc: nouveau at lists.freedesktop.org
Cc: linux-tegra at vger.kernel.org
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/drm_atomic_helper.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index f66b6c45cdd0..56e7729d993d 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2144,8 +2144,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
 int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 				  bool stall)
 {
-	int i;
-	long ret;
+	int i, ret;
 	struct drm_connector *connector;
 	struct drm_connector_state *old_conn_state, *new_conn_state;
 	struct drm_crtc *crtc;
@@ -2168,12 +2167,11 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 			if (!commit)
 				continue;
 
-			ret = wait_for_completion_timeout(&commit->hw_done,
-							  10*HZ);
-			if (ret == 0)
-				DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n",
-					  crtc->base.id, crtc->name);
+			ret = wait_for_completion_interruptible(&commit->hw_done);
 			drm_crtc_commit_put(commit);
+
+			if (ret)
+				return ret;
 		}
 	}
 
-- 
2.11.0

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

* ✗ Fi.CI.BAT: failure for series starting with [1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
  2017-06-28 13:28 ` Maarten Lankhorst
                   ` (2 preceding siblings ...)
  (?)
@ 2017-06-28 13:45 ` Patchwork
  -1 siblings, 0 replies; 21+ messages in thread
From: Patchwork @ 2017-06-28 13:45 UTC (permalink / raw)
  To: Maarten Lankhorst; +Cc: intel-gfx

== Series Details ==

Series: series starting with [1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
URL   : https://patchwork.freedesktop.org/series/26488/
State : failure

== Summary ==

Series 26488v1 Series without cover letter
https://patchwork.freedesktop.org/api/1.0/series/26488/revisions/1/mbox/

Test gem_exec_parallel:
        Subgroup basic:
                pass       -> INCOMPLETE (fi-pnv-d510)
Test gem_exec_suspend:
        Subgroup basic-s4-devices:
                pass       -> DMESG-WARN (fi-kbl-r) fdo#100125
Test kms_pipe_crc_basic:
        Subgroup suspend-read-crc-pipe-a:
                dmesg-warn -> PASS       (fi-byt-j1900) fdo#101517

fdo#100125 https://bugs.freedesktop.org/show_bug.cgi?id=100125
fdo#101517 https://bugs.freedesktop.org/show_bug.cgi?id=101517

fi-bdw-5557u     total:279  pass:268  dwarn:0   dfail:0   fail:0   skip:11  time:445s
fi-bdw-gvtdvm    total:279  pass:257  dwarn:8   dfail:0   fail:0   skip:14  time:433s
fi-blb-e6850     total:279  pass:224  dwarn:1   dfail:0   fail:0   skip:54  time:357s
fi-bsw-n3050     total:279  pass:242  dwarn:1   dfail:0   fail:0   skip:36  time:532s
fi-bxt-j4205     total:279  pass:260  dwarn:0   dfail:0   fail:0   skip:19  time:508s
fi-byt-j1900     total:279  pass:254  dwarn:1   dfail:0   fail:0   skip:24  time:483s
fi-byt-n2820     total:279  pass:249  dwarn:2   dfail:0   fail:0   skip:28  time:481s
fi-glk-2a        total:279  pass:260  dwarn:0   dfail:0   fail:0   skip:19  time:594s
fi-hsw-4770      total:279  pass:263  dwarn:0   dfail:0   fail:0   skip:16  time:435s
fi-hsw-4770r     total:279  pass:263  dwarn:0   dfail:0   fail:0   skip:16  time:420s
fi-ilk-650       total:279  pass:229  dwarn:0   dfail:0   fail:0   skip:50  time:413s
fi-ivb-3520m     total:279  pass:261  dwarn:0   dfail:0   fail:0   skip:18  time:491s
fi-ivb-3770      total:279  pass:261  dwarn:0   dfail:0   fail:0   skip:18  time:478s
fi-kbl-7500u     total:279  pass:261  dwarn:0   dfail:0   fail:0   skip:18  time:470s
fi-kbl-7560u     total:279  pass:268  dwarn:1   dfail:0   fail:0   skip:10  time:570s
fi-kbl-r         total:279  pass:260  dwarn:1   dfail:0   fail:0   skip:18  time:584s
fi-pnv-d510      total:68   pass:42   dwarn:0   dfail:0   fail:0   skip:25 
fi-skl-6260u     total:279  pass:269  dwarn:0   dfail:0   fail:0   skip:10  time:454s
fi-skl-6700hq    total:279  pass:223  dwarn:1   dfail:0   fail:30  skip:24  time:341s
fi-skl-6700k     total:279  pass:257  dwarn:4   dfail:0   fail:0   skip:18  time:464s
fi-skl-6770hq    total:279  pass:269  dwarn:0   dfail:0   fail:0   skip:10  time:476s
fi-skl-gvtdvm    total:279  pass:266  dwarn:0   dfail:0   fail:0   skip:13  time:437s
fi-snb-2520m     total:279  pass:251  dwarn:0   dfail:0   fail:0   skip:28  time:539s
fi-snb-2600      total:279  pass:250  dwarn:0   dfail:0   fail:0   skip:29  time:408s

90513552ce32ddf2a4efffa21a5df5f21a425a18 drm-tip: 2017y-06m-28d-11h-26m-16s UTC integration manifest
3ec2e30 drm/atomic: Wait indefinitely and interruptibly for hw_done.
d685f31 drm/atomic: Change drm_atomic_helper_swap_state to return an error.

== Logs ==

For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_5059/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 2/2] drm/atomic: Wait indefinitely and interruptibly for hw_done.
  2017-06-28 13:28   ` Maarten Lankhorst
@ 2017-06-30 13:41     ` Daniel Vetter
  -1 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-06-30 13:41 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: dri-devel, nouveau, Thierry Reding, Daniel Vetter,
	Boris Brezillon, Jonathan Hunter, Tomi Valkeinen, Ben Skeggs,
	linux-tegra, linux-arm-msm, intel-gfx, linux-mediatek,
	Jyri Sarha, Matthias Brugger, linux-arm-kernel, linux-kernel,
	freedreno

On Wed, Jun 28, 2017 at 03:28:12PM +0200, Maarten Lankhorst wrote:
> Without waiting for hw_done, previous atomic updates may dereference
> the wrong state and cause a lot of confusion. The real fix is fixing
> all obj->state to use the accessor macros, but for now wait
> indefinitely and interruptibly.
> 
> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
> Cc: David Airlie <airlied@linux.ie>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: CK Hu <ck.hu@mediatek.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Ben Skeggs <bskeggs@redhat.com>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Jonathan Hunter <jonathanh@nvidia.com>
> Cc: Jyri Sarha <jsarha@ti.com>
> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Cc: Eric Anholt <eric@anholt.net>
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-kernel@vger.kernel.org
> Cc: intel-gfx@lists.freedesktop.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-mediatek@lists.infradead.org
> Cc: linux-arm-msm@vger.kernel.org
> Cc: freedreno@lists.freedesktop.org
> Cc: nouveau@lists.freedesktop.org
> Cc: linux-tegra@vger.kernel.org
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 12 +++++-------
>  1 file changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index f66b6c45cdd0..56e7729d993d 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -2144,8 +2144,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
>  int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  				  bool stall)

Needs improved kernel-doc:

 * Returns:
 * 
 * 0 on success. Can return -EINTR when @stall is true and the waiting for
 * the previous commits has been interrupted.

With that Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

>  {
> -	int i;
> -	long ret;
> +	int i, ret;
>  	struct drm_connector *connector;
>  	struct drm_connector_state *old_conn_state, *new_conn_state;
>  	struct drm_crtc *crtc;
> @@ -2168,12 +2167,11 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  			if (!commit)
>  				continue;
>  
> -			ret = wait_for_completion_timeout(&commit->hw_done,
> -							  10*HZ);
> -			if (ret == 0)
> -				DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n",
> -					  crtc->base.id, crtc->name);
> +			ret = wait_for_completion_interruptible(&commit->hw_done);
>  			drm_crtc_commit_put(commit);
> +
> +			if (ret)
> +				return ret;
>  		}
>  	}
>  
> -- 
> 2.11.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* [PATCH 2/2] drm/atomic: Wait indefinitely and interruptibly for hw_done.
@ 2017-06-30 13:41     ` Daniel Vetter
  0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-06-30 13:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 28, 2017 at 03:28:12PM +0200, Maarten Lankhorst wrote:
> Without waiting for hw_done, previous atomic updates may dereference
> the wrong state and cause a lot of confusion. The real fix is fixing
> all obj->state to use the accessor macros, but for now wait
> indefinitely and interruptibly.
> 
> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
> Cc: David Airlie <airlied@linux.ie>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: CK Hu <ck.hu@mediatek.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Ben Skeggs <bskeggs@redhat.com>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Jonathan Hunter <jonathanh@nvidia.com>
> Cc: Jyri Sarha <jsarha@ti.com>
> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Cc: Eric Anholt <eric@anholt.net>
> Cc: dri-devel at lists.freedesktop.org
> Cc: linux-kernel at vger.kernel.org
> Cc: intel-gfx at lists.freedesktop.org
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-mediatek at lists.infradead.org
> Cc: linux-arm-msm at vger.kernel.org
> Cc: freedreno at lists.freedesktop.org
> Cc: nouveau at lists.freedesktop.org
> Cc: linux-tegra at vger.kernel.org
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_atomic_helper.c | 12 +++++-------
>  1 file changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index f66b6c45cdd0..56e7729d993d 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -2144,8 +2144,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
>  int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  				  bool stall)

Needs improved kernel-doc:

 * Returns:
 * 
 * 0 on success. Can return -EINTR when @stall is true and the waiting for
 * the previous commits has been interrupted.

With that Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

>  {
> -	int i;
> -	long ret;
> +	int i, ret;
>  	struct drm_connector *connector;
>  	struct drm_connector_state *old_conn_state, *new_conn_state;
>  	struct drm_crtc *crtc;
> @@ -2168,12 +2167,11 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  			if (!commit)
>  				continue;
>  
> -			ret = wait_for_completion_timeout(&commit->hw_done,
> -							  10*HZ);
> -			if (ret == 0)
> -				DRM_ERROR("[CRTC:%d:%s] hw_done timed out\n",
> -					  crtc->base.id, crtc->name);
> +			ret = wait_for_completion_interruptible(&commit->hw_done);
>  			drm_crtc_commit_put(commit);
> +
> +			if (ret)
> +				return ret;
>  		}
>  	}
>  
> -- 
> 2.11.0
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
  2017-06-28 13:28 ` Maarten Lankhorst
  (?)
@ 2017-06-30 13:56   ` Daniel Vetter
  -1 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-06-30 13:56 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: Boris Brezillon, nouveau, Tomi Valkeinen, Jyri Sarha,
	linux-kernel, dri-devel, Jonathan Hunter, linux-tegra,
	Thierry Reding, linux-mediatek, Ben Skeggs, linux-arm-msm,
	Daniel Vetter, freedreno, intel-gfx, linux-arm-kernel,
	Matthias Brugger

On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
> We want to change swap_state to wait indefinitely, but to do this
> swap_state should wait interruptibly. This requires propagating
> the error to each driver. All drivers have changes to deal with the
> clean up. In order to allow easy reverting, the commit that changes
> behavior is separate so someone only has to revert that for testing.
> 
> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
> failed cleanup_planes was not called.
> 
> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
> Cc: David Airlie <airlied@linux.ie>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: CK Hu <ck.hu@mediatek.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Ben Skeggs <bskeggs@redhat.com>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Jonathan Hunter <jonathanh@nvidia.com>
> Cc: Jyri Sarha <jsarha@ti.com>
> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Cc: Eric Anholt <eric@anholt.net>
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-kernel@vger.kernel.org
> Cc: intel-gfx@lists.freedesktop.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-mediatek@lists.infradead.org
> Cc: linux-arm-msm@vger.kernel.org
> Cc: freedreno@lists.freedesktop.org
> Cc: nouveau@lists.freedesktop.org
> Cc: linux-tegra@vger.kernel.org
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

We kinda need to backport this to older kernels, but I don't really see
how :( Maybe we should split this up:
patch 1: Change to int return type
patches 2-(n-1): Driver conversions
patch n: __must_check addition

That would at least somewhat make this backportable ...

> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
>  include/drm/drm_atomic_helper.h              |  4 ++--
>  10 files changed, 82 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> index 516d9547d331..d4f787bf1d4a 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>  		goto error;
>  	}
>  
> -	/* Swap the state, this is the point of no return. */
> -	drm_atomic_helper_swap_state(state, true);

Push the swap_state up over the commit setup (but after the allocation)
and there's no more a problem with unrolling.

> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err_pending;
>  
> +	/* Swap state succeeded, this is the point of no return. */
>  	drm_atomic_state_get(state);
>  	if (async)
>  		queue_work(dc->wq, &commit->work);
> @@ -555,6 +557,14 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>  
>  	return 0;
>  
> +err_pending:
> +	/* Fail the commit, wake up any waiter. */
> +	spin_lock(&dc->commit.wait.lock);
> +	dc->commit.pending = false;
> +	wake_up_all_locked(&dc->commit.wait);
> +	spin_unlock(&dc->commit.wait.lock);
> +err_free:
> +	kfree(commit);
>  error:
>  	drm_atomic_helper_cleanup_planes(dev, state);
>  	return ret;
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index f1847d29ba3e..f66b6c45cdd0 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1387,10 +1387,8 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  
>  	if (!nonblock) {
>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> -		if (ret) {
> -			drm_atomic_helper_cleanup_planes(dev, state);
> -			return ret;
> -		}
> +		if (ret)
> +			goto err;
>  	}
>  
>  	/*
> @@ -1399,7 +1397,9 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  	 * the software side now.
>  	 */
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err;
>  
>  	/*
>  	 * Everything below can be run asynchronously without the need to grab
> @@ -1428,6 +1428,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  		commit_tail(state);
>  
>  	return 0;
> +
> +err:
> +	drm_atomic_helper_cleanup_planes(dev, state);
> +	return ret;
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_commit);
>  
> @@ -2137,7 +2141,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
>   * the current atomic helpers this is almost always the case, since the helpers
>   * don't pass the right state structures to the callbacks.
>   */
> -void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
> +int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  				  bool stall)
>  {
>  	int i;
> @@ -2214,6 +2218,8 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  
>  	__for_each_private_obj(state, obj, obj_state, i, funcs)
>  		funcs->swap_state(obj, &state->private_objs[i].obj_state);
> +
> +	return 0;
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_swap_state);

Above hunks lgtm.

>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7d416428bdc1..e211d703fe2e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -13183,7 +13183,15 @@ static int intel_atomic_commit(struct drm_device *dev,
>  	if (INTEL_GEN(dev_priv) < 9)
>  		state->legacy_cursor_update = false;
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret) {
> +		i915_sw_fence_commit(&intel_state->commit_ready);
> +
> +		mutex_lock(&dev->struct_mutex);
> +		drm_atomic_helper_cleanup_planes(dev, state);
> +		mutex_unlock(&dev->struct_mutex);
> +		return ret;
> +	}
>  	dev_priv->wm.distrust_bios_wm = false;
>  	intel_shared_dpll_swap_state(state);
>  	intel_atomic_track_fbs(state);

lgtm.

> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 56f802d0a51c..9a130c84c861 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -109,7 +109,12 @@ static int mtk_atomic_commit(struct drm_device *drm,
>  	mutex_lock(&private->commit.lock);
>  	flush_work(&private->commit.work);
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret) {
> +		mutex_unlock(&private->commit.lock);
> +		drm_atomic_helper_cleanup_planes(drm, state);
> +		return ret;
> +	}
>  
>  	drm_atomic_state_get(state);
>  	if (async)

lgtm.

> diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
> index 9633a68b14d7..85dd485fdef4 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -232,8 +232,12 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 * mark our set of crtc's as busy:
>  	 */
>  	ret = start_atomic(dev->dev_private, c->crtc_mask);
> +	if (ret)
> +		goto err_free;
> +
> +	ret = drm_atomic_helper_swap_state(state, true);

Hm, might be simpler to have stall = false (which btw makes your
__must_check annotation a lie, you only have to check when you stall),
since start_atomic above already does stall for everything as needed.

>  	if (ret) {
> -		kfree(c);
> +		commit_destroy(c);
>  		goto error;
>  	}
>  
> @@ -241,11 +245,9 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 * 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
>  	 */
> -
> -	drm_atomic_helper_swap_state(state, true);
> -
> -	/* swap driver private state while still holding state_lock */
>  	if (to_kms_state(state)->state)
>  		priv->kms->funcs->swap_state(priv->kms, state);
>  
> @@ -275,6 +277,8 @@ int msm_atomic_commit(struct drm_device *dev,
>  
>  	return 0;
>  
> +err_free:
> +	kfree(c);
>  error:
>  	drm_atomic_helper_cleanup_planes(dev, state);
>  	return ret;
> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
> index 42a85c14aea0..fb2c763c88a8 100644
> --- a/drivers/gpu/drm/nouveau/nv50_display.c
> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
> @@ -4119,9 +4119,13 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  	if (!nonblock) {
>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>  		if (ret)
> -			goto done;
> +			goto err_cleanup;
>  	}
>  
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err_cleanup;
> +
>  	for_each_plane_in_state(state, plane, plane_state, i) {
>  		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
>  		struct nv50_wndw *wndw = nv50_wndw(plane);
> @@ -4135,7 +4139,6 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  		}
>  	}
>  
> -	drm_atomic_helper_swap_state(state, true);
>  	drm_atomic_state_get(state);
>  
>  	if (nonblock)
> @@ -4158,7 +4161,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  		pm_runtime_put_autosuspend(dev->dev);
>  		drm->have_disp_power_ref = false;
>  	}
> +	goto done;
>  
> +err_cleanup:
> +	drm_atomic_helper_cleanup_planes(dev, state);
>  done:
>  	pm_runtime_put_autosuspend(dev->dev);
>  	return ret;

lgtm, but might want to split out the bugfix.

> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> index ad3d124a972d..3ba659a5940d 100644
> --- a/drivers/gpu/drm/tegra/drm.c
> +++ b/drivers/gpu/drm/tegra/drm.c
> @@ -100,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm,
>  	 * the software side now.
>  	 */
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	err = drm_atomic_helper_swap_state(state, true);
> +	if (err) {
> +		mutex_unlock(&tegra->commit.lock);
> +		drm_atomic_helper_cleanup_planes(drm, state);
> +		return err;
> +	}
>  
>  	drm_atomic_state_get(state);
>  	if (nonblock)

lgtm.

> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> index d67e18983a7d..049d2f5a1ee4 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> @@ -108,7 +108,11 @@ static int tilcdc_commit(struct drm_device *dev,
>  	if (ret)
>  		return ret;
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret) {
> +		drm_atomic_helper_cleanup_planes(dev, state);
> +		return ret;
> +	}
>  
>  	/*
>  	 * Everything below can be run asynchronously without the need to grab

lgtm.

Well tilcdc should stop hand-rolling their commit since it's not even
nonblocking, but meh.

> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 27edae427025..83952a4014a5 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -113,20 +113,20 @@ static int vc4_atomic_commit(struct drm_device *dev,
>  
>  	if (!nonblock) {
>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> -		if (ret) {
> -			drm_atomic_helper_cleanup_planes(dev, state);
> -			up(&vc4->async_modeset);
> -			return ret;
> -		}
> +		if (ret)
> +			goto err;
>  	}
>  
>  	/*
> -	 * 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
> +	 * If swap_state() succeeds, 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.
>  	 */
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err;
>  
>  	/*
>  	 * Everything below can be run asynchronously without the need to grab
> @@ -151,6 +151,11 @@ static int vc4_atomic_commit(struct drm_device *dev,
>  		vc4_atomic_complete_commit(state);
>  
>  	return 0;
> +
> +err:
> +	drm_atomic_helper_cleanup_planes(dev, state);
> +	up(&vc4->async_modeset);
> +	return ret;
>  }
>  
>  static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,

lgtm. Will probably clash with ongoing work in vc4 to switch to plain
drm_atomic_helper_commit().

> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
> index 3bfeb2b2f746..4f3b6b5362ec 100644
> --- a/include/drm/drm_atomic_helper.h
> +++ b/include/drm/drm_atomic_helper.h
> @@ -80,8 +80,8 @@ void
>  drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state,
>  					 bool atomic);
>  
> -void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
> -				  bool stall);
> +int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
> +					      bool stall);

__must_check is a lie I think, since with stall = false you don't need it.
-Daniel

>  
>  /* nonblocking commit helpers */
>  int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
> -- 
> 2.11.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-06-30 13:56   ` Daniel Vetter
  0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-06-30 13:56 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: dri-devel, David Airlie, nouveau, Thierry Reding, Daniel Vetter,
	Boris Brezillon, Jonathan Hunter, Tomi Valkeinen, Ben Skeggs,
	CK Hu, linux-tegra, linux-arm-msm, intel-gfx, linux-mediatek,
	Jyri Sarha, Matthias Brugger, linux-arm-kernel, linux-kernel,
	Philipp Zabel, freedreno

On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
> We want to change swap_state to wait indefinitely, but to do this
> swap_state should wait interruptibly. This requires propagating
> the error to each driver. All drivers have changes to deal with the
> clean up. In order to allow easy reverting, the commit that changes
> behavior is separate so someone only has to revert that for testing.
> 
> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
> failed cleanup_planes was not called.
> 
> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
> Cc: David Airlie <airlied@linux.ie>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: CK Hu <ck.hu@mediatek.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Ben Skeggs <bskeggs@redhat.com>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Jonathan Hunter <jonathanh@nvidia.com>
> Cc: Jyri Sarha <jsarha@ti.com>
> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Cc: Eric Anholt <eric@anholt.net>
> Cc: dri-devel@lists.freedesktop.org
> Cc: linux-kernel@vger.kernel.org
> Cc: intel-gfx@lists.freedesktop.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-mediatek@lists.infradead.org
> Cc: linux-arm-msm@vger.kernel.org
> Cc: freedreno@lists.freedesktop.org
> Cc: nouveau@lists.freedesktop.org
> Cc: linux-tegra@vger.kernel.org
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

We kinda need to backport this to older kernels, but I don't really see
how :( Maybe we should split this up:
patch 1: Change to int return type
patches 2-(n-1): Driver conversions
patch n: __must_check addition

That would at least somewhat make this backportable ...

> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
>  include/drm/drm_atomic_helper.h              |  4 ++--
>  10 files changed, 82 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> index 516d9547d331..d4f787bf1d4a 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>  		goto error;
>  	}
>  
> -	/* Swap the state, this is the point of no return. */
> -	drm_atomic_helper_swap_state(state, true);

Push the swap_state up over the commit setup (but after the allocation)
and there's no more a problem with unrolling.

> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err_pending;
>  
> +	/* Swap state succeeded, this is the point of no return. */
>  	drm_atomic_state_get(state);
>  	if (async)
>  		queue_work(dc->wq, &commit->work);
> @@ -555,6 +557,14 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>  
>  	return 0;
>  
> +err_pending:
> +	/* Fail the commit, wake up any waiter. */
> +	spin_lock(&dc->commit.wait.lock);
> +	dc->commit.pending = false;
> +	wake_up_all_locked(&dc->commit.wait);
> +	spin_unlock(&dc->commit.wait.lock);
> +err_free:
> +	kfree(commit);
>  error:
>  	drm_atomic_helper_cleanup_planes(dev, state);
>  	return ret;
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index f1847d29ba3e..f66b6c45cdd0 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1387,10 +1387,8 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  
>  	if (!nonblock) {
>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> -		if (ret) {
> -			drm_atomic_helper_cleanup_planes(dev, state);
> -			return ret;
> -		}
> +		if (ret)
> +			goto err;
>  	}
>  
>  	/*
> @@ -1399,7 +1397,9 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  	 * the software side now.
>  	 */
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err;
>  
>  	/*
>  	 * Everything below can be run asynchronously without the need to grab
> @@ -1428,6 +1428,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  		commit_tail(state);
>  
>  	return 0;
> +
> +err:
> +	drm_atomic_helper_cleanup_planes(dev, state);
> +	return ret;
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_commit);
>  
> @@ -2137,7 +2141,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
>   * the current atomic helpers this is almost always the case, since the helpers
>   * don't pass the right state structures to the callbacks.
>   */
> -void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
> +int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  				  bool stall)
>  {
>  	int i;
> @@ -2214,6 +2218,8 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  
>  	__for_each_private_obj(state, obj, obj_state, i, funcs)
>  		funcs->swap_state(obj, &state->private_objs[i].obj_state);
> +
> +	return 0;
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_swap_state);

Above hunks lgtm.

>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7d416428bdc1..e211d703fe2e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -13183,7 +13183,15 @@ static int intel_atomic_commit(struct drm_device *dev,
>  	if (INTEL_GEN(dev_priv) < 9)
>  		state->legacy_cursor_update = false;
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret) {
> +		i915_sw_fence_commit(&intel_state->commit_ready);
> +
> +		mutex_lock(&dev->struct_mutex);
> +		drm_atomic_helper_cleanup_planes(dev, state);
> +		mutex_unlock(&dev->struct_mutex);
> +		return ret;
> +	}
>  	dev_priv->wm.distrust_bios_wm = false;
>  	intel_shared_dpll_swap_state(state);
>  	intel_atomic_track_fbs(state);

lgtm.

> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 56f802d0a51c..9a130c84c861 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -109,7 +109,12 @@ static int mtk_atomic_commit(struct drm_device *drm,
>  	mutex_lock(&private->commit.lock);
>  	flush_work(&private->commit.work);
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret) {
> +		mutex_unlock(&private->commit.lock);
> +		drm_atomic_helper_cleanup_planes(drm, state);
> +		return ret;
> +	}
>  
>  	drm_atomic_state_get(state);
>  	if (async)

lgtm.

> diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
> index 9633a68b14d7..85dd485fdef4 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -232,8 +232,12 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 * mark our set of crtc's as busy:
>  	 */
>  	ret = start_atomic(dev->dev_private, c->crtc_mask);
> +	if (ret)
> +		goto err_free;
> +
> +	ret = drm_atomic_helper_swap_state(state, true);

Hm, might be simpler to have stall = false (which btw makes your
__must_check annotation a lie, you only have to check when you stall),
since start_atomic above already does stall for everything as needed.

>  	if (ret) {
> -		kfree(c);
> +		commit_destroy(c);
>  		goto error;
>  	}
>  
> @@ -241,11 +245,9 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 * 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
>  	 */
> -
> -	drm_atomic_helper_swap_state(state, true);
> -
> -	/* swap driver private state while still holding state_lock */
>  	if (to_kms_state(state)->state)
>  		priv->kms->funcs->swap_state(priv->kms, state);
>  
> @@ -275,6 +277,8 @@ int msm_atomic_commit(struct drm_device *dev,
>  
>  	return 0;
>  
> +err_free:
> +	kfree(c);
>  error:
>  	drm_atomic_helper_cleanup_planes(dev, state);
>  	return ret;
> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
> index 42a85c14aea0..fb2c763c88a8 100644
> --- a/drivers/gpu/drm/nouveau/nv50_display.c
> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
> @@ -4119,9 +4119,13 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  	if (!nonblock) {
>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>  		if (ret)
> -			goto done;
> +			goto err_cleanup;
>  	}
>  
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err_cleanup;
> +
>  	for_each_plane_in_state(state, plane, plane_state, i) {
>  		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
>  		struct nv50_wndw *wndw = nv50_wndw(plane);
> @@ -4135,7 +4139,6 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  		}
>  	}
>  
> -	drm_atomic_helper_swap_state(state, true);
>  	drm_atomic_state_get(state);
>  
>  	if (nonblock)
> @@ -4158,7 +4161,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  		pm_runtime_put_autosuspend(dev->dev);
>  		drm->have_disp_power_ref = false;
>  	}
> +	goto done;
>  
> +err_cleanup:
> +	drm_atomic_helper_cleanup_planes(dev, state);
>  done:
>  	pm_runtime_put_autosuspend(dev->dev);
>  	return ret;

lgtm, but might want to split out the bugfix.

> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> index ad3d124a972d..3ba659a5940d 100644
> --- a/drivers/gpu/drm/tegra/drm.c
> +++ b/drivers/gpu/drm/tegra/drm.c
> @@ -100,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm,
>  	 * the software side now.
>  	 */
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	err = drm_atomic_helper_swap_state(state, true);
> +	if (err) {
> +		mutex_unlock(&tegra->commit.lock);
> +		drm_atomic_helper_cleanup_planes(drm, state);
> +		return err;
> +	}
>  
>  	drm_atomic_state_get(state);
>  	if (nonblock)

lgtm.

> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> index d67e18983a7d..049d2f5a1ee4 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> @@ -108,7 +108,11 @@ static int tilcdc_commit(struct drm_device *dev,
>  	if (ret)
>  		return ret;
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret) {
> +		drm_atomic_helper_cleanup_planes(dev, state);
> +		return ret;
> +	}
>  
>  	/*
>  	 * Everything below can be run asynchronously without the need to grab

lgtm.

Well tilcdc should stop hand-rolling their commit since it's not even
nonblocking, but meh.

> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 27edae427025..83952a4014a5 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -113,20 +113,20 @@ static int vc4_atomic_commit(struct drm_device *dev,
>  
>  	if (!nonblock) {
>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> -		if (ret) {
> -			drm_atomic_helper_cleanup_planes(dev, state);
> -			up(&vc4->async_modeset);
> -			return ret;
> -		}
> +		if (ret)
> +			goto err;
>  	}
>  
>  	/*
> -	 * 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
> +	 * If swap_state() succeeds, 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.
>  	 */
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err;
>  
>  	/*
>  	 * Everything below can be run asynchronously without the need to grab
> @@ -151,6 +151,11 @@ static int vc4_atomic_commit(struct drm_device *dev,
>  		vc4_atomic_complete_commit(state);
>  
>  	return 0;
> +
> +err:
> +	drm_atomic_helper_cleanup_planes(dev, state);
> +	up(&vc4->async_modeset);
> +	return ret;
>  }
>  
>  static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,

lgtm. Will probably clash with ongoing work in vc4 to switch to plain
drm_atomic_helper_commit().

> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
> index 3bfeb2b2f746..4f3b6b5362ec 100644
> --- a/include/drm/drm_atomic_helper.h
> +++ b/include/drm/drm_atomic_helper.h
> @@ -80,8 +80,8 @@ void
>  drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state,
>  					 bool atomic);
>  
> -void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
> -				  bool stall);
> +int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
> +					      bool stall);

__must_check is a lie I think, since with stall = false you don't need it.
-Daniel

>  
>  /* nonblocking commit helpers */
>  int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
> -- 
> 2.11.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-06-30 13:56   ` Daniel Vetter
  0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-06-30 13:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
> We want to change swap_state to wait indefinitely, but to do this
> swap_state should wait interruptibly. This requires propagating
> the error to each driver. All drivers have changes to deal with the
> clean up. In order to allow easy reverting, the commit that changes
> behavior is separate so someone only has to revert that for testing.
> 
> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
> failed cleanup_planes was not called.
> 
> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
> Cc: David Airlie <airlied@linux.ie>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: CK Hu <ck.hu@mediatek.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Ben Skeggs <bskeggs@redhat.com>
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: Jonathan Hunter <jonathanh@nvidia.com>
> Cc: Jyri Sarha <jsarha@ti.com>
> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> Cc: Eric Anholt <eric@anholt.net>
> Cc: dri-devel at lists.freedesktop.org
> Cc: linux-kernel at vger.kernel.org
> Cc: intel-gfx at lists.freedesktop.org
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-mediatek at lists.infradead.org
> Cc: linux-arm-msm at vger.kernel.org
> Cc: freedreno at lists.freedesktop.org
> Cc: nouveau at lists.freedesktop.org
> Cc: linux-tegra at vger.kernel.org
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

We kinda need to backport this to older kernels, but I don't really see
how :( Maybe we should split this up:
patch 1: Change to int return type
patches 2-(n-1): Driver conversions
patch n: __must_check addition

That would at least somewhat make this backportable ...

> ---
>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
>  include/drm/drm_atomic_helper.h              |  4 ++--
>  10 files changed, 82 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> index 516d9547d331..d4f787bf1d4a 100644
> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>  		goto error;
>  	}
>  
> -	/* Swap the state, this is the point of no return. */
> -	drm_atomic_helper_swap_state(state, true);

Push the swap_state up over the commit setup (but after the allocation)
and there's no more a problem with unrolling.

> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err_pending;
>  
> +	/* Swap state succeeded, this is the point of no return. */
>  	drm_atomic_state_get(state);
>  	if (async)
>  		queue_work(dc->wq, &commit->work);
> @@ -555,6 +557,14 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>  
>  	return 0;
>  
> +err_pending:
> +	/* Fail the commit, wake up any waiter. */
> +	spin_lock(&dc->commit.wait.lock);
> +	dc->commit.pending = false;
> +	wake_up_all_locked(&dc->commit.wait);
> +	spin_unlock(&dc->commit.wait.lock);
> +err_free:
> +	kfree(commit);
>  error:
>  	drm_atomic_helper_cleanup_planes(dev, state);
>  	return ret;
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index f1847d29ba3e..f66b6c45cdd0 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -1387,10 +1387,8 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  
>  	if (!nonblock) {
>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> -		if (ret) {
> -			drm_atomic_helper_cleanup_planes(dev, state);
> -			return ret;
> -		}
> +		if (ret)
> +			goto err;
>  	}
>  
>  	/*
> @@ -1399,7 +1397,9 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  	 * the software side now.
>  	 */
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err;
>  
>  	/*
>  	 * Everything below can be run asynchronously without the need to grab
> @@ -1428,6 +1428,10 @@ int drm_atomic_helper_commit(struct drm_device *dev,
>  		commit_tail(state);
>  
>  	return 0;
> +
> +err:
> +	drm_atomic_helper_cleanup_planes(dev, state);
> +	return ret;
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_commit);
>  
> @@ -2137,7 +2141,7 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes);
>   * the current atomic helpers this is almost always the case, since the helpers
>   * don't pass the right state structures to the callbacks.
>   */
> -void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
> +int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  				  bool stall)
>  {
>  	int i;
> @@ -2214,6 +2218,8 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>  
>  	__for_each_private_obj(state, obj, obj_state, i, funcs)
>  		funcs->swap_state(obj, &state->private_objs[i].obj_state);
> +
> +	return 0;
>  }
>  EXPORT_SYMBOL(drm_atomic_helper_swap_state);

Above hunks lgtm.

>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7d416428bdc1..e211d703fe2e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -13183,7 +13183,15 @@ static int intel_atomic_commit(struct drm_device *dev,
>  	if (INTEL_GEN(dev_priv) < 9)
>  		state->legacy_cursor_update = false;
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret) {
> +		i915_sw_fence_commit(&intel_state->commit_ready);
> +
> +		mutex_lock(&dev->struct_mutex);
> +		drm_atomic_helper_cleanup_planes(dev, state);
> +		mutex_unlock(&dev->struct_mutex);
> +		return ret;
> +	}
>  	dev_priv->wm.distrust_bios_wm = false;
>  	intel_shared_dpll_swap_state(state);
>  	intel_atomic_track_fbs(state);

lgtm.

> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index 56f802d0a51c..9a130c84c861 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -109,7 +109,12 @@ static int mtk_atomic_commit(struct drm_device *drm,
>  	mutex_lock(&private->commit.lock);
>  	flush_work(&private->commit.work);
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret) {
> +		mutex_unlock(&private->commit.lock);
> +		drm_atomic_helper_cleanup_planes(drm, state);
> +		return ret;
> +	}
>  
>  	drm_atomic_state_get(state);
>  	if (async)

lgtm.

> diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
> index 9633a68b14d7..85dd485fdef4 100644
> --- a/drivers/gpu/drm/msm/msm_atomic.c
> +++ b/drivers/gpu/drm/msm/msm_atomic.c
> @@ -232,8 +232,12 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 * mark our set of crtc's as busy:
>  	 */
>  	ret = start_atomic(dev->dev_private, c->crtc_mask);
> +	if (ret)
> +		goto err_free;
> +
> +	ret = drm_atomic_helper_swap_state(state, true);

Hm, might be simpler to have stall = false (which btw makes your
__must_check annotation a lie, you only have to check when you stall),
since start_atomic above already does stall for everything as needed.

>  	if (ret) {
> -		kfree(c);
> +		commit_destroy(c);
>  		goto error;
>  	}
>  
> @@ -241,11 +245,9 @@ int msm_atomic_commit(struct drm_device *dev,
>  	 * 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
>  	 */
> -
> -	drm_atomic_helper_swap_state(state, true);
> -
> -	/* swap driver private state while still holding state_lock */
>  	if (to_kms_state(state)->state)
>  		priv->kms->funcs->swap_state(priv->kms, state);
>  
> @@ -275,6 +277,8 @@ int msm_atomic_commit(struct drm_device *dev,
>  
>  	return 0;
>  
> +err_free:
> +	kfree(c);
>  error:
>  	drm_atomic_helper_cleanup_planes(dev, state);
>  	return ret;
> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
> index 42a85c14aea0..fb2c763c88a8 100644
> --- a/drivers/gpu/drm/nouveau/nv50_display.c
> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
> @@ -4119,9 +4119,13 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  	if (!nonblock) {
>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>  		if (ret)
> -			goto done;
> +			goto err_cleanup;
>  	}
>  
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err_cleanup;
> +
>  	for_each_plane_in_state(state, plane, plane_state, i) {
>  		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
>  		struct nv50_wndw *wndw = nv50_wndw(plane);
> @@ -4135,7 +4139,6 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  		}
>  	}
>  
> -	drm_atomic_helper_swap_state(state, true);
>  	drm_atomic_state_get(state);
>  
>  	if (nonblock)
> @@ -4158,7 +4161,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>  		pm_runtime_put_autosuspend(dev->dev);
>  		drm->have_disp_power_ref = false;
>  	}
> +	goto done;
>  
> +err_cleanup:
> +	drm_atomic_helper_cleanup_planes(dev, state);
>  done:
>  	pm_runtime_put_autosuspend(dev->dev);
>  	return ret;

lgtm, but might want to split out the bugfix.

> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> index ad3d124a972d..3ba659a5940d 100644
> --- a/drivers/gpu/drm/tegra/drm.c
> +++ b/drivers/gpu/drm/tegra/drm.c
> @@ -100,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm,
>  	 * the software side now.
>  	 */
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	err = drm_atomic_helper_swap_state(state, true);
> +	if (err) {
> +		mutex_unlock(&tegra->commit.lock);
> +		drm_atomic_helper_cleanup_planes(drm, state);
> +		return err;
> +	}
>  
>  	drm_atomic_state_get(state);
>  	if (nonblock)

lgtm.

> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> index d67e18983a7d..049d2f5a1ee4 100644
> --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
> @@ -108,7 +108,11 @@ static int tilcdc_commit(struct drm_device *dev,
>  	if (ret)
>  		return ret;
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret) {
> +		drm_atomic_helper_cleanup_planes(dev, state);
> +		return ret;
> +	}
>  
>  	/*
>  	 * Everything below can be run asynchronously without the need to grab

lgtm.

Well tilcdc should stop hand-rolling their commit since it's not even
nonblocking, but meh.

> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
> index 27edae427025..83952a4014a5 100644
> --- a/drivers/gpu/drm/vc4/vc4_kms.c
> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
> @@ -113,20 +113,20 @@ static int vc4_atomic_commit(struct drm_device *dev,
>  
>  	if (!nonblock) {
>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
> -		if (ret) {
> -			drm_atomic_helper_cleanup_planes(dev, state);
> -			up(&vc4->async_modeset);
> -			return ret;
> -		}
> +		if (ret)
> +			goto err;
>  	}
>  
>  	/*
> -	 * 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
> +	 * If swap_state() succeeds, 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.
>  	 */
>  
> -	drm_atomic_helper_swap_state(state, true);
> +	ret = drm_atomic_helper_swap_state(state, true);
> +	if (ret)
> +		goto err;
>  
>  	/*
>  	 * Everything below can be run asynchronously without the need to grab
> @@ -151,6 +151,11 @@ static int vc4_atomic_commit(struct drm_device *dev,
>  		vc4_atomic_complete_commit(state);
>  
>  	return 0;
> +
> +err:
> +	drm_atomic_helper_cleanup_planes(dev, state);
> +	up(&vc4->async_modeset);
> +	return ret;
>  }
>  
>  static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,

lgtm. Will probably clash with ongoing work in vc4 to switch to plain
drm_atomic_helper_commit().

> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
> index 3bfeb2b2f746..4f3b6b5362ec 100644
> --- a/include/drm/drm_atomic_helper.h
> +++ b/include/drm/drm_atomic_helper.h
> @@ -80,8 +80,8 @@ void
>  drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state,
>  					 bool atomic);
>  
> -void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
> -				  bool stall);
> +int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
> +					      bool stall);

__must_check is a lie I think, since with stall = false you don't need it.
-Daniel

>  
>  /* nonblocking commit helpers */
>  int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
> -- 
> 2.11.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
  2017-06-30 13:56   ` Daniel Vetter
  (?)
@ 2017-07-03 11:01       ` Maarten Lankhorst
  -1 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-07-03 11:01 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, David Airlie,
	nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Thierry Reding,
	Daniel Vetter, Boris Brezillon, Jonathan Hunter, Tomi Valkeinen,
	Ben Skeggs, CK Hu, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	intel-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Jyri Sarha,
	Matthias Brugger,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Philipp Zabel,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

Op 30-06-17 om 15:56 schreef Daniel Vetter:
> On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
>> We want to change swap_state to wait indefinitely, but to do this
>> swap_state should wait interruptibly. This requires propagating
>> the error to each driver. All drivers have changes to deal with the
>> clean up. In order to allow easy reverting, the commit that changes
>> behavior is separate so someone only has to revert that for testing.
>>
>> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
>> failed cleanup_planes was not called.
>>
>> Cc: Boris Brezillon <boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>> Cc: David Airlie <airlied-cv59FeDIM0c@public.gmane.org>
>> Cc: Daniel Vetter <daniel.vetter-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
>> Cc: Jani Nikula <jani.nikula-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
>> Cc: Sean Paul <seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
>> Cc: CK Hu <ck.hu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
>> Cc: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>> Cc: Matthias Brugger <matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Cc: Rob Clark <robdclark-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Cc: Ben Skeggs <bskeggs-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> Cc: Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Cc: Jonathan Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>> Cc: Jyri Sarha <jsarha-l0cyMroinI0@public.gmane.org>
>> Cc: Tomi Valkeinen <tomi.valkeinen-l0cyMroinI0@public.gmane.org>
>> Cc: Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
>> Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Cc: intel-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>> Cc: linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>> Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Cc: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> We kinda need to backport this to older kernels, but I don't really see
> how :( Maybe we should split this up:
> patch 1: Change to int return type
> patches 2-(n-1): Driver conversions
> patch n: __must_check addition
>
> That would at least somewhat make this backportable ...
>
>> ---
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
>>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
>>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
>>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
>>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
>>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
>>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
>>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
>>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
>>  include/drm/drm_atomic_helper.h              |  4 ++--
>>  10 files changed, 82 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> index 516d9547d331..d4f787bf1d4a 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>>  		goto error;
>>  	}
>>  
>> -	/* Swap the state, this is the point of no return. */
>> -	drm_atomic_helper_swap_state(state, true);
> Push the swap_state up over the commit setup (but after the allocation)
> and there's no more a problem with unrolling.
This can't be done higher up because of the interruptible wait.

Unless we change the patch series to move the waiting for hw_done to a separate step and get rid of the stall argument to swap_state once everything is converted. This could be useful for all drivers that have some kind of setup, because we could move the wait up slightly to suit the drivers needs.

~Maarten

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

* Re: [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-07-03 11:01       ` Maarten Lankhorst
  0 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-07-03 11:01 UTC (permalink / raw)
  To: dri-devel, David Airlie, nouveau, Thierry Reding, Daniel Vetter,
	Boris Brezillon, Jonathan Hunter, Tomi Valkeinen, Ben Skeggs,
	CK Hu, linux-tegra, linux-arm-msm, intel-gfx, linux-mediatek,
	Jyri Sarha, Matthias Brugger, linux-arm-kernel, linux-kernel,
	Philipp Zabel, freedreno

Op 30-06-17 om 15:56 schreef Daniel Vetter:
> On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
>> We want to change swap_state to wait indefinitely, but to do this
>> swap_state should wait interruptibly. This requires propagating
>> the error to each driver. All drivers have changes to deal with the
>> clean up. In order to allow easy reverting, the commit that changes
>> behavior is separate so someone only has to revert that for testing.
>>
>> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
>> failed cleanup_planes was not called.
>>
>> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
>> Cc: David Airlie <airlied@linux.ie>
>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>> Cc: Sean Paul <seanpaul@chromium.org>
>> Cc: CK Hu <ck.hu@mediatek.com>
>> Cc: Philipp Zabel <p.zabel@pengutronix.de>
>> Cc: Matthias Brugger <matthias.bgg@gmail.com>
>> Cc: Rob Clark <robdclark@gmail.com>
>> Cc: Ben Skeggs <bskeggs@redhat.com>
>> Cc: Thierry Reding <thierry.reding@gmail.com>
>> Cc: Jonathan Hunter <jonathanh@nvidia.com>
>> Cc: Jyri Sarha <jsarha@ti.com>
>> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> Cc: Eric Anholt <eric@anholt.net>
>> Cc: dri-devel@lists.freedesktop.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: intel-gfx@lists.freedesktop.org
>> Cc: linux-arm-kernel@lists.infradead.org
>> Cc: linux-mediatek@lists.infradead.org
>> Cc: linux-arm-msm@vger.kernel.org
>> Cc: freedreno@lists.freedesktop.org
>> Cc: nouveau@lists.freedesktop.org
>> Cc: linux-tegra@vger.kernel.org
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> We kinda need to backport this to older kernels, but I don't really see
> how :( Maybe we should split this up:
> patch 1: Change to int return type
> patches 2-(n-1): Driver conversions
> patch n: __must_check addition
>
> That would at least somewhat make this backportable ...
>
>> ---
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
>>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
>>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
>>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
>>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
>>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
>>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
>>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
>>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
>>  include/drm/drm_atomic_helper.h              |  4 ++--
>>  10 files changed, 82 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> index 516d9547d331..d4f787bf1d4a 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>>  		goto error;
>>  	}
>>  
>> -	/* Swap the state, this is the point of no return. */
>> -	drm_atomic_helper_swap_state(state, true);
> Push the swap_state up over the commit setup (but after the allocation)
> and there's no more a problem with unrolling.
This can't be done higher up because of the interruptible wait.

Unless we change the patch series to move the waiting for hw_done to a separate step and get rid of the stall argument to swap_state once everything is converted. This could be useful for all drivers that have some kind of setup, because we could move the wait up slightly to suit the drivers needs.

~Maarten

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

* [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-07-03 11:01       ` Maarten Lankhorst
  0 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-07-03 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

Op 30-06-17 om 15:56 schreef Daniel Vetter:
> On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
>> We want to change swap_state to wait indefinitely, but to do this
>> swap_state should wait interruptibly. This requires propagating
>> the error to each driver. All drivers have changes to deal with the
>> clean up. In order to allow easy reverting, the commit that changes
>> behavior is separate so someone only has to revert that for testing.
>>
>> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
>> failed cleanup_planes was not called.
>>
>> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
>> Cc: David Airlie <airlied@linux.ie>
>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>> Cc: Sean Paul <seanpaul@chromium.org>
>> Cc: CK Hu <ck.hu@mediatek.com>
>> Cc: Philipp Zabel <p.zabel@pengutronix.de>
>> Cc: Matthias Brugger <matthias.bgg@gmail.com>
>> Cc: Rob Clark <robdclark@gmail.com>
>> Cc: Ben Skeggs <bskeggs@redhat.com>
>> Cc: Thierry Reding <thierry.reding@gmail.com>
>> Cc: Jonathan Hunter <jonathanh@nvidia.com>
>> Cc: Jyri Sarha <jsarha@ti.com>
>> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> Cc: Eric Anholt <eric@anholt.net>
>> Cc: dri-devel at lists.freedesktop.org
>> Cc: linux-kernel at vger.kernel.org
>> Cc: intel-gfx at lists.freedesktop.org
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: linux-mediatek at lists.infradead.org
>> Cc: linux-arm-msm at vger.kernel.org
>> Cc: freedreno at lists.freedesktop.org
>> Cc: nouveau at lists.freedesktop.org
>> Cc: linux-tegra at vger.kernel.org
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> We kinda need to backport this to older kernels, but I don't really see
> how :( Maybe we should split this up:
> patch 1: Change to int return type
> patches 2-(n-1): Driver conversions
> patch n: __must_check addition
>
> That would at least somewhat make this backportable ...
>
>> ---
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
>>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
>>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
>>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
>>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
>>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
>>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
>>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
>>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
>>  include/drm/drm_atomic_helper.h              |  4 ++--
>>  10 files changed, 82 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> index 516d9547d331..d4f787bf1d4a 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>>  		goto error;
>>  	}
>>  
>> -	/* Swap the state, this is the point of no return. */
>> -	drm_atomic_helper_swap_state(state, true);
> Push the swap_state up over the commit setup (but after the allocation)
> and there's no more a problem with unrolling.
This can't be done higher up because of the interruptible wait.

Unless we change the patch series to move the waiting for hw_done to a separate step and get rid of the stall argument to swap_state once everything is converted. This could be useful for all drivers that have some kind of setup, because we could move the wait up slightly to suit the drivers needs.

~Maarten

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

* Re: [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
  2017-06-30 13:56   ` Daniel Vetter
  (?)
@ 2017-07-03 12:03       ` Maarten Lankhorst
  -1 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-07-03 12:03 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, David Airlie,
	nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Thierry Reding,
	Daniel Vetter, Boris Brezillon, Jonathan Hunter, Tomi Valkeinen,
	Ben Skeggs, CK Hu, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	intel-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Jyri Sarha,
	Matthias Brugger,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Philipp Zabel,
	freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

Op 30-06-17 om 15:56 schreef Daniel Vetter:
> On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
>> We want to change swap_state to wait indefinitely, but to do this
>> swap_state should wait interruptibly. This requires propagating
>> the error to each driver. All drivers have changes to deal with the
>> clean up. In order to allow easy reverting, the commit that changes
>> behavior is separate so someone only has to revert that for testing.
>>
>> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
>> failed cleanup_planes was not called.
>>
>> Cc: Boris Brezillon <boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>> Cc: David Airlie <airlied-cv59FeDIM0c@public.gmane.org>
>> Cc: Daniel Vetter <daniel.vetter-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
>> Cc: Jani Nikula <jani.nikula-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
>> Cc: Sean Paul <seanpaul-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
>> Cc: CK Hu <ck.hu-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
>> Cc: Philipp Zabel <p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
>> Cc: Matthias Brugger <matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Cc: Rob Clark <robdclark-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Cc: Ben Skeggs <bskeggs-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> Cc: Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> Cc: Jonathan Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>> Cc: Jyri Sarha <jsarha-l0cyMroinI0@public.gmane.org>
>> Cc: Tomi Valkeinen <tomi.valkeinen-l0cyMroinI0@public.gmane.org>
>> Cc: Eric Anholt <eric-WhKQ6XTQaPysTnJN9+BGXg@public.gmane.org>
>> Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Cc: intel-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>> Cc: linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>> Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Cc: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> We kinda need to backport this to older kernels, but I don't really see
> how :( Maybe we should split this up:
> patch 1: Change to int return type
> patches 2-(n-1): Driver conversions
> patch n: __must_check addition
>
> That would at least somewhat make this backportable ...
>
>> ---
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
>>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
>>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
>>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
>>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
>>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
>>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
>>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
>>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
>>  include/drm/drm_atomic_helper.h              |  4 ++--
>>  10 files changed, 82 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> index 516d9547d331..d4f787bf1d4a 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>>  		goto error;
>>  	}
>>  
>> -	/* Swap the state, this is the point of no return. */
>> -	drm_atomic_helper_swap_state(state, true);
> Push the swap_state up over the commit setup (but after the allocation)
> and there's no more a problem with unrolling.
I think just like msm this might also use stall = false safely.
>> diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
>> index 9633a68b14d7..85dd485fdef4 100644
>> --- a/drivers/gpu/drm/msm/msm_atomic.c
>> +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> @@ -232,8 +232,12 @@ int msm_atomic_commit(struct drm_device *dev,
>>  	 * mark our set of crtc's as busy:
>>  	 */
>>  	ret = start_atomic(dev->dev_private, c->crtc_mask);
>> +	if (ret)
>> +		goto err_free;
>> +
>> +	ret = drm_atomic_helper_swap_state(state, true);
> Hm, might be simpler to have stall = false (which btw makes your
> __must_check annotation a lie, you only have to check when you stall),
> since start_atomic above already does stall for everything as needed.
True, could we create a separate function for swap_state_and_wait, and kill the stall argument?
>>  	if (ret) {
>> -		kfree(c);
>> +		commit_destroy(c);
>>  		goto error;
>>  	}
>>  
>> @@ -241,11 +245,9 @@ int msm_atomic_commit(struct drm_device *dev,
>>  	 * 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
>>  	 */
>> -
>> -	drm_atomic_helper_swap_state(state, true);
>> -
>> -	/* swap driver private state while still holding state_lock */
>>  	if (to_kms_state(state)->state)
>>  		priv->kms->funcs->swap_state(priv->kms, state);
>>  
>> @@ -275,6 +277,8 @@ int msm_atomic_commit(struct drm_device *dev,
>>  
>>  	return 0;
>>  
>> +err_free:
>> +	kfree(c);
>>  error:
>>  	drm_atomic_helper_cleanup_planes(dev, state);
>>  	return ret;
>> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
>> index 42a85c14aea0..fb2c763c88a8 100644
>> --- a/drivers/gpu/drm/nouveau/nv50_display.c
>> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
>> @@ -4119,9 +4119,13 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>>  	if (!nonblock) {
>>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>>  		if (ret)
>> -			goto done;
>> +			goto err_cleanup;
>>  	}
>>  
>> +	ret = drm_atomic_helper_swap_state(state, true);
>> +	if (ret)
>> +		goto err_cleanup;
>> +
>>  	for_each_plane_in_state(state, plane, plane_state, i) {
>>  		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
>>  		struct nv50_wndw *wndw = nv50_wndw(plane);
>> @@ -4135,7 +4139,6 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>>  		}
>>  	}
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>>  	drm_atomic_state_get(state);
>>  
>>  	if (nonblock)
>> @@ -4158,7 +4161,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>>  		pm_runtime_put_autosuspend(dev->dev);
>>  		drm->have_disp_power_ref = false;
>>  	}
>> +	goto done;
>>  
>> +err_cleanup:
>> +	drm_atomic_helper_cleanup_planes(dev, state);
>>  done:
>>  	pm_runtime_put_autosuspend(dev->dev);
>>  	return ret;
> lgtm, but might want to split out the bugfix.
>
>> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
>> index ad3d124a972d..3ba659a5940d 100644
>> --- a/drivers/gpu/drm/tegra/drm.c
>> +++ b/drivers/gpu/drm/tegra/drm.c
>> @@ -100,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm,
>>  	 * the software side now.
>>  	 */
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>> +	err = drm_atomic_helper_swap_state(state, true);
>> +	if (err) {
>> +		mutex_unlock(&tegra->commit.lock);
>> +		drm_atomic_helper_cleanup_planes(drm, state);
>> +		return err;
>> +	}
>>  
>>  	drm_atomic_state_get(state);
>>  	if (nonblock)
> lgtm.
>
>> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
>> index d67e18983a7d..049d2f5a1ee4 100644
>> --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
>> +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
>> @@ -108,7 +108,11 @@ static int tilcdc_commit(struct drm_device *dev,
>>  	if (ret)
>>  		return ret;
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>> +	ret = drm_atomic_helper_swap_state(state, true);
>> +	if (ret) {
>> +		drm_atomic_helper_cleanup_planes(dev, state);
>> +		return ret;
>> +	}
>>  
>>  	/*
>>  	 * Everything below can be run asynchronously without the need to grab
> lgtm.
>
> Well tilcdc should stop hand-rolling their commit since it's not even
> nonblocking, but meh.
>
>> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
>> index 27edae427025..83952a4014a5 100644
>> --- a/drivers/gpu/drm/vc4/vc4_kms.c
>> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
>> @@ -113,20 +113,20 @@ static int vc4_atomic_commit(struct drm_device *dev,
>>  
>>  	if (!nonblock) {
>>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>> -		if (ret) {
>> -			drm_atomic_helper_cleanup_planes(dev, state);
>> -			up(&vc4->async_modeset);
>> -			return ret;
>> -		}
>> +		if (ret)
>> +			goto err;
>>  	}
>>  
>>  	/*
>> -	 * 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
>> +	 * If swap_state() succeeds, 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.
>>  	 */
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>> +	ret = drm_atomic_helper_swap_state(state, true);
>> +	if (ret)
>> +		goto err;
>>  
>>  	/*
>>  	 * Everything below can be run asynchronously without the need to grab
>> @@ -151,6 +151,11 @@ static int vc4_atomic_commit(struct drm_device *dev,
>>  		vc4_atomic_complete_commit(state);
>>  
>>  	return 0;
>> +
>> +err:
>> +	drm_atomic_helper_cleanup_planes(dev, state);
>> +	up(&vc4->async_modeset);
>> +	return ret;
>>  }
>>  
>>  static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
> lgtm. Will probably clash with ongoing work in vc4 to switch to plain
> drm_atomic_helper_commit().
>
>> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
>> index 3bfeb2b2f746..4f3b6b5362ec 100644
>> --- a/include/drm/drm_atomic_helper.h
>> +++ b/include/drm/drm_atomic_helper.h
>> @@ -80,8 +80,8 @@ void
>>  drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state,
>>  					 bool atomic);
>>  
>> -void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>> -				  bool stall);
>> +int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>> +					      bool stall);
> __must_check is a lie I think, since with stall = false you don't need it.
> -Daniel
>
>>  
>>  /* nonblocking commit helpers */
>>  int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
>> -- 
>> 2.11.0
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-07-03 12:03       ` Maarten Lankhorst
  0 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-07-03 12:03 UTC (permalink / raw)
  To: dri-devel, David Airlie, nouveau, Thierry Reding, Daniel Vetter,
	Boris Brezillon, Jonathan Hunter, Tomi Valkeinen, Ben Skeggs,
	CK Hu, linux-tegra, linux-arm-msm, intel-gfx, linux-mediatek,
	Jyri Sarha, Matthias Brugger, linux-arm-kernel, linux-kernel,
	Philipp Zabel, freedreno

Op 30-06-17 om 15:56 schreef Daniel Vetter:
> On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
>> We want to change swap_state to wait indefinitely, but to do this
>> swap_state should wait interruptibly. This requires propagating
>> the error to each driver. All drivers have changes to deal with the
>> clean up. In order to allow easy reverting, the commit that changes
>> behavior is separate so someone only has to revert that for testing.
>>
>> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
>> failed cleanup_planes was not called.
>>
>> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
>> Cc: David Airlie <airlied@linux.ie>
>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>> Cc: Sean Paul <seanpaul@chromium.org>
>> Cc: CK Hu <ck.hu@mediatek.com>
>> Cc: Philipp Zabel <p.zabel@pengutronix.de>
>> Cc: Matthias Brugger <matthias.bgg@gmail.com>
>> Cc: Rob Clark <robdclark@gmail.com>
>> Cc: Ben Skeggs <bskeggs@redhat.com>
>> Cc: Thierry Reding <thierry.reding@gmail.com>
>> Cc: Jonathan Hunter <jonathanh@nvidia.com>
>> Cc: Jyri Sarha <jsarha@ti.com>
>> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> Cc: Eric Anholt <eric@anholt.net>
>> Cc: dri-devel@lists.freedesktop.org
>> Cc: linux-kernel@vger.kernel.org
>> Cc: intel-gfx@lists.freedesktop.org
>> Cc: linux-arm-kernel@lists.infradead.org
>> Cc: linux-mediatek@lists.infradead.org
>> Cc: linux-arm-msm@vger.kernel.org
>> Cc: freedreno@lists.freedesktop.org
>> Cc: nouveau@lists.freedesktop.org
>> Cc: linux-tegra@vger.kernel.org
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> We kinda need to backport this to older kernels, but I don't really see
> how :( Maybe we should split this up:
> patch 1: Change to int return type
> patches 2-(n-1): Driver conversions
> patch n: __must_check addition
>
> That would at least somewhat make this backportable ...
>
>> ---
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
>>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
>>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
>>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
>>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
>>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
>>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
>>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
>>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
>>  include/drm/drm_atomic_helper.h              |  4 ++--
>>  10 files changed, 82 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> index 516d9547d331..d4f787bf1d4a 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>>  		goto error;
>>  	}
>>  
>> -	/* Swap the state, this is the point of no return. */
>> -	drm_atomic_helper_swap_state(state, true);
> Push the swap_state up over the commit setup (but after the allocation)
> and there's no more a problem with unrolling.
I think just like msm this might also use stall = false safely.
>> diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
>> index 9633a68b14d7..85dd485fdef4 100644
>> --- a/drivers/gpu/drm/msm/msm_atomic.c
>> +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> @@ -232,8 +232,12 @@ int msm_atomic_commit(struct drm_device *dev,
>>  	 * mark our set of crtc's as busy:
>>  	 */
>>  	ret = start_atomic(dev->dev_private, c->crtc_mask);
>> +	if (ret)
>> +		goto err_free;
>> +
>> +	ret = drm_atomic_helper_swap_state(state, true);
> Hm, might be simpler to have stall = false (which btw makes your
> __must_check annotation a lie, you only have to check when you stall),
> since start_atomic above already does stall for everything as needed.
True, could we create a separate function for swap_state_and_wait, and kill the stall argument?
>>  	if (ret) {
>> -		kfree(c);
>> +		commit_destroy(c);
>>  		goto error;
>>  	}
>>  
>> @@ -241,11 +245,9 @@ int msm_atomic_commit(struct drm_device *dev,
>>  	 * 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
>>  	 */
>> -
>> -	drm_atomic_helper_swap_state(state, true);
>> -
>> -	/* swap driver private state while still holding state_lock */
>>  	if (to_kms_state(state)->state)
>>  		priv->kms->funcs->swap_state(priv->kms, state);
>>  
>> @@ -275,6 +277,8 @@ int msm_atomic_commit(struct drm_device *dev,
>>  
>>  	return 0;
>>  
>> +err_free:
>> +	kfree(c);
>>  error:
>>  	drm_atomic_helper_cleanup_planes(dev, state);
>>  	return ret;
>> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
>> index 42a85c14aea0..fb2c763c88a8 100644
>> --- a/drivers/gpu/drm/nouveau/nv50_display.c
>> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
>> @@ -4119,9 +4119,13 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>>  	if (!nonblock) {
>>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>>  		if (ret)
>> -			goto done;
>> +			goto err_cleanup;
>>  	}
>>  
>> +	ret = drm_atomic_helper_swap_state(state, true);
>> +	if (ret)
>> +		goto err_cleanup;
>> +
>>  	for_each_plane_in_state(state, plane, plane_state, i) {
>>  		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
>>  		struct nv50_wndw *wndw = nv50_wndw(plane);
>> @@ -4135,7 +4139,6 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>>  		}
>>  	}
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>>  	drm_atomic_state_get(state);
>>  
>>  	if (nonblock)
>> @@ -4158,7 +4161,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>>  		pm_runtime_put_autosuspend(dev->dev);
>>  		drm->have_disp_power_ref = false;
>>  	}
>> +	goto done;
>>  
>> +err_cleanup:
>> +	drm_atomic_helper_cleanup_planes(dev, state);
>>  done:
>>  	pm_runtime_put_autosuspend(dev->dev);
>>  	return ret;
> lgtm, but might want to split out the bugfix.
>
>> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
>> index ad3d124a972d..3ba659a5940d 100644
>> --- a/drivers/gpu/drm/tegra/drm.c
>> +++ b/drivers/gpu/drm/tegra/drm.c
>> @@ -100,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm,
>>  	 * the software side now.
>>  	 */
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>> +	err = drm_atomic_helper_swap_state(state, true);
>> +	if (err) {
>> +		mutex_unlock(&tegra->commit.lock);
>> +		drm_atomic_helper_cleanup_planes(drm, state);
>> +		return err;
>> +	}
>>  
>>  	drm_atomic_state_get(state);
>>  	if (nonblock)
> lgtm.
>
>> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
>> index d67e18983a7d..049d2f5a1ee4 100644
>> --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
>> +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
>> @@ -108,7 +108,11 @@ static int tilcdc_commit(struct drm_device *dev,
>>  	if (ret)
>>  		return ret;
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>> +	ret = drm_atomic_helper_swap_state(state, true);
>> +	if (ret) {
>> +		drm_atomic_helper_cleanup_planes(dev, state);
>> +		return ret;
>> +	}
>>  
>>  	/*
>>  	 * Everything below can be run asynchronously without the need to grab
> lgtm.
>
> Well tilcdc should stop hand-rolling their commit since it's not even
> nonblocking, but meh.
>
>> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
>> index 27edae427025..83952a4014a5 100644
>> --- a/drivers/gpu/drm/vc4/vc4_kms.c
>> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
>> @@ -113,20 +113,20 @@ static int vc4_atomic_commit(struct drm_device *dev,
>>  
>>  	if (!nonblock) {
>>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>> -		if (ret) {
>> -			drm_atomic_helper_cleanup_planes(dev, state);
>> -			up(&vc4->async_modeset);
>> -			return ret;
>> -		}
>> +		if (ret)
>> +			goto err;
>>  	}
>>  
>>  	/*
>> -	 * 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
>> +	 * If swap_state() succeeds, 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.
>>  	 */
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>> +	ret = drm_atomic_helper_swap_state(state, true);
>> +	if (ret)
>> +		goto err;
>>  
>>  	/*
>>  	 * Everything below can be run asynchronously without the need to grab
>> @@ -151,6 +151,11 @@ static int vc4_atomic_commit(struct drm_device *dev,
>>  		vc4_atomic_complete_commit(state);
>>  
>>  	return 0;
>> +
>> +err:
>> +	drm_atomic_helper_cleanup_planes(dev, state);
>> +	up(&vc4->async_modeset);
>> +	return ret;
>>  }
>>  
>>  static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
> lgtm. Will probably clash with ongoing work in vc4 to switch to plain
> drm_atomic_helper_commit().
>
>> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
>> index 3bfeb2b2f746..4f3b6b5362ec 100644
>> --- a/include/drm/drm_atomic_helper.h
>> +++ b/include/drm/drm_atomic_helper.h
>> @@ -80,8 +80,8 @@ void
>>  drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state,
>>  					 bool atomic);
>>  
>> -void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>> -				  bool stall);
>> +int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>> +					      bool stall);
> __must_check is a lie I think, since with stall = false you don't need it.
> -Daniel
>
>>  
>>  /* nonblocking commit helpers */
>>  int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
>> -- 
>> 2.11.0
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-07-03 12:03       ` Maarten Lankhorst
  0 siblings, 0 replies; 21+ messages in thread
From: Maarten Lankhorst @ 2017-07-03 12:03 UTC (permalink / raw)
  To: linux-arm-kernel

Op 30-06-17 om 15:56 schreef Daniel Vetter:
> On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
>> We want to change swap_state to wait indefinitely, but to do this
>> swap_state should wait interruptibly. This requires propagating
>> the error to each driver. All drivers have changes to deal with the
>> clean up. In order to allow easy reverting, the commit that changes
>> behavior is separate so someone only has to revert that for testing.
>>
>> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
>> failed cleanup_planes was not called.
>>
>> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
>> Cc: David Airlie <airlied@linux.ie>
>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>> Cc: Jani Nikula <jani.nikula@linux.intel.com>
>> Cc: Sean Paul <seanpaul@chromium.org>
>> Cc: CK Hu <ck.hu@mediatek.com>
>> Cc: Philipp Zabel <p.zabel@pengutronix.de>
>> Cc: Matthias Brugger <matthias.bgg@gmail.com>
>> Cc: Rob Clark <robdclark@gmail.com>
>> Cc: Ben Skeggs <bskeggs@redhat.com>
>> Cc: Thierry Reding <thierry.reding@gmail.com>
>> Cc: Jonathan Hunter <jonathanh@nvidia.com>
>> Cc: Jyri Sarha <jsarha@ti.com>
>> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
>> Cc: Eric Anholt <eric@anholt.net>
>> Cc: dri-devel at lists.freedesktop.org
>> Cc: linux-kernel at vger.kernel.org
>> Cc: intel-gfx at lists.freedesktop.org
>> Cc: linux-arm-kernel at lists.infradead.org
>> Cc: linux-mediatek at lists.infradead.org
>> Cc: linux-arm-msm at vger.kernel.org
>> Cc: freedreno at lists.freedesktop.org
>> Cc: nouveau at lists.freedesktop.org
>> Cc: linux-tegra at vger.kernel.org
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> We kinda need to backport this to older kernels, but I don't really see
> how :( Maybe we should split this up:
> patch 1: Change to int return type
> patches 2-(n-1): Driver conversions
> patch n: __must_check addition
>
> That would at least somewhat make this backportable ...
>
>> ---
>>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
>>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
>>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
>>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
>>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
>>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
>>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
>>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
>>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
>>  include/drm/drm_atomic_helper.h              |  4 ++--
>>  10 files changed, 82 insertions(+), 29 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> index 516d9547d331..d4f787bf1d4a 100644
>> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
>> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
>>  		goto error;
>>  	}
>>  
>> -	/* Swap the state, this is the point of no return. */
>> -	drm_atomic_helper_swap_state(state, true);
> Push the swap_state up over the commit setup (but after the allocation)
> and there's no more a problem with unrolling.
I think just like msm this might also use stall = false safely.
>> diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
>> index 9633a68b14d7..85dd485fdef4 100644
>> --- a/drivers/gpu/drm/msm/msm_atomic.c
>> +++ b/drivers/gpu/drm/msm/msm_atomic.c
>> @@ -232,8 +232,12 @@ int msm_atomic_commit(struct drm_device *dev,
>>  	 * mark our set of crtc's as busy:
>>  	 */
>>  	ret = start_atomic(dev->dev_private, c->crtc_mask);
>> +	if (ret)
>> +		goto err_free;
>> +
>> +	ret = drm_atomic_helper_swap_state(state, true);
> Hm, might be simpler to have stall = false (which btw makes your
> __must_check annotation a lie, you only have to check when you stall),
> since start_atomic above already does stall for everything as needed.
True, could we create a separate function for swap_state_and_wait, and kill the stall argument?
>>  	if (ret) {
>> -		kfree(c);
>> +		commit_destroy(c);
>>  		goto error;
>>  	}
>>  
>> @@ -241,11 +245,9 @@ int msm_atomic_commit(struct drm_device *dev,
>>  	 * 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
>>  	 */
>> -
>> -	drm_atomic_helper_swap_state(state, true);
>> -
>> -	/* swap driver private state while still holding state_lock */
>>  	if (to_kms_state(state)->state)
>>  		priv->kms->funcs->swap_state(priv->kms, state);
>>  
>> @@ -275,6 +277,8 @@ int msm_atomic_commit(struct drm_device *dev,
>>  
>>  	return 0;
>>  
>> +err_free:
>> +	kfree(c);
>>  error:
>>  	drm_atomic_helper_cleanup_planes(dev, state);
>>  	return ret;
>> diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
>> index 42a85c14aea0..fb2c763c88a8 100644
>> --- a/drivers/gpu/drm/nouveau/nv50_display.c
>> +++ b/drivers/gpu/drm/nouveau/nv50_display.c
>> @@ -4119,9 +4119,13 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>>  	if (!nonblock) {
>>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>>  		if (ret)
>> -			goto done;
>> +			goto err_cleanup;
>>  	}
>>  
>> +	ret = drm_atomic_helper_swap_state(state, true);
>> +	if (ret)
>> +		goto err_cleanup;
>> +
>>  	for_each_plane_in_state(state, plane, plane_state, i) {
>>  		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
>>  		struct nv50_wndw *wndw = nv50_wndw(plane);
>> @@ -4135,7 +4139,6 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>>  		}
>>  	}
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>>  	drm_atomic_state_get(state);
>>  
>>  	if (nonblock)
>> @@ -4158,7 +4161,10 @@ nv50_disp_atomic_commit(struct drm_device *dev,
>>  		pm_runtime_put_autosuspend(dev->dev);
>>  		drm->have_disp_power_ref = false;
>>  	}
>> +	goto done;
>>  
>> +err_cleanup:
>> +	drm_atomic_helper_cleanup_planes(dev, state);
>>  done:
>>  	pm_runtime_put_autosuspend(dev->dev);
>>  	return ret;
> lgtm, but might want to split out the bugfix.
>
>> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
>> index ad3d124a972d..3ba659a5940d 100644
>> --- a/drivers/gpu/drm/tegra/drm.c
>> +++ b/drivers/gpu/drm/tegra/drm.c
>> @@ -100,7 +100,12 @@ static int tegra_atomic_commit(struct drm_device *drm,
>>  	 * the software side now.
>>  	 */
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>> +	err = drm_atomic_helper_swap_state(state, true);
>> +	if (err) {
>> +		mutex_unlock(&tegra->commit.lock);
>> +		drm_atomic_helper_cleanup_planes(drm, state);
>> +		return err;
>> +	}
>>  
>>  	drm_atomic_state_get(state);
>>  	if (nonblock)
> lgtm.
>
>> diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
>> index d67e18983a7d..049d2f5a1ee4 100644
>> --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
>> +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
>> @@ -108,7 +108,11 @@ static int tilcdc_commit(struct drm_device *dev,
>>  	if (ret)
>>  		return ret;
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>> +	ret = drm_atomic_helper_swap_state(state, true);
>> +	if (ret) {
>> +		drm_atomic_helper_cleanup_planes(dev, state);
>> +		return ret;
>> +	}
>>  
>>  	/*
>>  	 * Everything below can be run asynchronously without the need to grab
> lgtm.
>
> Well tilcdc should stop hand-rolling their commit since it's not even
> nonblocking, but meh.
>
>> diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
>> index 27edae427025..83952a4014a5 100644
>> --- a/drivers/gpu/drm/vc4/vc4_kms.c
>> +++ b/drivers/gpu/drm/vc4/vc4_kms.c
>> @@ -113,20 +113,20 @@ static int vc4_atomic_commit(struct drm_device *dev,
>>  
>>  	if (!nonblock) {
>>  		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
>> -		if (ret) {
>> -			drm_atomic_helper_cleanup_planes(dev, state);
>> -			up(&vc4->async_modeset);
>> -			return ret;
>> -		}
>> +		if (ret)
>> +			goto err;
>>  	}
>>  
>>  	/*
>> -	 * 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
>> +	 * If swap_state() succeeds, 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.
>>  	 */
>>  
>> -	drm_atomic_helper_swap_state(state, true);
>> +	ret = drm_atomic_helper_swap_state(state, true);
>> +	if (ret)
>> +		goto err;
>>  
>>  	/*
>>  	 * Everything below can be run asynchronously without the need to grab
>> @@ -151,6 +151,11 @@ static int vc4_atomic_commit(struct drm_device *dev,
>>  		vc4_atomic_complete_commit(state);
>>  
>>  	return 0;
>> +
>> +err:
>> +	drm_atomic_helper_cleanup_planes(dev, state);
>> +	up(&vc4->async_modeset);
>> +	return ret;
>>  }
>>  
>>  static struct drm_framebuffer *vc4_fb_create(struct drm_device *dev,
> lgtm. Will probably clash with ongoing work in vc4 to switch to plain
> drm_atomic_helper_commit().
>
>> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
>> index 3bfeb2b2f746..4f3b6b5362ec 100644
>> --- a/include/drm/drm_atomic_helper.h
>> +++ b/include/drm/drm_atomic_helper.h
>> @@ -80,8 +80,8 @@ void
>>  drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state,
>>  					 bool atomic);
>>  
>> -void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>> -				  bool stall);
>> +int __must_check drm_atomic_helper_swap_state(struct drm_atomic_state *state,
>> +					      bool stall);
> __must_check is a lie I think, since with stall = false you don't need it.
> -Daniel
>
>>  
>>  /* nonblocking commit helpers */
>>  int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
>> -- 
>> 2.11.0
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
  2017-07-03 11:01       ` Maarten Lankhorst
  (?)
@ 2017-07-03 16:35         ` Daniel Vetter
  -1 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-03 16:35 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: Boris Brezillon, David Airlie, nouveau, Tomi Valkeinen,
	Jyri Sarha, linux-kernel, dri-devel, Jonathan Hunter,
	linux-tegra, Thierry Reding, linux-mediatek, Ben Skeggs,
	Philipp Zabel, linux-arm-msm, CK Hu, Daniel Vetter, freedreno,
	intel-gfx, linux-arm-kernel, Matthias Brugger

On Mon, Jul 03, 2017 at 01:01:55PM +0200, Maarten Lankhorst wrote:
> Op 30-06-17 om 15:56 schreef Daniel Vetter:
> > On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
> >> We want to change swap_state to wait indefinitely, but to do this
> >> swap_state should wait interruptibly. This requires propagating
> >> the error to each driver. All drivers have changes to deal with the
> >> clean up. In order to allow easy reverting, the commit that changes
> >> behavior is separate so someone only has to revert that for testing.
> >>
> >> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
> >> failed cleanup_planes was not called.
> >>
> >> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
> >> Cc: David Airlie <airlied@linux.ie>
> >> Cc: Daniel Vetter <daniel.vetter@intel.com>
> >> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> >> Cc: Sean Paul <seanpaul@chromium.org>
> >> Cc: CK Hu <ck.hu@mediatek.com>
> >> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> >> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> >> Cc: Rob Clark <robdclark@gmail.com>
> >> Cc: Ben Skeggs <bskeggs@redhat.com>
> >> Cc: Thierry Reding <thierry.reding@gmail.com>
> >> Cc: Jonathan Hunter <jonathanh@nvidia.com>
> >> Cc: Jyri Sarha <jsarha@ti.com>
> >> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> >> Cc: Eric Anholt <eric@anholt.net>
> >> Cc: dri-devel@lists.freedesktop.org
> >> Cc: linux-kernel@vger.kernel.org
> >> Cc: intel-gfx@lists.freedesktop.org
> >> Cc: linux-arm-kernel@lists.infradead.org
> >> Cc: linux-mediatek@lists.infradead.org
> >> Cc: linux-arm-msm@vger.kernel.org
> >> Cc: freedreno@lists.freedesktop.org
> >> Cc: nouveau@lists.freedesktop.org
> >> Cc: linux-tegra@vger.kernel.org
> >> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > We kinda need to backport this to older kernels, but I don't really see
> > how :( Maybe we should split this up:
> > patch 1: Change to int return type
> > patches 2-(n-1): Driver conversions
> > patch n: __must_check addition
> >
> > That would at least somewhat make this backportable ...
> >
> >> ---
> >>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
> >>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
> >>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
> >>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
> >>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
> >>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
> >>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
> >>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
> >>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
> >>  include/drm/drm_atomic_helper.h              |  4 ++--
> >>  10 files changed, 82 insertions(+), 29 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> index 516d9547d331..d4f787bf1d4a 100644
> >> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
> >>  		goto error;
> >>  	}
> >>  
> >> -	/* Swap the state, this is the point of no return. */
> >> -	drm_atomic_helper_swap_state(state, true);
> > Push the swap_state up over the commit setup (but after the allocation)
> > and there's no more a problem with unrolling.
> This can't be done higher up because of the interruptible wait.
> 
> Unless we change the patch series to move the waiting for hw_done to a separate step and get rid of the stall argument to swap_state once everything is converted. This could be useful for all drivers that have some kind of setup, because we could move the wait up slightly to suit the drivers needs.

right, swap_state (well the swapping part, not the stalling part) must be
done as the last step and can't fail. Might be a reason do split them, but
not sure that's a good idea either. Please disregard my comment ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-07-03 16:35         ` Daniel Vetter
  0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-03 16:35 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: dri-devel, David Airlie, nouveau, Thierry Reding, Daniel Vetter,
	Boris Brezillon, Jonathan Hunter, Tomi Valkeinen, Ben Skeggs,
	CK Hu, linux-tegra, linux-arm-msm, intel-gfx, linux-mediatek,
	Jyri Sarha, Matthias Brugger, linux-arm-kernel, linux-kernel,
	Philipp Zabel, freedreno

On Mon, Jul 03, 2017 at 01:01:55PM +0200, Maarten Lankhorst wrote:
> Op 30-06-17 om 15:56 schreef Daniel Vetter:
> > On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
> >> We want to change swap_state to wait indefinitely, but to do this
> >> swap_state should wait interruptibly. This requires propagating
> >> the error to each driver. All drivers have changes to deal with the
> >> clean up. In order to allow easy reverting, the commit that changes
> >> behavior is separate so someone only has to revert that for testing.
> >>
> >> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
> >> failed cleanup_planes was not called.
> >>
> >> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
> >> Cc: David Airlie <airlied@linux.ie>
> >> Cc: Daniel Vetter <daniel.vetter@intel.com>
> >> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> >> Cc: Sean Paul <seanpaul@chromium.org>
> >> Cc: CK Hu <ck.hu@mediatek.com>
> >> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> >> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> >> Cc: Rob Clark <robdclark@gmail.com>
> >> Cc: Ben Skeggs <bskeggs@redhat.com>
> >> Cc: Thierry Reding <thierry.reding@gmail.com>
> >> Cc: Jonathan Hunter <jonathanh@nvidia.com>
> >> Cc: Jyri Sarha <jsarha@ti.com>
> >> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> >> Cc: Eric Anholt <eric@anholt.net>
> >> Cc: dri-devel@lists.freedesktop.org
> >> Cc: linux-kernel@vger.kernel.org
> >> Cc: intel-gfx@lists.freedesktop.org
> >> Cc: linux-arm-kernel@lists.infradead.org
> >> Cc: linux-mediatek@lists.infradead.org
> >> Cc: linux-arm-msm@vger.kernel.org
> >> Cc: freedreno@lists.freedesktop.org
> >> Cc: nouveau@lists.freedesktop.org
> >> Cc: linux-tegra@vger.kernel.org
> >> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > We kinda need to backport this to older kernels, but I don't really see
> > how :( Maybe we should split this up:
> > patch 1: Change to int return type
> > patches 2-(n-1): Driver conversions
> > patch n: __must_check addition
> >
> > That would at least somewhat make this backportable ...
> >
> >> ---
> >>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
> >>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
> >>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
> >>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
> >>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
> >>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
> >>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
> >>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
> >>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
> >>  include/drm/drm_atomic_helper.h              |  4 ++--
> >>  10 files changed, 82 insertions(+), 29 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> index 516d9547d331..d4f787bf1d4a 100644
> >> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
> >>  		goto error;
> >>  	}
> >>  
> >> -	/* Swap the state, this is the point of no return. */
> >> -	drm_atomic_helper_swap_state(state, true);
> > Push the swap_state up over the commit setup (but after the allocation)
> > and there's no more a problem with unrolling.
> This can't be done higher up because of the interruptible wait.
> 
> Unless we change the patch series to move the waiting for hw_done to a separate step and get rid of the stall argument to swap_state once everything is converted. This could be useful for all drivers that have some kind of setup, because we could move the wait up slightly to suit the drivers needs.

right, swap_state (well the swapping part, not the stalling part) must be
done as the last step and can't fail. Might be a reason do split them, but
not sure that's a good idea either. Please disregard my comment ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* [Intel-gfx] [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error.
@ 2017-07-03 16:35         ` Daniel Vetter
  0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2017-07-03 16:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 03, 2017 at 01:01:55PM +0200, Maarten Lankhorst wrote:
> Op 30-06-17 om 15:56 schreef Daniel Vetter:
> > On Wed, Jun 28, 2017 at 03:28:11PM +0200, Maarten Lankhorst wrote:
> >> We want to change swap_state to wait indefinitely, but to do this
> >> swap_state should wait interruptibly. This requires propagating
> >> the error to each driver. All drivers have changes to deal with the
> >> clean up. In order to allow easy reverting, the commit that changes
> >> behavior is separate so someone only has to revert that for testing.
> >>
> >> Nouveau has a small bugfix, if drm_atomic_helper_wait_for_fences
> >> failed cleanup_planes was not called.
> >>
> >> Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
> >> Cc: David Airlie <airlied@linux.ie>
> >> Cc: Daniel Vetter <daniel.vetter@intel.com>
> >> Cc: Jani Nikula <jani.nikula@linux.intel.com>
> >> Cc: Sean Paul <seanpaul@chromium.org>
> >> Cc: CK Hu <ck.hu@mediatek.com>
> >> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> >> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> >> Cc: Rob Clark <robdclark@gmail.com>
> >> Cc: Ben Skeggs <bskeggs@redhat.com>
> >> Cc: Thierry Reding <thierry.reding@gmail.com>
> >> Cc: Jonathan Hunter <jonathanh@nvidia.com>
> >> Cc: Jyri Sarha <jsarha@ti.com>
> >> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
> >> Cc: Eric Anholt <eric@anholt.net>
> >> Cc: dri-devel at lists.freedesktop.org
> >> Cc: linux-kernel at vger.kernel.org
> >> Cc: intel-gfx at lists.freedesktop.org
> >> Cc: linux-arm-kernel at lists.infradead.org
> >> Cc: linux-mediatek at lists.infradead.org
> >> Cc: linux-arm-msm at vger.kernel.org
> >> Cc: freedreno at lists.freedesktop.org
> >> Cc: nouveau at lists.freedesktop.org
> >> Cc: linux-tegra at vger.kernel.org
> >> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > We kinda need to backport this to older kernels, but I don't really see
> > how :( Maybe we should split this up:
> > patch 1: Change to int return type
> > patches 2-(n-1): Driver conversions
> > patch n: __must_check addition
> >
> > That would at least somewhat make this backportable ...
> >
> >> ---
> >>  drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 14 ++++++++++++--
> >>  drivers/gpu/drm/drm_atomic_helper.c          | 18 ++++++++++++------
> >>  drivers/gpu/drm/i915/intel_display.c         | 10 +++++++++-
> >>  drivers/gpu/drm/mediatek/mtk_drm_drv.c       |  7 ++++++-
> >>  drivers/gpu/drm/msm/msm_atomic.c             | 14 +++++++++-----
> >>  drivers/gpu/drm/nouveau/nv50_display.c       | 10 ++++++++--
> >>  drivers/gpu/drm/tegra/drm.c                  |  7 ++++++-
> >>  drivers/gpu/drm/tilcdc/tilcdc_drv.c          |  6 +++++-
> >>  drivers/gpu/drm/vc4/vc4_kms.c                | 21 +++++++++++++--------
> >>  include/drm/drm_atomic_helper.h              |  4 ++--
> >>  10 files changed, 82 insertions(+), 29 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> index 516d9547d331..d4f787bf1d4a 100644
> >> --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
> >> @@ -544,9 +544,11 @@ static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
> >>  		goto error;
> >>  	}
> >>  
> >> -	/* Swap the state, this is the point of no return. */
> >> -	drm_atomic_helper_swap_state(state, true);
> > Push the swap_state up over the commit setup (but after the allocation)
> > and there's no more a problem with unrolling.
> This can't be done higher up because of the interruptible wait.
> 
> Unless we change the patch series to move the waiting for hw_done to a separate step and get rid of the stall argument to swap_state once everything is converted. This could be useful for all drivers that have some kind of setup, because we could move the wait up slightly to suit the drivers needs.

right, swap_state (well the swapping part, not the stalling part) must be
done as the last step and can't fail. Might be a reason do split them, but
not sure that's a good idea either. Please disregard my comment ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

end of thread, other threads:[~2017-07-03 16:35 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-28 13:28 [PATCH 1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error Maarten Lankhorst
2017-06-28 13:28 ` Maarten Lankhorst
2017-06-28 13:28 ` Maarten Lankhorst
2017-06-28 13:28 ` [PATCH 2/2] drm/atomic: Wait indefinitely and interruptibly for hw_done Maarten Lankhorst
2017-06-28 13:28   ` Maarten Lankhorst
2017-06-28 13:28   ` Maarten Lankhorst
2017-06-30 13:41   ` Daniel Vetter
2017-06-30 13:41     ` Daniel Vetter
2017-06-28 13:45 ` ✗ Fi.CI.BAT: failure for series starting with [1/2] drm/atomic: Change drm_atomic_helper_swap_state to return an error Patchwork
2017-06-30 13:56 ` [Intel-gfx] [PATCH 1/2] " Daniel Vetter
2017-06-30 13:56   ` Daniel Vetter
2017-06-30 13:56   ` Daniel Vetter
     [not found]   ` <20170630135621.c2xlunjaepne2vqt-dv86pmgwkMBes7Z6vYuT8azUEOm+Xw19@public.gmane.org>
2017-07-03 11:01     ` Maarten Lankhorst
2017-07-03 11:01       ` Maarten Lankhorst
2017-07-03 11:01       ` Maarten Lankhorst
2017-07-03 16:35       ` Daniel Vetter
2017-07-03 16:35         ` [Intel-gfx] " Daniel Vetter
2017-07-03 16:35         ` Daniel Vetter
2017-07-03 12:03     ` Maarten Lankhorst
2017-07-03 12:03       ` Maarten Lankhorst
2017-07-03 12:03       ` Maarten Lankhorst

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.