drm/i915/guc/slpc: Add waitboost functionality for SLPC
authorVinay Belgaumkar <vinay.belgaumkar@intel.com>
Tue, 2 Nov 2021 01:26:07 +0000 (18:26 -0700)
committerJohn Harrison <John.C.Harrison@Intel.com>
Thu, 4 Nov 2021 00:44:13 +0000 (17:44 -0700)
Add helper in RPS code for handling SLPC and non-SLPC paths.
When boost is requested in the SLPC path, we can ask GuC to ramp
up the frequency req by setting the minimum frequency to boost freq.
Reset freq back to the min softlimit when there are no more waiters.

v2: Schedule a worker thread which can boost freq from within
an interrupt context as well.

v3: No need to check against requested freq before scheduling boost
work (Ashutosh)

Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211102012608.8609-3-vinay.belgaumkar@intel.com
drivers/gpu/drm/i915/gt/intel_rps.c
drivers/gpu/drm/i915/gt/intel_rps.h
drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
drivers/gpu/drm/i915/i915_request.c

index 5e275f8dda8cff2229d9d3a2901c98940a729eac..6f310c9d97650623e7d8b9ad5237dc7b81bae460 100644 (file)
@@ -936,8 +936,23 @@ void intel_rps_park(struct intel_rps *rps)
        GT_TRACE(rps_to_gt(rps), "park:%x\n", rps->cur_freq);
 }
 
+void intel_rps_dec_waiters(struct intel_rps *rps)
+{
+       struct intel_guc_slpc *slpc;
+
+       if (rps_uses_slpc(rps)) {
+               slpc = rps_to_slpc(rps);
+
+               intel_guc_slpc_dec_waiters(slpc);
+       } else {
+               atomic_dec(&rps->num_waiters);
+       }
+}
+
 void intel_rps_boost(struct i915_request *rq)
 {
+       struct intel_guc_slpc *slpc;
+
        if (i915_request_signaled(rq) || i915_request_has_waitboost(rq))
                return;
 
@@ -945,6 +960,16 @@ void intel_rps_boost(struct i915_request *rq)
        if (!test_and_set_bit(I915_FENCE_FLAG_BOOST, &rq->fence.flags)) {
                struct intel_rps *rps = &READ_ONCE(rq->engine)->gt->rps;
 
+               if (rps_uses_slpc(rps)) {
+                       slpc = rps_to_slpc(rps);
+
+                       /* Return if old value is non zero */
+                       if (!atomic_fetch_inc(&slpc->num_waiters))
+                               schedule_work(&slpc->boost_work);
+
+                       return;
+               }
+
                if (atomic_fetch_inc(&rps->num_waiters))
                        return;
 
index 11960d64ca822616d1404ca82e94d4b34454add2..407e878d500679be04913f6a9d83964d1b4b5dfd 100644 (file)
@@ -23,6 +23,7 @@ void intel_rps_disable(struct intel_rps *rps);
 void intel_rps_park(struct intel_rps *rps);
 void intel_rps_unpark(struct intel_rps *rps);
 void intel_rps_boost(struct i915_request *rq);
+void intel_rps_dec_waiters(struct intel_rps *rps);
 
 int intel_rps_set(struct intel_rps *rps, u8 val);
 void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive);
index 3a9750af0bdf9d3891c084a964fc6fdf8dd28ea6..db418396a145d91470841f08bed7687a1dd48c50 100644 (file)
@@ -446,7 +446,11 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
            val > slpc->max_freq_softlimit)
                return -EINVAL;
 
+       /* Need a lock now since waitboost can be modifying min as well */
+       mutex_lock(&slpc->lock);
+
        with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+
                ret = slpc_set_param(slpc,
                                     SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
                                     val);
@@ -459,6 +463,8 @@ int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
        if (!ret)
                slpc->min_freq_softlimit = val;
 
+       mutex_unlock(&slpc->lock);
+
        return ret;
 }
 
@@ -644,6 +650,20 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
        return 0;
 }
 
+void intel_guc_slpc_dec_waiters(struct intel_guc_slpc *slpc)
+{
+       /*
+        * Return min back to the softlimit.
+        * This is called during request retire,
+        * so we don't need to fail that if the
+        * set_param fails.
+        */
+       mutex_lock(&slpc->lock);
+       if (atomic_dec_and_test(&slpc->num_waiters))
+               slpc_force_min_freq(slpc, slpc->min_freq_softlimit);
+       mutex_unlock(&slpc->lock);
+}
+
 int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p)
 {
        struct drm_i915_private *i915 = slpc_to_i915(slpc);
index b625286477702b5a59fe8b33bd00428a75d595a8..d74d6d749bdce9a85fce368b80de68a0795c73b3 100644 (file)
@@ -39,5 +39,6 @@ int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val);
 int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p);
 void intel_guc_pm_intrmsk_enable(struct intel_gt *gt);
 void intel_guc_slpc_boost(struct intel_guc_slpc *slpc);
+void intel_guc_slpc_dec_waiters(struct intel_guc_slpc *slpc);
 
 #endif
index 2c3cd6e635b5db735e96a8d436a36f55f62b83ac..08f38e86231d609f3f56c6154c5d1989fec11b03 100644 (file)
@@ -339,7 +339,7 @@ bool i915_request_retire(struct i915_request *rq)
        }
 
        if (test_and_set_bit(I915_FENCE_FLAG_BOOST, &rq->fence.flags))
-               atomic_dec(&rq->engine->gt->rps.num_waiters);
+               intel_rps_dec_waiters(&rq->engine->gt->rps);
 
        /*
         * We only loosely track inflight requests across preemption,