All of lore.kernel.org
 help / color / mirror / Atom feed
* Track rpm wakerefs to fix bugs
@ 2019-01-10 10:11 Chris Wilson
  2019-01-10 10:11 ` [PATCH 01/21] drm/i915: Track all held rpm wakerefs Chris Wilson
                   ` (23 more replies)
  0 siblings, 24 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx

If we keep a cookie for every time we acquire a wakeref, we can use that
to keep track of who holds a wakeref and more importantly who still
holds one at important junctures (when the rpm count unexpectedly goes
to zero!)

Culminating in a bugfix for Ironlake which CI has been tripping over for
many months, pretty much disabling fi-ilk-m540.
-Chris


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

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

* [PATCH 01/21] drm/i915: Track all held rpm wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 02/21] drm/i915: Markup paired operations on wakerefs Chris Wilson
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Everytime we take a wakeref, record the stack trace of where it was
taken; clearing the set if we ever drop back to no owners. For debugging
a rpm leak, we can look at all the current wakerefs and check if they
have a matching rpm_put.

v2: Use skip=0 for unwinding the stack as it appears our noinline
function doesn't appear on the stack (nor does save_stack_trace itself!)
v3: Allow rpm->debug_count to disappear between inspections and so
avoid calling krealloc(0) as that may return a ZERO_PTR not NULL! (Mika)
v4: Show who last acquire/released the runtime pm

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Tested-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/Kconfig.debug            |   3 +-
 drivers/gpu/drm/i915/i915_debugfs.c           |   6 +
 drivers/gpu/drm/i915/i915_drv.c               |   8 +-
 drivers/gpu/drm/i915/i915_drv.h               |  20 ++
 drivers/gpu/drm/i915/intel_drv.h              |  44 ++-
 drivers/gpu/drm/i915/intel_runtime_pm.c       | 315 ++++++++++++++++--
 .../gpu/drm/i915/selftests/mock_gem_device.c  |   8 +-
 7 files changed, 354 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
index 9e36ffb5eb7c..ad4d71161dda 100644
--- a/drivers/gpu/drm/i915/Kconfig.debug
+++ b/drivers/gpu/drm/i915/Kconfig.debug
@@ -21,11 +21,11 @@ config DRM_I915_DEBUG
         select DEBUG_FS
         select PREEMPT_COUNT
         select I2C_CHARDEV
+        select STACKDEPOT
         select DRM_DP_AUX_CHARDEV
         select X86_MSR # used by igt/pm_rpm
         select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
         select DRM_DEBUG_MM if DRM=y
-        select STACKDEPOT if DRM=y # for DRM_DEBUG_MM
 	select DRM_DEBUG_SELFTEST
 	select SW_SYNC # signaling validation framework (igt/syncobj*)
 	select DRM_I915_SW_FENCE_DEBUG_OBJECTS
@@ -173,6 +173,7 @@ config DRM_I915_DEBUG_RUNTIME_PM
 	bool "Enable extra state checking for runtime PM"
 	depends on DRM_I915
 	default n
+	select STACKDEPOT
 	help
 	  Choose this option to turn on extra state checking for the
 	  runtime PM functionality. This may introduce overhead during
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d460ef522d9c..56ec65ec5199 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2702,6 +2702,12 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
 		   pci_power_name(pdev->current_state),
 		   pdev->current_state);
 
+	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)) {
+		struct drm_printer p = drm_seq_file_printer(m);
+
+		print_intel_runtime_pm_wakeref(dev_priv, &p);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 75652dc1e24c..5731f992cf44 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -905,6 +905,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv)
 	mutex_init(&dev_priv->pps_mutex);
 
 	i915_memcpy_init_early(dev_priv);
+	intel_runtime_pm_init_early(dev_priv);
 
 	ret = i915_workqueues_init(dev_priv);
 	if (ret < 0)
@@ -1807,8 +1808,7 @@ void i915_driver_unload(struct drm_device *dev)
 	i915_driver_cleanup_mmio(dev_priv);
 
 	enable_rpm_wakeref_asserts(dev_priv);
-
-	WARN_ON(atomic_read(&dev_priv->runtime_pm.wakeref_count));
+	intel_runtime_pm_cleanup(dev_priv);
 }
 
 static void i915_driver_release(struct drm_device *dev)
@@ -2010,6 +2010,8 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)
 
 out:
 	enable_rpm_wakeref_asserts(dev_priv);
+	if (!dev_priv->uncore.user_forcewake.count)
+		intel_runtime_pm_cleanup(dev_priv);
 
 	return ret;
 }
@@ -2965,7 +2967,7 @@ static int intel_runtime_suspend(struct device *kdev)
 	}
 
 	enable_rpm_wakeref_asserts(dev_priv);
-	WARN_ON_ONCE(atomic_read(&dev_priv->runtime_pm.wakeref_count));
+	intel_runtime_pm_cleanup(dev_priv);
 
 	if (intel_uncore_arm_unclaimed_mmio_detection(dev_priv))
 		DRM_ERROR("Unclaimed access detected prior to suspending\n");
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6f341822653c..525a26174fcf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -45,6 +45,7 @@
 #include <linux/pm_qos.h>
 #include <linux/reservation.h>
 #include <linux/shmem_fs.h>
+#include <linux/stackdepot.h>
 
 #include <drm/intel-gtt.h>
 #include <drm/drm_legacy.h> /* for struct drm_dma_handle */
@@ -1156,6 +1157,25 @@ struct i915_runtime_pm {
 	atomic_t wakeref_count;
 	bool suspended;
 	bool irqs_enabled;
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+	/*
+	 * To aide detection of wakeref leaks and general misuse, we
+	 * track all wakeref holders. With manual markup (i.e. returning
+	 * a cookie to each rpm_get caller which they then supply to their
+	 * paired rpm_put) we can remove corresponding pairs of and keep
+	 * the array trimmed to active wakerefs.
+	 */
+	struct intel_runtime_pm_debug {
+		spinlock_t lock;
+
+		depot_stack_handle_t last_acquire;
+		depot_stack_handle_t last_release;
+
+		depot_stack_handle_t *owners;
+		unsigned long count;
+	} debug;
+#endif
 };
 
 enum intel_pipe_crc_source {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1a11c2beb7f3..ac513fd70315 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -41,6 +41,8 @@
 #include <drm/drm_atomic.h>
 #include <media/cec-notifier.h>
 
+struct drm_printer;
+
 /**
  * __wait_for - magic wait macro
  *
@@ -2084,6 +2086,7 @@ bool intel_psr_enabled(struct intel_dp *intel_dp);
 void intel_init_quirks(struct drm_i915_private *dev_priv);
 
 /* intel_runtime_pm.c */
+void intel_runtime_pm_init_early(struct drm_i915_private *dev_priv);
 int intel_power_domains_init(struct drm_i915_private *);
 void intel_power_domains_cleanup(struct drm_i915_private *dev_priv);
 void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume);
@@ -2106,6 +2109,7 @@ void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume);
 void bxt_display_core_uninit(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_enable(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_disable(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_cleanup(struct drm_i915_private *dev_priv);
 const char *
 intel_display_power_domain_str(enum intel_display_power_domain domain);
 
@@ -2123,23 +2127,23 @@ void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
 			    u8 req_slices);
 
 static inline void
-assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv)
+assert_rpm_device_not_suspended(struct drm_i915_private *i915)
 {
-	WARN_ONCE(dev_priv->runtime_pm.suspended,
+	WARN_ONCE(i915->runtime_pm.suspended,
 		  "Device suspended during HW access\n");
 }
 
 static inline void
-assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
+assert_rpm_wakelock_held(struct drm_i915_private *i915)
 {
-	assert_rpm_device_not_suspended(dev_priv);
-	WARN_ONCE(!atomic_read(&dev_priv->runtime_pm.wakeref_count),
+	assert_rpm_device_not_suspended(i915);
+	WARN_ONCE(!atomic_read(&i915->runtime_pm.wakeref_count),
 		  "RPM wakelock ref not held during HW access");
 }
 
 /**
  * disable_rpm_wakeref_asserts - disable the RPM assert checks
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function disable asserts that check if we hold an RPM wakelock
  * reference, while keeping the device-not-suspended checks still enabled.
@@ -2156,14 +2160,14 @@ assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
  * enable_rpm_wakeref_asserts().
  */
 static inline void
-disable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
+disable_rpm_wakeref_asserts(struct drm_i915_private *i915)
 {
-	atomic_inc(&dev_priv->runtime_pm.wakeref_count);
+	atomic_inc(&i915->runtime_pm.wakeref_count);
 }
 
 /**
  * enable_rpm_wakeref_asserts - re-enable the RPM assert checks
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function re-enables the RPM assert checks after disabling them with
  * disable_rpm_wakeref_asserts. It's meant to be used only in special
@@ -2173,15 +2177,25 @@ disable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
  * disable_rpm_wakeref_asserts().
  */
 static inline void
-enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
+enable_rpm_wakeref_asserts(struct drm_i915_private *i915)
 {
-	atomic_dec(&dev_priv->runtime_pm.wakeref_count);
+	atomic_dec(&i915->runtime_pm.wakeref_count);
 }
 
-void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
-bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv);
-void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
-void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
+void intel_runtime_pm_get(struct drm_i915_private *i915);
+bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915);
+void intel_runtime_pm_get_noresume(struct drm_i915_private *i915);
+void intel_runtime_pm_put(struct drm_i915_private *i915);
+
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
+				    struct drm_printer *p);
+#else
+static inline void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
+						  struct drm_printer *p)
+{
+}
+#endif
 
 void chv_phy_powergate_lanes(struct intel_encoder *encoder,
 			     bool override, unsigned int mask);
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 9e9501f82f06..a2f8d1fcf136 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -29,6 +29,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/vgaarb.h>
 
+#include <drm/drm_print.h>
+
 #include "i915_drv.h"
 #include "intel_drv.h"
 
@@ -49,6 +51,237 @@
  * present for a given platform.
  */
 
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+
+#include <linux/sort.h>
+
+#define STACKDEPTH 8
+
+static void __print_depot_stack(depot_stack_handle_t stack,
+				char *buf, int sz, int indent)
+{
+	unsigned long entries[STACKDEPTH];
+	struct stack_trace trace = {
+		.entries = entries,
+		.max_entries = ARRAY_SIZE(entries),
+	};
+
+	depot_fetch_stack(stack, &trace);
+	snprint_stack_trace(buf, sz, &trace, indent);
+}
+
+static void init_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+	struct i915_runtime_pm *rpm = &i915->runtime_pm;
+
+	spin_lock_init(&rpm->debug.lock);
+}
+
+static noinline void
+track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+	struct i915_runtime_pm *rpm = &i915->runtime_pm;
+	unsigned long entries[STACKDEPTH];
+	struct stack_trace trace = {
+		.entries = entries,
+		.max_entries = ARRAY_SIZE(entries),
+		.skip = 0 /* gcc is ignoring noinline for tail calls? */
+	};
+	unsigned long flags;
+	depot_stack_handle_t stack, *stacks;
+
+	if (!HAS_RUNTIME_PM(i915))
+		return;
+
+	save_stack_trace(&trace);
+	if (trace.nr_entries &&
+	    trace.entries[trace.nr_entries - 1] == ULONG_MAX)
+		trace.nr_entries--;
+
+	stack = depot_save_stack(&trace, GFP_NOWAIT | __GFP_NOWARN);
+	if (!stack)
+		return;
+
+	spin_lock_irqsave(&rpm->debug.lock, flags);
+
+	if (!rpm->debug.count)
+		rpm->debug.last_acquire = stack;
+
+	stacks = krealloc(rpm->debug.owners,
+			  (rpm->debug.count + 1) * sizeof(*stacks),
+			  GFP_NOWAIT | __GFP_NOWARN);
+	if (stacks) {
+		stacks[rpm->debug.count++] = stack;
+		rpm->debug.owners = stacks;
+	}
+
+	spin_unlock_irqrestore(&rpm->debug.lock, flags);
+}
+
+static noinline void
+untrack_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+	struct i915_runtime_pm *rpm = &i915->runtime_pm;
+	depot_stack_handle_t *stacks;
+	unsigned long entries[STACKDEPTH];
+	struct stack_trace trace = {
+		.entries = entries,
+		.max_entries = ARRAY_SIZE(entries),
+		.skip = 1,
+	};
+	unsigned long flags;
+	depot_stack_handle_t stack;
+
+	if (!HAS_RUNTIME_PM(i915))
+		return;
+
+	save_stack_trace(&trace);
+	if (trace.nr_entries &&
+	    trace.entries[trace.nr_entries - 1] == ULONG_MAX)
+		trace.nr_entries--;
+
+	stack = depot_save_stack(&trace, GFP_NOWAIT | __GFP_NOWARN);
+
+	spin_lock_irqsave(&rpm->debug.lock, flags);
+	stacks = fetch_and_zero(&rpm->debug.owners);
+	rpm->debug.count = 0;
+	rpm->debug.last_release = stack;
+	spin_unlock_irqrestore(&rpm->debug.lock, flags);
+
+	kfree(stacks);
+}
+
+static int cmphandle(const void *_a, const void *_b)
+{
+	const depot_stack_handle_t * const a = _a, * const b = _b;
+
+	if (*a < *b)
+		return -1;
+	else if (*a > *b)
+		return 1;
+	else
+		return 0;
+}
+
+static void
+__print_intel_runtime_pm_wakeref(struct drm_printer *p,
+				 const struct intel_runtime_pm_debug *dbg)
+{
+	unsigned long i;
+	char *buf;
+
+	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	if (dbg->last_acquire) {
+		__print_depot_stack(dbg->last_acquire, buf, PAGE_SIZE, 2);
+		drm_printf(p, "Wakeref last acquired:\n%s", buf);
+	}
+
+	if (dbg->last_release) {
+		__print_depot_stack(dbg->last_release, buf, PAGE_SIZE, 2);
+		drm_printf(p, "Wakeref last released:\n%s", buf);
+	}
+
+	drm_printf(p, "Wakeref count: %lu\n", dbg->count);
+
+	sort(dbg->owners, dbg->count, sizeof(*dbg->owners), cmphandle, NULL);
+
+	for (i = 0; i < dbg->count; i++) {
+		depot_stack_handle_t stack = dbg->owners[i];
+		unsigned long rep;
+
+		rep = 1;
+		while (i + 1 < dbg->count && dbg->owners[i + 1] == stack)
+			rep++, i++;
+		__print_depot_stack(stack, buf, PAGE_SIZE, 2);
+		drm_printf(p, "Wakeref x%lu taken at:\n%s", rep, buf);
+	}
+
+	kfree(buf);
+}
+
+static void show_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+	struct i915_runtime_pm *rpm = &i915->runtime_pm;
+	struct intel_runtime_pm_debug dbg;
+	struct drm_printer p;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rpm->debug.lock, flags);
+
+	dbg = rpm->debug;
+
+	rpm->debug.owners = NULL;
+	rpm->debug.count = 0;
+
+	spin_unlock_irqrestore(&rpm->debug.lock, flags);
+	if (!dbg.count)
+		return;
+
+	p = drm_debug_printer("i915");
+	__print_intel_runtime_pm_wakeref(&p, &dbg);
+
+	kfree(dbg.owners);
+}
+
+void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
+				    struct drm_printer *p)
+{
+	struct intel_runtime_pm_debug dbg = {};
+
+	do {
+		struct i915_runtime_pm *rpm = &i915->runtime_pm;
+		unsigned long alloc = dbg.count;
+		depot_stack_handle_t *s;
+
+		spin_lock_irq(&rpm->debug.lock);
+		dbg.count = rpm->debug.count;
+		if (dbg.count <= alloc) {
+			memcpy(dbg.owners,
+			       rpm->debug.owners,
+			       dbg.count * sizeof(*s));
+		}
+		dbg.last_acquire = rpm->debug.last_acquire;
+		dbg.last_release = rpm->debug.last_release;
+		spin_unlock_irq(&rpm->debug.lock);
+		if (dbg.count <= alloc)
+			break;
+
+		s = krealloc(dbg.owners, dbg.count * sizeof(*s), GFP_KERNEL);
+		if (!s)
+			goto out;
+
+		dbg.owners = s;
+	} while (1);
+
+	__print_intel_runtime_pm_wakeref(p, &dbg);
+
+out:
+	kfree(dbg.owners);
+}
+
+#else
+
+static void init_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+}
+
+static void track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+}
+
+static void untrack_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+}
+
+static void show_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+{
+}
+
+#endif
+
 bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
 					 enum i915_power_well_id power_well_id);
 
@@ -3986,7 +4219,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
 
 /**
  * intel_runtime_pm_get - grab a runtime pm reference
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function grabs a device-level runtime pm reference (mostly used for GEM
  * code to ensure the GTT or GT is on) and ensures that it is powered up.
@@ -3994,22 +4227,24 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
  * Any runtime pm reference obtained by this function must have a symmetric
  * call to intel_runtime_pm_put() to release the reference again.
  */
-void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
+void intel_runtime_pm_get(struct drm_i915_private *i915)
 {
-	struct pci_dev *pdev = dev_priv->drm.pdev;
+	struct pci_dev *pdev = i915->drm.pdev;
 	struct device *kdev = &pdev->dev;
 	int ret;
 
 	ret = pm_runtime_get_sync(kdev);
 	WARN_ONCE(ret < 0, "pm_runtime_get_sync() failed: %d\n", ret);
 
-	atomic_inc(&dev_priv->runtime_pm.wakeref_count);
-	assert_rpm_wakelock_held(dev_priv);
+	atomic_inc(&i915->runtime_pm.wakeref_count);
+	assert_rpm_wakelock_held(i915);
+
+	track_intel_runtime_pm_wakeref(i915);
 }
 
 /**
  * intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function grabs a device-level runtime pm reference if the device is
  * already in use and ensures that it is powered up. It is illegal to try
@@ -4020,10 +4255,10 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
  *
  * Returns: True if the wakeref was acquired, or False otherwise.
  */
-bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
+bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
 {
 	if (IS_ENABLED(CONFIG_PM)) {
-		struct pci_dev *pdev = dev_priv->drm.pdev;
+		struct pci_dev *pdev = i915->drm.pdev;
 		struct device *kdev = &pdev->dev;
 
 		/*
@@ -4036,15 +4271,17 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
 			return false;
 	}
 
-	atomic_inc(&dev_priv->runtime_pm.wakeref_count);
-	assert_rpm_wakelock_held(dev_priv);
+	atomic_inc(&i915->runtime_pm.wakeref_count);
+	assert_rpm_wakelock_held(i915);
+
+	track_intel_runtime_pm_wakeref(i915);
 
 	return true;
 }
 
 /**
  * intel_runtime_pm_get_noresume - grab a runtime pm reference
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function grabs a device-level runtime pm reference (mostly used for GEM
  * code to ensure the GTT or GT is on).
@@ -4059,32 +4296,35 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
  * Any runtime pm reference obtained by this function must have a symmetric
  * call to intel_runtime_pm_put() to release the reference again.
  */
-void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv)
+void intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
 {
-	struct pci_dev *pdev = dev_priv->drm.pdev;
+	struct pci_dev *pdev = i915->drm.pdev;
 	struct device *kdev = &pdev->dev;
 
-	assert_rpm_wakelock_held(dev_priv);
+	assert_rpm_wakelock_held(i915);
 	pm_runtime_get_noresume(kdev);
 
-	atomic_inc(&dev_priv->runtime_pm.wakeref_count);
+	atomic_inc(&i915->runtime_pm.wakeref_count);
+
+	track_intel_runtime_pm_wakeref(i915);
 }
 
 /**
  * intel_runtime_pm_put - release a runtime pm reference
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function drops the device-level runtime pm reference obtained by
  * intel_runtime_pm_get() and might power down the corresponding
  * hardware block right away if this is the last reference.
  */
-void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
+void intel_runtime_pm_put(struct drm_i915_private *i915)
 {
-	struct pci_dev *pdev = dev_priv->drm.pdev;
+	struct pci_dev *pdev = i915->drm.pdev;
 	struct device *kdev = &pdev->dev;
 
-	assert_rpm_wakelock_held(dev_priv);
-	atomic_dec(&dev_priv->runtime_pm.wakeref_count);
+	assert_rpm_wakelock_held(i915);
+	if (atomic_dec_and_test(&i915->runtime_pm.wakeref_count))
+		untrack_intel_runtime_pm_wakeref(i915);
 
 	pm_runtime_mark_last_busy(kdev);
 	pm_runtime_put_autosuspend(kdev);
@@ -4092,7 +4332,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
 
 /**
  * intel_runtime_pm_enable - enable runtime pm
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function enables runtime pm at the end of the driver load sequence.
  *
@@ -4100,9 +4340,9 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
  * subordinate display power domains. That is done by
  * intel_power_domains_enable().
  */
-void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
+void intel_runtime_pm_enable(struct drm_i915_private *i915)
 {
-	struct pci_dev *pdev = dev_priv->drm.pdev;
+	struct pci_dev *pdev = i915->drm.pdev;
 	struct device *kdev = &pdev->dev;
 
 	/*
@@ -4124,7 +4364,7 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
 	 * so the driver's own RPM reference tracking asserts also work on
 	 * platforms without RPM support.
 	 */
-	if (!HAS_RUNTIME_PM(dev_priv)) {
+	if (!HAS_RUNTIME_PM(i915)) {
 		int ret;
 
 		pm_runtime_dont_use_autosuspend(kdev);
@@ -4142,17 +4382,36 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
 	pm_runtime_put_autosuspend(kdev);
 }
 
-void intel_runtime_pm_disable(struct drm_i915_private *dev_priv)
+void intel_runtime_pm_disable(struct drm_i915_private *i915)
 {
-	struct pci_dev *pdev = dev_priv->drm.pdev;
+	struct pci_dev *pdev = i915->drm.pdev;
 	struct device *kdev = &pdev->dev;
 
 	/* Transfer rpm ownership back to core */
-	WARN(pm_runtime_get_sync(&dev_priv->drm.pdev->dev) < 0,
+	WARN(pm_runtime_get_sync(kdev) < 0,
 	     "Failed to pass rpm ownership back to core\n");
 
 	pm_runtime_dont_use_autosuspend(kdev);
 
-	if (!HAS_RUNTIME_PM(dev_priv))
+	if (!HAS_RUNTIME_PM(i915))
 		pm_runtime_put(kdev);
 }
+
+void intel_runtime_pm_cleanup(struct drm_i915_private *i915)
+{
+	struct i915_runtime_pm *rpm = &i915->runtime_pm;
+
+	if (WARN(atomic_read(&rpm->wakeref_count),
+		 "i915->runtime_pm.wakeref_count=%d on cleanup\n",
+		 atomic_read(&rpm->wakeref_count))) {
+		show_intel_runtime_pm_wakeref(i915);
+		atomic_set(&rpm->wakeref_count, 0);
+	}
+
+	untrack_intel_runtime_pm_wakeref(i915);
+}
+
+void intel_runtime_pm_init_early(struct drm_i915_private *i915)
+{
+	init_intel_runtime_pm_wakeref(i915);
+}
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index baa3c38919de..082809569681 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -154,15 +154,17 @@ struct drm_i915_private *mock_gem_device(void)
 	pdev->dev.archdata.iommu = (void *)-1;
 #endif
 
+	i915 = (struct drm_i915_private *)(pdev + 1);
+	pci_set_drvdata(pdev, i915);
+
+	intel_runtime_pm_init_early(i915);
+
 	dev_pm_domain_set(&pdev->dev, &pm_domain);
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	if (pm_runtime_enabled(&pdev->dev))
 		WARN_ON(pm_runtime_get_sync(&pdev->dev));
 
-	i915 = (struct drm_i915_private *)(pdev + 1);
-	pci_set_drvdata(pdev, i915);
-
 	err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev);
 	if (err) {
 		pr_err("Failed to initialise mock GEM device: err=%d\n", err);
-- 
2.20.1

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

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

* [PATCH 02/21] drm/i915: Markup paired operations on wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
  2019-01-10 10:11 ` [PATCH 01/21] drm/i915: Track all held rpm wakerefs Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:20   ` Mika Kuoppala
  2019-01-10 10:11 ` [PATCH 03/21] drm/i915: Track GT wakeref Chris Wilson
                   ` (21 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

The majority of runtime-pm operations are bounded and scoped within a
function; these are easy to verify that the wakeref are handled
correctly. We can employ the compiler to help us, and reduce the number
of wakerefs tracked when debugging, by passing around cookies provided
by the various rpm_get functions to their rpm_put counterpart. This
makes the pairing explicit, and given the required wakeref cookie the
compiler can verify that we pass an initialised value to the rpm_put
(quite handy for double checking error paths).

For regular builds, the compiler should be able to eliminate the unused
local variables and the program growth should be minimal. Fwiw, it came
out as a net improvement as gcc was able to refactor rpm_get and
rpm_get_if_in_use together,

v2: Just s/rpm_put/rpm_put_unchecked/ everywhere, leaving the manual
mark up for smaller more targeted patches.
v3: Mention the cookie in Returns

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/gvt/aperture_gm.c        |  8 +-
 drivers/gpu/drm/i915/gvt/gvt.h                |  2 +-
 drivers/gpu/drm/i915/gvt/sched_policy.c       |  2 +-
 drivers/gpu/drm/i915/gvt/scheduler.c          |  4 +-
 drivers/gpu/drm/i915/i915_debugfs.c           | 54 +++++------
 drivers/gpu/drm/i915/i915_drv.h               |  2 +
 drivers/gpu/drm/i915/i915_gem.c               | 20 ++---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c    |  2 +-
 drivers/gpu/drm/i915/i915_gem_fence_reg.c     |  2 +-
 drivers/gpu/drm/i915/i915_gem_gtt.c           |  8 +-
 drivers/gpu/drm/i915/i915_gem_shrinker.c      | 10 +--
 drivers/gpu/drm/i915/i915_irq.c               |  2 +-
 drivers/gpu/drm/i915/i915_perf.c              |  4 +-
 drivers/gpu/drm/i915/i915_pmu.c               |  6 +-
 drivers/gpu/drm/i915/i915_sysfs.c             | 12 +--
 drivers/gpu/drm/i915/intel_display.c          |  2 +-
 drivers/gpu/drm/i915/intel_drv.h              | 15 +++-
 drivers/gpu/drm/i915/intel_engine_cs.c        |  4 +-
 drivers/gpu/drm/i915/intel_fbdev.c            |  4 +-
 drivers/gpu/drm/i915/intel_guc_log.c          |  6 +-
 drivers/gpu/drm/i915/intel_hotplug.c          |  2 +-
 drivers/gpu/drm/i915/intel_huc.c              |  2 +-
 drivers/gpu/drm/i915/intel_panel.c            |  2 +-
 drivers/gpu/drm/i915/intel_runtime_pm.c       | 90 +++++++++++++++----
 drivers/gpu/drm/i915/intel_uncore.c           |  2 +-
 drivers/gpu/drm/i915/selftests/huge_pages.c   |  2 +-
 drivers/gpu/drm/i915/selftests/i915_gem.c     | 10 +--
 .../drm/i915/selftests/i915_gem_coherency.c   |  2 +-
 .../gpu/drm/i915/selftests/i915_gem_context.c | 10 +--
 .../gpu/drm/i915/selftests/i915_gem_evict.c   |  2 +-
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c |  4 +-
 .../gpu/drm/i915/selftests/i915_gem_object.c  |  6 +-
 drivers/gpu/drm/i915/selftests/i915_request.c |  8 +-
 drivers/gpu/drm/i915/selftests/intel_guc.c    |  4 +-
 .../gpu/drm/i915/selftests/intel_hangcheck.c  |  6 +-
 drivers/gpu/drm/i915/selftests/intel_lrc.c    | 10 +--
 .../drm/i915/selftests/intel_workarounds.c    | 10 +--
 37 files changed, 202 insertions(+), 139 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c
index 359d37d5c958..1fa2f65c3cd1 100644
--- a/drivers/gpu/drm/i915/gvt/aperture_gm.c
+++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
@@ -180,7 +180,7 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu)
 	}
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
@@ -206,7 +206,7 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
 	_clear_vgpu_fence(vgpu);
 
 	mutex_unlock(&dev_priv->drm.struct_mutex);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	return 0;
 out_free_fence:
 	gvt_vgpu_err("Failed to alloc fences\n");
@@ -219,7 +219,7 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
 		vgpu->fence.regs[i] = NULL;
 	}
 	mutex_unlock(&dev_priv->drm.struct_mutex);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	return -ENOSPC;
 }
 
@@ -317,7 +317,7 @@ void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
 
 	intel_runtime_pm_get(dev_priv);
 	_clear_vgpu_fence(vgpu);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index b4ab1dad0143..435c746c3f73 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -597,7 +597,7 @@ static inline void mmio_hw_access_pre(struct drm_i915_private *dev_priv)
 
 static inline void mmio_hw_access_post(struct drm_i915_private *dev_priv)
 {
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c
index c32e7d5e8629..f04b3b965bfc 100644
--- a/drivers/gpu/drm/i915/gvt/sched_policy.c
+++ b/drivers/gpu/drm/i915/gvt/sched_policy.c
@@ -474,6 +474,6 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
 		}
 	}
 	spin_unlock_bh(&scheduler->mmio_context_lock);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	mutex_unlock(&vgpu->gvt->sched_lock);
 }
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
index 1ad8c5e1455d..3816dcae2185 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -997,7 +997,7 @@ static int workload_thread(void *priv)
 			intel_uncore_forcewake_put(gvt->dev_priv,
 					FORCEWAKE_ALL);
 
-		intel_runtime_pm_put(gvt->dev_priv);
+		intel_runtime_pm_put_unchecked(gvt->dev_priv);
 		if (ret && (vgpu_is_vm_unhealthy(ret)))
 			enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR);
 	}
@@ -1451,7 +1451,7 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
 		mutex_lock(&dev_priv->drm.struct_mutex);
 		ret = intel_gvt_scan_and_shadow_workload(workload);
 		mutex_unlock(&dev_priv->drm.struct_mutex);
-		intel_runtime_pm_put(dev_priv);
+		intel_runtime_pm_put_unchecked(dev_priv);
 	}
 
 	if (ret && (vgpu_is_vm_unhealthy(ret))) {
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 56ec65ec5199..43c130eb2217 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -877,7 +877,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 		}
 	}
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -953,7 +953,7 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file)
 
 	intel_runtime_pm_get(i915);
 	gpu = i915_capture_gpu_state(i915);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	if (IS_ERR(gpu))
 		return PTR_ERR(gpu);
 
@@ -1226,7 +1226,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
 	seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq);
 	seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	return ret;
 }
 
@@ -1292,7 +1292,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
 
 	intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	if (timer_pending(&dev_priv->gpu_error.hangcheck_work.timer))
 		seq_printf(m, "Hangcheck active, timer fires in %dms\n",
@@ -1579,7 +1579,7 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
 	else
 		err = ironlake_drpc_info(m);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return err;
 }
@@ -1632,7 +1632,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 	}
 
 	mutex_unlock(&fbc->lock);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -1695,7 +1695,7 @@ static int i915_ips_status(struct seq_file *m, void *unused)
 			seq_puts(m, "Currently: disabled\n");
 	}
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -1723,7 +1723,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
 		sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 
 	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
 
@@ -1756,7 +1756,7 @@ static int i915_emon_status(struct seq_file *m, void *unused)
 	seq_printf(m, "GFX power: %ld\n", gfx);
 	seq_printf(m, "Total power: %ld\n", chipset + gfx);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -1805,7 +1805,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 	mutex_unlock(&dev_priv->pcu_lock);
 
 out:
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	return ret;
 }
 
@@ -2017,7 +2017,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
 	if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
 		seq_puts(m, "L-shaped memory detected\n");
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -2067,7 +2067,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
 			act_freq = intel_get_cagf(dev_priv,
 						  I915_READ(GEN6_RPSTAT1));
 		}
-		intel_runtime_pm_put(dev_priv);
+		intel_runtime_pm_put_unchecked(dev_priv);
 	}
 
 	seq_printf(m, "RPS enabled? %d\n", rps->enabled);
@@ -2160,7 +2160,7 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data)
 
 	intel_runtime_pm_get(dev_priv);
 	seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -2192,7 +2192,7 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
 	for (i = 0; i < 16; i++)
 		seq_printf(m, "\t%2d: \t0x%x\n", i, I915_READ(SOFT_SCRATCH(i)));
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -2601,7 +2601,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 			   dev_priv->psr.last_exit);
 	}
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	return 0;
 }
 
@@ -2632,7 +2632,7 @@ i915_edp_psr_debug_set(void *data, u64 val)
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return ret;
 }
@@ -2665,7 +2665,7 @@ static int i915_energy_uJ(struct seq_file *m, void *data)
 	intel_runtime_pm_get(dev_priv);
 
 	if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &power)) {
-		intel_runtime_pm_put(dev_priv);
+		intel_runtime_pm_put_unchecked(dev_priv);
 		return -ENODEV;
 	}
 
@@ -2673,7 +2673,7 @@ static int i915_energy_uJ(struct seq_file *m, void *data)
 	power = I915_READ(MCH_SECP_NRG_STTS);
 	power = (1000000 * power) >> units; /* convert to uJ */
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	seq_printf(m, "%llu", power);
 
@@ -2775,7 +2775,7 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
 	seq_printf(m, "ssp base: 0x%08x\n", I915_READ(CSR_SSP_BASE));
 	seq_printf(m, "htp: 0x%08x\n", I915_READ(CSR_HTP_SKL));
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -3107,7 +3107,7 @@ static int i915_display_info(struct seq_file *m, void *unused)
 	drm_connector_list_iter_end(&conn_iter);
 	mutex_unlock(&dev->mode_config.mutex);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -3132,7 +3132,7 @@ static int i915_engine_info(struct seq_file *m, void *unused)
 	for_each_engine(engine, dev_priv, id)
 		intel_engine_dump(engine, &p, "%s\n", engine->name);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return 0;
 }
@@ -3258,7 +3258,7 @@ static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf,
 	dev_priv->wm.distrust_bios_wm = true;
 	dev_priv->ipc_enabled = enable;
 	intel_enable_ipc(dev_priv);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return len;
 }
@@ -4083,7 +4083,7 @@ i915_drop_caches_set(void *data, u64 val)
 		i915_gem_drain_freed_objects(i915);
 
 out:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	return ret;
 }
@@ -4105,7 +4105,7 @@ i915_cache_sharing_get(void *data, u64 *val)
 
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
 
@@ -4133,7 +4133,7 @@ i915_cache_sharing_set(void *data, u64 val)
 	snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
 	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	return 0;
 }
 
@@ -4381,7 +4381,7 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
 		gen10_sseu_device_status(dev_priv, &sseu);
 	}
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	i915_print_sseu_info(m, false, &sseu);
 
@@ -4409,7 +4409,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
 		return 0;
 
 	intel_uncore_forcewake_user_put(i915);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 525a26174fcf..9c00598f3bc7 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -131,6 +131,8 @@ bool i915_error_injected(void);
 	__i915_printk(i915, i915_error_injected() ? KERN_DEBUG : KERN_ERR, \
 		      fmt, ##__VA_ARGS__)
 
+typedef depot_stack_handle_t intel_wakeref_t;
+
 enum hpd_pin {
 	HPD_NONE = 0,
 	HPD_TV = HPD_NONE,     /* TV is known to be unreliable */
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ea85da393662..4380189a9cea 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -175,7 +175,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
 
 	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ);
 
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	return i915->gt.epoch;
 }
@@ -814,7 +814,7 @@ void i915_gem_flush_ggtt_writes(struct drm_i915_private *dev_priv)
 	POSTING_READ_FW(RING_HEAD(RENDER_RING_BASE));
 
 	spin_unlock_irq(&dev_priv->uncore.lock);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 static void
@@ -1149,7 +1149,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 		i915_vma_unpin(vma);
 	}
 out_unlock:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 
 	return ret;
@@ -1356,7 +1356,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 		i915_vma_unpin(vma);
 	}
 out_rpm:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 out_unlock:
 	mutex_unlock(&i915->drm.struct_mutex);
 	return ret;
@@ -1968,7 +1968,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 err_unlock:
 	mutex_unlock(&dev->struct_mutex);
 err_rpm:
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	i915_gem_object_unpin_pages(obj);
 err:
 	switch (ret) {
@@ -2068,7 +2068,7 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 	wmb();
 
 out:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 }
 
 void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
@@ -4765,7 +4765,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 		if (on)
 			cond_resched();
 	}
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 }
 
 static void i915_gem_flush_free_objects(struct drm_i915_private *i915)
@@ -4901,7 +4901,7 @@ void i915_gem_sanitize(struct drm_i915_private *i915)
 	intel_engines_sanitize(i915, false);
 
 	intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	i915_gem_contexts_lost(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
@@ -4965,12 +4965,12 @@ int i915_gem_suspend(struct drm_i915_private *i915)
 	if (WARN_ON(!intel_engines_are_idle(i915)))
 		i915_gem_set_wedged(i915); /* no hope, discard everything */
 
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	return 0;
 
 err_unlock:
 	mutex_unlock(&i915->drm.struct_mutex);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index e7994505d850..c80943698ca2 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -2424,7 +2424,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
 		eb_release_vmas(&eb);
 	mutex_unlock(&dev->struct_mutex);
 err_rpm:
-	intel_runtime_pm_put(eb.i915);
+	intel_runtime_pm_put_unchecked(eb.i915);
 	i915_gem_context_put(eb.ctx);
 err_destroy:
 	eb_destroy(&eb);
diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
index d67c07cdd0b8..b3391070acf7 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
@@ -258,7 +258,7 @@ static int fence_update(struct drm_i915_fence_reg *fence,
 	 */
 	if (intel_runtime_pm_get_if_in_use(fence->i915)) {
 		fence_write(fence, vma);
-		intel_runtime_pm_put(fence->i915);
+		intel_runtime_pm_put_unchecked(fence->i915);
 	}
 
 	if (vma) {
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index a8807fbed0aa..51f80ddd938d 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2536,7 +2536,7 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 
 	intel_runtime_pm_get(i915);
 	vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
 
@@ -2556,7 +2556,7 @@ static void ggtt_unbind_vma(struct i915_vma *vma)
 
 	intel_runtime_pm_get(i915);
 	vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 }
 
 static int aliasing_gtt_bind_vma(struct i915_vma *vma,
@@ -2590,7 +2590,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
 	if (flags & I915_VMA_GLOBAL_BIND) {
 		intel_runtime_pm_get(i915);
 		vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
-		intel_runtime_pm_put(i915);
+		intel_runtime_pm_put_unchecked(i915);
 	}
 
 	return 0;
@@ -2603,7 +2603,7 @@ static void aliasing_gtt_unbind_vma(struct i915_vma *vma)
 	if (vma->flags & I915_VMA_GLOBAL_BIND) {
 		intel_runtime_pm_get(i915);
 		vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
-		intel_runtime_pm_put(i915);
+		intel_runtime_pm_put_unchecked(i915);
 	}
 
 	if (vma->flags & I915_VMA_LOCAL_BIND) {
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 34b108f73f1d..1f0e79635087 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -265,7 +265,7 @@ i915_gem_shrink(struct drm_i915_private *i915,
 	}
 
 	if (flags & I915_SHRINK_BOUND)
-		intel_runtime_pm_put(i915);
+		intel_runtime_pm_put_unchecked(i915);
 
 	i915_retire_requests(i915);
 
@@ -299,7 +299,7 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
 				I915_SHRINK_BOUND |
 				I915_SHRINK_UNBOUND |
 				I915_SHRINK_ACTIVE);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	return freed;
 }
@@ -377,7 +377,7 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
 					 I915_SHRINK_ACTIVE |
 					 I915_SHRINK_BOUND |
 					 I915_SHRINK_UNBOUND);
-		intel_runtime_pm_put(i915);
+		intel_runtime_pm_put_unchecked(i915);
 	}
 
 	shrinker_unlock(i915, unlock);
@@ -422,7 +422,7 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
 	freed_pages = i915_gem_shrink(i915, -1UL, NULL,
 				      I915_SHRINK_BOUND |
 				      I915_SHRINK_UNBOUND);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	/* Because we may be allocating inside our own driver, we cannot
 	 * assert that there are no objects with pinned pages that are not
@@ -478,7 +478,7 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
 				       I915_SHRINK_BOUND |
 				       I915_SHRINK_UNBOUND |
 				       I915_SHRINK_VMAPS);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	/* We also want to clear any cached iomaps as they wrap vmap */
 	list_for_each_entry_safe(vma, next,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 288b0662f7b7..787a9ed1ef7d 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -3374,7 +3374,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
 	wake_up_all(&dev_priv->gpu_error.reset_queue);
 
 out:
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 /* Called from drm generic code, passed 'crtc' which
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 5b1ae5ed97b3..e4dfd1477c78 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -1365,7 +1365,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
 	free_oa_buffer(dev_priv);
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	if (stream->ctx)
 		oa_put_render_ctx_id(stream);
@@ -2123,7 +2123,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
 	put_oa_config(dev_priv, stream->oa_config);
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 err_config:
 	if (stream->ctx)
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index d6c8f8fdfda5..c99fcfce79d5 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -210,7 +210,7 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
 	if (fw)
 		intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 static void
@@ -231,7 +231,7 @@ frequency_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
 		    intel_runtime_pm_get_if_in_use(dev_priv)) {
 			val = intel_get_cagf(dev_priv,
 					     I915_READ_NOTRACE(GEN6_RPSTAT1));
-			intel_runtime_pm_put(dev_priv);
+			intel_runtime_pm_put_unchecked(dev_priv);
 		}
 
 		add_sample_mult(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_ACT],
@@ -448,7 +448,7 @@ static u64 get_rc6(struct drm_i915_private *i915)
 
 	if (intel_runtime_pm_get_if_in_use(i915)) {
 		val = __get_rc6(i915);
-		intel_runtime_pm_put(i915);
+		intel_runtime_pm_put_unchecked(i915);
 
 		/*
 		 * If we are coming back from being runtime suspended we must
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index c0cfe7ae2ba5..53c20e103d56 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -46,7 +46,7 @@ static u32 calc_residency(struct drm_i915_private *dev_priv,
 
 	intel_runtime_pm_get(dev_priv);
 	res = intel_rc6_residency_us(dev_priv, reg);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return DIV_ROUND_CLOSEST_ULL(res, 1000);
 }
@@ -274,7 +274,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev,
 	}
 	mutex_unlock(&dev_priv->pcu_lock);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
@@ -371,7 +371,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	    val > rps->max_freq ||
 	    val < rps->min_freq_softlimit) {
 		mutex_unlock(&dev_priv->pcu_lock);
-		intel_runtime_pm_put(dev_priv);
+		intel_runtime_pm_put_unchecked(dev_priv);
 		return -EINVAL;
 	}
 
@@ -392,7 +392,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
 	mutex_unlock(&dev_priv->pcu_lock);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return ret ?: count;
 }
@@ -429,7 +429,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	    val > rps->max_freq ||
 	    val > rps->max_freq_softlimit) {
 		mutex_unlock(&dev_priv->pcu_lock);
-		intel_runtime_pm_put(dev_priv);
+		intel_runtime_pm_put_unchecked(dev_priv);
 		return -EINVAL;
 	}
 
@@ -446,7 +446,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
 	mutex_unlock(&dev_priv->pcu_lock);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return ret ?: count;
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1cc441f06c73..a980d5d1e601 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2101,7 +2101,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 err:
 	atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	return vma;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ac513fd70315..a1e4e1033289 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -29,6 +29,7 @@
 #include <linux/i2c.h>
 #include <linux/hdmi.h>
 #include <linux/sched/clock.h>
+#include <linux/stackdepot.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 #include <drm/drm_crtc.h>
@@ -2182,10 +2183,16 @@ enable_rpm_wakeref_asserts(struct drm_i915_private *i915)
 	atomic_dec(&i915->runtime_pm.wakeref_count);
 }
 
-void intel_runtime_pm_get(struct drm_i915_private *i915);
-bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915);
-void intel_runtime_pm_get_noresume(struct drm_i915_private *i915);
-void intel_runtime_pm_put(struct drm_i915_private *i915);
+intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915);
+intel_wakeref_t intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915);
+intel_wakeref_t intel_runtime_pm_get_noresume(struct drm_i915_private *i915);
+
+void intel_runtime_pm_put_unchecked(struct drm_i915_private *i915);
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+void intel_runtime_pm_put(struct drm_i915_private *i915, intel_wakeref_t wref);
+#else
+#define intel_runtime_pm_put(i915, wref) intel_runtime_pm_put_unchecked(i915)
+#endif
 
 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 236cd040f271..85131166589c 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -928,7 +928,7 @@ static bool ring_is_idle(struct intel_engine_cs *engine)
 	if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
 		idle = false;
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return idle;
 }
@@ -1485,7 +1485,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
 
 	if (intel_runtime_pm_get_if_in_use(engine->i915)) {
 		intel_engine_print_registers(engine, m);
-		intel_runtime_pm_put(engine->i915);
+		intel_runtime_pm_put_unchecked(engine->i915);
 	} else {
 		drm_printf(m, "\tDevice is asleep; skipping register dump\n");
 	}
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index a0c5046e170c..215e5894842d 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -276,7 +276,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	ifbdev->vma = vma;
 	ifbdev->vma_flags = flags;
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 	vga_switcheroo_client_fb_set(pdev, info);
 	return 0;
@@ -284,7 +284,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 out_unpin:
 	intel_unpin_fb_vma(vma, flags);
 out_unlock:
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c
index d3ebdbc0182e..1b1581a42aa1 100644
--- a/drivers/gpu/drm/i915/intel_guc_log.c
+++ b/drivers/gpu/drm/i915/intel_guc_log.c
@@ -445,7 +445,7 @@ static void guc_log_capture_logs(struct intel_guc_log *log)
 	 */
 	intel_runtime_pm_get(dev_priv);
 	guc_action_flush_log_complete(guc);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 int intel_guc_log_create(struct intel_guc_log *log)
@@ -528,7 +528,7 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
 	ret = guc_action_control_log(guc, GUC_LOG_LEVEL_IS_VERBOSE(level),
 				     GUC_LOG_LEVEL_IS_ENABLED(level),
 				     GUC_LOG_LEVEL_TO_VERBOSITY(level));
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	if (ret) {
 		DRM_DEBUG_DRIVER("guc_log_control action failed %d\n", ret);
 		goto out_unlock;
@@ -610,7 +610,7 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log)
 
 	intel_runtime_pm_get(i915);
 	guc_action_flush_log(guc);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	/* GuC would have updated log buffer by now, so capture it */
 	guc_log_capture_logs(log);
diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
index ae92d6560165..b1a9cb960ca4 100644
--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -261,7 +261,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
 		dev_priv->display.hpd_irq_setup(dev_priv);
 	spin_unlock_irq(&dev_priv->irq_lock);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 bool intel_encoder_hotplug(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c
index bc27b691d824..c2b076e9bada 100644
--- a/drivers/gpu/drm/i915/intel_huc.c
+++ b/drivers/gpu/drm/i915/intel_huc.c
@@ -122,7 +122,7 @@ int intel_huc_check_status(struct intel_huc *huc)
 
 	intel_runtime_pm_get(dev_priv);
 	status = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED;
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return status;
 }
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index ee3e0842d542..c2b7455a023e 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1213,7 +1213,7 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
 	ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
 
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index a2f8d1fcf136..f585ef742efe 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -77,7 +77,7 @@ static void init_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
 	spin_lock_init(&rpm->debug.lock);
 }
 
-static noinline void
+static noinline depot_stack_handle_t
 track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
 {
 	struct i915_runtime_pm *rpm = &i915->runtime_pm;
@@ -91,7 +91,7 @@ track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
 	depot_stack_handle_t stack, *stacks;
 
 	if (!HAS_RUNTIME_PM(i915))
-		return;
+		return -1;
 
 	save_stack_trace(&trace);
 	if (trace.nr_entries &&
@@ -100,7 +100,7 @@ track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
 
 	stack = depot_save_stack(&trace, GFP_NOWAIT | __GFP_NOWARN);
 	if (!stack)
-		return;
+		return -1;
 
 	spin_lock_irqsave(&rpm->debug.lock, flags);
 
@@ -113,9 +113,50 @@ track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
 	if (stacks) {
 		stacks[rpm->debug.count++] = stack;
 		rpm->debug.owners = stacks;
+	} else {
+		stack = -1;
 	}
 
 	spin_unlock_irqrestore(&rpm->debug.lock, flags);
+
+	return stack;
+}
+
+static void cancel_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
+					    depot_stack_handle_t stack)
+{
+	struct i915_runtime_pm *rpm = &i915->runtime_pm;
+	unsigned long flags, n;
+	bool found = false;
+
+	if (unlikely(stack == -1))
+		return;
+
+	spin_lock_irqsave(&rpm->debug.lock, flags);
+	for (n = rpm->debug.count; n--; ) {
+		if (rpm->debug.owners[n] == stack) {
+			memmove(rpm->debug.owners + n,
+				rpm->debug.owners + n + 1,
+				(--rpm->debug.count - n) * sizeof(stack));
+			found = true;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&rpm->debug.lock, flags);
+
+	if (WARN(!found,
+		 "Unmatched wakeref (tracking %lu), count %u\n",
+		 rpm->debug.count, atomic_read(&rpm->wakeref_count))) {
+		char *buf;
+
+		buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		if (!buf)
+			return;
+
+		__print_depot_stack(stack, buf, PAGE_SIZE, 0);
+		DRM_DEBUG_DRIVER("wakeref %x from\n%s", stack, buf);
+		kfree(buf);
+	}
 }
 
 static noinline void
@@ -268,8 +309,10 @@ static void init_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
 {
 }
 
-static void track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
+static depot_stack_handle_t
+track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
 {
+	return -1;
 }
 
 static void untrack_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
@@ -1871,7 +1914,7 @@ bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
 	mutex_unlock(&power_domains->lock);
 
 	if (!is_enabled)
-		intel_runtime_pm_put(dev_priv);
+		intel_runtime_pm_put_unchecked(dev_priv);
 
 	return is_enabled;
 }
@@ -1905,7 +1948,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
 
 	mutex_unlock(&power_domains->lock);
 
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
 #define I830_PIPES_POWER_DOMAINS (		\
@@ -4013,7 +4056,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
 void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
 {
 	/* Keep the power well enabled, but cancel its rpm wakeref. */
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	/* Remove the refcount we took to keep power well support disabled. */
 	if (!i915_modparams.disable_power_well)
@@ -4226,8 +4269,10 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
  *
  * Any runtime pm reference obtained by this function must have a symmetric
  * call to intel_runtime_pm_put() to release the reference again.
+ *
+ * Returns: the wakeref cookie to pass to intel_runtime_pm_put()
  */
-void intel_runtime_pm_get(struct drm_i915_private *i915)
+intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915)
 {
 	struct pci_dev *pdev = i915->drm.pdev;
 	struct device *kdev = &pdev->dev;
@@ -4239,7 +4284,7 @@ void intel_runtime_pm_get(struct drm_i915_private *i915)
 	atomic_inc(&i915->runtime_pm.wakeref_count);
 	assert_rpm_wakelock_held(i915);
 
-	track_intel_runtime_pm_wakeref(i915);
+	return track_intel_runtime_pm_wakeref(i915);
 }
 
 /**
@@ -4253,9 +4298,10 @@ void intel_runtime_pm_get(struct drm_i915_private *i915)
  * Any runtime pm reference obtained by this function must have a symmetric
  * call to intel_runtime_pm_put() to release the reference again.
  *
- * Returns: True if the wakeref was acquired, or False otherwise.
+ * Returns: the wakeref cookie to pass to intel_runtime_pm_put(), evaluates
+ * as True if the wakeref was acquired, or False otherwise.
  */
-bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
+intel_wakeref_t intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
 {
 	if (IS_ENABLED(CONFIG_PM)) {
 		struct pci_dev *pdev = i915->drm.pdev;
@@ -4268,15 +4314,13 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
 		 * atm to the late/early system suspend/resume handlers.
 		 */
 		if (pm_runtime_get_if_in_use(kdev) <= 0)
-			return false;
+			return 0;
 	}
 
 	atomic_inc(&i915->runtime_pm.wakeref_count);
 	assert_rpm_wakelock_held(i915);
 
-	track_intel_runtime_pm_wakeref(i915);
-
-	return true;
+	return track_intel_runtime_pm_wakeref(i915);
 }
 
 /**
@@ -4295,8 +4339,10 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
  *
  * Any runtime pm reference obtained by this function must have a symmetric
  * call to intel_runtime_pm_put() to release the reference again.
+ *
+ * Returns: the wakeref cookie to pass to intel_runtime_pm_put()
  */
-void intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
+intel_wakeref_t intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
 {
 	struct pci_dev *pdev = i915->drm.pdev;
 	struct device *kdev = &pdev->dev;
@@ -4306,7 +4352,7 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
 
 	atomic_inc(&i915->runtime_pm.wakeref_count);
 
-	track_intel_runtime_pm_wakeref(i915);
+	return track_intel_runtime_pm_wakeref(i915);
 }
 
 /**
@@ -4317,7 +4363,7 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
  * intel_runtime_pm_get() and might power down the corresponding
  * hardware block right away if this is the last reference.
  */
-void intel_runtime_pm_put(struct drm_i915_private *i915)
+void intel_runtime_pm_put_unchecked(struct drm_i915_private *i915)
 {
 	struct pci_dev *pdev = i915->drm.pdev;
 	struct device *kdev = &pdev->dev;
@@ -4330,6 +4376,14 @@ void intel_runtime_pm_put(struct drm_i915_private *i915)
 	pm_runtime_put_autosuspend(kdev);
 }
 
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+void intel_runtime_pm_put(struct drm_i915_private *i915, intel_wakeref_t wref)
+{
+	cancel_intel_runtime_pm_wakeref(i915, wref);
+	intel_runtime_pm_put_unchecked(i915);
+}
+#endif
+
 /**
  * intel_runtime_pm_enable - enable runtime pm
  * @i915: i915 device instance
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index fff468f17d2d..8d4c76ac0e7d 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1709,7 +1709,7 @@ int i915_reg_read_ioctl(struct drm_device *dev,
 		reg->val = I915_READ8(entry->offset_ldw);
 	else
 		ret = -EINVAL;
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c
index 6c10734e948d..a4d8b12be12c 100644
--- a/drivers/gpu/drm/i915/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/selftests/huge_pages.c
@@ -1785,7 +1785,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv)
 	err = i915_subtests(tests, ctx);
 
 out_unlock:
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 
 	mock_file_free(dev_priv, file);
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c
index bdcc53e15e75..762e1a7125f5 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem.c
@@ -32,7 +32,7 @@ static int switch_to_context(struct drm_i915_private *i915,
 		i915_request_add(rq);
 	}
 
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	return err;
 }
@@ -76,7 +76,7 @@ static void simulate_hibernate(struct drm_i915_private *i915)
 	 */
 	trash_stolen(i915);
 
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 }
 
 static int pm_prepare(struct drm_i915_private *i915)
@@ -98,7 +98,7 @@ static void pm_suspend(struct drm_i915_private *i915)
 	i915_gem_suspend_gtt_mappings(i915);
 	i915_gem_suspend_late(i915);
 
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 }
 
 static void pm_hibernate(struct drm_i915_private *i915)
@@ -110,7 +110,7 @@ static void pm_hibernate(struct drm_i915_private *i915)
 	i915_gem_freeze(i915);
 	i915_gem_freeze_late(i915);
 
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 }
 
 static void pm_resume(struct drm_i915_private *i915)
@@ -125,7 +125,7 @@ static void pm_resume(struct drm_i915_private *i915)
 	i915_gem_sanitize(i915);
 	i915_gem_resume(i915);
 
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 }
 
 static int igt_gem_suspend(void *arg)
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
index f7392c1ffe75..eea4fc2445ae 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
@@ -376,7 +376,7 @@ static int igt_gem_coherency(void *arg)
 		}
 	}
 unlock:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	kfree(offsets);
 	return err;
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
index d00cdf3c2939..6e1a0711d201 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
@@ -243,7 +243,7 @@ static int live_nop_switch(void *arg)
 	}
 
 out_unlock:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	mock_file_free(i915, file);
 	return err;
@@ -609,7 +609,7 @@ static int igt_ctx_exec(void *arg)
 
 			intel_runtime_pm_get(i915);
 			err = gpu_fill(obj, ctx, engine, dw);
-			intel_runtime_pm_put(i915);
+			intel_runtime_pm_put_unchecked(i915);
 			if (err) {
 				pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
 				       ndwords, dw, max_dwords(obj),
@@ -715,7 +715,7 @@ static int igt_ctx_readonly(void *arg)
 
 			intel_runtime_pm_get(i915);
 			err = gpu_fill(obj, ctx, engine, dw);
-			intel_runtime_pm_put(i915);
+			intel_runtime_pm_put_unchecked(i915);
 			if (err) {
 				pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
 				       ndwords, dw, max_dwords(obj),
@@ -1067,7 +1067,7 @@ static int igt_vm_isolation(void *arg)
 		count, RUNTIME_INFO(i915)->num_rings);
 
 out_rpm:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 out_unlock:
 	if (end_live_test(&t))
 		err = -EIO;
@@ -1200,7 +1200,7 @@ static int igt_switch_to_kernel_context(void *arg)
 	if (igt_flush_test(i915, I915_WAIT_LOCKED))
 		err = -EIO;
 
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 
 	kernel_context_close(ctx);
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
index 4365979d8222..8d22f73a9b63 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
@@ -464,7 +464,7 @@ static int igt_evict_contexts(void *arg)
 	}
 	if (drm_mm_node_allocated(&hole))
 		drm_mm_remove_node(&hole);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 
 	return err;
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
index a9ed0ecc94e2..87cb0602a5fc 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
@@ -295,7 +295,7 @@ static int lowlevel_hole(struct drm_i915_private *i915,
 
 			intel_runtime_pm_get(i915);
 			vm->insert_entries(vm, &mock_vma, I915_CACHE_NONE, 0);
-			intel_runtime_pm_put(i915);
+			intel_runtime_pm_put_unchecked(i915);
 		}
 		count = n;
 
@@ -1216,7 +1216,7 @@ static int igt_ggtt_page(void *arg)
 	kfree(order);
 out_remove:
 	ggtt->vm.clear_range(&ggtt->vm, tmp.start, tmp.size);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	drm_mm_remove_node(&tmp);
 out_unpin:
 	i915_gem_object_unpin_pages(obj);
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
index be7ecb66ad11..b03890c590d7 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
@@ -444,7 +444,7 @@ next_tiling: ;
 	}
 
 out_unlock:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	i915_gem_object_unpin_pages(obj);
 out:
@@ -508,7 +508,7 @@ static void disable_retire_worker(struct drm_i915_private *i915)
 	if (!i915->gt.active_requests++) {
 		intel_runtime_pm_get(i915);
 		i915_gem_unpark(i915);
-		intel_runtime_pm_put(i915);
+		intel_runtime_pm_put_unchecked(i915);
 	}
 	mutex_unlock(&i915->drm.struct_mutex);
 	cancel_delayed_work_sync(&i915->gt.retire_work);
@@ -590,7 +590,7 @@ static int igt_mmap_offset_exhaustion(void *arg)
 		mutex_lock(&i915->drm.struct_mutex);
 		intel_runtime_pm_get(i915);
 		err = make_obj_busy(obj);
-		intel_runtime_pm_put(i915);
+		intel_runtime_pm_put_unchecked(i915);
 		mutex_unlock(&i915->drm.struct_mutex);
 		if (err) {
 			pr_err("[loop %d] Failed to busy the object\n", loop);
diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
index 07e557815308..e8880cabd5c7 100644
--- a/drivers/gpu/drm/i915/selftests/i915_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_request.c
@@ -403,7 +403,7 @@ static int live_nop_request(void *arg)
 	}
 
 out_unlock:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -553,7 +553,7 @@ static int live_empty_request(void *arg)
 	i915_vma_unpin(batch);
 	i915_vma_put(batch);
 out_unlock:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -731,7 +731,7 @@ static int live_all_engines(void *arg)
 	i915_vma_unpin(batch);
 	i915_vma_put(batch);
 out_unlock:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -860,7 +860,7 @@ static int live_sequential_engines(void *arg)
 		i915_request_put(request[id]);
 	}
 out_unlock:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
diff --git a/drivers/gpu/drm/i915/selftests/intel_guc.c b/drivers/gpu/drm/i915/selftests/intel_guc.c
index 32cba4cae31a..3590ba3d8897 100644
--- a/drivers/gpu/drm/i915/selftests/intel_guc.c
+++ b/drivers/gpu/drm/i915/selftests/intel_guc.c
@@ -225,7 +225,7 @@ static int igt_guc_clients(void *args)
 	guc_clients_create(guc);
 	guc_clients_enable(guc);
 unlock:
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 	return err;
 }
@@ -337,7 +337,7 @@ static int igt_guc_doorbells(void *arg)
 			guc_client_free(clients[i]);
 		}
 unlock:
-	intel_runtime_pm_put(dev_priv);
+	intel_runtime_pm_put_unchecked(dev_priv);
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 	return err;
 }
diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
index 0aadbd9c7d56..33bd3c4b6fa3 100644
--- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
+++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
@@ -402,7 +402,7 @@ static int igt_wedged_reset(void *arg)
 	i915_reset(i915, ALL_ENGINES, NULL);
 	GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags));
 
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	igt_global_reset_unlock(i915);
 
@@ -1636,7 +1636,7 @@ static int igt_atomic_reset(void *arg)
 	force_reset(i915);
 
 unlock:
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	igt_global_reset_unlock(i915);
 
@@ -1679,7 +1679,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
 	mutex_unlock(&i915->drm.struct_mutex);
 
 	i915_modparams.enable_hangcheck = saved_hangcheck;
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	return err;
 }
diff --git a/drivers/gpu/drm/i915/selftests/intel_lrc.c b/drivers/gpu/drm/i915/selftests/intel_lrc.c
index 00caaa00f02f..ac1b18a17f3c 100644
--- a/drivers/gpu/drm/i915/selftests/intel_lrc.c
+++ b/drivers/gpu/drm/i915/selftests/intel_lrc.c
@@ -65,7 +65,7 @@ static int live_sanitycheck(void *arg)
 	igt_spinner_fini(&spin);
 err_unlock:
 	igt_flush_test(i915, I915_WAIT_LOCKED);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -158,7 +158,7 @@ static int live_preempt(void *arg)
 	igt_spinner_fini(&spin_hi);
 err_unlock:
 	igt_flush_test(i915, I915_WAIT_LOCKED);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -251,7 +251,7 @@ static int live_late_preempt(void *arg)
 	igt_spinner_fini(&spin_hi);
 err_unlock:
 	igt_flush_test(i915, I915_WAIT_LOCKED);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 
@@ -374,7 +374,7 @@ static int live_preempt_hang(void *arg)
 	igt_spinner_fini(&spin_hi);
 err_unlock:
 	igt_flush_test(i915, I915_WAIT_LOCKED);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -627,7 +627,7 @@ static int live_preempt_smoke(void *arg)
 err_batch:
 	i915_gem_object_put(smoke.batch);
 err_unlock:
-	intel_runtime_pm_put(smoke.i915);
+	intel_runtime_pm_put_unchecked(smoke.i915);
 	mutex_unlock(&smoke.i915->drm.struct_mutex);
 	kfree(smoke.contexts);
 
diff --git a/drivers/gpu/drm/i915/selftests/intel_workarounds.c b/drivers/gpu/drm/i915/selftests/intel_workarounds.c
index 8b3f3200a3bd..b1b39c70c702 100644
--- a/drivers/gpu/drm/i915/selftests/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/selftests/intel_workarounds.c
@@ -94,7 +94,7 @@ read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
 
 	intel_runtime_pm_get(engine->i915);
 	rq = i915_request_alloc(engine, ctx);
-	intel_runtime_pm_put(engine->i915);
+	intel_runtime_pm_put_unchecked(engine->i915);
 	if (IS_ERR(rq)) {
 		err = PTR_ERR(rq);
 		goto err_pin;
@@ -241,7 +241,7 @@ switch_to_scratch_context(struct intel_engine_cs *engine,
 	else
 		rq = i915_request_alloc(engine, ctx);
 
-	intel_runtime_pm_put(engine->i915);
+	intel_runtime_pm_put_unchecked(engine->i915);
 
 	kernel_context_close(ctx);
 
@@ -300,7 +300,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
 
 	intel_runtime_pm_get(i915);
 	err = reset(engine);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 
 	if (want_spin) {
 		igt_spinner_end(&spin);
@@ -414,7 +414,7 @@ live_gpu_reset_gt_engine_workarounds(void *arg)
 
 out:
 	reference_lists_fini(i915, &lists);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	igt_global_reset_unlock(i915);
 
 	return ok ? 0 : -ESRCH;
@@ -496,7 +496,7 @@ live_engine_reset_gt_engine_workarounds(void *arg)
 
 err:
 	reference_lists_fini(i915, &lists);
-	intel_runtime_pm_put(i915);
+	intel_runtime_pm_put_unchecked(i915);
 	igt_global_reset_unlock(i915);
 	kernel_context_close(ctx);
 
-- 
2.20.1

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

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

* [PATCH 03/21] drm/i915: Track GT wakeref
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
  2019-01-10 10:11 ` [PATCH 01/21] drm/i915: Track all held rpm wakerefs Chris Wilson
  2019-01-10 10:11 ` [PATCH 02/21] drm/i915: Markup paired operations on wakerefs Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 04/21] drm/i915: Track the rpm wakerefs for error handling Chris Wilson
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Record the wakeref used for keeping the device awake as the GPU is
executing requests and be sure to cancel the tracking upon parking.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h |  2 +-
 drivers/gpu/drm/i915/i915_gem.c | 11 +++++++----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9c00598f3bc7..f7f193c087f6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1979,7 +1979,7 @@ struct drm_i915_private {
 		 * In order to reduce the effect on performance, there
 		 * is a slight delay before we do so.
 		 */
-		bool awake;
+		intel_wakeref_t awake;
 
 		/**
 		 * The number of times we have woken up.
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 4380189a9cea..0cb419310508 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -138,6 +138,8 @@ int i915_mutex_lock_interruptible(struct drm_device *dev)
 
 static u32 __i915_gem_park(struct drm_i915_private *i915)
 {
+	intel_wakeref_t wakeref;
+
 	GEM_TRACE("\n");
 
 	lockdep_assert_held(&i915->drm.struct_mutex);
@@ -168,14 +170,15 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
 	i915_pmu_gt_parked(i915);
 	i915_vma_parked(i915);
 
-	i915->gt.awake = false;
+	wakeref = fetch_and_zero(&i915->gt.awake);
+	GEM_BUG_ON(!wakeref);
 
 	if (INTEL_GEN(i915) >= 6)
 		gen6_rps_idle(i915);
 
 	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ);
 
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	return i915->gt.epoch;
 }
@@ -204,7 +207,8 @@ void i915_gem_unpark(struct drm_i915_private *i915)
 	if (i915->gt.awake)
 		return;
 
-	intel_runtime_pm_get_noresume(i915);
+	i915->gt.awake = intel_runtime_pm_get_noresume(i915);
+	GEM_BUG_ON(!i915->gt.awake);
 
 	/*
 	 * It seems that the DMC likes to transition between the DC states a lot
@@ -219,7 +223,6 @@ void i915_gem_unpark(struct drm_i915_private *i915)
 	 */
 	intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
 
-	i915->gt.awake = true;
 	if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */
 		i915->gt.epoch = 1;
 
-- 
2.20.1

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

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

* [PATCH 04/21] drm/i915: Track the rpm wakerefs for error handling
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (2 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 03/21] drm/i915: Track GT wakeref Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 05/21] drm/i915: Mark up sysfs with rpm wakeref tracking Chris Wilson
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Keep hold of the local wakeref used in error handling, to cancel
the tracking upon release so that leaks can be identified.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 787a9ed1ef7d..94187e68d39a 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -3291,6 +3291,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
 		       const char *fmt, ...)
 {
 	struct intel_engine_cs *engine;
+	intel_wakeref_t wakeref;
 	unsigned int tmp;
 	char error_msg[80];
 	char *msg = NULL;
@@ -3312,7 +3313,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
 	 * isn't the case at least when we get here by doing a
 	 * simulated reset via debugfs, so get an RPM reference.
 	 */
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	engine_mask &= INTEL_INFO(dev_priv)->ring_mask;
 
@@ -3374,7 +3375,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
 	wake_up_all(&dev_priv->gpu_error.reset_queue);
 
 out:
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 }
 
 /* Called from drm generic code, passed 'crtc' which
-- 
2.20.1

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

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

* [PATCH 05/21] drm/i915: Mark up sysfs with rpm wakeref tracking
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (3 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 04/21] drm/i915: Track the rpm wakerefs for error handling Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 06/21] drm/i915: Mark up debugfs " Chris Wilson
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

As sysfs has a simple pattern of taking a rpm wakeref around the user
access, we can track the local reference and drop it as soon as
possible.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_sysfs.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 53c20e103d56..2cbbf165d179 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -42,11 +42,12 @@ static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev)
 static u32 calc_residency(struct drm_i915_private *dev_priv,
 			  i915_reg_t reg)
 {
+	intel_wakeref_t wakeref;
 	u64 res;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	res = intel_rc6_residency_us(dev_priv, reg);
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return DIV_ROUND_CLOSEST_ULL(res, 1000);
 }
@@ -258,9 +259,10 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev,
 				    struct device_attribute *attr, char *buf)
 {
 	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
+	intel_wakeref_t wakeref;
 	int ret;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	mutex_lock(&dev_priv->pcu_lock);
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
@@ -274,7 +276,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev,
 	}
 	mutex_unlock(&dev_priv->pcu_lock);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
@@ -354,6 +356,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 {
 	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
 	struct intel_rps *rps = &dev_priv->gt_pm.rps;
+	intel_wakeref_t wakeref;
 	u32 val;
 	ssize_t ret;
 
@@ -361,7 +364,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	if (ret)
 		return ret;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	mutex_lock(&dev_priv->pcu_lock);
 
@@ -371,7 +374,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 	    val > rps->max_freq ||
 	    val < rps->min_freq_softlimit) {
 		mutex_unlock(&dev_priv->pcu_lock);
-		intel_runtime_pm_put_unchecked(dev_priv);
+		intel_runtime_pm_put(dev_priv, wakeref);
 		return -EINVAL;
 	}
 
@@ -392,7 +395,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
 
 	mutex_unlock(&dev_priv->pcu_lock);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return ret ?: count;
 }
@@ -412,6 +415,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 {
 	struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev);
 	struct intel_rps *rps = &dev_priv->gt_pm.rps;
+	intel_wakeref_t wakeref;
 	u32 val;
 	ssize_t ret;
 
@@ -419,7 +423,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	if (ret)
 		return ret;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	mutex_lock(&dev_priv->pcu_lock);
 
@@ -429,7 +433,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 	    val > rps->max_freq ||
 	    val > rps->max_freq_softlimit) {
 		mutex_unlock(&dev_priv->pcu_lock);
-		intel_runtime_pm_put_unchecked(dev_priv);
+		intel_runtime_pm_put(dev_priv, wakeref);
 		return -EINVAL;
 	}
 
@@ -446,7 +450,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
 
 	mutex_unlock(&dev_priv->pcu_lock);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return ret ?: count;
 }
-- 
2.20.1

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

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

* [PATCH 06/21] drm/i915: Mark up debugfs with rpm wakeref tracking
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (4 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 05/21] drm/i915: Mark up sysfs with rpm wakeref tracking Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 07/21] drm/i915/perf: Track the rpm wakeref Chris Wilson
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

As debugfs has a simple pattern of taking a rpm wakeref around the user
access, we can track the local reference and drop it as soon as
possible.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c | 135 +++++++++++++++++-----------
 1 file changed, 82 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 43c130eb2217..bed8a379fe00 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -674,9 +674,10 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct intel_engine_cs *engine;
 	enum intel_engine_id id;
+	intel_wakeref_t wakeref;
 	int i, pipe;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	if (IS_CHERRYVIEW(dev_priv)) {
 		seq_printf(m, "Master Interrupt Control:\t%08x\n",
@@ -877,7 +878,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 		}
 	}
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return 0;
 }
@@ -950,10 +951,11 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file)
 {
 	struct drm_i915_private *i915 = inode->i_private;
 	struct i915_gpu_state *gpu;
+	intel_wakeref_t wakeref;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	gpu = i915_capture_gpu_state(i915);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	if (IS_ERR(gpu))
 		return PTR_ERR(gpu);
 
@@ -1012,9 +1014,10 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct intel_rps *rps = &dev_priv->gt_pm.rps;
+	intel_wakeref_t wakeref;
 	int ret = 0;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	if (IS_GEN(dev_priv, 5)) {
 		u16 rgvswctl = I915_READ16(MEMSWCTL);
@@ -1226,7 +1229,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
 	seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq);
 	seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	return ret;
 }
 
@@ -1265,6 +1268,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
 	u64 acthd[I915_NUM_ENGINES];
 	u32 seqno[I915_NUM_ENGINES];
 	struct intel_instdone instdone;
+	intel_wakeref_t wakeref;
 	enum intel_engine_id id;
 
 	if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags))
@@ -1283,7 +1287,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
 		return 0;
 	}
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	for_each_engine(engine, dev_priv, id) {
 		acthd[id] = intel_engine_get_active_head(engine);
@@ -1292,7 +1296,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
 
 	intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	if (timer_pending(&dev_priv->gpu_error.hangcheck_work.timer))
 		seq_printf(m, "Hangcheck active, timer fires in %dms\n",
@@ -1568,9 +1572,10 @@ static int gen6_drpc_info(struct seq_file *m)
 static int i915_drpc_info(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	intel_wakeref_t wakeref;
 	int err;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		err = vlv_drpc_info(m);
@@ -1579,7 +1584,7 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
 	else
 		err = ironlake_drpc_info(m);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return err;
 }
@@ -1601,11 +1606,12 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct intel_fbc *fbc = &dev_priv->fbc;
+	intel_wakeref_t wakeref;
 
 	if (!HAS_FBC(dev_priv))
 		return -ENODEV;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	mutex_lock(&fbc->lock);
 
 	if (intel_fbc_is_active(dev_priv))
@@ -1632,7 +1638,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 	}
 
 	mutex_unlock(&fbc->lock);
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return 0;
 }
@@ -1677,11 +1683,12 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_fbc_false_color_fops,
 static int i915_ips_status(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	intel_wakeref_t wakeref;
 
 	if (!HAS_IPS(dev_priv))
 		return -ENODEV;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "Enabled by kernel parameter: %s\n",
 		   yesno(i915_modparams.enable_ips));
@@ -1695,7 +1702,7 @@ static int i915_ips_status(struct seq_file *m, void *unused)
 			seq_puts(m, "Currently: disabled\n");
 	}
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return 0;
 }
@@ -1703,9 +1710,10 @@ static int i915_ips_status(struct seq_file *m, void *unused)
 static int i915_sr_status(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	intel_wakeref_t wakeref;
 	bool sr_enabled = false;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
 	if (INTEL_GEN(dev_priv) >= 9)
@@ -1723,7 +1731,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
 		sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 
 	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
 
@@ -1735,29 +1743,30 @@ static int i915_emon_status(struct seq_file *m, void *unused)
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct drm_device *dev = &dev_priv->drm;
 	unsigned long temp, chipset, gfx;
+	intel_wakeref_t wakeref;
 	int ret;
 
 	if (!IS_GEN(dev_priv, 5))
 		return -ENODEV;
 
-	intel_runtime_pm_get(dev_priv);
-
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
+	wakeref = intel_runtime_pm_get(dev_priv);
+
 	temp = i915_mch_val(dev_priv);
 	chipset = i915_chipset_val(dev_priv);
 	gfx = i915_gfx_val(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
+	intel_runtime_pm_put(dev_priv, wakeref);
+
 	seq_printf(m, "GMCH temp: %ld\n", temp);
 	seq_printf(m, "Chipset power: %ld\n", chipset);
 	seq_printf(m, "GFX power: %ld\n", gfx);
 	seq_printf(m, "Total power: %ld\n", chipset + gfx);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
-
 	return 0;
 }
 
@@ -1766,13 +1775,14 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct intel_rps *rps = &dev_priv->gt_pm.rps;
 	unsigned int max_gpu_freq, min_gpu_freq;
+	intel_wakeref_t wakeref;
 	int gpu_freq, ia_freq;
 	int ret;
 
 	if (!HAS_LLC(dev_priv))
 		return -ENODEV;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	ret = mutex_lock_interruptible(&dev_priv->pcu_lock);
 	if (ret)
@@ -1805,7 +1815,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 	mutex_unlock(&dev_priv->pcu_lock);
 
 out:
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	return ret;
 }
 
@@ -1978,8 +1988,9 @@ static const char *swizzle_string(unsigned swizzle)
 static int i915_swizzle_info(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	intel_wakeref_t wakeref;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
 		   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
@@ -2017,7 +2028,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
 	if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
 		seq_puts(m, "L-shaped memory detected\n");
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return 0;
 }
@@ -2054,9 +2065,11 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
 	struct drm_device *dev = &dev_priv->drm;
 	struct intel_rps *rps = &dev_priv->gt_pm.rps;
 	u32 act_freq = rps->cur_freq;
+	intel_wakeref_t wakeref;
 	struct drm_file *file;
 
-	if (intel_runtime_pm_get_if_in_use(dev_priv)) {
+	wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
+	if (wakeref) {
 		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 			mutex_lock(&dev_priv->pcu_lock);
 			act_freq = vlv_punit_read(dev_priv,
@@ -2067,7 +2080,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
 			act_freq = intel_get_cagf(dev_priv,
 						  I915_READ(GEN6_RPSTAT1));
 		}
-		intel_runtime_pm_put_unchecked(dev_priv);
+		intel_runtime_pm_put(dev_priv, wakeref);
 	}
 
 	seq_printf(m, "RPS enabled? %d\n", rps->enabled);
@@ -2150,6 +2163,7 @@ static int i915_llc(struct seq_file *m, void *data)
 static int i915_huc_load_status_info(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	intel_wakeref_t wakeref;
 	struct drm_printer p;
 
 	if (!HAS_HUC(dev_priv))
@@ -2158,9 +2172,9 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data)
 	p = drm_seq_file_printer(m);
 	intel_uc_fw_dump(&dev_priv->huc.fw, &p);
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return 0;
 }
@@ -2168,6 +2182,7 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data)
 static int i915_guc_load_status_info(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	intel_wakeref_t wakeref;
 	struct drm_printer p;
 	u32 tmp, i;
 
@@ -2177,7 +2192,7 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
 	p = drm_seq_file_printer(m);
 	intel_uc_fw_dump(&dev_priv->guc.fw, &p);
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	tmp = I915_READ(GUC_STATUS);
 
@@ -2192,7 +2207,7 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
 	for (i = 0; i < 16; i++)
 		seq_printf(m, "\t%2d: \t0x%x\n", i, I915_READ(SOFT_SCRATCH(i)));
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return 0;
 }
@@ -2550,6 +2565,7 @@ psr_source_status(struct drm_i915_private *dev_priv, struct seq_file *m)
 static int i915_edp_psr_status(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	intel_wakeref_t wakeref;
 	u32 psrperf = 0;
 	bool enabled = false;
 	bool sink_support;
@@ -2562,7 +2578,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 	if (!sink_support)
 		return 0;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	mutex_lock(&dev_priv->psr.lock);
 	seq_printf(m, "PSR mode: %s\n",
@@ -2601,7 +2617,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
 			   dev_priv->psr.last_exit);
 	}
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	return 0;
 }
 
@@ -2610,6 +2626,7 @@ i915_edp_psr_debug_set(void *data, u64 val)
 {
 	struct drm_i915_private *dev_priv = data;
 	struct drm_modeset_acquire_ctx ctx;
+	intel_wakeref_t wakeref;
 	int ret;
 
 	if (!CAN_PSR(dev_priv))
@@ -2617,7 +2634,7 @@ i915_edp_psr_debug_set(void *data, u64 val)
 
 	DRM_DEBUG_KMS("Setting PSR debug to %llx\n", val);
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
 
@@ -2632,7 +2649,7 @@ i915_edp_psr_debug_set(void *data, u64 val)
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return ret;
 }
@@ -2657,15 +2674,16 @@ static int i915_energy_uJ(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	unsigned long long power;
+	intel_wakeref_t wakeref;
 	u32 units;
 
 	if (INTEL_GEN(dev_priv) < 6)
 		return -ENODEV;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &power)) {
-		intel_runtime_pm_put_unchecked(dev_priv);
+		intel_runtime_pm_put(dev_priv, wakeref);
 		return -ENODEV;
 	}
 
@@ -2673,7 +2691,7 @@ static int i915_energy_uJ(struct seq_file *m, void *data)
 	power = I915_READ(MCH_SECP_NRG_STTS);
 	power = (1000000 * power) >> units; /* convert to uJ */
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	seq_printf(m, "%llu", power);
 
@@ -2742,6 +2760,7 @@ static int i915_power_domain_info(struct seq_file *m, void *unused)
 static int i915_dmc_info(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	intel_wakeref_t wakeref;
 	struct intel_csr *csr;
 
 	if (!HAS_CSR(dev_priv))
@@ -2749,7 +2768,7 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
 
 	csr = &dev_priv->csr;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "fw loaded: %s\n", yesno(csr->dmc_payload != NULL));
 	seq_printf(m, "path: %s\n", csr->fw_path);
@@ -2775,7 +2794,7 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
 	seq_printf(m, "ssp base: 0x%08x\n", I915_READ(CSR_SSP_BASE));
 	seq_printf(m, "htp: 0x%08x\n", I915_READ(CSR_HTP_SKL));
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return 0;
 }
@@ -3058,8 +3077,10 @@ static int i915_display_info(struct seq_file *m, void *unused)
 	struct intel_crtc *crtc;
 	struct drm_connector *connector;
 	struct drm_connector_list_iter conn_iter;
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_runtime_pm_get(dev_priv);
 
-	intel_runtime_pm_get(dev_priv);
 	seq_printf(m, "CRTC info\n");
 	seq_printf(m, "---------\n");
 	for_each_intel_crtc(dev, crtc) {
@@ -3107,7 +3128,7 @@ static int i915_display_info(struct seq_file *m, void *unused)
 	drm_connector_list_iter_end(&conn_iter);
 	mutex_unlock(&dev->mode_config.mutex);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return 0;
 }
@@ -3116,10 +3137,11 @@ static int i915_engine_info(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct intel_engine_cs *engine;
+	intel_wakeref_t wakeref;
 	enum intel_engine_id id;
 	struct drm_printer p;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "GT awake? %s (epoch %u)\n",
 		   yesno(dev_priv->gt.awake), dev_priv->gt.epoch);
@@ -3132,7 +3154,7 @@ static int i915_engine_info(struct seq_file *m, void *unused)
 	for_each_engine(engine, dev_priv, id)
 		intel_engine_dump(engine, &p, "%s\n", engine->name);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return 0;
 }
@@ -3245,6 +3267,7 @@ static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf,
 {
 	struct seq_file *m = file->private_data;
 	struct drm_i915_private *dev_priv = m->private;
+	intel_wakeref_t wakeref;
 	int ret;
 	bool enable;
 
@@ -3252,13 +3275,15 @@ static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf,
 	if (ret < 0)
 		return ret;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
+
 	if (!dev_priv->ipc_enabled && enable)
 		DRM_INFO("Enabling IPC: WM will be proper only after next commit\n");
 	dev_priv->wm.distrust_bios_wm = true;
 	dev_priv->ipc_enabled = enable;
 	intel_enable_ipc(dev_priv);
-	intel_runtime_pm_put_unchecked(dev_priv);
+
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return len;
 }
@@ -4024,11 +4049,12 @@ static int
 i915_drop_caches_set(void *data, u64 val)
 {
 	struct drm_i915_private *i915 = data;
+	intel_wakeref_t wakeref;
 	int ret = 0;
 
 	DRM_DEBUG("Dropping caches: 0x%08llx [0x%08llx]\n",
 		  val, val & DROP_ALL);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	if (val & DROP_RESET_ACTIVE && !intel_engines_are_idle(i915))
 		i915_gem_set_wedged(i915);
@@ -4083,7 +4109,7 @@ i915_drop_caches_set(void *data, u64 val)
 		i915_gem_drain_freed_objects(i915);
 
 out:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	return ret;
 }
@@ -4096,16 +4122,17 @@ static int
 i915_cache_sharing_get(void *data, u64 *val)
 {
 	struct drm_i915_private *dev_priv = data;
+	intel_wakeref_t wakeref;
 	u32 snpcr;
 
 	if (!(IS_GEN_RANGE(dev_priv, 6, 7)))
 		return -ENODEV;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
 
@@ -4116,6 +4143,7 @@ static int
 i915_cache_sharing_set(void *data, u64 val)
 {
 	struct drm_i915_private *dev_priv = data;
+	intel_wakeref_t wakeref;
 	u32 snpcr;
 
 	if (!(IS_GEN_RANGE(dev_priv, 6, 7)))
@@ -4124,7 +4152,7 @@ i915_cache_sharing_set(void *data, u64 val)
 	if (val > 3)
 		return -EINVAL;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
 
 	/* Update the cache sharing policy here as well */
@@ -4133,7 +4161,7 @@ i915_cache_sharing_set(void *data, u64 val)
 	snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
 	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	return 0;
 }
 
@@ -4355,6 +4383,7 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct sseu_dev_info sseu;
+	intel_wakeref_t wakeref;
 
 	if (INTEL_GEN(dev_priv) < 8)
 		return -ENODEV;
@@ -4369,7 +4398,7 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
 	sseu.max_eus_per_subslice =
 		RUNTIME_INFO(dev_priv)->sseu.max_eus_per_subslice;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	if (IS_CHERRYVIEW(dev_priv)) {
 		cherryview_sseu_device_status(dev_priv, &sseu);
@@ -4381,7 +4410,7 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
 		gen10_sseu_device_status(dev_priv, &sseu);
 	}
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	i915_print_sseu_info(m, false, &sseu);
 
-- 
2.20.1

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

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

* [PATCH 07/21] drm/i915/perf: Track the rpm wakeref
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (5 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 06/21] drm/i915: Mark up debugfs " Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 08/21] drm/i915/pmu: Track " Chris Wilson
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Keep track of our wakeref used to keep the device awake so we can catch
any leak.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h  | 2 ++
 drivers/gpu/drm/i915/i915_perf.c | 6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f7f193c087f6..f0a405604b75 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1333,6 +1333,8 @@ struct i915_perf_stream {
 	 */
 	struct list_head link;
 
+	intel_wakeref_t wakeref;
+
 	/**
 	 * @sample_flags: Flags representing the `DRM_I915_PERF_PROP_SAMPLE_*`
 	 * properties given when opening a stream, representing the contents
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index e4dfd1477c78..faff6cf1aaa1 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -1365,7 +1365,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
 	free_oa_buffer(dev_priv);
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, stream->wakeref);
 
 	if (stream->ctx)
 		oa_put_render_ctx_id(stream);
@@ -2087,7 +2087,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
 	 *   In our case we are expecting that taking pm + FORCEWAKE
 	 *   references will effectively disable RC6.
 	 */
-	intel_runtime_pm_get(dev_priv);
+	stream->wakeref = intel_runtime_pm_get(dev_priv);
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
 	ret = alloc_oa_buffer(dev_priv);
@@ -2123,7 +2123,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
 	put_oa_config(dev_priv, stream->oa_config);
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, stream->wakeref);
 
 err_config:
 	if (stream->ctx)
-- 
2.20.1

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

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

* [PATCH 08/21] drm/i915/pmu: Track rpm wakeref
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (6 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 07/21] drm/i915/perf: Track the rpm wakeref Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 09/21] drm/i915/guc: Track the " Chris Wilson
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Track the wakeref used for temporary access to the device, and discard
it upon release so that leaks can be identified.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_pmu.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index c99fcfce79d5..3d43fc9dd25d 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -167,6 +167,7 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
 {
 	struct intel_engine_cs *engine;
 	enum intel_engine_id id;
+	intel_wakeref_t wakeref;
 	bool fw = false;
 
 	if ((dev_priv->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
@@ -175,7 +176,8 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
 	if (!dev_priv->gt.awake)
 		return;
 
-	if (!intel_runtime_pm_get_if_in_use(dev_priv))
+	wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
+	if (!wakeref)
 		return;
 
 	for_each_engine(engine, dev_priv, id) {
@@ -210,7 +212,7 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
 	if (fw)
 		intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 }
 
 static void
@@ -227,11 +229,15 @@ frequency_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
 		u32 val;
 
 		val = dev_priv->gt_pm.rps.cur_freq;
-		if (dev_priv->gt.awake &&
-		    intel_runtime_pm_get_if_in_use(dev_priv)) {
-			val = intel_get_cagf(dev_priv,
-					     I915_READ_NOTRACE(GEN6_RPSTAT1));
-			intel_runtime_pm_put_unchecked(dev_priv);
+		if (dev_priv->gt.awake) {
+			intel_wakeref_t wakeref =
+				intel_runtime_pm_get_if_in_use(dev_priv);
+
+			if (wakeref) {
+				val = intel_get_cagf(dev_priv,
+						     I915_READ_NOTRACE(GEN6_RPSTAT1));
+				intel_runtime_pm_put(dev_priv, wakeref);
+			}
 		}
 
 		add_sample_mult(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_ACT],
@@ -443,12 +449,14 @@ static u64 __get_rc6(struct drm_i915_private *i915)
 static u64 get_rc6(struct drm_i915_private *i915)
 {
 #if IS_ENABLED(CONFIG_PM)
+	intel_wakeref_t wakeref;
 	unsigned long flags;
 	u64 val;
 
-	if (intel_runtime_pm_get_if_in_use(i915)) {
+	wakeref = intel_runtime_pm_get_if_in_use(i915);
+	if (wakeref) {
 		val = __get_rc6(i915);
-		intel_runtime_pm_put_unchecked(i915);
+		intel_runtime_pm_put(i915, wakeref);
 
 		/*
 		 * If we are coming back from being runtime suspended we must
-- 
2.20.1

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

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

* [PATCH 09/21] drm/i915/guc: Track the rpm wakeref
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (7 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 08/21] drm/i915/pmu: Track " Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 10/21] drm/i915/gem: Track the rpm wakerefs Chris Wilson
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Keep track of our acquired wakeref for interacting with the guc, so that
we can cancel it upon release and so clearly identify leaks.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_guc_log.c | 15 +++++++++------
 drivers/gpu/drm/i915/intel_huc.c     |  5 +++--
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c
index 1b1581a42aa1..20c0b36d748e 100644
--- a/drivers/gpu/drm/i915/intel_guc_log.c
+++ b/drivers/gpu/drm/i915/intel_guc_log.c
@@ -436,6 +436,7 @@ static void guc_log_capture_logs(struct intel_guc_log *log)
 {
 	struct intel_guc *guc = log_to_guc(log);
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	intel_wakeref_t wakeref;
 
 	guc_read_update_log_buffer(log);
 
@@ -443,9 +444,9 @@ static void guc_log_capture_logs(struct intel_guc_log *log)
 	 * Generally device is expected to be active only at this
 	 * time, so get/put should be really quick.
 	 */
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	guc_action_flush_log_complete(guc);
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 }
 
 int intel_guc_log_create(struct intel_guc_log *log)
@@ -505,6 +506,7 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
 {
 	struct intel_guc *guc = log_to_guc(log);
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	intel_wakeref_t wakeref;
 	int ret;
 
 	BUILD_BUG_ON(GUC_LOG_VERBOSITY_MIN != 0);
@@ -524,11 +526,11 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
 		goto out_unlock;
 	}
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	ret = guc_action_control_log(guc, GUC_LOG_LEVEL_IS_VERBOSE(level),
 				     GUC_LOG_LEVEL_IS_ENABLED(level),
 				     GUC_LOG_LEVEL_TO_VERBOSITY(level));
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	if (ret) {
 		DRM_DEBUG_DRIVER("guc_log_control action failed %d\n", ret);
 		goto out_unlock;
@@ -601,6 +603,7 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log)
 {
 	struct intel_guc *guc = log_to_guc(log);
 	struct drm_i915_private *i915 = guc_to_i915(guc);
+	intel_wakeref_t wakeref;
 
 	/*
 	 * Before initiating the forceful flush, wait for any pending/ongoing
@@ -608,9 +611,9 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log)
 	 */
 	flush_work(&log->relay.flush_work);
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	guc_action_flush_log(guc);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	/* GuC would have updated log buffer by now, so capture it */
 	guc_log_capture_logs(log);
diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c
index c2b076e9bada..3e8c18b6a42d 100644
--- a/drivers/gpu/drm/i915/intel_huc.c
+++ b/drivers/gpu/drm/i915/intel_huc.c
@@ -115,14 +115,15 @@ int intel_huc_auth(struct intel_huc *huc)
 int intel_huc_check_status(struct intel_huc *huc)
 {
 	struct drm_i915_private *dev_priv = huc_to_i915(huc);
+	intel_wakeref_t wakeref;
 	bool status;
 
 	if (!HAS_HUC(dev_priv))
 		return -ENODEV;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	status = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED;
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return status;
 }
-- 
2.20.1

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

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

* [PATCH 10/21] drm/i915/gem: Track the rpm wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (8 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 09/21] drm/i915/guc: Track the " Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 11/21] drm/i915/fb: Track " Chris Wilson
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Keep track of the temporary rpm wakerefs used for user access to the
device, so that we can cancel them upon release and clearly identify any
leaks.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c            | 47 +++++++++++++---------
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  5 ++-
 drivers/gpu/drm/i915/i915_gem_fence_reg.c  |  6 ++-
 drivers/gpu/drm/i915/i915_gem_gtt.c        | 22 ++++++----
 drivers/gpu/drm/i915/i915_gem_shrinker.c   | 32 +++++++++------
 drivers/gpu/drm/i915/intel_engine_cs.c     | 12 ++++--
 drivers/gpu/drm/i915/intel_uncore.c        |  5 ++-
 7 files changed, 81 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0cb419310508..98a91df16392 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -785,6 +785,8 @@ fb_write_origin(struct drm_i915_gem_object *obj, unsigned int domain)
 
 void i915_gem_flush_ggtt_writes(struct drm_i915_private *dev_priv)
 {
+	intel_wakeref_t wakeref;
+
 	/*
 	 * No actual flushing is required for the GTT write domain for reads
 	 * from the GTT domain. Writes to it "immediately" go to main memory
@@ -811,13 +813,13 @@ void i915_gem_flush_ggtt_writes(struct drm_i915_private *dev_priv)
 
 	i915_gem_chipset_flush(dev_priv);
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	spin_lock_irq(&dev_priv->uncore.lock);
 
 	POSTING_READ_FW(RING_HEAD(RENDER_RING_BASE));
 
 	spin_unlock_irq(&dev_priv->uncore.lock);
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 }
 
 static void
@@ -1069,6 +1071,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 {
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct i915_ggtt *ggtt = &i915->ggtt;
+	intel_wakeref_t wakeref;
 	struct drm_mm_node node;
 	struct i915_vma *vma;
 	void __user *user_data;
@@ -1079,7 +1082,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 	if (ret)
 		return ret;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
 				       PIN_MAPPABLE |
 				       PIN_NONFAULT |
@@ -1152,7 +1155,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
 		i915_vma_unpin(vma);
 	}
 out_unlock:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 
 	return ret;
@@ -1253,6 +1256,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 {
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct i915_ggtt *ggtt = &i915->ggtt;
+	intel_wakeref_t wakeref;
 	struct drm_mm_node node;
 	struct i915_vma *vma;
 	u64 remain, offset;
@@ -1271,13 +1275,14 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 		 * This easily dwarfs any performance advantage from
 		 * using the cache bypass of indirect GGTT access.
 		 */
-		if (!intel_runtime_pm_get_if_in_use(i915)) {
+		wakeref = intel_runtime_pm_get_if_in_use(i915);
+		if (!wakeref) {
 			ret = -EFAULT;
 			goto out_unlock;
 		}
 	} else {
 		/* No backing pages, no fallback, we must force GGTT access */
-		intel_runtime_pm_get(i915);
+		wakeref = intel_runtime_pm_get(i915);
 	}
 
 	vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
@@ -1359,7 +1364,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 		i915_vma_unpin(vma);
 	}
 out_rpm:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 out_unlock:
 	mutex_unlock(&i915->drm.struct_mutex);
 	return ret;
@@ -1864,6 +1869,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	bool write = area->vm_flags & VM_WRITE;
+	intel_wakeref_t wakeref;
 	struct i915_vma *vma;
 	pgoff_t page_offset;
 	int ret;
@@ -1893,7 +1899,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 	if (ret)
 		goto err;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
@@ -1971,7 +1977,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 err_unlock:
 	mutex_unlock(&dev->struct_mutex);
 err_rpm:
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	i915_gem_object_unpin_pages(obj);
 err:
 	switch (ret) {
@@ -2044,6 +2050,7 @@ void
 i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	intel_wakeref_t wakeref;
 
 	/* Serialisation between user GTT access and our code depends upon
 	 * revoking the CPU's PTE whilst the mutex is held. The next user
@@ -2054,7 +2061,7 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 	 * wakeref.
 	 */
 	lockdep_assert_held(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	if (!obj->userfault_count)
 		goto out;
@@ -2071,7 +2078,7 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 	wmb();
 
 out:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 }
 
 void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
@@ -4706,8 +4713,9 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 				    struct llist_node *freed)
 {
 	struct drm_i915_gem_object *obj, *on;
+	intel_wakeref_t wakeref;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	llist_for_each_entry_safe(obj, on, freed, freed) {
 		struct i915_vma *vma, *vn;
 
@@ -4768,7 +4776,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 		if (on)
 			cond_resched();
 	}
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 }
 
 static void i915_gem_flush_free_objects(struct drm_i915_private *i915)
@@ -4877,11 +4885,13 @@ void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj)
 
 void i915_gem_sanitize(struct drm_i915_private *i915)
 {
+	intel_wakeref_t wakeref;
+
 	GEM_TRACE("\n");
 
 	mutex_lock(&i915->drm.struct_mutex);
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	intel_uncore_forcewake_get(i915, FORCEWAKE_ALL);
 
 	/*
@@ -4904,7 +4914,7 @@ void i915_gem_sanitize(struct drm_i915_private *i915)
 	intel_engines_sanitize(i915, false);
 
 	intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	i915_gem_contexts_lost(i915);
 	mutex_unlock(&i915->drm.struct_mutex);
@@ -4912,11 +4922,12 @@ void i915_gem_sanitize(struct drm_i915_private *i915)
 
 int i915_gem_suspend(struct drm_i915_private *i915)
 {
+	intel_wakeref_t wakeref;
 	int ret;
 
 	GEM_TRACE("\n");
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	intel_suspend_gt_powersave(i915);
 
 	mutex_lock(&i915->drm.struct_mutex);
@@ -4968,12 +4979,12 @@ int i915_gem_suspend(struct drm_i915_private *i915)
 	if (WARN_ON(!intel_engines_are_idle(i915)))
 		i915_gem_set_wedged(i915); /* no hope, discard everything */
 
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	return 0;
 
 err_unlock:
 	mutex_unlock(&i915->drm.struct_mutex);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index c80943698ca2..f250109e1f66 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -2202,6 +2202,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
 	struct i915_execbuffer eb;
 	struct dma_fence *in_fence = NULL;
 	struct sync_file *out_fence = NULL;
+	intel_wakeref_t wakeref;
 	int out_fence_fd = -1;
 	int err;
 
@@ -2272,7 +2273,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
 	 * wakeref that we hold until the GPU has been idle for at least
 	 * 100ms.
 	 */
-	intel_runtime_pm_get(eb.i915);
+	wakeref = intel_runtime_pm_get(eb.i915);
 
 	err = i915_mutex_lock_interruptible(dev);
 	if (err)
@@ -2424,7 +2425,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
 		eb_release_vmas(&eb);
 	mutex_unlock(&dev->struct_mutex);
 err_rpm:
-	intel_runtime_pm_put_unchecked(eb.i915);
+	intel_runtime_pm_put(eb.i915, wakeref);
 	i915_gem_context_put(eb.ctx);
 err_destroy:
 	eb_destroy(&eb);
diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
index b3391070acf7..f7947d89cf45 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
@@ -209,6 +209,7 @@ static void fence_write(struct drm_i915_fence_reg *fence,
 static int fence_update(struct drm_i915_fence_reg *fence,
 			struct i915_vma *vma)
 {
+	intel_wakeref_t wakeref;
 	int ret;
 
 	if (vma) {
@@ -256,9 +257,10 @@ static int fence_update(struct drm_i915_fence_reg *fence,
 	 * If the device is currently powered down, we will defer the write
 	 * to the runtime resume, see i915_gem_restore_fences().
 	 */
-	if (intel_runtime_pm_get_if_in_use(fence->i915)) {
+	wakeref = intel_runtime_pm_get_if_in_use(fence->i915);
+	if (wakeref) {
 		fence_write(fence, vma);
-		intel_runtime_pm_put_unchecked(fence->i915);
+		intel_runtime_pm_put(fence->i915, wakeref);
 	}
 
 	if (vma) {
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 51f80ddd938d..e2c61633e95d 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2527,6 +2527,7 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 {
 	struct drm_i915_private *i915 = vma->vm->i915;
 	struct drm_i915_gem_object *obj = vma->obj;
+	intel_wakeref_t wakeref;
 	u32 pte_flags;
 
 	/* Applicable to VLV (gen8+ do not support RO in the GGTT) */
@@ -2534,9 +2535,9 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 	if (i915_gem_object_is_readonly(obj))
 		pte_flags |= PTE_READ_ONLY;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
 
@@ -2553,10 +2554,11 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 static void ggtt_unbind_vma(struct i915_vma *vma)
 {
 	struct drm_i915_private *i915 = vma->vm->i915;
+	intel_wakeref_t wakeref;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 }
 
 static int aliasing_gtt_bind_vma(struct i915_vma *vma,
@@ -2588,9 +2590,11 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
 	}
 
 	if (flags & I915_VMA_GLOBAL_BIND) {
-		intel_runtime_pm_get(i915);
+		intel_wakeref_t wakeref;
+
+		wakeref = intel_runtime_pm_get(i915);
 		vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
-		intel_runtime_pm_put_unchecked(i915);
+		intel_runtime_pm_put(i915, wakeref);
 	}
 
 	return 0;
@@ -2601,9 +2605,11 @@ static void aliasing_gtt_unbind_vma(struct i915_vma *vma)
 	struct drm_i915_private *i915 = vma->vm->i915;
 
 	if (vma->flags & I915_VMA_GLOBAL_BIND) {
-		intel_runtime_pm_get(i915);
+		intel_wakeref_t wakeref;
+
+		wakeref = intel_runtime_pm_get(i915);
 		vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
-		intel_runtime_pm_put_unchecked(i915);
+		intel_runtime_pm_put(i915, wakeref);
 	}
 
 	if (vma->flags & I915_VMA_LOCAL_BIND) {
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 1f0e79635087..7d1722f7299b 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -153,6 +153,7 @@ i915_gem_shrink(struct drm_i915_private *i915,
 		{ &i915->mm.bound_list, I915_SHRINK_BOUND },
 		{ NULL, 0 },
 	}, *phase;
+	intel_wakeref_t wakeref = 0;
 	unsigned long count = 0;
 	unsigned long scanned = 0;
 	bool unlock;
@@ -182,9 +183,11 @@ i915_gem_shrink(struct drm_i915_private *i915,
 	 * device just to recover a little memory. If absolutely necessary,
 	 * we will force the wake during oom-notifier.
 	 */
-	if ((flags & I915_SHRINK_BOUND) &&
-	    !intel_runtime_pm_get_if_in_use(i915))
-		flags &= ~I915_SHRINK_BOUND;
+	if (flags & I915_SHRINK_BOUND) {
+		wakeref = intel_runtime_pm_get_if_in_use(i915);
+		if (!wakeref)
+			flags &= ~I915_SHRINK_BOUND;
+	}
 
 	/*
 	 * As we may completely rewrite the (un)bound list whilst unbinding
@@ -265,7 +268,7 @@ i915_gem_shrink(struct drm_i915_private *i915,
 	}
 
 	if (flags & I915_SHRINK_BOUND)
-		intel_runtime_pm_put_unchecked(i915);
+		intel_runtime_pm_put(i915, wakeref);
 
 	i915_retire_requests(i915);
 
@@ -292,14 +295,15 @@ i915_gem_shrink(struct drm_i915_private *i915,
  */
 unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
 {
+	intel_wakeref_t wakeref;
 	unsigned long freed;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	freed = i915_gem_shrink(i915, -1UL, NULL,
 				I915_SHRINK_BOUND |
 				I915_SHRINK_UNBOUND |
 				I915_SHRINK_ACTIVE);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	return freed;
 }
@@ -370,14 +374,16 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
 					 I915_SHRINK_BOUND |
 					 I915_SHRINK_UNBOUND);
 	if (sc->nr_scanned < sc->nr_to_scan && current_is_kswapd()) {
-		intel_runtime_pm_get(i915);
+		intel_wakeref_t wakeref;
+
+		wakeref = intel_runtime_pm_get(i915);
 		freed += i915_gem_shrink(i915,
 					 sc->nr_to_scan - sc->nr_scanned,
 					 &sc->nr_scanned,
 					 I915_SHRINK_ACTIVE |
 					 I915_SHRINK_BOUND |
 					 I915_SHRINK_UNBOUND);
-		intel_runtime_pm_put_unchecked(i915);
+		intel_runtime_pm_put(i915, wakeref);
 	}
 
 	shrinker_unlock(i915, unlock);
@@ -417,12 +423,13 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
 		container_of(nb, struct drm_i915_private, mm.oom_notifier);
 	struct drm_i915_gem_object *obj;
 	unsigned long unevictable, bound, unbound, freed_pages;
+	intel_wakeref_t wakeref;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	freed_pages = i915_gem_shrink(i915, -1UL, NULL,
 				      I915_SHRINK_BOUND |
 				      I915_SHRINK_UNBOUND);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	/* Because we may be allocating inside our own driver, we cannot
 	 * assert that there are no objects with pinned pages that are not
@@ -460,6 +467,7 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
 		container_of(nb, struct drm_i915_private, mm.vmap_notifier);
 	struct i915_vma *vma, *next;
 	unsigned long freed_pages = 0;
+	intel_wakeref_t wakeref;
 	bool unlock;
 	int ret;
 
@@ -473,12 +481,12 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
 	if (ret)
 		goto out;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	freed_pages += i915_gem_shrink(i915, -1UL, NULL,
 				       I915_SHRINK_BOUND |
 				       I915_SHRINK_UNBOUND |
 				       I915_SHRINK_VMAPS);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	/* We also want to clear any cached iomaps as they wrap vmap */
 	list_for_each_entry_safe(vma, next,
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 85131166589c..bf4dae2649ab 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -913,10 +913,12 @@ void intel_engine_get_instdone(struct intel_engine_cs *engine,
 static bool ring_is_idle(struct intel_engine_cs *engine)
 {
 	struct drm_i915_private *dev_priv = engine->i915;
+	intel_wakeref_t wakeref;
 	bool idle = true;
 
 	/* If the whole device is asleep, the engine must be idle */
-	if (!intel_runtime_pm_get_if_in_use(dev_priv))
+	wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
+	if (!wakeref)
 		return true;
 
 	/* First check that no commands are left in the ring */
@@ -928,7 +930,7 @@ static bool ring_is_idle(struct intel_engine_cs *engine)
 	if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
 		idle = false;
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return idle;
 }
@@ -1425,6 +1427,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
 	const struct intel_engine_execlists * const execlists = &engine->execlists;
 	struct i915_gpu_error * const error = &engine->i915->gpu_error;
 	struct i915_request *rq, *last;
+	intel_wakeref_t wakeref;
 	unsigned long flags;
 	struct rb_node *rb;
 	int count;
@@ -1483,9 +1486,10 @@ void intel_engine_dump(struct intel_engine_cs *engine,
 
 	rcu_read_unlock();
 
-	if (intel_runtime_pm_get_if_in_use(engine->i915)) {
+	wakeref = intel_runtime_pm_get_if_in_use(engine->i915);
+	if (wakeref) {
 		intel_engine_print_registers(engine, m);
-		intel_runtime_pm_put_unchecked(engine->i915);
+		intel_runtime_pm_put(engine->i915, wakeref);
 	} else {
 		drm_printf(m, "\tDevice is asleep; skipping register dump\n");
 	}
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 8d4c76ac0e7d..d494d92da02c 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1670,6 +1670,7 @@ int i915_reg_read_ioctl(struct drm_device *dev,
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_reg_read *reg = data;
 	struct reg_whitelist const *entry;
+	intel_wakeref_t wakeref;
 	unsigned int flags;
 	int remain;
 	int ret = 0;
@@ -1695,7 +1696,7 @@ int i915_reg_read_ioctl(struct drm_device *dev,
 
 	flags = reg->offset & (entry->size - 1);
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	if (entry->size == 8 && flags == I915_REG_READ_8B_WA)
 		reg->val = I915_READ64_2x32(entry->offset_ldw,
 					    entry->offset_udw);
@@ -1709,7 +1710,7 @@ int i915_reg_read_ioctl(struct drm_device *dev,
 		reg->val = I915_READ8(entry->offset_ldw);
 	else
 		ret = -EINVAL;
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return ret;
 }
-- 
2.20.1

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

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

* [PATCH 11/21] drm/i915/fb: Track rpm wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (9 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 10/21] drm/i915/gem: Track the rpm wakerefs Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 12/21] drm/i915/hotplug: Track temporary rpm wakeref Chris Wilson
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Keep track of the rpm wakeref used for framebuffer access so that we can
cancel upon release and so more clearly identify leaks.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 5 +++--
 drivers/gpu/drm/i915/intel_fbdev.c   | 9 +++++----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a980d5d1e601..b0b8f9ffd873 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2023,6 +2023,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 	struct drm_device *dev = fb->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+	intel_wakeref_t wakeref;
 	struct i915_vma *vma;
 	unsigned int pinctl;
 	u32 alignment;
@@ -2046,7 +2047,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 	 * intel_runtime_pm_put(), so it is correct to wrap only the
 	 * pin/unpin/fence and not more.
 	 */
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
 
@@ -2101,7 +2102,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 err:
 	atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	return vma;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 215e5894842d..3036d835bc2b 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -177,8 +177,9 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	const struct i915_ggtt_view view = {
 		.type = I915_GGTT_VIEW_NORMAL,
 	};
-	struct fb_info *info;
 	struct drm_framebuffer *fb;
+	intel_wakeref_t wakeref;
+	struct fb_info *info;
 	struct i915_vma *vma;
 	unsigned long flags = 0;
 	bool prealloc = false;
@@ -209,7 +210,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	}
 
 	mutex_lock(&dev->struct_mutex);
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	/* Pin the GGTT vma for our access via info->screen_base.
 	 * This also validates that any existing fb inherited from the
@@ -276,7 +277,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	ifbdev->vma = vma;
 	ifbdev->vma_flags = flags;
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	mutex_unlock(&dev->struct_mutex);
 	vga_switcheroo_client_fb_set(pdev, info);
 	return 0;
@@ -284,7 +285,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
 out_unpin:
 	intel_unpin_fb_vma(vma, flags);
 out_unlock:
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
-- 
2.20.1

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

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

* [PATCH 12/21] drm/i915/hotplug: Track temporary rpm wakeref
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (10 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 11/21] drm/i915/fb: Track " Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 13/21] drm/i915/panel: " Chris Wilson
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Keep track of the temporary rpm wakeref inside hotplug detection, so
that we can cancel it immediately upon release and so clearly identify
leaks.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_hotplug.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
index b1a9cb960ca4..e027d2b4abe5 100644
--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -226,9 +226,10 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
 		container_of(work, typeof(*dev_priv),
 			     hotplug.reenable_work.work);
 	struct drm_device *dev = &dev_priv->drm;
+	intel_wakeref_t wakeref;
 	enum hpd_pin pin;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	spin_lock_irq(&dev_priv->irq_lock);
 	for_each_hpd_pin(pin) {
@@ -261,7 +262,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
 		dev_priv->display.hpd_irq_setup(dev_priv);
 	spin_unlock_irq(&dev_priv->irq_lock);
 
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 }
 
 bool intel_encoder_hotplug(struct intel_encoder *encoder,
-- 
2.20.1

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

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

* [PATCH 13/21] drm/i915/panel: Track temporary rpm wakeref
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (11 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 12/21] drm/i915/hotplug: Track temporary rpm wakeref Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 14/21] drm/i915/selftests: Mark up rpm wakerefs Chris Wilson
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Keep track of the temporary rpm wakeref used for panel backlight access,
so that we can cancel it immediately upon release and so more clearly
identify leaks.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_panel.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index c2b7455a023e..93a2e4b5c54c 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1203,17 +1203,18 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
 	struct intel_connector *connector = bl_get_data(bd);
 	struct drm_device *dev = connector->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	intel_wakeref_t wakeref;
 	u32 hw_level;
 	int ret;
 
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 
 	hw_level = intel_panel_get_backlight(connector);
 	ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
 
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 
 	return ret;
 }
-- 
2.20.1

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

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

* [PATCH 14/21] drm/i915/selftests: Mark up rpm wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (12 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 13/21] drm/i915/panel: " Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 15/21] drm/i915: Syntatic sugar for using intel_runtime_pm Chris Wilson
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Track the temporary wakerefs used within the selftests so that leaks are
clear.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/selftests/huge_pages.c   |  5 ++--
 drivers/gpu/drm/i915/selftests/i915_gem.c     | 29 ++++++++++++-------
 .../drm/i915/selftests/i915_gem_coherency.c   |  5 ++--
 .../gpu/drm/i915/selftests/i915_gem_context.c | 27 ++++++++++-------
 .../gpu/drm/i915/selftests/i915_gem_evict.c   | 11 ++++---
 drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 10 ++++---
 .../gpu/drm/i915/selftests/i915_gem_object.c  | 18 ++++++++----
 drivers/gpu/drm/i915/selftests/i915_request.c | 22 ++++++++------
 drivers/gpu/drm/i915/selftests/intel_guc.c    | 10 ++++---
 .../gpu/drm/i915/selftests/intel_hangcheck.c  | 15 ++++++----
 drivers/gpu/drm/i915/selftests/intel_lrc.c    | 25 +++++++++-------
 .../drm/i915/selftests/intel_workarounds.c    | 29 ++++++++++++-------
 12 files changed, 128 insertions(+), 78 deletions(-)

diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c
index a4d8b12be12c..a52450111802 100644
--- a/drivers/gpu/drm/i915/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/selftests/huge_pages.c
@@ -1756,6 +1756,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv)
 	};
 	struct drm_file *file;
 	struct i915_gem_context *ctx;
+	intel_wakeref_t wakeref;
 	int err;
 
 	if (!HAS_PPGTT(dev_priv)) {
@@ -1771,7 +1772,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv)
 		return PTR_ERR(file);
 
 	mutex_lock(&dev_priv->drm.struct_mutex);
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	ctx = live_context(dev_priv, file);
 	if (IS_ERR(ctx)) {
@@ -1785,7 +1786,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv)
 	err = i915_subtests(tests, ctx);
 
 out_unlock:
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 
 	mock_file_free(dev_priv, file);
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c
index 762e1a7125f5..01a46c46fe25 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem.c
@@ -16,9 +16,10 @@ static int switch_to_context(struct drm_i915_private *i915,
 {
 	struct intel_engine_cs *engine;
 	enum intel_engine_id id;
+	intel_wakeref_t wakeref;
 	int err = 0;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	for_each_engine(engine, i915, id) {
 		struct i915_request *rq;
@@ -32,7 +33,7 @@ static int switch_to_context(struct drm_i915_private *i915,
 		i915_request_add(rq);
 	}
 
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	return err;
 }
@@ -65,7 +66,9 @@ static void trash_stolen(struct drm_i915_private *i915)
 
 static void simulate_hibernate(struct drm_i915_private *i915)
 {
-	intel_runtime_pm_get(i915);
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_runtime_pm_get(i915);
 
 	/*
 	 * As a final sting in the tail, invalidate stolen. Under a real S4,
@@ -76,7 +79,7 @@ static void simulate_hibernate(struct drm_i915_private *i915)
 	 */
 	trash_stolen(i915);
 
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 }
 
 static int pm_prepare(struct drm_i915_private *i915)
@@ -93,39 +96,45 @@ static int pm_prepare(struct drm_i915_private *i915)
 
 static void pm_suspend(struct drm_i915_private *i915)
 {
-	intel_runtime_pm_get(i915);
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_runtime_pm_get(i915);
 
 	i915_gem_suspend_gtt_mappings(i915);
 	i915_gem_suspend_late(i915);
 
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 }
 
 static void pm_hibernate(struct drm_i915_private *i915)
 {
-	intel_runtime_pm_get(i915);
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_runtime_pm_get(i915);
 
 	i915_gem_suspend_gtt_mappings(i915);
 
 	i915_gem_freeze(i915);
 	i915_gem_freeze_late(i915);
 
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 }
 
 static void pm_resume(struct drm_i915_private *i915)
 {
+	intel_wakeref_t wakeref;
+
 	/*
 	 * Both suspend and hibernate follow the same wakeup path and assume
 	 * that runtime-pm just works.
 	 */
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	intel_engines_sanitize(i915, false);
 	i915_gem_sanitize(i915);
 	i915_gem_resume(i915);
 
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 }
 
 static int igt_gem_suspend(void *arg)
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
index eea4fc2445ae..fd89a5a33c1a 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
@@ -279,6 +279,7 @@ static int igt_gem_coherency(void *arg)
 	struct drm_i915_private *i915 = arg;
 	const struct igt_coherency_mode *read, *write, *over;
 	struct drm_i915_gem_object *obj;
+	intel_wakeref_t wakeref;
 	unsigned long count, n;
 	u32 *offsets, *values;
 	int err = 0;
@@ -298,7 +299,7 @@ static int igt_gem_coherency(void *arg)
 	values = offsets + ncachelines;
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	for (over = igt_coherency_mode; over->name; over++) {
 		if (!over->set)
 			continue;
@@ -376,7 +377,7 @@ static int igt_gem_coherency(void *arg)
 		}
 	}
 unlock:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	kfree(offsets);
 	return err;
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
index 6e1a0711d201..7a9b1f20b019 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
@@ -119,6 +119,7 @@ static int live_nop_switch(void *arg)
 	struct intel_engine_cs *engine;
 	struct i915_gem_context **ctx;
 	enum intel_engine_id id;
+	intel_wakeref_t wakeref;
 	struct drm_file *file;
 	struct live_test t;
 	unsigned long n;
@@ -140,7 +141,7 @@ static int live_nop_switch(void *arg)
 		return PTR_ERR(file);
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	ctx = kcalloc(nctx, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx) {
@@ -243,7 +244,7 @@ static int live_nop_switch(void *arg)
 	}
 
 out_unlock:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	mock_file_free(i915, file);
 	return err;
@@ -593,6 +594,8 @@ static int igt_ctx_exec(void *arg)
 		}
 
 		for_each_engine(engine, i915, id) {
+			intel_wakeref_t wakeref;
+
 			if (!engine->context_size)
 				continue; /* No logical context support in HW */
 
@@ -607,9 +610,9 @@ static int igt_ctx_exec(void *arg)
 				}
 			}
 
-			intel_runtime_pm_get(i915);
+			wakeref = intel_runtime_pm_get(i915);
 			err = gpu_fill(obj, ctx, engine, dw);
-			intel_runtime_pm_put_unchecked(i915);
+			intel_runtime_pm_put(i915, wakeref);
 			if (err) {
 				pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
 				       ndwords, dw, max_dwords(obj),
@@ -699,6 +702,8 @@ static int igt_ctx_readonly(void *arg)
 		unsigned int id;
 
 		for_each_engine(engine, i915, id) {
+			intel_wakeref_t wakeref;
+
 			if (!intel_engine_can_store_dword(engine))
 				continue;
 
@@ -713,9 +718,9 @@ static int igt_ctx_readonly(void *arg)
 					i915_gem_object_set_readonly(obj);
 			}
 
-			intel_runtime_pm_get(i915);
+			wakeref = intel_runtime_pm_get(i915);
 			err = gpu_fill(obj, ctx, engine, dw);
-			intel_runtime_pm_put_unchecked(i915);
+			intel_runtime_pm_put(i915, wakeref);
 			if (err) {
 				pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
 				       ndwords, dw, max_dwords(obj),
@@ -976,6 +981,7 @@ static int igt_vm_isolation(void *arg)
 	struct drm_i915_private *i915 = arg;
 	struct i915_gem_context *ctx_a, *ctx_b;
 	struct intel_engine_cs *engine;
+	intel_wakeref_t wakeref;
 	struct drm_file *file;
 	I915_RND_STATE(prng);
 	unsigned long count;
@@ -1022,7 +1028,7 @@ static int igt_vm_isolation(void *arg)
 	GEM_BUG_ON(ctx_b->ppgtt->vm.total != vm_total);
 	vm_total -= I915_GTT_PAGE_SIZE;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	count = 0;
 	for_each_engine(engine, i915, id) {
@@ -1067,7 +1073,7 @@ static int igt_vm_isolation(void *arg)
 		count, RUNTIME_INFO(i915)->num_rings);
 
 out_rpm:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 out_unlock:
 	if (end_live_test(&t))
 		err = -EIO;
@@ -1165,6 +1171,7 @@ static int igt_switch_to_kernel_context(void *arg)
 	struct intel_engine_cs *engine;
 	struct i915_gem_context *ctx;
 	enum intel_engine_id id;
+	intel_wakeref_t wakeref;
 	int err;
 
 	/*
@@ -1175,7 +1182,7 @@ static int igt_switch_to_kernel_context(void *arg)
 	 */
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	ctx = kernel_context(i915);
 	if (IS_ERR(ctx)) {
@@ -1200,7 +1207,7 @@ static int igt_switch_to_kernel_context(void *arg)
 	if (igt_flush_test(i915, I915_WAIT_LOCKED))
 		err = -EIO;
 
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 
 	kernel_context_close(ctx);
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
index 8d22f73a9b63..e1ff6a1c2cb0 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
@@ -336,6 +336,7 @@ static int igt_evict_contexts(void *arg)
 		struct drm_mm_node node;
 		struct reserved *next;
 	} *reserved = NULL;
+	intel_wakeref_t wakeref;
 	struct drm_mm_node hole;
 	unsigned long count;
 	int err;
@@ -355,7 +356,7 @@ static int igt_evict_contexts(void *arg)
 		return 0;
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	/* Reserve a block so that we know we have enough to fit a few rq */
 	memset(&hole, 0, sizeof(hole));
@@ -400,8 +401,10 @@ static int igt_evict_contexts(void *arg)
 		struct drm_file *file;
 
 		file = mock_file(i915);
-		if (IS_ERR(file))
-			return PTR_ERR(file);
+		if (IS_ERR(file)) {
+			err = PTR_ERR(file);
+			break;
+		}
 
 		count = 0;
 		mutex_lock(&i915->drm.struct_mutex);
@@ -464,7 +467,7 @@ static int igt_evict_contexts(void *arg)
 	}
 	if (drm_mm_node_allocated(&hole))
 		drm_mm_remove_node(&hole);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 
 	return err;
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
index 87cb0602a5fc..fea8ab14e79d 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
@@ -275,6 +275,7 @@ static int lowlevel_hole(struct drm_i915_private *i915,
 
 		for (n = 0; n < count; n++) {
 			u64 addr = hole_start + order[n] * BIT_ULL(size);
+			intel_wakeref_t wakeref;
 
 			GEM_BUG_ON(addr + BIT_ULL(size) > vm->total);
 
@@ -293,9 +294,9 @@ static int lowlevel_hole(struct drm_i915_private *i915,
 			mock_vma.node.size = BIT_ULL(size);
 			mock_vma.node.start = addr;
 
-			intel_runtime_pm_get(i915);
+			wakeref = intel_runtime_pm_get(i915);
 			vm->insert_entries(vm, &mock_vma, I915_CACHE_NONE, 0);
-			intel_runtime_pm_put_unchecked(i915);
+			intel_runtime_pm_put(i915, wakeref);
 		}
 		count = n;
 
@@ -1144,6 +1145,7 @@ static int igt_ggtt_page(void *arg)
 	struct drm_i915_private *i915 = arg;
 	struct i915_ggtt *ggtt = &i915->ggtt;
 	struct drm_i915_gem_object *obj;
+	intel_wakeref_t wakeref;
 	struct drm_mm_node tmp;
 	unsigned int *order, n;
 	int err;
@@ -1169,7 +1171,7 @@ static int igt_ggtt_page(void *arg)
 	if (err)
 		goto out_unpin;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	for (n = 0; n < count; n++) {
 		u64 offset = tmp.start + n * PAGE_SIZE;
@@ -1216,7 +1218,7 @@ static int igt_ggtt_page(void *arg)
 	kfree(order);
 out_remove:
 	ggtt->vm.clear_range(&ggtt->vm, tmp.start, tmp.size);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	drm_mm_remove_node(&tmp);
 out_unpin:
 	i915_gem_object_unpin_pages(obj);
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
index b03890c590d7..3575e1387c3f 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
@@ -308,6 +308,7 @@ static int igt_partial_tiling(void *arg)
 	const unsigned int nreal = 1 << 12; /* largest tile row x2 */
 	struct drm_i915_private *i915 = arg;
 	struct drm_i915_gem_object *obj;
+	intel_wakeref_t wakeref;
 	int tiling;
 	int err;
 
@@ -333,7 +334,7 @@ static int igt_partial_tiling(void *arg)
 	}
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	if (1) {
 		IGT_TIMEOUT(end);
@@ -444,7 +445,7 @@ next_tiling: ;
 	}
 
 out_unlock:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	i915_gem_object_unpin_pages(obj);
 out:
@@ -506,11 +507,14 @@ static void disable_retire_worker(struct drm_i915_private *i915)
 
 	mutex_lock(&i915->drm.struct_mutex);
 	if (!i915->gt.active_requests++) {
-		intel_runtime_pm_get(i915);
+		intel_wakeref_t wakeref;
+
+		wakeref = intel_runtime_pm_get(i915);
 		i915_gem_unpark(i915);
-		intel_runtime_pm_put_unchecked(i915);
+		intel_runtime_pm_put(i915, wakeref);
 	}
 	mutex_unlock(&i915->drm.struct_mutex);
+
 	cancel_delayed_work_sync(&i915->gt.retire_work);
 	cancel_delayed_work_sync(&i915->gt.idle_work);
 }
@@ -578,6 +582,8 @@ static int igt_mmap_offset_exhaustion(void *arg)
 
 	/* Now fill with busy dead objects that we expect to reap */
 	for (loop = 0; loop < 3; loop++) {
+		intel_wakeref_t wakeref;
+
 		if (i915_terminally_wedged(&i915->gpu_error))
 			break;
 
@@ -588,9 +594,9 @@ static int igt_mmap_offset_exhaustion(void *arg)
 		}
 
 		mutex_lock(&i915->drm.struct_mutex);
-		intel_runtime_pm_get(i915);
+		wakeref = intel_runtime_pm_get(i915);
 		err = make_obj_busy(obj);
-		intel_runtime_pm_put_unchecked(i915);
+		intel_runtime_pm_put(i915, wakeref);
 		mutex_unlock(&i915->drm.struct_mutex);
 		if (err) {
 			pr_err("[loop %d] Failed to busy the object\n", loop);
diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
index e8880cabd5c7..8b73a8c21377 100644
--- a/drivers/gpu/drm/i915/selftests/i915_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_request.c
@@ -332,6 +332,7 @@ static int live_nop_request(void *arg)
 {
 	struct drm_i915_private *i915 = arg;
 	struct intel_engine_cs *engine;
+	intel_wakeref_t wakeref;
 	struct live_test t;
 	unsigned int id;
 	int err = -ENODEV;
@@ -342,7 +343,7 @@ static int live_nop_request(void *arg)
 	 */
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	for_each_engine(engine, i915, id) {
 		struct i915_request *request = NULL;
@@ -403,7 +404,7 @@ static int live_nop_request(void *arg)
 	}
 
 out_unlock:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -478,8 +479,9 @@ static int live_empty_request(void *arg)
 {
 	struct drm_i915_private *i915 = arg;
 	struct intel_engine_cs *engine;
-	struct live_test t;
+	intel_wakeref_t wakeref;
 	struct i915_vma *batch;
+	struct live_test t;
 	unsigned int id;
 	int err = 0;
 
@@ -489,7 +491,7 @@ static int live_empty_request(void *arg)
 	 */
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	batch = empty_batch(i915);
 	if (IS_ERR(batch)) {
@@ -553,7 +555,7 @@ static int live_empty_request(void *arg)
 	i915_vma_unpin(batch);
 	i915_vma_put(batch);
 out_unlock:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -637,6 +639,7 @@ static int live_all_engines(void *arg)
 	struct drm_i915_private *i915 = arg;
 	struct intel_engine_cs *engine;
 	struct i915_request *request[I915_NUM_ENGINES];
+	intel_wakeref_t wakeref;
 	struct i915_vma *batch;
 	struct live_test t;
 	unsigned int id;
@@ -648,7 +651,7 @@ static int live_all_engines(void *arg)
 	 */
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	err = begin_live_test(&t, i915, __func__, "");
 	if (err)
@@ -731,7 +734,7 @@ static int live_all_engines(void *arg)
 	i915_vma_unpin(batch);
 	i915_vma_put(batch);
 out_unlock:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -742,6 +745,7 @@ static int live_sequential_engines(void *arg)
 	struct i915_request *request[I915_NUM_ENGINES] = {};
 	struct i915_request *prev = NULL;
 	struct intel_engine_cs *engine;
+	intel_wakeref_t wakeref;
 	struct live_test t;
 	unsigned int id;
 	int err;
@@ -753,7 +757,7 @@ static int live_sequential_engines(void *arg)
 	 */
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	err = begin_live_test(&t, i915, __func__, "");
 	if (err)
@@ -860,7 +864,7 @@ static int live_sequential_engines(void *arg)
 		i915_request_put(request[id]);
 	}
 out_unlock:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
diff --git a/drivers/gpu/drm/i915/selftests/intel_guc.c b/drivers/gpu/drm/i915/selftests/intel_guc.c
index 3590ba3d8897..c5e0a0e98fcb 100644
--- a/drivers/gpu/drm/i915/selftests/intel_guc.c
+++ b/drivers/gpu/drm/i915/selftests/intel_guc.c
@@ -137,12 +137,13 @@ static bool client_doorbell_in_sync(struct intel_guc_client *client)
 static int igt_guc_clients(void *args)
 {
 	struct drm_i915_private *dev_priv = args;
+	intel_wakeref_t wakeref;
 	struct intel_guc *guc;
 	int err = 0;
 
 	GEM_BUG_ON(!HAS_GUC(dev_priv));
 	mutex_lock(&dev_priv->drm.struct_mutex);
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	guc = &dev_priv->guc;
 	if (!guc) {
@@ -225,7 +226,7 @@ static int igt_guc_clients(void *args)
 	guc_clients_create(guc);
 	guc_clients_enable(guc);
 unlock:
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 	return err;
 }
@@ -238,13 +239,14 @@ static int igt_guc_clients(void *args)
 static int igt_guc_doorbells(void *arg)
 {
 	struct drm_i915_private *dev_priv = arg;
+	intel_wakeref_t wakeref;
 	struct intel_guc *guc;
 	int i, err = 0;
 	u16 db_id;
 
 	GEM_BUG_ON(!HAS_GUC(dev_priv));
 	mutex_lock(&dev_priv->drm.struct_mutex);
-	intel_runtime_pm_get(dev_priv);
+	wakeref = intel_runtime_pm_get(dev_priv);
 
 	guc = &dev_priv->guc;
 	if (!guc) {
@@ -337,7 +339,7 @@ static int igt_guc_doorbells(void *arg)
 			guc_client_free(clients[i]);
 		}
 unlock:
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_runtime_pm_put(dev_priv, wakeref);
 	mutex_unlock(&dev_priv->drm.struct_mutex);
 	return err;
 }
diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
index 33bd3c4b6fa3..12550b55c42f 100644
--- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
+++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
@@ -388,12 +388,13 @@ static int igt_global_reset(void *arg)
 static int igt_wedged_reset(void *arg)
 {
 	struct drm_i915_private *i915 = arg;
+	intel_wakeref_t wakeref;
 
 	/* Check that we can recover a wedged device with a GPU reset */
 
 	igt_global_reset_lock(i915);
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	i915_gem_set_wedged(i915);
 	GEM_BUG_ON(!i915_terminally_wedged(&i915->gpu_error));
@@ -402,7 +403,7 @@ static int igt_wedged_reset(void *arg)
 	i915_reset(i915, ALL_ENGINES, NULL);
 	GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags));
 
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	igt_global_reset_unlock(i915);
 
@@ -1600,6 +1601,7 @@ static int igt_atomic_reset(void *arg)
 		{ }
 	};
 	struct drm_i915_private *i915 = arg;
+	intel_wakeref_t wakeref;
 	int err = 0;
 
 	/* Check that the resets are usable from atomic context */
@@ -1609,7 +1611,7 @@ static int igt_atomic_reset(void *arg)
 
 	igt_global_reset_lock(i915);
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	/* Flush any requests before we get started and check basics */
 	force_reset(i915);
@@ -1636,7 +1638,7 @@ static int igt_atomic_reset(void *arg)
 	force_reset(i915);
 
 unlock:
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	igt_global_reset_unlock(i915);
 
@@ -1660,6 +1662,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
 		SUBTEST(igt_handle_error),
 		SUBTEST(igt_atomic_reset),
 	};
+	intel_wakeref_t wakeref;
 	bool saved_hangcheck;
 	int err;
 
@@ -1669,7 +1672,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
 	if (i915_terminally_wedged(&i915->gpu_error))
 		return -EIO; /* we're long past hope of a successful reset */
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	saved_hangcheck = fetch_and_zero(&i915_modparams.enable_hangcheck);
 
 	err = i915_subtests(tests, i915);
@@ -1679,7 +1682,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
 	mutex_unlock(&i915->drm.struct_mutex);
 
 	i915_modparams.enable_hangcheck = saved_hangcheck;
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	return err;
 }
diff --git a/drivers/gpu/drm/i915/selftests/intel_lrc.c b/drivers/gpu/drm/i915/selftests/intel_lrc.c
index ac1b18a17f3c..e6073cd4719c 100644
--- a/drivers/gpu/drm/i915/selftests/intel_lrc.c
+++ b/drivers/gpu/drm/i915/selftests/intel_lrc.c
@@ -18,13 +18,14 @@ static int live_sanitycheck(void *arg)
 	struct i915_gem_context *ctx;
 	enum intel_engine_id id;
 	struct igt_spinner spin;
+	intel_wakeref_t wakeref;
 	int err = -ENOMEM;
 
 	if (!HAS_LOGICAL_RING_CONTEXTS(i915))
 		return 0;
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	if (igt_spinner_init(&spin, i915))
 		goto err_unlock;
@@ -65,7 +66,7 @@ static int live_sanitycheck(void *arg)
 	igt_spinner_fini(&spin);
 err_unlock:
 	igt_flush_test(i915, I915_WAIT_LOCKED);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -77,13 +78,14 @@ static int live_preempt(void *arg)
 	struct igt_spinner spin_hi, spin_lo;
 	struct intel_engine_cs *engine;
 	enum intel_engine_id id;
+	intel_wakeref_t wakeref;
 	int err = -ENOMEM;
 
 	if (!HAS_LOGICAL_RING_PREEMPTION(i915))
 		return 0;
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	if (igt_spinner_init(&spin_hi, i915))
 		goto err_unlock;
@@ -158,7 +160,7 @@ static int live_preempt(void *arg)
 	igt_spinner_fini(&spin_hi);
 err_unlock:
 	igt_flush_test(i915, I915_WAIT_LOCKED);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -171,13 +173,14 @@ static int live_late_preempt(void *arg)
 	struct intel_engine_cs *engine;
 	struct i915_sched_attr attr = {};
 	enum intel_engine_id id;
+	intel_wakeref_t wakeref;
 	int err = -ENOMEM;
 
 	if (!HAS_LOGICAL_RING_PREEMPTION(i915))
 		return 0;
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	if (igt_spinner_init(&spin_hi, i915))
 		goto err_unlock;
@@ -251,7 +254,7 @@ static int live_late_preempt(void *arg)
 	igt_spinner_fini(&spin_hi);
 err_unlock:
 	igt_flush_test(i915, I915_WAIT_LOCKED);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 
@@ -270,6 +273,7 @@ static int live_preempt_hang(void *arg)
 	struct igt_spinner spin_hi, spin_lo;
 	struct intel_engine_cs *engine;
 	enum intel_engine_id id;
+	intel_wakeref_t wakeref;
 	int err = -ENOMEM;
 
 	if (!HAS_LOGICAL_RING_PREEMPTION(i915))
@@ -279,7 +283,7 @@ static int live_preempt_hang(void *arg)
 		return 0;
 
 	mutex_lock(&i915->drm.struct_mutex);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 
 	if (igt_spinner_init(&spin_hi, i915))
 		goto err_unlock;
@@ -374,7 +378,7 @@ static int live_preempt_hang(void *arg)
 	igt_spinner_fini(&spin_hi);
 err_unlock:
 	igt_flush_test(i915, I915_WAIT_LOCKED);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	mutex_unlock(&i915->drm.struct_mutex);
 	return err;
 }
@@ -562,6 +566,7 @@ static int live_preempt_smoke(void *arg)
 		.ncontext = 1024,
 	};
 	const unsigned int phase[] = { 0, BATCH };
+	intel_wakeref_t wakeref;
 	int err = -ENOMEM;
 	u32 *cs;
 	int n;
@@ -576,7 +581,7 @@ static int live_preempt_smoke(void *arg)
 		return -ENOMEM;
 
 	mutex_lock(&smoke.i915->drm.struct_mutex);
-	intel_runtime_pm_get(smoke.i915);
+	wakeref = intel_runtime_pm_get(smoke.i915);
 
 	smoke.batch = i915_gem_object_create_internal(smoke.i915, PAGE_SIZE);
 	if (IS_ERR(smoke.batch)) {
@@ -627,7 +632,7 @@ static int live_preempt_smoke(void *arg)
 err_batch:
 	i915_gem_object_put(smoke.batch);
 err_unlock:
-	intel_runtime_pm_put_unchecked(smoke.i915);
+	intel_runtime_pm_put(smoke.i915, wakeref);
 	mutex_unlock(&smoke.i915->drm.struct_mutex);
 	kfree(smoke.contexts);
 
diff --git a/drivers/gpu/drm/i915/selftests/intel_workarounds.c b/drivers/gpu/drm/i915/selftests/intel_workarounds.c
index b1b39c70c702..75324b6249e3 100644
--- a/drivers/gpu/drm/i915/selftests/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/selftests/intel_workarounds.c
@@ -60,10 +60,11 @@ reference_lists_fini(struct drm_i915_private *i915, struct wa_lists *lists)
 static struct drm_i915_gem_object *
 read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
 {
+	const u32 base = engine->mmio_base;
 	struct drm_i915_gem_object *result;
+	intel_wakeref_t wakeref;
 	struct i915_request *rq;
 	struct i915_vma *vma;
-	const u32 base = engine->mmio_base;
 	u32 srm, *cs;
 	int err;
 	int i;
@@ -92,9 +93,9 @@ read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
 	if (err)
 		goto err_obj;
 
-	intel_runtime_pm_get(engine->i915);
+	wakeref = intel_runtime_pm_get(engine->i915);
 	rq = i915_request_alloc(engine, ctx);
-	intel_runtime_pm_put_unchecked(engine->i915);
+	intel_runtime_pm_put(engine->i915, wakeref);
 	if (IS_ERR(rq)) {
 		err = PTR_ERR(rq);
 		goto err_pin;
@@ -228,20 +229,21 @@ switch_to_scratch_context(struct intel_engine_cs *engine,
 {
 	struct i915_gem_context *ctx;
 	struct i915_request *rq;
+	intel_wakeref_t wakeref;
 	int err = 0;
 
 	ctx = kernel_context(engine->i915);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
-	intel_runtime_pm_get(engine->i915);
+	wakeref = intel_runtime_pm_get(engine->i915);
 
 	if (spin)
 		rq = igt_spinner_create_request(spin, ctx, engine, MI_NOOP);
 	else
 		rq = i915_request_alloc(engine, ctx);
 
-	intel_runtime_pm_put_unchecked(engine->i915);
+	intel_runtime_pm_put(engine->i915, wakeref);
 
 	kernel_context_close(ctx);
 
@@ -273,6 +275,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
 	bool want_spin = reset == do_engine_reset;
 	struct i915_gem_context *ctx;
 	struct igt_spinner spin;
+	intel_wakeref_t wakeref;
 	int err;
 
 	pr_info("Checking %d whitelisted registers (RING_NONPRIV) [%s]\n",
@@ -298,9 +301,9 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
 	if (err)
 		goto out;
 
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
 	err = reset(engine);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 
 	if (want_spin) {
 		igt_spinner_end(&spin);
@@ -391,6 +394,7 @@ live_gpu_reset_gt_engine_workarounds(void *arg)
 {
 	struct drm_i915_private *i915 = arg;
 	struct i915_gpu_error *error = &i915->gpu_error;
+	intel_wakeref_t wakeref;
 	struct wa_lists lists;
 	bool ok;
 
@@ -400,7 +404,8 @@ live_gpu_reset_gt_engine_workarounds(void *arg)
 	pr_info("Verifying after GPU reset...\n");
 
 	igt_global_reset_lock(i915);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
+
 	reference_lists_init(i915, &lists);
 
 	ok = verify_gt_engine_wa(i915, &lists, "before reset");
@@ -414,7 +419,7 @@ live_gpu_reset_gt_engine_workarounds(void *arg)
 
 out:
 	reference_lists_fini(i915, &lists);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	igt_global_reset_unlock(i915);
 
 	return ok ? 0 : -ESRCH;
@@ -429,6 +434,7 @@ live_engine_reset_gt_engine_workarounds(void *arg)
 	struct igt_spinner spin;
 	enum intel_engine_id id;
 	struct i915_request *rq;
+	intel_wakeref_t wakeref;
 	struct wa_lists lists;
 	int ret = 0;
 
@@ -440,7 +446,8 @@ live_engine_reset_gt_engine_workarounds(void *arg)
 		return PTR_ERR(ctx);
 
 	igt_global_reset_lock(i915);
-	intel_runtime_pm_get(i915);
+	wakeref = intel_runtime_pm_get(i915);
+
 	reference_lists_init(i915, &lists);
 
 	for_each_engine(engine, i915, id) {
@@ -496,7 +503,7 @@ live_engine_reset_gt_engine_workarounds(void *arg)
 
 err:
 	reference_lists_fini(i915, &lists);
-	intel_runtime_pm_put_unchecked(i915);
+	intel_runtime_pm_put(i915, wakeref);
 	igt_global_reset_unlock(i915);
 	kernel_context_close(ctx);
 
-- 
2.20.1

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

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

* [PATCH 15/21] drm/i915: Syntatic sugar for using intel_runtime_pm
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (13 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 14/21] drm/i915/selftests: Mark up rpm wakerefs Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 10:11 ` [PATCH 16/21] drm/i915: Markup paired operations on display power domains Chris Wilson
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Frequently, we use intel_runtime_pm_get/_put around a small block.
Formalise that usage by providing a macro to define such a block with an
automatic closure to scope the intel_runtime_pm wakeref to that block,
i.e. macro abuse smelling of python.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c           | 162 ++++++++----------
 drivers/gpu/drm/i915/i915_gem.c               |  10 +-
 drivers/gpu/drm/i915/i915_gem_gtt.c           |  23 ++-
 drivers/gpu/drm/i915/i915_gem_shrinker.c      |  51 +++---
 drivers/gpu/drm/i915/i915_pmu.c               |   7 +-
 drivers/gpu/drm/i915/i915_sysfs.c             |   7 +-
 drivers/gpu/drm/i915/intel_drv.h              |   8 +
 drivers/gpu/drm/i915/intel_guc_log.c          |  26 ++-
 drivers/gpu/drm/i915/intel_huc.c              |   7 +-
 drivers/gpu/drm/i915/intel_panel.c            |  18 +-
 drivers/gpu/drm/i915/intel_uncore.c           |  30 ++--
 drivers/gpu/drm/i915/selftests/i915_gem.c     |  34 ++--
 .../gpu/drm/i915/selftests/i915_gem_context.c |  12 +-
 .../gpu/drm/i915/selftests/i915_gem_object.c  |  11 +-
 .../drm/i915/selftests/intel_workarounds.c    |  28 +--
 15 files changed, 203 insertions(+), 231 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index bed8a379fe00..34cbd9a20583 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -953,9 +953,9 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file)
 	struct i915_gpu_state *gpu;
 	intel_wakeref_t wakeref;
 
-	wakeref = intel_runtime_pm_get(i915);
-	gpu = i915_capture_gpu_state(i915);
-	intel_runtime_pm_put(i915, wakeref);
+	gpu = NULL;
+	with_intel_runtime_pm(i915, wakeref)
+		gpu = i915_capture_gpu_state(i915);
 	if (IS_ERR(gpu))
 		return PTR_ERR(gpu);
 
@@ -1287,17 +1287,15 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
 		return 0;
 	}
 
-	wakeref = intel_runtime_pm_get(dev_priv);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		for_each_engine(engine, dev_priv, id) {
+			acthd[id] = intel_engine_get_active_head(engine);
+			seqno[id] = intel_engine_get_seqno(engine);
+		}
 
-	for_each_engine(engine, dev_priv, id) {
-		acthd[id] = intel_engine_get_active_head(engine);
-		seqno[id] = intel_engine_get_seqno(engine);
+		intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
 	}
 
-	intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
-
-	intel_runtime_pm_put(dev_priv, wakeref);
-
 	if (timer_pending(&dev_priv->gpu_error.hangcheck_work.timer))
 		seq_printf(m, "Hangcheck active, timer fires in %dms\n",
 			   jiffies_to_msecs(dev_priv->gpu_error.hangcheck_work.timer.expires -
@@ -1573,18 +1571,16 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	intel_wakeref_t wakeref;
-	int err;
-
-	wakeref = intel_runtime_pm_get(dev_priv);
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		err = vlv_drpc_info(m);
-	else if (INTEL_GEN(dev_priv) >= 6)
-		err = gen6_drpc_info(m);
-	else
-		err = ironlake_drpc_info(m);
+	int err = -ENODEV;
 
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+			err = vlv_drpc_info(m);
+		else if (INTEL_GEN(dev_priv) >= 6)
+			err = gen6_drpc_info(m);
+		else
+			err = ironlake_drpc_info(m);
+	}
 
 	return err;
 }
@@ -2068,8 +2064,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
 	intel_wakeref_t wakeref;
 	struct drm_file *file;
 
-	wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
-	if (wakeref) {
+	with_intel_runtime_pm_if_in_use(dev_priv, wakeref) {
 		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 			mutex_lock(&dev_priv->pcu_lock);
 			act_freq = vlv_punit_read(dev_priv,
@@ -2080,7 +2075,6 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
 			act_freq = intel_get_cagf(dev_priv,
 						  I915_READ(GEN6_RPSTAT1));
 		}
-		intel_runtime_pm_put(dev_priv, wakeref);
 	}
 
 	seq_printf(m, "RPS enabled? %d\n", rps->enabled);
@@ -2172,9 +2166,8 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data)
 	p = drm_seq_file_printer(m);
 	intel_uc_fw_dump(&dev_priv->huc.fw, &p);
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-	seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref)
+		seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
 
 	return 0;
 }
@@ -2184,7 +2177,6 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	intel_wakeref_t wakeref;
 	struct drm_printer p;
-	u32 tmp, i;
 
 	if (!HAS_GUC(dev_priv))
 		return -ENODEV;
@@ -2192,22 +2184,23 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
 	p = drm_seq_file_printer(m);
 	intel_uc_fw_dump(&dev_priv->guc.fw, &p);
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-
-	tmp = I915_READ(GUC_STATUS);
-
-	seq_printf(m, "\nGuC status 0x%08x:\n", tmp);
-	seq_printf(m, "\tBootrom status = 0x%x\n",
-		(tmp & GS_BOOTROM_MASK) >> GS_BOOTROM_SHIFT);
-	seq_printf(m, "\tuKernel status = 0x%x\n",
-		(tmp & GS_UKERNEL_MASK) >> GS_UKERNEL_SHIFT);
-	seq_printf(m, "\tMIA Core status = 0x%x\n",
-		(tmp & GS_MIA_MASK) >> GS_MIA_SHIFT);
-	seq_puts(m, "\nScratch registers:\n");
-	for (i = 0; i < 16; i++)
-		seq_printf(m, "\t%2d: \t0x%x\n", i, I915_READ(SOFT_SCRATCH(i)));
-
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		u32 tmp = I915_READ(GUC_STATUS);
+		u32 i;
+
+		seq_printf(m, "\nGuC status 0x%08x:\n", tmp);
+		seq_printf(m, "\tBootrom status = 0x%x\n",
+			   (tmp & GS_BOOTROM_MASK) >> GS_BOOTROM_SHIFT);
+		seq_printf(m, "\tuKernel status = 0x%x\n",
+			   (tmp & GS_UKERNEL_MASK) >> GS_UKERNEL_SHIFT);
+		seq_printf(m, "\tMIA Core status = 0x%x\n",
+			   (tmp & GS_MIA_MASK) >> GS_MIA_SHIFT);
+		seq_puts(m, "\nScratch registers:\n");
+		for (i = 0; i < 16; i++) {
+			seq_printf(m, "\t%2d: \t0x%x\n",
+				   i, I915_READ(SOFT_SCRATCH(i)));
+		}
+	}
 
 	return 0;
 }
@@ -2680,19 +2673,14 @@ static int i915_energy_uJ(struct seq_file *m, void *data)
 	if (INTEL_GEN(dev_priv) < 6)
 		return -ENODEV;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-
-	if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &power)) {
-		intel_runtime_pm_put(dev_priv, wakeref);
+	if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &power))
 		return -ENODEV;
-	}
 
 	units = (power & 0x1f00) >> 8;
-	power = I915_READ(MCH_SECP_NRG_STTS);
-	power = (1000000 * power) >> units; /* convert to uJ */
-
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref)
+		power = I915_READ(MCH_SECP_NRG_STTS);
 
+	power = (1000000 * power) >> units; /* convert to uJ */
 	seq_printf(m, "%llu", power);
 
 	return 0;
@@ -3268,22 +3256,20 @@ static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf,
 	struct seq_file *m = file->private_data;
 	struct drm_i915_private *dev_priv = m->private;
 	intel_wakeref_t wakeref;
-	int ret;
 	bool enable;
+	int ret;
 
 	ret = kstrtobool_from_user(ubuf, len, &enable);
 	if (ret < 0)
 		return ret;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-
-	if (!dev_priv->ipc_enabled && enable)
-		DRM_INFO("Enabling IPC: WM will be proper only after next commit\n");
-	dev_priv->wm.distrust_bios_wm = true;
-	dev_priv->ipc_enabled = enable;
-	intel_enable_ipc(dev_priv);
-
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		if (!dev_priv->ipc_enabled && enable)
+			DRM_INFO("Enabling IPC: WM will be proper only after next commit\n");
+		dev_priv->wm.distrust_bios_wm = true;
+		dev_priv->ipc_enabled = enable;
+		intel_enable_ipc(dev_priv);
+	}
 
 	return len;
 }
@@ -4123,16 +4109,13 @@ i915_cache_sharing_get(void *data, u64 *val)
 {
 	struct drm_i915_private *dev_priv = data;
 	intel_wakeref_t wakeref;
-	u32 snpcr;
+	u32 snpcr = 0;
 
 	if (!(IS_GEN_RANGE(dev_priv, 6, 7)))
 		return -ENODEV;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-
-	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
-
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref)
+		snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 
 	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
 
@@ -4144,7 +4127,6 @@ i915_cache_sharing_set(void *data, u64 val)
 {
 	struct drm_i915_private *dev_priv = data;
 	intel_wakeref_t wakeref;
-	u32 snpcr;
 
 	if (!(IS_GEN_RANGE(dev_priv, 6, 7)))
 		return -ENODEV;
@@ -4152,16 +4134,17 @@ i915_cache_sharing_set(void *data, u64 val)
 	if (val > 3)
 		return -EINVAL;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
 	DRM_DEBUG_DRIVER("Manually setting uncore sharing to %llu\n", val);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		u32 snpcr;
+
+		/* Update the cache sharing policy here as well */
+		snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
+		snpcr &= ~GEN6_MBC_SNPCR_MASK;
+		snpcr |= val << GEN6_MBC_SNPCR_SHIFT;
+		I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
+	}
 
-	/* Update the cache sharing policy here as well */
-	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
-	snpcr &= ~GEN6_MBC_SNPCR_MASK;
-	snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
-	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
-
-	intel_runtime_pm_put(dev_priv, wakeref);
 	return 0;
 }
 
@@ -4398,20 +4381,17 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
 	sseu.max_eus_per_subslice =
 		RUNTIME_INFO(dev_priv)->sseu.max_eus_per_subslice;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-
-	if (IS_CHERRYVIEW(dev_priv)) {
-		cherryview_sseu_device_status(dev_priv, &sseu);
-	} else if (IS_BROADWELL(dev_priv)) {
-		broadwell_sseu_device_status(dev_priv, &sseu);
-	} else if (IS_GEN(dev_priv, 9)) {
-		gen9_sseu_device_status(dev_priv, &sseu);
-	} else if (INTEL_GEN(dev_priv) >= 10) {
-		gen10_sseu_device_status(dev_priv, &sseu);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		if (IS_CHERRYVIEW(dev_priv))
+			cherryview_sseu_device_status(dev_priv, &sseu);
+		else if (IS_BROADWELL(dev_priv))
+			broadwell_sseu_device_status(dev_priv, &sseu);
+		else if (IS_GEN(dev_priv, 9))
+			gen9_sseu_device_status(dev_priv, &sseu);
+		else if (INTEL_GEN(dev_priv) >= 10)
+			gen10_sseu_device_status(dev_priv, &sseu);
 	}
 
-	intel_runtime_pm_put(dev_priv, wakeref);
-
 	i915_print_sseu_info(m, false, &sseu);
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 98a91df16392..67fd119bdad8 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -813,13 +813,13 @@ void i915_gem_flush_ggtt_writes(struct drm_i915_private *dev_priv)
 
 	i915_gem_chipset_flush(dev_priv);
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-	spin_lock_irq(&dev_priv->uncore.lock);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		spin_lock_irq(&dev_priv->uncore.lock);
 
-	POSTING_READ_FW(RING_HEAD(RENDER_RING_BASE));
+		POSTING_READ_FW(RING_HEAD(RENDER_RING_BASE));
 
-	spin_unlock_irq(&dev_priv->uncore.lock);
-	intel_runtime_pm_put(dev_priv, wakeref);
+		spin_unlock_irq(&dev_priv->uncore.lock);
+	}
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index e2c61633e95d..dbea14bf67cc 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2535,9 +2535,8 @@ static int ggtt_bind_vma(struct i915_vma *vma,
 	if (i915_gem_object_is_readonly(obj))
 		pte_flags |= PTE_READ_ONLY;
 
-	wakeref = intel_runtime_pm_get(i915);
-	vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
-	intel_runtime_pm_put(i915, wakeref);
+	with_intel_runtime_pm(i915, wakeref)
+		vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
 
 	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
 
@@ -2556,9 +2555,8 @@ static void ggtt_unbind_vma(struct i915_vma *vma)
 	struct drm_i915_private *i915 = vma->vm->i915;
 	intel_wakeref_t wakeref;
 
-	wakeref = intel_runtime_pm_get(i915);
-	vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
-	intel_runtime_pm_put(i915, wakeref);
+	with_intel_runtime_pm(i915, wakeref)
+		vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
 }
 
 static int aliasing_gtt_bind_vma(struct i915_vma *vma,
@@ -2592,9 +2590,10 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
 	if (flags & I915_VMA_GLOBAL_BIND) {
 		intel_wakeref_t wakeref;
 
-		wakeref = intel_runtime_pm_get(i915);
-		vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
-		intel_runtime_pm_put(i915, wakeref);
+		with_intel_runtime_pm(i915, wakeref) {
+			vma->vm->insert_entries(vma->vm, vma,
+						cache_level, pte_flags);
+		}
 	}
 
 	return 0;
@@ -2605,11 +2604,11 @@ static void aliasing_gtt_unbind_vma(struct i915_vma *vma)
 	struct drm_i915_private *i915 = vma->vm->i915;
 
 	if (vma->flags & I915_VMA_GLOBAL_BIND) {
+		struct i915_address_space *vm = vma->vm;
 		intel_wakeref_t wakeref;
 
-		wakeref = intel_runtime_pm_get(i915);
-		vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
-		intel_runtime_pm_put(i915, wakeref);
+		with_intel_runtime_pm(i915, wakeref)
+			vm->clear_range(vm, vma->node.start, vma->size);
 	}
 
 	if (vma->flags & I915_VMA_LOCAL_BIND) {
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index 7d1722f7299b..90603a921663 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -296,14 +296,14 @@ i915_gem_shrink(struct drm_i915_private *i915,
 unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
 {
 	intel_wakeref_t wakeref;
-	unsigned long freed;
+	unsigned long freed = 0;
 
-	wakeref = intel_runtime_pm_get(i915);
-	freed = i915_gem_shrink(i915, -1UL, NULL,
-				I915_SHRINK_BOUND |
-				I915_SHRINK_UNBOUND |
-				I915_SHRINK_ACTIVE);
-	intel_runtime_pm_put(i915, wakeref);
+	with_intel_runtime_pm(i915, wakeref) {
+		freed = i915_gem_shrink(i915, -1UL, NULL,
+					I915_SHRINK_BOUND |
+					I915_SHRINK_UNBOUND |
+					I915_SHRINK_ACTIVE);
+	}
 
 	return freed;
 }
@@ -376,14 +376,14 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
 	if (sc->nr_scanned < sc->nr_to_scan && current_is_kswapd()) {
 		intel_wakeref_t wakeref;
 
-		wakeref = intel_runtime_pm_get(i915);
-		freed += i915_gem_shrink(i915,
-					 sc->nr_to_scan - sc->nr_scanned,
-					 &sc->nr_scanned,
-					 I915_SHRINK_ACTIVE |
-					 I915_SHRINK_BOUND |
-					 I915_SHRINK_UNBOUND);
-		intel_runtime_pm_put(i915, wakeref);
+		with_intel_runtime_pm(i915, wakeref) {
+			freed += i915_gem_shrink(i915,
+						 sc->nr_to_scan - sc->nr_scanned,
+						 &sc->nr_scanned,
+						 I915_SHRINK_ACTIVE |
+						 I915_SHRINK_BOUND |
+						 I915_SHRINK_UNBOUND);
+		}
 	}
 
 	shrinker_unlock(i915, unlock);
@@ -425,11 +425,11 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
 	unsigned long unevictable, bound, unbound, freed_pages;
 	intel_wakeref_t wakeref;
 
-	wakeref = intel_runtime_pm_get(i915);
-	freed_pages = i915_gem_shrink(i915, -1UL, NULL,
-				      I915_SHRINK_BOUND |
-				      I915_SHRINK_UNBOUND);
-	intel_runtime_pm_put(i915, wakeref);
+	freed_pages = 0;
+	with_intel_runtime_pm(i915, wakeref)
+		freed_pages += i915_gem_shrink(i915, -1UL, NULL,
+					       I915_SHRINK_BOUND |
+					       I915_SHRINK_UNBOUND);
 
 	/* Because we may be allocating inside our own driver, we cannot
 	 * assert that there are no objects with pinned pages that are not
@@ -481,12 +481,11 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
 	if (ret)
 		goto out;
 
-	wakeref = intel_runtime_pm_get(i915);
-	freed_pages += i915_gem_shrink(i915, -1UL, NULL,
-				       I915_SHRINK_BOUND |
-				       I915_SHRINK_UNBOUND |
-				       I915_SHRINK_VMAPS);
-	intel_runtime_pm_put(i915, wakeref);
+	with_intel_runtime_pm(i915, wakeref)
+		freed_pages += i915_gem_shrink(i915, -1UL, NULL,
+					       I915_SHRINK_BOUND |
+					       I915_SHRINK_UNBOUND |
+					       I915_SHRINK_VMAPS);
 
 	/* We also want to clear any cached iomaps as they wrap vmap */
 	list_for_each_entry_safe(vma, next,
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index 3d43fc9dd25d..b1cb2d3cae16 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -230,14 +230,11 @@ frequency_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
 
 		val = dev_priv->gt_pm.rps.cur_freq;
 		if (dev_priv->gt.awake) {
-			intel_wakeref_t wakeref =
-				intel_runtime_pm_get_if_in_use(dev_priv);
+			intel_wakeref_t wakeref;
 
-			if (wakeref) {
+			with_intel_runtime_pm_if_in_use(dev_priv, wakeref)
 				val = intel_get_cagf(dev_priv,
 						     I915_READ_NOTRACE(GEN6_RPSTAT1));
-				intel_runtime_pm_put(dev_priv, wakeref);
-			}
 		}
 
 		add_sample_mult(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_ACT],
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 2cbbf165d179..41313005af42 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -43,11 +43,10 @@ static u32 calc_residency(struct drm_i915_private *dev_priv,
 			  i915_reg_t reg)
 {
 	intel_wakeref_t wakeref;
-	u64 res;
+	u64 res = 0;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-	res = intel_rc6_residency_us(dev_priv, reg);
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref)
+		res = intel_rc6_residency_us(dev_priv, reg);
 
 	return DIV_ROUND_CLOSEST_ULL(res, 1000);
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a1e4e1033289..93c86b19700e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -2187,6 +2187,14 @@ intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915);
 intel_wakeref_t intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915);
 intel_wakeref_t intel_runtime_pm_get_noresume(struct drm_i915_private *i915);
 
+#define with_intel_runtime_pm(i915, wf) \
+	for ((wf) = intel_runtime_pm_get(i915); (wf); \
+	     intel_runtime_pm_put(i915, (wf)), (wf) = 0)
+
+#define with_intel_runtime_pm_if_in_use(i915, wf) \
+	for ((wf) = intel_runtime_pm_get_if_in_use(i915); (wf); \
+	     intel_runtime_pm_put(i915, (wf)), (wf) = 0)
+
 void intel_runtime_pm_put_unchecked(struct drm_i915_private *i915);
 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 void intel_runtime_pm_put(struct drm_i915_private *i915, intel_wakeref_t wref);
diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c
index 20c0b36d748e..b53582c0c6c1 100644
--- a/drivers/gpu/drm/i915/intel_guc_log.c
+++ b/drivers/gpu/drm/i915/intel_guc_log.c
@@ -444,9 +444,8 @@ static void guc_log_capture_logs(struct intel_guc_log *log)
 	 * Generally device is expected to be active only at this
 	 * time, so get/put should be really quick.
 	 */
-	wakeref = intel_runtime_pm_get(dev_priv);
-	guc_action_flush_log_complete(guc);
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref)
+		guc_action_flush_log_complete(guc);
 }
 
 int intel_guc_log_create(struct intel_guc_log *log)
@@ -507,7 +506,7 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
 	struct intel_guc *guc = log_to_guc(log);
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
 	intel_wakeref_t wakeref;
-	int ret;
+	int ret = 0;
 
 	BUILD_BUG_ON(GUC_LOG_VERBOSITY_MIN != 0);
 	GEM_BUG_ON(!log->vma);
@@ -521,16 +520,14 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
 
 	mutex_lock(&dev_priv->drm.struct_mutex);
 
-	if (log->level == level) {
-		ret = 0;
+	if (log->level == level)
 		goto out_unlock;
-	}
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-	ret = guc_action_control_log(guc, GUC_LOG_LEVEL_IS_VERBOSE(level),
-				     GUC_LOG_LEVEL_IS_ENABLED(level),
-				     GUC_LOG_LEVEL_TO_VERBOSITY(level));
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref)
+		ret = guc_action_control_log(guc,
+					     GUC_LOG_LEVEL_IS_VERBOSE(level),
+					     GUC_LOG_LEVEL_IS_ENABLED(level),
+					     GUC_LOG_LEVEL_TO_VERBOSITY(level));
 	if (ret) {
 		DRM_DEBUG_DRIVER("guc_log_control action failed %d\n", ret);
 		goto out_unlock;
@@ -611,9 +608,8 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log)
 	 */
 	flush_work(&log->relay.flush_work);
 
-	wakeref = intel_runtime_pm_get(i915);
-	guc_action_flush_log(guc);
-	intel_runtime_pm_put(i915, wakeref);
+	with_intel_runtime_pm(i915, wakeref)
+		guc_action_flush_log(guc);
 
 	/* GuC would have updated log buffer by now, so capture it */
 	guc_log_capture_logs(log);
diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c
index 3e8c18b6a42d..9bd1c9002c2a 100644
--- a/drivers/gpu/drm/i915/intel_huc.c
+++ b/drivers/gpu/drm/i915/intel_huc.c
@@ -116,14 +116,13 @@ int intel_huc_check_status(struct intel_huc *huc)
 {
 	struct drm_i915_private *dev_priv = huc_to_i915(huc);
 	intel_wakeref_t wakeref;
-	bool status;
+	bool status = false;
 
 	if (!HAS_HUC(dev_priv))
 		return -ENODEV;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-	status = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED;
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref)
+		status = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED;
 
 	return status;
 }
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 93a2e4b5c54c..5a39a6347a7a 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1204,17 +1204,19 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
 	struct drm_device *dev = connector->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	intel_wakeref_t wakeref;
-	u32 hw_level;
-	int ret;
+	int ret = 0;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		u32 hw_level;
 
-	hw_level = intel_panel_get_backlight(connector);
-	ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
+		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 
-	drm_modeset_unlock(&dev->mode_config.connection_mutex);
-	intel_runtime_pm_put(dev_priv, wakeref);
+		hw_level = intel_panel_get_backlight(connector);
+		ret = scale_hw_to_user(connector,
+				       hw_level, bd->props.max_brightness);
+
+		drm_modeset_unlock(&dev->mode_config.connection_mutex);
+	}
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index d494d92da02c..681ea532585e 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1696,21 +1696,21 @@ int i915_reg_read_ioctl(struct drm_device *dev,
 
 	flags = reg->offset & (entry->size - 1);
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-	if (entry->size == 8 && flags == I915_REG_READ_8B_WA)
-		reg->val = I915_READ64_2x32(entry->offset_ldw,
-					    entry->offset_udw);
-	else if (entry->size == 8 && flags == 0)
-		reg->val = I915_READ64(entry->offset_ldw);
-	else if (entry->size == 4 && flags == 0)
-		reg->val = I915_READ(entry->offset_ldw);
-	else if (entry->size == 2 && flags == 0)
-		reg->val = I915_READ16(entry->offset_ldw);
-	else if (entry->size == 1 && flags == 0)
-		reg->val = I915_READ8(entry->offset_ldw);
-	else
-		ret = -EINVAL;
-	intel_runtime_pm_put(dev_priv, wakeref);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		if (entry->size == 8 && flags == I915_REG_READ_8B_WA)
+			reg->val = I915_READ64_2x32(entry->offset_ldw,
+						    entry->offset_udw);
+		else if (entry->size == 8 && flags == 0)
+			reg->val = I915_READ64(entry->offset_ldw);
+		else if (entry->size == 4 && flags == 0)
+			reg->val = I915_READ(entry->offset_ldw);
+		else if (entry->size == 2 && flags == 0)
+			reg->val = I915_READ16(entry->offset_ldw);
+		else if (entry->size == 1 && flags == 0)
+			reg->val = I915_READ8(entry->offset_ldw);
+		else
+			ret = -EINVAL;
+	}
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c
index 01a46c46fe25..e77b7ed449ae 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem.c
@@ -98,26 +98,22 @@ static void pm_suspend(struct drm_i915_private *i915)
 {
 	intel_wakeref_t wakeref;
 
-	wakeref = intel_runtime_pm_get(i915);
-
-	i915_gem_suspend_gtt_mappings(i915);
-	i915_gem_suspend_late(i915);
-
-	intel_runtime_pm_put(i915, wakeref);
+	with_intel_runtime_pm(i915, wakeref) {
+		i915_gem_suspend_gtt_mappings(i915);
+		i915_gem_suspend_late(i915);
+	}
 }
 
 static void pm_hibernate(struct drm_i915_private *i915)
 {
 	intel_wakeref_t wakeref;
 
-	wakeref = intel_runtime_pm_get(i915);
-
-	i915_gem_suspend_gtt_mappings(i915);
-
-	i915_gem_freeze(i915);
-	i915_gem_freeze_late(i915);
+	with_intel_runtime_pm(i915, wakeref) {
+		i915_gem_suspend_gtt_mappings(i915);
 
-	intel_runtime_pm_put(i915, wakeref);
+		i915_gem_freeze(i915);
+		i915_gem_freeze_late(i915);
+	}
 }
 
 static void pm_resume(struct drm_i915_private *i915)
@@ -128,13 +124,11 @@ static void pm_resume(struct drm_i915_private *i915)
 	 * Both suspend and hibernate follow the same wakeup path and assume
 	 * that runtime-pm just works.
 	 */
-	wakeref = intel_runtime_pm_get(i915);
-
-	intel_engines_sanitize(i915, false);
-	i915_gem_sanitize(i915);
-	i915_gem_resume(i915);
-
-	intel_runtime_pm_put(i915, wakeref);
+	with_intel_runtime_pm(i915, wakeref) {
+		intel_engines_sanitize(i915, false);
+		i915_gem_sanitize(i915);
+		i915_gem_resume(i915);
+	}
 }
 
 static int igt_gem_suspend(void *arg)
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
index 7a9b1f20b019..4cba50679607 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
@@ -610,9 +610,9 @@ static int igt_ctx_exec(void *arg)
 				}
 			}
 
-			wakeref = intel_runtime_pm_get(i915);
-			err = gpu_fill(obj, ctx, engine, dw);
-			intel_runtime_pm_put(i915, wakeref);
+			err = 0;
+			with_intel_runtime_pm(i915, wakeref)
+				err = gpu_fill(obj, ctx, engine, dw);
 			if (err) {
 				pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
 				       ndwords, dw, max_dwords(obj),
@@ -718,9 +718,9 @@ static int igt_ctx_readonly(void *arg)
 					i915_gem_object_set_readonly(obj);
 			}
 
-			wakeref = intel_runtime_pm_get(i915);
-			err = gpu_fill(obj, ctx, engine, dw);
-			intel_runtime_pm_put(i915, wakeref);
+			err = 0;
+			with_intel_runtime_pm(i915, wakeref)
+				err = gpu_fill(obj, ctx, engine, dw);
 			if (err) {
 				pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
 				       ndwords, dw, max_dwords(obj),
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
index 3575e1387c3f..395ae878e0f7 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
@@ -509,9 +509,8 @@ static void disable_retire_worker(struct drm_i915_private *i915)
 	if (!i915->gt.active_requests++) {
 		intel_wakeref_t wakeref;
 
-		wakeref = intel_runtime_pm_get(i915);
-		i915_gem_unpark(i915);
-		intel_runtime_pm_put(i915, wakeref);
+		with_intel_runtime_pm(i915, wakeref)
+			i915_gem_unpark(i915);
 	}
 	mutex_unlock(&i915->drm.struct_mutex);
 
@@ -593,10 +592,10 @@ static int igt_mmap_offset_exhaustion(void *arg)
 			goto out;
 		}
 
+		err = 0;
 		mutex_lock(&i915->drm.struct_mutex);
-		wakeref = intel_runtime_pm_get(i915);
-		err = make_obj_busy(obj);
-		intel_runtime_pm_put(i915, wakeref);
+		with_intel_runtime_pm(i915, wakeref)
+			err = make_obj_busy(obj);
 		mutex_unlock(&i915->drm.struct_mutex);
 		if (err) {
 			pr_err("[loop %d] Failed to busy the object\n", loop);
diff --git a/drivers/gpu/drm/i915/selftests/intel_workarounds.c b/drivers/gpu/drm/i915/selftests/intel_workarounds.c
index 75324b6249e3..9009d7b8b136 100644
--- a/drivers/gpu/drm/i915/selftests/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/selftests/intel_workarounds.c
@@ -93,9 +93,9 @@ read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
 	if (err)
 		goto err_obj;
 
-	wakeref = intel_runtime_pm_get(engine->i915);
-	rq = i915_request_alloc(engine, ctx);
-	intel_runtime_pm_put(engine->i915, wakeref);
+	rq = ERR_PTR(-ENODEV);
+	with_intel_runtime_pm(engine->i915, wakeref)
+		rq = i915_request_alloc(engine, ctx);
 	if (IS_ERR(rq)) {
 		err = PTR_ERR(rq);
 		goto err_pin;
@@ -236,14 +236,15 @@ switch_to_scratch_context(struct intel_engine_cs *engine,
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
-	wakeref = intel_runtime_pm_get(engine->i915);
-
-	if (spin)
-		rq = igt_spinner_create_request(spin, ctx, engine, MI_NOOP);
-	else
-		rq = i915_request_alloc(engine, ctx);
-
-	intel_runtime_pm_put(engine->i915, wakeref);
+	rq = ERR_PTR(-ENODEV);
+	with_intel_runtime_pm(engine->i915, wakeref) {
+		if (spin)
+			rq = igt_spinner_create_request(spin,
+							ctx, engine,
+							MI_NOOP);
+		else
+			rq = i915_request_alloc(engine, ctx);
+	}
 
 	kernel_context_close(ctx);
 
@@ -301,9 +302,8 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
 	if (err)
 		goto out;
 
-	wakeref = intel_runtime_pm_get(i915);
-	err = reset(engine);
-	intel_runtime_pm_put(i915, wakeref);
+	with_intel_runtime_pm(i915, wakeref)
+		err = reset(engine);
 
 	if (want_spin) {
 		igt_spinner_end(&spin);
-- 
2.20.1

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

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

* [PATCH 16/21] drm/i915: Markup paired operations on display power domains
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (14 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 15/21] drm/i915: Syntatic sugar for using intel_runtime_pm Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 15:51   ` Mika Kuoppala
  2019-01-10 10:11 ` [PATCH 17/21] drm/i915: Track the wakeref used to initialise " Chris Wilson
                   ` (7 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

The majority of runtime-pm operations are bounded and scoped within a
function; these are easy to verify that the wakeref are handled
correctly. We can employ the compiler to help us, and reduce the number
of wakerefs tracked when debugging, by passing around cookies provided
by the various rpm_get functions to their rpm_put counterpart. This
makes the pairing explicit, and given the required wakeref cookie the
compiler can verify that we pass an initialised value to the rpm_put
(quite handy for double checking error paths).

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c     | 35 ++++++------
 drivers/gpu/drm/i915/i915_drv.h         |  2 +
 drivers/gpu/drm/i915/i915_gem.c         |  4 +-
 drivers/gpu/drm/i915/icl_dsi.c          | 36 ++++++++-----
 drivers/gpu/drm/i915/intel_audio.c      |  3 +-
 drivers/gpu/drm/i915/intel_cdclk.c      | 10 ++--
 drivers/gpu/drm/i915/intel_crt.c        | 25 +++++----
 drivers/gpu/drm/i915/intel_csr.c        | 25 +++++++--
 drivers/gpu/drm/i915/intel_ddi.c        | 36 ++++++++-----
 drivers/gpu/drm/i915/intel_display.c    | 68 ++++++++++++++---------
 drivers/gpu/drm/i915/intel_dp.c         | 38 +++++++------
 drivers/gpu/drm/i915/intel_dpll_mgr.c   | 66 +++++++++++++++--------
 drivers/gpu/drm/i915/intel_drv.h        | 17 ++++--
 drivers/gpu/drm/i915/intel_dsi.h        |  1 +
 drivers/gpu/drm/i915/intel_hdmi.c       | 18 ++++---
 drivers/gpu/drm/i915/intel_i2c.c        | 20 +++----
 drivers/gpu/drm/i915/intel_lvds.c       |  8 +--
 drivers/gpu/drm/i915/intel_pipe_crc.c   |  6 ++-
 drivers/gpu/drm/i915/intel_pm.c         |  6 ++-
 drivers/gpu/drm/i915/intel_runtime_pm.c | 71 ++++++++++++++++---------
 drivers/gpu/drm/i915/intel_sprite.c     | 24 ++++++---
 drivers/gpu/drm/i915/intel_vdsc.c       |  4 +-
 drivers/gpu/drm/i915/vlv_dsi.c          | 14 +++--
 23 files changed, 347 insertions(+), 190 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 34cbd9a20583..b7dcacf2a5d3 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -626,10 +626,12 @@ static void gen8_display_interrupt_info(struct seq_file *m)
 
 	for_each_pipe(dev_priv, pipe) {
 		enum intel_display_power_domain power_domain;
+		intel_wakeref_t wakeref;
 
 		power_domain = POWER_DOMAIN_PIPE(pipe);
-		if (!intel_display_power_get_if_enabled(dev_priv,
-							power_domain)) {
+		wakeref = intel_display_power_get_if_enabled(dev_priv,
+							     power_domain);
+		if (!wakeref) {
 			seq_printf(m, "Pipe %c power disabled\n",
 				   pipe_name(pipe));
 			continue;
@@ -644,7 +646,7 @@ static void gen8_display_interrupt_info(struct seq_file *m)
 			   pipe_name(pipe),
 			   I915_READ(GEN8_DE_PIPE_IER(pipe)));
 
-		intel_display_power_put(dev_priv, power_domain);
+		intel_display_power_put(dev_priv, power_domain, wakeref);
 	}
 
 	seq_printf(m, "Display Engine port interrupt mask:\t%08x\n",
@@ -680,6 +682,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 	wakeref = intel_runtime_pm_get(dev_priv);
 
 	if (IS_CHERRYVIEW(dev_priv)) {
+		intel_wakeref_t pref;
+
 		seq_printf(m, "Master Interrupt Control:\t%08x\n",
 			   I915_READ(GEN8_MASTER_IRQ));
 
@@ -695,8 +699,9 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 			enum intel_display_power_domain power_domain;
 
 			power_domain = POWER_DOMAIN_PIPE(pipe);
-			if (!intel_display_power_get_if_enabled(dev_priv,
-								power_domain)) {
+			pref = intel_display_power_get_if_enabled(dev_priv,
+								  power_domain);
+			if (!pref) {
 				seq_printf(m, "Pipe %c power disabled\n",
 					   pipe_name(pipe));
 				continue;
@@ -706,17 +711,17 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 				   pipe_name(pipe),
 				   I915_READ(PIPESTAT(pipe)));
 
-			intel_display_power_put(dev_priv, power_domain);
+			intel_display_power_put(dev_priv, power_domain, pref);
 		}
 
-		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+		pref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 		seq_printf(m, "Port hotplug:\t%08x\n",
 			   I915_READ(PORT_HOTPLUG_EN));
 		seq_printf(m, "DPFLIPSTAT:\t%08x\n",
 			   I915_READ(VLV_DPFLIPSTAT));
 		seq_printf(m, "DPINVGTT:\t%08x\n",
 			   I915_READ(DPINVGTT));
-		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, pref);
 
 		for (i = 0; i < 4; i++) {
 			seq_printf(m, "GT Interrupt IMR %d:\t%08x\n",
@@ -779,10 +784,12 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 			   I915_READ(VLV_IMR));
 		for_each_pipe(dev_priv, pipe) {
 			enum intel_display_power_domain power_domain;
+			intel_wakeref_t pref;
 
 			power_domain = POWER_DOMAIN_PIPE(pipe);
-			if (!intel_display_power_get_if_enabled(dev_priv,
-								power_domain)) {
+			pref = intel_display_power_get_if_enabled(dev_priv,
+								  power_domain);
+			if (!pref) {
 				seq_printf(m, "Pipe %c power disabled\n",
 					   pipe_name(pipe));
 				continue;
@@ -791,7 +798,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 			seq_printf(m, "Pipe %c stat:\t%08x\n",
 				   pipe_name(pipe),
 				   I915_READ(PIPESTAT(pipe)));
-			intel_display_power_put(dev_priv, power_domain);
+			intel_display_power_put(dev_priv, power_domain, pref);
 		}
 
 		seq_printf(m, "Master IER:\t%08x\n",
@@ -1709,8 +1716,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
 	intel_wakeref_t wakeref;
 	bool sr_enabled = false;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
 	if (INTEL_GEN(dev_priv) >= 9)
 		/* no global SR status; inspect per-plane WM */;
@@ -1726,8 +1732,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
 	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
-	intel_runtime_pm_put(dev_priv, wakeref);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
 
 	seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f0a405604b75..44c1b21febba 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -344,6 +344,7 @@ struct intel_csr {
 	uint32_t mmiodata[8];
 	uint32_t dc_state;
 	uint32_t allowed_dc_mask;
+	intel_wakeref_t wakeref;
 };
 
 enum i915_cache_level {
@@ -1982,6 +1983,7 @@ struct drm_i915_private {
 		 * is a slight delay before we do so.
 		 */
 		intel_wakeref_t awake;
+		intel_wakeref_t power;
 
 		/**
 		 * The number of times we have woken up.
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 67fd119bdad8..5ed1c8576525 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -176,7 +176,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
 	if (INTEL_GEN(i915) >= 6)
 		gen6_rps_idle(i915);
 
-	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ);
+	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, i915->gt.power);
 
 	intel_runtime_pm_put(i915, wakeref);
 
@@ -221,7 +221,7 @@ void i915_gem_unpark(struct drm_i915_private *i915)
 	 * Work around it by grabbing a GT IRQ power domain whilst there is any
 	 * GT activity, preventing any DC state transitions.
 	 */
-	intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
+	i915->gt.power = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
 
 	if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */
 		i915->gt.epoch = 1;
diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
index 4dd793b78996..f3a5f03646ce 100644
--- a/drivers/gpu/drm/i915/icl_dsi.c
+++ b/drivers/gpu/drm/i915/icl_dsi.c
@@ -337,9 +337,11 @@ static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
 	}
 
 	for_each_dsi_port(port, intel_dsi->ports) {
-		intel_display_power_get(dev_priv, port == PORT_A ?
-					POWER_DOMAIN_PORT_DDI_A_IO :
-					POWER_DOMAIN_PORT_DDI_B_IO);
+		intel_dsi->io_wakeref[port] =
+			intel_display_power_get(dev_priv,
+						port == PORT_A ?
+						POWER_DOMAIN_PORT_DDI_A_IO :
+						POWER_DOMAIN_PORT_DDI_B_IO);
 	}
 }
 
@@ -1125,10 +1127,18 @@ static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
 	enum port port;
 	u32 tmp;
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_A_IO);
-
-	if (intel_dsi->dual_link)
-		intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_B_IO);
+	for_each_dsi_port(port, intel_dsi->ports) {
+		intel_wakeref_t wakeref;
+
+		wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]);
+		if (wakeref) {
+			intel_display_power_put(dev_priv,
+						port == PORT_A ?
+						POWER_DOMAIN_PORT_DDI_A_IO :
+						POWER_DOMAIN_PORT_DDI_B_IO,
+						wakeref);
+		}
+	}
 
 	/* set mode to DDI */
 	for_each_dsi_port(port, intel_dsi->ports) {
@@ -1229,13 +1239,15 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
-	u32 tmp;
-	enum port port;
 	enum transcoder dsi_trans;
+	intel_wakeref_t wakeref;
+	enum port port;
 	bool ret = false;
+	u32 tmp;
 
-	if (!intel_display_power_get_if_enabled(dev_priv,
-						encoder->power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     encoder->power_domain);
+	if (!wakeref)
 		return false;
 
 	for_each_dsi_port(port, intel_dsi->ports) {
@@ -1260,7 +1272,7 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
 		ret = tmp & PIPECONF_ENABLE;
 	}
 out:
-	intel_display_power_put(dev_priv, encoder->power_domain);
+	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 202a58cf2d9f..de26cd0a5497 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -748,7 +748,8 @@ static void i915_audio_component_get_power(struct device *kdev)
 
 static void i915_audio_component_put_power(struct device *kdev)
 {
-	intel_display_power_put(kdev_to_i915(kdev), POWER_DOMAIN_AUDIO);
+	intel_display_power_put_unchecked(kdev_to_i915(kdev),
+					  POWER_DOMAIN_AUDIO);
 }
 
 static void i915_audio_component_codec_wake_override(struct device *kdev,
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
index 2021e484a287..73cb7250118e 100644
--- a/drivers/gpu/drm/i915/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/intel_cdclk.c
@@ -520,6 +520,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
 {
 	int cdclk = cdclk_state->cdclk;
 	u32 val, cmd = cdclk_state->voltage_level;
+	intel_wakeref_t wakeref;
 
 	switch (cdclk) {
 	case 400000:
@@ -539,7 +540,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
 	 * a system suspend.  So grab the PIPE-A domain, which covers
 	 * the HW blocks needed for the following programming.
 	 */
-	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
 
 	mutex_lock(&dev_priv->pcu_lock);
 	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
@@ -593,7 +594,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
 
 	vlv_program_pfi_credits(dev_priv);
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A, wakeref);
 }
 
 static void chv_set_cdclk(struct drm_i915_private *dev_priv,
@@ -601,6 +602,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
 {
 	int cdclk = cdclk_state->cdclk;
 	u32 val, cmd = cdclk_state->voltage_level;
+	intel_wakeref_t wakeref;
 
 	switch (cdclk) {
 	case 333333:
@@ -619,7 +621,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
 	 * a system suspend.  So grab the PIPE-A domain, which covers
 	 * the HW blocks needed for the following programming.
 	 */
-	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
 
 	mutex_lock(&dev_priv->pcu_lock);
 	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
@@ -637,7 +639,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
 
 	vlv_program_pfi_credits(dev_priv);
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A, wakeref);
 }
 
 static int bdw_calc_cdclk(int min_cdclk)
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 951e9bae6921..33bd2addcbdd 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -83,15 +83,17 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+	intel_wakeref_t wakeref;
 	bool ret;
 
-	if (!intel_display_power_get_if_enabled(dev_priv,
-						encoder->power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     encoder->power_domain);
+	if (!wakeref)
 		return false;
 
 	ret = intel_crt_port_enabled(dev_priv, crt->adpa_reg, pipe);
 
-	intel_display_power_put(dev_priv, encoder->power_domain);
+	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
 	return ret;
 }
@@ -776,6 +778,7 @@ intel_crt_detect(struct drm_connector *connector,
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	struct intel_crt *crt = intel_attached_crt(connector);
 	struct intel_encoder *intel_encoder = &crt->base;
+	intel_wakeref_t wakeref;
 	int status, ret;
 	struct intel_load_detect_pipe tmp;
 
@@ -784,7 +787,8 @@ intel_crt_detect(struct drm_connector *connector,
 		      force);
 
 	if (i915_modparams.load_detect_test) {
-		intel_display_power_get(dev_priv, intel_encoder->power_domain);
+		wakeref = intel_display_power_get(dev_priv,
+						  intel_encoder->power_domain);
 		goto load_detect;
 	}
 
@@ -792,7 +796,8 @@ intel_crt_detect(struct drm_connector *connector,
 	if (dmi_check_system(intel_spurious_crt_detect))
 		return connector_status_disconnected;
 
-	intel_display_power_get(dev_priv, intel_encoder->power_domain);
+	wakeref = intel_display_power_get(dev_priv,
+					  intel_encoder->power_domain);
 
 	if (I915_HAS_HOTPLUG(dev_priv)) {
 		/* We can not rely on the HPD pin always being correctly wired
@@ -847,7 +852,7 @@ intel_crt_detect(struct drm_connector *connector,
 	}
 
 out:
-	intel_display_power_put(dev_priv, intel_encoder->power_domain);
+	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
 	return status;
 }
 
@@ -857,10 +862,12 @@ static int intel_crt_get_modes(struct drm_connector *connector)
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crt *crt = intel_attached_crt(connector);
 	struct intel_encoder *intel_encoder = &crt->base;
-	int ret;
+	intel_wakeref_t wakeref;
 	struct i2c_adapter *i2c;
+	int ret;
 
-	intel_display_power_get(dev_priv, intel_encoder->power_domain);
+	wakeref = intel_display_power_get(dev_priv,
+					  intel_encoder->power_domain);
 
 	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
 	ret = intel_crt_ddc_get_modes(connector, i2c);
@@ -872,7 +879,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
 	ret = intel_crt_ddc_get_modes(connector, i2c);
 
 out:
-	intel_display_power_put(dev_priv, intel_encoder->power_domain);
+	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
index a516697bf57d..ea5fb64d33dd 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -409,6 +409,21 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
 	return memcpy(dmc_payload, &fw->data[readcount], nbytes);
 }
 
+static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
+{
+	WARN_ON(dev_priv->csr.wakeref);
+	dev_priv->csr.wakeref =
+		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+}
+
+static void intel_csr_runtime_pm_put(struct drm_i915_private *dev_priv)
+{
+	intel_wakeref_t wakeref __maybe_unused =
+		fetch_and_zero(&dev_priv->csr.wakeref);
+
+	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
+}
+
 static void csr_load_work_fn(struct work_struct *work)
 {
 	struct drm_i915_private *dev_priv;
@@ -424,8 +439,7 @@ static void csr_load_work_fn(struct work_struct *work)
 
 	if (dev_priv->csr.dmc_payload) {
 		intel_csr_load_program(dev_priv);
-
-		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+		intel_csr_runtime_pm_put(dev_priv);
 
 		DRM_INFO("Finished loading DMC firmware %s (v%u.%u)\n",
 			 dev_priv->csr.fw_path,
@@ -467,7 +481,7 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
 	 * suspend as runtime suspend *requires* a working CSR for whatever
 	 * reason.
 	 */
-	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+	intel_csr_runtime_pm_get(dev_priv);
 
 	if (INTEL_GEN(dev_priv) >= 12) {
 		/* Allow to load fw via parameter using the last known size */
@@ -538,7 +552,7 @@ void intel_csr_ucode_suspend(struct drm_i915_private *dev_priv)
 
 	/* Drop the reference held in case DMC isn't loaded. */
 	if (!dev_priv->csr.dmc_payload)
-		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+		intel_csr_runtime_pm_put(dev_priv);
 }
 
 /**
@@ -558,7 +572,7 @@ void intel_csr_ucode_resume(struct drm_i915_private *dev_priv)
 	 * loaded.
 	 */
 	if (!dev_priv->csr.dmc_payload)
-		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+		intel_csr_runtime_pm_get(dev_priv);
 }
 
 /**
@@ -574,6 +588,7 @@ void intel_csr_ucode_fini(struct drm_i915_private *dev_priv)
 		return;
 
 	intel_csr_ucode_suspend(dev_priv);
+	WARN_ON(dev_priv->csr.wakeref);
 
 	kfree(dev_priv->csr.dmc_payload);
 }
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 2d6ed990a232..7f3cd055de50 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1860,12 +1860,14 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
 {
 	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	intel_wakeref_t wakeref;
 	enum pipe pipe = 0;
 	int ret = 0;
 	uint32_t tmp;
 
-	if (WARN_ON(!intel_display_power_get_if_enabled(dev_priv,
-						intel_encoder->power_domain)))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     intel_encoder->power_domain);
+	if (WARN_ON(!wakeref))
 		return -ENXIO;
 
 	if (WARN_ON(!intel_encoder->get_hw_state(intel_encoder, &pipe))) {
@@ -1880,7 +1882,7 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
 		tmp &= ~TRANS_DDI_HDCP_SIGNALLING;
 	I915_WRITE(TRANS_DDI_FUNC_CTL(pipe), tmp);
 out:
-	intel_display_power_put(dev_priv, intel_encoder->power_domain);
+	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
 	return ret;
 }
 
@@ -1891,13 +1893,15 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
 	struct intel_encoder *encoder = intel_connector->encoder;
 	int type = intel_connector->base.connector_type;
 	enum port port = encoder->port;
-	enum pipe pipe = 0;
 	enum transcoder cpu_transcoder;
+	intel_wakeref_t wakeref;
+	enum pipe pipe = 0;
 	uint32_t tmp;
 	bool ret;
 
-	if (!intel_display_power_get_if_enabled(dev_priv,
-						encoder->power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     encoder->power_domain);
+	if (!wakeref)
 		return false;
 
 	if (!encoder->get_hw_state(encoder, &pipe)) {
@@ -1939,7 +1943,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
 	}
 
 out:
-	intel_display_power_put(dev_priv, encoder->power_domain);
+	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
 	return ret;
 }
@@ -1950,6 +1954,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	enum port port = encoder->port;
+	intel_wakeref_t wakeref;
 	enum pipe p;
 	u32 tmp;
 	u8 mst_pipe_mask;
@@ -1957,8 +1962,9 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
 	*pipe_mask = 0;
 	*is_dp_mst = false;
 
-	if (!intel_display_power_get_if_enabled(dev_priv,
-						encoder->power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     encoder->power_domain);
+	if (!wakeref)
 		return;
 
 	tmp = I915_READ(DDI_BUF_CTL(port));
@@ -2029,7 +2035,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
 				  "(PHY_CTL %08x)\n", port_name(port), tmp);
 	}
 
-	intel_display_power_put(dev_priv, encoder->power_domain);
+	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 }
 
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
@@ -3286,7 +3292,8 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
 	intel_edp_panel_vdd_on(intel_dp);
 	intel_edp_panel_off(intel_dp);
 
-	intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain);
+	intel_display_power_put_unchecked(dev_priv,
+					  dig_port->ddi_io_power_domain);
 
 	intel_ddi_clk_disable(encoder);
 }
@@ -3306,7 +3313,8 @@ static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder,
 
 	intel_disable_ddi_buf(encoder, old_crtc_state);
 
-	intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain);
+	intel_display_power_put_unchecked(dev_priv,
+					  dig_port->ddi_io_power_domain);
 
 	intel_ddi_clk_disable(encoder);
 
@@ -3626,8 +3634,8 @@ intel_ddi_post_pll_disable(struct intel_encoder *encoder,
 
 	if (intel_crtc_has_dp_encoder(crtc_state) ||
 	    intel_port_is_tc(dev_priv, encoder->port))
-		intel_display_power_put(dev_priv,
-					intel_ddi_main_link_aux_domain(dig_port));
+		intel_display_power_put_unchecked(dev_priv,
+						  intel_ddi_main_link_aux_domain(dig_port));
 }
 
 void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b0b8f9ffd873..36c56d1637b8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1197,17 +1197,19 @@ void assert_pipe(struct drm_i915_private *dev_priv,
 	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
 								      pipe);
 	enum intel_display_power_domain power_domain;
+	intel_wakeref_t wakeref;
 
 	/* we keep both pipes enabled on 830 */
 	if (IS_I830(dev_priv))
 		state = true;
 
 	power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
-	if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (wakeref) {
 		u32 val = I915_READ(PIPECONF(cpu_transcoder));
 		cur_state = !!(val & PIPECONF_ENABLE);
 
-		intel_display_power_put(dev_priv, power_domain);
+		intel_display_power_put(dev_priv, power_domain, wakeref);
 	} else {
 		cur_state = false;
 	}
@@ -3412,6 +3414,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum intel_display_power_domain power_domain;
 	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+	intel_wakeref_t wakeref;
 	bool ret;
 	u32 val;
 
@@ -3421,7 +3424,8 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
 	 * display power wells.
 	 */
 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return false;
 
 	val = I915_READ(DSPCNTR(i9xx_plane));
@@ -3434,7 +3438,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
 		*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
 			DISPPLANE_SEL_PIPE_SHIFT;
 
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
@@ -6107,7 +6111,7 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
 	enum intel_display_power_domain domain;
 
 	for_each_power_domain(domain, domains)
-		intel_display_power_put(dev_priv, domain);
+		intel_display_power_put_unchecked(dev_priv, domain);
 }
 
 static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
@@ -6354,7 +6358,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
 
 	domains = intel_crtc->enabled_power_domains;
 	for_each_power_domain(domain, domains)
-		intel_display_power_put(dev_priv, domain);
+		intel_display_power_put_unchecked(dev_priv, domain);
 	intel_crtc->enabled_power_domains = 0;
 
 	dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
@@ -7966,11 +7970,13 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	enum intel_display_power_domain power_domain;
+	intel_wakeref_t wakeref;
 	uint32_t tmp;
 	bool ret;
 
 	power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return false;
 
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
@@ -8071,7 +8077,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 	ret = true;
 
 out:
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
@@ -9038,11 +9044,13 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	enum intel_display_power_domain power_domain;
+	intel_wakeref_t wakeref;
 	uint32_t tmp;
 	bool ret;
 
 	power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return false;
 
 	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
@@ -9125,7 +9133,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 	ret = true;
 
 out:
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
@@ -9734,7 +9742,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 
 out:
 	for_each_power_domain(power_domain, power_domain_mask)
-		intel_display_power_put(dev_priv, power_domain);
+		intel_display_power_put_unchecked(dev_priv, power_domain);
 
 	return active;
 }
@@ -9984,17 +9992,19 @@ static bool i845_cursor_get_hw_state(struct intel_plane *plane,
 {
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum intel_display_power_domain power_domain;
+	intel_wakeref_t wakeref;
 	bool ret;
 
 	power_domain = POWER_DOMAIN_PIPE(PIPE_A);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return false;
 
 	ret = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
 
 	*pipe = PIPE_A;
 
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
@@ -10217,6 +10227,7 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
 {
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum intel_display_power_domain power_domain;
+	intel_wakeref_t wakeref;
 	bool ret;
 	u32 val;
 
@@ -10226,7 +10237,8 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
 	 * display power wells.
 	 */
 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return false;
 
 	val = I915_READ(CURCNTR(plane->pipe));
@@ -10239,7 +10251,7 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
 		*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
 			MCURSOR_PIPE_SELECT_SHIFT;
 
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
@@ -12950,6 +12962,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 	struct drm_crtc *crtc;
 	struct intel_crtc *intel_crtc;
 	u64 put_domains[I915_MAX_PIPES] = {};
+	intel_wakeref_t wakeref = 0;
 	int i;
 
 	intel_atomic_commit_fence_wait(intel_state);
@@ -12957,7 +12970,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 	drm_atomic_helper_wait_for_dependencies(state);
 
 	if (intel_state->modeset)
-		intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
+		wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
 
 	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
 		old_intel_crtc_state = to_intel_crtc_state(old_crtc_state);
@@ -13094,7 +13107,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 		 * the culprit.
 		 */
 		intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
-		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
+		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, wakeref);
 	}
 
 	/*
@@ -15496,19 +15509,25 @@ void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv)
 
 void i915_redisable_vga(struct drm_i915_private *dev_priv)
 {
-	/* This function can be called both from intel_modeset_setup_hw_state or
+	intel_wakeref_t wakeref;
+
+	/*
+	 * This function can be called both from intel_modeset_setup_hw_state or
 	 * at a very early point in our resume sequence, where the power well
 	 * structures are not yet restored. Since this function is at a very
 	 * paranoid "someone might have enabled VGA while we were not looking"
 	 * level, just check if the power well is enabled instead of trying to
 	 * follow the "don't touch the power well if we don't need it" policy
-	 * the rest of the driver uses. */
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA))
+	 * the rest of the driver uses.
+	 */
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     POWER_DOMAIN_VGA);
+	if (!wakeref)
 		return;
 
 	i915_redisable_vga_power_on(dev_priv);
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_VGA, wakeref);
 }
 
 /* FIXME read out full plane state for all planes */
@@ -15808,12 +15827,13 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
 			     struct drm_modeset_acquire_ctx *ctx)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_crtc *crtc;
 	struct intel_crtc_state *crtc_state;
 	struct intel_encoder *encoder;
+	struct intel_crtc *crtc;
+	intel_wakeref_t wakeref;
 	int i;
 
-	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
 	intel_early_display_was(dev_priv);
 	intel_modeset_readout_hw_state(dev);
@@ -15883,7 +15903,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
 			modeset_put_power_domains(dev_priv, put_domains);
 	}
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
 
 	intel_fbc_init_pipe_state(dev_priv);
 }
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d3cd40e656fe..fc85fd77a661 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -621,8 +621,8 @@ static void pps_unlock(struct intel_dp *intel_dp)
 
 	mutex_unlock(&dev_priv->pps_mutex);
 
-	intel_display_power_put(dev_priv,
-				intel_aux_power_domain(dp_to_dig_port(intel_dp)));
+	intel_display_power_put_unchecked(dev_priv,
+					  intel_aux_power_domain(dp_to_dig_port(intel_dp)));
 }
 
 static void
@@ -2511,8 +2511,8 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 	if ((pp & PANEL_POWER_ON) == 0)
 		intel_dp->panel_power_off_time = ktime_get_boottime();
 
-	intel_display_power_put(dev_priv,
-				intel_aux_power_domain(intel_dig_port));
+	intel_display_power_put_unchecked(dev_priv,
+					  intel_aux_power_domain(intel_dig_port));
 }
 
 static void edp_panel_vdd_work(struct work_struct *__work)
@@ -2657,7 +2657,7 @@ static void edp_panel_off(struct intel_dp *intel_dp)
 	intel_dp->panel_power_off_time = ktime_get_boottime();
 
 	/* We got a reference when we enabled the VDD. */
-	intel_display_power_put(dev_priv, intel_aux_power_domain(dig_port));
+	intel_display_power_put_unchecked(dev_priv, intel_aux_power_domain(dig_port));
 }
 
 void intel_edp_panel_off(struct intel_dp *intel_dp)
@@ -2983,16 +2983,18 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	intel_wakeref_t wakeref;
 	bool ret;
 
-	if (!intel_display_power_get_if_enabled(dev_priv,
-						encoder->power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     encoder->power_domain);
+	if (!wakeref)
 		return false;
 
 	ret = intel_dp_port_enabled(dev_priv, intel_dp->output_reg,
 				    encoder->port, pipe);
 
-	intel_display_power_put(dev_priv, encoder->power_domain);
+	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
 	return ret;
 }
@@ -5365,12 +5367,13 @@ intel_dp_detect(struct drm_connector *connector,
 	enum drm_connector_status status;
 	enum intel_display_power_domain aux_domain =
 		intel_aux_power_domain(dig_port);
+	intel_wakeref_t wakeref;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, connector->name);
 	WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
 
-	intel_display_power_get(dev_priv, aux_domain);
+	wakeref = intel_display_power_get(dev_priv, aux_domain);
 
 	/* Can't disconnect eDP */
 	if (intel_dp_is_edp(intel_dp))
@@ -5436,7 +5439,7 @@ intel_dp_detect(struct drm_connector *connector,
 
 		ret = intel_dp_retrain_link(encoder, ctx);
 		if (ret) {
-			intel_display_power_put(dev_priv, aux_domain);
+			intel_display_power_put(dev_priv, aux_domain, wakeref);
 			return ret;
 		}
 	}
@@ -5460,7 +5463,7 @@ intel_dp_detect(struct drm_connector *connector,
 	if (status != connector_status_connected && !intel_dp->is_mst)
 		intel_dp_unset_edid(intel_dp);
 
-	intel_display_power_put(dev_priv, aux_domain);
+	intel_display_power_put(dev_priv, aux_domain, wakeref);
 	return status;
 }
 
@@ -5473,6 +5476,7 @@ intel_dp_force(struct drm_connector *connector)
 	struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
 	enum intel_display_power_domain aux_domain =
 		intel_aux_power_domain(dig_port);
+	intel_wakeref_t wakeref;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, connector->name);
@@ -5481,11 +5485,11 @@ intel_dp_force(struct drm_connector *connector)
 	if (connector->status != connector_status_connected)
 		return;
 
-	intel_display_power_get(dev_priv, aux_domain);
+	wakeref = intel_display_power_get(dev_priv, aux_domain);
 
 	intel_dp_set_edid(intel_dp);
 
-	intel_display_power_put(dev_priv, aux_domain);
+	intel_display_power_put(dev_priv, aux_domain, wakeref);
 }
 
 static int intel_dp_get_modes(struct drm_connector *connector)
@@ -5931,6 +5935,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	enum irqreturn ret = IRQ_NONE;
+	intel_wakeref_t wakeref;
 
 	if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {
 		/*
@@ -5953,8 +5958,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
 		return IRQ_NONE;
 	}
 
-	intel_display_power_get(dev_priv,
-				intel_aux_power_domain(intel_dig_port));
+	wakeref = intel_display_power_get(dev_priv,
+					  intel_aux_power_domain(intel_dig_port));
 
 	if (intel_dp->is_mst) {
 		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
@@ -5984,7 +5989,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
 
 put_power:
 	intel_display_power_put(dev_priv,
-				intel_aux_power_domain(intel_dig_port));
+				intel_aux_power_domain(intel_dig_port),
+				wakeref);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index d513ca875c67..04870e960537 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -345,9 +345,12 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
 				      struct intel_dpll_hw_state *hw_state)
 {
 	const enum intel_dpll_id id = pll->info->id;
+	intel_wakeref_t wakeref;
 	uint32_t val;
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     POWER_DOMAIN_PLLS);
+	if (!wakeref)
 		return false;
 
 	val = I915_READ(PCH_DPLL(id));
@@ -355,7 +358,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
 	hw_state->fp0 = I915_READ(PCH_FP0(id));
 	hw_state->fp1 = I915_READ(PCH_FP1(id));
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
 	return val & DPLL_VCO_ENABLE;
 }
@@ -509,15 +512,18 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
 				       struct intel_dpll_hw_state *hw_state)
 {
 	const enum intel_dpll_id id = pll->info->id;
+	intel_wakeref_t wakeref;
 	uint32_t val;
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     POWER_DOMAIN_PLLS);
+	if (!wakeref)
 		return false;
 
 	val = I915_READ(WRPLL_CTL(id));
 	hw_state->wrpll = val;
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
 	return val & WRPLL_PLL_ENABLE;
 }
@@ -526,15 +532,18 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
 				      struct intel_shared_dpll *pll,
 				      struct intel_dpll_hw_state *hw_state)
 {
+	intel_wakeref_t wakeref;
 	uint32_t val;
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     POWER_DOMAIN_PLLS);
+	if (!wakeref)
 		return false;
 
 	val = I915_READ(SPLL_CTL);
 	hw_state->spll = val;
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
 	return val & SPLL_PLL_ENABLE;
 }
@@ -989,9 +998,12 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
 	uint32_t val;
 	const struct skl_dpll_regs *regs = skl_dpll_regs;
 	const enum intel_dpll_id id = pll->info->id;
+	intel_wakeref_t wakeref;
 	bool ret;
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     POWER_DOMAIN_PLLS);
+	if (!wakeref)
 		return false;
 
 	ret = false;
@@ -1011,7 +1023,7 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
 	ret = true;
 
 out:
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
 	return ret;
 }
@@ -1020,12 +1032,15 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
 				       struct intel_shared_dpll *pll,
 				       struct intel_dpll_hw_state *hw_state)
 {
-	uint32_t val;
 	const struct skl_dpll_regs *regs = skl_dpll_regs;
 	const enum intel_dpll_id id = pll->info->id;
+	intel_wakeref_t wakeref;
+	uint32_t val;
 	bool ret;
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     POWER_DOMAIN_PLLS);
+	if (!wakeref)
 		return false;
 
 	ret = false;
@@ -1041,7 +1056,7 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
 	ret = true;
 
 out:
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
 	return ret;
 }
@@ -1579,14 +1594,17 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
 					struct intel_dpll_hw_state *hw_state)
 {
 	enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
-	uint32_t val;
-	bool ret;
+	intel_wakeref_t wakeref;
 	enum dpio_phy phy;
 	enum dpio_channel ch;
+	uint32_t val;
+	bool ret;
 
 	bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     POWER_DOMAIN_PLLS);
+	if (!wakeref)
 		return false;
 
 	ret = false;
@@ -1643,7 +1661,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
 	ret = true;
 
 out:
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
 	return ret;
 }
@@ -2091,10 +2109,13 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
 				     struct intel_dpll_hw_state *hw_state)
 {
 	const enum intel_dpll_id id = pll->info->id;
+	intel_wakeref_t wakeref;
 	uint32_t val;
 	bool ret;
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     POWER_DOMAIN_PLLS);
+	if (!wakeref)
 		return false;
 
 	ret = false;
@@ -2113,7 +2134,7 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
 	ret = true;
 
 out:
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 
 	return ret;
 }
@@ -2950,11 +2971,14 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
 				 struct intel_dpll_hw_state *hw_state)
 {
 	const enum intel_dpll_id id = pll->info->id;
-	uint32_t val;
-	enum port port;
+	intel_wakeref_t wakeref;
 	bool ret = false;
+	enum port port;
+	uint32_t val;
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     POWER_DOMAIN_PLLS);
+	if (!wakeref)
 		return false;
 
 	val = I915_READ(icl_pll_id_to_enable_reg(id));
@@ -3007,7 +3031,7 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
 
 	ret = true;
 out:
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 93c86b19700e..6fa1e6ff0e28 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -2118,12 +2118,21 @@ bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
 				    enum intel_display_power_domain domain);
 bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
 				      enum intel_display_power_domain domain);
-void intel_display_power_get(struct drm_i915_private *dev_priv,
-			     enum intel_display_power_domain domain);
-bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
 					enum intel_display_power_domain domain);
+intel_wakeref_t
+intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+				   enum intel_display_power_domain domain);
+void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
+				       enum intel_display_power_domain domain);
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 void intel_display_power_put(struct drm_i915_private *dev_priv,
-			     enum intel_display_power_domain domain);
+			     enum intel_display_power_domain domain,
+			     intel_wakeref_t wakeref);
+#else
+#define intel_display_power_put(i915, domain, wakeref) \
+	intel_display_power_put_unchecked(i915, domain)
+#endif
 void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
 			    u8 req_slices);
 
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index fc7a09049f81..df3d390e25fe 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -39,6 +39,7 @@ struct intel_dsi {
 	struct intel_encoder base;
 
 	struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS];
+	intel_wakeref_t io_wakeref[I915_MAX_PORTS];
 
 	/* GPIO Desc for CRC based Panel control */
 	struct gpio_desc *gpio_panel;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 14a0c28fe7c1..14727ac06f67 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1190,15 +1190,17 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	intel_wakeref_t wakeref;
 	bool ret;
 
-	if (!intel_display_power_get_if_enabled(dev_priv,
-						encoder->power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     encoder->power_domain);
+	if (!wakeref)
 		return false;
 
 	ret = intel_sdvo_port_enabled(dev_priv, intel_hdmi->hdmi_reg, pipe);
 
-	intel_display_power_put(dev_priv, encoder->power_domain);
+	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
 	return ret;
 }
@@ -1895,11 +1897,12 @@ intel_hdmi_set_edid(struct drm_connector *connector)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	intel_wakeref_t wakeref;
 	struct edid *edid;
 	bool connected = false;
 	struct i2c_adapter *i2c;
 
-	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
 	i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
 
@@ -1914,7 +1917,7 @@ intel_hdmi_set_edid(struct drm_connector *connector)
 
 	intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
 
 	to_intel_connector(connector)->detect_edid = edid;
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
@@ -1939,11 +1942,12 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
 	struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
+	intel_wakeref_t wakeref;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, connector->name);
 
-	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
 	if (IS_ICELAKE(dev_priv) &&
 	    !intel_digital_port_connected(encoder))
@@ -1955,7 +1959,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 		status = connector_status_connected;
 
 out:
-	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
 
 	if (status != connector_status_connected)
 		cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index c6159aff9dc8..4f6dc8c94634 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -697,12 +697,13 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
 static int
 gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
 {
-	struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
-					       adapter);
+	struct intel_gmbus *bus =
+		container_of(adapter, struct intel_gmbus, adapter);
 	struct drm_i915_private *dev_priv = bus->dev_priv;
+	intel_wakeref_t wakeref;
 	int ret;
 
-	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
 	if (bus->force_bit) {
 		ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
@@ -714,17 +715,16 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
 			bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
 	}
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
 
 	return ret;
 }
 
 int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
 {
-	struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
-					       adapter);
+	struct intel_gmbus *bus =
+		container_of(adapter, struct intel_gmbus, adapter);
 	struct drm_i915_private *dev_priv = bus->dev_priv;
-	int ret;
 	u8 cmd = DRM_HDCP_DDC_AKSV;
 	u8 buf[DRM_HDCP_KSV_LEN] = { 0 };
 	struct i2c_msg msgs[] = {
@@ -741,8 +741,10 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
 			.buf = buf,
 		}
 	};
+	intel_wakeref_t wakeref;
+	int ret;
 
-	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 	mutex_lock(&dev_priv->gmbus_mutex);
 
 	/*
@@ -753,7 +755,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
 	ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
 
 	mutex_unlock(&dev_priv->gmbus_mutex);
-	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 6adcc8d037bf..b01aacb5d73d 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -94,15 +94,17 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+	intel_wakeref_t wakeref;
 	bool ret;
 
-	if (!intel_display_power_get_if_enabled(dev_priv,
-						encoder->power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     encoder->power_domain);
+	if (!wakeref)
 		return false;
 
 	ret = intel_lvds_port_enabled(dev_priv, lvds_encoder->reg, pipe);
 
-	intel_display_power_put(dev_priv, encoder->power_domain);
+	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c
index bdabcfab8090..56d614b02302 100644
--- a/drivers/gpu/drm/i915/intel_pipe_crc.c
+++ b/drivers/gpu/drm/i915/intel_pipe_crc.c
@@ -589,6 +589,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
 	struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
 	enum intel_display_power_domain power_domain;
 	enum intel_pipe_crc_source source;
+	intel_wakeref_t wakeref;
 	u32 val = 0; /* shut up gcc */
 	int ret = 0;
 
@@ -598,7 +599,8 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
 	}
 
 	power_domain = POWER_DOMAIN_PIPE(crtc->index);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) {
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref) {
 		DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
 		return -EIO;
 	}
@@ -624,7 +626,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
 	pipe_crc->skipped = 0;
 
 out:
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 83b01cde8113..ab7257720c7e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3989,10 +3989,12 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	enum intel_display_power_domain power_domain;
 	enum pipe pipe = crtc->pipe;
+	intel_wakeref_t wakeref;
 	enum plane_id plane_id;
 
 	power_domain = POWER_DOMAIN_PIPE(pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return;
 
 	for_each_plane_id_on_crtc(crtc, plane_id)
@@ -4001,7 +4003,7 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
 					   &ddb_y[plane_id],
 					   &ddb_uv[plane_id]);
 
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 }
 
 void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index f585ef742efe..fd2fc10dd1e4 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -1867,18 +1867,19 @@ __intel_display_power_get_domain(struct drm_i915_private *dev_priv,
  * Any power domain reference obtained by this function must have a symmetric
  * call to intel_display_power_put() to release the reference again.
  */
-void intel_display_power_get(struct drm_i915_private *dev_priv,
-			     enum intel_display_power_domain domain)
+intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
+					enum intel_display_power_domain domain)
 {
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
-
-	intel_runtime_pm_get(dev_priv);
+	intel_wakeref_t wakeref = intel_runtime_pm_get(dev_priv);
 
 	mutex_lock(&power_domains->lock);
 
 	__intel_display_power_get_domain(dev_priv, domain);
 
 	mutex_unlock(&power_domains->lock);
+
+	return wakeref;
 }
 
 /**
@@ -1893,13 +1894,16 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
  * Any power domain reference obtained by this function must have a symmetric
  * call to intel_display_power_put() to release the reference again.
  */
-bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
-					enum intel_display_power_domain domain)
+intel_wakeref_t
+intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+				   enum intel_display_power_domain domain)
 {
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	intel_wakeref_t wakeref;
 	bool is_enabled;
 
-	if (!intel_runtime_pm_get_if_in_use(dev_priv))
+	wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
+	if (!wakeref)
 		return false;
 
 	mutex_lock(&power_domains->lock);
@@ -1913,23 +1917,16 @@ bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
 
 	mutex_unlock(&power_domains->lock);
 
-	if (!is_enabled)
-		intel_runtime_pm_put_unchecked(dev_priv);
+	if (!is_enabled) {
+		intel_runtime_pm_put(dev_priv, wakeref);
+		wakeref = 0;
+	}
 
-	return is_enabled;
+	return wakeref;
 }
 
-/**
- * intel_display_power_put - release a power domain reference
- * @dev_priv: i915 device instance
- * @domain: power domain to reference
- *
- * This function drops the power domain reference obtained by
- * intel_display_power_get() and might power down the corresponding hardware
- * block right away if this is the last reference.
- */
-void intel_display_power_put(struct drm_i915_private *dev_priv,
-			     enum intel_display_power_domain domain)
+static void __intel_display_power_put(struct drm_i915_private *dev_priv,
+				      enum intel_display_power_domain domain)
 {
 	struct i915_power_domains *power_domains;
 	struct i915_power_well *power_well;
@@ -1947,10 +1944,34 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
 		intel_power_well_put(dev_priv, power_well);
 
 	mutex_unlock(&power_domains->lock);
+}
 
+/**
+ * intel_display_power_put - release a power domain reference
+ * @dev_priv: i915 device instance
+ * @domain: power domain to reference
+ *
+ * This function drops the power domain reference obtained by
+ * intel_display_power_get() and might power down the corresponding hardware
+ * block right away if this is the last reference.
+ */
+void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
+				       enum intel_display_power_domain domain)
+{
+	__intel_display_power_put(dev_priv, domain);
 	intel_runtime_pm_put_unchecked(dev_priv);
 }
 
+#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
+void intel_display_power_put(struct drm_i915_private *dev_priv,
+			     enum intel_display_power_domain domain,
+			     intel_wakeref_t wakeref)
+{
+	__intel_display_power_put(dev_priv, domain);
+	intel_runtime_pm_put(dev_priv, wakeref);
+}
+#endif
+
 #define I830_PIPES_POWER_DOMAINS (		\
 	BIT_ULL(POWER_DOMAIN_PIPE_A) |		\
 	BIT_ULL(POWER_DOMAIN_PIPE_B) |		\
@@ -4060,7 +4081,7 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
 
 	/* Remove the refcount we took to keep power well support disabled. */
 	if (!i915_modparams.disable_power_well)
-		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
 
 	intel_power_domains_verify_state(dev_priv);
 }
@@ -4079,7 +4100,7 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
  */
 void intel_power_domains_enable(struct drm_i915_private *dev_priv)
 {
-	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
 
 	intel_power_domains_verify_state(dev_priv);
 }
@@ -4114,7 +4135,7 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
 {
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
 
-	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
 
 	/*
 	 * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
@@ -4135,7 +4156,7 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
 	 * power wells if power domains must be deinitialized for suspend.
 	 */
 	if (!i915_modparams.disable_power_well) {
-		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
 		intel_power_domains_verify_state(dev_priv);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 8f3982c03925..87a06fcca284 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -618,17 +618,19 @@ skl_plane_get_hw_state(struct intel_plane *plane,
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum intel_display_power_domain power_domain;
 	enum plane_id plane_id = plane->id;
+	intel_wakeref_t wakeref;
 	bool ret;
 
 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return false;
 
 	ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
 
 	*pipe = plane->pipe;
 
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
@@ -882,17 +884,19 @@ vlv_plane_get_hw_state(struct intel_plane *plane,
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum intel_display_power_domain power_domain;
 	enum plane_id plane_id = plane->id;
+	intel_wakeref_t wakeref;
 	bool ret;
 
 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return false;
 
 	ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
 
 	*pipe = plane->pipe;
 
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
@@ -1051,17 +1055,19 @@ ivb_plane_get_hw_state(struct intel_plane *plane,
 {
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum intel_display_power_domain power_domain;
+	intel_wakeref_t wakeref;
 	bool ret;
 
 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return false;
 
 	ret =  I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
 
 	*pipe = plane->pipe;
 
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
@@ -1217,17 +1223,19 @@ g4x_plane_get_hw_state(struct intel_plane *plane,
 {
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum intel_display_power_domain power_domain;
+	intel_wakeref_t wakeref;
 	bool ret;
 
 	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return false;
 
 	ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
 
 	*pipe = plane->pipe;
 
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_vdsc.c b/drivers/gpu/drm/i915/intel_vdsc.c
index 48537827616f..23abf03736e7 100644
--- a/drivers/gpu/drm/i915/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/intel_vdsc.c
@@ -1082,6 +1082,6 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
 	I915_WRITE(dss_ctl2_reg, dss_ctl2_val);
 
 	/* Disable Power wells for VDSC/joining */
-	intel_display_power_put(dev_priv,
-				intel_dsc_power_domain(old_crtc_state));
+	intel_display_power_put_unchecked(dev_priv,
+					  intel_dsc_power_domain(old_crtc_state));
 }
diff --git a/drivers/gpu/drm/i915/vlv_dsi.c b/drivers/gpu/drm/i915/vlv_dsi.c
index bb1287020f80..d116fead8514 100644
--- a/drivers/gpu/drm/i915/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/vlv_dsi.c
@@ -959,13 +959,15 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	intel_wakeref_t wakeref;
 	enum port port;
 	bool active = false;
 
 	DRM_DEBUG_KMS("\n");
 
-	if (!intel_display_power_get_if_enabled(dev_priv,
-						encoder->power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv,
+						     encoder->power_domain);
+	if (!wakeref)
 		return false;
 
 	/*
@@ -1021,7 +1023,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
 	}
 
 out_put_power:
-	intel_display_power_put(dev_priv, encoder->power_domain);
+	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
 
 	return active;
 }
@@ -1574,6 +1576,7 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
 	enum drm_panel_orientation orientation;
 	struct intel_plane *plane;
 	struct intel_crtc *crtc;
+	intel_wakeref_t wakeref;
 	enum pipe pipe;
 	u32 val;
 
@@ -1584,7 +1587,8 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
 	plane = to_intel_plane(crtc->base.primary);
 
 	power_domain = POWER_DOMAIN_PIPE(pipe);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
+	if (!wakeref)
 		return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
 
 	val = I915_READ(DSPCNTR(plane->i9xx_plane));
@@ -1596,7 +1600,7 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
 	else
 		orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
 
-	intel_display_power_put(dev_priv, power_domain);
+	intel_display_power_put(dev_priv, power_domain, wakeref);
 
 	return orientation;
 }
-- 
2.20.1

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

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

* [PATCH 17/21] drm/i915: Track the wakeref used to initialise display power domains
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (15 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 16/21] drm/i915: Markup paired operations on display power domains Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-10 23:15   ` John Harrison
  2019-01-11 13:09   ` Mika Kuoppala
  2019-01-10 10:11 ` [PATCH 18/21] drm/i915: Combined gt.awake/gt.power wakerefs Chris Wilson
                   ` (6 subsequent siblings)
  23 siblings, 2 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

On module load and unload, we grab the POWER_DOMAIN_INIT powerwells and
transfer them to the runtime-pm code. We can use our wakeref tracking to
verify that the wakeref is indeed passed from init to enable, and
disable to fini; and across suspend.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c     |   3 +
 drivers/gpu/drm/i915/i915_drv.h         |   2 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 151 +++++++++++++-----------
 3 files changed, 88 insertions(+), 68 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index b7dcacf2a5d3..96717a23b32f 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2699,6 +2699,9 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
 	if (!HAS_RUNTIME_PM(dev_priv))
 		seq_puts(m, "Runtime power management not supported\n");
 
+	seq_printf(m, "Runtime power management: %s\n",
+		   enableddisabled(!dev_priv->power_domains.wakeref));
+
 	seq_printf(m, "GPU idle: %s (epoch %u)\n",
 		   yesno(!dev_priv->gt.awake), dev_priv->gt.epoch);
 	seq_printf(m, "IRQs disabled: %s\n",
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 44c1b21febba..259b91b62ff2 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -822,6 +822,8 @@ struct i915_power_domains {
 	bool display_core_suspended;
 	int power_well_count;
 
+	intel_wakeref_t wakeref;
+
 	struct mutex lock;
 	int domain_use_count[POWER_DOMAIN_NUM];
 	struct i915_power_well *power_wells;
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index fd2fc10dd1e4..8d38f3e7fad1 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -4009,7 +4009,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
 
 /**
  * intel_power_domains_init_hw - initialize hardware power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  * @resume: Called from resume code paths or not
  *
  * This function initializes the hardware power domain state and enables all
@@ -4023,30 +4023,31 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
  * intel_power_domains_enable()) and must be paired with
  * intel_power_domains_fini_hw().
  */
-void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
+void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)
 {
-	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_domains *power_domains = &i915->power_domains;
 
 	power_domains->initializing = true;
 
-	if (IS_ICELAKE(dev_priv)) {
-		icl_display_core_init(dev_priv, resume);
-	} else if (IS_CANNONLAKE(dev_priv)) {
-		cnl_display_core_init(dev_priv, resume);
-	} else if (IS_GEN9_BC(dev_priv)) {
-		skl_display_core_init(dev_priv, resume);
-	} else if (IS_GEN9_LP(dev_priv)) {
-		bxt_display_core_init(dev_priv, resume);
-	} else if (IS_CHERRYVIEW(dev_priv)) {
+	if (IS_ICELAKE(i915)) {
+		icl_display_core_init(i915, resume);
+	} else if (IS_CANNONLAKE(i915)) {
+		cnl_display_core_init(i915, resume);
+	} else if (IS_GEN9_BC(i915)) {
+		skl_display_core_init(i915, resume);
+	} else if (IS_GEN9_LP(i915)) {
+		bxt_display_core_init(i915, resume);
+	} else if (IS_CHERRYVIEW(i915)) {
 		mutex_lock(&power_domains->lock);
-		chv_phy_control_init(dev_priv);
+		chv_phy_control_init(i915);
 		mutex_unlock(&power_domains->lock);
-	} else if (IS_VALLEYVIEW(dev_priv)) {
+	} else if (IS_VALLEYVIEW(i915)) {
 		mutex_lock(&power_domains->lock);
-		vlv_cmnlane_wa(dev_priv);
+		vlv_cmnlane_wa(i915);
 		mutex_unlock(&power_domains->lock);
-	} else if (IS_IVYBRIDGE(dev_priv) || INTEL_GEN(dev_priv) >= 7)
-		intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
+	} else if (IS_IVYBRIDGE(i915) || INTEL_GEN(i915) >= 7) {
+		intel_pch_reset_handshake(i915, !HAS_PCH_NOP(i915));
+	}
 
 	/*
 	 * Keep all power wells enabled for any dependent HW access during
@@ -4054,18 +4055,20 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
 	 * resources powered until display HW readout is complete. We drop
 	 * this reference in intel_power_domains_enable().
 	 */
-	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+	power_domains->wakeref =
+		intel_display_power_get(i915, POWER_DOMAIN_INIT);
+
 	/* Disable power support if the user asked so. */
 	if (!i915_modparams.disable_power_well)
-		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
-	intel_power_domains_sync_hw(dev_priv);
+		intel_display_power_get(i915, POWER_DOMAIN_INIT);
+	intel_power_domains_sync_hw(i915);
 
 	power_domains->initializing = false;
 }
 
 /**
  * intel_power_domains_fini_hw - deinitialize hw power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * De-initializes the display power domain HW state. It also ensures that the
  * device stays powered up so that the driver can be reloaded.
@@ -4074,21 +4077,24 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
  * intel_power_domains_disable()) and must be paired with
  * intel_power_domains_init_hw().
  */
-void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
+void intel_power_domains_fini_hw(struct drm_i915_private *i915)
 {
-	/* Keep the power well enabled, but cancel its rpm wakeref. */
-	intel_runtime_pm_put_unchecked(dev_priv);
+	intel_wakeref_t wakeref __maybe_unused =
+		fetch_and_zero(&i915->power_domains.wakeref);
 
 	/* Remove the refcount we took to keep power well support disabled. */
 	if (!i915_modparams.disable_power_well)
-		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
+		intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
+
+	intel_power_domains_verify_state(i915);
 
-	intel_power_domains_verify_state(dev_priv);
+	/* Keep the power well enabled, but cancel its rpm wakeref. */
+	intel_runtime_pm_put(i915, wakeref);
 }
 
 /**
  * intel_power_domains_enable - enable toggling of display power wells
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * Enable the ondemand enabling/disabling of the display power wells. Note that
  * power wells not belonging to POWER_DOMAIN_INIT are allowed to be toggled
@@ -4098,30 +4104,36 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
  * of display HW readout (which will acquire the power references reflecting
  * the current HW state).
  */
-void intel_power_domains_enable(struct drm_i915_private *dev_priv)
+void intel_power_domains_enable(struct drm_i915_private *i915)
 {
-	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
+	intel_wakeref_t wakeref __maybe_unused =
+		fetch_and_zero(&i915->power_domains.wakeref);
 
-	intel_power_domains_verify_state(dev_priv);
+	intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
+	intel_power_domains_verify_state(i915);
 }
 
 /**
  * intel_power_domains_disable - disable toggling of display power wells
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * Disable the ondemand enabling/disabling of the display power wells. See
  * intel_power_domains_enable() for which power wells this call controls.
  */
-void intel_power_domains_disable(struct drm_i915_private *dev_priv)
+void intel_power_domains_disable(struct drm_i915_private *i915)
 {
-	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+	struct i915_power_domains *power_domains = &i915->power_domains;
 
-	intel_power_domains_verify_state(dev_priv);
+	WARN_ON(power_domains->wakeref);
+	power_domains->wakeref =
+		intel_display_power_get(i915, POWER_DOMAIN_INIT);
+
+	intel_power_domains_verify_state(i915);
 }
 
 /**
  * intel_power_domains_suspend - suspend power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  * @suspend_mode: specifies the target suspend state (idle, mem, hibernation)
  *
  * This function prepares the hardware power domain state before entering
@@ -4130,12 +4142,14 @@ void intel_power_domains_disable(struct drm_i915_private *dev_priv)
  * It must be called with power domains already disabled (after a call to
  * intel_power_domains_disable()) and paired with intel_power_domains_resume().
  */
-void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
+void intel_power_domains_suspend(struct drm_i915_private *i915,
 				 enum i915_drm_suspend_mode suspend_mode)
 {
-	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_domains *power_domains = &i915->power_domains;
+	intel_wakeref_t wakeref __maybe_unused =
+		fetch_and_zero(&power_domains->wakeref);
 
-	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
+	intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
 
 	/*
 	 * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
@@ -4144,10 +4158,10 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
 	 * resources as required and also enable deeper system power states
 	 * that would be blocked if the firmware was inactive.
 	 */
-	if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
+	if (!(i915->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
 	    suspend_mode == I915_DRM_SUSPEND_IDLE &&
-	    dev_priv->csr.dmc_payload != NULL) {
-		intel_power_domains_verify_state(dev_priv);
+	    i915->csr.dmc_payload) {
+		intel_power_domains_verify_state(i915);
 		return;
 	}
 
@@ -4156,25 +4170,25 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
 	 * power wells if power domains must be deinitialized for suspend.
 	 */
 	if (!i915_modparams.disable_power_well) {
-		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
-		intel_power_domains_verify_state(dev_priv);
+		intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
+		intel_power_domains_verify_state(i915);
 	}
 
-	if (IS_ICELAKE(dev_priv))
-		icl_display_core_uninit(dev_priv);
-	else if (IS_CANNONLAKE(dev_priv))
-		cnl_display_core_uninit(dev_priv);
-	else if (IS_GEN9_BC(dev_priv))
-		skl_display_core_uninit(dev_priv);
-	else if (IS_GEN9_LP(dev_priv))
-		bxt_display_core_uninit(dev_priv);
+	if (IS_ICELAKE(i915))
+		icl_display_core_uninit(i915);
+	else if (IS_CANNONLAKE(i915))
+		cnl_display_core_uninit(i915);
+	else if (IS_GEN9_BC(i915))
+		skl_display_core_uninit(i915);
+	else if (IS_GEN9_LP(i915))
+		bxt_display_core_uninit(i915);
 
 	power_domains->display_core_suspended = true;
 }
 
 /**
  * intel_power_domains_resume - resume power domain state
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * This function resume the hardware power domain state during system resume.
  *
@@ -4182,28 +4196,30 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
  * intel_power_domains_enable()) and must be paired with
  * intel_power_domains_suspend().
  */
-void intel_power_domains_resume(struct drm_i915_private *dev_priv)
+void intel_power_domains_resume(struct drm_i915_private *i915)
 {
-	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_domains *power_domains = &i915->power_domains;
 
 	if (power_domains->display_core_suspended) {
-		intel_power_domains_init_hw(dev_priv, true);
+		intel_power_domains_init_hw(i915, true);
 		power_domains->display_core_suspended = false;
 	} else {
-		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+		WARN_ON(power_domains->wakeref);
+		power_domains->wakeref =
+			intel_display_power_get(i915, POWER_DOMAIN_INIT);
 	}
 
-	intel_power_domains_verify_state(dev_priv);
+	intel_power_domains_verify_state(i915);
 }
 
 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 
-static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
+static void intel_power_domains_dump_info(struct drm_i915_private *i915)
 {
-	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_domains *power_domains = &i915->power_domains;
 	struct i915_power_well *power_well;
 
-	for_each_power_well(dev_priv, power_well) {
+	for_each_power_well(i915, power_well) {
 		enum intel_display_power_domain domain;
 
 		DRM_DEBUG_DRIVER("%-25s %d\n",
@@ -4218,7 +4234,7 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
 
 /**
  * intel_power_domains_verify_state - verify the HW/SW state for all power wells
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
  *
  * Verify if the reference count of each power well matches its HW enabled
  * state and the total refcount of the domains it belongs to. This must be
@@ -4226,22 +4242,21 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
  * acquiring reference counts for any power wells in use and disabling the
  * ones left on by BIOS but not required by any active output.
  */
-static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
+static void intel_power_domains_verify_state(struct drm_i915_private *i915)
 {
-	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_domains *power_domains = &i915->power_domains;
 	struct i915_power_well *power_well;
 	bool dump_domain_info;
 
 	mutex_lock(&power_domains->lock);
 
 	dump_domain_info = false;
-	for_each_power_well(dev_priv, power_well) {
+	for_each_power_well(i915, power_well) {
 		enum intel_display_power_domain domain;
 		int domains_count;
 		bool enabled;
 
-		enabled = power_well->desc->ops->is_enabled(dev_priv,
-							    power_well);
+		enabled = power_well->desc->ops->is_enabled(i915, power_well);
 		if ((power_well->count || power_well->desc->always_on) !=
 		    enabled)
 			DRM_ERROR("power well %s state mismatch (refcount %d/enabled %d)",
@@ -4265,7 +4280,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
 		static bool dumped;
 
 		if (!dumped) {
-			intel_power_domains_dump_info(dev_priv);
+			intel_power_domains_dump_info(i915);
 			dumped = true;
 		}
 	}
@@ -4275,7 +4290,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
 
 #else
 
-static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
+static void intel_power_domains_verify_state(struct drm_i915_private *i915)
 {
 }
 
-- 
2.20.1

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

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

* [PATCH 18/21] drm/i915: Combined gt.awake/gt.power wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (16 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 17/21] drm/i915: Track the wakeref used to initialise " Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-14 14:20   ` Mika Kuoppala
  2019-01-10 10:11 ` [PATCH 19/21] drm/i915/dp: Markup pps lock power well Chris Wilson
                   ` (5 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

As the GT_IRQ power domain implies a wakeref, we can use it inplace of
our existing redundant rpm grab.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h                  |  1 -
 drivers/gpu/drm/i915/i915_gem.c                  | 11 ++++-------
 drivers/gpu/drm/i915/intel_lrc.c                 |  2 +-
 drivers/gpu/drm/i915/selftests/mock_gem_device.c |  1 +
 4 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 259b91b62ff2..25941c649282 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1985,7 +1985,6 @@ struct drm_i915_private {
 		 * is a slight delay before we do so.
 		 */
 		intel_wakeref_t awake;
-		intel_wakeref_t power;
 
 		/**
 		 * The number of times we have woken up.
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 5ed1c8576525..0bfed33178e1 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -176,9 +176,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
 	if (INTEL_GEN(i915) >= 6)
 		gen6_rps_idle(i915);
 
-	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, i915->gt.power);
-
-	intel_runtime_pm_put(i915, wakeref);
+	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, wakeref);
 
 	return i915->gt.epoch;
 }
@@ -203,13 +201,11 @@ void i915_gem_unpark(struct drm_i915_private *i915)
 
 	lockdep_assert_held(&i915->drm.struct_mutex);
 	GEM_BUG_ON(!i915->gt.active_requests);
+	assert_rpm_wakelock_held(i915);
 
 	if (i915->gt.awake)
 		return;
 
-	i915->gt.awake = intel_runtime_pm_get_noresume(i915);
-	GEM_BUG_ON(!i915->gt.awake);
-
 	/*
 	 * It seems that the DMC likes to transition between the DC states a lot
 	 * when there are no connected displays (no active power domains) during
@@ -221,7 +217,8 @@ void i915_gem_unpark(struct drm_i915_private *i915)
 	 * Work around it by grabbing a GT IRQ power domain whilst there is any
 	 * GT activity, preventing any DC state transitions.
 	 */
-	i915->gt.power = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
+	i915->gt.awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
+	GEM_BUG_ON(!i915->gt.awake);
 
 	if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */
 		i915->gt.epoch = 1;
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 1effbf49fa08..608458b92db3 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1045,7 +1045,7 @@ static void execlists_submission_tasklet(unsigned long data)
 
 	GEM_TRACE("%s awake?=%d, active=%x\n",
 		  engine->name,
-		  engine->i915->gt.awake,
+		  !!engine->i915->gt.awake,
 		  engine->execlists.active);
 
 	spin_lock_irqsave(&engine->timeline.lock, flags);
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index 082809569681..2c55e0fa64c9 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -164,6 +164,7 @@ struct drm_i915_private *mock_gem_device(void)
 	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	if (pm_runtime_enabled(&pdev->dev))
 		WARN_ON(pm_runtime_get_sync(&pdev->dev));
+	disable_rpm_wakeref_asserts(i915);
 
 	err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev);
 	if (err) {
-- 
2.20.1

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

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

* [PATCH 19/21] drm/i915/dp: Markup pps lock power well
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (17 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 18/21] drm/i915: Combined gt.awake/gt.power wakerefs Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-11  0:16   ` John Harrison
  2019-01-10 10:11 ` [PATCH 20/21] drm/i915: Complain if hsw_get_pipe_config acquires the same power well twice Chris Wilson
                   ` (4 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Track where and when we acquire and release the power well for pps
access along the dp aux link, with a view to detecting if we leak any
wakerefs.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 231 +++++++++++++++++---------------
 1 file changed, 121 insertions(+), 110 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index fc85fd77a661..db0f3a4402f5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -601,30 +601,39 @@ intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
 static void
 intel_dp_pps_init(struct intel_dp *intel_dp);
 
-static void pps_lock(struct intel_dp *intel_dp)
+static intel_wakeref_t
+pps_lock(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	intel_wakeref_t wakeref;
 
 	/*
 	 * See intel_power_sequencer_reset() why we need
 	 * a power domain reference here.
 	 */
-	intel_display_power_get(dev_priv,
-				intel_aux_power_domain(dp_to_dig_port(intel_dp)));
+	wakeref = intel_display_power_get(dev_priv,
+					  intel_aux_power_domain(dp_to_dig_port(intel_dp)));
 
 	mutex_lock(&dev_priv->pps_mutex);
+
+	return wakeref;
 }
 
-static void pps_unlock(struct intel_dp *intel_dp)
+static intel_wakeref_t
+pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
 	mutex_unlock(&dev_priv->pps_mutex);
-
-	intel_display_power_put_unchecked(dev_priv,
-					  intel_aux_power_domain(dp_to_dig_port(intel_dp)));
+	intel_display_power_put(dev_priv,
+				intel_aux_power_domain(dp_to_dig_port(intel_dp)),
+				wakeref);
+	return 0;
 }
 
+#define with_pps_lock(dp, wf) \
+	for (wf = pps_lock(dp); wf; wf = pps_unlock(dp, wf))
+
 static void
 vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 {
@@ -973,30 +982,30 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp),
 						 edp_notifier);
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	intel_wakeref_t wakeref;
 
 	if (!intel_dp_is_edp(intel_dp) || code != SYS_RESTART)
 		return 0;
 
-	pps_lock(intel_dp);
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
-		i915_reg_t pp_ctrl_reg, pp_div_reg;
-		u32 pp_div;
-
-		pp_ctrl_reg = PP_CONTROL(pipe);
-		pp_div_reg  = PP_DIVISOR(pipe);
-		pp_div = I915_READ(pp_div_reg);
-		pp_div &= PP_REFERENCE_DIVIDER_MASK;
-
-		/* 0x1F write to PP_DIV_REG sets max cycle delay */
-		I915_WRITE(pp_div_reg, pp_div | 0x1F);
-		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
-		msleep(intel_dp->panel_power_cycle_delay);
+	with_pps_lock(intel_dp, wakeref) {
+		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+			enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
+			i915_reg_t pp_ctrl_reg, pp_div_reg;
+			u32 pp_div;
+
+			pp_ctrl_reg = PP_CONTROL(pipe);
+			pp_div_reg  = PP_DIVISOR(pipe);
+			pp_div = I915_READ(pp_div_reg);
+			pp_div &= PP_REFERENCE_DIVIDER_MASK;
+
+			/* 0x1F write to PP_DIV_REG sets max cycle delay */
+			I915_WRITE(pp_div_reg, pp_div | 0x1F);
+			I915_WRITE(pp_ctrl_reg,
+				   PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
+			msleep(intel_dp->panel_power_cycle_delay);
+		}
 	}
 
-	pps_unlock(intel_dp);
-
 	return 0;
 }
 
@@ -1184,16 +1193,17 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 			to_i915(intel_dig_port->base.base.dev);
 	i915_reg_t ch_ctl, ch_data[5];
 	uint32_t aux_clock_divider;
+	intel_wakeref_t wakeref;
 	int i, ret, recv_bytes;
-	uint32_t status;
 	int try, clock = 0;
+	uint32_t status;
 	bool vdd;
 
 	ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
 	for (i = 0; i < ARRAY_SIZE(ch_data); i++)
 		ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
 
-	pps_lock(intel_dp);
+	wakeref = pps_lock(intel_dp);
 
 	/*
 	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
@@ -1337,7 +1347,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	if (vdd)
 		edp_panel_vdd_off(intel_dp, false);
 
-	pps_unlock(intel_dp);
+	pps_unlock(intel_dp, wakeref);
 
 	return ret;
 }
@@ -2464,15 +2474,15 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
  */
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
+	intel_wakeref_t wakeref;
 	bool vdd;
 
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	pps_lock(intel_dp);
-	vdd = edp_panel_vdd_on(intel_dp);
-	pps_unlock(intel_dp);
-
+	vdd = false;
+	with_pps_lock(intel_dp, wakeref)
+		vdd = edp_panel_vdd_on(intel_dp);
 	I915_STATE_WARN(!vdd, "eDP port %c VDD already requested on\n",
 	     port_name(dp_to_dig_port(intel_dp)->base.port));
 }
@@ -2517,13 +2527,15 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 
 static void edp_panel_vdd_work(struct work_struct *__work)
 {
-	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
-						 struct intel_dp, panel_vdd_work);
+	struct intel_dp *intel_dp =
+		container_of(to_delayed_work(__work),
+			     struct intel_dp, panel_vdd_work);
+	intel_wakeref_t wakeref;
 
-	pps_lock(intel_dp);
-	if (!intel_dp->want_panel_vdd)
-		edp_panel_vdd_off_sync(intel_dp);
-	pps_unlock(intel_dp);
+	with_pps_lock(intel_dp, wakeref) {
+		if (!intel_dp->want_panel_vdd)
+			edp_panel_vdd_off_sync(intel_dp);
+	}
 }
 
 static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
@@ -2613,12 +2625,13 @@ static void edp_panel_on(struct intel_dp *intel_dp)
 
 void intel_edp_panel_on(struct intel_dp *intel_dp)
 {
+	intel_wakeref_t wakeref;
+
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	pps_lock(intel_dp);
-	edp_panel_on(intel_dp);
-	pps_unlock(intel_dp);
+	with_pps_lock(intel_dp, wakeref)
+		edp_panel_on(intel_dp);
 }
 
 
@@ -2662,20 +2675,20 @@ static void edp_panel_off(struct intel_dp *intel_dp)
 
 void intel_edp_panel_off(struct intel_dp *intel_dp)
 {
+	intel_wakeref_t wakeref;
+
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	pps_lock(intel_dp);
-	edp_panel_off(intel_dp);
-	pps_unlock(intel_dp);
+	with_pps_lock(intel_dp, wakeref)
+		edp_panel_off(intel_dp);
 }
 
 /* Enable backlight in the panel power control. */
 static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	u32 pp;
-	i915_reg_t pp_ctrl_reg;
+	intel_wakeref_t wakeref;
 
 	/*
 	 * If we enable the backlight right away following a panel power
@@ -2685,17 +2698,16 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
 	 */
 	wait_backlight_on(intel_dp);
 
-	pps_lock(intel_dp);
+	with_pps_lock(intel_dp, wakeref) {
+		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+		u32 pp;
 
-	pp = ironlake_get_pp_control(intel_dp);
-	pp |= EDP_BLC_ENABLE;
-
-	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-
-	I915_WRITE(pp_ctrl_reg, pp);
-	POSTING_READ(pp_ctrl_reg);
+		pp = ironlake_get_pp_control(intel_dp);
+		pp |= EDP_BLC_ENABLE;
 
-	pps_unlock(intel_dp);
+		I915_WRITE(pp_ctrl_reg, pp);
+		POSTING_READ(pp_ctrl_reg);
+	}
 }
 
 /* Enable backlight PWM and backlight PP control. */
@@ -2717,23 +2729,21 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
 static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	u32 pp;
-	i915_reg_t pp_ctrl_reg;
+	intel_wakeref_t wakeref;
 
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	pps_lock(intel_dp);
-
-	pp = ironlake_get_pp_control(intel_dp);
-	pp &= ~EDP_BLC_ENABLE;
-
-	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+	with_pps_lock(intel_dp, wakeref) {
+		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+		u32 pp;
 
-	I915_WRITE(pp_ctrl_reg, pp);
-	POSTING_READ(pp_ctrl_reg);
+		pp = ironlake_get_pp_control(intel_dp);
+		pp &= ~EDP_BLC_ENABLE;
 
-	pps_unlock(intel_dp);
+		I915_WRITE(pp_ctrl_reg, pp);
+		POSTING_READ(pp_ctrl_reg);
+	}
 
 	intel_dp->last_backlight_off = jiffies;
 	edp_wait_backlight_off(intel_dp);
@@ -2761,12 +2771,12 @@ static void intel_edp_backlight_power(struct intel_connector *connector,
 				      bool enable)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
+	intel_wakeref_t wakeref;
 	bool is_enabled;
 
-	pps_lock(intel_dp);
-	is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
-	pps_unlock(intel_dp);
-
+	is_enabled = false;
+	with_pps_lock(intel_dp, wakeref)
+		is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
 	if (is_enabled == enable)
 		return;
 
@@ -3276,22 +3286,21 @@ static void intel_enable_dp(struct intel_encoder *encoder,
 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
 	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 	enum pipe pipe = crtc->pipe;
+	intel_wakeref_t wakeref;
 
 	if (WARN_ON(dp_reg & DP_PORT_EN))
 		return;
 
-	pps_lock(intel_dp);
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		vlv_init_panel_power_sequencer(encoder, pipe_config);
-
-	intel_dp_enable_port(intel_dp, pipe_config);
+	with_pps_lock(intel_dp, wakeref) {
+		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+			vlv_init_panel_power_sequencer(encoder, pipe_config);
 
-	edp_panel_vdd_on(intel_dp);
-	edp_panel_on(intel_dp);
-	edp_panel_vdd_off(intel_dp, true);
+		intel_dp_enable_port(intel_dp, pipe_config);
 
-	pps_unlock(intel_dp);
+		edp_panel_vdd_on(intel_dp);
+		edp_panel_on(intel_dp);
+		edp_panel_vdd_off(intel_dp, true);
+	}
 
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		unsigned int lane_mask = 0x0;
@@ -3989,9 +3998,10 @@ intel_dp_link_down(struct intel_encoder *encoder,
 	intel_dp->DP = DP;
 
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		pps_lock(intel_dp);
-		intel_dp->active_pipe = INVALID_PIPE;
-		pps_unlock(intel_dp);
+		intel_wakeref_t wakeref;
+
+		with_pps_lock(intel_dp, wakeref)
+			intel_dp->active_pipe = INVALID_PIPE;
 	}
 }
 
@@ -5561,14 +5571,15 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder)
 
 	intel_dp_mst_encoder_cleanup(intel_dig_port);
 	if (intel_dp_is_edp(intel_dp)) {
+		intel_wakeref_t wakeref;
+
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
 		/*
 		 * vdd might still be enabled do to the delayed vdd off.
 		 * Make sure vdd is actually turned off here.
 		 */
-		pps_lock(intel_dp);
-		edp_panel_vdd_off_sync(intel_dp);
-		pps_unlock(intel_dp);
+		with_pps_lock(intel_dp, wakeref)
+			edp_panel_vdd_off_sync(intel_dp);
 
 		if (intel_dp->edp_notifier.notifier_call) {
 			unregister_reboot_notifier(&intel_dp->edp_notifier);
@@ -5590,6 +5601,7 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	intel_wakeref_t wakeref;
 
 	if (!intel_dp_is_edp(intel_dp))
 		return;
@@ -5599,9 +5611,8 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 	 * Make sure vdd is actually turned off here.
 	 */
 	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-	pps_lock(intel_dp);
-	edp_panel_vdd_off_sync(intel_dp);
-	pps_unlock(intel_dp);
+	with_pps_lock(intel_dp, wakeref)
+		edp_panel_vdd_off_sync(intel_dp);
 }
 
 static
@@ -5882,6 +5893,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp);
+	intel_wakeref_t wakeref;
 
 	if (!HAS_DDI(dev_priv))
 		intel_dp->DP = I915_READ(intel_dp->output_reg);
@@ -5891,18 +5903,19 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 
 	intel_dp->reset_link_params = true;
 
-	pps_lock(intel_dp);
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		intel_dp->active_pipe = vlv_active_pipe(intel_dp);
+	with_pps_lock(intel_dp, wakeref) {
+		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+			intel_dp->active_pipe = vlv_active_pipe(intel_dp);
 
-	if (intel_dp_is_edp(intel_dp)) {
-		/* Reinit the power sequencer, in case BIOS did something with it. */
-		intel_dp_pps_init(intel_dp);
-		intel_edp_panel_vdd_sanitize(intel_dp);
+		if (intel_dp_is_edp(intel_dp)) {
+			/*
+			 * Reinit the power sequencer, in case BIOS did
+			 * something nasty with it.
+			 */
+			intel_dp_pps_init(intel_dp);
+			intel_edp_panel_vdd_sanitize(intel_dp);
+		}
 	}
-
-	pps_unlock(intel_dp);
 }
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
@@ -6698,8 +6711,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	struct drm_display_mode *downclock_mode = NULL;
 	bool has_dpcd;
 	struct drm_display_mode *scan;
-	struct edid *edid;
 	enum pipe pipe = INVALID_PIPE;
+	intel_wakeref_t wakeref;
+	struct edid *edid;
 
 	if (!intel_dp_is_edp(intel_dp))
 		return true;
@@ -6719,13 +6733,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 		return false;
 	}
 
-	pps_lock(intel_dp);
-
-	intel_dp_init_panel_power_timestamps(intel_dp);
-	intel_dp_pps_init(intel_dp);
-	intel_edp_panel_vdd_sanitize(intel_dp);
-
-	pps_unlock(intel_dp);
+	with_pps_lock(intel_dp, wakeref) {
+		intel_dp_init_panel_power_timestamps(intel_dp);
+		intel_dp_pps_init(intel_dp);
+		intel_edp_panel_vdd_sanitize(intel_dp);
+	}
 
 	/* Cache DPCD and EDID for edp. */
 	has_dpcd = intel_edp_init_dpcd(intel_dp);
@@ -6810,9 +6822,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	 * vdd might still be enabled do to the delayed vdd off.
 	 * Make sure vdd is actually turned off here.
 	 */
-	pps_lock(intel_dp);
-	edp_panel_vdd_off_sync(intel_dp);
-	pps_unlock(intel_dp);
+	with_pps_lock(intel_dp, wakeref)
+		edp_panel_vdd_off_sync(intel_dp);
 
 	return false;
 }
-- 
2.20.1

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

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

* [PATCH 20/21] drm/i915: Complain if hsw_get_pipe_config acquires the same power well twice
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (18 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 19/21] drm/i915/dp: Markup pps lock power well Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-11 13:47   ` Mika Kuoppala
  2019-01-10 10:11 ` [PATCH 21/21] drm/i915: Mark up Ironlake ips with rpm wakerefs Chris Wilson
                   ` (3 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

As we only release each power well once, we assume that each transcoder
maps to a different domain. Complain if this is not so.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 36c56d1637b8..7c974cf064fd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9569,6 +9569,8 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
 	power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
 	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
 		return false;
+
+	WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
 	*power_domain_mask |= BIT_ULL(power_domain);
 
 	tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
@@ -9596,6 +9598,8 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
 		power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
 		if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
 			continue;
+
+		WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
 		*power_domain_mask |= BIT_ULL(power_domain);
 
 		/*
@@ -9712,7 +9716,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 
 	power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
 	if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
+		WARN_ON(power_domain_mask & BIT_ULL(power_domain));
 		power_domain_mask |= BIT_ULL(power_domain);
+
 		if (INTEL_GEN(dev_priv) >= 9)
 			skylake_get_pfit_config(crtc, pipe_config);
 		else
-- 
2.20.1

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

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

* [PATCH 21/21] drm/i915: Mark up Ironlake ips with rpm wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (19 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 20/21] drm/i915: Complain if hsw_get_pipe_config acquires the same power well twice Chris Wilson
@ 2019-01-10 10:11 ` Chris Wilson
  2019-01-11 21:05   ` John Harrison
  2019-01-14 15:01   ` Mika Kuoppala
  2019-01-10 11:47 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/21] drm/i915: Track all held " Patchwork
                   ` (2 subsequent siblings)
  23 siblings, 2 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 10:11 UTC (permalink / raw)
  To: intel-gfx; +Cc: Jani Nikula

Currently Ironlake operates under the assumption that rpm awake (and its
error checking is disabled). As such, we have missed a few places where we
access registers without taking the rpm wakeref and thus trigger
warnings. intel_ips being one culprit.

As this involved adding a potentially sleeping rpm_get, we have to
rearrange the spinlocks slightly and so switch to acquiring a device-ref
under the spinlock rather than hold the spinlock for the whole
operation. To be consistent, we make the change in pattern common to the
intel_ips interface even though this adds a few more atomic operations
than necessary in a few cases.

v2: Sagar noted the mb around setting mch_dev were overkill as we only
need ordering there, and that i915_emon_status was still using
struct_mutex for no reason, but lacked rpm.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c |  32 ++----
 drivers/gpu/drm/i915/i915_drv.c     |   3 +
 drivers/gpu/drm/i915/intel_pm.c     | 172 ++++++++++++++--------------
 3 files changed, 102 insertions(+), 105 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 96717a23b32f..c0263c233faa 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1741,32 +1741,24 @@ static int i915_sr_status(struct seq_file *m, void *unused)
 
 static int i915_emon_status(struct seq_file *m, void *unused)
 {
-	struct drm_i915_private *dev_priv = node_to_i915(m->private);
-	struct drm_device *dev = &dev_priv->drm;
-	unsigned long temp, chipset, gfx;
+	struct drm_i915_private *i915 = node_to_i915(m->private);
 	intel_wakeref_t wakeref;
-	int ret;
 
-	if (!IS_GEN(dev_priv, 5))
+	if (!IS_GEN(i915, 5))
 		return -ENODEV;
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
+	with_intel_runtime_pm(i915, wakeref) {
+		unsigned long temp, chipset, gfx;
 
-	wakeref = intel_runtime_pm_get(dev_priv);
-
-	temp = i915_mch_val(dev_priv);
-	chipset = i915_chipset_val(dev_priv);
-	gfx = i915_gfx_val(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
+		temp = i915_mch_val(i915);
+		chipset = i915_chipset_val(i915);
+		gfx = i915_gfx_val(i915);
 
-	intel_runtime_pm_put(dev_priv, wakeref);
-
-	seq_printf(m, "GMCH temp: %ld\n", temp);
-	seq_printf(m, "Chipset power: %ld\n", chipset);
-	seq_printf(m, "GFX power: %ld\n", gfx);
-	seq_printf(m, "Total power: %ld\n", chipset + gfx);
+		seq_printf(m, "GMCH temp: %ld\n", temp);
+		seq_printf(m, "Chipset power: %ld\n", chipset);
+		seq_printf(m, "GFX power: %ld\n", gfx);
+		seq_printf(m, "Total power: %ld\n", chipset + gfx);
+	}
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 5731f992cf44..dafbbfadd1ad 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1780,6 +1780,9 @@ void i915_driver_unload(struct drm_device *dev)
 
 	i915_driver_unregister(dev_priv);
 
+	/* Flush any external code that still may be under the RCU lock */
+	synchronize_rcu();
+
 	if (i915_gem_suspend(dev_priv))
 		DRM_ERROR("failed to idle hardware; continuing to unload!\n");
 
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ab7257720c7e..7613ae72df3d 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -6203,10 +6203,6 @@ void intel_init_ipc(struct drm_i915_private *dev_priv)
  */
 DEFINE_SPINLOCK(mchdev_lock);
 
-/* Global for IPS driver to get at the current i915 device. Protected by
- * mchdev_lock. */
-static struct drm_i915_private *i915_mch_dev;
-
 bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val)
 {
 	u16 rgvswctl;
@@ -7849,16 +7845,17 @@ static unsigned long __i915_chipset_val(struct drm_i915_private *dev_priv)
 
 unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
 {
-	unsigned long val;
+	intel_wakeref_t wakeref;
+	unsigned long val = 0;
 
 	if (!IS_GEN(dev_priv, 5))
 		return 0;
 
-	spin_lock_irq(&mchdev_lock);
-
-	val = __i915_chipset_val(dev_priv);
-
-	spin_unlock_irq(&mchdev_lock);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		spin_lock_irq(&mchdev_lock);
+		val = __i915_chipset_val(dev_priv);
+		spin_unlock_irq(&mchdev_lock);
+	}
 
 	return val;
 }
@@ -7935,14 +7932,16 @@ static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
 
 void i915_update_gfx_val(struct drm_i915_private *dev_priv)
 {
+	intel_wakeref_t wakeref;
+
 	if (!IS_GEN(dev_priv, 5))
 		return;
 
-	spin_lock_irq(&mchdev_lock);
-
-	__i915_update_gfx_val(dev_priv);
-
-	spin_unlock_irq(&mchdev_lock);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		spin_lock_irq(&mchdev_lock);
+		__i915_update_gfx_val(dev_priv);
+		spin_unlock_irq(&mchdev_lock);
+	}
 }
 
 static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
@@ -7984,18 +7983,34 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
 
 unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
 {
-	unsigned long val;
+	intel_wakeref_t wakeref;
+	unsigned long val = 0;
 
 	if (!IS_GEN(dev_priv, 5))
 		return 0;
 
-	spin_lock_irq(&mchdev_lock);
+	with_intel_runtime_pm(dev_priv, wakeref) {
+		spin_lock_irq(&mchdev_lock);
+		val = __i915_gfx_val(dev_priv);
+		spin_unlock_irq(&mchdev_lock);
+	}
 
-	val = __i915_gfx_val(dev_priv);
+	return val;
+}
 
-	spin_unlock_irq(&mchdev_lock);
+static struct drm_i915_private *i915_mch_dev;
 
-	return val;
+static struct drm_i915_private *mchdev_get(void)
+{
+	struct drm_i915_private *i915;
+
+	rcu_read_lock();
+	i915 = i915_mch_dev;
+	if (!kref_get_unless_zero(&i915->drm.ref))
+		i915 = NULL;
+	rcu_read_unlock();
+
+	return i915;
 }
 
 /**
@@ -8006,23 +8021,24 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
  */
 unsigned long i915_read_mch_val(void)
 {
-	struct drm_i915_private *dev_priv;
-	unsigned long chipset_val, graphics_val, ret = 0;
-
-	spin_lock_irq(&mchdev_lock);
-	if (!i915_mch_dev)
-		goto out_unlock;
-	dev_priv = i915_mch_dev;
-
-	chipset_val = __i915_chipset_val(dev_priv);
-	graphics_val = __i915_gfx_val(dev_priv);
+	struct drm_i915_private *i915;
+	unsigned long chipset_val = 0;
+	unsigned long graphics_val = 0;
+	intel_wakeref_t wakeref;
 
-	ret = chipset_val + graphics_val;
+	i915 = mchdev_get();
+	if (!i915)
+		return 0;
 
-out_unlock:
-	spin_unlock_irq(&mchdev_lock);
+	with_intel_runtime_pm(i915, wakeref) {
+		spin_lock_irq(&mchdev_lock);
+		chipset_val = __i915_chipset_val(i915);
+		graphics_val = __i915_gfx_val(i915);
+		spin_unlock_irq(&mchdev_lock);
+	}
 
-	return ret;
+	drm_dev_put(&i915->drm);
+	return chipset_val + graphics_val;
 }
 EXPORT_SYMBOL_GPL(i915_read_mch_val);
 
@@ -8033,23 +8049,19 @@ EXPORT_SYMBOL_GPL(i915_read_mch_val);
  */
 bool i915_gpu_raise(void)
 {
-	struct drm_i915_private *dev_priv;
-	bool ret = true;
-
-	spin_lock_irq(&mchdev_lock);
-	if (!i915_mch_dev) {
-		ret = false;
-		goto out_unlock;
-	}
-	dev_priv = i915_mch_dev;
+	struct drm_i915_private *i915;
 
-	if (dev_priv->ips.max_delay > dev_priv->ips.fmax)
-		dev_priv->ips.max_delay--;
+	i915 = mchdev_get();
+	if (!i915)
+		return false;
 
-out_unlock:
+	spin_lock_irq(&mchdev_lock);
+	if (i915->ips.max_delay > i915->ips.fmax)
+		i915->ips.max_delay--;
 	spin_unlock_irq(&mchdev_lock);
 
-	return ret;
+	drm_dev_put(&i915->drm);
+	return true;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_raise);
 
@@ -8061,23 +8073,19 @@ EXPORT_SYMBOL_GPL(i915_gpu_raise);
  */
 bool i915_gpu_lower(void)
 {
-	struct drm_i915_private *dev_priv;
-	bool ret = true;
-
-	spin_lock_irq(&mchdev_lock);
-	if (!i915_mch_dev) {
-		ret = false;
-		goto out_unlock;
-	}
-	dev_priv = i915_mch_dev;
+	struct drm_i915_private *i915;
 
-	if (dev_priv->ips.max_delay < dev_priv->ips.min_delay)
-		dev_priv->ips.max_delay++;
+	i915 = mchdev_get();
+	if (!i915)
+		return false;
 
-out_unlock:
+	spin_lock_irq(&mchdev_lock);
+	if (i915->ips.max_delay < i915->ips.min_delay)
+		i915->ips.max_delay++;
 	spin_unlock_irq(&mchdev_lock);
 
-	return ret;
+	drm_dev_put(&i915->drm);
+	return true;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_lower);
 
@@ -8088,13 +8096,16 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
  */
 bool i915_gpu_busy(void)
 {
-	bool ret = false;
+	struct drm_i915_private *i915;
+	bool ret;
 
-	spin_lock_irq(&mchdev_lock);
-	if (i915_mch_dev)
-		ret = i915_mch_dev->gt.awake;
-	spin_unlock_irq(&mchdev_lock);
+	i915 = mchdev_get();
+	if (!i915)
+		return false;
 
+	ret = i915->gt.awake;
+
+	drm_dev_put(&i915->drm);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_busy);
@@ -8107,24 +8118,19 @@ EXPORT_SYMBOL_GPL(i915_gpu_busy);
  */
 bool i915_gpu_turbo_disable(void)
 {
-	struct drm_i915_private *dev_priv;
-	bool ret = true;
-
-	spin_lock_irq(&mchdev_lock);
-	if (!i915_mch_dev) {
-		ret = false;
-		goto out_unlock;
-	}
-	dev_priv = i915_mch_dev;
-
-	dev_priv->ips.max_delay = dev_priv->ips.fstart;
+	struct drm_i915_private *i915;
+	bool ret;
 
-	if (!ironlake_set_drps(dev_priv, dev_priv->ips.fstart))
-		ret = false;
+	i915 = mchdev_get();
+	if (!i915)
+		return false;
 
-out_unlock:
+	spin_lock_irq(&mchdev_lock);
+	i915->ips.max_delay = i915->ips.fstart;
+	ret = ironlake_set_drps(i915, i915->ips.fstart);
 	spin_unlock_irq(&mchdev_lock);
 
+	drm_dev_put(&i915->drm);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
@@ -8153,18 +8159,14 @@ void intel_gpu_ips_init(struct drm_i915_private *dev_priv)
 {
 	/* We only register the i915 ips part with intel-ips once everything is
 	 * set up, to avoid intel-ips sneaking in and reading bogus values. */
-	spin_lock_irq(&mchdev_lock);
-	i915_mch_dev = dev_priv;
-	spin_unlock_irq(&mchdev_lock);
+	rcu_assign_pointer(i915_mch_dev, dev_priv);
 
 	ips_ping_for_i915_load();
 }
 
 void intel_gpu_ips_teardown(void)
 {
-	spin_lock_irq(&mchdev_lock);
-	i915_mch_dev = NULL;
-	spin_unlock_irq(&mchdev_lock);
+	rcu_assign_pointer(i915_mch_dev, NULL);
 }
 
 static void intel_init_emon(struct drm_i915_private *dev_priv)
-- 
2.20.1

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

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

* Re: [PATCH 02/21] drm/i915: Markup paired operations on wakerefs
  2019-01-10 10:11 ` [PATCH 02/21] drm/i915: Markup paired operations on wakerefs Chris Wilson
@ 2019-01-10 10:20   ` Mika Kuoppala
  0 siblings, 0 replies; 39+ messages in thread
From: Mika Kuoppala @ 2019-01-10 10:20 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

Chris Wilson <chris@chris-wilson.co.uk> writes:

> The majority of runtime-pm operations are bounded and scoped within a
> function; these are easy to verify that the wakeref are handled
> correctly. We can employ the compiler to help us, and reduce the number
> of wakerefs tracked when debugging, by passing around cookies provided
> by the various rpm_get functions to their rpm_put counterpart. This
> makes the pairing explicit, and given the required wakeref cookie the
> compiler can verify that we pass an initialised value to the rpm_put
> (quite handy for double checking error paths).
>
> For regular builds, the compiler should be able to eliminate the unused
> local variables and the program growth should be minimal. Fwiw, it came
> out as a net improvement as gcc was able to refactor rpm_get and
> rpm_get_if_in_use together,
>
> v2: Just s/rpm_put/rpm_put_unchecked/ everywhere, leaving the manual
> mark up for smaller more targeted patches.
> v3: Mention the cookie in Returns
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula@intel.com>
> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>

Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/gvt/aperture_gm.c        |  8 +-
>  drivers/gpu/drm/i915/gvt/gvt.h                |  2 +-
>  drivers/gpu/drm/i915/gvt/sched_policy.c       |  2 +-
>  drivers/gpu/drm/i915/gvt/scheduler.c          |  4 +-
>  drivers/gpu/drm/i915/i915_debugfs.c           | 54 +++++------
>  drivers/gpu/drm/i915/i915_drv.h               |  2 +
>  drivers/gpu/drm/i915/i915_gem.c               | 20 ++---
>  drivers/gpu/drm/i915/i915_gem_execbuffer.c    |  2 +-
>  drivers/gpu/drm/i915/i915_gem_fence_reg.c     |  2 +-
>  drivers/gpu/drm/i915/i915_gem_gtt.c           |  8 +-
>  drivers/gpu/drm/i915/i915_gem_shrinker.c      | 10 +--
>  drivers/gpu/drm/i915/i915_irq.c               |  2 +-
>  drivers/gpu/drm/i915/i915_perf.c              |  4 +-
>  drivers/gpu/drm/i915/i915_pmu.c               |  6 +-
>  drivers/gpu/drm/i915/i915_sysfs.c             | 12 +--
>  drivers/gpu/drm/i915/intel_display.c          |  2 +-
>  drivers/gpu/drm/i915/intel_drv.h              | 15 +++-
>  drivers/gpu/drm/i915/intel_engine_cs.c        |  4 +-
>  drivers/gpu/drm/i915/intel_fbdev.c            |  4 +-
>  drivers/gpu/drm/i915/intel_guc_log.c          |  6 +-
>  drivers/gpu/drm/i915/intel_hotplug.c          |  2 +-
>  drivers/gpu/drm/i915/intel_huc.c              |  2 +-
>  drivers/gpu/drm/i915/intel_panel.c            |  2 +-
>  drivers/gpu/drm/i915/intel_runtime_pm.c       | 90 +++++++++++++++----
>  drivers/gpu/drm/i915/intel_uncore.c           |  2 +-
>  drivers/gpu/drm/i915/selftests/huge_pages.c   |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem.c     | 10 +--
>  .../drm/i915/selftests/i915_gem_coherency.c   |  2 +-
>  .../gpu/drm/i915/selftests/i915_gem_context.c | 10 +--
>  .../gpu/drm/i915/selftests/i915_gem_evict.c   |  2 +-
>  drivers/gpu/drm/i915/selftests/i915_gem_gtt.c |  4 +-
>  .../gpu/drm/i915/selftests/i915_gem_object.c  |  6 +-
>  drivers/gpu/drm/i915/selftests/i915_request.c |  8 +-
>  drivers/gpu/drm/i915/selftests/intel_guc.c    |  4 +-
>  .../gpu/drm/i915/selftests/intel_hangcheck.c  |  6 +-
>  drivers/gpu/drm/i915/selftests/intel_lrc.c    | 10 +--
>  .../drm/i915/selftests/intel_workarounds.c    | 10 +--
>  37 files changed, 202 insertions(+), 139 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c
> index 359d37d5c958..1fa2f65c3cd1 100644
> --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c
> +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
> @@ -180,7 +180,7 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu)
>  	}
>  	mutex_unlock(&dev_priv->drm.struct_mutex);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
>  static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
> @@ -206,7 +206,7 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
>  	_clear_vgpu_fence(vgpu);
>  
>  	mutex_unlock(&dev_priv->drm.struct_mutex);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	return 0;
>  out_free_fence:
>  	gvt_vgpu_err("Failed to alloc fences\n");
> @@ -219,7 +219,7 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
>  		vgpu->fence.regs[i] = NULL;
>  	}
>  	mutex_unlock(&dev_priv->drm.struct_mutex);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	return -ENOSPC;
>  }
>  
> @@ -317,7 +317,7 @@ void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
>  
>  	intel_runtime_pm_get(dev_priv);
>  	_clear_vgpu_fence(vgpu);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
> index b4ab1dad0143..435c746c3f73 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -597,7 +597,7 @@ static inline void mmio_hw_access_pre(struct drm_i915_private *dev_priv)
>  
>  static inline void mmio_hw_access_post(struct drm_i915_private *dev_priv)
>  {
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c
> index c32e7d5e8629..f04b3b965bfc 100644
> --- a/drivers/gpu/drm/i915/gvt/sched_policy.c
> +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c
> @@ -474,6 +474,6 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
>  		}
>  	}
>  	spin_unlock_bh(&scheduler->mmio_context_lock);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	mutex_unlock(&vgpu->gvt->sched_lock);
>  }
> diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
> index 1ad8c5e1455d..3816dcae2185 100644
> --- a/drivers/gpu/drm/i915/gvt/scheduler.c
> +++ b/drivers/gpu/drm/i915/gvt/scheduler.c
> @@ -997,7 +997,7 @@ static int workload_thread(void *priv)
>  			intel_uncore_forcewake_put(gvt->dev_priv,
>  					FORCEWAKE_ALL);
>  
> -		intel_runtime_pm_put(gvt->dev_priv);
> +		intel_runtime_pm_put_unchecked(gvt->dev_priv);
>  		if (ret && (vgpu_is_vm_unhealthy(ret)))
>  			enter_failsafe_mode(vgpu, GVT_FAILSAFE_GUEST_ERR);
>  	}
> @@ -1451,7 +1451,7 @@ intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
>  		mutex_lock(&dev_priv->drm.struct_mutex);
>  		ret = intel_gvt_scan_and_shadow_workload(workload);
>  		mutex_unlock(&dev_priv->drm.struct_mutex);
> -		intel_runtime_pm_put(dev_priv);
> +		intel_runtime_pm_put_unchecked(dev_priv);
>  	}
>  
>  	if (ret && (vgpu_is_vm_unhealthy(ret))) {
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 56ec65ec5199..43c130eb2217 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -877,7 +877,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>  		}
>  	}
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -953,7 +953,7 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file)
>  
>  	intel_runtime_pm_get(i915);
>  	gpu = i915_capture_gpu_state(i915);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	if (IS_ERR(gpu))
>  		return PTR_ERR(gpu);
>  
> @@ -1226,7 +1226,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
>  	seq_printf(m, "Max CD clock frequency: %d kHz\n", dev_priv->max_cdclk_freq);
>  	seq_printf(m, "Max pixel clock frequency: %d kHz\n", dev_priv->max_dotclk_freq);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	return ret;
>  }
>  
> @@ -1292,7 +1292,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
>  
>  	intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	if (timer_pending(&dev_priv->gpu_error.hangcheck_work.timer))
>  		seq_printf(m, "Hangcheck active, timer fires in %dms\n",
> @@ -1579,7 +1579,7 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
>  	else
>  		err = ironlake_drpc_info(m);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return err;
>  }
> @@ -1632,7 +1632,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
>  	}
>  
>  	mutex_unlock(&fbc->lock);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -1695,7 +1695,7 @@ static int i915_ips_status(struct seq_file *m, void *unused)
>  			seq_puts(m, "Currently: disabled\n");
>  	}
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -1723,7 +1723,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
>  		sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
>  
>  	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
>  
> @@ -1756,7 +1756,7 @@ static int i915_emon_status(struct seq_file *m, void *unused)
>  	seq_printf(m, "GFX power: %ld\n", gfx);
>  	seq_printf(m, "Total power: %ld\n", chipset + gfx);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -1805,7 +1805,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
>  	mutex_unlock(&dev_priv->pcu_lock);
>  
>  out:
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	return ret;
>  }
>  
> @@ -2017,7 +2017,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
>  	if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
>  		seq_puts(m, "L-shaped memory detected\n");
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -2067,7 +2067,7 @@ static int i915_rps_boost_info(struct seq_file *m, void *data)
>  			act_freq = intel_get_cagf(dev_priv,
>  						  I915_READ(GEN6_RPSTAT1));
>  		}
> -		intel_runtime_pm_put(dev_priv);
> +		intel_runtime_pm_put_unchecked(dev_priv);
>  	}
>  
>  	seq_printf(m, "RPS enabled? %d\n", rps->enabled);
> @@ -2160,7 +2160,7 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data)
>  
>  	intel_runtime_pm_get(dev_priv);
>  	seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2));
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -2192,7 +2192,7 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
>  	for (i = 0; i < 16; i++)
>  		seq_printf(m, "\t%2d: \t0x%x\n", i, I915_READ(SOFT_SCRATCH(i)));
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -2601,7 +2601,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
>  			   dev_priv->psr.last_exit);
>  	}
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	return 0;
>  }
>  
> @@ -2632,7 +2632,7 @@ i915_edp_psr_debug_set(void *data, u64 val)
>  	drm_modeset_drop_locks(&ctx);
>  	drm_modeset_acquire_fini(&ctx);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return ret;
>  }
> @@ -2665,7 +2665,7 @@ static int i915_energy_uJ(struct seq_file *m, void *data)
>  	intel_runtime_pm_get(dev_priv);
>  
>  	if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &power)) {
> -		intel_runtime_pm_put(dev_priv);
> +		intel_runtime_pm_put_unchecked(dev_priv);
>  		return -ENODEV;
>  	}
>  
> @@ -2673,7 +2673,7 @@ static int i915_energy_uJ(struct seq_file *m, void *data)
>  	power = I915_READ(MCH_SECP_NRG_STTS);
>  	power = (1000000 * power) >> units; /* convert to uJ */
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	seq_printf(m, "%llu", power);
>  
> @@ -2775,7 +2775,7 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
>  	seq_printf(m, "ssp base: 0x%08x\n", I915_READ(CSR_SSP_BASE));
>  	seq_printf(m, "htp: 0x%08x\n", I915_READ(CSR_HTP_SKL));
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -3107,7 +3107,7 @@ static int i915_display_info(struct seq_file *m, void *unused)
>  	drm_connector_list_iter_end(&conn_iter);
>  	mutex_unlock(&dev->mode_config.mutex);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -3132,7 +3132,7 @@ static int i915_engine_info(struct seq_file *m, void *unused)
>  	for_each_engine(engine, dev_priv, id)
>  		intel_engine_dump(engine, &p, "%s\n", engine->name);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return 0;
>  }
> @@ -3258,7 +3258,7 @@ static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf,
>  	dev_priv->wm.distrust_bios_wm = true;
>  	dev_priv->ipc_enabled = enable;
>  	intel_enable_ipc(dev_priv);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return len;
>  }
> @@ -4083,7 +4083,7 @@ i915_drop_caches_set(void *data, u64 val)
>  		i915_gem_drain_freed_objects(i915);
>  
>  out:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	return ret;
>  }
> @@ -4105,7 +4105,7 @@ i915_cache_sharing_get(void *data, u64 *val)
>  
>  	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
>  
> @@ -4133,7 +4133,7 @@ i915_cache_sharing_set(void *data, u64 val)
>  	snpcr |= (val << GEN6_MBC_SNPCR_SHIFT);
>  	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	return 0;
>  }
>  
> @@ -4381,7 +4381,7 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
>  		gen10_sseu_device_status(dev_priv, &sseu);
>  	}
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	i915_print_sseu_info(m, false, &sseu);
>  
> @@ -4409,7 +4409,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
>  		return 0;
>  
>  	intel_uncore_forcewake_user_put(i915);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 525a26174fcf..9c00598f3bc7 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -131,6 +131,8 @@ bool i915_error_injected(void);
>  	__i915_printk(i915, i915_error_injected() ? KERN_DEBUG : KERN_ERR, \
>  		      fmt, ##__VA_ARGS__)
>  
> +typedef depot_stack_handle_t intel_wakeref_t;
> +
>  enum hpd_pin {
>  	HPD_NONE = 0,
>  	HPD_TV = HPD_NONE,     /* TV is known to be unreliable */
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index ea85da393662..4380189a9cea 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -175,7 +175,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
>  
>  	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ);
>  
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	return i915->gt.epoch;
>  }
> @@ -814,7 +814,7 @@ void i915_gem_flush_ggtt_writes(struct drm_i915_private *dev_priv)
>  	POSTING_READ_FW(RING_HEAD(RENDER_RING_BASE));
>  
>  	spin_unlock_irq(&dev_priv->uncore.lock);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
>  static void
> @@ -1149,7 +1149,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
>  		i915_vma_unpin(vma);
>  	}
>  out_unlock:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  
>  	return ret;
> @@ -1356,7 +1356,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
>  		i915_vma_unpin(vma);
>  	}
>  out_rpm:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  out_unlock:
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	return ret;
> @@ -1968,7 +1968,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
>  err_unlock:
>  	mutex_unlock(&dev->struct_mutex);
>  err_rpm:
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	i915_gem_object_unpin_pages(obj);
>  err:
>  	switch (ret) {
> @@ -2068,7 +2068,7 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
>  	wmb();
>  
>  out:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  }
>  
>  void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
> @@ -4765,7 +4765,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
>  		if (on)
>  			cond_resched();
>  	}
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  }
>  
>  static void i915_gem_flush_free_objects(struct drm_i915_private *i915)
> @@ -4901,7 +4901,7 @@ void i915_gem_sanitize(struct drm_i915_private *i915)
>  	intel_engines_sanitize(i915, false);
>  
>  	intel_uncore_forcewake_put(i915, FORCEWAKE_ALL);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	i915_gem_contexts_lost(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
> @@ -4965,12 +4965,12 @@ int i915_gem_suspend(struct drm_i915_private *i915)
>  	if (WARN_ON(!intel_engines_are_idle(i915)))
>  		i915_gem_set_wedged(i915); /* no hope, discard everything */
>  
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	return 0;
>  
>  err_unlock:
>  	mutex_unlock(&i915->drm.struct_mutex);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	return ret;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index e7994505d850..c80943698ca2 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -2424,7 +2424,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
>  		eb_release_vmas(&eb);
>  	mutex_unlock(&dev->struct_mutex);
>  err_rpm:
> -	intel_runtime_pm_put(eb.i915);
> +	intel_runtime_pm_put_unchecked(eb.i915);
>  	i915_gem_context_put(eb.ctx);
>  err_destroy:
>  	eb_destroy(&eb);
> diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
> index d67c07cdd0b8..b3391070acf7 100644
> --- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c
> +++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
> @@ -258,7 +258,7 @@ static int fence_update(struct drm_i915_fence_reg *fence,
>  	 */
>  	if (intel_runtime_pm_get_if_in_use(fence->i915)) {
>  		fence_write(fence, vma);
> -		intel_runtime_pm_put(fence->i915);
> +		intel_runtime_pm_put_unchecked(fence->i915);
>  	}
>  
>  	if (vma) {
> diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
> index a8807fbed0aa..51f80ddd938d 100644
> --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> @@ -2536,7 +2536,7 @@ static int ggtt_bind_vma(struct i915_vma *vma,
>  
>  	intel_runtime_pm_get(i915);
>  	vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
>  
> @@ -2556,7 +2556,7 @@ static void ggtt_unbind_vma(struct i915_vma *vma)
>  
>  	intel_runtime_pm_get(i915);
>  	vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  }
>  
>  static int aliasing_gtt_bind_vma(struct i915_vma *vma,
> @@ -2590,7 +2590,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
>  	if (flags & I915_VMA_GLOBAL_BIND) {
>  		intel_runtime_pm_get(i915);
>  		vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
> -		intel_runtime_pm_put(i915);
> +		intel_runtime_pm_put_unchecked(i915);
>  	}
>  
>  	return 0;
> @@ -2603,7 +2603,7 @@ static void aliasing_gtt_unbind_vma(struct i915_vma *vma)
>  	if (vma->flags & I915_VMA_GLOBAL_BIND) {
>  		intel_runtime_pm_get(i915);
>  		vma->vm->clear_range(vma->vm, vma->node.start, vma->size);
> -		intel_runtime_pm_put(i915);
> +		intel_runtime_pm_put_unchecked(i915);
>  	}
>  
>  	if (vma->flags & I915_VMA_LOCAL_BIND) {
> diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
> index 34b108f73f1d..1f0e79635087 100644
> --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
> +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
> @@ -265,7 +265,7 @@ i915_gem_shrink(struct drm_i915_private *i915,
>  	}
>  
>  	if (flags & I915_SHRINK_BOUND)
> -		intel_runtime_pm_put(i915);
> +		intel_runtime_pm_put_unchecked(i915);
>  
>  	i915_retire_requests(i915);
>  
> @@ -299,7 +299,7 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *i915)
>  				I915_SHRINK_BOUND |
>  				I915_SHRINK_UNBOUND |
>  				I915_SHRINK_ACTIVE);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	return freed;
>  }
> @@ -377,7 +377,7 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
>  					 I915_SHRINK_ACTIVE |
>  					 I915_SHRINK_BOUND |
>  					 I915_SHRINK_UNBOUND);
> -		intel_runtime_pm_put(i915);
> +		intel_runtime_pm_put_unchecked(i915);
>  	}
>  
>  	shrinker_unlock(i915, unlock);
> @@ -422,7 +422,7 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
>  	freed_pages = i915_gem_shrink(i915, -1UL, NULL,
>  				      I915_SHRINK_BOUND |
>  				      I915_SHRINK_UNBOUND);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	/* Because we may be allocating inside our own driver, we cannot
>  	 * assert that there are no objects with pinned pages that are not
> @@ -478,7 +478,7 @@ i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr
>  				       I915_SHRINK_BOUND |
>  				       I915_SHRINK_UNBOUND |
>  				       I915_SHRINK_VMAPS);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	/* We also want to clear any cached iomaps as they wrap vmap */
>  	list_for_each_entry_safe(vma, next,
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 288b0662f7b7..787a9ed1ef7d 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -3374,7 +3374,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv,
>  	wake_up_all(&dev_priv->gpu_error.reset_queue);
>  
>  out:
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
>  /* Called from drm generic code, passed 'crtc' which
> diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
> index 5b1ae5ed97b3..e4dfd1477c78 100644
> --- a/drivers/gpu/drm/i915/i915_perf.c
> +++ b/drivers/gpu/drm/i915/i915_perf.c
> @@ -1365,7 +1365,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
>  	free_oa_buffer(dev_priv);
>  
>  	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	if (stream->ctx)
>  		oa_put_render_ctx_id(stream);
> @@ -2123,7 +2123,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
>  	put_oa_config(dev_priv, stream->oa_config);
>  
>  	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  err_config:
>  	if (stream->ctx)
> diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
> index d6c8f8fdfda5..c99fcfce79d5 100644
> --- a/drivers/gpu/drm/i915/i915_pmu.c
> +++ b/drivers/gpu/drm/i915/i915_pmu.c
> @@ -210,7 +210,7 @@ engines_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
>  	if (fw)
>  		intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
>  static void
> @@ -231,7 +231,7 @@ frequency_sample(struct drm_i915_private *dev_priv, unsigned int period_ns)
>  		    intel_runtime_pm_get_if_in_use(dev_priv)) {
>  			val = intel_get_cagf(dev_priv,
>  					     I915_READ_NOTRACE(GEN6_RPSTAT1));
> -			intel_runtime_pm_put(dev_priv);
> +			intel_runtime_pm_put_unchecked(dev_priv);
>  		}
>  
>  		add_sample_mult(&dev_priv->pmu.sample[__I915_SAMPLE_FREQ_ACT],
> @@ -448,7 +448,7 @@ static u64 get_rc6(struct drm_i915_private *i915)
>  
>  	if (intel_runtime_pm_get_if_in_use(i915)) {
>  		val = __get_rc6(i915);
> -		intel_runtime_pm_put(i915);
> +		intel_runtime_pm_put_unchecked(i915);
>  
>  		/*
>  		 * If we are coming back from being runtime suspended we must
> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
> index c0cfe7ae2ba5..53c20e103d56 100644
> --- a/drivers/gpu/drm/i915/i915_sysfs.c
> +++ b/drivers/gpu/drm/i915/i915_sysfs.c
> @@ -46,7 +46,7 @@ static u32 calc_residency(struct drm_i915_private *dev_priv,
>  
>  	intel_runtime_pm_get(dev_priv);
>  	res = intel_rc6_residency_us(dev_priv, reg);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return DIV_ROUND_CLOSEST_ULL(res, 1000);
>  }
> @@ -274,7 +274,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev,
>  	}
>  	mutex_unlock(&dev_priv->pcu_lock);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return snprintf(buf, PAGE_SIZE, "%d\n", ret);
>  }
> @@ -371,7 +371,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>  	    val > rps->max_freq ||
>  	    val < rps->min_freq_softlimit) {
>  		mutex_unlock(&dev_priv->pcu_lock);
> -		intel_runtime_pm_put(dev_priv);
> +		intel_runtime_pm_put_unchecked(dev_priv);
>  		return -EINVAL;
>  	}
>  
> @@ -392,7 +392,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
>  
>  	mutex_unlock(&dev_priv->pcu_lock);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return ret ?: count;
>  }
> @@ -429,7 +429,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
>  	    val > rps->max_freq ||
>  	    val > rps->max_freq_softlimit) {
>  		mutex_unlock(&dev_priv->pcu_lock);
> -		intel_runtime_pm_put(dev_priv);
> +		intel_runtime_pm_put_unchecked(dev_priv);
>  		return -EINVAL;
>  	}
>  
> @@ -446,7 +446,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
>  
>  	mutex_unlock(&dev_priv->pcu_lock);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return ret ?: count;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 1cc441f06c73..a980d5d1e601 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2101,7 +2101,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
>  err:
>  	atomic_dec(&dev_priv->gpu_error.pending_fb_pin);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	return vma;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index ac513fd70315..a1e4e1033289 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -29,6 +29,7 @@
>  #include <linux/i2c.h>
>  #include <linux/hdmi.h>
>  #include <linux/sched/clock.h>
> +#include <linux/stackdepot.h>
>  #include <drm/i915_drm.h>
>  #include "i915_drv.h"
>  #include <drm/drm_crtc.h>
> @@ -2182,10 +2183,16 @@ enable_rpm_wakeref_asserts(struct drm_i915_private *i915)
>  	atomic_dec(&i915->runtime_pm.wakeref_count);
>  }
>  
> -void intel_runtime_pm_get(struct drm_i915_private *i915);
> -bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915);
> -void intel_runtime_pm_get_noresume(struct drm_i915_private *i915);
> -void intel_runtime_pm_put(struct drm_i915_private *i915);
> +intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915);
> +intel_wakeref_t intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915);
> +intel_wakeref_t intel_runtime_pm_get_noresume(struct drm_i915_private *i915);
> +
> +void intel_runtime_pm_put_unchecked(struct drm_i915_private *i915);
> +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
> +void intel_runtime_pm_put(struct drm_i915_private *i915, intel_wakeref_t wref);
> +#else
> +#define intel_runtime_pm_put(i915, wref) intel_runtime_pm_put_unchecked(i915)
> +#endif
>  
>  #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
>  void print_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
> diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
> index 236cd040f271..85131166589c 100644
> --- a/drivers/gpu/drm/i915/intel_engine_cs.c
> +++ b/drivers/gpu/drm/i915/intel_engine_cs.c
> @@ -928,7 +928,7 @@ static bool ring_is_idle(struct intel_engine_cs *engine)
>  	if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE))
>  		idle = false;
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return idle;
>  }
> @@ -1485,7 +1485,7 @@ void intel_engine_dump(struct intel_engine_cs *engine,
>  
>  	if (intel_runtime_pm_get_if_in_use(engine->i915)) {
>  		intel_engine_print_registers(engine, m);
> -		intel_runtime_pm_put(engine->i915);
> +		intel_runtime_pm_put_unchecked(engine->i915);
>  	} else {
>  		drm_printf(m, "\tDevice is asleep; skipping register dump\n");
>  	}
> diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
> index a0c5046e170c..215e5894842d 100644
> --- a/drivers/gpu/drm/i915/intel_fbdev.c
> +++ b/drivers/gpu/drm/i915/intel_fbdev.c
> @@ -276,7 +276,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
>  	ifbdev->vma = vma;
>  	ifbdev->vma_flags = flags;
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  	vga_switcheroo_client_fb_set(pdev, info);
>  	return 0;
> @@ -284,7 +284,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
>  out_unpin:
>  	intel_unpin_fb_vma(vma, flags);
>  out_unlock:
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	mutex_unlock(&dev->struct_mutex);
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c
> index d3ebdbc0182e..1b1581a42aa1 100644
> --- a/drivers/gpu/drm/i915/intel_guc_log.c
> +++ b/drivers/gpu/drm/i915/intel_guc_log.c
> @@ -445,7 +445,7 @@ static void guc_log_capture_logs(struct intel_guc_log *log)
>  	 */
>  	intel_runtime_pm_get(dev_priv);
>  	guc_action_flush_log_complete(guc);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
>  int intel_guc_log_create(struct intel_guc_log *log)
> @@ -528,7 +528,7 @@ int intel_guc_log_set_level(struct intel_guc_log *log, u32 level)
>  	ret = guc_action_control_log(guc, GUC_LOG_LEVEL_IS_VERBOSE(level),
>  				     GUC_LOG_LEVEL_IS_ENABLED(level),
>  				     GUC_LOG_LEVEL_TO_VERBOSITY(level));
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	if (ret) {
>  		DRM_DEBUG_DRIVER("guc_log_control action failed %d\n", ret);
>  		goto out_unlock;
> @@ -610,7 +610,7 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log)
>  
>  	intel_runtime_pm_get(i915);
>  	guc_action_flush_log(guc);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	/* GuC would have updated log buffer by now, so capture it */
>  	guc_log_capture_logs(log);
> diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c
> index ae92d6560165..b1a9cb960ca4 100644
> --- a/drivers/gpu/drm/i915/intel_hotplug.c
> +++ b/drivers/gpu/drm/i915/intel_hotplug.c
> @@ -261,7 +261,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
>  		dev_priv->display.hpd_irq_setup(dev_priv);
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
>  bool intel_encoder_hotplug(struct intel_encoder *encoder,
> diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c
> index bc27b691d824..c2b076e9bada 100644
> --- a/drivers/gpu/drm/i915/intel_huc.c
> +++ b/drivers/gpu/drm/i915/intel_huc.c
> @@ -122,7 +122,7 @@ int intel_huc_check_status(struct intel_huc *huc)
>  
>  	intel_runtime_pm_get(dev_priv);
>  	status = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED;
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return status;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index ee3e0842d542..c2b7455a023e 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -1213,7 +1213,7 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
>  	ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);
>  
>  	drm_modeset_unlock(&dev->mode_config.connection_mutex);
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index a2f8d1fcf136..f585ef742efe 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -77,7 +77,7 @@ static void init_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
>  	spin_lock_init(&rpm->debug.lock);
>  }
>  
> -static noinline void
> +static noinline depot_stack_handle_t
>  track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
>  {
>  	struct i915_runtime_pm *rpm = &i915->runtime_pm;
> @@ -91,7 +91,7 @@ track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
>  	depot_stack_handle_t stack, *stacks;
>  
>  	if (!HAS_RUNTIME_PM(i915))
> -		return;
> +		return -1;
>  
>  	save_stack_trace(&trace);
>  	if (trace.nr_entries &&
> @@ -100,7 +100,7 @@ track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
>  
>  	stack = depot_save_stack(&trace, GFP_NOWAIT | __GFP_NOWARN);
>  	if (!stack)
> -		return;
> +		return -1;
>  
>  	spin_lock_irqsave(&rpm->debug.lock, flags);
>  
> @@ -113,9 +113,50 @@ track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
>  	if (stacks) {
>  		stacks[rpm->debug.count++] = stack;
>  		rpm->debug.owners = stacks;
> +	} else {
> +		stack = -1;
>  	}
>  
>  	spin_unlock_irqrestore(&rpm->debug.lock, flags);
> +
> +	return stack;
> +}
> +
> +static void cancel_intel_runtime_pm_wakeref(struct drm_i915_private *i915,
> +					    depot_stack_handle_t stack)
> +{
> +	struct i915_runtime_pm *rpm = &i915->runtime_pm;
> +	unsigned long flags, n;
> +	bool found = false;
> +
> +	if (unlikely(stack == -1))
> +		return;
> +
> +	spin_lock_irqsave(&rpm->debug.lock, flags);
> +	for (n = rpm->debug.count; n--; ) {
> +		if (rpm->debug.owners[n] == stack) {
> +			memmove(rpm->debug.owners + n,
> +				rpm->debug.owners + n + 1,
> +				(--rpm->debug.count - n) * sizeof(stack));
> +			found = true;
> +			break;
> +		}
> +	}
> +	spin_unlock_irqrestore(&rpm->debug.lock, flags);
> +
> +	if (WARN(!found,
> +		 "Unmatched wakeref (tracking %lu), count %u\n",
> +		 rpm->debug.count, atomic_read(&rpm->wakeref_count))) {
> +		char *buf;
> +
> +		buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
> +		if (!buf)
> +			return;
> +
> +		__print_depot_stack(stack, buf, PAGE_SIZE, 0);
> +		DRM_DEBUG_DRIVER("wakeref %x from\n%s", stack, buf);
> +		kfree(buf);
> +	}
>  }
>  
>  static noinline void
> @@ -268,8 +309,10 @@ static void init_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
>  {
>  }
>  
> -static void track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
> +static depot_stack_handle_t
> +track_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
>  {
> +	return -1;
>  }
>  
>  static void untrack_intel_runtime_pm_wakeref(struct drm_i915_private *i915)
> @@ -1871,7 +1914,7 @@ bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
>  	mutex_unlock(&power_domains->lock);
>  
>  	if (!is_enabled)
> -		intel_runtime_pm_put(dev_priv);
> +		intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return is_enabled;
>  }
> @@ -1905,7 +1948,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
>  
>  	mutex_unlock(&power_domains->lock);
>  
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
>  #define I830_PIPES_POWER_DOMAINS (		\
> @@ -4013,7 +4056,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
>  void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
>  {
>  	/* Keep the power well enabled, but cancel its rpm wakeref. */
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	/* Remove the refcount we took to keep power well support disabled. */
>  	if (!i915_modparams.disable_power_well)
> @@ -4226,8 +4269,10 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
>   *
>   * Any runtime pm reference obtained by this function must have a symmetric
>   * call to intel_runtime_pm_put() to release the reference again.
> + *
> + * Returns: the wakeref cookie to pass to intel_runtime_pm_put()
>   */
> -void intel_runtime_pm_get(struct drm_i915_private *i915)
> +intel_wakeref_t intel_runtime_pm_get(struct drm_i915_private *i915)
>  {
>  	struct pci_dev *pdev = i915->drm.pdev;
>  	struct device *kdev = &pdev->dev;
> @@ -4239,7 +4284,7 @@ void intel_runtime_pm_get(struct drm_i915_private *i915)
>  	atomic_inc(&i915->runtime_pm.wakeref_count);
>  	assert_rpm_wakelock_held(i915);
>  
> -	track_intel_runtime_pm_wakeref(i915);
> +	return track_intel_runtime_pm_wakeref(i915);
>  }
>  
>  /**
> @@ -4253,9 +4298,10 @@ void intel_runtime_pm_get(struct drm_i915_private *i915)
>   * Any runtime pm reference obtained by this function must have a symmetric
>   * call to intel_runtime_pm_put() to release the reference again.
>   *
> - * Returns: True if the wakeref was acquired, or False otherwise.
> + * Returns: the wakeref cookie to pass to intel_runtime_pm_put(), evaluates
> + * as True if the wakeref was acquired, or False otherwise.
>   */
> -bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
> +intel_wakeref_t intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
>  {
>  	if (IS_ENABLED(CONFIG_PM)) {
>  		struct pci_dev *pdev = i915->drm.pdev;
> @@ -4268,15 +4314,13 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
>  		 * atm to the late/early system suspend/resume handlers.
>  		 */
>  		if (pm_runtime_get_if_in_use(kdev) <= 0)
> -			return false;
> +			return 0;
>  	}
>  
>  	atomic_inc(&i915->runtime_pm.wakeref_count);
>  	assert_rpm_wakelock_held(i915);
>  
> -	track_intel_runtime_pm_wakeref(i915);
> -
> -	return true;
> +	return track_intel_runtime_pm_wakeref(i915);
>  }
>  
>  /**
> @@ -4295,8 +4339,10 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *i915)
>   *
>   * Any runtime pm reference obtained by this function must have a symmetric
>   * call to intel_runtime_pm_put() to release the reference again.
> + *
> + * Returns: the wakeref cookie to pass to intel_runtime_pm_put()
>   */
> -void intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
> +intel_wakeref_t intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
>  {
>  	struct pci_dev *pdev = i915->drm.pdev;
>  	struct device *kdev = &pdev->dev;
> @@ -4306,7 +4352,7 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
>  
>  	atomic_inc(&i915->runtime_pm.wakeref_count);
>  
> -	track_intel_runtime_pm_wakeref(i915);
> +	return track_intel_runtime_pm_wakeref(i915);
>  }
>  
>  /**
> @@ -4317,7 +4363,7 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *i915)
>   * intel_runtime_pm_get() and might power down the corresponding
>   * hardware block right away if this is the last reference.
>   */
> -void intel_runtime_pm_put(struct drm_i915_private *i915)
> +void intel_runtime_pm_put_unchecked(struct drm_i915_private *i915)
>  {
>  	struct pci_dev *pdev = i915->drm.pdev;
>  	struct device *kdev = &pdev->dev;
> @@ -4330,6 +4376,14 @@ void intel_runtime_pm_put(struct drm_i915_private *i915)
>  	pm_runtime_put_autosuspend(kdev);
>  }
>  
> +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
> +void intel_runtime_pm_put(struct drm_i915_private *i915, intel_wakeref_t wref)
> +{
> +	cancel_intel_runtime_pm_wakeref(i915, wref);
> +	intel_runtime_pm_put_unchecked(i915);
> +}
> +#endif
> +
>  /**
>   * intel_runtime_pm_enable - enable runtime pm
>   * @i915: i915 device instance
> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
> index fff468f17d2d..8d4c76ac0e7d 100644
> --- a/drivers/gpu/drm/i915/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/intel_uncore.c
> @@ -1709,7 +1709,7 @@ int i915_reg_read_ioctl(struct drm_device *dev,
>  		reg->val = I915_READ8(entry->offset_ldw);
>  	else
>  		ret = -EINVAL;
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c
> index 6c10734e948d..a4d8b12be12c 100644
> --- a/drivers/gpu/drm/i915/selftests/huge_pages.c
> +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c
> @@ -1785,7 +1785,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv)
>  	err = i915_subtests(tests, ctx);
>  
>  out_unlock:
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	mutex_unlock(&dev_priv->drm.struct_mutex);
>  
>  	mock_file_free(dev_priv, file);
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c
> index bdcc53e15e75..762e1a7125f5 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c
> @@ -32,7 +32,7 @@ static int switch_to_context(struct drm_i915_private *i915,
>  		i915_request_add(rq);
>  	}
>  
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	return err;
>  }
> @@ -76,7 +76,7 @@ static void simulate_hibernate(struct drm_i915_private *i915)
>  	 */
>  	trash_stolen(i915);
>  
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  }
>  
>  static int pm_prepare(struct drm_i915_private *i915)
> @@ -98,7 +98,7 @@ static void pm_suspend(struct drm_i915_private *i915)
>  	i915_gem_suspend_gtt_mappings(i915);
>  	i915_gem_suspend_late(i915);
>  
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  }
>  
>  static void pm_hibernate(struct drm_i915_private *i915)
> @@ -110,7 +110,7 @@ static void pm_hibernate(struct drm_i915_private *i915)
>  	i915_gem_freeze(i915);
>  	i915_gem_freeze_late(i915);
>  
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  }
>  
>  static void pm_resume(struct drm_i915_private *i915)
> @@ -125,7 +125,7 @@ static void pm_resume(struct drm_i915_private *i915)
>  	i915_gem_sanitize(i915);
>  	i915_gem_resume(i915);
>  
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  }
>  
>  static int igt_gem_suspend(void *arg)
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
> index f7392c1ffe75..eea4fc2445ae 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c
> @@ -376,7 +376,7 @@ static int igt_gem_coherency(void *arg)
>  		}
>  	}
>  unlock:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	kfree(offsets);
>  	return err;
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
> index d00cdf3c2939..6e1a0711d201 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c
> @@ -243,7 +243,7 @@ static int live_nop_switch(void *arg)
>  	}
>  
>  out_unlock:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	mock_file_free(i915, file);
>  	return err;
> @@ -609,7 +609,7 @@ static int igt_ctx_exec(void *arg)
>  
>  			intel_runtime_pm_get(i915);
>  			err = gpu_fill(obj, ctx, engine, dw);
> -			intel_runtime_pm_put(i915);
> +			intel_runtime_pm_put_unchecked(i915);
>  			if (err) {
>  				pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
>  				       ndwords, dw, max_dwords(obj),
> @@ -715,7 +715,7 @@ static int igt_ctx_readonly(void *arg)
>  
>  			intel_runtime_pm_get(i915);
>  			err = gpu_fill(obj, ctx, engine, dw);
> -			intel_runtime_pm_put(i915);
> +			intel_runtime_pm_put_unchecked(i915);
>  			if (err) {
>  				pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) in ctx %u [full-ppgtt? %s], err=%d\n",
>  				       ndwords, dw, max_dwords(obj),
> @@ -1067,7 +1067,7 @@ static int igt_vm_isolation(void *arg)
>  		count, RUNTIME_INFO(i915)->num_rings);
>  
>  out_rpm:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  out_unlock:
>  	if (end_live_test(&t))
>  		err = -EIO;
> @@ -1200,7 +1200,7 @@ static int igt_switch_to_kernel_context(void *arg)
>  	if (igt_flush_test(i915, I915_WAIT_LOCKED))
>  		err = -EIO;
>  
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  
>  	kernel_context_close(ctx);
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> index 4365979d8222..8d22f73a9b63 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c
> @@ -464,7 +464,7 @@ static int igt_evict_contexts(void *arg)
>  	}
>  	if (drm_mm_node_allocated(&hole))
>  		drm_mm_remove_node(&hole);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  
>  	return err;
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
> index a9ed0ecc94e2..87cb0602a5fc 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
> @@ -295,7 +295,7 @@ static int lowlevel_hole(struct drm_i915_private *i915,
>  
>  			intel_runtime_pm_get(i915);
>  			vm->insert_entries(vm, &mock_vma, I915_CACHE_NONE, 0);
> -			intel_runtime_pm_put(i915);
> +			intel_runtime_pm_put_unchecked(i915);
>  		}
>  		count = n;
>  
> @@ -1216,7 +1216,7 @@ static int igt_ggtt_page(void *arg)
>  	kfree(order);
>  out_remove:
>  	ggtt->vm.clear_range(&ggtt->vm, tmp.start, tmp.size);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	drm_mm_remove_node(&tmp);
>  out_unpin:
>  	i915_gem_object_unpin_pages(obj);
> diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
> index be7ecb66ad11..b03890c590d7 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c
> @@ -444,7 +444,7 @@ next_tiling: ;
>  	}
>  
>  out_unlock:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	i915_gem_object_unpin_pages(obj);
>  out:
> @@ -508,7 +508,7 @@ static void disable_retire_worker(struct drm_i915_private *i915)
>  	if (!i915->gt.active_requests++) {
>  		intel_runtime_pm_get(i915);
>  		i915_gem_unpark(i915);
> -		intel_runtime_pm_put(i915);
> +		intel_runtime_pm_put_unchecked(i915);
>  	}
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	cancel_delayed_work_sync(&i915->gt.retire_work);
> @@ -590,7 +590,7 @@ static int igt_mmap_offset_exhaustion(void *arg)
>  		mutex_lock(&i915->drm.struct_mutex);
>  		intel_runtime_pm_get(i915);
>  		err = make_obj_busy(obj);
> -		intel_runtime_pm_put(i915);
> +		intel_runtime_pm_put_unchecked(i915);
>  		mutex_unlock(&i915->drm.struct_mutex);
>  		if (err) {
>  			pr_err("[loop %d] Failed to busy the object\n", loop);
> diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
> index 07e557815308..e8880cabd5c7 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_request.c
> +++ b/drivers/gpu/drm/i915/selftests/i915_request.c
> @@ -403,7 +403,7 @@ static int live_nop_request(void *arg)
>  	}
>  
>  out_unlock:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	return err;
>  }
> @@ -553,7 +553,7 @@ static int live_empty_request(void *arg)
>  	i915_vma_unpin(batch);
>  	i915_vma_put(batch);
>  out_unlock:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	return err;
>  }
> @@ -731,7 +731,7 @@ static int live_all_engines(void *arg)
>  	i915_vma_unpin(batch);
>  	i915_vma_put(batch);
>  out_unlock:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	return err;
>  }
> @@ -860,7 +860,7 @@ static int live_sequential_engines(void *arg)
>  		i915_request_put(request[id]);
>  	}
>  out_unlock:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	return err;
>  }
> diff --git a/drivers/gpu/drm/i915/selftests/intel_guc.c b/drivers/gpu/drm/i915/selftests/intel_guc.c
> index 32cba4cae31a..3590ba3d8897 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_guc.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_guc.c
> @@ -225,7 +225,7 @@ static int igt_guc_clients(void *args)
>  	guc_clients_create(guc);
>  	guc_clients_enable(guc);
>  unlock:
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	mutex_unlock(&dev_priv->drm.struct_mutex);
>  	return err;
>  }
> @@ -337,7 +337,7 @@ static int igt_guc_doorbells(void *arg)
>  			guc_client_free(clients[i]);
>  		}
>  unlock:
> -	intel_runtime_pm_put(dev_priv);
> +	intel_runtime_pm_put_unchecked(dev_priv);
>  	mutex_unlock(&dev_priv->drm.struct_mutex);
>  	return err;
>  }
> diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
> index 0aadbd9c7d56..33bd3c4b6fa3 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c
> @@ -402,7 +402,7 @@ static int igt_wedged_reset(void *arg)
>  	i915_reset(i915, ALL_ENGINES, NULL);
>  	GEM_BUG_ON(test_bit(I915_RESET_HANDOFF, &i915->gpu_error.flags));
>  
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	igt_global_reset_unlock(i915);
>  
> @@ -1636,7 +1636,7 @@ static int igt_atomic_reset(void *arg)
>  	force_reset(i915);
>  
>  unlock:
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	igt_global_reset_unlock(i915);
>  
> @@ -1679,7 +1679,7 @@ int intel_hangcheck_live_selftests(struct drm_i915_private *i915)
>  	mutex_unlock(&i915->drm.struct_mutex);
>  
>  	i915_modparams.enable_hangcheck = saved_hangcheck;
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	return err;
>  }
> diff --git a/drivers/gpu/drm/i915/selftests/intel_lrc.c b/drivers/gpu/drm/i915/selftests/intel_lrc.c
> index 00caaa00f02f..ac1b18a17f3c 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_lrc.c
> @@ -65,7 +65,7 @@ static int live_sanitycheck(void *arg)
>  	igt_spinner_fini(&spin);
>  err_unlock:
>  	igt_flush_test(i915, I915_WAIT_LOCKED);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	return err;
>  }
> @@ -158,7 +158,7 @@ static int live_preempt(void *arg)
>  	igt_spinner_fini(&spin_hi);
>  err_unlock:
>  	igt_flush_test(i915, I915_WAIT_LOCKED);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	return err;
>  }
> @@ -251,7 +251,7 @@ static int live_late_preempt(void *arg)
>  	igt_spinner_fini(&spin_hi);
>  err_unlock:
>  	igt_flush_test(i915, I915_WAIT_LOCKED);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	return err;
>  
> @@ -374,7 +374,7 @@ static int live_preempt_hang(void *arg)
>  	igt_spinner_fini(&spin_hi);
>  err_unlock:
>  	igt_flush_test(i915, I915_WAIT_LOCKED);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	mutex_unlock(&i915->drm.struct_mutex);
>  	return err;
>  }
> @@ -627,7 +627,7 @@ static int live_preempt_smoke(void *arg)
>  err_batch:
>  	i915_gem_object_put(smoke.batch);
>  err_unlock:
> -	intel_runtime_pm_put(smoke.i915);
> +	intel_runtime_pm_put_unchecked(smoke.i915);
>  	mutex_unlock(&smoke.i915->drm.struct_mutex);
>  	kfree(smoke.contexts);
>  
> diff --git a/drivers/gpu/drm/i915/selftests/intel_workarounds.c b/drivers/gpu/drm/i915/selftests/intel_workarounds.c
> index 8b3f3200a3bd..b1b39c70c702 100644
> --- a/drivers/gpu/drm/i915/selftests/intel_workarounds.c
> +++ b/drivers/gpu/drm/i915/selftests/intel_workarounds.c
> @@ -94,7 +94,7 @@ read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine)
>  
>  	intel_runtime_pm_get(engine->i915);
>  	rq = i915_request_alloc(engine, ctx);
> -	intel_runtime_pm_put(engine->i915);
> +	intel_runtime_pm_put_unchecked(engine->i915);
>  	if (IS_ERR(rq)) {
>  		err = PTR_ERR(rq);
>  		goto err_pin;
> @@ -241,7 +241,7 @@ switch_to_scratch_context(struct intel_engine_cs *engine,
>  	else
>  		rq = i915_request_alloc(engine, ctx);
>  
> -	intel_runtime_pm_put(engine->i915);
> +	intel_runtime_pm_put_unchecked(engine->i915);
>  
>  	kernel_context_close(ctx);
>  
> @@ -300,7 +300,7 @@ static int check_whitelist_across_reset(struct intel_engine_cs *engine,
>  
>  	intel_runtime_pm_get(i915);
>  	err = reset(engine);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  
>  	if (want_spin) {
>  		igt_spinner_end(&spin);
> @@ -414,7 +414,7 @@ live_gpu_reset_gt_engine_workarounds(void *arg)
>  
>  out:
>  	reference_lists_fini(i915, &lists);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	igt_global_reset_unlock(i915);
>  
>  	return ok ? 0 : -ESRCH;
> @@ -496,7 +496,7 @@ live_engine_reset_gt_engine_workarounds(void *arg)
>  
>  err:
>  	reference_lists_fini(i915, &lists);
> -	intel_runtime_pm_put(i915);
> +	intel_runtime_pm_put_unchecked(i915);
>  	igt_global_reset_unlock(i915);
>  	kernel_context_close(ctx);
>  
> -- 
> 2.20.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/21] drm/i915: Track all held rpm wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (20 preceding siblings ...)
  2019-01-10 10:11 ` [PATCH 21/21] drm/i915: Mark up Ironlake ips with rpm wakerefs Chris Wilson
@ 2019-01-10 11:47 ` Patchwork
  2019-01-10 11:54 ` ✗ Fi.CI.SPARSE: " Patchwork
  2019-01-10 12:31 ` ✗ Fi.CI.BAT: failure " Patchwork
  23 siblings, 0 replies; 39+ messages in thread
From: Patchwork @ 2019-01-10 11:47 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/21] drm/i915: Track all held rpm wakerefs
URL   : https://patchwork.freedesktop.org/series/54986/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
7870145b7f82 drm/i915: Track all held rpm wakerefs
-:131: CHECK:UNCOMMENTED_DEFINITION: spinlock_t definition without comment
#131: FILE: drivers/gpu/drm/i915/i915_drv.h:1170:
+		spinlock_t lock;

total: 0 errors, 0 warnings, 1 checks, 639 lines checked
954a33b45c7d drm/i915: Markup paired operations on wakerefs
-:371: WARNING:NEW_TYPEDEFS: do not add new typedefs
#371: FILE: drivers/gpu/drm/i915/i915_drv.h:134:
+typedef depot_stack_handle_t intel_wakeref_t;

total: 0 errors, 1 warnings, 0 checks, 1166 lines checked
58ba2feb0515 drm/i915: Track GT wakeref
a646944f6422 drm/i915: Track the rpm wakerefs for error handling
a9d5508ffe7b drm/i915: Mark up sysfs with rpm wakeref tracking
643ff3ef2e75 drm/i915: Mark up debugfs with rpm wakeref tracking
43e91ef6865e drm/i915/perf: Track the rpm wakeref
cd2cb400338c drm/i915/pmu: Track rpm wakeref
dbc84b458d63 drm/i915/guc: Track the rpm wakeref
d475d5434be3 drm/i915/gem: Track the rpm wakerefs
d30d0a3e3993 drm/i915/fb: Track rpm wakerefs
1b677042aa6e drm/i915/hotplug: Track temporary rpm wakeref
632413ce6bfc drm/i915/panel: Track temporary rpm wakeref
f9b85ebc3896 drm/i915/selftests: Mark up rpm wakerefs
8ecf35c401ff drm/i915: Syntatic sugar for using intel_runtime_pm
-:513: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'i915' - possible side-effects?
#513: FILE: drivers/gpu/drm/i915/intel_drv.h:2190:
+#define with_intel_runtime_pm(i915, wf) \
+	for ((wf) = intel_runtime_pm_get(i915); (wf); \
+	     intel_runtime_pm_put(i915, (wf)), (wf) = 0)

-:513: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'wf' - possible side-effects?
#513: FILE: drivers/gpu/drm/i915/intel_drv.h:2190:
+#define with_intel_runtime_pm(i915, wf) \
+	for ((wf) = intel_runtime_pm_get(i915); (wf); \
+	     intel_runtime_pm_put(i915, (wf)), (wf) = 0)

-:517: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'i915' - possible side-effects?
#517: FILE: drivers/gpu/drm/i915/intel_drv.h:2194:
+#define with_intel_runtime_pm_if_in_use(i915, wf) \
+	for ((wf) = intel_runtime_pm_get_if_in_use(i915); (wf); \
+	     intel_runtime_pm_put(i915, (wf)), (wf) = 0)

-:517: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'wf' - possible side-effects?
#517: FILE: drivers/gpu/drm/i915/intel_drv.h:2194:
+#define with_intel_runtime_pm_if_in_use(i915, wf) \
+	for ((wf) = intel_runtime_pm_get_if_in_use(i915); (wf); \
+	     intel_runtime_pm_put(i915, (wf)), (wf) = 0)

total: 0 errors, 0 warnings, 4 checks, 734 lines checked
adda353c332e drm/i915: Markup paired operations on display power domains
57f1d83af1b8 drm/i915: Track the wakeref used to initialise display power domains
-:214: WARNING:LINE_SPACING: Missing a blank line after declarations
#214: FILE: drivers/gpu/drm/i915/intel_runtime_pm.c:4149:
+	struct i915_power_domains *power_domains = &i915->power_domains;
+	intel_wakeref_t wakeref __maybe_unused =

total: 0 errors, 1 warnings, 0 checks, 324 lines checked
ffcfcfce0a8e drm/i915: Combined gt.awake/gt.power wakerefs
dae8d188692d drm/i915/dp: Markup pps lock power well
-:58: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'dp' - possible side-effects?
#58: FILE: drivers/gpu/drm/i915/intel_dp.c:634:
+#define with_pps_lock(dp, wf) \
+	for (wf = pps_lock(dp); wf; wf = pps_unlock(dp, wf))

-:58: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'wf' - possible side-effects?
#58: FILE: drivers/gpu/drm/i915/intel_dp.c:634:
+#define with_pps_lock(dp, wf) \
+	for (wf = pps_lock(dp); wf; wf = pps_unlock(dp, wf))

total: 0 errors, 0 warnings, 2 checks, 430 lines checked
20a65c10474c drm/i915: Complain if hsw_get_pipe_config acquires the same power well twice
f0e17f7e1c9f drm/i915: Mark up Ironlake ips with rpm wakerefs

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

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

* ✗ Fi.CI.SPARSE: warning for series starting with [01/21] drm/i915: Track all held rpm wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (21 preceding siblings ...)
  2019-01-10 11:47 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/21] drm/i915: Track all held " Patchwork
@ 2019-01-10 11:54 ` Patchwork
  2019-01-10 12:31 ` ✗ Fi.CI.BAT: failure " Patchwork
  23 siblings, 0 replies; 39+ messages in thread
From: Patchwork @ 2019-01-10 11:54 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/21] drm/i915: Track all held rpm wakerefs
URL   : https://patchwork.freedesktop.org/series/54986/
State : warning

== Summary ==

$ dim sparse origin/drm-tip
Sparse version: v0.5.2
Commit: drm/i915: Track all held rpm wakerefs
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3546:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3566:16: warning: expression using sizeof(void)

Commit: drm/i915: Markup paired operations on wakerefs
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3566:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3568:16: warning: expression using sizeof(void)

Commit: drm/i915: Track GT wakeref
Okay!

Commit: drm/i915: Track the rpm wakerefs for error handling
Okay!

Commit: drm/i915: Mark up sysfs with rpm wakeref tracking
Okay!

Commit: drm/i915: Mark up debugfs with rpm wakeref tracking
Okay!

Commit: drm/i915/perf: Track the rpm wakeref
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3568:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3570:16: warning: expression using sizeof(void)

Commit: drm/i915/pmu: Track rpm wakeref
Okay!

Commit: drm/i915/guc: Track the rpm wakeref
Okay!

Commit: drm/i915/gem: Track the rpm wakerefs
Okay!

Commit: drm/i915/fb: Track rpm wakerefs
Okay!

Commit: drm/i915/hotplug: Track temporary rpm wakeref
Okay!

Commit: drm/i915/panel: Track temporary rpm wakeref
Okay!

Commit: drm/i915/selftests: Mark up rpm wakerefs
Okay!

Commit: drm/i915: Syntatic sugar for using intel_runtime_pm
Okay!

Commit: drm/i915: Markup paired operations on display power domains
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3570:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3572:16: warning: expression using sizeof(void)

Commit: drm/i915: Track the wakeref used to initialise display power domains
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3572:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3574:16: warning: expression using sizeof(void)

Commit: drm/i915: Combined gt.awake/gt.power wakerefs
-drivers/gpu/drm/i915/selftests/../i915_drv.h:3574:16: warning: expression using sizeof(void)
+drivers/gpu/drm/i915/selftests/../i915_drv.h:3573:16: warning: expression using sizeof(void)

Commit: drm/i915/dp: Markup pps lock power well
Okay!

Commit: drm/i915: Complain if hsw_get_pipe_config acquires the same power well twice
Okay!

Commit: drm/i915: Mark up Ironlake ips with rpm wakerefs
Okay!

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

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

* ✗ Fi.CI.BAT: failure for series starting with [01/21] drm/i915: Track all held rpm wakerefs
  2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
                   ` (22 preceding siblings ...)
  2019-01-10 11:54 ` ✗ Fi.CI.SPARSE: " Patchwork
@ 2019-01-10 12:31 ` Patchwork
  23 siblings, 0 replies; 39+ messages in thread
From: Patchwork @ 2019-01-10 12:31 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

== Series Details ==

Series: series starting with [01/21] drm/i915: Track all held rpm wakerefs
URL   : https://patchwork.freedesktop.org/series/54986/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_5391 -> Patchwork_11272
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_11272 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_11272, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/54986/revisions/1/

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_11272:

### IGT changes ###

#### Possible regressions ####

  * igt@i915_selftest@live_gtt:
    - fi-bdw-gvtdvm:      PASS -> DMESG-WARN
    - fi-bsw-n3050:       PASS -> DMESG-WARN
    - fi-skl-gvtdvm:      PASS -> DMESG-WARN

  
#### Warnings ####

  * igt@kms_busy@basic-flip-a:
    - fi-kbl-7567u:       PASS -> {SKIP} +2

  * igt@pm_rpm@basic-pci-d3-state:
    - fi-byt-n2820:       {SKIP} -> PASS
    - fi-bsw-kefka:       PASS -> {SKIP}

  
Known issues
------------

  Here are the changes found in Patchwork_11272 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_basic@cs-compute:
    - fi-kbl-8809g:       NOTRUN -> FAIL [fdo#108094]

  * igt@amdgpu/amd_prime@amd-to-i915:
    - fi-kbl-8809g:       NOTRUN -> FAIL [fdo#107341]

  * igt@gem_exec_suspend@basic-s3:
    - fi-blb-e6850:       PASS -> INCOMPLETE [fdo#107718]

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-kbl-7500u:       PASS -> FAIL [fdo#108767]

  * igt@kms_flip@basic-flip-vs-modeset:
    - fi-skl-6700hq:      PASS -> DMESG-WARN [fdo#105998]

  * igt@kms_pipe_crc_basic@read-crc-pipe-a-frame-sequence:
    - fi-byt-clapper:     PASS -> FAIL [fdo#103191] / [fdo#107362]

  * igt@kms_pipe_crc_basic@read-crc-pipe-b:
    - fi-byt-clapper:     PASS -> FAIL [fdo#107362] +1

  * igt@pm_rpm@basic-rte:
    - fi-bsw-kefka:       PASS -> FAIL [fdo#108800]

  
#### Possible fixes ####

  * igt@amdgpu/amd_basic@userptr:
    - fi-kbl-8809g:       DMESG-WARN [fdo#108965] -> PASS

  * igt@i915_selftest@live_hangcheck:
    - fi-bwr-2160:        DMESG-FAIL [fdo#108735] -> PASS

  * igt@kms_frontbuffer_tracking@basic:
    - fi-byt-clapper:     FAIL [fdo#103167] -> PASS

  * igt@pm_rpm@basic-rte:
    - fi-byt-n2820:       FAIL [fdo#108800] -> PASS

  
#### Warnings ####

  * igt@kms_chamelium@common-hpd-after-suspend:
    - fi-kbl-7567u:       DMESG-WARN [fdo#103558] / [fdo#105079] / [fdo#105602] -> DMESG-FAIL [fdo#105079]

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#103191]: https://bugs.freedesktop.org/show_bug.cgi?id=103191
  [fdo#103558]: https://bugs.freedesktop.org/show_bug.cgi?id=103558
  [fdo#104108]: https://bugs.freedesktop.org/show_bug.cgi?id=104108
  [fdo#105079]: https://bugs.freedesktop.org/show_bug.cgi?id=105079
  [fdo#105602]: https://bugs.freedesktop.org/show_bug.cgi?id=105602
  [fdo#105998]: https://bugs.freedesktop.org/show_bug.cgi?id=105998
  [fdo#107341]: https://bugs.freedesktop.org/show_bug.cgi?id=107341
  [fdo#107362]: https://bugs.freedesktop.org/show_bug.cgi?id=107362
  [fdo#107718]: https://bugs.freedesktop.org/show_bug.cgi?id=107718
  [fdo#108094]: https://bugs.freedesktop.org/show_bug.cgi?id=108094
  [fdo#108735]: https://bugs.freedesktop.org/show_bug.cgi?id=108735
  [fdo#108767]: https://bugs.freedesktop.org/show_bug.cgi?id=108767
  [fdo#108800]: https://bugs.freedesktop.org/show_bug.cgi?id=108800
  [fdo#108965]: https://bugs.freedesktop.org/show_bug.cgi?id=108965
  [fdo#109241]: https://bugs.freedesktop.org/show_bug.cgi?id=109241


Participating hosts (50 -> 44)
------------------------------

  Missing    (6): fi-kbl-soraka fi-ilk-m540 fi-byt-squawks fi-bsw-cyan fi-gdg-551 fi-bdw-samus 


Build changes
-------------

    * Linux: CI_DRM_5391 -> Patchwork_11272

  CI_DRM_5391: 301489f99b4cbab3fe70de185a74747e7fca46c3 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_4758: f01796214bbde31e37b0593e547ad9436fdd02ba @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_11272: f0e17f7e1c9f384bad53cb2dd756bb13ca7781d7 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

f0e17f7e1c9f drm/i915: Mark up Ironlake ips with rpm wakerefs
20a65c10474c drm/i915: Complain if hsw_get_pipe_config acquires the same power well twice
dae8d188692d drm/i915/dp: Markup pps lock power well
ffcfcfce0a8e drm/i915: Combined gt.awake/gt.power wakerefs
57f1d83af1b8 drm/i915: Track the wakeref used to initialise display power domains
adda353c332e drm/i915: Markup paired operations on display power domains
8ecf35c401ff drm/i915: Syntatic sugar for using intel_runtime_pm
f9b85ebc3896 drm/i915/selftests: Mark up rpm wakerefs
632413ce6bfc drm/i915/panel: Track temporary rpm wakeref
1b677042aa6e drm/i915/hotplug: Track temporary rpm wakeref
d30d0a3e3993 drm/i915/fb: Track rpm wakerefs
d475d5434be3 drm/i915/gem: Track the rpm wakerefs
dbc84b458d63 drm/i915/guc: Track the rpm wakeref
cd2cb400338c drm/i915/pmu: Track rpm wakeref
43e91ef6865e drm/i915/perf: Track the rpm wakeref
643ff3ef2e75 drm/i915: Mark up debugfs with rpm wakeref tracking
a9d5508ffe7b drm/i915: Mark up sysfs with rpm wakeref tracking
a646944f6422 drm/i915: Track the rpm wakerefs for error handling
58ba2feb0515 drm/i915: Track GT wakeref
954a33b45c7d drm/i915: Markup paired operations on wakerefs
7870145b7f82 drm/i915: Track all held rpm wakerefs

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_11272/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 16/21] drm/i915: Markup paired operations on display power domains
  2019-01-10 10:11 ` [PATCH 16/21] drm/i915: Markup paired operations on display power domains Chris Wilson
@ 2019-01-10 15:51   ` Mika Kuoppala
  2019-01-10 16:21     ` Chris Wilson
  0 siblings, 1 reply; 39+ messages in thread
From: Mika Kuoppala @ 2019-01-10 15:51 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

Chris Wilson <chris@chris-wilson.co.uk> writes:

> The majority of runtime-pm operations are bounded and scoped within a
> function; these are easy to verify that the wakeref are handled
> correctly. We can employ the compiler to help us, and reduce the number
> of wakerefs tracked when debugging, by passing around cookies provided
> by the various rpm_get functions to their rpm_put counterpart. This
> makes the pairing explicit, and given the required wakeref cookie the
> compiler can verify that we pass an initialised value to the rpm_put
> (quite handy for double checking error paths).
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c     | 35 ++++++------
>  drivers/gpu/drm/i915/i915_drv.h         |  2 +
>  drivers/gpu/drm/i915/i915_gem.c         |  4 +-
>  drivers/gpu/drm/i915/icl_dsi.c          | 36 ++++++++-----
>  drivers/gpu/drm/i915/intel_audio.c      |  3 +-
>  drivers/gpu/drm/i915/intel_cdclk.c      | 10 ++--
>  drivers/gpu/drm/i915/intel_crt.c        | 25 +++++----
>  drivers/gpu/drm/i915/intel_csr.c        | 25 +++++++--
>  drivers/gpu/drm/i915/intel_ddi.c        | 36 ++++++++-----
>  drivers/gpu/drm/i915/intel_display.c    | 68 ++++++++++++++---------
>  drivers/gpu/drm/i915/intel_dp.c         | 38 +++++++------
>  drivers/gpu/drm/i915/intel_dpll_mgr.c   | 66 +++++++++++++++--------
>  drivers/gpu/drm/i915/intel_drv.h        | 17 ++++--
>  drivers/gpu/drm/i915/intel_dsi.h        |  1 +
>  drivers/gpu/drm/i915/intel_hdmi.c       | 18 ++++---
>  drivers/gpu/drm/i915/intel_i2c.c        | 20 +++----
>  drivers/gpu/drm/i915/intel_lvds.c       |  8 +--
>  drivers/gpu/drm/i915/intel_pipe_crc.c   |  6 ++-
>  drivers/gpu/drm/i915/intel_pm.c         |  6 ++-
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 71 ++++++++++++++++---------
>  drivers/gpu/drm/i915/intel_sprite.c     | 24 ++++++---
>  drivers/gpu/drm/i915/intel_vdsc.c       |  4 +-
>  drivers/gpu/drm/i915/vlv_dsi.c          | 14 +++--
>  23 files changed, 347 insertions(+), 190 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 34cbd9a20583..b7dcacf2a5d3 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -626,10 +626,12 @@ static void gen8_display_interrupt_info(struct seq_file *m)
>  
>  	for_each_pipe(dev_priv, pipe) {
>  		enum intel_display_power_domain power_domain;
> +		intel_wakeref_t wakeref;
>  
>  		power_domain = POWER_DOMAIN_PIPE(pipe);
> -		if (!intel_display_power_get_if_enabled(dev_priv,
> -							power_domain)) {
> +		wakeref = intel_display_power_get_if_enabled(dev_priv,
> +							     power_domain);
> +		if (!wakeref) {
>  			seq_printf(m, "Pipe %c power disabled\n",
>  				   pipe_name(pipe));
>  			continue;
> @@ -644,7 +646,7 @@ static void gen8_display_interrupt_info(struct seq_file *m)
>  			   pipe_name(pipe),
>  			   I915_READ(GEN8_DE_PIPE_IER(pipe)));
>  
> -		intel_display_power_put(dev_priv, power_domain);
> +		intel_display_power_put(dev_priv, power_domain, wakeref);
>  	}
>  
>  	seq_printf(m, "Display Engine port interrupt mask:\t%08x\n",
> @@ -680,6 +682,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>  	wakeref = intel_runtime_pm_get(dev_priv);
>  
>  	if (IS_CHERRYVIEW(dev_priv)) {
> +		intel_wakeref_t pref;
> +

In here you are introducing a new, descriptive, power reference for display.
But then you drop it after using it twice. And can't seem to find
reason for inconsistency.

>  		seq_printf(m, "Master Interrupt Control:\t%08x\n",
>  			   I915_READ(GEN8_MASTER_IRQ));
>  
> @@ -695,8 +699,9 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>  			enum intel_display_power_domain power_domain;
>  
>  			power_domain = POWER_DOMAIN_PIPE(pipe);
> -			if (!intel_display_power_get_if_enabled(dev_priv,
> -								power_domain)) {
> +			pref = intel_display_power_get_if_enabled(dev_priv,
> +								  power_domain);
> +			if (!pref) {
>  				seq_printf(m, "Pipe %c power disabled\n",
>  					   pipe_name(pipe));
>  				continue;
> @@ -706,17 +711,17 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>  				   pipe_name(pipe),
>  				   I915_READ(PIPESTAT(pipe)));
>  
> -			intel_display_power_put(dev_priv, power_domain);
> +			intel_display_power_put(dev_priv, power_domain, pref);
>  		}
>  
> -		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +		pref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
>  		seq_printf(m, "Port hotplug:\t%08x\n",
>  			   I915_READ(PORT_HOTPLUG_EN));
>  		seq_printf(m, "DPFLIPSTAT:\t%08x\n",
>  			   I915_READ(VLV_DPFLIPSTAT));
>  		seq_printf(m, "DPINVGTT:\t%08x\n",
>  			   I915_READ(DPINVGTT));
> -		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, pref);
>  
>  		for (i = 0; i < 4; i++) {
>  			seq_printf(m, "GT Interrupt IMR %d:\t%08x\n",
> @@ -779,10 +784,12 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>  			   I915_READ(VLV_IMR));
>  		for_each_pipe(dev_priv, pipe) {
>  			enum intel_display_power_domain power_domain;
> +			intel_wakeref_t pref;
>  
>  			power_domain = POWER_DOMAIN_PIPE(pipe);
> -			if (!intel_display_power_get_if_enabled(dev_priv,
> -								power_domain)) {
> +			pref = intel_display_power_get_if_enabled(dev_priv,
> +								  power_domain);
> +			if (!pref) {
>  				seq_printf(m, "Pipe %c power disabled\n",
>  					   pipe_name(pipe));
>  				continue;
> @@ -791,7 +798,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>  			seq_printf(m, "Pipe %c stat:\t%08x\n",
>  				   pipe_name(pipe),
>  				   I915_READ(PIPESTAT(pipe)));
> -			intel_display_power_put(dev_priv, power_domain);
> +			intel_display_power_put(dev_priv, power_domain, pref);
>  		}
>  
>  		seq_printf(m, "Master IER:\t%08x\n",
> @@ -1709,8 +1716,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
>  	intel_wakeref_t wakeref;
>  	bool sr_enabled = false;
>  
> -	wakeref = intel_runtime_pm_get(dev_priv);
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
>  
>  	if (INTEL_GEN(dev_priv) >= 9)
>  		/* no global SR status; inspect per-plane WM */;
> @@ -1726,8 +1732,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
>  	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>  		sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> -	intel_runtime_pm_put(dev_priv, wakeref);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
>  
>  	seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index f0a405604b75..44c1b21febba 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -344,6 +344,7 @@ struct intel_csr {
>  	uint32_t mmiodata[8];
>  	uint32_t dc_state;
>  	uint32_t allowed_dc_mask;
> +	intel_wakeref_t wakeref;
>  };
>  
>  enum i915_cache_level {
> @@ -1982,6 +1983,7 @@ struct drm_i915_private {
>  		 * is a slight delay before we do so.
>  		 */
>  		intel_wakeref_t awake;
> +		intel_wakeref_t power;

This prolly explains the prefs above :)

>  
>  		/**
>  		 * The number of times we have woken up.
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 67fd119bdad8..5ed1c8576525 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -176,7 +176,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
>  	if (INTEL_GEN(i915) >= 6)
>  		gen6_rps_idle(i915);
>  
> -	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ);
> +	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, i915->gt.power);
>  
>  	intel_runtime_pm_put(i915, wakeref);
>  
> @@ -221,7 +221,7 @@ void i915_gem_unpark(struct drm_i915_private *i915)
>  	 * Work around it by grabbing a GT IRQ power domain whilst there is any
>  	 * GT activity, preventing any DC state transitions.
>  	 */
> -	intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
> +	i915->gt.power = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
>  
>  	if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */
>  		i915->gt.epoch = 1;
> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
> index 4dd793b78996..f3a5f03646ce 100644
> --- a/drivers/gpu/drm/i915/icl_dsi.c
> +++ b/drivers/gpu/drm/i915/icl_dsi.c
> @@ -337,9 +337,11 @@ static void gen11_dsi_enable_io_power(struct intel_encoder *encoder)
>  	}
>  
>  	for_each_dsi_port(port, intel_dsi->ports) {
> -		intel_display_power_get(dev_priv, port == PORT_A ?
> -					POWER_DOMAIN_PORT_DDI_A_IO :
> -					POWER_DOMAIN_PORT_DDI_B_IO);
> +		intel_dsi->io_wakeref[port] =
> +			intel_display_power_get(dev_priv,
> +						port == PORT_A ?
> +						POWER_DOMAIN_PORT_DDI_A_IO :
> +						POWER_DOMAIN_PORT_DDI_B_IO);
>  	}
>  }
>  
> @@ -1125,10 +1127,18 @@ static void gen11_dsi_disable_io_power(struct intel_encoder *encoder)
>  	enum port port;
>  	u32 tmp;
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_A_IO);
> -
> -	if (intel_dsi->dual_link)
> -		intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_B_IO);
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		intel_wakeref_t wakeref;
> +
> +		wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]);
> +		if (wakeref) {
> +			intel_display_power_put(dev_priv,
> +						port == PORT_A ?
> +						POWER_DOMAIN_PORT_DDI_A_IO :
> +						POWER_DOMAIN_PORT_DDI_B_IO,
> +						wakeref);
> +		}
> +	}

Ok, well. I have been trying to figure out what really is going on here.

First it seems that you fix a bug. We take refs for each dsi port but
only release once special casing 'dual_link' without this patch.

Second, all the hw access is before getting the refs, looking
suspicious.

>  
>  	/* set mode to DDI */
>  	for_each_dsi_port(port, intel_dsi->ports) {
> @@ -1229,13 +1239,15 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> -	u32 tmp;
> -	enum port port;
>  	enum transcoder dsi_trans;
> +	intel_wakeref_t wakeref;
> +	enum port port;
>  	bool ret = false;
> +	u32 tmp;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv,
> -						encoder->power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     encoder->power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	for_each_dsi_port(port, intel_dsi->ports) {
> @@ -1260,7 +1272,7 @@ static bool gen11_dsi_get_hw_state(struct intel_encoder *encoder,
>  		ret = tmp & PIPECONF_ENABLE;
>  	}
>  out:
> -	intel_display_power_put(dev_priv, encoder->power_domain);
> +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  	return ret;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
> index 202a58cf2d9f..de26cd0a5497 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -748,7 +748,8 @@ static void i915_audio_component_get_power(struct device *kdev)
>  
>  static void i915_audio_component_put_power(struct device *kdev)
>  {
> -	intel_display_power_put(kdev_to_i915(kdev), POWER_DOMAIN_AUDIO);
> +	intel_display_power_put_unchecked(kdev_to_i915(kdev),
> +					  POWER_DOMAIN_AUDIO);
>  }
>  
>  static void i915_audio_component_codec_wake_override(struct device *kdev,
> diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c
> index 2021e484a287..73cb7250118e 100644
> --- a/drivers/gpu/drm/i915/intel_cdclk.c
> +++ b/drivers/gpu/drm/i915/intel_cdclk.c
> @@ -520,6 +520,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
>  {
>  	int cdclk = cdclk_state->cdclk;
>  	u32 val, cmd = cdclk_state->voltage_level;
> +	intel_wakeref_t wakeref;
>  
>  	switch (cdclk) {
>  	case 400000:
> @@ -539,7 +540,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
>  	 * a system suspend.  So grab the PIPE-A domain, which covers
>  	 * the HW blocks needed for the following programming.
>  	 */
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
>  
>  	mutex_lock(&dev_priv->pcu_lock);
>  	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> @@ -593,7 +594,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
>  
>  	vlv_program_pfi_credits(dev_priv);
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A, wakeref);
>  }
>  
>  static void chv_set_cdclk(struct drm_i915_private *dev_priv,
> @@ -601,6 +602,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
>  {
>  	int cdclk = cdclk_state->cdclk;
>  	u32 val, cmd = cdclk_state->voltage_level;
> +	intel_wakeref_t wakeref;
>  
>  	switch (cdclk) {
>  	case 333333:
> @@ -619,7 +621,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
>  	 * a system suspend.  So grab the PIPE-A domain, which covers
>  	 * the HW blocks needed for the following programming.
>  	 */
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
>  
>  	mutex_lock(&dev_priv->pcu_lock);
>  	val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ);
> @@ -637,7 +639,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
>  
>  	vlv_program_pfi_credits(dev_priv);
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PIPE_A, wakeref);
>  }
>  
>  static int bdw_calc_cdclk(int min_cdclk)
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 951e9bae6921..33bd2addcbdd 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -83,15 +83,17 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	struct intel_crt *crt = intel_encoder_to_crt(encoder);
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv,
> -						encoder->power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     encoder->power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = intel_crt_port_enabled(dev_priv, crt->adpa_reg, pipe);
>  
> -	intel_display_power_put(dev_priv, encoder->power_domain);
> +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -776,6 +778,7 @@ intel_crt_detect(struct drm_connector *connector,
>  	struct drm_i915_private *dev_priv = to_i915(connector->dev);
>  	struct intel_crt *crt = intel_attached_crt(connector);
>  	struct intel_encoder *intel_encoder = &crt->base;
> +	intel_wakeref_t wakeref;
>  	int status, ret;
>  	struct intel_load_detect_pipe tmp;
>  
> @@ -784,7 +787,8 @@ intel_crt_detect(struct drm_connector *connector,
>  		      force);
>  
>  	if (i915_modparams.load_detect_test) {
> -		intel_display_power_get(dev_priv, intel_encoder->power_domain);
> +		wakeref = intel_display_power_get(dev_priv,
> +						  intel_encoder->power_domain);
>  		goto load_detect;
>  	}
>  
> @@ -792,7 +796,8 @@ intel_crt_detect(struct drm_connector *connector,
>  	if (dmi_check_system(intel_spurious_crt_detect))
>  		return connector_status_disconnected;
>  
> -	intel_display_power_get(dev_priv, intel_encoder->power_domain);
> +	wakeref = intel_display_power_get(dev_priv,
> +					  intel_encoder->power_domain);
>  
>  	if (I915_HAS_HOTPLUG(dev_priv)) {
>  		/* We can not rely on the HPD pin always being correctly wired
> @@ -847,7 +852,7 @@ intel_crt_detect(struct drm_connector *connector,
>  	}
>  
>  out:
> -	intel_display_power_put(dev_priv, intel_encoder->power_domain);
> +	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
>  	return status;
>  }
>  
> @@ -857,10 +862,12 @@ static int intel_crt_get_modes(struct drm_connector *connector)
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	struct intel_crt *crt = intel_attached_crt(connector);
>  	struct intel_encoder *intel_encoder = &crt->base;
> -	int ret;
> +	intel_wakeref_t wakeref;
>  	struct i2c_adapter *i2c;
> +	int ret;
>  
> -	intel_display_power_get(dev_priv, intel_encoder->power_domain);
> +	wakeref = intel_display_power_get(dev_priv,
> +					  intel_encoder->power_domain);
>  
>  	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
>  	ret = intel_crt_ddc_get_modes(connector, i2c);
> @@ -872,7 +879,7 @@ static int intel_crt_get_modes(struct drm_connector *connector)
>  	ret = intel_crt_ddc_get_modes(connector, i2c);
>  
>  out:
> -	intel_display_power_put(dev_priv, intel_encoder->power_domain);
> +	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c
> index a516697bf57d..ea5fb64d33dd 100644
> --- a/drivers/gpu/drm/i915/intel_csr.c
> +++ b/drivers/gpu/drm/i915/intel_csr.c
> @@ -409,6 +409,21 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
>  	return memcpy(dmc_payload, &fw->data[readcount], nbytes);
>  }
>  
> +static void intel_csr_runtime_pm_get(struct drm_i915_private *dev_priv)
> +{
> +	WARN_ON(dev_priv->csr.wakeref);
> +	dev_priv->csr.wakeref =
> +		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +}
> +
> +static void intel_csr_runtime_pm_put(struct drm_i915_private *dev_priv)
> +{
> +	intel_wakeref_t wakeref __maybe_unused =
> +		fetch_and_zero(&dev_priv->csr.wakeref);
> +
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
> +}
> +
>  static void csr_load_work_fn(struct work_struct *work)
>  {
>  	struct drm_i915_private *dev_priv;
> @@ -424,8 +439,7 @@ static void csr_load_work_fn(struct work_struct *work)
>  
>  	if (dev_priv->csr.dmc_payload) {
>  		intel_csr_load_program(dev_priv);
> -
> -		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +		intel_csr_runtime_pm_put(dev_priv);
>  
>  		DRM_INFO("Finished loading DMC firmware %s (v%u.%u)\n",
>  			 dev_priv->csr.fw_path,
> @@ -467,7 +481,7 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
>  	 * suspend as runtime suspend *requires* a working CSR for whatever
>  	 * reason.
>  	 */
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +	intel_csr_runtime_pm_get(dev_priv);
>  
>  	if (INTEL_GEN(dev_priv) >= 12) {
>  		/* Allow to load fw via parameter using the last known size */
> @@ -538,7 +552,7 @@ void intel_csr_ucode_suspend(struct drm_i915_private *dev_priv)
>  
>  	/* Drop the reference held in case DMC isn't loaded. */
>  	if (!dev_priv->csr.dmc_payload)
> -		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +		intel_csr_runtime_pm_put(dev_priv);
>  }
>  
>  /**
> @@ -558,7 +572,7 @@ void intel_csr_ucode_resume(struct drm_i915_private *dev_priv)
>  	 * loaded.
>  	 */
>  	if (!dev_priv->csr.dmc_payload)
> -		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +		intel_csr_runtime_pm_get(dev_priv);
>  }
>  
>  /**
> @@ -574,6 +588,7 @@ void intel_csr_ucode_fini(struct drm_i915_private *dev_priv)
>  		return;
>  
>  	intel_csr_ucode_suspend(dev_priv);
> +	WARN_ON(dev_priv->csr.wakeref);
>  
>  	kfree(dev_priv->csr.dmc_payload);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 2d6ed990a232..7f3cd055de50 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1860,12 +1860,14 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
>  {
>  	struct drm_device *dev = intel_encoder->base.dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> +	intel_wakeref_t wakeref;
>  	enum pipe pipe = 0;
>  	int ret = 0;
>  	uint32_t tmp;
>  
> -	if (WARN_ON(!intel_display_power_get_if_enabled(dev_priv,
> -						intel_encoder->power_domain)))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     intel_encoder->power_domain);
> +	if (WARN_ON(!wakeref))
>  		return -ENXIO;
>  
>  	if (WARN_ON(!intel_encoder->get_hw_state(intel_encoder, &pipe))) {
> @@ -1880,7 +1882,7 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
>  		tmp &= ~TRANS_DDI_HDCP_SIGNALLING;
>  	I915_WRITE(TRANS_DDI_FUNC_CTL(pipe), tmp);
>  out:
> -	intel_display_power_put(dev_priv, intel_encoder->power_domain);
> +	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
>  	return ret;
>  }
>  
> @@ -1891,13 +1893,15 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
>  	struct intel_encoder *encoder = intel_connector->encoder;
>  	int type = intel_connector->base.connector_type;
>  	enum port port = encoder->port;
> -	enum pipe pipe = 0;
>  	enum transcoder cpu_transcoder;
> +	intel_wakeref_t wakeref;
> +	enum pipe pipe = 0;
>  	uint32_t tmp;
>  	bool ret;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv,
> -						encoder->power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     encoder->power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	if (!encoder->get_hw_state(encoder, &pipe)) {
> @@ -1939,7 +1943,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
>  	}
>  
>  out:
> -	intel_display_power_put(dev_priv, encoder->power_domain);
> +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -1950,6 +1954,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
>  	struct drm_device *dev = encoder->base.dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	enum port port = encoder->port;
> +	intel_wakeref_t wakeref;
>  	enum pipe p;
>  	u32 tmp;
>  	u8 mst_pipe_mask;
> @@ -1957,8 +1962,9 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
>  	*pipe_mask = 0;
>  	*is_dp_mst = false;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv,
> -						encoder->power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     encoder->power_domain);
> +	if (!wakeref)
>  		return;
>  
>  	tmp = I915_READ(DDI_BUF_CTL(port));
> @@ -2029,7 +2035,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
>  				  "(PHY_CTL %08x)\n", port_name(port), tmp);
>  	}
>  
> -	intel_display_power_put(dev_priv, encoder->power_domain);
> +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  }
>  
>  bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
> @@ -3286,7 +3292,8 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,
>  	intel_edp_panel_vdd_on(intel_dp);
>  	intel_edp_panel_off(intel_dp);
>  
> -	intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain);
> +	intel_display_power_put_unchecked(dev_priv,
> +					  dig_port->ddi_io_power_domain);
>  
>  	intel_ddi_clk_disable(encoder);
>  }
> @@ -3306,7 +3313,8 @@ static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder,
>  
>  	intel_disable_ddi_buf(encoder, old_crtc_state);
>  
> -	intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain);
> +	intel_display_power_put_unchecked(dev_priv,
> +					  dig_port->ddi_io_power_domain);
>  
>  	intel_ddi_clk_disable(encoder);
>  
> @@ -3626,8 +3634,8 @@ intel_ddi_post_pll_disable(struct intel_encoder *encoder,
>  
>  	if (intel_crtc_has_dp_encoder(crtc_state) ||
>  	    intel_port_is_tc(dev_priv, encoder->port))
> -		intel_display_power_put(dev_priv,
> -					intel_ddi_main_link_aux_domain(dig_port));
> +		intel_display_power_put_unchecked(dev_priv,
> +						  intel_ddi_main_link_aux_domain(dig_port));
>  }
>  
>  void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index b0b8f9ffd873..36c56d1637b8 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1197,17 +1197,19 @@ void assert_pipe(struct drm_i915_private *dev_priv,
>  	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
>  								      pipe);
>  	enum intel_display_power_domain power_domain;
> +	intel_wakeref_t wakeref;
>  
>  	/* we keep both pipes enabled on 830 */
>  	if (IS_I830(dev_priv))
>  		state = true;
>  
>  	power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
> -	if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (wakeref) {
>  		u32 val = I915_READ(PIPECONF(cpu_transcoder));
>  		cur_state = !!(val & PIPECONF_ENABLE);
>  
> -		intel_display_power_put(dev_priv, power_domain);
> +		intel_display_power_put(dev_priv, power_domain, wakeref);
>  	} else {
>  		cur_state = false;
>  	}
> @@ -3412,6 +3414,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>  	enum intel_display_power_domain power_domain;
>  	enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  	u32 val;
>  
> @@ -3421,7 +3424,8 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
>  	 * display power wells.
>  	 */
>  	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	val = I915_READ(DSPCNTR(i9xx_plane));
> @@ -3434,7 +3438,7 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
>  		*pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
>  			DISPPLANE_SEL_PIPE_SHIFT;
>  
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -6107,7 +6111,7 @@ static void modeset_put_power_domains(struct drm_i915_private *dev_priv,
>  	enum intel_display_power_domain domain;
>  
>  	for_each_power_domain(domain, domains)
> -		intel_display_power_put(dev_priv, domain);
> +		intel_display_power_put_unchecked(dev_priv, domain);
>  }
>  
>  static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
> @@ -6354,7 +6358,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
>  
>  	domains = intel_crtc->enabled_power_domains;
>  	for_each_power_domain(domain, domains)
> -		intel_display_power_put(dev_priv, domain);
> +		intel_display_power_put_unchecked(dev_priv, domain);
>  	intel_crtc->enabled_power_domains = 0;
>  
>  	dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
> @@ -7966,11 +7970,13 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>  	enum intel_display_power_domain power_domain;
> +	intel_wakeref_t wakeref;
>  	uint32_t tmp;
>  	bool ret;
>  
>  	power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> @@ -8071,7 +8077,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
>  	ret = true;
>  
>  out:
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -9038,11 +9044,13 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
>  	struct drm_device *dev = crtc->base.dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
>  	enum intel_display_power_domain power_domain;
> +	intel_wakeref_t wakeref;
>  	uint32_t tmp;
>  	bool ret;
>  
>  	power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
> @@ -9125,7 +9133,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
>  	ret = true;
>  
>  out:
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -9734,7 +9742,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>  
>  out:
>  	for_each_power_domain(power_domain, power_domain_mask)
> -		intel_display_power_put(dev_priv, power_domain);
> +		intel_display_power_put_unchecked(dev_priv, power_domain);
>  
>  	return active;
>  }
> @@ -9984,17 +9992,19 @@ static bool i845_cursor_get_hw_state(struct intel_plane *plane,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>  	enum intel_display_power_domain power_domain;
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
>  	power_domain = POWER_DOMAIN_PIPE(PIPE_A);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
>  
>  	*pipe = PIPE_A;
>  
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -10217,6 +10227,7 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>  	enum intel_display_power_domain power_domain;
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  	u32 val;
>  
> @@ -10226,7 +10237,8 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
>  	 * display power wells.
>  	 */
>  	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	val = I915_READ(CURCNTR(plane->pipe));
> @@ -10239,7 +10251,7 @@ static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
>  		*pipe = (val & MCURSOR_PIPE_SELECT_MASK) >>
>  			MCURSOR_PIPE_SELECT_SHIFT;
>  
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -12950,6 +12962,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
>  	struct drm_crtc *crtc;
>  	struct intel_crtc *intel_crtc;
>  	u64 put_domains[I915_MAX_PIPES] = {};
> +	intel_wakeref_t wakeref = 0;
>  	int i;
>  
>  	intel_atomic_commit_fence_wait(intel_state);
> @@ -12957,7 +12970,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
>  	drm_atomic_helper_wait_for_dependencies(state);
>  
>  	if (intel_state->modeset)
> -		intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
> +		wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
>  
>  	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
>  		old_intel_crtc_state = to_intel_crtc_state(old_crtc_state);
> @@ -13094,7 +13107,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
>  		 * the culprit.
>  		 */
>  		intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
> -		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
> +		intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, wakeref);
>  	}
>  
>  	/*
> @@ -15496,19 +15509,25 @@ void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv)
>  
>  void i915_redisable_vga(struct drm_i915_private *dev_priv)
>  {
> -	/* This function can be called both from intel_modeset_setup_hw_state or
> +	intel_wakeref_t wakeref;
> +
> +	/*
> +	 * This function can be called both from intel_modeset_setup_hw_state or
>  	 * at a very early point in our resume sequence, where the power well
>  	 * structures are not yet restored. Since this function is at a very
>  	 * paranoid "someone might have enabled VGA while we were not looking"
>  	 * level, just check if the power well is enabled instead of trying to
>  	 * follow the "don't touch the power well if we don't need it" policy
> -	 * the rest of the driver uses. */
> -	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA))
> +	 * the rest of the driver uses.
> +	 */
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     POWER_DOMAIN_VGA);
> +	if (!wakeref)
>  		return;
>  
>  	i915_redisable_vga_power_on(dev_priv);
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_VGA, wakeref);
>  }
>  
>  /* FIXME read out full plane state for all planes */
> @@ -15808,12 +15827,13 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
>  			     struct drm_modeset_acquire_ctx *ctx)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> -	struct intel_crtc *crtc;
>  	struct intel_crtc_state *crtc_state;
>  	struct intel_encoder *encoder;
> +	struct intel_crtc *crtc;

Not that I mind but I don't understand the reasoning
behind the change of order on this and on few other places in this
patch.


> +	intel_wakeref_t wakeref;
>  	int i;
>  
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
>  
>  	intel_early_display_was(dev_priv);
>  	intel_modeset_readout_hw_state(dev);
> @@ -15883,7 +15903,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
>  			modeset_put_power_domains(dev_priv, put_domains);
>  	}
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref);
>  
>  	intel_fbc_init_pipe_state(dev_priv);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index d3cd40e656fe..fc85fd77a661 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -621,8 +621,8 @@ static void pps_unlock(struct intel_dp *intel_dp)
>  
>  	mutex_unlock(&dev_priv->pps_mutex);
>  
> -	intel_display_power_put(dev_priv,
> -				intel_aux_power_domain(dp_to_dig_port(intel_dp)));
> +	intel_display_power_put_unchecked(dev_priv,
> +					  intel_aux_power_domain(dp_to_dig_port(intel_dp)));
>  }
>  
>  static void
> @@ -2511,8 +2511,8 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
>  	if ((pp & PANEL_POWER_ON) == 0)
>  		intel_dp->panel_power_off_time = ktime_get_boottime();
>  
> -	intel_display_power_put(dev_priv,
> -				intel_aux_power_domain(intel_dig_port));
> +	intel_display_power_put_unchecked(dev_priv,
> +					  intel_aux_power_domain(intel_dig_port));
>  }
>  
>  static void edp_panel_vdd_work(struct work_struct *__work)
> @@ -2657,7 +2657,7 @@ static void edp_panel_off(struct intel_dp *intel_dp)
>  	intel_dp->panel_power_off_time = ktime_get_boottime();
>  
>  	/* We got a reference when we enabled the VDD. */
> -	intel_display_power_put(dev_priv, intel_aux_power_domain(dig_port));
> +	intel_display_power_put_unchecked(dev_priv, intel_aux_power_domain(dig_port));
>  }
>  
>  void intel_edp_panel_off(struct intel_dp *intel_dp)
> @@ -2983,16 +2983,18 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv,
> -						encoder->power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     encoder->power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = intel_dp_port_enabled(dev_priv, intel_dp->output_reg,
>  				    encoder->port, pipe);
>  
> -	intel_display_power_put(dev_priv, encoder->power_domain);
> +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -5365,12 +5367,13 @@ intel_dp_detect(struct drm_connector *connector,
>  	enum drm_connector_status status;
>  	enum intel_display_power_domain aux_domain =
>  		intel_aux_power_domain(dig_port);
> +	intel_wakeref_t wakeref;
>  
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>  		      connector->base.id, connector->name);
>  	WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
>  
> -	intel_display_power_get(dev_priv, aux_domain);
> +	wakeref = intel_display_power_get(dev_priv, aux_domain);
>  
>  	/* Can't disconnect eDP */
>  	if (intel_dp_is_edp(intel_dp))
> @@ -5436,7 +5439,7 @@ intel_dp_detect(struct drm_connector *connector,
>  
>  		ret = intel_dp_retrain_link(encoder, ctx);
>  		if (ret) {
> -			intel_display_power_put(dev_priv, aux_domain);
> +			intel_display_power_put(dev_priv, aux_domain, wakeref);
>  			return ret;
>  		}
>  	}
> @@ -5460,7 +5463,7 @@ intel_dp_detect(struct drm_connector *connector,
>  	if (status != connector_status_connected && !intel_dp->is_mst)
>  		intel_dp_unset_edid(intel_dp);
>  
> -	intel_display_power_put(dev_priv, aux_domain);
> +	intel_display_power_put(dev_priv, aux_domain, wakeref);
>  	return status;
>  }
>  
> @@ -5473,6 +5476,7 @@ intel_dp_force(struct drm_connector *connector)
>  	struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
>  	enum intel_display_power_domain aux_domain =
>  		intel_aux_power_domain(dig_port);
> +	intel_wakeref_t wakeref;
>  
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>  		      connector->base.id, connector->name);
> @@ -5481,11 +5485,11 @@ intel_dp_force(struct drm_connector *connector)
>  	if (connector->status != connector_status_connected)
>  		return;
>  
> -	intel_display_power_get(dev_priv, aux_domain);
> +	wakeref = intel_display_power_get(dev_priv, aux_domain);
>  
>  	intel_dp_set_edid(intel_dp);
>  
> -	intel_display_power_put(dev_priv, aux_domain);
> +	intel_display_power_put(dev_priv, aux_domain, wakeref);
>  }
>  
>  static int intel_dp_get_modes(struct drm_connector *connector)
> @@ -5931,6 +5935,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
>  	struct intel_dp *intel_dp = &intel_dig_port->dp;
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	enum irqreturn ret = IRQ_NONE;
> +	intel_wakeref_t wakeref;
>  
>  	if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {
>  		/*
> @@ -5953,8 +5958,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
>  		return IRQ_NONE;
>  	}
>  
> -	intel_display_power_get(dev_priv,
> -				intel_aux_power_domain(intel_dig_port));
> +	wakeref = intel_display_power_get(dev_priv,
> +					  intel_aux_power_domain(intel_dig_port));
>  
>  	if (intel_dp->is_mst) {
>  		if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
> @@ -5984,7 +5989,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
>  
>  put_power:
>  	intel_display_power_put(dev_priv,
> -				intel_aux_power_domain(intel_dig_port));
> +				intel_aux_power_domain(intel_dig_port),
> +				wakeref);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> index d513ca875c67..04870e960537 100644
> --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
> +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
> @@ -345,9 +345,12 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
>  				      struct intel_dpll_hw_state *hw_state)
>  {
>  	const enum intel_dpll_id id = pll->info->id;
> +	intel_wakeref_t wakeref;
>  	uint32_t val;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     POWER_DOMAIN_PLLS);
> +	if (!wakeref)
>  		return false;
>  
>  	val = I915_READ(PCH_DPLL(id));
> @@ -355,7 +358,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
>  	hw_state->fp0 = I915_READ(PCH_FP0(id));
>  	hw_state->fp1 = I915_READ(PCH_FP1(id));
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>  	return val & DPLL_VCO_ENABLE;
>  }
> @@ -509,15 +512,18 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
>  				       struct intel_dpll_hw_state *hw_state)
>  {
>  	const enum intel_dpll_id id = pll->info->id;
> +	intel_wakeref_t wakeref;
>  	uint32_t val;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     POWER_DOMAIN_PLLS);
> +	if (!wakeref)
>  		return false;
>  
>  	val = I915_READ(WRPLL_CTL(id));
>  	hw_state->wrpll = val;
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>  	return val & WRPLL_PLL_ENABLE;
>  }
> @@ -526,15 +532,18 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
>  				      struct intel_shared_dpll *pll,
>  				      struct intel_dpll_hw_state *hw_state)
>  {
> +	intel_wakeref_t wakeref;
>  	uint32_t val;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     POWER_DOMAIN_PLLS);
> +	if (!wakeref)
>  		return false;
>  
>  	val = I915_READ(SPLL_CTL);
>  	hw_state->spll = val;
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>  	return val & SPLL_PLL_ENABLE;
>  }
> @@ -989,9 +998,12 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
>  	uint32_t val;
>  	const struct skl_dpll_regs *regs = skl_dpll_regs;
>  	const enum intel_dpll_id id = pll->info->id;
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     POWER_DOMAIN_PLLS);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = false;
> @@ -1011,7 +1023,7 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
>  	ret = true;
>  
>  out:
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>  	return ret;
>  }
> @@ -1020,12 +1032,15 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
>  				       struct intel_shared_dpll *pll,
>  				       struct intel_dpll_hw_state *hw_state)
>  {
> -	uint32_t val;
>  	const struct skl_dpll_regs *regs = skl_dpll_regs;
>  	const enum intel_dpll_id id = pll->info->id;
> +	intel_wakeref_t wakeref;
> +	uint32_t val;
>  	bool ret;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     POWER_DOMAIN_PLLS);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = false;
> @@ -1041,7 +1056,7 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
>  	ret = true;
>  
>  out:
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>  	return ret;
>  }
> @@ -1579,14 +1594,17 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
>  					struct intel_dpll_hw_state *hw_state)
>  {
>  	enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
> -	uint32_t val;
> -	bool ret;
> +	intel_wakeref_t wakeref;
>  	enum dpio_phy phy;
>  	enum dpio_channel ch;
> +	uint32_t val;
> +	bool ret;
>  
>  	bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     POWER_DOMAIN_PLLS);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = false;
> @@ -1643,7 +1661,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
>  	ret = true;
>  
>  out:
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>  	return ret;
>  }
> @@ -2091,10 +2109,13 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
>  				     struct intel_dpll_hw_state *hw_state)
>  {
>  	const enum intel_dpll_id id = pll->info->id;
> +	intel_wakeref_t wakeref;
>  	uint32_t val;
>  	bool ret;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     POWER_DOMAIN_PLLS);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = false;
> @@ -2113,7 +2134,7 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
>  	ret = true;
>  
>  out:
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  
>  	return ret;
>  }
> @@ -2950,11 +2971,14 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
>  				 struct intel_dpll_hw_state *hw_state)
>  {
>  	const enum intel_dpll_id id = pll->info->id;
> -	uint32_t val;
> -	enum port port;
> +	intel_wakeref_t wakeref;
>  	bool ret = false;
> +	enum port port;
> +	uint32_t val;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     POWER_DOMAIN_PLLS);
> +	if (!wakeref)
>  		return false;
>  
>  	val = I915_READ(icl_pll_id_to_enable_reg(id));
> @@ -3007,7 +3031,7 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
>  
>  	ret = true;
>  out:
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
>  	return ret;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 93c86b19700e..6fa1e6ff0e28 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -2118,12 +2118,21 @@ bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
>  				    enum intel_display_power_domain domain);
>  bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
>  				      enum intel_display_power_domain domain);
> -void intel_display_power_get(struct drm_i915_private *dev_priv,
> -			     enum intel_display_power_domain domain);
> -bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
> +intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
>  					enum intel_display_power_domain domain);
> +intel_wakeref_t
> +intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
> +				   enum intel_display_power_domain domain);
> +void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
> +				       enum intel_display_power_domain domain);
> +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
>  void intel_display_power_put(struct drm_i915_private *dev_priv,
> -			     enum intel_display_power_domain domain);
> +			     enum intel_display_power_domain domain,
> +			     intel_wakeref_t wakeref);
> +#else
> +#define intel_display_power_put(i915, domain, wakeref) \
> +	intel_display_power_put_unchecked(i915, domain)
> +#endif
>  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
>  			    u8 req_slices);
>  
> diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
> index fc7a09049f81..df3d390e25fe 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.h
> +++ b/drivers/gpu/drm/i915/intel_dsi.h
> @@ -39,6 +39,7 @@ struct intel_dsi {
>  	struct intel_encoder base;
>  
>  	struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS];
> +	intel_wakeref_t io_wakeref[I915_MAX_PORTS];
>  
>  	/* GPIO Desc for CRC based Panel control */
>  	struct gpio_desc *gpio_panel;
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 14a0c28fe7c1..14727ac06f67 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1190,15 +1190,17 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv,
> -						encoder->power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     encoder->power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = intel_sdvo_port_enabled(dev_priv, intel_hdmi->hdmi_reg, pipe);
>  
> -	intel_display_power_put(dev_priv, encoder->power_domain);
> +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -1895,11 +1897,12 @@ intel_hdmi_set_edid(struct drm_connector *connector)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(connector->dev);
>  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
> +	intel_wakeref_t wakeref;
>  	struct edid *edid;
>  	bool connected = false;
>  	struct i2c_adapter *i2c;
>  
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
>  
>  	i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
>  
> @@ -1914,7 +1917,7 @@ intel_hdmi_set_edid(struct drm_connector *connector)
>  
>  	intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
>  
>  	to_intel_connector(connector)->detect_edid = edid;
>  	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
> @@ -1939,11 +1942,12 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
>  	struct drm_i915_private *dev_priv = to_i915(connector->dev);
>  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
>  	struct intel_encoder *encoder = &hdmi_to_dig_port(intel_hdmi)->base;
> +	intel_wakeref_t wakeref;
>  
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>  		      connector->base.id, connector->name);
>  
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
>  
>  	if (IS_ICELAKE(dev_priv) &&
>  	    !intel_digital_port_connected(encoder))
> @@ -1955,7 +1959,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
>  		status = connector_status_connected;
>  
>  out:
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
>  
>  	if (status != connector_status_connected)
>  		cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
> diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
> index c6159aff9dc8..4f6dc8c94634 100644
> --- a/drivers/gpu/drm/i915/intel_i2c.c
> +++ b/drivers/gpu/drm/i915/intel_i2c.c
> @@ -697,12 +697,13 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
>  static int
>  gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
>  {
> -	struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
> -					       adapter);
> +	struct intel_gmbus *bus =
> +		container_of(adapter, struct intel_gmbus, adapter);
>  	struct drm_i915_private *dev_priv = bus->dev_priv;
> +	intel_wakeref_t wakeref;
>  	int ret;
>  
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
>  
>  	if (bus->force_bit) {
>  		ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
> @@ -714,17 +715,16 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
>  			bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
>  	}
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
>  
>  	return ret;
>  }
>  
>  int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
>  {
> -	struct intel_gmbus *bus = container_of(adapter, struct intel_gmbus,
> -					       adapter);
> +	struct intel_gmbus *bus =
> +		container_of(adapter, struct intel_gmbus, adapter);
>  	struct drm_i915_private *dev_priv = bus->dev_priv;
> -	int ret;
>  	u8 cmd = DRM_HDCP_DDC_AKSV;
>  	u8 buf[DRM_HDCP_KSV_LEN] = { 0 };
>  	struct i2c_msg msgs[] = {
> @@ -741,8 +741,10 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
>  			.buf = buf,
>  		}
>  	};
> +	intel_wakeref_t wakeref;
> +	int ret;
>  
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
>  	mutex_lock(&dev_priv->gmbus_mutex);
>  
>  	/*
> @@ -753,7 +755,7 @@ int intel_gmbus_output_aksv(struct i2c_adapter *adapter)
>  	ret = do_gmbus_xfer(adapter, msgs, ARRAY_SIZE(msgs), GMBUS_AKSV_SELECT);
>  
>  	mutex_unlock(&dev_priv->gmbus_mutex);
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 6adcc8d037bf..b01aacb5d73d 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -94,15 +94,17 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv,
> -						encoder->power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     encoder->power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = intel_lvds_port_enabled(dev_priv, lvds_encoder->reg, pipe);
>  
> -	intel_display_power_put(dev_priv, encoder->power_domain);
> +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c
> index bdabcfab8090..56d614b02302 100644
> --- a/drivers/gpu/drm/i915/intel_pipe_crc.c
> +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c
> @@ -589,6 +589,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
>  	struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
>  	enum intel_display_power_domain power_domain;
>  	enum intel_pipe_crc_source source;
> +	intel_wakeref_t wakeref;
>  	u32 val = 0; /* shut up gcc */
>  	int ret = 0;
>  
> @@ -598,7 +599,8 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
>  	}
>  
>  	power_domain = POWER_DOMAIN_PIPE(crtc->index);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) {
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref) {
>  		DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
>  		return -EIO;
>  	}
> @@ -624,7 +626,7 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
>  	pipe_crc->skipped = 0;
>  
>  out:
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 83b01cde8113..ab7257720c7e 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -3989,10 +3989,12 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>  	enum intel_display_power_domain power_domain;
>  	enum pipe pipe = crtc->pipe;
> +	intel_wakeref_t wakeref;
>  	enum plane_id plane_id;
>  
>  	power_domain = POWER_DOMAIN_PIPE(pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return;
>  
>  	for_each_plane_id_on_crtc(crtc, plane_id)
> @@ -4001,7 +4003,7 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc,
>  					   &ddb_y[plane_id],
>  					   &ddb_uv[plane_id]);
>  
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  }
>  
>  void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index f585ef742efe..fd2fc10dd1e4 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -1867,18 +1867,19 @@ __intel_display_power_get_domain(struct drm_i915_private *dev_priv,
>   * Any power domain reference obtained by this function must have a symmetric
>   * call to intel_display_power_put() to release the reference again.
>   */
> -void intel_display_power_get(struct drm_i915_private *dev_priv,
> -			     enum intel_display_power_domain domain)
> +intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
> +					enum intel_display_power_domain domain)
>  {
>  	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> -
> -	intel_runtime_pm_get(dev_priv);
> +	intel_wakeref_t wakeref = intel_runtime_pm_get(dev_priv);
>  
>  	mutex_lock(&power_domains->lock);
>  
>  	__intel_display_power_get_domain(dev_priv, domain);
>  
>  	mutex_unlock(&power_domains->lock);
> +
> +	return wakeref;
>  }
>  
>  /**
> @@ -1893,13 +1894,16 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
>   * Any power domain reference obtained by this function must have a symmetric
>   * call to intel_display_power_put() to release the reference again.
>   */
> -bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
> -					enum intel_display_power_domain domain)
> +intel_wakeref_t
> +intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
> +				   enum intel_display_power_domain domain)
>  {
>  	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	intel_wakeref_t wakeref;
>  	bool is_enabled;
>  
> -	if (!intel_runtime_pm_get_if_in_use(dev_priv))
> +	wakeref = intel_runtime_pm_get_if_in_use(dev_priv);
> +	if (!wakeref)
>  		return false;
>  
>  	mutex_lock(&power_domains->lock);
> @@ -1913,23 +1917,16 @@ bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
>  
>  	mutex_unlock(&power_domains->lock);
>  
> -	if (!is_enabled)
> -		intel_runtime_pm_put_unchecked(dev_priv);
> +	if (!is_enabled) {
> +		intel_runtime_pm_put(dev_priv, wakeref);
> +		wakeref = 0;
> +	}
>  
> -	return is_enabled;
> +	return wakeref;
>  }
>  
> -/**
> - * intel_display_power_put - release a power domain reference
> - * @dev_priv: i915 device instance
> - * @domain: power domain to reference
> - *
> - * This function drops the power domain reference obtained by
> - * intel_display_power_get() and might power down the corresponding hardware
> - * block right away if this is the last reference.
> - */
> -void intel_display_power_put(struct drm_i915_private *dev_priv,
> -			     enum intel_display_power_domain domain)
> +static void __intel_display_power_put(struct drm_i915_private *dev_priv,
> +				      enum intel_display_power_domain domain)
>  {
>  	struct i915_power_domains *power_domains;
>  	struct i915_power_well *power_well;
> @@ -1947,10 +1944,34 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
>  		intel_power_well_put(dev_priv, power_well);
>  
>  	mutex_unlock(&power_domains->lock);
> +}
>  
> +/**
> + * intel_display_power_put - release a power domain reference

+unchecked? or is this in wrong place.

And the perf oa_config unrelated changes are gone. Good.
-Mika

> + * @dev_priv: i915 device instance
> + * @domain: power domain to reference
> + *
> + * This function drops the power domain reference obtained by
> + * intel_display_power_get() and might power down the corresponding hardware
> + * block right away if this is the last reference.
> + */
> +void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
> +				       enum intel_display_power_domain domain)
> +{
> +	__intel_display_power_put(dev_priv, domain);
>  	intel_runtime_pm_put_unchecked(dev_priv);
>  }
>  
> +#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
> +void intel_display_power_put(struct drm_i915_private *dev_priv,
> +			     enum intel_display_power_domain domain,
> +			     intel_wakeref_t wakeref)
> +{
> +	__intel_display_power_put(dev_priv, domain);
> +	intel_runtime_pm_put(dev_priv, wakeref);
> +}
> +#endif
> +
>  #define I830_PIPES_POWER_DOMAINS (		\
>  	BIT_ULL(POWER_DOMAIN_PIPE_A) |		\
>  	BIT_ULL(POWER_DOMAIN_PIPE_B) |		\
> @@ -4060,7 +4081,7 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
>  
>  	/* Remove the refcount we took to keep power well support disabled. */
>  	if (!i915_modparams.disable_power_well)
> -		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
>  
>  	intel_power_domains_verify_state(dev_priv);
>  }
> @@ -4079,7 +4100,7 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
>   */
>  void intel_power_domains_enable(struct drm_i915_private *dev_priv)
>  {
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
>  
>  	intel_power_domains_verify_state(dev_priv);
>  }
> @@ -4114,7 +4135,7 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
>  {
>  	struct i915_power_domains *power_domains = &dev_priv->power_domains;
>  
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
>  
>  	/*
>  	 * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
> @@ -4135,7 +4156,7 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
>  	 * power wells if power domains must be deinitialized for suspend.
>  	 */
>  	if (!i915_modparams.disable_power_well) {
> -		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
>  		intel_power_domains_verify_state(dev_priv);
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 8f3982c03925..87a06fcca284 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -618,17 +618,19 @@ skl_plane_get_hw_state(struct intel_plane *plane,
>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>  	enum intel_display_power_domain power_domain;
>  	enum plane_id plane_id = plane->id;
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
>  	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
>  
>  	*pipe = plane->pipe;
>  
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -882,17 +884,19 @@ vlv_plane_get_hw_state(struct intel_plane *plane,
>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>  	enum intel_display_power_domain power_domain;
>  	enum plane_id plane_id = plane->id;
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
>  	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
>  
>  	*pipe = plane->pipe;
>  
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -1051,17 +1055,19 @@ ivb_plane_get_hw_state(struct intel_plane *plane,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>  	enum intel_display_power_domain power_domain;
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
>  	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	ret =  I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
>  
>  	*pipe = plane->pipe;
>  
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> @@ -1217,17 +1223,19 @@ g4x_plane_get_hw_state(struct intel_plane *plane,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
>  	enum intel_display_power_domain power_domain;
> +	intel_wakeref_t wakeref;
>  	bool ret;
>  
>  	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
>  
>  	*pipe = plane->pipe;
>  
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/i915/intel_vdsc.c b/drivers/gpu/drm/i915/intel_vdsc.c
> index 48537827616f..23abf03736e7 100644
> --- a/drivers/gpu/drm/i915/intel_vdsc.c
> +++ b/drivers/gpu/drm/i915/intel_vdsc.c
> @@ -1082,6 +1082,6 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state)
>  	I915_WRITE(dss_ctl2_reg, dss_ctl2_val);
>  
>  	/* Disable Power wells for VDSC/joining */
> -	intel_display_power_put(dev_priv,
> -				intel_dsc_power_domain(old_crtc_state));
> +	intel_display_power_put_unchecked(dev_priv,
> +					  intel_dsc_power_domain(old_crtc_state));
>  }
> diff --git a/drivers/gpu/drm/i915/vlv_dsi.c b/drivers/gpu/drm/i915/vlv_dsi.c
> index bb1287020f80..d116fead8514 100644
> --- a/drivers/gpu/drm/i915/vlv_dsi.c
> +++ b/drivers/gpu/drm/i915/vlv_dsi.c
> @@ -959,13 +959,15 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> +	intel_wakeref_t wakeref;
>  	enum port port;
>  	bool active = false;
>  
>  	DRM_DEBUG_KMS("\n");
>  
> -	if (!intel_display_power_get_if_enabled(dev_priv,
> -						encoder->power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv,
> +						     encoder->power_domain);
> +	if (!wakeref)
>  		return false;
>  
>  	/*
> @@ -1021,7 +1023,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
>  	}
>  
>  out_put_power:
> -	intel_display_power_put(dev_priv, encoder->power_domain);
> +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
>  
>  	return active;
>  }
> @@ -1574,6 +1576,7 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
>  	enum drm_panel_orientation orientation;
>  	struct intel_plane *plane;
>  	struct intel_crtc *crtc;
> +	intel_wakeref_t wakeref;
>  	enum pipe pipe;
>  	u32 val;
>  
> @@ -1584,7 +1587,8 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
>  	plane = to_intel_plane(crtc->base.primary);
>  
>  	power_domain = POWER_DOMAIN_PIPE(pipe);
> -	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
> +	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
> +	if (!wakeref)
>  		return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
>  
>  	val = I915_READ(DSPCNTR(plane->i9xx_plane));
> @@ -1596,7 +1600,7 @@ vlv_dsi_get_hw_panel_orientation(struct intel_connector *connector)
>  	else
>  		orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
>  
> -	intel_display_power_put(dev_priv, power_domain);
> +	intel_display_power_put(dev_priv, power_domain, wakeref);
>  
>  	return orientation;
>  }
> -- 
> 2.20.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 16/21] drm/i915: Markup paired operations on display power domains
  2019-01-10 15:51   ` Mika Kuoppala
@ 2019-01-10 16:21     ` Chris Wilson
  2019-01-10 16:49       ` Mika Kuoppala
  0 siblings, 1 reply; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 16:21 UTC (permalink / raw)
  To: Mika Kuoppala, intel-gfx; +Cc: Jani Nikula

Quoting Mika Kuoppala (2019-01-10 15:51:33)
> Chris Wilson <chris@chris-wilson.co.uk> writes:
> > @@ -680,6 +682,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
> >       wakeref = intel_runtime_pm_get(dev_priv);
> >  
> >       if (IS_CHERRYVIEW(dev_priv)) {
> > +             intel_wakeref_t pref;
> > +
> 
> In here you are introducing a new, descriptive, power reference for display.
> But then you drop it after using it twice. And can't seem to find
> reason for inconsistency.

pref, pref, pref...

> >               seq_printf(m, "Master Interrupt Control:\t%08x\n",
> >                          I915_READ(GEN8_MASTER_IRQ));
> >  
> > @@ -695,8 +699,9 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
> >                       enum intel_display_power_domain power_domain;
> >  
> >                       power_domain = POWER_DOMAIN_PIPE(pipe);
> > -                     if (!intel_display_power_get_if_enabled(dev_priv,
> > -                                                             power_domain)) {
> > +                     pref = intel_display_power_get_if_enabled(dev_priv,
> > +                                                               power_domain);
> > +                     if (!pref) {

ah, it would have been chosen to fit 80cols.

> >                               seq_printf(m, "Pipe %c power disabled\n",
> >                                          pipe_name(pipe));
> >                               continue;
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index f0a405604b75..44c1b21febba 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -344,6 +344,7 @@ struct intel_csr {
> >       uint32_t mmiodata[8];
> >       uint32_t dc_state;
> >       uint32_t allowed_dc_mask;
> > +     intel_wakeref_t wakeref;
> >  };
> >  
> >  enum i915_cache_level {
> > @@ -1982,6 +1983,7 @@ struct drm_i915_private {
> >                * is a slight delay before we do so.
> >                */
> >               intel_wakeref_t awake;
> > +             intel_wakeref_t power;
> 
> This prolly explains the prefs above :)

Possibly.

> > -     intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_A_IO);
> > -
> > -     if (intel_dsi->dual_link)
> > -             intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_B_IO);
> > +     for_each_dsi_port(port, intel_dsi->ports) {
> > +             intel_wakeref_t wakeref;
> > +
> > +             wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]);
> > +             if (wakeref) {
> > +                     intel_display_power_put(dev_priv,
> > +                                             port == PORT_A ?
> > +                                             POWER_DOMAIN_PORT_DDI_A_IO :
> > +                                             POWER_DOMAIN_PORT_DDI_B_IO,
> > +                                             wakeref);
> > +             }
> > +     }
> 
> Ok, well. I have been trying to figure out what really is going on here.
> 
> First it seems that you fix a bug. We take refs for each dsi port but
> only release once special casing 'dual_link' without this patch.
> 
> Second, all the hw access is before getting the refs, looking
> suspicious.

There's always been two, just this moves into a for(;;). I don't think
it was buggy, but I do think the for(;;) has the advantage of being
clearer that it operates over all the ports and wakerefs.

> > @@ -15808,12 +15827,13 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
> >                            struct drm_modeset_acquire_ctx *ctx)
> >  {
> >       struct drm_i915_private *dev_priv = to_i915(dev);
> > -     struct intel_crtc *crtc;
> >       struct intel_crtc_state *crtc_state;
> >       struct intel_encoder *encoder;
> > +     struct intel_crtc *crtc;
> 
> Not that I mind but I don't understand the reasoning
> behind the change of order on this and on few other places in this
> patch.

Just quietly moving everyone over to a tidy set of variable definitions
(we are not meant to grow Christmas trees as part of the kernel coding
style).

> > -/**
> > - * intel_display_power_put - release a power domain reference
> > - * @dev_priv: i915 device instance
> > - * @domain: power domain to reference
> > - *
> > - * This function drops the power domain reference obtained by
> > - * intel_display_power_get() and might power down the corresponding hardware
> > - * block right away if this is the last reference.
> > - */
> > -void intel_display_power_put(struct drm_i915_private *dev_priv,
> > -                          enum intel_display_power_domain domain)
> > +static void __intel_display_power_put(struct drm_i915_private *dev_priv,
> > +                                   enum intel_display_power_domain domain)
> >  {
> >       struct i915_power_domains *power_domains;
> >       struct i915_power_well *power_well;
> > @@ -1947,10 +1944,34 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
> >               intel_power_well_put(dev_priv, power_well);
> >  
> >       mutex_unlock(&power_domains->lock);
> > +}
> >  
> > +/**
> > + * intel_display_power_put - release a power domain reference
> 
> +unchecked? or is this in wrong place.

unchecked doesn't exist, you just need a stronger pair of glasses.

So the only API documented interface is the full version that requires
you take ownership of your wakeref, we don't tempt you with the easy
version that is meant to only exist for transitioning
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 16/21] drm/i915: Markup paired operations on display power domains
  2019-01-10 16:21     ` Chris Wilson
@ 2019-01-10 16:49       ` Mika Kuoppala
  0 siblings, 0 replies; 39+ messages in thread
From: Mika Kuoppala @ 2019-01-10 16:49 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

Chris Wilson <chris@chris-wilson.co.uk> writes:

> Quoting Mika Kuoppala (2019-01-10 15:51:33)
>> Chris Wilson <chris@chris-wilson.co.uk> writes:
>> > @@ -680,6 +682,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>> >       wakeref = intel_runtime_pm_get(dev_priv);
>> >  
>> >       if (IS_CHERRYVIEW(dev_priv)) {
>> > +             intel_wakeref_t pref;
>> > +
>> 
>> In here you are introducing a new, descriptive, power reference for display.
>> But then you drop it after using it twice. And can't seem to find
>> reason for inconsistency.
>
> pref, pref, pref...
>
>> >               seq_printf(m, "Master Interrupt Control:\t%08x\n",
>> >                          I915_READ(GEN8_MASTER_IRQ));
>> >  
>> > @@ -695,8 +699,9 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
>> >                       enum intel_display_power_domain power_domain;
>> >  
>> >                       power_domain = POWER_DOMAIN_PIPE(pipe);
>> > -                     if (!intel_display_power_get_if_enabled(dev_priv,
>> > -                                                             power_domain)) {
>> > +                     pref = intel_display_power_get_if_enabled(dev_priv,
>> > +                                                               power_domain);
>> > +                     if (!pref) {
>
> ah, it would have been chosen to fit 80cols.

You should have adopted it then fully! :)
>
>> >                               seq_printf(m, "Pipe %c power disabled\n",
>> >                                          pipe_name(pipe));
>> >                               continue;
>> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> > index f0a405604b75..44c1b21febba 100644
>> > --- a/drivers/gpu/drm/i915/i915_drv.h
>> > +++ b/drivers/gpu/drm/i915/i915_drv.h
>> > @@ -344,6 +344,7 @@ struct intel_csr {
>> >       uint32_t mmiodata[8];
>> >       uint32_t dc_state;
>> >       uint32_t allowed_dc_mask;
>> > +     intel_wakeref_t wakeref;
>> >  };
>> >  
>> >  enum i915_cache_level {
>> > @@ -1982,6 +1983,7 @@ struct drm_i915_private {
>> >                * is a slight delay before we do so.
>> >                */
>> >               intel_wakeref_t awake;
>> > +             intel_wakeref_t power;
>> 
>> This prolly explains the prefs above :)
>
> Possibly.
>
>> > -     intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_A_IO);
>> > -
>> > -     if (intel_dsi->dual_link)
>> > -             intel_display_power_put(dev_priv, POWER_DOMAIN_PORT_DDI_B_IO);
>> > +     for_each_dsi_port(port, intel_dsi->ports) {
>> > +             intel_wakeref_t wakeref;
>> > +
>> > +             wakeref = fetch_and_zero(&intel_dsi->io_wakeref[port]);
>> > +             if (wakeref) {
>> > +                     intel_display_power_put(dev_priv,
>> > +                                             port == PORT_A ?
>> > +                                             POWER_DOMAIN_PORT_DDI_A_IO :
>> > +                                             POWER_DOMAIN_PORT_DDI_B_IO,
>> > +                                             wakeref);
>> > +             }
>> > +     }
>> 
>> Ok, well. I have been trying to figure out what really is going on here.
>> 
>> First it seems that you fix a bug. We take refs for each dsi port but
>> only release once special casing 'dual_link' without this patch.
>> 
>> Second, all the hw access is before getting the refs, looking
>> suspicious.
>
> There's always been two, just this moves into a for(;;). I don't think
> it was buggy, but I do think the for(;;) has the advantage of being
> clearer that it operates over all the ports and wakerefs.

Agreed that your patch makes it more clear.

I am still suspicious about the ordering, hopefully there is
upper lever pdomain to cover access. But that is not
problem for this patch.

Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>

>
>> > @@ -15808,12 +15827,13 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
>> >                            struct drm_modeset_acquire_ctx *ctx)
>> >  {
>> >       struct drm_i915_private *dev_priv = to_i915(dev);
>> > -     struct intel_crtc *crtc;
>> >       struct intel_crtc_state *crtc_state;
>> >       struct intel_encoder *encoder;
>> > +     struct intel_crtc *crtc;
>> 
>> Not that I mind but I don't understand the reasoning
>> behind the change of order on this and on few other places in this
>> patch.
>
> Just quietly moving everyone over to a tidy set of variable definitions
> (we are not meant to grow Christmas trees as part of the kernel coding
> style).
>
>> > -/**
>> > - * intel_display_power_put - release a power domain reference
>> > - * @dev_priv: i915 device instance
>> > - * @domain: power domain to reference
>> > - *
>> > - * This function drops the power domain reference obtained by
>> > - * intel_display_power_get() and might power down the corresponding hardware
>> > - * block right away if this is the last reference.
>> > - */
>> > -void intel_display_power_put(struct drm_i915_private *dev_priv,
>> > -                          enum intel_display_power_domain domain)
>> > +static void __intel_display_power_put(struct drm_i915_private *dev_priv,
>> > +                                   enum intel_display_power_domain domain)
>> >  {
>> >       struct i915_power_domains *power_domains;
>> >       struct i915_power_well *power_well;
>> > @@ -1947,10 +1944,34 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
>> >               intel_power_well_put(dev_priv, power_well);
>> >  
>> >       mutex_unlock(&power_domains->lock);
>> > +}
>> >  
>> > +/**
>> > + * intel_display_power_put - release a power domain reference
>> 
>> +unchecked? or is this in wrong place.
>
> unchecked doesn't exist, you just need a stronger pair of glasses.
>
> So the only API documented interface is the full version that requires
> you take ownership of your wakeref, we don't tempt you with the easy
> version that is meant to only exist for transitioning
> -Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 17/21] drm/i915: Track the wakeref used to initialise display power domains
  2019-01-10 10:11 ` [PATCH 17/21] drm/i915: Track the wakeref used to initialise " Chris Wilson
@ 2019-01-10 23:15   ` John Harrison
  2019-01-10 23:21     ` Chris Wilson
  2019-01-11 13:09   ` Mika Kuoppala
  1 sibling, 1 reply; 39+ messages in thread
From: John Harrison @ 2019-01-10 23:15 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

On 1/10/2019 02:11, Chris Wilson wrote:
> On module load and unload, we grab the POWER_DOMAIN_INIT powerwells and
> transfer them to the runtime-pm code. We can use our wakeref tracking to
> verify that the wakeref is indeed passed from init to enable, and
> disable to fini; and across suspend.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_debugfs.c     |   3 +
>   drivers/gpu/drm/i915/i915_drv.h         |   2 +
>   drivers/gpu/drm/i915/intel_runtime_pm.c | 151 +++++++++++++-----------
>   3 files changed, 88 insertions(+), 68 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index b7dcacf2a5d3..96717a23b32f 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2699,6 +2699,9 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
>   	if (!HAS_RUNTIME_PM(dev_priv))
>   		seq_puts(m, "Runtime power management not supported\n");
>   
> +	seq_printf(m, "Runtime power management: %s\n",
> +		   enableddisabled(!dev_priv->power_domains.wakeref));
> +
>   	seq_printf(m, "GPU idle: %s (epoch %u)\n",
>   		   yesno(!dev_priv->gt.awake), dev_priv->gt.epoch);
>   	seq_printf(m, "IRQs disabled: %s\n",
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 44c1b21febba..259b91b62ff2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -822,6 +822,8 @@ struct i915_power_domains {
>   	bool display_core_suspended;
>   	int power_well_count;
>   
> +	intel_wakeref_t wakeref;
> +
>   	struct mutex lock;
>   	int domain_use_count[POWER_DOMAIN_NUM];
>   	struct i915_power_well *power_wells;
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index fd2fc10dd1e4..8d38f3e7fad1 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -4009,7 +4009,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
>   
>   /**
>    * intel_power_domains_init_hw - initialize hardware power domain state
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>    * @resume: Called from resume code paths or not
>    *
>    * This function initializes the hardware power domain state and enables all
> @@ -4023,30 +4023,31 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
>    * intel_power_domains_enable()) and must be paired with
>    * intel_power_domains_fini_hw().
>    */
> -void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
> +void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)
>   {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>   
>   	power_domains->initializing = true;
>   
> -	if (IS_ICELAKE(dev_priv)) {
> -		icl_display_core_init(dev_priv, resume);
> -	} else if (IS_CANNONLAKE(dev_priv)) {
> -		cnl_display_core_init(dev_priv, resume);
> -	} else if (IS_GEN9_BC(dev_priv)) {
> -		skl_display_core_init(dev_priv, resume);
> -	} else if (IS_GEN9_LP(dev_priv)) {
> -		bxt_display_core_init(dev_priv, resume);
> -	} else if (IS_CHERRYVIEW(dev_priv)) {
> +	if (IS_ICELAKE(i915)) {
> +		icl_display_core_init(i915, resume);
> +	} else if (IS_CANNONLAKE(i915)) {
> +		cnl_display_core_init(i915, resume);
> +	} else if (IS_GEN9_BC(i915)) {
> +		skl_display_core_init(i915, resume);
> +	} else if (IS_GEN9_LP(i915)) {
> +		bxt_display_core_init(i915, resume);
> +	} else if (IS_CHERRYVIEW(i915)) {
>   		mutex_lock(&power_domains->lock);
> -		chv_phy_control_init(dev_priv);
> +		chv_phy_control_init(i915);
>   		mutex_unlock(&power_domains->lock);
> -	} else if (IS_VALLEYVIEW(dev_priv)) {
> +	} else if (IS_VALLEYVIEW(i915)) {
>   		mutex_lock(&power_domains->lock);
> -		vlv_cmnlane_wa(dev_priv);
> +		vlv_cmnlane_wa(i915);
>   		mutex_unlock(&power_domains->lock);
> -	} else if (IS_IVYBRIDGE(dev_priv) || INTEL_GEN(dev_priv) >= 7)
> -		intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
> +	} else if (IS_IVYBRIDGE(i915) || INTEL_GEN(i915) >= 7) {
> +		intel_pch_reset_handshake(i915, !HAS_PCH_NOP(i915));
> +	}
>   
>   	/*
>   	 * Keep all power wells enabled for any dependent HW access during
> @@ -4054,18 +4055,20 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
>   	 * resources powered until display HW readout is complete. We drop
>   	 * this reference in intel_power_domains_enable().
>   	 */
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +	power_domains->wakeref =
> +		intel_display_power_get(i915, POWER_DOMAIN_INIT);
> +
>   	/* Disable power support if the user asked so. */
>   	if (!i915_modparams.disable_power_well)
> -		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> -	intel_power_domains_sync_hw(dev_priv);
> +		intel_display_power_get(i915, POWER_DOMAIN_INIT);
Why not save this cookie away somewhere too, e.g. 
power_domains->wakeref_disable? That way you can also get rid of the 
put_unchecked calls below.

> +	intel_power_domains_sync_hw(i915);
>   
>   	power_domains->initializing = false;
>   }
>   
>   /**
>    * intel_power_domains_fini_hw - deinitialize hw power domain state
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>    *
>    * De-initializes the display power domain HW state. It also ensures that the
>    * device stays powered up so that the driver can be reloaded.
> @@ -4074,21 +4077,24 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
>    * intel_power_domains_disable()) and must be paired with
>    * intel_power_domains_init_hw().
>    */
> -void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
> +void intel_power_domains_fini_hw(struct drm_i915_private *i915)
>   {
> -	/* Keep the power well enabled, but cancel its rpm wakeref. */
> -	intel_runtime_pm_put_unchecked(dev_priv);
> +	intel_wakeref_t wakeref __maybe_unused =
> +		fetch_and_zero(&i915->power_domains.wakeref);
Why the '__maybe_unused'? The call to put is unconditional. Or is it 
about keeping the compiler happy in the case where the wakeref tracking 
is disabled? Although I don't recall seeing any 'maybe's in the earlier 
patches.

>   
>   	/* Remove the refcount we took to keep power well support disabled. */
>   	if (!i915_modparams.disable_power_well)
> -		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
> +		intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
> +
> +	intel_power_domains_verify_state(i915);
>   
> -	intel_power_domains_verify_state(dev_priv);
> +	/* Keep the power well enabled, but cancel its rpm wakeref. */
> +	intel_runtime_pm_put(i915, wakeref);
>   }
>   
>   /**
>    * intel_power_domains_enable - enable toggling of display power wells
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>    *
>    * Enable the ondemand enabling/disabling of the display power wells. Note that
>    * power wells not belonging to POWER_DOMAIN_INIT are allowed to be toggled
> @@ -4098,30 +4104,36 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
>    * of display HW readout (which will acquire the power references reflecting
>    * the current HW state).
>    */
> -void intel_power_domains_enable(struct drm_i915_private *dev_priv)
> +void intel_power_domains_enable(struct drm_i915_private *i915)
>   {
> -	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
> +	intel_wakeref_t wakeref __maybe_unused =
> +		fetch_and_zero(&i915->power_domains.wakeref);
>   
> -	intel_power_domains_verify_state(dev_priv);
> +	intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
> +	intel_power_domains_verify_state(i915);
>   }
>   
>   /**
>    * intel_power_domains_disable - disable toggling of display power wells
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>    *
>    * Disable the ondemand enabling/disabling of the display power wells. See
>    * intel_power_domains_enable() for which power wells this call controls.
>    */
> -void intel_power_domains_disable(struct drm_i915_private *dev_priv)
> +void intel_power_domains_disable(struct drm_i915_private *i915)
>   {
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>   
> -	intel_power_domains_verify_state(dev_priv);
> +	WARN_ON(power_domains->wakeref);
> +	power_domains->wakeref =
> +		intel_display_power_get(i915, POWER_DOMAIN_INIT);
> +
> +	intel_power_domains_verify_state(i915);
>   }
>   
>   /**
>    * intel_power_domains_suspend - suspend power domain state
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>    * @suspend_mode: specifies the target suspend state (idle, mem, hibernation)
>    *
>    * This function prepares the hardware power domain state before entering
> @@ -4130,12 +4142,14 @@ void intel_power_domains_disable(struct drm_i915_private *dev_priv)
>    * It must be called with power domains already disabled (after a call to
>    * intel_power_domains_disable()) and paired with intel_power_domains_resume().
>    */
> -void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
> +void intel_power_domains_suspend(struct drm_i915_private *i915,
>   				 enum i915_drm_suspend_mode suspend_mode)
>   {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
> +	intel_wakeref_t wakeref __maybe_unused =
> +		fetch_and_zero(&power_domains->wakeref);
>   
> -	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
> +	intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
>   
>   	/*
>   	 * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
> @@ -4144,10 +4158,10 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
>   	 * resources as required and also enable deeper system power states
>   	 * that would be blocked if the firmware was inactive.
>   	 */
> -	if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
> +	if (!(i915->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
>   	    suspend_mode == I915_DRM_SUSPEND_IDLE &&
> -	    dev_priv->csr.dmc_payload != NULL) {
> -		intel_power_domains_verify_state(dev_priv);
> +	    i915->csr.dmc_payload) {
> +		intel_power_domains_verify_state(i915);
>   		return;
>   	}
>   
> @@ -4156,25 +4170,25 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
>   	 * power wells if power domains must be deinitialized for suspend.
>   	 */
>   	if (!i915_modparams.disable_power_well) {
> -		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
> -		intel_power_domains_verify_state(dev_priv);
> +		intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
> +		intel_power_domains_verify_state(i915);
>   	}
>   
> -	if (IS_ICELAKE(dev_priv))
> -		icl_display_core_uninit(dev_priv);
> -	else if (IS_CANNONLAKE(dev_priv))
> -		cnl_display_core_uninit(dev_priv);
> -	else if (IS_GEN9_BC(dev_priv))
> -		skl_display_core_uninit(dev_priv);
> -	else if (IS_GEN9_LP(dev_priv))
> -		bxt_display_core_uninit(dev_priv);
> +	if (IS_ICELAKE(i915))
> +		icl_display_core_uninit(i915);
> +	else if (IS_CANNONLAKE(i915))
> +		cnl_display_core_uninit(i915);
> +	else if (IS_GEN9_BC(i915))
> +		skl_display_core_uninit(i915);
> +	else if (IS_GEN9_LP(i915))
> +		bxt_display_core_uninit(i915);
>   
>   	power_domains->display_core_suspended = true;
>   }
>   
>   /**
>    * intel_power_domains_resume - resume power domain state
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>    *
>    * This function resume the hardware power domain state during system resume.
>    *
> @@ -4182,28 +4196,30 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
>    * intel_power_domains_enable()) and must be paired with
>    * intel_power_domains_suspend().
>    */
> -void intel_power_domains_resume(struct drm_i915_private *dev_priv)
> +void intel_power_domains_resume(struct drm_i915_private *i915)
>   {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>   
>   	if (power_domains->display_core_suspended) {
> -		intel_power_domains_init_hw(dev_priv, true);
> +		intel_power_domains_init_hw(i915, true);
>   		power_domains->display_core_suspended = false;
>   	} else {
> -		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +		WARN_ON(power_domains->wakeref);
> +		power_domains->wakeref =
> +			intel_display_power_get(i915, POWER_DOMAIN_INIT);
>   	}
>   
> -	intel_power_domains_verify_state(dev_priv);
> +	intel_power_domains_verify_state(i915);
>   }
>   
>   #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
>   
> -static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
> +static void intel_power_domains_dump_info(struct drm_i915_private *i915)
>   {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>   	struct i915_power_well *power_well;
>   
> -	for_each_power_well(dev_priv, power_well) {
> +	for_each_power_well(i915, power_well) {
>   		enum intel_display_power_domain domain;
>   
>   		DRM_DEBUG_DRIVER("%-25s %d\n",
> @@ -4218,7 +4234,7 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
>   
>   /**
>    * intel_power_domains_verify_state - verify the HW/SW state for all power wells
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>    *
>    * Verify if the reference count of each power well matches its HW enabled
>    * state and the total refcount of the domains it belongs to. This must be
> @@ -4226,22 +4242,21 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
>    * acquiring reference counts for any power wells in use and disabling the
>    * ones left on by BIOS but not required by any active output.
>    */
> -static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
> +static void intel_power_domains_verify_state(struct drm_i915_private *i915)
>   {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>   	struct i915_power_well *power_well;
>   	bool dump_domain_info;
>   
>   	mutex_lock(&power_domains->lock);
>   
>   	dump_domain_info = false;
> -	for_each_power_well(dev_priv, power_well) {
> +	for_each_power_well(i915, power_well) {
>   		enum intel_display_power_domain domain;
>   		int domains_count;
>   		bool enabled;
>   
> -		enabled = power_well->desc->ops->is_enabled(dev_priv,
> -							    power_well);
> +		enabled = power_well->desc->ops->is_enabled(i915, power_well);
>   		if ((power_well->count || power_well->desc->always_on) !=
>   		    enabled)
>   			DRM_ERROR("power well %s state mismatch (refcount %d/enabled %d)",
> @@ -4265,7 +4280,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
>   		static bool dumped;
>   
>   		if (!dumped) {
> -			intel_power_domains_dump_info(dev_priv);
> +			intel_power_domains_dump_info(i915);
>   			dumped = true;
>   		}
>   	}
> @@ -4275,7 +4290,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
>   
>   #else
>   
> -static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
> +static void intel_power_domains_verify_state(struct drm_i915_private *i915)
>   {
>   }
>   

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

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

* Re: [PATCH 17/21] drm/i915: Track the wakeref used to initialise display power domains
  2019-01-10 23:15   ` John Harrison
@ 2019-01-10 23:21     ` Chris Wilson
  0 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-10 23:21 UTC (permalink / raw)
  To: John Harrison, intel-gfx; +Cc: Jani Nikula

Quoting John Harrison (2019-01-10 23:15:31)
> On 1/10/2019 02:11, Chris Wilson wrote:
> > @@ -4054,18 +4055,20 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
> >        * resources powered until display HW readout is complete. We drop
> >        * this reference in intel_power_domains_enable().
> >        */
> > -     intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> > +     power_domains->wakeref =
> > +             intel_display_power_get(i915, POWER_DOMAIN_INIT);
> > +
> >       /* Disable power support if the user asked so. */
> >       if (!i915_modparams.disable_power_well)
> > -             intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> > -     intel_power_domains_sync_hw(dev_priv);
> > +             intel_display_power_get(i915, POWER_DOMAIN_INIT);
> Why not save this cookie away somewhere too, e.g. 
> power_domains->wakeref_disable? That way you can also get rid of the 
> put_unchecked calls below.

Just seemed like a bit more hassle for the case where rpm was
intentionally disabled by the user. The system is going to leak the
wakerefs, tracking seemed pointless, so I just threw my hands up in the
air and gave up.

> > +     intel_power_domains_sync_hw(i915);
> >   
> >       power_domains->initializing = false;
> >   }
> >   
> >   /**
> >    * intel_power_domains_fini_hw - deinitialize hw power domain state
> > - * @dev_priv: i915 device instance
> > + * @i915: i915 device instance
> >    *
> >    * De-initializes the display power domain HW state. It also ensures that the
> >    * device stays powered up so that the driver can be reloaded.
> > @@ -4074,21 +4077,24 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
> >    * intel_power_domains_disable()) and must be paired with
> >    * intel_power_domains_init_hw().
> >    */
> > -void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
> > +void intel_power_domains_fini_hw(struct drm_i915_private *i915)
> >   {
> > -     /* Keep the power well enabled, but cancel its rpm wakeref. */
> > -     intel_runtime_pm_put_unchecked(dev_priv);
> > +     intel_wakeref_t wakeref __maybe_unused =
> > +             fetch_and_zero(&i915->power_domains.wakeref);
> Why the '__maybe_unused'? The call to put is unconditional. Or is it 
> about keeping the compiler happy in the case where the wakeref tracking 
> is disabled? Although I don't recall seeing any 'maybe's in the earlier 
> patches.

Just about keeping the compiler happy when the compiler complained.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 19/21] drm/i915/dp: Markup pps lock power well
  2019-01-10 10:11 ` [PATCH 19/21] drm/i915/dp: Markup pps lock power well Chris Wilson
@ 2019-01-11  0:16   ` John Harrison
  2019-01-11  1:19     ` Chris Wilson
  0 siblings, 1 reply; 39+ messages in thread
From: John Harrison @ 2019-01-11  0:16 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

On 1/10/2019 02:11, Chris Wilson wrote:
> Track where and when we acquire and release the power well for pps
> access along the dp aux link, with a view to detecting if we leak any
> wakerefs.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>   drivers/gpu/drm/i915/intel_dp.c | 231 +++++++++++++++++---------------
>   1 file changed, 121 insertions(+), 110 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index fc85fd77a661..db0f3a4402f5 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -601,30 +601,39 @@ intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
>   static void
>   intel_dp_pps_init(struct intel_dp *intel_dp);
>   
> -static void pps_lock(struct intel_dp *intel_dp)
> +static intel_wakeref_t
> +pps_lock(struct intel_dp *intel_dp)
>   {
>   	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
Any particular reason for leaving these as dev_priv when the earlier 
patches converted everything in sight to i915?

Otherwise:
Reviewed-by: John Harrison <John.C.Harrison@Intel.com>


> +	intel_wakeref_t wakeref;
>   
>   	/*
>   	 * See intel_power_sequencer_reset() why we need
>   	 * a power domain reference here.
>   	 */
> -	intel_display_power_get(dev_priv,
> -				intel_aux_power_domain(dp_to_dig_port(intel_dp)));
> +	wakeref = intel_display_power_get(dev_priv,
> +					  intel_aux_power_domain(dp_to_dig_port(intel_dp)));
>   
>   	mutex_lock(&dev_priv->pps_mutex);
> +
> +	return wakeref;
>   }
>   
> -static void pps_unlock(struct intel_dp *intel_dp)
> +static intel_wakeref_t
> +pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
>   {
>   	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>   
>   	mutex_unlock(&dev_priv->pps_mutex);
> -
> -	intel_display_power_put_unchecked(dev_priv,
> -					  intel_aux_power_domain(dp_to_dig_port(intel_dp)));
> +	intel_display_power_put(dev_priv,
> +				intel_aux_power_domain(dp_to_dig_port(intel_dp)),
> +				wakeref);
> +	return 0;
>   }
>   
> +#define with_pps_lock(dp, wf) \
> +	for (wf = pps_lock(dp); wf; wf = pps_unlock(dp, wf))
> +
>   static void
>   vlv_power_sequencer_kick(struct intel_dp *intel_dp)
>   {
> @@ -973,30 +982,30 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>   	struct intel_dp *intel_dp = container_of(this, typeof(* intel_dp),
>   						 edp_notifier);
>   	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	intel_wakeref_t wakeref;
>   
>   	if (!intel_dp_is_edp(intel_dp) || code != SYS_RESTART)
>   		return 0;
>   
> -	pps_lock(intel_dp);
> -
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> -		i915_reg_t pp_ctrl_reg, pp_div_reg;
> -		u32 pp_div;
> -
> -		pp_ctrl_reg = PP_CONTROL(pipe);
> -		pp_div_reg  = PP_DIVISOR(pipe);
> -		pp_div = I915_READ(pp_div_reg);
> -		pp_div &= PP_REFERENCE_DIVIDER_MASK;
> -
> -		/* 0x1F write to PP_DIV_REG sets max cycle delay */
> -		I915_WRITE(pp_div_reg, pp_div | 0x1F);
> -		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> -		msleep(intel_dp->panel_power_cycle_delay);
> +	with_pps_lock(intel_dp, wakeref) {
> +		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> +			enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> +			i915_reg_t pp_ctrl_reg, pp_div_reg;
> +			u32 pp_div;
> +
> +			pp_ctrl_reg = PP_CONTROL(pipe);
> +			pp_div_reg  = PP_DIVISOR(pipe);
> +			pp_div = I915_READ(pp_div_reg);
> +			pp_div &= PP_REFERENCE_DIVIDER_MASK;
> +
> +			/* 0x1F write to PP_DIV_REG sets max cycle delay */
> +			I915_WRITE(pp_div_reg, pp_div | 0x1F);
> +			I915_WRITE(pp_ctrl_reg,
> +				   PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> +			msleep(intel_dp->panel_power_cycle_delay);
> +		}
>   	}
>   
> -	pps_unlock(intel_dp);
> -
>   	return 0;
>   }
>   
> @@ -1184,16 +1193,17 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
>   			to_i915(intel_dig_port->base.base.dev);
>   	i915_reg_t ch_ctl, ch_data[5];
>   	uint32_t aux_clock_divider;
> +	intel_wakeref_t wakeref;
>   	int i, ret, recv_bytes;
> -	uint32_t status;
>   	int try, clock = 0;
> +	uint32_t status;
>   	bool vdd;
>   
>   	ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
>   	for (i = 0; i < ARRAY_SIZE(ch_data); i++)
>   		ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
>   
> -	pps_lock(intel_dp);
> +	wakeref = pps_lock(intel_dp);
>   
>   	/*
>   	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
> @@ -1337,7 +1347,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
>   	if (vdd)
>   		edp_panel_vdd_off(intel_dp, false);
>   
> -	pps_unlock(intel_dp);
> +	pps_unlock(intel_dp, wakeref);
>   
>   	return ret;
>   }
> @@ -2464,15 +2474,15 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>    */
>   void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
>   {
> +	intel_wakeref_t wakeref;
>   	bool vdd;
>   
>   	if (!intel_dp_is_edp(intel_dp))
>   		return;
>   
> -	pps_lock(intel_dp);
> -	vdd = edp_panel_vdd_on(intel_dp);
> -	pps_unlock(intel_dp);
> -
> +	vdd = false;
> +	with_pps_lock(intel_dp, wakeref)
> +		vdd = edp_panel_vdd_on(intel_dp);
>   	I915_STATE_WARN(!vdd, "eDP port %c VDD already requested on\n",
>   	     port_name(dp_to_dig_port(intel_dp)->base.port));
>   }
> @@ -2517,13 +2527,15 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
>   
>   static void edp_panel_vdd_work(struct work_struct *__work)
>   {
> -	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
> -						 struct intel_dp, panel_vdd_work);
> +	struct intel_dp *intel_dp =
> +		container_of(to_delayed_work(__work),
> +			     struct intel_dp, panel_vdd_work);
> +	intel_wakeref_t wakeref;
>   
> -	pps_lock(intel_dp);
> -	if (!intel_dp->want_panel_vdd)
> -		edp_panel_vdd_off_sync(intel_dp);
> -	pps_unlock(intel_dp);
> +	with_pps_lock(intel_dp, wakeref) {
> +		if (!intel_dp->want_panel_vdd)
> +			edp_panel_vdd_off_sync(intel_dp);
> +	}
>   }
>   
>   static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
> @@ -2613,12 +2625,13 @@ static void edp_panel_on(struct intel_dp *intel_dp)
>   
>   void intel_edp_panel_on(struct intel_dp *intel_dp)
>   {
> +	intel_wakeref_t wakeref;
> +
>   	if (!intel_dp_is_edp(intel_dp))
>   		return;
>   
> -	pps_lock(intel_dp);
> -	edp_panel_on(intel_dp);
> -	pps_unlock(intel_dp);
> +	with_pps_lock(intel_dp, wakeref)
> +		edp_panel_on(intel_dp);
>   }
>   
>   
> @@ -2662,20 +2675,20 @@ static void edp_panel_off(struct intel_dp *intel_dp)
>   
>   void intel_edp_panel_off(struct intel_dp *intel_dp)
>   {
> +	intel_wakeref_t wakeref;
> +
>   	if (!intel_dp_is_edp(intel_dp))
>   		return;
>   
> -	pps_lock(intel_dp);
> -	edp_panel_off(intel_dp);
> -	pps_unlock(intel_dp);
> +	with_pps_lock(intel_dp, wakeref)
> +		edp_panel_off(intel_dp);
>   }
>   
>   /* Enable backlight in the panel power control. */
>   static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
>   {
>   	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_ctrl_reg;
> +	intel_wakeref_t wakeref;
>   
>   	/*
>   	 * If we enable the backlight right away following a panel power
> @@ -2685,17 +2698,16 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
>   	 */
>   	wait_backlight_on(intel_dp);
>   
> -	pps_lock(intel_dp);
> +	with_pps_lock(intel_dp, wakeref) {
> +		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +		u32 pp;
>   
> -	pp = ironlake_get_pp_control(intel_dp);
> -	pp |= EDP_BLC_ENABLE;
> -
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -
> -	I915_WRITE(pp_ctrl_reg, pp);
> -	POSTING_READ(pp_ctrl_reg);
> +		pp = ironlake_get_pp_control(intel_dp);
> +		pp |= EDP_BLC_ENABLE;
>   
> -	pps_unlock(intel_dp);
> +		I915_WRITE(pp_ctrl_reg, pp);
> +		POSTING_READ(pp_ctrl_reg);
> +	}
>   }
>   
>   /* Enable backlight PWM and backlight PP control. */
> @@ -2717,23 +2729,21 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
>   static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
>   {
>   	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_ctrl_reg;
> +	intel_wakeref_t wakeref;
>   
>   	if (!intel_dp_is_edp(intel_dp))
>   		return;
>   
> -	pps_lock(intel_dp);
> -
> -	pp = ironlake_get_pp_control(intel_dp);
> -	pp &= ~EDP_BLC_ENABLE;
> -
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +	with_pps_lock(intel_dp, wakeref) {
> +		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +		u32 pp;
>   
> -	I915_WRITE(pp_ctrl_reg, pp);
> -	POSTING_READ(pp_ctrl_reg);
> +		pp = ironlake_get_pp_control(intel_dp);
> +		pp &= ~EDP_BLC_ENABLE;
>   
> -	pps_unlock(intel_dp);
> +		I915_WRITE(pp_ctrl_reg, pp);
> +		POSTING_READ(pp_ctrl_reg);
> +	}
>   
>   	intel_dp->last_backlight_off = jiffies;
>   	edp_wait_backlight_off(intel_dp);
> @@ -2761,12 +2771,12 @@ static void intel_edp_backlight_power(struct intel_connector *connector,
>   				      bool enable)
>   {
>   	struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
> +	intel_wakeref_t wakeref;
>   	bool is_enabled;
>   
> -	pps_lock(intel_dp);
> -	is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
> -	pps_unlock(intel_dp);
> -
> +	is_enabled = false;
> +	with_pps_lock(intel_dp, wakeref)
> +		is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
>   	if (is_enabled == enable)
>   		return;
>   
> @@ -3276,22 +3286,21 @@ static void intel_enable_dp(struct intel_encoder *encoder,
>   	struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
>   	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
>   	enum pipe pipe = crtc->pipe;
> +	intel_wakeref_t wakeref;
>   
>   	if (WARN_ON(dp_reg & DP_PORT_EN))
>   		return;
>   
> -	pps_lock(intel_dp);
> -
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		vlv_init_panel_power_sequencer(encoder, pipe_config);
> -
> -	intel_dp_enable_port(intel_dp, pipe_config);
> +	with_pps_lock(intel_dp, wakeref) {
> +		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +			vlv_init_panel_power_sequencer(encoder, pipe_config);
>   
> -	edp_panel_vdd_on(intel_dp);
> -	edp_panel_on(intel_dp);
> -	edp_panel_vdd_off(intel_dp, true);
> +		intel_dp_enable_port(intel_dp, pipe_config);
>   
> -	pps_unlock(intel_dp);
> +		edp_panel_vdd_on(intel_dp);
> +		edp_panel_on(intel_dp);
> +		edp_panel_vdd_off(intel_dp, true);
> +	}
>   
>   	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
>   		unsigned int lane_mask = 0x0;
> @@ -3989,9 +3998,10 @@ intel_dp_link_down(struct intel_encoder *encoder,
>   	intel_dp->DP = DP;
>   
>   	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		pps_lock(intel_dp);
> -		intel_dp->active_pipe = INVALID_PIPE;
> -		pps_unlock(intel_dp);
> +		intel_wakeref_t wakeref;
> +
> +		with_pps_lock(intel_dp, wakeref)
> +			intel_dp->active_pipe = INVALID_PIPE;
>   	}
>   }
>   
> @@ -5561,14 +5571,15 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder)
>   
>   	intel_dp_mst_encoder_cleanup(intel_dig_port);
>   	if (intel_dp_is_edp(intel_dp)) {
> +		intel_wakeref_t wakeref;
> +
>   		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
>   		/*
>   		 * vdd might still be enabled do to the delayed vdd off.
>   		 * Make sure vdd is actually turned off here.
>   		 */
> -		pps_lock(intel_dp);
> -		edp_panel_vdd_off_sync(intel_dp);
> -		pps_unlock(intel_dp);
> +		with_pps_lock(intel_dp, wakeref)
> +			edp_panel_vdd_off_sync(intel_dp);
>   
>   		if (intel_dp->edp_notifier.notifier_call) {
>   			unregister_reboot_notifier(&intel_dp->edp_notifier);
> @@ -5590,6 +5601,7 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>   void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
>   {
>   	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
> +	intel_wakeref_t wakeref;
>   
>   	if (!intel_dp_is_edp(intel_dp))
>   		return;
> @@ -5599,9 +5611,8 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
>   	 * Make sure vdd is actually turned off here.
>   	 */
>   	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> -	pps_lock(intel_dp);
> -	edp_panel_vdd_off_sync(intel_dp);
> -	pps_unlock(intel_dp);
> +	with_pps_lock(intel_dp, wakeref)
> +		edp_panel_vdd_off_sync(intel_dp);
>   }
>   
>   static
> @@ -5882,6 +5893,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
>   	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
>   	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>   	struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp);
> +	intel_wakeref_t wakeref;
>   
>   	if (!HAS_DDI(dev_priv))
>   		intel_dp->DP = I915_READ(intel_dp->output_reg);
> @@ -5891,18 +5903,19 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
>   
>   	intel_dp->reset_link_params = true;
>   
> -	pps_lock(intel_dp);
> -
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		intel_dp->active_pipe = vlv_active_pipe(intel_dp);
> +	with_pps_lock(intel_dp, wakeref) {
> +		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +			intel_dp->active_pipe = vlv_active_pipe(intel_dp);
>   
> -	if (intel_dp_is_edp(intel_dp)) {
> -		/* Reinit the power sequencer, in case BIOS did something with it. */
> -		intel_dp_pps_init(intel_dp);
> -		intel_edp_panel_vdd_sanitize(intel_dp);
> +		if (intel_dp_is_edp(intel_dp)) {
> +			/*
> +			 * Reinit the power sequencer, in case BIOS did
> +			 * something nasty with it.
> +			 */
> +			intel_dp_pps_init(intel_dp);
> +			intel_edp_panel_vdd_sanitize(intel_dp);
> +		}
>   	}
> -
> -	pps_unlock(intel_dp);
>   }
>   
>   static const struct drm_connector_funcs intel_dp_connector_funcs = {
> @@ -6698,8 +6711,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>   	struct drm_display_mode *downclock_mode = NULL;
>   	bool has_dpcd;
>   	struct drm_display_mode *scan;
> -	struct edid *edid;
>   	enum pipe pipe = INVALID_PIPE;
> +	intel_wakeref_t wakeref;
> +	struct edid *edid;
>   
>   	if (!intel_dp_is_edp(intel_dp))
>   		return true;
> @@ -6719,13 +6733,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>   		return false;
>   	}
>   
> -	pps_lock(intel_dp);
> -
> -	intel_dp_init_panel_power_timestamps(intel_dp);
> -	intel_dp_pps_init(intel_dp);
> -	intel_edp_panel_vdd_sanitize(intel_dp);
> -
> -	pps_unlock(intel_dp);
> +	with_pps_lock(intel_dp, wakeref) {
> +		intel_dp_init_panel_power_timestamps(intel_dp);
> +		intel_dp_pps_init(intel_dp);
> +		intel_edp_panel_vdd_sanitize(intel_dp);
> +	}
>   
>   	/* Cache DPCD and EDID for edp. */
>   	has_dpcd = intel_edp_init_dpcd(intel_dp);
> @@ -6810,9 +6822,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>   	 * vdd might still be enabled do to the delayed vdd off.
>   	 * Make sure vdd is actually turned off here.
>   	 */
> -	pps_lock(intel_dp);
> -	edp_panel_vdd_off_sync(intel_dp);
> -	pps_unlock(intel_dp);
> +	with_pps_lock(intel_dp, wakeref)
> +		edp_panel_vdd_off_sync(intel_dp);
>   
>   	return false;
>   }

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

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

* Re: [PATCH 19/21] drm/i915/dp: Markup pps lock power well
  2019-01-11  0:16   ` John Harrison
@ 2019-01-11  1:19     ` Chris Wilson
  0 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-11  1:19 UTC (permalink / raw)
  To: John Harrison, intel-gfx; +Cc: Jani Nikula

Quoting John Harrison (2019-01-11 00:16:16)
> On 1/10/2019 02:11, Chris Wilson wrote:
> > Track where and when we acquire and release the power well for pps
> > access along the dp aux link, with a view to detecting if we leak any
> > wakerefs.
> >
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Jani Nikula <jani.nikula@intel.com>
> > ---
> >   drivers/gpu/drm/i915/intel_dp.c | 231 +++++++++++++++++---------------
> >   1 file changed, 121 insertions(+), 110 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index fc85fd77a661..db0f3a4402f5 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -601,30 +601,39 @@ intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> >   static void
> >   intel_dp_pps_init(struct intel_dp *intel_dp);
> >   
> > -static void pps_lock(struct intel_dp *intel_dp)
> > +static intel_wakeref_t
> > +pps_lock(struct intel_dp *intel_dp)
> >   {
> >       struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> Any particular reason for leaving these as dev_priv when the earlier 
> patches converted everything in sight to i915?

It usually meant I hit a I915_READ early on that dissuaded me from
trying to sneak the change in, or that I didn't think it was going to be
as large a conversion as it turned out to be. So no reason other than
reticence.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 17/21] drm/i915: Track the wakeref used to initialise display power domains
  2019-01-10 10:11 ` [PATCH 17/21] drm/i915: Track the wakeref used to initialise " Chris Wilson
  2019-01-10 23:15   ` John Harrison
@ 2019-01-11 13:09   ` Mika Kuoppala
  1 sibling, 0 replies; 39+ messages in thread
From: Mika Kuoppala @ 2019-01-11 13:09 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

Chris Wilson <chris@chris-wilson.co.uk> writes:

> On module load and unload, we grab the POWER_DOMAIN_INIT powerwells and
> transfer them to the runtime-pm code. We can use our wakeref tracking to
> verify that the wakeref is indeed passed from init to enable, and
> disable to fini; and across suspend.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c     |   3 +
>  drivers/gpu/drm/i915/i915_drv.h         |   2 +
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 151 +++++++++++++-----------
>  3 files changed, 88 insertions(+), 68 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index b7dcacf2a5d3..96717a23b32f 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2699,6 +2699,9 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
>  	if (!HAS_RUNTIME_PM(dev_priv))
>  		seq_puts(m, "Runtime power management not supported\n");
>  
> +	seq_printf(m, "Runtime power management: %s\n",
> +		   enableddisabled(!dev_priv->power_domains.wakeref));
> +
>  	seq_printf(m, "GPU idle: %s (epoch %u)\n",
>  		   yesno(!dev_priv->gt.awake), dev_priv->gt.epoch);
>  	seq_printf(m, "IRQs disabled: %s\n",
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 44c1b21febba..259b91b62ff2 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -822,6 +822,8 @@ struct i915_power_domains {
>  	bool display_core_suspended;
>  	int power_well_count;
>  
> +	intel_wakeref_t wakeref;
> +
>  	struct mutex lock;
>  	int domain_use_count[POWER_DOMAIN_NUM];
>  	struct i915_power_well *power_wells;
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index fd2fc10dd1e4..8d38f3e7fad1 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -4009,7 +4009,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
>  
>  /**
>   * intel_power_domains_init_hw - initialize hardware power domain state
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>   * @resume: Called from resume code paths or not
>   *
>   * This function initializes the hardware power domain state and enables all
> @@ -4023,30 +4023,31 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv);
>   * intel_power_domains_enable()) and must be paired with
>   * intel_power_domains_fini_hw().
>   */
> -void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
> +void intel_power_domains_init_hw(struct drm_i915_private *i915, bool resume)
>  {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>  
>  	power_domains->initializing = true;
>  
> -	if (IS_ICELAKE(dev_priv)) {
> -		icl_display_core_init(dev_priv, resume);
> -	} else if (IS_CANNONLAKE(dev_priv)) {
> -		cnl_display_core_init(dev_priv, resume);
> -	} else if (IS_GEN9_BC(dev_priv)) {
> -		skl_display_core_init(dev_priv, resume);
> -	} else if (IS_GEN9_LP(dev_priv)) {
> -		bxt_display_core_init(dev_priv, resume);
> -	} else if (IS_CHERRYVIEW(dev_priv)) {
> +	if (IS_ICELAKE(i915)) {
> +		icl_display_core_init(i915, resume);
> +	} else if (IS_CANNONLAKE(i915)) {
> +		cnl_display_core_init(i915, resume);
> +	} else if (IS_GEN9_BC(i915)) {
> +		skl_display_core_init(i915, resume);
> +	} else if (IS_GEN9_LP(i915)) {
> +		bxt_display_core_init(i915, resume);
> +	} else if (IS_CHERRYVIEW(i915)) {
>  		mutex_lock(&power_domains->lock);
> -		chv_phy_control_init(dev_priv);
> +		chv_phy_control_init(i915);
>  		mutex_unlock(&power_domains->lock);
> -	} else if (IS_VALLEYVIEW(dev_priv)) {
> +	} else if (IS_VALLEYVIEW(i915)) {
>  		mutex_lock(&power_domains->lock);
> -		vlv_cmnlane_wa(dev_priv);
> +		vlv_cmnlane_wa(i915);
>  		mutex_unlock(&power_domains->lock);
> -	} else if (IS_IVYBRIDGE(dev_priv) || INTEL_GEN(dev_priv) >= 7)
> -		intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv));
> +	} else if (IS_IVYBRIDGE(i915) || INTEL_GEN(i915) >= 7) {
> +		intel_pch_reset_handshake(i915, !HAS_PCH_NOP(i915));
> +	}
>  
>  	/*
>  	 * Keep all power wells enabled for any dependent HW access during
> @@ -4054,18 +4055,20 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
>  	 * resources powered until display HW readout is complete. We drop
>  	 * this reference in intel_power_domains_enable().
>  	 */
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +	power_domains->wakeref =
> +		intel_display_power_get(i915, POWER_DOMAIN_INIT);
> +
>  	/* Disable power support if the user asked so. */
>  	if (!i915_modparams.disable_power_well)
> -		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);

For the uninitiated, the comment vs the conditional did raise
heart rate.

Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>


> -	intel_power_domains_sync_hw(dev_priv);
> +		intel_display_power_get(i915, POWER_DOMAIN_INIT);
> +	intel_power_domains_sync_hw(i915);
>  
>  	power_domains->initializing = false;
>  }
>  
>  /**
>   * intel_power_domains_fini_hw - deinitialize hw power domain state
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>   *
>   * De-initializes the display power domain HW state. It also ensures that the
>   * device stays powered up so that the driver can be reloaded.
> @@ -4074,21 +4077,24 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
>   * intel_power_domains_disable()) and must be paired with
>   * intel_power_domains_init_hw().
>   */
> -void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
> +void intel_power_domains_fini_hw(struct drm_i915_private *i915)
>  {
> -	/* Keep the power well enabled, but cancel its rpm wakeref. */
> -	intel_runtime_pm_put_unchecked(dev_priv);
> +	intel_wakeref_t wakeref __maybe_unused =
> +		fetch_and_zero(&i915->power_domains.wakeref);
>  
>  	/* Remove the refcount we took to keep power well support disabled. */
>  	if (!i915_modparams.disable_power_well)
> -		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
> +		intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
> +
> +	intel_power_domains_verify_state(i915);
>  
> -	intel_power_domains_verify_state(dev_priv);
> +	/* Keep the power well enabled, but cancel its rpm wakeref. */
> +	intel_runtime_pm_put(i915, wakeref);
>  }
>  
>  /**
>   * intel_power_domains_enable - enable toggling of display power wells
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>   *
>   * Enable the ondemand enabling/disabling of the display power wells. Note that
>   * power wells not belonging to POWER_DOMAIN_INIT are allowed to be toggled
> @@ -4098,30 +4104,36 @@ void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv)
>   * of display HW readout (which will acquire the power references reflecting
>   * the current HW state).
>   */
> -void intel_power_domains_enable(struct drm_i915_private *dev_priv)
> +void intel_power_domains_enable(struct drm_i915_private *i915)
>  {
> -	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
> +	intel_wakeref_t wakeref __maybe_unused =
> +		fetch_and_zero(&i915->power_domains.wakeref);
>  
> -	intel_power_domains_verify_state(dev_priv);
> +	intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
> +	intel_power_domains_verify_state(i915);
>  }
>  
>  /**
>   * intel_power_domains_disable - disable toggling of display power wells
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>   *
>   * Disable the ondemand enabling/disabling of the display power wells. See
>   * intel_power_domains_enable() for which power wells this call controls.
>   */
> -void intel_power_domains_disable(struct drm_i915_private *dev_priv)
> +void intel_power_domains_disable(struct drm_i915_private *i915)
>  {
> -	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>  
> -	intel_power_domains_verify_state(dev_priv);
> +	WARN_ON(power_domains->wakeref);
> +	power_domains->wakeref =
> +		intel_display_power_get(i915, POWER_DOMAIN_INIT);
> +
> +	intel_power_domains_verify_state(i915);
>  }
>  
>  /**
>   * intel_power_domains_suspend - suspend power domain state
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>   * @suspend_mode: specifies the target suspend state (idle, mem, hibernation)
>   *
>   * This function prepares the hardware power domain state before entering
> @@ -4130,12 +4142,14 @@ void intel_power_domains_disable(struct drm_i915_private *dev_priv)
>   * It must be called with power domains already disabled (after a call to
>   * intel_power_domains_disable()) and paired with intel_power_domains_resume().
>   */
> -void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
> +void intel_power_domains_suspend(struct drm_i915_private *i915,
>  				 enum i915_drm_suspend_mode suspend_mode)
>  {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
> +	intel_wakeref_t wakeref __maybe_unused =
> +		fetch_and_zero(&power_domains->wakeref);
>  
> -	intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
> +	intel_display_power_put(i915, POWER_DOMAIN_INIT, wakeref);
>  
>  	/*
>  	 * In case of suspend-to-idle (aka S0ix) on a DMC platform without DC9
> @@ -4144,10 +4158,10 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
>  	 * resources as required and also enable deeper system power states
>  	 * that would be blocked if the firmware was inactive.
>  	 */
> -	if (!(dev_priv->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
> +	if (!(i915->csr.allowed_dc_mask & DC_STATE_EN_DC9) &&
>  	    suspend_mode == I915_DRM_SUSPEND_IDLE &&
> -	    dev_priv->csr.dmc_payload != NULL) {
> -		intel_power_domains_verify_state(dev_priv);
> +	    i915->csr.dmc_payload) {
> +		intel_power_domains_verify_state(i915);
>  		return;
>  	}
>  
> @@ -4156,25 +4170,25 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
>  	 * power wells if power domains must be deinitialized for suspend.
>  	 */
>  	if (!i915_modparams.disable_power_well) {
> -		intel_display_power_put_unchecked(dev_priv, POWER_DOMAIN_INIT);
> -		intel_power_domains_verify_state(dev_priv);
> +		intel_display_power_put_unchecked(i915, POWER_DOMAIN_INIT);
> +		intel_power_domains_verify_state(i915);
>  	}
>  
> -	if (IS_ICELAKE(dev_priv))
> -		icl_display_core_uninit(dev_priv);
> -	else if (IS_CANNONLAKE(dev_priv))
> -		cnl_display_core_uninit(dev_priv);
> -	else if (IS_GEN9_BC(dev_priv))
> -		skl_display_core_uninit(dev_priv);
> -	else if (IS_GEN9_LP(dev_priv))
> -		bxt_display_core_uninit(dev_priv);
> +	if (IS_ICELAKE(i915))
> +		icl_display_core_uninit(i915);
> +	else if (IS_CANNONLAKE(i915))
> +		cnl_display_core_uninit(i915);
> +	else if (IS_GEN9_BC(i915))
> +		skl_display_core_uninit(i915);
> +	else if (IS_GEN9_LP(i915))
> +		bxt_display_core_uninit(i915);
>  
>  	power_domains->display_core_suspended = true;
>  }
>  
>  /**
>   * intel_power_domains_resume - resume power domain state
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>   *
>   * This function resume the hardware power domain state during system resume.
>   *
> @@ -4182,28 +4196,30 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
>   * intel_power_domains_enable()) and must be paired with
>   * intel_power_domains_suspend().
>   */
> -void intel_power_domains_resume(struct drm_i915_private *dev_priv)
> +void intel_power_domains_resume(struct drm_i915_private *i915)
>  {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>  
>  	if (power_domains->display_core_suspended) {
> -		intel_power_domains_init_hw(dev_priv, true);
> +		intel_power_domains_init_hw(i915, true);
>  		power_domains->display_core_suspended = false;
>  	} else {
> -		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +		WARN_ON(power_domains->wakeref);
> +		power_domains->wakeref =
> +			intel_display_power_get(i915, POWER_DOMAIN_INIT);
>  	}
>  
> -	intel_power_domains_verify_state(dev_priv);
> +	intel_power_domains_verify_state(i915);
>  }
>  
>  #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
>  
> -static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
> +static void intel_power_domains_dump_info(struct drm_i915_private *i915)
>  {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>  	struct i915_power_well *power_well;
>  
> -	for_each_power_well(dev_priv, power_well) {
> +	for_each_power_well(i915, power_well) {
>  		enum intel_display_power_domain domain;
>  
>  		DRM_DEBUG_DRIVER("%-25s %d\n",
> @@ -4218,7 +4234,7 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
>  
>  /**
>   * intel_power_domains_verify_state - verify the HW/SW state for all power wells
> - * @dev_priv: i915 device instance
> + * @i915: i915 device instance
>   *
>   * Verify if the reference count of each power well matches its HW enabled
>   * state and the total refcount of the domains it belongs to. This must be
> @@ -4226,22 +4242,21 @@ static void intel_power_domains_dump_info(struct drm_i915_private *dev_priv)
>   * acquiring reference counts for any power wells in use and disabling the
>   * ones left on by BIOS but not required by any active output.
>   */
> -static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
> +static void intel_power_domains_verify_state(struct drm_i915_private *i915)
>  {
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_domains *power_domains = &i915->power_domains;
>  	struct i915_power_well *power_well;
>  	bool dump_domain_info;
>  
>  	mutex_lock(&power_domains->lock);
>  
>  	dump_domain_info = false;
> -	for_each_power_well(dev_priv, power_well) {
> +	for_each_power_well(i915, power_well) {
>  		enum intel_display_power_domain domain;
>  		int domains_count;
>  		bool enabled;
>  
> -		enabled = power_well->desc->ops->is_enabled(dev_priv,
> -							    power_well);
> +		enabled = power_well->desc->ops->is_enabled(i915, power_well);
>  		if ((power_well->count || power_well->desc->always_on) !=
>  		    enabled)
>  			DRM_ERROR("power well %s state mismatch (refcount %d/enabled %d)",
> @@ -4265,7 +4280,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
>  		static bool dumped;
>  
>  		if (!dumped) {
> -			intel_power_domains_dump_info(dev_priv);
> +			intel_power_domains_dump_info(i915);
>  			dumped = true;
>  		}
>  	}
> @@ -4275,7 +4290,7 @@ static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
>  
>  #else
>  
> -static void intel_power_domains_verify_state(struct drm_i915_private *dev_priv)
> +static void intel_power_domains_verify_state(struct drm_i915_private *i915)
>  {
>  }
>  
> -- 
> 2.20.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 20/21] drm/i915: Complain if hsw_get_pipe_config acquires the same power well twice
  2019-01-10 10:11 ` [PATCH 20/21] drm/i915: Complain if hsw_get_pipe_config acquires the same power well twice Chris Wilson
@ 2019-01-11 13:47   ` Mika Kuoppala
  0 siblings, 0 replies; 39+ messages in thread
From: Mika Kuoppala @ 2019-01-11 13:47 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

Chris Wilson <chris@chris-wilson.co.uk> writes:

> As we only release each power well once, we assume that each transcoder
> maps to a different domain. Complain if this is not so.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula@intel.com>

Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>

> ---
>  drivers/gpu/drm/i915/intel_display.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 36c56d1637b8..7c974cf064fd 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -9569,6 +9569,8 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
>  	power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
>  	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
>  		return false;
> +
> +	WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
>  	*power_domain_mask |= BIT_ULL(power_domain);
>  
>  	tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
> @@ -9596,6 +9598,8 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
>  		power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
>  		if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
>  			continue;
> +
> +		WARN_ON(*power_domain_mask & BIT_ULL(power_domain));
>  		*power_domain_mask |= BIT_ULL(power_domain);
>  
>  		/*
> @@ -9712,7 +9716,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>  
>  	power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
>  	if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
> +		WARN_ON(power_domain_mask & BIT_ULL(power_domain));
>  		power_domain_mask |= BIT_ULL(power_domain);
> +
>  		if (INTEL_GEN(dev_priv) >= 9)
>  			skylake_get_pfit_config(crtc, pipe_config);
>  		else
> -- 
> 2.20.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 21/21] drm/i915: Mark up Ironlake ips with rpm wakerefs
  2019-01-10 10:11 ` [PATCH 21/21] drm/i915: Mark up Ironlake ips with rpm wakerefs Chris Wilson
@ 2019-01-11 21:05   ` John Harrison
  2019-01-14 15:01   ` Mika Kuoppala
  1 sibling, 0 replies; 39+ messages in thread
From: John Harrison @ 2019-01-11 21:05 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

On 1/10/2019 02:11, Chris Wilson wrote:
> Currently Ironlake operates under the assumption that rpm awake (and its
> error checking is disabled). As such, we have missed a few places where we
> access registers without taking the rpm wakeref and thus trigger
> warnings. intel_ips being one culprit.
>
> As this involved adding a potentially sleeping rpm_get, we have to
> rearrange the spinlocks slightly and so switch to acquiring a device-ref
> under the spinlock rather than hold the spinlock for the whole
> operation. To be consistent, we make the change in pattern common to the
> intel_ips interface even though this adds a few more atomic operations
> than necessary in a few cases.
>
> v2: Sagar noted the mb around setting mch_dev were overkill as we only
> need ordering there, and that i915_emon_status was still using
> struct_mutex for no reason, but lacked rpm.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>   drivers/gpu/drm/i915/i915_debugfs.c |  32 ++----
>   drivers/gpu/drm/i915/i915_drv.c     |   3 +
>   drivers/gpu/drm/i915/intel_pm.c     | 172 ++++++++++++++--------------
>   3 files changed, 102 insertions(+), 105 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 96717a23b32f..c0263c233faa 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1741,32 +1741,24 @@ static int i915_sr_status(struct seq_file *m, void *unused)
>   
>   static int i915_emon_status(struct seq_file *m, void *unused)
>   {
> -	struct drm_i915_private *dev_priv = node_to_i915(m->private);
> -	struct drm_device *dev = &dev_priv->drm;
> -	unsigned long temp, chipset, gfx;
> +	struct drm_i915_private *i915 = node_to_i915(m->private);
>   	intel_wakeref_t wakeref;
> -	int ret;
>   
> -	if (!IS_GEN(dev_priv, 5))
> +	if (!IS_GEN(i915, 5))
>   		return -ENODEV;
>   
> -	ret = mutex_lock_interruptible(&dev->struct_mutex);
> -	if (ret)
> -		return ret;
> +	with_intel_runtime_pm(i915, wakeref) {
> +		unsigned long temp, chipset, gfx;
>   
> -	wakeref = intel_runtime_pm_get(dev_priv);
> -
> -	temp = i915_mch_val(dev_priv);
> -	chipset = i915_chipset_val(dev_priv);
> -	gfx = i915_gfx_val(dev_priv);
> -	mutex_unlock(&dev->struct_mutex);
> +		temp = i915_mch_val(i915);
> +		chipset = i915_chipset_val(i915);
> +		gfx = i915_gfx_val(i915);
>   
> -	intel_runtime_pm_put(dev_priv, wakeref);
> -
> -	seq_printf(m, "GMCH temp: %ld\n", temp);
> -	seq_printf(m, "Chipset power: %ld\n", chipset);
> -	seq_printf(m, "GFX power: %ld\n", gfx);
> -	seq_printf(m, "Total power: %ld\n", chipset + gfx);
> +		seq_printf(m, "GMCH temp: %ld\n", temp);
> +		seq_printf(m, "Chipset power: %ld\n", chipset);
> +		seq_printf(m, "GFX power: %ld\n", gfx);
> +		seq_printf(m, "Total power: %ld\n", chipset + gfx);
> +	}
I would have left the variable declarations and printfs outside of the 
pm hold. No need to keep the power on while doing a bunch of string 
manipulations.

>   
>   	return 0;
>   }
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 5731f992cf44..dafbbfadd1ad 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1780,6 +1780,9 @@ void i915_driver_unload(struct drm_device *dev)
>   
>   	i915_driver_unregister(dev_priv);
>   
> +	/* Flush any external code that still may be under the RCU lock */
> +	synchronize_rcu();
> +
>   	if (i915_gem_suspend(dev_priv))
>   		DRM_ERROR("failed to idle hardware; continuing to unload!\n");
>   
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index ab7257720c7e..7613ae72df3d 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -6203,10 +6203,6 @@ void intel_init_ipc(struct drm_i915_private *dev_priv)
>    */
>   DEFINE_SPINLOCK(mchdev_lock);
>   
> -/* Global for IPS driver to get at the current i915 device. Protected by
> - * mchdev_lock. */
> -static struct drm_i915_private *i915_mch_dev;
> -
>   bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val)
>   {
>   	u16 rgvswctl;
> @@ -7849,16 +7845,17 @@ static unsigned long __i915_chipset_val(struct drm_i915_private *dev_priv)
>   
>   unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
>   {
> -	unsigned long val;
> +	intel_wakeref_t wakeref;
> +	unsigned long val = 0;
>   
>   	if (!IS_GEN(dev_priv, 5))
>   		return 0;
>   
> -	spin_lock_irq(&mchdev_lock);
> -
> -	val = __i915_chipset_val(dev_priv);
> -
> -	spin_unlock_irq(&mchdev_lock);
> +	with_intel_runtime_pm(dev_priv, wakeref) {
> +		spin_lock_irq(&mchdev_lock);
> +		val = __i915_chipset_val(dev_priv);
> +		spin_unlock_irq(&mchdev_lock);
> +	}
>   
>   	return val;
>   }
> @@ -7935,14 +7932,16 @@ static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
>   
>   void i915_update_gfx_val(struct drm_i915_private *dev_priv)
>   {
> +	intel_wakeref_t wakeref;
> +
>   	if (!IS_GEN(dev_priv, 5))
>   		return;
>   
> -	spin_lock_irq(&mchdev_lock);
> -
> -	__i915_update_gfx_val(dev_priv);
> -
> -	spin_unlock_irq(&mchdev_lock);
> +	with_intel_runtime_pm(dev_priv, wakeref) {
> +		spin_lock_irq(&mchdev_lock);
> +		__i915_update_gfx_val(dev_priv);
> +		spin_unlock_irq(&mchdev_lock);
> +	}
>   }
>   
>   static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
> @@ -7984,18 +7983,34 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
>   
>   unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
>   {
> -	unsigned long val;
> +	intel_wakeref_t wakeref;
> +	unsigned long val = 0;
>   
>   	if (!IS_GEN(dev_priv, 5))
>   		return 0;
>   
> -	spin_lock_irq(&mchdev_lock);
> +	with_intel_runtime_pm(dev_priv, wakeref) {
> +		spin_lock_irq(&mchdev_lock);
> +		val = __i915_gfx_val(dev_priv);
> +		spin_unlock_irq(&mchdev_lock);
> +	}
>   
> -	val = __i915_gfx_val(dev_priv);
> +	return val;
> +}
>   
> -	spin_unlock_irq(&mchdev_lock);
> +static struct drm_i915_private *i915_mch_dev;
>   
> -	return val;
> +static struct drm_i915_private *mchdev_get(void)
> +{
> +	struct drm_i915_private *i915;
> +
> +	rcu_read_lock();
> +	i915 = i915_mch_dev;
> +	if (!kref_get_unless_zero(&i915->drm.ref))
> +		i915 = NULL;
> +	rcu_read_unlock();
> +
> +	return i915;
>   }
>   
>   /**
> @@ -8006,23 +8021,24 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
>    */
>   unsigned long i915_read_mch_val(void)
>   {
> -	struct drm_i915_private *dev_priv;
> -	unsigned long chipset_val, graphics_val, ret = 0;
> -
> -	spin_lock_irq(&mchdev_lock);
> -	if (!i915_mch_dev)
> -		goto out_unlock;
> -	dev_priv = i915_mch_dev;
> -
> -	chipset_val = __i915_chipset_val(dev_priv);
> -	graphics_val = __i915_gfx_val(dev_priv);
> +	struct drm_i915_private *i915;
> +	unsigned long chipset_val = 0;
> +	unsigned long graphics_val = 0;
> +	intel_wakeref_t wakeref;
>   
> -	ret = chipset_val + graphics_val;
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return 0;
>   
> -out_unlock:
> -	spin_unlock_irq(&mchdev_lock);
> +	with_intel_runtime_pm(i915, wakeref) {
> +		spin_lock_irq(&mchdev_lock);
> +		chipset_val = __i915_chipset_val(i915);
> +		graphics_val = __i915_gfx_val(i915);
> +		spin_unlock_irq(&mchdev_lock);
> +	}
>   
> -	return ret;
> +	drm_dev_put(&i915->drm);
> +	return chipset_val + graphics_val;
>   }
>   EXPORT_SYMBOL_GPL(i915_read_mch_val);
>   
> @@ -8033,23 +8049,19 @@ EXPORT_SYMBOL_GPL(i915_read_mch_val);
>    */
>   bool i915_gpu_raise(void)
>   {
> -	struct drm_i915_private *dev_priv;
> -	bool ret = true;
> -
> -	spin_lock_irq(&mchdev_lock);
> -	if (!i915_mch_dev) {
> -		ret = false;
> -		goto out_unlock;
> -	}
> -	dev_priv = i915_mch_dev;
> +	struct drm_i915_private *i915;
>   
> -	if (dev_priv->ips.max_delay > dev_priv->ips.fmax)
> -		dev_priv->ips.max_delay--;
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return false;
>   
> -out_unlock:
> +	spin_lock_irq(&mchdev_lock);
> +	if (i915->ips.max_delay > i915->ips.fmax)
> +		i915->ips.max_delay--;
>   	spin_unlock_irq(&mchdev_lock);
>   
> -	return ret;
> +	drm_dev_put(&i915->drm);
> +	return true;
>   }
>   EXPORT_SYMBOL_GPL(i915_gpu_raise);
>   
> @@ -8061,23 +8073,19 @@ EXPORT_SYMBOL_GPL(i915_gpu_raise);
>    */
>   bool i915_gpu_lower(void)
>   {
> -	struct drm_i915_private *dev_priv;
> -	bool ret = true;
> -
> -	spin_lock_irq(&mchdev_lock);
> -	if (!i915_mch_dev) {
> -		ret = false;
> -		goto out_unlock;
> -	}
> -	dev_priv = i915_mch_dev;
> +	struct drm_i915_private *i915;
>   
> -	if (dev_priv->ips.max_delay < dev_priv->ips.min_delay)
> -		dev_priv->ips.max_delay++;
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return false;
>   
> -out_unlock:
> +	spin_lock_irq(&mchdev_lock);
> +	if (i915->ips.max_delay < i915->ips.min_delay)
> +		i915->ips.max_delay++;
>   	spin_unlock_irq(&mchdev_lock);
>   
> -	return ret;
> +	drm_dev_put(&i915->drm);
> +	return true;
>   }
>   EXPORT_SYMBOL_GPL(i915_gpu_lower);
>   
> @@ -8088,13 +8096,16 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
>    */
>   bool i915_gpu_busy(void)
>   {
> -	bool ret = false;
> +	struct drm_i915_private *i915;
> +	bool ret;
>   
> -	spin_lock_irq(&mchdev_lock);
> -	if (i915_mch_dev)
> -		ret = i915_mch_dev->gt.awake;
> -	spin_unlock_irq(&mchdev_lock);
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return false;
>   
> +	ret = i915->gt.awake;
> +
> +	drm_dev_put(&i915->drm);
>   	return ret;
>   }
>   EXPORT_SYMBOL_GPL(i915_gpu_busy);
> @@ -8107,24 +8118,19 @@ EXPORT_SYMBOL_GPL(i915_gpu_busy);
>    */
>   bool i915_gpu_turbo_disable(void)
>   {
> -	struct drm_i915_private *dev_priv;
> -	bool ret = true;
> -
> -	spin_lock_irq(&mchdev_lock);
> -	if (!i915_mch_dev) {
> -		ret = false;
> -		goto out_unlock;
> -	}
> -	dev_priv = i915_mch_dev;
> -
> -	dev_priv->ips.max_delay = dev_priv->ips.fstart;
> +	struct drm_i915_private *i915;
> +	bool ret;
>   
> -	if (!ironlake_set_drps(dev_priv, dev_priv->ips.fstart))
> -		ret = false;
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return false;
>   
> -out_unlock:
> +	spin_lock_irq(&mchdev_lock);
> +	i915->ips.max_delay = i915->ips.fstart;
> +	ret = ironlake_set_drps(i915, i915->ips.fstart);
>   	spin_unlock_irq(&mchdev_lock);
>   
> +	drm_dev_put(&i915->drm);
>   	return ret;
>   }
>   EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
> @@ -8153,18 +8159,14 @@ void intel_gpu_ips_init(struct drm_i915_private *dev_priv)
>   {
>   	/* We only register the i915 ips part with intel-ips once everything is
>   	 * set up, to avoid intel-ips sneaking in and reading bogus values. */
> -	spin_lock_irq(&mchdev_lock);
> -	i915_mch_dev = dev_priv;
> -	spin_unlock_irq(&mchdev_lock);
> +	rcu_assign_pointer(i915_mch_dev, dev_priv);
>   
>   	ips_ping_for_i915_load();
>   }
>   
>   void intel_gpu_ips_teardown(void)
>   {
> -	spin_lock_irq(&mchdev_lock);
> -	i915_mch_dev = NULL;
> -	spin_unlock_irq(&mchdev_lock);
> +	rcu_assign_pointer(i915_mch_dev, NULL);
>   }
>   
>   static void intel_init_emon(struct drm_i915_private *dev_priv)

I am somewhat nervous about all those globals. But assuming all of this 
code is Ironlake only and not just the few bits that have an obvious 
'if(!GEN(5)) return;' in them, then I guess it's not an issue going 
forwards.

Either way, the changes themselves all look valid so:
Reviewed-by: John Harrison <John.C.Harrison@Intel.com>

John.

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

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

* Re: [PATCH 18/21] drm/i915: Combined gt.awake/gt.power wakerefs
  2019-01-10 10:11 ` [PATCH 18/21] drm/i915: Combined gt.awake/gt.power wakerefs Chris Wilson
@ 2019-01-14 14:20   ` Mika Kuoppala
  0 siblings, 0 replies; 39+ messages in thread
From: Mika Kuoppala @ 2019-01-14 14:20 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

Chris Wilson <chris@chris-wilson.co.uk> writes:

> As the GT_IRQ power domain implies a wakeref, we can use it inplace of
> our existing redundant rpm grab.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h                  |  1 -
>  drivers/gpu/drm/i915/i915_gem.c                  | 11 ++++-------
>  drivers/gpu/drm/i915/intel_lrc.c                 |  2 +-
>  drivers/gpu/drm/i915/selftests/mock_gem_device.c |  1 +
>  4 files changed, 6 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 259b91b62ff2..25941c649282 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1985,7 +1985,6 @@ struct drm_i915_private {
>  		 * is a slight delay before we do so.
>  		 */
>  		intel_wakeref_t awake;
> -		intel_wakeref_t power;
>  
>  		/**
>  		 * The number of times we have woken up.
> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
> index 5ed1c8576525..0bfed33178e1 100644
> --- a/drivers/gpu/drm/i915/i915_gem.c
> +++ b/drivers/gpu/drm/i915/i915_gem.c
> @@ -176,9 +176,7 @@ static u32 __i915_gem_park(struct drm_i915_private *i915)
>  	if (INTEL_GEN(i915) >= 6)
>  		gen6_rps_idle(i915);
>  
> -	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, i915->gt.power);
> -
> -	intel_runtime_pm_put(i915, wakeref);
> +	intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, wakeref);
>  
>  	return i915->gt.epoch;
>  }
> @@ -203,13 +201,11 @@ void i915_gem_unpark(struct drm_i915_private *i915)
>  
>  	lockdep_assert_held(&i915->drm.struct_mutex);
>  	GEM_BUG_ON(!i915->gt.active_requests);
> +	assert_rpm_wakelock_held(i915);
>  
>  	if (i915->gt.awake)
>  		return;
>  
> -	i915->gt.awake = intel_runtime_pm_get_noresume(i915);
> -	GEM_BUG_ON(!i915->gt.awake);
> -
>  	/*
>  	 * It seems that the DMC likes to transition between the DC states a lot
>  	 * when there are no connected displays (no active power domains) during
> @@ -221,7 +217,8 @@ void i915_gem_unpark(struct drm_i915_private *i915)
>  	 * Work around it by grabbing a GT IRQ power domain whilst there is any
>  	 * GT activity, preventing any DC state transitions.
>  	 */
> -	i915->gt.power = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
> +	i915->gt.awake = intel_display_power_get(i915, POWER_DOMAIN_GT_IRQ);
> +	GEM_BUG_ON(!i915->gt.awake);
>  
>  	if (unlikely(++i915->gt.epoch == 0)) /* keep 0 as invalid */
>  		i915->gt.epoch = 1;
> diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
> index 1effbf49fa08..608458b92db3 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/intel_lrc.c
> @@ -1045,7 +1045,7 @@ static void execlists_submission_tasklet(unsigned long data)
>  
>  	GEM_TRACE("%s awake?=%d, active=%x\n",
>  		  engine->name,
> -		  engine->i915->gt.awake,
> +		  !!engine->i915->gt.awake,
>  		  engine->execlists.active);
>  
>  	spin_lock_irqsave(&engine->timeline.lock, flags);
> diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
> index 082809569681..2c55e0fa64c9 100644
> --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
> +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
> @@ -164,6 +164,7 @@ struct drm_i915_private *mock_gem_device(void)
>  	pm_runtime_dont_use_autosuspend(&pdev->dev);
>  	if (pm_runtime_enabled(&pdev->dev))
>  		WARN_ON(pm_runtime_get_sync(&pdev->dev));
> +	disable_rpm_wakeref_asserts(i915);
>

With this seemingly unwarranted disable removed,
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>

>  	err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev);
>  	if (err) {
> -- 
> 2.20.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 21/21] drm/i915: Mark up Ironlake ips with rpm wakerefs
  2019-01-10 10:11 ` [PATCH 21/21] drm/i915: Mark up Ironlake ips with rpm wakerefs Chris Wilson
  2019-01-11 21:05   ` John Harrison
@ 2019-01-14 15:01   ` Mika Kuoppala
  2019-01-14 16:57     ` Chris Wilson
  1 sibling, 1 reply; 39+ messages in thread
From: Mika Kuoppala @ 2019-01-14 15:01 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: Jani Nikula

Chris Wilson <chris@chris-wilson.co.uk> writes:

> Currently Ironlake operates under the assumption that rpm awake (and its
> error checking is disabled). As such, we have missed a few places where we
> access registers without taking the rpm wakeref and thus trigger
> warnings. intel_ips being one culprit.
>
> As this involved adding a potentially sleeping rpm_get, we have to
> rearrange the spinlocks slightly and so switch to acquiring a device-ref
> under the spinlock rather than hold the spinlock for the whole
> operation. To be consistent, we make the change in pattern common to the
> intel_ips interface even though this adds a few more atomic operations
> than necessary in a few cases.
>
> v2: Sagar noted the mb around setting mch_dev were overkill as we only
> need ordering there, and that i915_emon_status was still using
> struct_mutex for no reason, but lacked rpm.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c |  32 ++----
>  drivers/gpu/drm/i915/i915_drv.c     |   3 +
>  drivers/gpu/drm/i915/intel_pm.c     | 172 ++++++++++++++--------------
>  3 files changed, 102 insertions(+), 105 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index 96717a23b32f..c0263c233faa 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -1741,32 +1741,24 @@ static int i915_sr_status(struct seq_file *m, void *unused)
>  
>  static int i915_emon_status(struct seq_file *m, void *unused)
>  {
> -	struct drm_i915_private *dev_priv = node_to_i915(m->private);
> -	struct drm_device *dev = &dev_priv->drm;
> -	unsigned long temp, chipset, gfx;
> +	struct drm_i915_private *i915 = node_to_i915(m->private);
>  	intel_wakeref_t wakeref;
> -	int ret;
>  
> -	if (!IS_GEN(dev_priv, 5))
> +	if (!IS_GEN(i915, 5))
>  		return -ENODEV;
>  
> -	ret = mutex_lock_interruptible(&dev->struct_mutex);
> -	if (ret)
> -		return ret;
> +	with_intel_runtime_pm(i915, wakeref) {
> +		unsigned long temp, chipset, gfx;
>  
> -	wakeref = intel_runtime_pm_get(dev_priv);
> -
> -	temp = i915_mch_val(dev_priv);
> -	chipset = i915_chipset_val(dev_priv);
> -	gfx = i915_gfx_val(dev_priv);
> -	mutex_unlock(&dev->struct_mutex);
> +		temp = i915_mch_val(i915);
> +		chipset = i915_chipset_val(i915);
> +		gfx = i915_gfx_val(i915);
>  
> -	intel_runtime_pm_put(dev_priv, wakeref);
> -
> -	seq_printf(m, "GMCH temp: %ld\n", temp);
> -	seq_printf(m, "Chipset power: %ld\n", chipset);
> -	seq_printf(m, "GFX power: %ld\n", gfx);
> -	seq_printf(m, "Total power: %ld\n", chipset + gfx);
> +		seq_printf(m, "GMCH temp: %ld\n", temp);
> +		seq_printf(m, "Chipset power: %ld\n", chipset);
> +		seq_printf(m, "GFX power: %ld\n", gfx);
> +		seq_printf(m, "Total power: %ld\n", chipset + gfx);
> +	}
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 5731f992cf44..dafbbfadd1ad 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1780,6 +1780,9 @@ void i915_driver_unload(struct drm_device *dev)
>  
>  	i915_driver_unregister(dev_priv);
>  
> +	/* Flush any external code that still may be under the RCU lock */
> +	synchronize_rcu();
> +
>  	if (i915_gem_suspend(dev_priv))
>  		DRM_ERROR("failed to idle hardware; continuing to unload!\n");
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index ab7257720c7e..7613ae72df3d 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -6203,10 +6203,6 @@ void intel_init_ipc(struct drm_i915_private *dev_priv)
>   */
>  DEFINE_SPINLOCK(mchdev_lock);
>  
> -/* Global for IPS driver to get at the current i915 device. Protected by
> - * mchdev_lock. */
> -static struct drm_i915_private *i915_mch_dev;
> -
>  bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val)
>  {
>  	u16 rgvswctl;
> @@ -7849,16 +7845,17 @@ static unsigned long __i915_chipset_val(struct drm_i915_private *dev_priv)
>  
>  unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
>  {
> -	unsigned long val;
> +	intel_wakeref_t wakeref;
> +	unsigned long val = 0;
>  
>  	if (!IS_GEN(dev_priv, 5))
>  		return 0;
>  
> -	spin_lock_irq(&mchdev_lock);
> -
> -	val = __i915_chipset_val(dev_priv);
> -
> -	spin_unlock_irq(&mchdev_lock);
> +	with_intel_runtime_pm(dev_priv, wakeref) {
> +		spin_lock_irq(&mchdev_lock);

This lock is now much more ips lock than mchdev_lock.
Name should reflect that, so ips_lock?

> +		val = __i915_chipset_val(dev_priv);
> +		spin_unlock_irq(&mchdev_lock);
> +	}
>  
>  	return val;
>  }
> @@ -7935,14 +7932,16 @@ static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
>  
>  void i915_update_gfx_val(struct drm_i915_private *dev_priv)
>  {
> +	intel_wakeref_t wakeref;
> +
>  	if (!IS_GEN(dev_priv, 5))
>  		return;
>  
> -	spin_lock_irq(&mchdev_lock);
> -
> -	__i915_update_gfx_val(dev_priv);
> -
> -	spin_unlock_irq(&mchdev_lock);
> +	with_intel_runtime_pm(dev_priv, wakeref) {
> +		spin_lock_irq(&mchdev_lock);
> +		__i915_update_gfx_val(dev_priv);
> +		spin_unlock_irq(&mchdev_lock);
> +	}
>  }
>  
>  static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
> @@ -7984,18 +7983,34 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv)
>  
>  unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
>  {
> -	unsigned long val;
> +	intel_wakeref_t wakeref;
> +	unsigned long val = 0;
>  
>  	if (!IS_GEN(dev_priv, 5))
>  		return 0;
>  
> -	spin_lock_irq(&mchdev_lock);
> +	with_intel_runtime_pm(dev_priv, wakeref) {
> +		spin_lock_irq(&mchdev_lock);
> +		val = __i915_gfx_val(dev_priv);
> +		spin_unlock_irq(&mchdev_lock);
> +	}
>  
> -	val = __i915_gfx_val(dev_priv);
> +	return val;
> +}
>  
> -	spin_unlock_irq(&mchdev_lock);
> +static struct drm_i915_private *i915_mch_dev;
>  
> -	return val;
> +static struct drm_i915_private *mchdev_get(void)
> +{
> +	struct drm_i915_private *i915;
> +
> +	rcu_read_lock();
> +	i915 = i915_mch_dev;
> +	if (!kref_get_unless_zero(&i915->drm.ref))
> +		i915 = NULL;
> +	rcu_read_unlock();
> +
> +	return i915;
>  }
>  
>  /**
> @@ -8006,23 +8021,24 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
>   */
>  unsigned long i915_read_mch_val(void)
>  {
> -	struct drm_i915_private *dev_priv;
> -	unsigned long chipset_val, graphics_val, ret = 0;
> -
> -	spin_lock_irq(&mchdev_lock);
> -	if (!i915_mch_dev)
> -		goto out_unlock;
> -	dev_priv = i915_mch_dev;
> -
> -	chipset_val = __i915_chipset_val(dev_priv);
> -	graphics_val = __i915_gfx_val(dev_priv);
> +	struct drm_i915_private *i915;
> +	unsigned long chipset_val = 0;
> +	unsigned long graphics_val = 0;
> +	intel_wakeref_t wakeref;
>  
> -	ret = chipset_val + graphics_val;
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return 0;
>  
> -out_unlock:
> -	spin_unlock_irq(&mchdev_lock);
> +	with_intel_runtime_pm(i915, wakeref) {
> +		spin_lock_irq(&mchdev_lock);
> +		chipset_val = __i915_chipset_val(i915);
> +		graphics_val = __i915_gfx_val(i915);
> +		spin_unlock_irq(&mchdev_lock);
> +	}
>  
> -	return ret;
> +	drm_dev_put(&i915->drm);

mchdev_put() would read better.
-Mika


> +	return chipset_val + graphics_val;
>  }
>  EXPORT_SYMBOL_GPL(i915_read_mch_val);
>  
> @@ -8033,23 +8049,19 @@ EXPORT_SYMBOL_GPL(i915_read_mch_val);
>   */
>  bool i915_gpu_raise(void)
>  {
> -	struct drm_i915_private *dev_priv;
> -	bool ret = true;
> -
> -	spin_lock_irq(&mchdev_lock);
> -	if (!i915_mch_dev) {
> -		ret = false;
> -		goto out_unlock;
> -	}
> -	dev_priv = i915_mch_dev;
> +	struct drm_i915_private *i915;
>  
> -	if (dev_priv->ips.max_delay > dev_priv->ips.fmax)
> -		dev_priv->ips.max_delay--;
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return false;
>  
> -out_unlock:
> +	spin_lock_irq(&mchdev_lock);
> +	if (i915->ips.max_delay > i915->ips.fmax)
> +		i915->ips.max_delay--;
>  	spin_unlock_irq(&mchdev_lock);
>  
> -	return ret;
> +	drm_dev_put(&i915->drm);
> +	return true;
>  }
>  EXPORT_SYMBOL_GPL(i915_gpu_raise);
>  
> @@ -8061,23 +8073,19 @@ EXPORT_SYMBOL_GPL(i915_gpu_raise);
>   */
>  bool i915_gpu_lower(void)
>  {
> -	struct drm_i915_private *dev_priv;
> -	bool ret = true;
> -
> -	spin_lock_irq(&mchdev_lock);
> -	if (!i915_mch_dev) {
> -		ret = false;
> -		goto out_unlock;
> -	}
> -	dev_priv = i915_mch_dev;
> +	struct drm_i915_private *i915;
>  
> -	if (dev_priv->ips.max_delay < dev_priv->ips.min_delay)
> -		dev_priv->ips.max_delay++;
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return false;
>  
> -out_unlock:
> +	spin_lock_irq(&mchdev_lock);
> +	if (i915->ips.max_delay < i915->ips.min_delay)
> +		i915->ips.max_delay++;
>  	spin_unlock_irq(&mchdev_lock);
>  
> -	return ret;
> +	drm_dev_put(&i915->drm);
> +	return true;
>  }
>  EXPORT_SYMBOL_GPL(i915_gpu_lower);
>  
> @@ -8088,13 +8096,16 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
>   */
>  bool i915_gpu_busy(void)
>  {
> -	bool ret = false;
> +	struct drm_i915_private *i915;
> +	bool ret;
>  
> -	spin_lock_irq(&mchdev_lock);
> -	if (i915_mch_dev)
> -		ret = i915_mch_dev->gt.awake;
> -	spin_unlock_irq(&mchdev_lock);
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return false;
>  
> +	ret = i915->gt.awake;
> +
> +	drm_dev_put(&i915->drm);
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(i915_gpu_busy);
> @@ -8107,24 +8118,19 @@ EXPORT_SYMBOL_GPL(i915_gpu_busy);
>   */
>  bool i915_gpu_turbo_disable(void)
>  {
> -	struct drm_i915_private *dev_priv;
> -	bool ret = true;
> -
> -	spin_lock_irq(&mchdev_lock);
> -	if (!i915_mch_dev) {
> -		ret = false;
> -		goto out_unlock;
> -	}
> -	dev_priv = i915_mch_dev;
> -
> -	dev_priv->ips.max_delay = dev_priv->ips.fstart;
> +	struct drm_i915_private *i915;
> +	bool ret;
>  
> -	if (!ironlake_set_drps(dev_priv, dev_priv->ips.fstart))
> -		ret = false;
> +	i915 = mchdev_get();
> +	if (!i915)
> +		return false;
>  
> -out_unlock:
> +	spin_lock_irq(&mchdev_lock);
> +	i915->ips.max_delay = i915->ips.fstart;
> +	ret = ironlake_set_drps(i915, i915->ips.fstart);
>  	spin_unlock_irq(&mchdev_lock);
>  
> +	drm_dev_put(&i915->drm);
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
> @@ -8153,18 +8159,14 @@ void intel_gpu_ips_init(struct drm_i915_private *dev_priv)
>  {
>  	/* We only register the i915 ips part with intel-ips once everything is
>  	 * set up, to avoid intel-ips sneaking in and reading bogus values. */
> -	spin_lock_irq(&mchdev_lock);
> -	i915_mch_dev = dev_priv;
> -	spin_unlock_irq(&mchdev_lock);
> +	rcu_assign_pointer(i915_mch_dev, dev_priv);
>  
>  	ips_ping_for_i915_load();
>  }
>  
>  void intel_gpu_ips_teardown(void)
>  {
> -	spin_lock_irq(&mchdev_lock);
> -	i915_mch_dev = NULL;
> -	spin_unlock_irq(&mchdev_lock);
> +	rcu_assign_pointer(i915_mch_dev, NULL);
>  }
>  
>  static void intel_init_emon(struct drm_i915_private *dev_priv)
> -- 
> 2.20.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 21/21] drm/i915: Mark up Ironlake ips with rpm wakerefs
  2019-01-14 15:01   ` Mika Kuoppala
@ 2019-01-14 16:57     ` Chris Wilson
  0 siblings, 0 replies; 39+ messages in thread
From: Chris Wilson @ 2019-01-14 16:57 UTC (permalink / raw)
  To: Mika Kuoppala, intel-gfx; +Cc: Jani Nikula

Quoting Mika Kuoppala (2019-01-14 15:01:59)
> Chris Wilson <chris@chris-wilson.co.uk> writes:
> >  unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
> >  {
> > -     unsigned long val;
> > +     intel_wakeref_t wakeref;
> > +     unsigned long val = 0;
> >  
> >       if (!IS_GEN(dev_priv, 5))
> >               return 0;
> >  
> > -     spin_lock_irq(&mchdev_lock);
> > -
> > -     val = __i915_chipset_val(dev_priv);
> > -
> > -     spin_unlock_irq(&mchdev_lock);
> > +     with_intel_runtime_pm(dev_priv, wakeref) {
> > +             spin_lock_irq(&mchdev_lock);
> 
> This lock is now much more ips lock than mchdev_lock.
> Name should reflect that, so ips_lock?

ips is a user, the mch is the device. The interface is yucky, so best
forget and move on, honestly.

[snip]

> > -     return ret;
> > +     drm_dev_put(&i915->drm);
> 
> mchdev_put() would read better.

Nah. mchdev_get() returns a new reference to the underlying device. From
that moment on, it's just a regular device reference. We are not
operating on the singleton itself.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

end of thread, other threads:[~2019-01-14 16:57 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-10 10:11 Track rpm wakerefs to fix bugs Chris Wilson
2019-01-10 10:11 ` [PATCH 01/21] drm/i915: Track all held rpm wakerefs Chris Wilson
2019-01-10 10:11 ` [PATCH 02/21] drm/i915: Markup paired operations on wakerefs Chris Wilson
2019-01-10 10:20   ` Mika Kuoppala
2019-01-10 10:11 ` [PATCH 03/21] drm/i915: Track GT wakeref Chris Wilson
2019-01-10 10:11 ` [PATCH 04/21] drm/i915: Track the rpm wakerefs for error handling Chris Wilson
2019-01-10 10:11 ` [PATCH 05/21] drm/i915: Mark up sysfs with rpm wakeref tracking Chris Wilson
2019-01-10 10:11 ` [PATCH 06/21] drm/i915: Mark up debugfs " Chris Wilson
2019-01-10 10:11 ` [PATCH 07/21] drm/i915/perf: Track the rpm wakeref Chris Wilson
2019-01-10 10:11 ` [PATCH 08/21] drm/i915/pmu: Track " Chris Wilson
2019-01-10 10:11 ` [PATCH 09/21] drm/i915/guc: Track the " Chris Wilson
2019-01-10 10:11 ` [PATCH 10/21] drm/i915/gem: Track the rpm wakerefs Chris Wilson
2019-01-10 10:11 ` [PATCH 11/21] drm/i915/fb: Track " Chris Wilson
2019-01-10 10:11 ` [PATCH 12/21] drm/i915/hotplug: Track temporary rpm wakeref Chris Wilson
2019-01-10 10:11 ` [PATCH 13/21] drm/i915/panel: " Chris Wilson
2019-01-10 10:11 ` [PATCH 14/21] drm/i915/selftests: Mark up rpm wakerefs Chris Wilson
2019-01-10 10:11 ` [PATCH 15/21] drm/i915: Syntatic sugar for using intel_runtime_pm Chris Wilson
2019-01-10 10:11 ` [PATCH 16/21] drm/i915: Markup paired operations on display power domains Chris Wilson
2019-01-10 15:51   ` Mika Kuoppala
2019-01-10 16:21     ` Chris Wilson
2019-01-10 16:49       ` Mika Kuoppala
2019-01-10 10:11 ` [PATCH 17/21] drm/i915: Track the wakeref used to initialise " Chris Wilson
2019-01-10 23:15   ` John Harrison
2019-01-10 23:21     ` Chris Wilson
2019-01-11 13:09   ` Mika Kuoppala
2019-01-10 10:11 ` [PATCH 18/21] drm/i915: Combined gt.awake/gt.power wakerefs Chris Wilson
2019-01-14 14:20   ` Mika Kuoppala
2019-01-10 10:11 ` [PATCH 19/21] drm/i915/dp: Markup pps lock power well Chris Wilson
2019-01-11  0:16   ` John Harrison
2019-01-11  1:19     ` Chris Wilson
2019-01-10 10:11 ` [PATCH 20/21] drm/i915: Complain if hsw_get_pipe_config acquires the same power well twice Chris Wilson
2019-01-11 13:47   ` Mika Kuoppala
2019-01-10 10:11 ` [PATCH 21/21] drm/i915: Mark up Ironlake ips with rpm wakerefs Chris Wilson
2019-01-11 21:05   ` John Harrison
2019-01-14 15:01   ` Mika Kuoppala
2019-01-14 16:57     ` Chris Wilson
2019-01-10 11:47 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/21] drm/i915: Track all held " Patchwork
2019-01-10 11:54 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-01-10 12:31 ` ✗ Fi.CI.BAT: failure " Patchwork

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.