[Intel-gfx] [PATCH v4] drm/i915/selftests: add basic selftests for rc6
From: Andi Shyti Add three basic tests for rc6 power status: 1. live_rc6_basic - simply checks if rc6 works when it's enabled or stops when it's disabled. 2. live_rc6_threshold - rc6 should not work when the evaluation interval is less than the threshold and should work otherwise. 3. live_rc6_busy - keeps the gpu busy and then goes in idle; checks that we don't fall in rc6 when busy and that we do fall in rc6 when idling. The three tests are added as sutest of the bigger live_late_gt_pm selftest. The basic rc6 functionality is tested by checking the reference counter within the evaluation interval. Signed-off-by: Andi Shyti Cc: Chris Wilson --- Hi, just resending this patch that was going in decomposition. It's rebased on top of drm-tip. Andi Changelog: * v3 -> v4: - just a small refactoring where test_rc6 becomes a measure function while another test_rc6 checks the return value from the measure. * v2 -> v3: - rebased on top of the latest drm-tip - fixed exiting order in rc6_basic to avoid exiting without releasing the pm reference * v1 -> v2: - some changes from Chris (thank you!). drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 3 + drivers/gpu/drm/i915/gt/selftest_rc6.c | 190 +++ drivers/gpu/drm/i915/gt/selftest_rc6.h | 3 + 3 files changed, 196 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c index 09ff8e4f88af..84d1a58cfa28 100644 --- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c @@ -51,6 +51,9 @@ static int live_gt_resume(void *arg) int intel_gt_pm_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { + SUBTEST(live_rc6_basic), + SUBTEST(live_rc6_threshold), + SUBTEST(live_rc6_busy), SUBTEST(live_rc6_manual), SUBTEST(live_gt_resume), }; diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.c b/drivers/gpu/drm/i915/gt/selftest_rc6.c index 5f7e2dcf5686..bd0e75421a4a 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rc6.c +++ b/drivers/gpu/drm/i915/gt/selftest_rc6.c @@ -11,6 +11,7 @@ #include "selftest_rc6.h" #include "selftests/i915_random.h" +#include "selftests/igt_spinner.h" int live_rc6_manual(void *arg) { @@ -202,3 +203,192 @@ int live_rc6_ctx_wa(void *arg) kfree(engines); return err; } + +static bool test_rc6(struct intel_rc6 *rc6, bool enabled) +{ + struct intel_uncore *uncore = rc6_to_uncore(rc6); + intel_wakeref_t wakeref; + u32 ec1, ec2; + u32 interval; + + wakeref = intel_runtime_pm_get(uncore->rpm); + + interval = intel_uncore_read(uncore, GEN6_RC_EVALUATION_INTERVAL); + + /* +* the interval is stored in steps of 1.28us +*/ + interval = div_u64(mul_u32_u32(interval, 128), + 100 * 1000); /* => miliseconds */ + + ec1 = intel_uncore_read(uncore, GEN6_GT_GFX_RC6); + + /* +* It's not important to precisely wait the interval time. +* I'll wait at least twice the time in order to be sure +* that the counting happens in the reference counter. +*/ + msleep(2 * interval); + + ec2 = intel_uncore_read(uncore, GEN6_GT_GFX_RC6); + + intel_runtime_pm_put(uncore->rpm, wakeref); + + return enabled != (ec1 >= ec2); +} + +int live_rc6_basic(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_rc6 *rc6 = >->rc6; + intel_wakeref_t wakeref; + int i, err = 0; + + if (!rc6->supported) + return 0; + + wakeref = intel_runtime_pm_get(gt->uncore->rpm); + + /* +* the two loops test rc6 both in case it's enabled +* and in the case it's disabled. It restores the prvious +* status +*/ + for (i = 0; i < 2; i++) { + if (!test_rc6(rc6, rc6->enabled)) { + err = -EINVAL; + + /* restore before leaving */ + if (!i) + goto exit; + } + + if (rc6->enabled) + intel_rc6_disable(>->rc6); + else + intel_rc6_enable(>->rc6); + } + +exit: + intel_runtime_pm_put(gt->uncore->rpm, wakeref); + return err; +} + +int live_rc6_threshold(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_uncore *uncore = gt->uncore; + struct intel_rc6 *rc6 = >->rc6; + intel_wakeref_t wakeref; + u32 threshold, interval; + u32 t_orig, i_orig; + int err = 0; + + if (!rc6->supported) + return 0; + + wakeref = intel_runtime_pm_get(uncore->rpm); + + t_orig = intel_uncore_read(uncore, GEN6_RC6_THRESHOLD); + i_orig = intel_uncore_read(uncore, GEN6_RC_EVALUATION_
[Intel-gfx] [PATCH v4] drm/i915/selftests: add basic selftests for rc6
From: Andi Shyti Add three basic tests for rc6 power status: 1. live_rc6_basic - simply checks if rc6 works when it's enabled or stops when it's disabled. 2. live_rc6_threshold - rc6 should not work when the evaluation interval is less than the threshold and should work otherwise. 3. live_rc6_busy - keeps the gpu busy and then goes in idle; checks that we don't fall in rc6 when busy and that we do fall in rc6 when idling. The three tests are added as sutest of the bigger live_late_gt_pm selftest. The basic rc6 functionality is tested by checking the reference counter within the evaluation interval. Signed-off-by: Andi Shyti Cc: Chris Wilson --- Hi, just resending this patch that was going in decomposition. It's rebased on top of drm-tip. Andi Changelog: * v3 -> v4: - just a small refactoring where test_rc6 becomes a measure function while another test_rc6 checks the return value from the measure. * v2 -> v3: - rebased on top of the latest drm-tip - fixed exiting order in rc6_basic to avoid exiting without releasing the pm reference * v1 -> v2: - some changes from Chris (thank you!). drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 3 + drivers/gpu/drm/i915/gt/selftest_rc6.c | 190 +++ drivers/gpu/drm/i915/gt/selftest_rc6.h | 3 + 3 files changed, 196 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c index 09ff8e4f88af..84d1a58cfa28 100644 --- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c @@ -51,6 +51,9 @@ static int live_gt_resume(void *arg) int intel_gt_pm_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { + SUBTEST(live_rc6_basic), + SUBTEST(live_rc6_threshold), + SUBTEST(live_rc6_busy), SUBTEST(live_rc6_manual), SUBTEST(live_gt_resume), }; diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.c b/drivers/gpu/drm/i915/gt/selftest_rc6.c index 5f7e2dcf5686..bd0e75421a4a 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rc6.c +++ b/drivers/gpu/drm/i915/gt/selftest_rc6.c @@ -11,6 +11,7 @@ #include "selftest_rc6.h" #include "selftests/i915_random.h" +#include "selftests/igt_spinner.h" int live_rc6_manual(void *arg) { @@ -202,3 +203,192 @@ int live_rc6_ctx_wa(void *arg) kfree(engines); return err; } + +static bool test_rc6(struct intel_rc6 *rc6, bool enabled) +{ + struct intel_uncore *uncore = rc6_to_uncore(rc6); + intel_wakeref_t wakeref; + u32 ec1, ec2; + u32 interval; + + wakeref = intel_runtime_pm_get(uncore->rpm); + + interval = intel_uncore_read(uncore, GEN6_RC_EVALUATION_INTERVAL); + + /* +* the interval is stored in steps of 1.28us +*/ + interval = div_u64(mul_u32_u32(interval, 128), + 100 * 1000); /* => miliseconds */ + + ec1 = intel_uncore_read(uncore, GEN6_GT_GFX_RC6); + + /* +* It's not important to precisely wait the interval time. +* I'll wait at least twice the time in order to be sure +* that the counting happens in the reference counter. +*/ + msleep(2 * interval); + + ec2 = intel_uncore_read(uncore, GEN6_GT_GFX_RC6); + + intel_runtime_pm_put(uncore->rpm, wakeref); + + return enabled != (ec1 >= ec2); +} + +int live_rc6_basic(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_rc6 *rc6 = >->rc6; + intel_wakeref_t wakeref; + int i, err = 0; + + if (!rc6->supported) + return 0; + + wakeref = intel_runtime_pm_get(gt->uncore->rpm); + + /* +* the two loops test rc6 both in case it's enabled +* and in the case it's disabled. It restores the prvious +* status +*/ + for (i = 0; i < 2; i++) { + if (!test_rc6(rc6, rc6->enabled)) { + err = -EINVAL; + + /* restore before leaving */ + if (!i) + goto exit; + } + + if (rc6->enabled) + intel_rc6_disable(>->rc6); + else + intel_rc6_enable(>->rc6); + } + +exit: + intel_runtime_pm_put(gt->uncore->rpm, wakeref); + return err; +} + +int live_rc6_threshold(void *arg) +{ + struct intel_gt *gt = arg; + struct intel_uncore *uncore = gt->uncore; + struct intel_rc6 *rc6 = >->rc6; + intel_wakeref_t wakeref; + u32 threshold, interval; + u32 t_orig, i_orig; + int err = 0; + + if (!rc6->supported) + return 0; + + wakeref = intel_runtime_pm_get(uncore->rpm); + + t_orig = intel_uncore_read(uncore, GEN6_RC6_THRESHOLD); + i_orig = intel_uncore_read(uncore, GEN6_RC_EVALUATION_