diff mbox series

drm/i915/guc/slpc: Provide sysfs for efficient freq

Message ID 20230418000915.3489494-1-vinay.belgaumkar@intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915/guc/slpc: Provide sysfs for efficient freq | expand

Commit Message

Vinay Belgaumkar April 18, 2023, 12:09 a.m. UTC
SLPC enables use of efficient freq at init by default. It is
possible for GuC to request frequencies that are higher than
the 'software' max if user has set it lower than the efficient
level.

Scenarios/tests that require strict fixing of freq below the efficient
level will need to disable it through this interface.

v2: Keep just one interface to toggle sysfs. With this, user will
be completely responsible for toggling efficient frequency if need
be. There will be no implicit disabling when user sets min < RP1 (Ashutosh)

v3: Remove unused label, review comments (Ashutosh)

v4: Toggle efficient freq usage in SLPC selftest and checkpatch fixes

Fixes: 95ccf312a1e4 ("drm/i915/guc/slpc: Allow SLPC to use efficient frequency")
Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
 drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c   | 35 ++++++++++++++++
 drivers/gpu/drm/i915/gt/selftest_slpc.c       | 13 +++---
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c   | 40 ++++++++++++++-----
 drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h   |  1 +
 .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h |  1 +
 5 files changed, 72 insertions(+), 18 deletions(-)

Comments

Andi Shyti April 18, 2023, 1:39 a.m. UTC | #1
Hi Vinay,

Looks good, just few minor comments below,

[...]

> @@ -267,13 +267,11 @@ static int run_test(struct intel_gt *gt, int test_type)
>  	}
>  
>  	/*
> -	 * Set min frequency to RPn so that we can test the whole
> -	 * range of RPn-RP0. This also turns off efficient freq
> -	 * usage and makes results more predictable.
> +	 * Turn off efficient freq so RPn/RP0 ranges are obeyed
>  	 */
> -	err = slpc_set_min_freq(slpc, slpc->min_freq);
> +	err = intel_guc_slpc_set_ignore_eff_freq(slpc, true);
>  	if (err) {
> -		pr_err("Unable to update min freq!");
> +		pr_err("Unable to turn off efficient freq!");

drm_err()? or gt_err()? As we are here we can use a proper
printing.

How is this change related to the scope of this patch?

>  		return err;
>  	}
>  
> @@ -358,9 +356,10 @@ static int run_test(struct intel_gt *gt, int test_type)
>  			break;
>  	}
>  
> -	/* Restore min/max frequencies */
> -	slpc_set_max_freq(slpc, slpc_max_freq);
> +	/* Restore min/max frequencies and efficient flag */
>  	slpc_set_min_freq(slpc, slpc_min_freq);
> +	slpc_set_max_freq(slpc, slpc_max_freq);
> +	intel_guc_slpc_set_ignore_eff_freq(slpc, false);

mmhhh... do we care here about the return value?

