All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze
@ 2016-09-16 19:23 Chris Wilson
  2016-09-16 19:23 ` [PATCH 2/2] drm/i915/execlists: Reset RING registers upon resume Chris Wilson
  2016-09-19  8:31 ` [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze Joonas Lahtinen
  0 siblings, 2 replies; 6+ messages in thread
From: Chris Wilson @ 2016-09-16 19:23 UTC (permalink / raw)
  To: intel-gfx

At the point of creating the hibernation image, the runtime power manage
core is disabled - and using the rpm functions triggers a warn.
i915_gem_shrink_all() tries to unbind objects, which requires device
access and so tries to how an rpm reference triggering a warning:

[   44.235420] ------------[ cut here ]------------
[   44.235424] WARNING: CPU: 2 PID: 2199 at drivers/gpu/drm/i915/intel_runtime_pm.c:2688 intel_runtime_pm_get_if_in_use+0xe6/0xf0
[   44.235426] WARN_ON_ONCE(ret < 0)
[   44.235445] Modules linked in: ctr ccm arc4 rt2800usb rt2x00usb rt2800lib rt2x00lib crc_ccitt mac80211 cmac cfg80211 btusb rfcomm bnep btrtl btbcm btintel bluetooth dcdbas x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_realtek crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec_generic aesni_intel snd_hda_codec_hdmi aes_x86_64 lrw gf128mul snd_hda_intel glue_helper ablk_helper cryptd snd_hda_codec hid_multitouch joydev snd_hda_core binfmt_misc i2c_hid serio_raw snd_pcm acpi_pad snd_timer snd i2c_designware_platform 8250_dw nls_iso8859_1 i2c_designware_core lpc_ich mfd_core soundcore usbhid hid psmouse ahci libahci
[   44.235447] CPU: 2 PID: 2199 Comm: kworker/u8:8 Not tainted 4.8.0-rc5+ #130
[   44.235447] Hardware name: Dell Inc. XPS 13 9343/0310JH, BIOS A07 11/11/2015
[   44.235450] Workqueue: events_unbound async_run_entry_fn
[   44.235453]  0000000000000000 ffff8801b2f7fb98 ffffffff81306c2f ffff8801b2f7fbe8
[   44.235454]  0000000000000000 ffff8801b2f7fbd8 ffffffff81056c01 00000a801f50ecc0
[   44.235456]  ffff88020ce50000 ffff88020ce59b60 ffffffff81a60b5c ffffffff81414840
[   44.235456] Call Trace:
[   44.235459]  [<ffffffff81306c2f>] dump_stack+0x4d/0x6e
[   44.235461]  [<ffffffff81056c01>] __warn+0xd1/0xf0
[   44.235464]  [<ffffffff81414840>] ? i915_pm_suspend_late+0x30/0x30
[   44.235465]  [<ffffffff81056c6f>] warn_slowpath_fmt+0x4f/0x60
[   44.235468]  [<ffffffff814e73ce>] ? pm_runtime_get_if_in_use+0x6e/0xa0
[   44.235469]  [<ffffffff81433526>] intel_runtime_pm_get_if_in_use+0xe6/0xf0
[   44.235471]  [<ffffffff81458a26>] i915_gem_shrink+0x306/0x360
[   44.235473]  [<ffffffff81343fd4>] ? pci_platform_power_transition+0x24/0x90
[   44.235475]  [<ffffffff81414840>] ? i915_pm_suspend_late+0x30/0x30
[   44.235476]  [<ffffffff81458dfb>] i915_gem_shrink_all+0x1b/0x30
[   44.235478]  [<ffffffff814560b3>] i915_gem_freeze_late+0x33/0x90
[   44.235479]  [<ffffffff81414877>] i915_pm_freeze_late+0x37/0x40
[   44.235481]  [<ffffffff814e9b8e>] dpm_run_callback+0x4e/0x130
[   44.235483]  [<ffffffff814ea5db>] __device_suspend_late+0xdb/0x1f0
[   44.235484]  [<ffffffff814ea70f>] async_suspend_late+0x1f/0xa0
[   44.235486]  [<ffffffff81077557>] async_run_entry_fn+0x37/0x150
[   44.235488]  [<ffffffff8106f518>] process_one_work+0x148/0x3f0
[   44.235490]  [<ffffffff8106f8eb>] worker_thread+0x12b/0x490
[   44.235491]  [<ffffffff8106f7c0>] ? process_one_work+0x3f0/0x3f0
[   44.235492]  [<ffffffff81074d09>] kthread+0xc9/0xe0
[   44.235495]  [<ffffffff816e257f>] ret_from_fork+0x1f/0x40
[   44.235496]  [<ffffffff81074c40>] ? kthread_park+0x60/0x60
[   44.235497] ---[ end trace e438706b97c7f132 ]---

Alternatively, to actually shrink everything we have to do so slightly
earlier in the hibernation process.

Fixes: 7aab2d534e35 ("drm/i915: Shrink objects prior to hibernation")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c | 11 ++++++++++-
 drivers/gpu/drm/i915/i915_drv.h |  1 +
 drivers/gpu/drm/i915/i915_gem.c | 17 ++++++++++++++++-
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b2e67aaad531..b236d0c87fc5 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1869,7 +1869,16 @@ static int i915_pm_resume(struct device *kdev)
 /* freeze: before creating the hibernation_image */
 static int i915_pm_freeze(struct device *kdev)
 {
-	return i915_pm_suspend(kdev);
+	int ret;
+	ret = i915_pm_suspend(kdev);
+	if (ret)
+		return ret;
+
+	ret = i915_gem_freeze(kdev_to_i915(kdev));
+	if (ret)
+		return ret;
+
+	return 0;
 }
 
 static int i915_pm_freeze_late(struct device *kdev)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e6b9f6e49f82..56b5b3cf9a80 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3047,6 +3047,7 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
 int i915_gem_load_init(struct drm_device *dev);
 void i915_gem_load_cleanup(struct drm_device *dev);
 void i915_gem_load_init_fences(struct drm_i915_private *dev_priv);
+int i915_gem_freeze(struct drm_i915_private *dev_priv);
 int i915_gem_freeze_late(struct drm_i915_private *dev_priv);
 
 void *i915_gem_object_alloc(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 28914374c286..3c99450e5ee5 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4669,6 +4669,19 @@ void i915_gem_load_cleanup(struct drm_device *dev)
 	rcu_barrier();
 }
 
+int i915_gem_freeze(struct drm_i915_private *dev_priv)
+{
+	intel_runtime_pm_get(dev_priv);
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	i915_gem_shrink_all(dev_priv);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+
+	intel_runtime_pm_put(dev_priv);
+
+	return 0;
+}
+
 int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
 {
 	struct drm_i915_gem_object *obj;
@@ -4692,7 +4705,8 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
 	 * the objects as well.
 	 */
 
-	i915_gem_shrink_all(dev_priv);
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	i915_gem_shrink(dev_priv, -1UL, I915_SHRINK_UNBOUND);
 
 	for (p = phases; *p; p++) {
 		list_for_each_entry(obj, *p, global_list) {
@@ -4700,6 +4714,7 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
 			obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 		}
 	}
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 
 	return 0;
 }
-- 
2.9.3

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

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

* [PATCH 2/2] drm/i915/execlists: Reset RING registers upon resume
  2016-09-16 19:23 [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze Chris Wilson
@ 2016-09-16 19:23 ` Chris Wilson
  2016-09-19  8:24   ` Joonas Lahtinen
  2016-09-19  8:31 ` [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze Joonas Lahtinen
  1 sibling, 1 reply; 6+ messages in thread
From: Chris Wilson @ 2016-09-16 19:23 UTC (permalink / raw)
  To: intel-gfx

There is a disparity in the context image saved to disk and our own
bookkeeping - that is we presume the RING_HEAD and RING_TAIL match our
stored ce->ring->tail value. However, as we emit WA_TAIL_DWORDS into the
ring but may not tell the GPU about them, the GPU may be lagging behind
our bookkeeping. Upon hibernation we do not save stolen pages, presuming
that their contents are volatile. This means that although we start
writing into the ring at tail, the GPU starts executing from its HEAD
and there may be some garbage in between and so the GPU promptly hangs
upon resume.

Testcase: igt/gem_exec_suspend/basic-S4
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=96526
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/intel_lrc.c | 49 ++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index bc1786478f8e..ec2ad603be86 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2100,30 +2100,41 @@ error_deref_obj:
 
 void intel_lr_context_resume(struct drm_i915_private *dev_priv)
 {
-	struct i915_gem_context *ctx = dev_priv->kernel_context;
 	struct intel_engine_cs *engine;
+	struct i915_gem_context *ctx;
+
+	/* Because we emit WA_TAIL_DWORDS there may be a disparity
+	 * between our bookkeeping in ce->ring->head and ce->ring->tail and
+	 * that stored in context. As we only write new comamnds from
+	 * ce->ring->tail onwards, everything before that is junk. If the GPU
+	 * starts reading from its RING_HEAD from the context, it may try to
+	 * execute that junk and die.
+	 *
+	 * So to avoid that we reset the context images upon resume. For
+	 * simplicity, we just zero everything out.
+	 */
+	list_for_each_entry(ctx, &dev_priv->context_list, link) {
+		for_each_engine(engine, dev_priv) {
+			struct intel_context *ce = &ctx->engine[engine->id];
+			u32 *reg_state;
 
-	for_each_engine(engine, dev_priv) {
-		struct intel_context *ce = &ctx->engine[engine->id];
-		void *vaddr;
-		uint32_t *reg_state;
-
-		if (!ce->state)
-			continue;
-
-		vaddr = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB);
-		if (WARN_ON(IS_ERR(vaddr)))
-			continue;
+			if (!ce->state)
+				continue;
 
-		reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
+			reg_state = i915_gem_object_pin_map(ce->state->obj,
+							    I915_MAP_WB);
+			if (WARN_ON(IS_ERR(reg_state)))
+				continue;
 
-		reg_state[CTX_RING_HEAD+1] = 0;
-		reg_state[CTX_RING_TAIL+1] = 0;
+			reg_state += LRC_STATE_PN * PAGE_SIZE / sizeof(u32);
+			reg_state[CTX_RING_HEAD+1] = 0;
+			reg_state[CTX_RING_TAIL+1] = 0;
 
-		ce->state->obj->dirty = true;
-		i915_gem_object_unpin_map(ce->state->obj);
+			ce->state->obj->dirty = true;
+			i915_gem_object_unpin_map(ce->state->obj);
 
-		ce->ring->head = 0;
-		ce->ring->tail = 0;
+			ce->ring->head = ce->ring->tail = 0;
+			ce->ring->last_retired_head = -1;
+		}
 	}
 }
-- 
2.9.3

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

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

* Re: [PATCH 2/2] drm/i915/execlists: Reset RING registers upon resume
  2016-09-16 19:23 ` [PATCH 2/2] drm/i915/execlists: Reset RING registers upon resume Chris Wilson
@ 2016-09-19  8:24   ` Joonas Lahtinen
  0 siblings, 0 replies; 6+ messages in thread
From: Joonas Lahtinen @ 2016-09-19  8:24 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On pe, 2016-09-16 at 20:23 +0100, Chris Wilson wrote:
>  void intel_lr_context_resume(struct drm_i915_private *dev_priv)
>  {
> > -	struct i915_gem_context *ctx = dev_priv->kernel_context;
> >  	struct intel_engine_cs *engine;
> > +	struct i915_gem_context *ctx;
> +
> > +	/* Because we emit WA_TAIL_DWORDS there may be a disparity
> > +	 * between our bookkeeping in ce->ring->head and ce->ring->tail and
> +	 * that stored in context. As we only write new comamnds from

"new commands"

> +	 * ce->ring->tail onwards, everything before that is junk. If the GPU
> > +	 * starts reading from its RING_HEAD from the context, it may try to
> > +	 * execute that junk and die.
> > +	 *
> > +	 * So to avoid that we reset the context images upon resume. For
> > +	 * simplicity, we just zero everything out.
> > +	 */
> > +	list_for_each_entry(ctx, &dev_priv->context_list, link) {
> > +		for_each_engine(engine, dev_priv) {
> > +			struct intel_context *ce = &ctx->engine[engine->id];
> > +			u32 *reg_state;
>  
> > -	for_each_engine(engine, dev_priv) {
> > -		struct intel_context *ce = &ctx->engine[engine->id];
> > -		void *vaddr;
> > -		uint32_t *reg_state;
> -
> > -		if (!ce->state)
> > -			continue;
> -
> > -		vaddr = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB);
> > -		if (WARN_ON(IS_ERR(vaddr)))
> > -			continue;
> > +			if (!ce->state)
> > +				continue;
>  
> > -		reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
> > +			reg_state = i915_gem_object_pin_map(ce->state->obj,
> > +							    I915_MAP_WB);
> > +			if (WARN_ON(IS_ERR(reg_state)))
> > +				continue;
>  
> > -		reg_state[CTX_RING_HEAD+1] = 0;
> > -		reg_state[CTX_RING_TAIL+1] = 0;
> +			reg_state += LRC_STATE_PN * PAGE_SIZE / sizeof(u32);

/ sizeof(*reg_state) I presume.

Also add a newline here.

With those;

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>

Regards, Joonas
-- 
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze
  2016-09-16 19:23 [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze Chris Wilson
  2016-09-16 19:23 ` [PATCH 2/2] drm/i915/execlists: Reset RING registers upon resume Chris Wilson
@ 2016-09-19  8:31 ` Joonas Lahtinen
  2016-09-19  8:38   ` Chris Wilson
  1 sibling, 1 reply; 6+ messages in thread
From: Joonas Lahtinen @ 2016-09-19  8:31 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx

On pe, 2016-09-16 at 20:23 +0100, Chris Wilson wrote:
>  int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
>  {
> >  	struct drm_i915_gem_object *obj;
> @@ -4692,7 +4705,8 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
> >  	 * the objects as well.
> >  	 */
>  
> > -	i915_gem_shrink_all(dev_priv);
> +	mutex_lock(&dev_priv->drm.struct_mutex);

Previously the shrinking here was without a mutex. And the new
shrinking during _freeze is also mutex protected, any specific reason?

Regards, Joonas
-- 
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze
  2016-09-19  8:31 ` [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze Joonas Lahtinen
@ 2016-09-19  8:38   ` Chris Wilson
  2016-09-19 12:09     ` Joonas Lahtinen
  0 siblings, 1 reply; 6+ messages in thread
From: Chris Wilson @ 2016-09-19  8:38 UTC (permalink / raw)
  To: Joonas Lahtinen; +Cc: intel-gfx

On Mon, Sep 19, 2016 at 11:31:37AM +0300, Joonas Lahtinen wrote:
> On pe, 2016-09-16 at 20:23 +0100, Chris Wilson wrote:
> >  int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
> >  {
> > >  	struct drm_i915_gem_object *obj;
> > @@ -4692,7 +4705,8 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
> > >  	 * the objects as well.
> > >  	 */
> >  
> > > -	i915_gem_shrink_all(dev_priv);
> > +	mutex_lock(&dev_priv->drm.struct_mutex);
> 
> Previously the shrinking here was without a mutex. And the new
> shrinking during _freeze is also mutex protected, any specific reason?

Silencing lockdep. We know we are single threaded here, but lockdep
doesn't. This version of i915_gem_shrink() doesn't automagically take
the struct_mutex (later versions do).
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze
  2016-09-19  8:38   ` Chris Wilson
@ 2016-09-19 12:09     ` Joonas Lahtinen
  0 siblings, 0 replies; 6+ messages in thread
From: Joonas Lahtinen @ 2016-09-19 12:09 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

On ma, 2016-09-19 at 09:38 +0100, Chris Wilson wrote:
> On Mon, Sep 19, 2016 at 11:31:37AM +0300, Joonas Lahtinen wrote:
> > 
> > On pe, 2016-09-16 at 20:23 +0100, Chris Wilson wrote:
> > > 
> > >  int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
> > >  {
> > > > 
> > > > > > > >  	struct drm_i915_gem_object *obj;
> > > @@ -4692,7 +4705,8 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv)
> > > > 
> > > > > > > >  	 * the objects as well.
> > > > > > > >  	 */
> > >  
> > > > 
> > > > > > > > -	i915_gem_shrink_all(dev_priv);
> > > > > > +	mutex_lock(&dev_priv->drm.struct_mutex);
> > 
> > Previously the shrinking here was without a mutex. And the new
> > shrinking during _freeze is also mutex protected, any specific reason?
> 
> Silencing lockdep. We know we are single threaded here, but lockdep
> doesn't. This version of i915_gem_shrink() doesn't automagically take
> the struct_mutex (later versions do).

Throw the info to commit message. Then all good.

Regards, Joonas

> -Chris
> 
-- 
Joonas Lahtinen
Open Source Technology Center
Intel Corporation
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

end of thread, other threads:[~2016-09-19 12:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-16 19:23 [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze Chris Wilson
2016-09-16 19:23 ` [PATCH 2/2] drm/i915/execlists: Reset RING registers upon resume Chris Wilson
2016-09-19  8:24   ` Joonas Lahtinen
2016-09-19  8:31 ` [PATCH 1/2] drm/i915: Only shrink the unbound objects during freeze Joonas Lahtinen
2016-09-19  8:38   ` Chris Wilson
2016-09-19 12:09     ` Joonas Lahtinen

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.