drm/i915: Only shrink the unbound objects during freeze
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 21 Sep 2016 13:51:07 +0000 (14:51 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 21 Sep 2016 15:57:06 +0000 (16:57 +0100)
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.

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 <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20160921135108.29574-2-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c

index 8ae5853ea3c6f9f9f01923c577b4fa170b0cb91f..bfb2efd8d4d44e996d6af1d75299f12fab534c92 100644 (file)
@@ -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)
index 356899543d4b76e1c6531bc2422ae38b5c0a179e..008c74bfabada7634c6e6830628183326f0ac3c5 100644 (file)
@@ -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);
index aeb46658ab3c1c90dd628a5d6792254c18244fd8..1418c1c522cbf2aefbe57eb0792bae1f33eaedc2 100644 (file)
@@ -4593,6 +4593,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;
@@ -4616,7 +4629,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) {
@@ -4624,6 +4638,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;
 }