>  
>  	if (igt_flush_test(gt->i915))
>  		err = -EIO;
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> index 026d73855f36..b1b70ee3001b 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
> @@ -277,6 +277,7 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>  
>  	slpc->max_freq_softlimit = 0;
>  	slpc->min_freq_softlimit = 0;
> +	slpc->ignore_eff_freq = false;
>  	slpc->min_is_rpmax = false;
>  
>  	slpc->boost_freq = 0;
> @@ -457,6 +458,31 @@ int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val)
>  	return ret;
>  }
>  
> +int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val)
> +{
> +	struct drm_i915_private *i915 = slpc_to_i915(slpc);
> +	intel_wakeref_t wakeref;
> +	int ret = 0;

no need to initialize ret here.

> +
> +	mutex_lock(&slpc->lock);
> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
> +
> +	ret = slpc_set_param(slpc,
> +			     SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY,
> +			     val);
> +	if (ret) {
> +		guc_probe_error(slpc_to_guc(slpc), "Failed to set efficient freq(%d): %pe\n",
> +				val, ERR_PTR(ret));
> +		goto out;
> +	}
> +
> +	slpc->ignore_eff_freq = val;

nit that you can ignore: if you put this under else and save
brackets and a goto.

Andi
Vinay Belgaumkar April 18, 2023, 6:04 a.m. UTC | #2
On 4/17/2023 6:39 PM, Andi Shyti wrote:
> Hi Vinay,
>
> Looks good, just few minor comments below,
>
> [...]
>
>> @@ -267,13 +267,11 @@ static int run_test(struct intel_gt *gt, int test_type)
>>   	}
>>   
>>   	/*
>> -	 * Set min frequency to RPn so that we can test the whole
>> -	 * range of RPn-RP0. This also turns off efficient freq
>> -	 * usage and makes results more predictable.
>> +	 * Turn off efficient freq so RPn/RP0 ranges are obeyed
>>   	 */
>> -	err = slpc_set_min_freq(slpc, slpc->min_freq);
>> +	err = intel_guc_slpc_set_ignore_eff_freq(slpc, true);
>>   	if (err) {
>> -		pr_err("Unable to update min freq!");
>> +		pr_err("Unable to turn off efficient freq!");
> drm_err()? or gt_err()? As we are here we can use a proper
> printing.
>
> How is this change related to the scope of this patch?
The selftest was relying on setting min freq < RP1 to disable efficient 
freq, now that we have an interface, the test should use that (former 
method will not work). Should this be a separate patch?
>
>>   		return err;
>>   	}
>>   
>> @@ -358,9 +356,10 @@ static int run_test(struct intel_gt *gt, int test_type)
>>   			break;
>>   	}
>>   
>> -	/* Restore min/max frequencies */
>> -	slpc_set_max_freq(slpc, slpc_max_freq);
>> +	/* Restore min/max frequencies and efficient flag */
>>   	slpc_set_min_freq(slpc, slpc_min_freq);
>> +	slpc_set_max_freq(slpc, slpc_max_freq);
>> +	intel_guc_slpc_set_ignore_eff_freq(slpc, false);
> mmhhh... do we care here about the return value?
I guess we should, will add.
>
>>   
>>   	if (igt_flush_test(gt->i915))
>>   		err = -EIO;
>> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> index 026d73855f36..b1b70ee3001b 100644
>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>> @@ -277,6 +277,7 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>>   
>>   	slpc->max_freq_softlimit = 0;
>>   	slpc->min_freq_softlimit = 0;
>> +	slpc->ignore_eff_freq = false;
>>   	slpc->min_is_rpmax = false;
>>   
>>   	slpc->boost_freq = 0;
>> @@ -457,6 +458,31 @@ int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val)
>>   	return ret;
>>   }
>>   
>> +int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val)
>> +{
>> +	struct drm_i915_private *i915 = slpc_to_i915(slpc);
>> +	intel_wakeref_t wakeref;
>> +	int ret = 0;
> no need to initialize ret here.
ok.
>
>> +
>> +	mutex_lock(&slpc->lock);
>> +	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
>> +
>> +	ret = slpc_set_param(slpc,
>> +			     SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY,
>> +			     val);
>> +	if (ret) {
>> +		guc_probe_error(slpc_to_guc(slpc), "Failed to set efficient freq(%d): %pe\n",
>> +				val, ERR_PTR(ret));
>> +		goto out;
>> +	}
>> +
>> +	slpc->ignore_eff_freq = val;
> nit that you can ignore: if you put this under else and save
> brackets and a goto.

ok.

Thanks,

Vinay.

>
> Andi
Andi Shyti April 18, 2023, 7:10 a.m. UTC | #3
Hi Vinay,

On Mon, Apr 17, 2023 at 11:04:31PM -0700, Belgaumkar, Vinay wrote:
> 
> On 4/17/2023 6:39 PM, Andi Shyti wrote:
> > Hi Vinay,
> > 
> > Looks good, just few minor comments below,
> > 
> > [...]
> > 
> > > @@ -267,13 +267,11 @@ static int run_test(struct intel_gt *gt, int test_type)
> > >   	}
> > >   	/*
> > > -	 * Set min frequency to RPn so that we can test the whole
> > > -	 * range of RPn-RP0. This also turns off efficient freq
> > > -	 * usage and makes results more predictable.
> > > +	 * Turn off efficient freq so RPn/RP0 ranges are obeyed
> > >   	 */
> > > -	err = slpc_set_min_freq(slpc, slpc->min_freq);
> > > +	err = intel_guc_slpc_set_ignore_eff_freq(slpc, true);
> > >   	if (err) {
> > > -		pr_err("Unable to update min freq!");
> > > +		pr_err("Unable to turn off efficient freq!");
> > drm_err()? or gt_err()? As we are here we can use a proper
> > printing.
> > 
> > How is this change related to the scope of this patch?
> The selftest was relying on setting min freq < RP1 to disable efficient
> freq, now that we have an interface, the test should use that (former method
> will not work). Should this be a separate patch?

I would have placed it in a separate patch. But I'm not strong
with it, up to you.

Thanks,
Andi
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
index 28f27091cd3b..ee2b44f896a2 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
@@ -451,6 +451,33 @@  static ssize_t punit_req_freq_mhz_show(struct kobject *kobj,
 	return sysfs_emit(buff, "%u\n", preq);
 }
 
+static ssize_t slpc_ignore_eff_freq_show(struct kobject *kobj,
+					 struct kobj_attribute *attr,
+					 char *buff)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
+	struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
+
+	return sysfs_emit(buff, "%u\n", slpc->ignore_eff_freq);
+}
+
+static ssize_t slpc_ignore_eff_freq_store(struct kobject *kobj,
+					  struct kobj_attribute *attr,
+					  const char *buff, size_t count)
+{
+	struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
+	struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
+	int err;
+	u32 val;
+
+	err = kstrtou32(buff, 0, &val);
+	if (err)
+		return err;
+
+	err = intel_guc_slpc_set_ignore_eff_freq(slpc, val);
+	return err ?: count;
+}
+
 struct intel_gt_bool_throttle_attr {
 	struct attribute attr;
 	ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
@@ -663,6 +690,8 @@  static struct kobj_attribute attr_media_freq_factor_scale =
 INTEL_GT_ATTR_RO(media_RP0_freq_mhz);
 INTEL_GT_ATTR_RO(media_RPn_freq_mhz);
 
+INTEL_GT_ATTR_RW(slpc_ignore_eff_freq);
+
 static const struct attribute *media_perf_power_attrs[] = {
 	&attr_media_freq_factor.attr,
 	&attr_media_freq_factor_scale.attr,
@@ -744,6 +773,12 @@  void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
 	if (ret)
 		gt_warn(gt, "failed to create punit_req_freq_mhz sysfs (%pe)", ERR_PTR(ret));
 
+	if (intel_uc_uses_guc_slpc(&gt->uc)) {
+		ret = sysfs_create_file(kobj, &attr_slpc_ignore_eff_freq.attr);
+		if (ret)
+			gt_warn(gt, "failed to create ignore_eff_freq sysfs (%pe)", ERR_PTR(ret));
+	}
+
 	if (i915_mmio_reg_valid(intel_gt_perf_limit_reasons_reg(gt))) {
 		ret = sysfs_create_files(kobj, throttle_reason_attrs);
 		if (ret)
diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c
index bd44ce73a504..0de44db34d27 100644
--- a/drivers/gpu/drm/i915/gt/selftest_slpc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
@@ -267,13 +267,11 @@  static int run_test(struct intel_gt *gt, int test_type)
 	}
 
 	/*
-	 * Set min frequency to RPn so that we can test the whole
-	 * range of RPn-RP0. This also turns off efficient freq
-	 * usage and makes results more predictable.
+	 * Turn off efficient freq so RPn/RP0 ranges are obeyed
 	 */
-	err = slpc_set_min_freq(slpc, slpc->min_freq);
+	err = intel_guc_slpc_set_ignore_eff_freq(slpc, true);
 	if (err) {
-		pr_err("Unable to update min freq!");
+		pr_err("Unable to turn off efficient freq!");
 		return err;
 	}
 
@@ -358,9 +356,10 @@  static int run_test(struct intel_gt *gt, int test_type)
 			break;
 	}
 
-	/* Restore min/max frequencies */
-	slpc_set_max_freq(slpc, slpc_max_freq);
+	/* Restore min/max frequencies and efficient flag */
 	slpc_set_min_freq(slpc, slpc_min_freq);
+	slpc_set_max_freq(slpc, slpc_max_freq);
+	intel_guc_slpc_set_ignore_eff_freq(slpc, false);
 
 	if (igt_flush_test(gt->i915))
 		err = -EIO;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
index 026d73855f36..b1b70ee3001b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -277,6 +277,7 @@  int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
 
 	slpc->max_freq_softlimit = 0;
 	slpc->min_freq_softlimit = 0;
+	slpc->ignore_eff_freq = false;
 	slpc->min_is_rpmax = false;
 
 	slpc->boost_freq = 0;
@@ -457,6 +458,31 @@  int intel_guc_slpc_get_max_freq(struct intel_guc_slpc *slpc, u32 *val)
 	return ret;
 }
 
