drm/i915: Lift runtime-pm acquire callbacks out of intel_wakeref.mutex
authorjsg <jsg@openbsd.org>
Mon, 12 Aug 2024 23:36:45 +0000 (23:36 +0000)
committerjsg <jsg@openbsd.org>
Mon, 12 Aug 2024 23:36:45 +0000 (23:36 +0000)
From Chris Wilson
4cd64e9d2c7206db05e7162d0258b455726b7ec5 in mainline linux

sys/dev/pci/drm/i915/intel_wakeref.c

index fabd41b..5c3f009 100644 (file)
 #include "intel_wakeref.h"
 #include "i915_drv.h"
 
-static void rpm_get(struct intel_wakeref *wf)
-{
-       wf->wakeref = intel_runtime_pm_get(&wf->i915->runtime_pm);
-}
-
-static void rpm_put(struct intel_wakeref *wf)
-{
-       intel_wakeref_t wakeref = fetch_and_zero(&wf->wakeref);
-
-       intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
-       INTEL_WAKEREF_BUG_ON(!wakeref);
-}
-
 int __intel_wakeref_get_first(struct intel_wakeref *wf)
 {
+       intel_wakeref_t wakeref;
+       int ret = 0;
+
+       wakeref = intel_runtime_pm_get(&wf->i915->runtime_pm);
        /*
         * Treat get/put as different subclasses, as we may need to run
         * the put callback from under the shrinker and do not want to
@@ -32,41 +23,52 @@ int __intel_wakeref_get_first(struct intel_wakeref *wf)
         * upon acquiring the wakeref.
         */
        mutex_lock_nested(&wf->mutex, SINGLE_DEPTH_NESTING);
-       if (!atomic_read(&wf->count)) {
-               int err;
-
-               rpm_get(wf);
 
-               err = wf->ops->get(wf);
-               if (unlikely(err)) {
-                       rpm_put(wf);
-                       mutex_unlock(&wf->mutex);
-                       return err;
+       if (!atomic_read(&wf->count)) {
+               INTEL_WAKEREF_BUG_ON(wf->wakeref);
+               wf->wakeref = wakeref;
+               wakeref = 0;
+
+               ret = wf->ops->get(wf);
+               if (ret) {
+                       wakeref = xchg(&wf->wakeref, 0);
+                       wake_up_var(&wf->wakeref);
+                       goto unlock;
                }
 
                smp_mb__before_atomic(); /* release wf->count */
        }
+
        atomic_inc(&wf->count);
+       INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0);
+
+unlock:
        mutex_unlock(&wf->mutex);
+       if (unlikely(wakeref))
+               intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
 
-       INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0);
-       return 0;
+       return ret;
 }
 
 static void ____intel_wakeref_put_last(struct intel_wakeref *wf)
 {
+       intel_wakeref_t wakeref = 0;
+
        INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0);
        if (unlikely(!atomic_dec_and_test(&wf->count)))
                goto unlock;
 
        /* ops->put() must reschedule its own release on error/deferral */
        if (likely(!wf->ops->put(wf))) {
-               rpm_put(wf);
+               INTEL_WAKEREF_BUG_ON(!wf->wakeref);
+               wakeref = xchg(&wf->wakeref, 0);
                wake_up_var(&wf->wakeref);
        }
 
 unlock:
        mutex_unlock(&wf->mutex);
+       if (wakeref)
+               intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
 }
 
 void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags)