From ec7ce653d9f6eb22404dee468bf63d8fcaff9c42 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 21 Sep 2016 14:51:07 +0100 Subject: [PATCH] drm/i915: Only shrink the unbound objects during freeze 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] [] dump_stack+0x4d/0x6e [ 44.235461] [] __warn+0xd1/0xf0 [ 44.235464] [] ? i915_pm_suspend_late+0x30/0x30 [ 44.235465] [] warn_slowpath_fmt+0x4f/0x60 [ 44.235468] [] ? pm_runtime_get_if_in_use+0x6e/0xa0 [ 44.235469] [] intel_runtime_pm_get_if_in_use+0xe6/0xf0 [ 44.235471] [] i915_gem_shrink+0x306/0x360 [ 44.235473] [] ? pci_platform_power_transition+0x24/0x90 [ 44.235475] [] ? i915_pm_suspend_late+0x30/0x30 [ 44.235476] [] i915_gem_shrink_all+0x1b/0x30 [ 44.235478] [] i915_gem_freeze_late+0x33/0x90 [ 44.235479] [] i915_pm_freeze_late+0x37/0x40 [ 44.235481] [] dpm_run_callback+0x4e/0x130 [ 44.235483] [] __device_suspend_late+0xdb/0x1f0 [ 44.235484] [] async_suspend_late+0x1f/0xa0 [ 44.235486] [] async_run_entry_fn+0x37/0x150 [ 44.235488] [] process_one_work+0x148/0x3f0 [ 44.235490] [] worker_thread+0x12b/0x490 [ 44.235491] [] ? process_one_work+0x3f0/0x3f0 [ 44.235492] [] kthread+0xc9/0xe0 [ 44.235495] [] ret_from_fork+0x1f/0x40 [ 44.235496] [] ? 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. To keep lockdep silent, we need to take struct_mutex for the shrinker even though we know that we are the only user during the freeze. Fixes: 7aab2d534e35 ("drm/i915: Shrink objects prior to hibernation") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Reviewed-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/20160921135108.29574-2-chris@chris-wilson.co.uk (cherry picked from commit 6a800eabba34945c2986d70114b41d564bad52a8) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.c | 12 +++++++++++- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 17 ++++++++++++++++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8ae5853ea3c6f9..bfb2efd8d4d44e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1863,7 +1863,17 @@ 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 4dd307ed433686..e08001abf1f0e9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3076,6 +3076,7 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data, void 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 eb1ca8886bb964..981a106901ae1a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4596,6 +4596,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; @@ -4619,7 +4632,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) { @@ -4627,6 +4641,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; }