+int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val)
+{
+	struct drm_i915_private *i915 = slpc_to_i915(slpc);
+	intel_wakeref_t wakeref;
+	int ret = 0;
+
+	mutex_lock(&slpc->lock);
+	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+
+	ret = slpc_set_param(slpc,
+			     SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY,
+			     val);
+	if (ret) {
+		guc_probe_error(slpc_to_guc(slpc), "Failed to set efficient freq(%d): %pe\n",
+				val, ERR_PTR(ret));
+		goto out;
+	}
+
+	slpc->ignore_eff_freq = val;
+out:
+	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
+	mutex_unlock(&slpc->lock);
+	return ret;
+}
+
 /**
  * intel_guc_slpc_set_min_freq() - Set min frequency limit for SLPC.
  * @slpc: pointer to intel_guc_slpc.
@@ -482,16 +508,6 @@  int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
 	mutex_lock(&slpc->lock);
 	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
 
-	/* Ignore efficient freq if lower min freq is requested */
-	ret = slpc_set_param(slpc,
-			     SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY,
-			     val < slpc->rp1_freq);
-	if (ret) {
-		guc_probe_error(slpc_to_guc(slpc), "Failed to toggle efficient freq: %pe\n",
-				ERR_PTR(ret));
-		goto out;
-	}
-
 	ret = slpc_set_param(slpc,
 			     SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ,
 			     val);
