diff mbox

[v4,6/7] drm/i915: add support for checking RPM atomic sections

Message ID 1447423716-11398-1-git-send-email-imre.deak@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Imre Deak Nov. 13, 2015, 2:08 p.m. UTC
In some cases we want to check whether we hold an RPM wakelock reference
for the whole duration of a sequence. To achieve this add a new RPM atomic sequence
counter that we increment any time the wakelock refcount drops to zero.
Check whether the sequence number stays the same during the atomic
section and that we hold the wakelock at the beginning of the section.

Motivated by Chris.

v2-v3:
- unchanged
v4:
- swap the order of atomic_read() and assert_rpm_wakelock_held() in
  assert_rpm_atomic_begin() to avoid race

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h         |  1 +
 drivers/gpu/drm/i915/intel_drv.h        | 17 +++++++++++++++++
 drivers/gpu/drm/i915/intel_pm.c         |  1 +
 drivers/gpu/drm/i915/intel_runtime_pm.c |  3 ++-
 4 files changed, 21 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 658cb9b..c265d47 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1600,6 +1600,7 @@  struct skl_wm_level {
  */
 struct i915_runtime_pm {
 	atomic_t wakelock_count;
+	atomic_t atomic_seq;
 	bool suspended;
 	bool irqs_enabled;
 };
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ee403d7..9e975f3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1443,6 +1443,23 @@  assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
 		  "RPM wakelock not held during HW access");
 }
 
+static inline int
+assert_rpm_atomic_begin(struct drm_i915_private *dev_priv)
+{
+	int seq = atomic_read(&dev_priv->pm.atomic_seq);
+
+	assert_rpm_wakelock_held(dev_priv);
+
+	return seq;
+}
+
+static inline void
+assert_rpm_atomic_end(struct drm_i915_private *dev_priv, int begin_seq)
+{
+	WARN_ONCE(atomic_read(&dev_priv->pm.atomic_seq) != begin_seq,
+		 "HW access outside of RPM atomic section\n");
+}
+
 /**
  * disable_rpm_asserts - disable the RPM assert checks
  * @dev_priv: i915 device instance
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6d74d32..2390237 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -7215,4 +7215,5 @@  void intel_pm_setup(struct drm_device *dev)
 
 	dev_priv->pm.suspended = false;
 	atomic_set(&dev_priv->pm.wakelock_count, 0);
+	atomic_set(&dev_priv->pm.atomic_seq, 0);
 }
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 44b0575..4334758 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -2186,7 +2186,8 @@  void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
 	struct device *device = &dev->pdev->dev;
 
 	assert_rpm_wakelock_held(dev_priv);
-	atomic_dec(&dev_priv->pm.wakelock_count);
+	if (atomic_dec_and_test(&dev_priv->pm.wakelock_count))
+		atomic_inc(&dev_priv->pm.atomic_seq);
 
 	pm_runtime_mark_last_busy(device);
 	pm_runtime_put_autosuspend(device);