diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 74f1d78cbe2e5..1943b8f0e6844 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -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; }; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index eff7d2e7d71b8..d523ebb2f89db 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -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 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3232305301ca9..8d0d6f59a72be 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -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); } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 4c80d2adac705..a0b9eaf77fe90 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -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);