@@ -499,7 +515,6 @@  int intel_guc_slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 val)
 	if (!ret)
 		slpc->min_freq_softlimit = val;
 
-out:
 	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 	mutex_unlock(&slpc->lock);
 
@@ -752,6 +767,9 @@  int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
 	/* Set cached media freq ratio mode */
 	intel_guc_slpc_set_media_ratio_mode(slpc, slpc->media_ratio_mode);
 
+	/* Set cached value of ignore efficient freq */
+	intel_guc_slpc_set_ignore_eff_freq(slpc, slpc->ignore_eff_freq);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
index 17ed515f6a85..597eb5413ddf 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -46,5 +46,6 @@  void intel_guc_slpc_boost(struct intel_guc_slpc *slpc);
 void intel_guc_slpc_dec_waiters(struct intel_guc_slpc *slpc);
 int intel_guc_slpc_unset_gucrc_mode(struct intel_guc_slpc *slpc);
 int intel_guc_slpc_override_gucrc_mode(struct intel_guc_slpc *slpc, u32 mode);
+int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val);
 
 #endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h
index a6ef53b04e04..a88651331497 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h
@@ -31,6 +31,7 @@  struct intel_guc_slpc {
 	/* frequency softlimits */
 	u32 min_freq_softlimit;
 	u32 max_freq_softlimit;
+	bool ignore_eff_freq;
 
 	/* cached media ratio mode */
 	u32 media_ratio_mode;