[Intel-gfx] [PATCH v3] drm/i915/slpc: Use platform limits for min/max frequency
Belgaumkar, Vinay
vinay.belgaumkar at intel.com
Mon Oct 24 19:38:20 UTC 2022
On 10/21/2022 10:26 PM, Dixit, Ashutosh wrote:
> On Fri, 21 Oct 2022 18:38:57 -0700, Belgaumkar, Vinay wrote:
>> On 10/20/2022 3:57 PM, Dixit, Ashutosh wrote:
>>> On Tue, 18 Oct 2022 11:30:31 -0700, Vinay Belgaumkar wrote:
>>> Hi Vinay,
>>>
>>>> diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c
>>>> index 4c6e9257e593..e42bc215e54d 100644
>>>> --- a/drivers/gpu/drm/i915/gt/selftest_slpc.c
>>>> +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
>>>> @@ -234,6 +234,7 @@ static int run_test(struct intel_gt *gt, int test_type)
>>>> enum intel_engine_id id;
>>>> struct igt_spinner spin;
>>>> u32 slpc_min_freq, slpc_max_freq;
>>>> + u32 saved_min_freq;
>>>> int err = 0;
>>>>
>>>> if (!intel_uc_uses_guc_slpc(>->uc))
>>>> @@ -252,20 +253,35 @@ static int run_test(struct intel_gt *gt, int test_type)
>>>> return -EIO;
>>>> }
>>>>
>>>> - /*
>>>> - * FIXME: With efficient frequency enabled, GuC can request
>>>> - * frequencies higher than the SLPC max. While this is fixed
>>>> - * in GuC, we level set these tests with RPn as min.
>>>> - */
>>>> - err = slpc_set_min_freq(slpc, slpc->min_freq);
>>>> - if (err)
>>>> - return err;
>>>> + if (slpc_min_freq == slpc_max_freq) {
>>>> + /* Server parts will have min/max clamped to RP0 */
>>>> + if (slpc->min_is_rpmax) {
>>>> + err = slpc_set_min_freq(slpc, slpc->min_freq);
>>>> + if (err) {
>>>> + pr_err("Unable to update min freq on server part");
>>>> + return err;
>>>> + }
>>>>
>>>> - if (slpc->min_freq == slpc->rp0_freq) {
>>>> - pr_err("Min/Max are fused to the same value\n");
>>>> - return -EINVAL;
>>>> + } else {
>>>> + pr_err("Min/Max are fused to the same value\n");
>>>> + return -EINVAL;
>>> Sorry but I am not following this else case here. Why are we saying min/max
>>> are fused to the same value? In this case we can't do
>>> "slpc_set_min_freq(slpc, slpc->min_freq)" ? That is, we can't change SLPC
>>> min freq?
>> This would be an error case due to a faulty part. We may come across a part
>> where min/max is fused to the same value.
> But even then the original check is much clearer since it is actually
> comparing the fused freq's:
>
> if (slpc->min_freq == slpc->rp0_freq)
>
> Because if min/max have been changed slpc_min_freq and slpc_max_freq are no
> longer fused freq.
>
> And also this check should be right at the top of run_test, right after if
> (!intel_uc_uses_guc_slpc), rather than in the middle here (otherwise
> because we are basically not doing any error rewinding so causing memory
> leaks if any of the functions return error).
ok.
>
>>>> + }
>>>> + } else {
>>>> + /*
>>>> + * FIXME: With efficient frequency enabled, GuC can request
>>>> + * frequencies higher than the SLPC max. While this is fixed
>>>> + * in GuC, we level set these tests with RPn as min.
>>>> + */
>>>> + err = slpc_set_min_freq(slpc, slpc->min_freq);
>>>> + if (err)
>>>> + return err;
>>>> }
> So let's do what is suggested above and then see what remains here and if
> we need all these code changes. Most likely we can just do unconditionally
> what we were doing before, i.e.:
>
> err = slpc_set_min_freq(slpc, slpc->min_freq);
> if (err)
> return err;
>
>>>> + saved_min_freq = slpc_min_freq;
>>>> +
>>>> + /* New temp min freq = RPn */
>>>> + slpc_min_freq = slpc->min_freq;
> Why do we need saved_min_freq? We can retain slpc_min_freq and in the check below:
>
> if (max_act_freq <= slpc_min_freq)
>
> We can just change the check to:
>
> if (max_act_freq <= slpc->min_freq)
>
> Looks like to have been a bug in the original code?
Not a bug, it wasn't needed until we didn't have server parts
(slpc_min_freq would typically be slpc->min_freq on non-server parts).
>>>> +
>>>> intel_gt_pm_wait_for_idle(gt);
>>>> intel_gt_pm_get(gt);
>>>> for_each_engine(engine, gt, id) {
>>>> @@ -347,7 +363,7 @@ static int run_test(struct intel_gt *gt, int test_type)
>>>>
>>>> /* Restore min/max frequencies */
>>>> slpc_set_max_freq(slpc, slpc_max_freq);
>>>> - slpc_set_min_freq(slpc, slpc_min_freq);
>>>> + slpc_set_min_freq(slpc, saved_min_freq);
>>>>
>>>> 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 fdd895f73f9f..b7cdeec44bd3 100644
>>>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>>>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
>>>> @@ -263,6 +263,7 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
>>>>
>>>> slpc->max_freq_softlimit = 0;
>>>> slpc->min_freq_softlimit = 0;
>>>> + slpc->min_is_rpmax = false;
>>>>
>>>> slpc->boost_freq = 0;
>>>> atomic_set(&slpc->num_waiters, 0);
>>>> @@ -588,6 +589,32 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc)
>>>> return 0;
>>>> }
>>>>
>>>> +static bool is_slpc_min_freq_rpmax(struct intel_guc_slpc *slpc)
>>>> +{
>>>> + int slpc_min_freq;
>>>> +
>>>> + if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq))
>>>> + return false;
>>> I am wondering what happens if the above fails on server? Should we return
>>> true or false on server and what are the consequences of returning false on
>>> server?
>>>
>>> Any case I think we should at least put a drm_err or something here just in
>>> case this ever fails so we'll know something weird happened.
>> Makes sense.
>>
>>>> +
>>>> + if (slpc_min_freq == SLPC_MAX_FREQ_MHZ)
>>>> + return true;
>>>> + else
>>>> + return false;
>>>> +}
>>>> +
>>>> +static void update_server_min_softlimit(struct intel_guc_slpc *slpc)
>>>> +{
>>>> + /* For server parts, SLPC min will be at RPMax.
>>>> + * Use min softlimit to clamp it to RP0 instead.
>>>> + */
>>>> + if (is_slpc_min_freq_rpmax(slpc) &&
>>>> + !slpc->min_freq_softlimit) {
> This should be swapped around:
>
> if (!slpc->min_freq_softlimit && is_slpc_min_freq_rpmax(slpc))
>
> So we should only have to call is_slpc_min_freq_rpmax if
> slpc->min_freq_softlimit is 0 (that is only once the first time during
> init).
ok.
>
>>>> + slpc->min_is_rpmax = true;
>>>> + slpc->min_freq_softlimit = slpc->rp0_freq;
>>>> + (slpc_to_gt(slpc))->defaults.min_freq = slpc->min_freq_softlimit;
>>>> + }
>>>> +}
>>>> +
>>>> static int slpc_use_fused_rp0(struct intel_guc_slpc *slpc)
>>>> {
>>>> /* Force SLPC to used platform rp0 */
>>>> @@ -647,6 +674,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
>>>>
>>>> slpc_get_rp_values(slpc);
>>>>
>>>> + /* Handle the case where min=max=RPmax */
>>>> + update_server_min_softlimit(slpc);
>>>> +
>>>> /* Set SLPC max limit to RP0 */
>>>> ret = slpc_use_fused_rp0(slpc);
>>>> if (unlikely(ret)) {
>>>> 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 82a98f78f96c..11975a31c9d0 100644
>>>> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>>>> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
>>>> @@ -9,6 +9,8 @@
>>>> #include "intel_guc_submission.h"
>>>> #include "intel_guc_slpc_types.h"
>>>>
>>>> +#define SLPC_MAX_FREQ_MHZ 4250
>>> This seems to be really a value (255 converted to freq) so seems ok to
>>> intepret in MHz.
yes, GuC returns the value in MHz.
Thanks,
Vinay.
>>>
>>> Thanks.
>>> --
>>> Ashutosh
More information about the dri-devel
mailing list