drm/i915: add support for checking RPM atomic sections
authorImre Deak <imre.deak@intel.com>
Tue, 15 Dec 2015 18:10:37 +0000 (20:10 +0200)
committerImre Deak <imre.deak@intel.com>
Thu, 17 Dec 2015 14:37:43 +0000 (16:37 +0200)
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>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> (v3)
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1450203038-5150-10-git-send-email-imre.deak@intel.com
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_runtime_pm.c

index 74f1d78cbe2e572d1cf0206d27ab29cf2e09b397..1943b8f0e684487f38414438b8510a5c3af31904 100644 (file)
@@ -1606,6 +1606,7 @@ struct skl_wm_level {
  */
 struct i915_runtime_pm {
        atomic_t wakeref_count;
+       atomic_t atomic_seq;
        bool suspended;
        bool irqs_enabled;
 };
index eff7d2e7d71b881c6d5eb65a4e14b6c31b23ab7b..d523ebb2f89dbac35120ce0ee78be868f19b355f 100644 (file)
@@ -1446,6 +1446,23 @@ assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
                  "RPM wakelock ref 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_wakeref_asserts - disable the RPM assert checks
  * @dev_priv: i915 device instance
index 3232305301ca99d5634b829ba75b2918f8a49bb1..8d0d6f59a72bef31073cb120684b69b134a4edbe 100644 (file)
@@ -7247,4 +7247,5 @@ void intel_pm_setup(struct drm_device *dev)
 
        dev_priv->pm.suspended = false;
        atomic_set(&dev_priv->pm.wakeref_count, 0);
+       atomic_set(&dev_priv->pm.atomic_seq, 0);
 }
index 4c80d2adac7050b95224d8975dfdc0c8f878860c..a0b9eaf77fe904b26431eac66137eec6bbc7af40 100644 (file)
@@ -2287,7 +2287,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.wakeref_count);
+       if (atomic_dec_and_test(&dev_priv->pm.wakeref_count))
+               atomic_inc(&dev_priv->pm.atomic_seq);
 
        pm_runtime_mark_last_busy(device);
        pm_runtime_put_autosuspend(device);