[PATCH i-g-t] tests/xe/pmu: Add pmu tests
Simple tests for validating the PMU implementation for GT C6 residencies and frequency. These tests validate the kernel series which is currently in review here - https://patchwork.freedesktop.org/series/139121/ Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- lib/igt_perf.c | 18 ++ lib/igt_perf.h | 2 + tests/intel/xe_pmu.c | 412 +++ tests/meson.build| 1 + 4 files changed, 433 insertions(+) create mode 100644 tests/intel/xe_pmu.c diff --git a/lib/igt_perf.c b/lib/igt_perf.c index 3866c6d77..88ea66ffc 100644 --- a/lib/igt_perf.c +++ b/lib/igt_perf.c @@ -129,6 +129,18 @@ uint64_t igt_perf_type_id(const char *device) return strtoull(buf, NULL, 0); } +int igt_xe_perf_events_dir(int xe) +{ + char buf[80]; + char path[PATH_MAX]; + + memset(buf, 0, sizeof(buf)); + + xe_perf_device(xe, buf, sizeof(buf)); + snprintf(path, sizeof(path), "/sys/bus/event_source/devices/%s/events", buf); + return open(path, O_RDONLY); +} + int igt_perf_events_dir(int i915) { char buf[80]; @@ -183,6 +195,12 @@ int perf_xe_open(int xe, uint64_t config) PERF_FORMAT_TOTAL_TIME_ENABLED); } +int perf_xe_open_group(int xe, uint64_t config, int group) +{ + return _perf_open(xe_perf_type_id(xe), config, group, + PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP); +} + int perf_i915_open(int i915, uint64_t config) { return _perf_open(i915_perf_type_id(i915), config, -1, diff --git a/lib/igt_perf.h b/lib/igt_perf.h index 3d9ba2917..8aff78d0e 100644 --- a/lib/igt_perf.h +++ b/lib/igt_perf.h @@ -55,6 +55,7 @@ perf_event_open(struct perf_event_attr *attr, uint64_t igt_perf_type_id(const char *device); int igt_perf_events_dir(int i915); +int igt_xe_perf_events_dir(int xe); int igt_perf_open(uint64_t type, uint64_t config); int igt_perf_open_group(uint64_t type, uint64_t config, int group); @@ -71,5 +72,6 @@ int perf_i915_open(int i915, uint64_t config); int perf_i915_open_group(int i915, uint64_t config, int group); int perf_xe_open(int xe, uint64_t config); +int perf_xe_open_group(int xe, uint64_t config, int group); #endif /* I915_PERF_H */ diff --git a/tests/intel/xe_pmu.c b/tests/intel/xe_pmu.c new file mode 100644 index 0..f5ef24757 --- /dev/null +++ b/tests/intel/xe_pmu.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +/** + * TEST: Test Xe PMU functionality + * Category: Perf Monitoring Unit + * Mega feature: Perf Monitoring Unit + * Sub-category: Power Management + * Functionality: Power/Perf + * Test category: Functional tests + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "igt.h" +#include "igt_device.h" +#include "igt_power.h" +#include "igt_sysfs.h" +#include "igt_perf.h" + +#include "lib/igt_syncobj.h" +#include "xe/xe_ioctl.h" +#include "xe/xe_query.h" +#include "xe/xe_spin.h" +#include "xe/xe_util.h" + +#define SLEEP_DURATION 2 /* in seconds */ +const double tolerance = 0.1; +const unsigned long batch_duration_ns = 500e6; +const char *no_debug_data = "\0"; + +#define __assert_within_epsilon(x, ref, tol_up, tol_down, debug_data) \ + igt_assert_f((double)(x) <= (1.0 + (tol_up)) * (double)(ref) && \ +(double)(x) >= (1.0 - (tol_down)) * (double)(ref), \ +"'%s' != '%s' (%f not within +%.1f%%/-%.1f%% tolerance of %f)\n%s\n",\ +#x, #ref, (double)(x), \ +(tol_up) * 100.0, (tol_down) * 100.0, \ +(double)(ref), debug_data) + +#define assert_within_epsilon(x, ref, tolerance) \ + __assert_within_epsilon(x, ref, tolerance, tolerance, no_debug_data) + +#define assert_within_epsilon_debug(x, ref, tolerance, debug_data) \ + __assert_within_epsilon(x, ref, tolerance, tolerance, debug_data) + +struct workload { + struct drm_xe_sync sync[2]; + struct drm_xe_exec exec; + uint64_t addr; + struct xe_spin_opts spin_opts; + struct xe_spin *spin; + uint32_t exec_queue; + uint32_t syncobj; + size_t bo_size; + uint32_t bo; + uint32_t vm; +}; + +static int open_pmu(int xe, uint64_t config) +{ + int fd; + + fd = perf_xe_open(xe, config); + igt_skip_on(fd < 0 && errno == ENODEV); + igt_assert(fd >= 0); + + return fd; +} + +static int open_group(int xe, uint64_t config, int group) +{ + int fd; + + fd = perf_xe_open_group(xe, config, group); + igt_skip_on(fd < 0 && errno == ENODEV); + igt_assert(fd >= 0); + + return fd; +} + +static uint64_t __pmu_read_single(int fd, uint64_t *ts) +{ + uint64_t data[2]; + + i
[PATCH i-g-t] tests/xe_gt_freq: Use sync reset
Some recent WAs reduce the GT freq during driver load/reset. Use sync reset so that we give enough time for GT frequency to be restored after reset has completed. Also, stash/restore frequencies per GT as they can be different. Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2676 Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2711 Cc: Badal Nilawar Signed-off-by: Vinay Belgaumkar --- tests/intel/xe_gt_freq.c | 24 +--- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/tests/intel/xe_gt_freq.c b/tests/intel/xe_gt_freq.c index 427e12c55..de4d111ea 100644 --- a/tests/intel/xe_gt_freq.c +++ b/tests/intel/xe_gt_freq.c @@ -341,7 +341,8 @@ static void test_reset(int fd, int gt_id, int cycles) igt_assert_f(get_freq(fd, gt_id, "cur") == rpn, "Failed after %d good cycles\n", i); - xe_force_gt_reset_async(fd, gt_id); + xe_force_gt_reset_sync(fd, gt_id); + usleep(SLPC_FREQ_LATENCY_US); igt_assert_f(get_freq(fd, gt_id, "min") == rpn, @@ -433,16 +434,23 @@ igt_main int fd; int gt; struct drm_xe_engine_class_instance *hwe; - uint32_t stash_min; - uint32_t stash_max; + uint32_t *stash_min, *stash_max; + int num_gts; igt_fixture { fd = drm_open_driver(DRIVER_XE); igt_require(xe_sysfs_gt_has_node(fd, 0, "freq0")); + num_gts = xe_number_gt(fd); + /* The defaults are the same. Stashing the gt0 is enough */ - stash_min = get_freq(fd, 0, "min"); - stash_max = get_freq(fd, 0, "max"); + stash_min = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t *) malloc(sizeof(uint32_t) * num_gts); + + xe_for_each_gt(fd, gt) { + stash_min[gt] = get_freq(fd, gt, "min"); + stash_max[gt] = get_freq(fd, gt, "max"); + } } igt_subtest("throttle_basic_api") { @@ -517,9 +525,11 @@ igt_main igt_fixture { xe_for_each_gt(fd, gt) { - set_freq(fd, gt, "min", stash_min); - set_freq(fd, gt, "max", stash_max); + set_freq(fd, gt, "max", stash_max[gt]); + set_freq(fd, gt, "min", stash_min[gt]); } + free(stash_min); + free(stash_max); drm_close_driver(fd); } } -- 2.38.1
[PATCH v4 i-g-t] tests/xe_gt_freq: Avoid RPe usage in subtests
We are seeing several instances where the RPe, which can be altered by pcode dynamically, is causing subtests to fail randomly. Instead of relying on it, we can use a mid frequency value for these subtests and avoid these failures. v2: Fix bug in the tolerance function. Remove rpe usage from freq_range* as well (Badal). Fix test documentation to reflect change (Riana). v3: Actual frequency cannot be guaranteed to follow the requested value v4: Handle cases where RPe can be greater than min/cur freq. Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2200 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2196 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2262 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2256 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2203 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2412 Cc: Riana Tauro Cc: Badal Nilawar Signed-off-by: Vinay Belgaumkar --- tests/intel/xe_gt_freq.c | 57 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/tests/intel/xe_gt_freq.c b/tests/intel/xe_gt_freq.c index 93ebb5ed0..c9d59508b 100644 --- a/tests/intel/xe_gt_freq.c +++ b/tests/intel/xe_gt_freq.c @@ -26,6 +26,9 @@ #include #define MAX_N_EXEC_QUEUES 16 +#define GT_FREQUENCY_MULTIPLIER50 +#define GT_FREQUENCY_SCALER3 +#define FREQ_UNIT_MHZ DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, GT_FREQUENCY_SCALER) /* * Too many intermediate components and steps before freq is adjusted @@ -70,9 +73,14 @@ static uint32_t get_freq(int fd, int gt_id, const char *freq_name) return freq; } -static uint32_t rpe(int fd, int gt_id) +static bool within_expected_range(uint32_t freq, uint32_t val) { - return get_freq(fd, gt_id, "rpe"); + /* +* GT Frequencies are requested at units of 16.66 Mhz, so allow +* that tolerance. +*/ + return (freq <= val + FREQ_UNIT_MHZ) && + (freq >= val - FREQ_UNIT_MHZ); } static uint32_t get_throttle(int fd, int gt_id, const char *throttle_file) @@ -128,6 +136,8 @@ static void test_freq_basic_api(int fd, int gt_id) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); + uint32_t rpmid = (rp0 + rpn) / 2; + uint32_t min_freq, max_freq; /* * Negative bound tests @@ -142,16 +152,19 @@ static void test_freq_basic_api(int fd, int gt_id) /* Assert min requests are respected from rp0 to rpn */ igt_assert(set_freq(fd, gt_id, "min", rp0) > 0); igt_assert(get_freq(fd, gt_id, "min") == rp0); - igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); - igt_assert(get_freq(fd, gt_id, "min") == rpe(fd, gt_id)); + igt_assert(set_freq(fd, gt_id, "min", rpmid) > 0); + min_freq = get_freq(fd, gt_id, "min"); + /* SLPC can set min higher than rpmid - as it follows RPe */ + igt_assert(min_freq >= (rpmid - FREQ_UNIT_MHZ)); igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); igt_assert(get_freq(fd, gt_id, "min") == rpn); /* Assert max requests are respected from rpn to rp0 */ igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); igt_assert(get_freq(fd, gt_id, "max") == rpn); - igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); - igt_assert(get_freq(fd, gt_id, "max") == rpe(fd, gt_id)); + igt_assert(set_freq(fd, gt_id, "max", rpmid) > 0); + max_freq = get_freq(fd, gt_id, "max"); + igt_assert(within_expected_range(max_freq, rpmid)); igt_assert(set_freq(fd, gt_id, "max", rp0) > 0); igt_assert(get_freq(fd, gt_id, "max") == rp0); } @@ -168,13 +181,16 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); + uint32_t rpmid = (rp0 + rpn) / 2; + uint32_t cur_freq, act_freq; igt_debug("Starting testing fixed request\n"); /* * For Fixed freq we need to set both min and max to the desired value * Then we check if hardware is actually operating at the desired freq -* And let's do this for all the 3 known Render Performance (RP) values. +* And let's do this for all the 2 known Render Performance (RP) values +* RP0 and RPn and something in between. */ igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); @@ -190,17 +206,20 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) igt_assert(ge
[PATCH v3 i-g-t] tests/xe_gt_freq: Avoid RPe usage in subtests
We are seeing several instances where the RPe, which can be altered by pcode dynamically, is causing subtests to fail randomly. Instead of relying on it, we can use a mid frequency value for these subtests and avoid these failures. v2: Fix bug in the tolerance function. Remove rpe usage from freq_range* as well (Badal). Fix test documentation to reflect change (Riana). v3: Actual frequency cannot be guaranteed to follow the requested value Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2200 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2196 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2262 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2256 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2203 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2412 Cc: Riana Tauro Cc: Badal Nilawar Signed-off-by: Vinay Belgaumkar --- tests/intel/xe_gt_freq.c | 55 +++- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/tests/intel/xe_gt_freq.c b/tests/intel/xe_gt_freq.c index 93ebb5ed0..7c0457ddf 100644 --- a/tests/intel/xe_gt_freq.c +++ b/tests/intel/xe_gt_freq.c @@ -26,6 +26,9 @@ #include #define MAX_N_EXEC_QUEUES 16 +#define GT_FREQUENCY_MULTIPLIER50 +#define GT_FREQUENCY_SCALER3 +#define FREQ_UNIT_MHZ DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, GT_FREQUENCY_SCALER) /* * Too many intermediate components and steps before freq is adjusted @@ -70,9 +73,14 @@ static uint32_t get_freq(int fd, int gt_id, const char *freq_name) return freq; } -static uint32_t rpe(int fd, int gt_id) +static bool within_expected_range(uint32_t freq, uint32_t val) { - return get_freq(fd, gt_id, "rpe"); + /* +* GT Frequencies are requested at units of 16.66 Mhz, so allow +* that tolerance. +*/ + return (freq <= val + FREQ_UNIT_MHZ) && + (freq >= val - FREQ_UNIT_MHZ); } static uint32_t get_throttle(int fd, int gt_id, const char *throttle_file) @@ -128,6 +136,8 @@ static void test_freq_basic_api(int fd, int gt_id) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); + uint32_t rpmid = (rp0 + rpn) / 2; + uint32_t min_freq, max_freq; /* * Negative bound tests @@ -142,16 +152,18 @@ static void test_freq_basic_api(int fd, int gt_id) /* Assert min requests are respected from rp0 to rpn */ igt_assert(set_freq(fd, gt_id, "min", rp0) > 0); igt_assert(get_freq(fd, gt_id, "min") == rp0); - igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); - igt_assert(get_freq(fd, gt_id, "min") == rpe(fd, gt_id)); + igt_assert(set_freq(fd, gt_id, "min", rpmid) > 0); + min_freq = get_freq(fd, gt_id, "min"); + igt_assert(within_expected_range(min_freq, rpmid)); igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); igt_assert(get_freq(fd, gt_id, "min") == rpn); /* Assert max requests are respected from rpn to rp0 */ igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); igt_assert(get_freq(fd, gt_id, "max") == rpn); - igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); - igt_assert(get_freq(fd, gt_id, "max") == rpe(fd, gt_id)); + igt_assert(set_freq(fd, gt_id, "max", rpmid) > 0); + max_freq = get_freq(fd, gt_id, "max"); + igt_assert(within_expected_range(max_freq, rpmid)); igt_assert(set_freq(fd, gt_id, "max", rp0) > 0); igt_assert(get_freq(fd, gt_id, "max") == rp0); } @@ -168,13 +180,16 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); + uint32_t rpmid = (rp0 + rpn) / 2; + uint32_t cur_freq, act_freq; igt_debug("Starting testing fixed request\n"); /* * For Fixed freq we need to set both min and max to the desired value * Then we check if hardware is actually operating at the desired freq -* And let's do this for all the 3 known Render Performance (RP) values. +* And let's do this for all the 2 known Render Performance (RP) values +* RP0 and RPn and something in between. */ igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); @@ -190,17 +205,19 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) igt_assert(get_freq(fd, gt_id, "act") == rpn); } - igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); -
[PATCH v2 i-g-t] tests/xe_gt_freq: Avoid RPe usage in subtests
We are seeing several instances where the RPe, which can be altered by pcode dynamically, is causing subtests to fail randomly. Instead of relying on it, we can use a mid frequency value for these subtests and avoid these failures. v2: Fix bug in the tolerance function. Remove rpe usage from freq_range* as well (Badal). Fix test documentation to reflect change (Riana). Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2200 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2196 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2262 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2256 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2203 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2412 Cc: Riana Tauro Cc: Badal Nilawar Signed-off-by: Vinay Belgaumkar --- tests/intel/xe_gt_freq.c | 53 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/tests/intel/xe_gt_freq.c b/tests/intel/xe_gt_freq.c index 93ebb5ed0..1ada37834 100644 --- a/tests/intel/xe_gt_freq.c +++ b/tests/intel/xe_gt_freq.c @@ -26,6 +26,9 @@ #include #define MAX_N_EXEC_QUEUES 16 +#define GT_FREQUENCY_MULTIPLIER50 +#define GT_FREQUENCY_SCALER3 +#define FREQ_UNIT_MHZ DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, GT_FREQUENCY_SCALER) /* * Too many intermediate components and steps before freq is adjusted @@ -70,9 +73,14 @@ static uint32_t get_freq(int fd, int gt_id, const char *freq_name) return freq; } -static uint32_t rpe(int fd, int gt_id) +static bool within_expected_range(uint32_t freq, uint32_t val) { - return get_freq(fd, gt_id, "rpe"); + /* +* GT Frequencies are requested at units of 16.66 Mhz, so allow +* that tolerance. +*/ + return (freq <= val + FREQ_UNIT_MHZ) && + (freq >= val - FREQ_UNIT_MHZ); } static uint32_t get_throttle(int fd, int gt_id, const char *throttle_file) @@ -128,6 +136,8 @@ static void test_freq_basic_api(int fd, int gt_id) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); + uint32_t rpmid = (rp0 + rpn) / 2; + uint32_t min_freq, max_freq; /* * Negative bound tests @@ -142,16 +152,18 @@ static void test_freq_basic_api(int fd, int gt_id) /* Assert min requests are respected from rp0 to rpn */ igt_assert(set_freq(fd, gt_id, "min", rp0) > 0); igt_assert(get_freq(fd, gt_id, "min") == rp0); - igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); - igt_assert(get_freq(fd, gt_id, "min") == rpe(fd, gt_id)); + igt_assert(set_freq(fd, gt_id, "min", rpmid) > 0); + min_freq = get_freq(fd, gt_id, "min"); + igt_assert(within_expected_range(min_freq, rpmid)); igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); igt_assert(get_freq(fd, gt_id, "min") == rpn); /* Assert max requests are respected from rpn to rp0 */ igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); igt_assert(get_freq(fd, gt_id, "max") == rpn); - igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); - igt_assert(get_freq(fd, gt_id, "max") == rpe(fd, gt_id)); + igt_assert(set_freq(fd, gt_id, "max", rpmid) > 0); + max_freq = get_freq(fd, gt_id, "max"); + igt_assert(within_expected_range(max_freq, rpmid)); igt_assert(set_freq(fd, gt_id, "max", rp0) > 0); igt_assert(get_freq(fd, gt_id, "max") == rp0); } @@ -168,13 +180,16 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); + uint32_t rpmid = (rp0 + rpn) / 2; + uint32_t cur_freq, act_freq; igt_debug("Starting testing fixed request\n"); /* * For Fixed freq we need to set both min and max to the desired value * Then we check if hardware is actually operating at the desired freq -* And let's do this for all the 3 known Render Performance (RP) values. +* And let's do this for all the 2 known Render Performance (RP) values +* RP0 and RPn and something in between. */ igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); @@ -190,17 +205,19 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) igt_assert(get_freq(fd, gt_id, "act") == rpn); } - igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); - igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) >
[PATCH i-g-t] tests/xe_gt_freq: Avoid RPe usage in subtests
We are seeing several instances where the RPe, which can be altered by pcode dynamically, is causing subtests to fail randomly. Instead of relying on it, we can use a mid frequency value for these subtests and avoid these failures. Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2262 Link: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2256 Signed-off-by: Vinay Belgaumkar --- tests/intel/xe_gt_freq.c | 37 + 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/tests/intel/xe_gt_freq.c b/tests/intel/xe_gt_freq.c index 93ebb5ed0..442f5658f 100644 --- a/tests/intel/xe_gt_freq.c +++ b/tests/intel/xe_gt_freq.c @@ -26,6 +26,9 @@ #include #define MAX_N_EXEC_QUEUES 16 +#define GT_FREQUENCY_MULTIPLIER50 +#define GT_FREQUENCY_SCALER3 +#define FREQ_UNIT_MHZ (GT_FREQUENCY_MULTIPLIER / GT_FREQUENCY_SCALER) /* * Too many intermediate components and steps before freq is adjusted @@ -70,6 +73,16 @@ static uint32_t get_freq(int fd, int gt_id, const char *freq_name) return freq; } +static bool within_expected_range(uint32_t freq, uint32_t val) +{ + /* +* GT Frequencies are requested at units of 16.66 Mhz, so allow +* that tolerance. +*/ + return (freq <= val + FREQ_UNIT_MHZ) || + (freq >= val - FREQ_UNIT_MHZ); +} + static uint32_t rpe(int fd, int gt_id) { return get_freq(fd, gt_id, "rpe"); @@ -128,6 +141,8 @@ static void test_freq_basic_api(int fd, int gt_id) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); + uint32_t rpmid = (rp0 + rpn) / 2; + uint32_t min_freq, max_freq; /* * Negative bound tests @@ -142,16 +157,18 @@ static void test_freq_basic_api(int fd, int gt_id) /* Assert min requests are respected from rp0 to rpn */ igt_assert(set_freq(fd, gt_id, "min", rp0) > 0); igt_assert(get_freq(fd, gt_id, "min") == rp0); - igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); - igt_assert(get_freq(fd, gt_id, "min") == rpe(fd, gt_id)); + igt_assert(set_freq(fd, gt_id, "min", rpmid) > 0); + min_freq = get_freq(fd, gt_id, "min"); + igt_assert(within_expected_range(min_freq, rpmid)); igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); igt_assert(get_freq(fd, gt_id, "min") == rpn); /* Assert max requests are respected from rpn to rp0 */ igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); igt_assert(get_freq(fd, gt_id, "max") == rpn); - igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); - igt_assert(get_freq(fd, gt_id, "max") == rpe(fd, gt_id)); + igt_assert(set_freq(fd, gt_id, "max", rpmid) > 0); + max_freq = get_freq(fd, gt_id, "min"); + igt_assert(within_expected_range(max_freq, rpmid)); igt_assert(set_freq(fd, gt_id, "max", rp0) > 0); igt_assert(get_freq(fd, gt_id, "max") == rp0); } @@ -168,6 +185,8 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); + uint32_t rpmid = (rp0 + rpn) / 2; + uint32_t cur_freq, act_freq; igt_debug("Starting testing fixed request\n"); @@ -190,17 +209,19 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) igt_assert(get_freq(fd, gt_id, "act") == rpn); } - igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); - igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); + igt_assert(set_freq(fd, gt_id, "min", rpmid) > 0); + igt_assert(set_freq(fd, gt_id, "max", rpmid) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert(get_freq(fd, gt_id, "cur") == rpe(fd, gt_id)); + cur_freq = get_freq(fd, gt_id, "cur"); + igt_assert(within_expected_range(cur_freq, rpmid)); if (gt_idle) { igt_assert_f(igt_wait(xe_is_gt_in_c6(fd, gt_id), 1000, 10), "GT %d should be in C6\n", gt_id); igt_assert(get_freq(fd, gt_id, "act") == 0); } else { - igt_assert(get_freq(fd, gt_id, "act") == rpe(fd, gt_id)); + act_freq = get_freq(fd, gt_id, "act"); + igt_assert(within_expected_range(act_freq, rpmid)); } igt_assert(set_freq(fd, gt_id, "min", rp0) > 0); -- 2.38.1
[PATCH i-g-t v2] test/xe_gt_freq: Add helper to read RPe freq
We are seeing a possible switch in RPe right after RC6 wakeup. Ensure we obtain the latest RPe by reading it every time. If pcode does change the RPe after RC6 exit, the cur frequency should get updated to match it. v2: Rebase and add another comment to commit message (Badal) Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/1414 Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/1829 Fixes: adcc68266b8e ("tests/intel/xe_gt_freq: Check for RPe freq updates") Reviewed-by: Badal Nilawar Signed-off-by: Vinay Belgaumkar --- tests/intel/xe_gt_freq.c | 40 ++-- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/tests/intel/xe_gt_freq.c b/tests/intel/xe_gt_freq.c index b3562181d..93ebb5ed0 100644 --- a/tests/intel/xe_gt_freq.c +++ b/tests/intel/xe_gt_freq.c @@ -70,6 +70,11 @@ static uint32_t get_freq(int fd, int gt_id, const char *freq_name) return freq; } +static uint32_t rpe(int fd, int gt_id) +{ + return get_freq(fd, gt_id, "rpe"); +} + static uint32_t get_throttle(int fd, int gt_id, const char *throttle_file) { uint32_t val; @@ -122,7 +127,6 @@ static void test_throttle_basic_api(int fd, int gt_id) static void test_freq_basic_api(int fd, int gt_id) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); - uint32_t rpe = get_freq(fd, gt_id, "rpe"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); /* @@ -138,16 +142,16 @@ static void test_freq_basic_api(int fd, int gt_id) /* Assert min requests are respected from rp0 to rpn */ igt_assert(set_freq(fd, gt_id, "min", rp0) > 0); igt_assert(get_freq(fd, gt_id, "min") == rp0); - igt_assert(set_freq(fd, gt_id, "min", rpe) > 0); - igt_assert(get_freq(fd, gt_id, "min") == rpe); + igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); + igt_assert(get_freq(fd, gt_id, "min") == rpe(fd, gt_id)); igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); igt_assert(get_freq(fd, gt_id, "min") == rpn); /* Assert max requests are respected from rpn to rp0 */ igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); igt_assert(get_freq(fd, gt_id, "max") == rpn); - igt_assert(set_freq(fd, gt_id, "max", rpe) > 0); - igt_assert(get_freq(fd, gt_id, "max") == rpe); + igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); + igt_assert(get_freq(fd, gt_id, "max") == rpe(fd, gt_id)); igt_assert(set_freq(fd, gt_id, "max", rp0) > 0); igt_assert(get_freq(fd, gt_id, "max") == rp0); } @@ -163,7 +167,6 @@ static void test_freq_basic_api(int fd, int gt_id) static void test_freq_fixed(int fd, int gt_id, bool gt_idle) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); - uint32_t rpe = get_freq(fd, gt_id, "rpe"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); igt_debug("Starting testing fixed request\n"); @@ -187,20 +190,17 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) igt_assert(get_freq(fd, gt_id, "act") == rpn); } - /* Refresh value of rpe, pcode could have adjusted it */ - rpe = get_freq(fd, gt_id, "rpe"); - - igt_assert(set_freq(fd, gt_id, "min", rpe) > 0); - igt_assert(set_freq(fd, gt_id, "max", rpe) > 0); + igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); + igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert(get_freq(fd, gt_id, "cur") == rpe); + igt_assert(get_freq(fd, gt_id, "cur") == rpe(fd, gt_id)); if (gt_idle) { igt_assert_f(igt_wait(xe_is_gt_in_c6(fd, gt_id), 1000, 10), "GT %d should be in C6\n", gt_id); igt_assert(get_freq(fd, gt_id, "act") == 0); } else { - igt_assert(get_freq(fd, gt_id, "act") == rpe); + igt_assert(get_freq(fd, gt_id, "act") == rpe(fd, gt_id)); } igt_assert(set_freq(fd, gt_id, "min", rp0) > 0); @@ -232,16 +232,15 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) static void test_freq_range(int fd, int gt_id, bool gt_idle) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); - uint32_t rpe = get_freq(fd, gt_id, "rpe"); uint32_t cur, act; igt_debug("Starting testing range request\n"); igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); - igt_assert(set_freq(fd, gt_id, "max", rpe) > 0); + igt_ass
[PATCH i-g-t] test/xe_gt_freq: Add helper to read RPe freq
We are seeing a possible switch in RPe right after RC6 wakeup. Ensure we obtain the latest RPe by reading it every time. Fixes: adcc68266b8e ("tests/intel/xe_gt_freq: Check for RPe freq updates") Signed-off-by: Vinay Belgaumkar --- tests/intel/xe_gt_freq.c | 43 ++-- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/tests/intel/xe_gt_freq.c b/tests/intel/xe_gt_freq.c index d2e4d1a09..65ec3b0c4 100644 --- a/tests/intel/xe_gt_freq.c +++ b/tests/intel/xe_gt_freq.c @@ -70,6 +70,11 @@ static uint32_t get_freq(int fd, int gt_id, const char *freq_name) return freq; } +static uint32_t rpe(int fd, int gt_id) +{ + return get_freq(fd, gt_id, "rpe"); +} + static uint32_t get_throttle(int fd, int gt_id, const char *throttle_file) { uint32_t val; @@ -122,7 +127,6 @@ static void test_throttle_basic_api(int fd, int gt_id) static void test_freq_basic_api(int fd, int gt_id) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); - uint32_t rpe = get_freq(fd, gt_id, "rpe"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); /* @@ -138,16 +142,16 @@ static void test_freq_basic_api(int fd, int gt_id) /* Assert min requests are respected from rp0 to rpn */ igt_assert(set_freq(fd, gt_id, "min", rp0) > 0); igt_assert(get_freq(fd, gt_id, "min") == rp0); - igt_assert(set_freq(fd, gt_id, "min", rpe) > 0); - igt_assert(get_freq(fd, gt_id, "min") == rpe); + igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); + igt_assert(get_freq(fd, gt_id, "min") == rpe(fd, gt_id)); igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); igt_assert(get_freq(fd, gt_id, "min") == rpn); /* Assert max requests are respected from rpn to rp0 */ igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); igt_assert(get_freq(fd, gt_id, "max") == rpn); - igt_assert(set_freq(fd, gt_id, "max", rpe) > 0); - igt_assert(get_freq(fd, gt_id, "max") == rpe); + igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); + igt_assert(get_freq(fd, gt_id, "max") == rpe(fd, gt_id)); igt_assert(set_freq(fd, gt_id, "max", rp0) > 0); igt_assert(get_freq(fd, gt_id, "max") == rp0); } @@ -163,7 +167,6 @@ static void test_freq_basic_api(int fd, int gt_id) static void test_freq_fixed(int fd, int gt_id, bool gt_idle) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); - uint32_t rpe = get_freq(fd, gt_id, "rpe"); uint32_t rp0 = get_freq(fd, gt_id, "rp0"); igt_debug("Starting testing fixed request\n"); @@ -187,20 +190,17 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) igt_assert(get_freq(fd, gt_id, "act") == rpn); } - /* Refresh value of rpe, pcode could have adjusted it */ - rpe = get_freq(fd, gt_id, "rpe"); - - igt_assert(set_freq(fd, gt_id, "min", rpe) > 0); - igt_assert(set_freq(fd, gt_id, "max", rpe) > 0); + igt_assert(set_freq(fd, gt_id, "min", rpe(fd, gt_id)) > 0); + igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert(get_freq(fd, gt_id, "cur") == rpe); + igt_assert(get_freq(fd, gt_id, "cur") == rpe(fd, gt_id)); if (gt_idle) { igt_assert_f(igt_wait(xe_is_gt_in_c6(fd, gt_id), 1000, 10), "GT %d should be in C6\n", gt_id); igt_assert(get_freq(fd, gt_id, "act") == 0); } else { - igt_assert(get_freq(fd, gt_id, "act") == rpe); + igt_assert(get_freq(fd, gt_id, "act") == rpe(fd, gt_id)); } igt_assert(set_freq(fd, gt_id, "min", rp0) > 0); @@ -232,16 +232,15 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) static void test_freq_range(int fd, int gt_id, bool gt_idle) { uint32_t rpn = get_freq(fd, gt_id, "rpn"); - uint32_t rpe = get_freq(fd, gt_id, "rpe"); uint32_t cur, act; igt_debug("Starting testing range request\n"); igt_assert(set_freq(fd, gt_id, "min", rpn) > 0); - igt_assert(set_freq(fd, gt_id, "max", rpe) > 0); + igt_assert(set_freq(fd, gt_id, "max", rpe(fd, gt_id)) > 0); usleep(ACT_FREQ_LATENCY_US); cur = get_freq(fd, gt_id, "cur"); - igt_assert(rpn <= cur && cur <= rpe); + igt_assert(rpn <= cur && cur <= rpe(fd, gt_id)); if (gt_idle) {
[PATCH i-g-t] tests/intel/xe_gt_freq: Check for RPe freq updates
Pcode can dynamically update RPe frequency. Use the latest value in tests that check it. Signed-off-by: Vinay Belgaumkar --- tests/intel/xe_gt_freq.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/tests/intel/xe_gt_freq.c b/tests/intel/xe_gt_freq.c index c12f6c52c..5c6373016 100644 --- a/tests/intel/xe_gt_freq.c +++ b/tests/intel/xe_gt_freq.c @@ -186,6 +186,9 @@ static void test_freq_fixed(int fd, int gt_id, bool gt_idle) igt_assert(get_freq(fd, gt_id, "act") == rpn); } + /* Refresh value of rpe, pcode could have adjusted it */ + rpe = get_freq(fd, gt_id, "rpe"); + igt_assert(set_freq(fd, gt_id, "min", rpe) > 0); igt_assert(set_freq(fd, gt_id, "max", rpe) > 0); usleep(ACT_FREQ_LATENCY_US); @@ -268,6 +271,10 @@ static void test_freq_low_max(int fd, int gt_id) igt_assert(set_freq(fd, gt_id, "min", rpe) > 0); igt_assert(set_freq(fd, gt_id, "max", rpn) > 0); usleep(ACT_FREQ_LATENCY_US); + + /* Refresh value of rpe, pcode could have adjusted it */ + rpe = get_freq(fd, gt_id, "rpe"); + igt_assert(get_freq(fd, gt_id, "cur") == rpe); if (!xe_is_gt_in_c6(fd, gt_id)) -- 2.38.1
[PATCH v4] drm/i915/guc: Use context hints for GT frequency
Allow user to provide a low latency context hint. When set, KMD sends a hint to GuC which results in special handling for this context. SLPC will ramp the GT frequency aggressively every time it switches to this context. The down freq threshold will also be lower so GuC will ramp down the GT freq for this context more slowly. We also disable waitboost for this context as that will interfere with the strategy. We need to enable the use of SLPC Compute strategy during init, but it will apply only to contexts that set this bit during context creation. Userland can check whether this feature is supported using a new param- I915_PARAM_HAS_CONTEXT_FREQ_HINT. This flag is true for all guc submission enabled platforms as they use SLPC for frequency management. The Mesa usage model for this flag is here - https://gitlab.freedesktop.org/sushmave/mesa/-/commits/compute_hint v2: Rename flags as per review suggestions (Rodrigo, Tvrtko). Also, use flag bits in intel_context as it allows finer control for toggling per engine if needed (Tvrtko). v3: Minor review comments (Tvrtko) v4: Update comment (Sushma) Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: Sushma Venkatesh Reddy Reviewed-by: Rodrigo Vivi Acked-by: Ivan Briano Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 16 -- .../gpu/drm/i915/gem/i915_gem_context_types.h | 1 + drivers/gpu/drm/i915/gt/intel_context_types.h | 1 + drivers/gpu/drm/i915/gt/intel_rps.c | 4 .../drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 21 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 17 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 ++ drivers/gpu/drm/i915/i915_getparam.c | 6 ++ include/uapi/drm/i915_drm.h | 15 + 10 files changed, 86 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index dcbfe32fd30c..81f65cab1330 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -879,6 +879,7 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, struct i915_gem_proto_context *pc, struct drm_i915_gem_context_param *args) { + struct drm_i915_private *i915 = fpriv->i915; int ret = 0; switch (args->param) { @@ -904,6 +905,13 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, pc->user_flags &= ~BIT(UCONTEXT_BANNABLE); break; + case I915_CONTEXT_PARAM_LOW_LATENCY: + if (intel_uc_uses_guc_submission(&to_gt(i915)->uc)) + pc->user_flags |= BIT(UCONTEXT_LOW_LATENCY); + else + ret = -EINVAL; + break; + case I915_CONTEXT_PARAM_RECOVERABLE: if (args->size) ret = -EINVAL; @@ -992,6 +1000,9 @@ static int intel_context_set_gem(struct intel_context *ce, if (sseu.slice_mask && !WARN_ON(ce->engine->class != RENDER_CLASS)) ret = intel_context_reconfigure_sseu(ce, sseu); + if (test_bit(UCONTEXT_LOW_LATENCY, &ctx->user_flags)) + __set_bit(CONTEXT_LOW_LATENCY, &ce->flags); + return ret; } @@ -1630,6 +1641,9 @@ i915_gem_create_context(struct drm_i915_private *i915, if (vm) ctx->vm = vm; + /* Assign early so intel_context_set_gem can access these flags */ + ctx->user_flags = pc->user_flags; + mutex_init(&ctx->engines_mutex); if (pc->num_user_engines >= 0) { i915_gem_context_set_user_engines(ctx); @@ -1652,8 +1666,6 @@ i915_gem_create_context(struct drm_i915_private *i915, * is no remap info, it will be a NOP. */ ctx->remap_slice = ALL_L3_SLICES(i915); - ctx->user_flags = pc->user_flags; - for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++) ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index 03bc7f9d191b..b6d97da63d1f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -338,6 +338,7 @@ struct i915_gem_context { #define UCONTEXT_BANNABLE 2 #define UCONTEXT_RECOVERABLE 3 #define UCONTEXT_PERSISTENCE 4 +#define UCONTEXT_LOW_LATENCY 5 /** * @flags: small set of booleans diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 7eccbd70d89f..ed95a7b57cbb 100644 --- a/drivers/gpu/d
[PATCH v3] drm/i915/guc: Use context hints for GT frequency
Allow user to provide a low latency context hint. When set, KMD sends a hint to GuC which results in special handling for this context. SLPC will ramp the GT frequency aggressively every time it switches to this context. The down freq threshold will also be lower so GuC will ramp down the GT freq for this context more slowly. We also disable waitboost for this context as that will interfere with the strategy. We need to enable the use of SLPC Compute strategy during init, but it will apply only to contexts that set this bit during context creation. Userland can check whether this feature is supported using a new param- I915_PARAM_HAS_CONTEXT_FREQ_HINTS. This flag is true for all guc submission enabled platforms as they use SLPC for frequency management. The Mesa usage model for this flag is here - https://gitlab.freedesktop.org/sushmave/mesa/-/commits/compute_hint v2: Rename flags as per review suggestions (Rodrigo, Tvrtko). Also, use flag bits in intel_context as it allows finer control for toggling per engine if needed (Tvrtko). v3: Minor review comments (Tvrtko) Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: Sushma Venkatesh Reddy Acked-by: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 16 -- .../gpu/drm/i915/gem/i915_gem_context_types.h | 1 + drivers/gpu/drm/i915/gt/intel_context_types.h | 1 + drivers/gpu/drm/i915/gt/intel_rps.c | 4 .../drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 21 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 17 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 ++ drivers/gpu/drm/i915/i915_getparam.c | 6 ++ include/uapi/drm/i915_drm.h | 15 + 10 files changed, 86 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index dcbfe32fd30c..81f65cab1330 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -879,6 +879,7 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, struct i915_gem_proto_context *pc, struct drm_i915_gem_context_param *args) { + struct drm_i915_private *i915 = fpriv->i915; int ret = 0; switch (args->param) { @@ -904,6 +905,13 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, pc->user_flags &= ~BIT(UCONTEXT_BANNABLE); break; + case I915_CONTEXT_PARAM_LOW_LATENCY: + if (intel_uc_uses_guc_submission(&to_gt(i915)->uc)) + pc->user_flags |= BIT(UCONTEXT_LOW_LATENCY); + else + ret = -EINVAL; + break; + case I915_CONTEXT_PARAM_RECOVERABLE: if (args->size) ret = -EINVAL; @@ -992,6 +1000,9 @@ static int intel_context_set_gem(struct intel_context *ce, if (sseu.slice_mask && !WARN_ON(ce->engine->class != RENDER_CLASS)) ret = intel_context_reconfigure_sseu(ce, sseu); + if (test_bit(UCONTEXT_LOW_LATENCY, &ctx->user_flags)) + __set_bit(CONTEXT_LOW_LATENCY, &ce->flags); + return ret; } @@ -1630,6 +1641,9 @@ i915_gem_create_context(struct drm_i915_private *i915, if (vm) ctx->vm = vm; + /* Assign early so intel_context_set_gem can access these flags */ + ctx->user_flags = pc->user_flags; + mutex_init(&ctx->engines_mutex); if (pc->num_user_engines >= 0) { i915_gem_context_set_user_engines(ctx); @@ -1652,8 +1666,6 @@ i915_gem_create_context(struct drm_i915_private *i915, * is no remap info, it will be a NOP. */ ctx->remap_slice = ALL_L3_SLICES(i915); - ctx->user_flags = pc->user_flags; - for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++) ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index 03bc7f9d191b..b6d97da63d1f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -338,6 +338,7 @@ struct i915_gem_context { #define UCONTEXT_BANNABLE 2 #define UCONTEXT_RECOVERABLE 3 #define UCONTEXT_PERSISTENCE 4 +#define UCONTEXT_LOW_LATENCY 5 /** * @flags: small set of booleans diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 7eccbd70d89f..ed95a7b57cbb 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/
[PATCH v2] drm/i915/guc: Use context hints for GT freq
Allow user to provide a low latency context hint. When set, KMD sends a hint to GuC which results in special handling for this context. SLPC will ramp the GT frequency aggressively every time it switches to this context. The down freq threshold will also be lower so GuC will ramp down the GT freq for this context more slowly. We also disable waitboost for this context as that will interfere with the strategy. We need to enable the use of SLPC Compute strategy during init, but it will apply only to contexts that set this bit during context creation. Userland can check whether this feature is supported using a new param- I915_PARAM_HAS_CONTEXT_FREQ_HINTS. This flag is true for all guc submission enabled platforms as they use SLPC for frequency management. The Mesa usage model for this flag is here - https://gitlab.freedesktop.org/sushmave/mesa/-/commits/compute_hint v2: Rename flags as per review suggestions (Rodrigo, Tvrtko). Also, use flag bits in intel_context as it allows finer control for toggling per engine if needed (Tvrtko). Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: Sushma Venkatesh Reddy Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 15 +++-- .../gpu/drm/i915/gem/i915_gem_context_types.h | 1 + drivers/gpu/drm/i915/gt/intel_context_types.h | 1 + drivers/gpu/drm/i915/gt/intel_rps.c | 5 + .../drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 21 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 17 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 ++ drivers/gpu/drm/i915/i915_getparam.c | 12 +++ include/uapi/drm/i915_drm.h | 15 + 10 files changed, 92 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index dcbfe32fd30c..0799cb0b2803 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -879,6 +879,7 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, struct i915_gem_proto_context *pc, struct drm_i915_gem_context_param *args) { + struct drm_i915_private *i915 = fpriv->i915; int ret = 0; switch (args->param) { @@ -904,6 +905,13 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, pc->user_flags &= ~BIT(UCONTEXT_BANNABLE); break; + case I915_CONTEXT_PARAM_LOW_LATENCY: + if (intel_uc_uses_guc_submission(&to_gt(i915)->uc)) + pc->user_flags |= BIT(UCONTEXT_LOW_LATENCY); + else + ret = -EINVAL; + break; + case I915_CONTEXT_PARAM_RECOVERABLE: if (args->size) ret = -EINVAL; @@ -992,6 +1000,9 @@ static int intel_context_set_gem(struct intel_context *ce, if (sseu.slice_mask && !WARN_ON(ce->engine->class != RENDER_CLASS)) ret = intel_context_reconfigure_sseu(ce, sseu); + if (test_bit(UCONTEXT_LOW_LATENCY, &ctx->user_flags)) + set_bit(CONTEXT_LOW_LATENCY, &ce->flags); + return ret; } @@ -1630,6 +1641,8 @@ i915_gem_create_context(struct drm_i915_private *i915, if (vm) ctx->vm = vm; + ctx->user_flags = pc->user_flags; + mutex_init(&ctx->engines_mutex); if (pc->num_user_engines >= 0) { i915_gem_context_set_user_engines(ctx); @@ -1652,8 +1665,6 @@ i915_gem_create_context(struct drm_i915_private *i915, * is no remap info, it will be a NOP. */ ctx->remap_slice = ALL_L3_SLICES(i915); - ctx->user_flags = pc->user_flags; - for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++) ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index 03bc7f9d191b..b6d97da63d1f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -338,6 +338,7 @@ struct i915_gem_context { #define UCONTEXT_BANNABLE 2 #define UCONTEXT_RECOVERABLE 3 #define UCONTEXT_PERSISTENCE 4 +#define UCONTEXT_LOW_LATENCY 5 /** * @flags: small set of booleans diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 7eccbd70d89f..ed95a7b57cbb 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -130,6 +130,7 @@ struct intel_context { #define CONTEXT_PERMA_PIN 11 #define
[PATCH] drm/i915/guc: Add Compute context hint
Allow user to provide a context hint. When this is set, KMD will send a hint to GuC which results in special handling for this context. SLPC will ramp the GT frequency aggressively every time it switches to this context. The down freq threshold will also be lower so GuC will ramp down the GT freq for this context more slowly. We also disable waitboost for this context as that will interfere with the strategy. We need to enable the use of Compute strategy during SLPC init, but it will apply only to contexts that set this bit during context creation. Userland can check whether this feature is supported using a new param- I915_PARAM_HAS_COMPUTE_CONTEXT. This flag is true for all guc submission enabled platforms since they use SLPC for freq management. The Mesa usage model for this flag is here - https://gitlab.freedesktop.org/sushmave/mesa/-/commits/compute_hint Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 8 +++ .../gpu/drm/i915/gem/i915_gem_context_types.h | 1 + drivers/gpu/drm/i915/gt/intel_rps.c | 8 +++ .../drm/i915/gt/uc/abi/guc_actions_slpc_abi.h | 21 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 17 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 7 +++ drivers/gpu/drm/i915/i915_getparam.c | 11 ++ include/uapi/drm/i915_drm.h | 15 + 9 files changed, 89 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index dcbfe32fd30c..ceab7dbe9b47 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -879,6 +879,7 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, struct i915_gem_proto_context *pc, struct drm_i915_gem_context_param *args) { + struct drm_i915_private *i915 = fpriv->i915; int ret = 0; switch (args->param) { @@ -904,6 +905,13 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, pc->user_flags &= ~BIT(UCONTEXT_BANNABLE); break; + case I915_CONTEXT_PARAM_IS_COMPUTE: + if (!intel_uc_uses_guc_submission(&to_gt(i915)->uc)) + ret = -EINVAL; + else + pc->user_flags |= BIT(UCONTEXT_COMPUTE); + break; + case I915_CONTEXT_PARAM_RECOVERABLE: if (args->size) ret = -EINVAL; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index 03bc7f9d191b..db86d6f6245f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -338,6 +338,7 @@ struct i915_gem_context { #define UCONTEXT_BANNABLE 2 #define UCONTEXT_RECOVERABLE 3 #define UCONTEXT_PERSISTENCE 4 +#define UCONTEXT_COMPUTE 5 /** * @flags: small set of booleans diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 4feef874e6d6..1ed40cd61b70 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -24,6 +24,7 @@ #include "intel_pcode.h" #include "intel_rps.h" #include "vlv_sideband.h" +#include "../gem/i915_gem_context.h" #include "../../../platform/x86/intel_ips.h" #define BUSY_MAX_EI20u /* ms */ @@ -1018,6 +1019,13 @@ void intel_rps_boost(struct i915_request *rq) struct intel_rps *rps = &READ_ONCE(rq->engine)->gt->rps; if (rps_uses_slpc(rps)) { + const struct i915_gem_context *ctx; + + ctx = i915_request_gem_context(rq); + if (ctx && + test_bit(UCONTEXT_COMPUTE, &ctx->user_flags)) + return; + slpc = rps_to_slpc(rps); if (slpc->min_freq_softlimit >= slpc->boost_freq) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h index 811add10c30d..c34674e797c6 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h @@ -207,6 +207,27 @@ struct slpc_shared_data { u8 reserved_mode_definition[4096]; } __packed; +struct slpc_context_frequency_request { + u32 frequency_request:16; + u32 reserved:12; + u32 is_compute:1; + u32 ignore_busyness:1; + u32 is_minimum:1; + u32 is_predefined:1; +} __packed; + +#define SLPC_CTX_FREQ_REQ_IS_COMPUTE REG
[PATCH v2] drm/i915/mtl: Wake GT before sending H2G message
Instead of waiting until the interrupt reaches GuC, we can grab a forcewake while triggering the H2G interrupt. GEN11_GUC_HOST_INTERRUPT is inside sgunit and is not affected by forcewakes. However, there could be some delays when platform is entering/exiting some higher level platform sleep states and a H2G is triggered. A forcewake ensures those sleep states have been fully exited and further processing occurs as expected. The hysteresis timers for C6 and higher sleep states will ensure there is no unwanted race between the wake and processing of the interrupts by GuC. This will have an official WA soon so adding a FIXME in the comments. v2: Make the new ranges watertight to address BAT failures and update commit message (Matt R). Reviewed-by: Matt Roper Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/intel_uncore.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index dfefad5a5fec..76400e9c40f0 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1800,7 +1800,10 @@ static const struct intel_forcewake_range __mtl_fw_ranges[] = { GEN_FW_RANGE(0x24000, 0x2, 0), /* 0x24000 - 0x2407f: always on 0x24080 - 0x2: reserved */ - GEN_FW_RANGE(0x3, 0x3, FORCEWAKE_GT) + GEN_FW_RANGE(0x3, 0x3, FORCEWAKE_GT), + GEN_FW_RANGE(0x4, 0x1901ef, 0), + GEN_FW_RANGE(0x1901f0, 0x1901f3, FORCEWAKE_GT) + /* FIXME: WA to wake GT while triggering H2G */ }; /* -- 2.38.1
[PATCH] drm/i915/mtl: Wake GT before sending H2G message
Instead of waiting until the interrupt reaches GuC, we can grab a forcewake while triggering the H2G interrupt. GEN11_GUC_HOST_INTERRUPT is inside an "always on" domain with respect to RC6. However, there could be some delays when platform is entering/exiting some higher level platform sleep states and a H2G is triggered. A forcewake ensures those sleep states have been fully exited and further processing occurs as expected. This will have an official WA soon so adding a FIXME in the comments. Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/intel_uncore.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index dfefad5a5fec..121458a31886 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1800,7 +1800,10 @@ static const struct intel_forcewake_range __mtl_fw_ranges[] = { GEN_FW_RANGE(0x24000, 0x2, 0), /* 0x24000 - 0x2407f: always on 0x24080 - 0x2: reserved */ - GEN_FW_RANGE(0x3, 0x3, FORCEWAKE_GT) + GEN_FW_RANGE(0x3, 0x3, FORCEWAKE_GT), + GEN_FW_RANGE(0x4, 0x1901ec, 0), + GEN_FW_RANGE(0x1901f0, 0x1901f0, FORCEWAKE_GT) + /* FIXME: WA to wake GT while triggering H2G */ }; /* -- 2.38.1
[PATCH i-g-t] tests/perf_pmu: Set defaults before frequency test
Seeing random issues where this test skips due to invalid boost freq at the start. Also ensure that we restore the frequencies at the end. v2: Use save/restore functions instead of exit_handler. Adding an exit_handler necessitated moving drm_close() into the handler. However, the module-reload subtest at the end expects drm-fd to be closed. Also setup expected frequencies (Kamil) and address other nits (Kamil) Link: https://gitlab.freedesktop.org/drm/intel/-/issues/9432 Cc: Kamil Konieczny Signed-off-by: Vinay Belgaumkar --- tests/intel/perf_pmu.c | 62 +- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/tests/intel/perf_pmu.c b/tests/intel/perf_pmu.c index c6e6a8b77..4ae2b60ae 100644 --- a/tests/intel/perf_pmu.c +++ b/tests/intel/perf_pmu.c @@ -2454,12 +2454,69 @@ static void pmu_read(int i915) for_each_if((e)->class == I915_ENGINE_CLASS_RENDER) \ igt_dynamic_f("%s", e->name) +int fd = -1; +uint32_t *stash_min, *stash_max, *stash_boost; + +static void save_sysfs_freq(int i915) +{ + int gt, num_gts, sysfs, tmp; + uint32_t rpn_freq, rp0_freq; + + num_gts = igt_sysfs_get_num_gt(i915); + + stash_min = (uint32_t *)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t *)malloc(sizeof(uint32_t) * num_gts); + stash_boost = (uint32_t *)malloc(sizeof(uint32_t) * num_gts); + + /* Save boost, min and max across GTs */ + i915_for_each_gt(i915, tmp, gt) { + sysfs = igt_sysfs_gt_open(i915, gt); + igt_require(sysfs >= 0); + + stash_min[gt] = igt_sysfs_get_u32(sysfs, "rps_min_freq_mhz"); + stash_max[gt] = igt_sysfs_get_u32(sysfs, "rps_max_freq_mhz"); + stash_boost[gt] = igt_sysfs_get_u32(sysfs, "rps_boost_freq_mhz"); + igt_debug("GT: %d, min: %d, max: %d, boost:%d\n", + gt, stash_min[gt], stash_max[gt], stash_boost[gt]); + + rpn_freq = igt_sysfs_get_u32(sysfs, "rps_RPn_freq_mhz"); + rp0_freq = igt_sysfs_get_u32(sysfs, "rps_RP0_freq_mhz"); + + /* Set pre-conditions, in case frequencies are in non-default state */ + igt_require(__igt_sysfs_set_u32(sysfs, "rps_max_freq_mhz", rp0_freq)); + igt_require(__igt_sysfs_set_u32(sysfs, "rps_boost_freq_mhz", rp0_freq)); + igt_require(__igt_sysfs_set_u32(sysfs, "rps_min_freq_mhz", rpn_freq)); + + close(sysfs); + } +} + +static void restore_sysfs_freq(int i915) +{ + int sysfs, gt, tmp; + + /* Restore frequencies */ + i915_for_each_gt(fd, tmp, gt) { + sysfs = igt_sysfs_gt_open(fd, gt); + igt_require(sysfs >= 0); + + igt_require(__igt_sysfs_set_u32(sysfs, "rps_max_freq_mhz", stash_max[gt])); + igt_require(__igt_sysfs_set_u32(sysfs, "rps_min_freq_mhz", stash_min[gt])); + igt_require(__igt_sysfs_set_u32(sysfs, "rps_boost_freq_mhz", stash_boost[gt])); + + close(sysfs); + } + free(stash_min); + free(stash_max); + free(stash_boost); +} + igt_main { const struct intel_execution_engine2 *e; unsigned int num_engines = 0; const intel_ctx_t *ctx = NULL; - int gt, tmp, fd = -1; + int gt, tmp; int num_gt = 0; /** @@ -2664,12 +2721,15 @@ igt_main * Test GPU frequency. */ igt_subtest_with_dynamic("frequency") { + save_sysfs_freq(fd); + i915_for_each_gt(fd, tmp, gt) { igt_dynamic_f("gt%u", gt) test_frequency(fd, gt); igt_dynamic_f("idle-gt%u", gt) test_frequency_idle(fd, gt); } + restore_sysfs_freq(fd); } /** -- 2.38.1
[PATCH i-g-t] tests/perf_pmu: Restore sysfs freq in exit handler
Seeing random issues where this test starts with invalid values. Ensure that we restore the frequencies in case test exits early due to some system issues. Link: https://gitlab.freedesktop.org/drm/intel/-/issues/9432 Signed-off-by: Vinay Belgaumkar --- tests/intel/perf_pmu.c | 53 +- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/tests/intel/perf_pmu.c b/tests/intel/perf_pmu.c index c6e6a8b77..ceacc1d3d 100644 --- a/tests/intel/perf_pmu.c +++ b/tests/intel/perf_pmu.c @@ -2454,12 +2454,59 @@ static void pmu_read(int i915) for_each_if((e)->class == I915_ENGINE_CLASS_RENDER) \ igt_dynamic_f("%s", e->name) +int fd = -1; +uint32_t *stash_min, *stash_max, *stash_boost; + +static void save_sysfs_freq(int i915) +{ + int gt, num_gts, sysfs, tmp; + + num_gts = igt_sysfs_get_num_gt(i915); + + stash_min = (uint32_t *)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t *)malloc(sizeof(uint32_t) * num_gts); + stash_boost = (uint32_t *)malloc(sizeof(uint32_t) * num_gts); + + /* Save boost, min and max across GTs */ + i915_for_each_gt(i915, tmp, gt) { + sysfs = igt_sysfs_gt_open(i915, gt); + igt_require(sysfs >= 0); + + stash_min[gt] = igt_sysfs_get_u32(sysfs, "rps_min_freq_mhz"); + stash_max[gt] = igt_sysfs_get_u32(sysfs, "rps_max_freq_mhz"); + stash_boost[gt] = igt_sysfs_get_u32(sysfs, "rps_boost_freq_mhz"); + igt_debug("GT: %d, min: %d, max: %d, boost:%d\n", + gt, stash_min[gt], stash_max[gt], stash_boost[gt]); + + close(sysfs); + } +} + +static void restore_sysfs_freq(int sig) +{ + int sysfs, gt, tmp; + + /* Restore frequencies */ + i915_for_each_gt(fd, tmp, gt) { + sysfs = igt_sysfs_gt_open(fd, gt); + igt_require(sysfs >= 0); + + igt_require(__igt_sysfs_set_u32(sysfs, "rps_max_freq_mhz", stash_max[gt])); + igt_require(__igt_sysfs_set_u32(sysfs, "rps_min_freq_mhz", stash_min[gt])); + igt_require(__igt_sysfs_set_u32(sysfs, "rps_boost_freq_mhz", stash_boost[gt])); + + close(sysfs); + } + free(stash_min); + free(stash_max); +} + igt_main { const struct intel_execution_engine2 *e; unsigned int num_engines = 0; const intel_ctx_t *ctx = NULL; - int gt, tmp, fd = -1; + int gt, tmp; int num_gt = 0; /** @@ -2482,6 +2529,7 @@ igt_main i915_for_each_gt(fd, tmp, gt) num_gt++; + } igt_describe("Verify i915 pmu dir exists and read all events"); @@ -2664,6 +2712,9 @@ igt_main * Test GPU frequency. */ igt_subtest_with_dynamic("frequency") { + save_sysfs_freq(fd); + igt_install_exit_handler(restore_sysfs_freq); + i915_for_each_gt(fd, tmp, gt) { igt_dynamic_f("gt%u", gt) test_frequency(fd, gt); -- 2.38.1
[Intel-gfx] [PATCH] drm/i915: Read a shadowed mmio register for ggtt flush
We read RENDER_HEAD as a part of the flush. If GT is in deeper sleep states, this could lead to read errors since we are not using a forcewake. Safer to read a shadowed register instead. Cc: John Harrison Cc: Daniele Ceraolo Spurio Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_gt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index ed32bf5b1546..ea814ea5f700 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -451,7 +451,7 @@ void intel_gt_flush_ggtt_writes(struct intel_gt *gt) spin_lock_irqsave(&uncore->lock, flags); intel_uncore_posting_read_fw(uncore, -RING_HEAD(RENDER_RING_BASE)); +RING_TAIL(RENDER_RING_BASE)); spin_unlock_irqrestore(&uncore->lock, flags); } } -- 2.38.1
[Intel-gfx] [PATCH] drm/i915: Initialize residency registers earlier
If we skip RC6 init, residency registers do not get initialized, leading to incorrect drpc debug output. Also release the wakeref since we skip intel_rc6_enable() entirely when rc6_supported is false. Fixes: 78d0b4552c37 ("drm/i915/gt: Use RC6 residency types as arguments to residency functions") Suggested-by: Alan Previn Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_rc6.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 7090e4be29cb..58dc0dab9b64 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -608,11 +608,13 @@ void intel_rc6_init(struct intel_rc6 *rc6) /* Disable runtime-pm until we can save the GPU state with rc6 pctx */ rpm_get(rc6); - if (!rc6_supported(rc6)) - return; - rc6_res_reg_init(rc6); + if (!rc6_supported(rc6)) { + rpm_put(rc6); + return; + } + if (IS_CHERRYVIEW(i915)) err = chv_rc6_init(rc6); else if (IS_VALLEYVIEW(i915)) -- 2.38.1
[Intel-gfx] [PATCH v2] drm/i915/mtl: Don't set PIPE_CONTROL_FLUSH_L3
This bit does not cause an explicit L3 flush. We already use PIPE_CONTROL_DC_FLUSH_ENABLE for that purpose. v2: Use FLUSH_L3 only pre-MTL since spec will likely remain the same going forward. Cc: Nirmoy Das Cc: Mika Kuoppala Acked-by: Mika Kuoppala Reviewed-by: Nirmoy Das Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index ba4c2422b340..86a04afff64b 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -278,7 +278,8 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) * deals with Protected Memory which is not needed for * AUX CCS invalidation and lead to unwanted side effects. */ - if (mode & EMIT_FLUSH) + if ((mode & EMIT_FLUSH) && + GRAPHICS_VER_FULL(rq->i915) < IP_VER(12, 70)) bit_group_1 |= PIPE_CONTROL_FLUSH_L3; bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH; @@ -812,12 +813,14 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs) u32 flags = (PIPE_CONTROL_CS_STALL | PIPE_CONTROL_TLB_INVALIDATE | PIPE_CONTROL_TILE_CACHE_FLUSH | -PIPE_CONTROL_FLUSH_L3 | PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH | PIPE_CONTROL_DEPTH_CACHE_FLUSH | PIPE_CONTROL_DC_FLUSH_ENABLE | PIPE_CONTROL_FLUSH_ENABLE); + if (GRAPHICS_VER_FULL(rq->i915) < IP_VER(12, 70)) + flags |= PIPE_CONTROL_FLUSH_L3; + /* Wa_14016712196 */ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || IS_DG2(i915)) /* dummy PIPE_CONTROL + depth flush */ -- 2.38.1
[Intel-gfx] [PATCH] drm/i915/mtl: Don't set PIPE_CONTROL_FLUSH_L3
This bit does not cause an explicit L3 flush. We already use PIPE_CONTROL_DC_FLUSH_ENABLE for that purpose. Cc: Nirmoy Das Cc: Mikka Kuoppala Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index ba4c2422b340..abbc02f3e66e 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -247,6 +247,7 @@ static int mtl_dummy_pipe_control(struct i915_request *rq) int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) { struct intel_engine_cs *engine = rq->engine; + struct intel_gt *gt = rq->engine->gt; /* * On Aux CCS platforms the invalidation of the Aux @@ -278,7 +279,8 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) * deals with Protected Memory which is not needed for * AUX CCS invalidation and lead to unwanted side effects. */ - if (mode & EMIT_FLUSH) + if ((mode & EMIT_FLUSH) && + !(IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71 bit_group_1 |= PIPE_CONTROL_FLUSH_L3; bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH; @@ -812,12 +814,14 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs) u32 flags = (PIPE_CONTROL_CS_STALL | PIPE_CONTROL_TLB_INVALIDATE | PIPE_CONTROL_TILE_CACHE_FLUSH | -PIPE_CONTROL_FLUSH_L3 | PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH | PIPE_CONTROL_DEPTH_CACHE_FLUSH | PIPE_CONTROL_DC_FLUSH_ENABLE | PIPE_CONTROL_FLUSH_ENABLE); + if (!(IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71 + flags |= PIPE_CONTROL_FLUSH_L3; + /* Wa_14016712196 */ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || IS_DG2(i915)) /* dummy PIPE_CONTROL + depth flush */ -- 2.38.1
[Intel-gfx] [PATCH] drm/i915/gem: Allow users to disable waitboost
Provide a bit to disable waitboost while waiting on a gem object. Waitboost results in increased power consumption by requesting RP0 while waiting for the request to complete. Add a bit in the gem_wait() IOCTL where this can be disabled. This is related to the libva API change here - Link: https://github.com/XinfengZhang/libva/commit/3d90d18c67609a73121bb71b20ee4776b54b61a7 Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gem/i915_gem_wait.c | 9 ++--- drivers/gpu/drm/i915/i915_request.c | 3 ++- drivers/gpu/drm/i915/i915_request.h | 1 + include/uapi/drm/i915_drm.h | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index d4b918fb11ce..955885ec859d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -72,7 +72,8 @@ i915_gem_object_wait_reservation(struct dma_resv *resv, struct dma_fence *fence; long ret = timeout ?: 1; - i915_gem_object_boost(resv, flags); + if (!(flags & I915_WAITBOOST_DISABLE)) + i915_gem_object_boost(resv, flags); dma_resv_iter_begin(&cursor, resv, dma_resv_usage_rw(flags & I915_WAIT_ALL)); @@ -236,7 +237,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) ktime_t start; long ret; - if (args->flags != 0) + if (args->flags != 0 || args->flags != I915_GEM_WAITBOOST_DISABLE) return -EINVAL; obj = i915_gem_object_lookup(file, args->bo_handle); @@ -248,7 +249,9 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) ret = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE | I915_WAIT_PRIORITY | - I915_WAIT_ALL, + I915_WAIT_ALL | + (args->flags & I915_GEM_WAITBOOST_DISABLE ? + I915_WAITBOOST_DISABLE : 0), to_wait_timeout(args->timeout_ns)); if (args->timeout_ns > 0) { diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index f59081066a19..2957409b4b2a 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -2044,7 +2044,8 @@ long i915_request_wait_timeout(struct i915_request *rq, * but at a cost of spending more power processing the workload * (bad for battery). */ - if (flags & I915_WAIT_PRIORITY && !i915_request_started(rq)) + if (!(flags & I915_WAITBOOST_DISABLE) && (flags & I915_WAIT_PRIORITY) && + !i915_request_started(rq)) intel_rps_boost(rq); wait.tsk = current; diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index 0ac55b2e4223..3cc00e8254dc 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -445,6 +445,7 @@ long i915_request_wait(struct i915_request *rq, #define I915_WAIT_INTERRUPTIBLEBIT(0) #define I915_WAIT_PRIORITY BIT(1) /* small priority bump for the request */ #define I915_WAIT_ALL BIT(2) /* used by i915_gem_object_wait() */ +#define I915_WAITBOOST_DISABLE BIT(3) /* used by i915_gem_object_wait() */ void i915_request_show(struct drm_printer *m, const struct i915_request *rq, diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 7000e5910a1d..4adee70e39cf 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1928,6 +1928,7 @@ struct drm_i915_gem_wait { /** Handle of BO we shall wait on */ __u32 bo_handle; __u32 flags; +#define I915_GEM_WAITBOOST_DISABLE (1u<<0) /** Number of nanoseconds to wait, Returns time remaining. */ __s64 timeout_ns; }; -- 2.38.1
[Intel-gfx] [PATCH i-g-t] tests/i915_pm_freq_api: Set min/max to expected values
A prior(rps) test leaves the system in a bad state causing failures in the basic test. Set min/max to expected values before running it. Test will restore values at the end. Link: https://gitlab.freedesktop.org/drm/intel/-/issues/8670 Signed-off-by: Vinay Belgaumkar --- tests/intel/i915_pm_freq_api.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/intel/i915_pm_freq_api.c b/tests/intel/i915_pm_freq_api.c index 03bd0d05b..6018692a2 100644 --- a/tests/intel/i915_pm_freq_api.c +++ b/tests/intel/i915_pm_freq_api.c @@ -55,7 +55,11 @@ static void test_freq_basic_api(int dirfd, int gt) rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); - igt_debug("GT: %d, RPn: %d, RPe: %d, RP0: %d", gt, rpn, rpe, rp0); + igt_debug("GT: %d, RPn: %d, RPe: %d, RP0: %d\n", gt, rpn, rpe, rp0); + + /* Set min/max to RPn, RP0 for baseline behavior */ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0) > 0); /* * Negative bound tests @@ -170,7 +174,7 @@ igt_main for_each_sysfs_gt_dirfd(i915, dirfd, gt) { stash_min[gt] = get_freq(dirfd, RPS_MIN_FREQ_MHZ); stash_max[gt] = get_freq(dirfd, RPS_MAX_FREQ_MHZ); - igt_debug("GT: %d, min: %d, max: %d", gt, stash_min[gt], stash_max[gt]); + igt_debug("GT: %d, min: %d, max: %d\n", gt, stash_min[gt], stash_max[gt]); igt_pm_ignore_slpc_efficient_freq(i915, dirfd, true); } igt_install_exit_handler(restore_sysfs_freq); -- 2.38.1
[Intel-gfx] [PATCH i-g-t] tests/i915_pm_freq_api: Test s2idle instead of S3
Test skips whenever S3 is not supported, use s2idle instead, which is widely enabled. Cc: Anshuman Gupta Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index 2912287c4..03bd0d05b 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -125,7 +125,7 @@ static void test_suspend(int i915, int dirfd, int gt) igt_assert_eq(req_freq, rpn); /* Manually trigger a suspend */ - igt_system_suspend_autoresume(SUSPEND_STATE_S3, + igt_system_suspend_autoresume(SUSPEND_STATE_FREEZE, SUSPEND_TEST_NONE); req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); -- 2.38.1
[Intel-gfx] [PATCH v4 i-g-t] tests/i915_pm_freq_api: Ignore zero register value
Register read for requested_freq can return 0 when system is in runtime_pm. Make allowance for this case. v2: Explicit check for runtime_pm status (Riana) v3: Revert back to v1, the runtime util functions do not work as expected. v4: Add a debug print for min/max freq before test begins Link: https://gitlab.freedesktop.org/drm/intel/issues/8736 Link: https://gitlab.freedesktop.org/drm/intel/issues/8989 Reviewed-by: Riana Tauro Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 19 +++ 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index cf21cc936..2912287c4 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -88,6 +88,7 @@ static void test_freq_basic_api(int dirfd, int gt) static void test_reset(int i915, int dirfd, int gt, int count) { uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + uint32_t req_freq; int fd; for (int i = 0; i < count; i++) { @@ -95,14 +96,18 @@ static void test_reset(int i915, int dirfd, int gt, int count) igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); /* Manually trigger a GT reset */ fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); igt_require(fd >= 0); igt_ignore_warn(write(fd, "1\n", 2)); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); } close(fd); } @@ -110,17 +115,22 @@ static void test_reset(int i915, int dirfd, int gt, int count) static void test_suspend(int i915, int dirfd, int gt) { uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + uint32_t req_freq; igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); /* Manually trigger a suspend */ igt_system_suspend_autoresume(SUSPEND_STATE_S3, SUSPEND_TEST_NONE); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); } int i915 = -1; @@ -160,6 +170,7 @@ igt_main for_each_sysfs_gt_dirfd(i915, dirfd, gt) { stash_min[gt] = get_freq(dirfd, RPS_MIN_FREQ_MHZ); stash_max[gt] = get_freq(dirfd, RPS_MAX_FREQ_MHZ); + igt_debug("GT: %d, min: %d, max: %d", gt, stash_min[gt], stash_max[gt]); igt_pm_ignore_slpc_efficient_freq(i915, dirfd, true); } igt_install_exit_handler(restore_sysfs_freq); -- 2.38.1
[Intel-gfx] [PATCH v3 i-g-t] tests/i915_pm_freq_api: Ignore zero register value
Register read for requested_freq can return 0 when system is in runtime_pm. Make allowance for this case. v2: Explicit check for runtime_pm status (Riana) v3: Revert back to v1, the runtime util functions do not work as expected. Link: https://gitlab.freedesktop.org/drm/intel/issues/8736 Link: https://gitlab.freedesktop.org/drm/intel/issues/8989 Reviewed-by: Riana Tauro Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 18 ++ 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index cf21cc936..9c71411ee 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -88,6 +88,7 @@ static void test_freq_basic_api(int dirfd, int gt) static void test_reset(int i915, int dirfd, int gt, int count) { uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + uint32_t req_freq; int fd; for (int i = 0; i < count; i++) { @@ -95,14 +96,18 @@ static void test_reset(int i915, int dirfd, int gt, int count) igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); /* Manually trigger a GT reset */ fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); igt_require(fd >= 0); igt_ignore_warn(write(fd, "1\n", 2)); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); } close(fd); } @@ -110,17 +115,22 @@ static void test_reset(int i915, int dirfd, int gt, int count) static void test_suspend(int i915, int dirfd, int gt) { uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + uint32_t req_freq; igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); /* Manually trigger a suspend */ igt_system_suspend_autoresume(SUSPEND_STATE_S3, SUSPEND_TEST_NONE); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); } int i915 = -1; -- 2.38.1
[Intel-gfx] [PATCH v2 i-g-t] tests/i915_pm_freq_api: Ignore zero register value
Register read for requested_freq can return 0 when system is in runtime_pm. Make allowance for this case. v2: Explicit check for runtime_pm status (Riana) Link: https://gitlab.freedesktop.org/drm/intel/issues/8736 Link: https://gitlab.freedesktop.org/drm/intel/issues/8989 Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index cf21cc936..6713ad213 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -95,14 +95,16 @@ static void test_reset(int i915, int dirfd, int gt, int count) igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + if (igt_get_runtime_pm_status() == IGT_RUNTIME_PM_STATUS_ACTIVE) + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); /* Manually trigger a GT reset */ fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); igt_require(fd >= 0); igt_ignore_warn(write(fd, "1\n", 2)); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + if (igt_get_runtime_pm_status() == IGT_RUNTIME_PM_STATUS_ACTIVE) + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); } close(fd); } @@ -114,13 +116,15 @@ static void test_suspend(int i915, int dirfd, int gt) igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + if (igt_get_runtime_pm_status() == IGT_RUNTIME_PM_STATUS_ACTIVE) + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); /* Manually trigger a suspend */ igt_system_suspend_autoresume(SUSPEND_STATE_S3, SUSPEND_TEST_NONE); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + if (igt_get_runtime_pm_status() == IGT_RUNTIME_PM_STATUS_ACTIVE) + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); } int i915 = -1; -- 2.38.1
[Intel-gfx] [PATCH i-g-t] tests/i915_pm_freq_api: Ignore zero register value
Register read for requested_freq can return 0 when system is in runtime_pm. Make allowance for this case. Link: https://gitlab.freedesktop.org/drm/intel/issues/8736 Link: https://gitlab.freedesktop.org/drm/intel/issues/8989 Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 18 ++ 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index cf21cc936..9c71411ee 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -88,6 +88,7 @@ static void test_freq_basic_api(int dirfd, int gt) static void test_reset(int i915, int dirfd, int gt, int count) { uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + uint32_t req_freq; int fd; for (int i = 0; i < count; i++) { @@ -95,14 +96,18 @@ static void test_reset(int i915, int dirfd, int gt, int count) igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); /* Manually trigger a GT reset */ fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); igt_require(fd >= 0); igt_ignore_warn(write(fd, "1\n", 2)); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); } close(fd); } @@ -110,17 +115,22 @@ static void test_reset(int i915, int dirfd, int gt, int count) static void test_suspend(int i915, int dirfd, int gt) { uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + uint32_t req_freq; igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); /* Manually trigger a suspend */ igt_system_suspend_autoresume(SUSPEND_STATE_S3, SUSPEND_TEST_NONE); - igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); + req_freq = get_freq(dirfd, RPS_CUR_FREQ_MHZ); + if (req_freq) + igt_assert_eq(req_freq, rpn); } int i915 = -1; -- 2.38.1
[Intel-gfx] [PATCH v2] drm/i915/guc/slpc: Restore efficient freq earlier
This should be done before the soft min/max frequencies are restored. When we disable the "Ignore efficient frequency" flag, GuC does not actually bring the requested freq down to RPn. Specifically, this scenario- - ignore efficient freq set to true - reduce min to RPn (from efficient) - suspend - resume (includes GuC load, restore soft min/max, restore efficient freq) - validate min freq has been resored to RPn This will fail if we didn't first restore(disable, in this case) efficient freq flag before setting the soft min frequency. v2: Bring the min freq down to RPn when we disable efficient freq (Rodrigo) Also made the change to set the min softlimit to RPn at init. Otherwise, we were storing RPe there. Link: https://gitlab.freedesktop.org/drm/intel/-/issues/8736 Fixes: 55f9720dbf23 ("drm/i915/guc/slpc: Provide sysfs for efficient freq") Fixes: 95ccf312a1e4 ("drm/i915/guc/slpc: Allow SLPC to use efficient frequency") Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 22 + 1 file changed, 14 insertions(+), 8 deletions(-) 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 ee9f83af7cf6..477df260ae3a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -470,12 +470,19 @@ int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val) ret = slpc_set_param(slpc, SLPC_PARAM_IGNORE_EFFICIENT_FREQUENCY, val); - if (ret) + if (ret) { guc_probe_error(slpc_to_guc(slpc), "Failed to set efficient freq(%d): %pe\n", val, ERR_PTR(ret)); - else + } else { slpc->ignore_eff_freq = val; + /* Set min to RPn when we disable efficient freq */ + if (val) + ret = slpc_set_param(slpc, + SLPC_PARAM_GLOBAL_MIN_GT_UNSLICE_FREQ_MHZ, +slpc->min_freq); + } + intel_runtime_pm_put(&i915->runtime_pm, wakeref); mutex_unlock(&slpc->lock); return ret; @@ -602,9 +609,8 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc) return ret; if (!slpc->min_freq_softlimit) { - ret = intel_guc_slpc_get_min_freq(slpc, &slpc->min_freq_softlimit); - if (unlikely(ret)) - return ret; + /* Min softlimit is initialized to RPn */ + slpc->min_freq_softlimit = slpc->min_freq; slpc_to_gt(slpc)->defaults.min_freq = slpc->min_freq_softlimit; } else { return intel_guc_slpc_set_min_freq(slpc, @@ -755,6 +761,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) return ret; } + /* Set cached value of ignore efficient freq */ + intel_guc_slpc_set_ignore_eff_freq(slpc, slpc->ignore_eff_freq); + /* Revert SLPC min/max to softlimits if necessary */ ret = slpc_set_softlimits(slpc); if (unlikely(ret)) { @@ -765,9 +774,6 @@ 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; } -- 2.38.1
[Intel-gfx] [PATCH] drm/i915/guc/slpc: Restore efficient freq earlier
This should be done before the soft min/max frequencies are restored. When we disable the "Ignore efficient frequency" flag, GuC does not actually bring the requested freq down to RPn. Specifically, this scenario- - ignore efficient freq set to true - reduce min to RPn (from efficient) - suspend - resume (includes GuC load, restore soft min/max, restore efficient freq) - validate min freq has been resored to RPn This will fail if we didn't first restore(disable, in this case) efficient freq flag before setting the soft min frequency. Link: https://gitlab.freedesktop.org/drm/intel/-/issues/8736 Fixes: 55f9720dbf23 ("drm/i915/guc/slpc: Provide sysfs for efficient freq") Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 ee9f83af7cf6..f16dff7c3185 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -743,6 +743,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) intel_guc_pm_intrmsk_enable(slpc_to_gt(slpc)); + /* Set cached value of ignore efficient freq */ + intel_guc_slpc_set_ignore_eff_freq(slpc, slpc->ignore_eff_freq); + slpc_get_rp_values(slpc); /* Handle the case where min=max=RPmax */ @@ -765,9 +768,6 @@ 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; } -- 2.38.1
[Intel-gfx] [PATCH v3 i-g-t] i915_pm_freq_api: Add some debug to tests
Some subtests seem to be failing in CI, use igt_assert_eq where we compare the requested freq, which will print the values being compared. Also print the RP values at the beginning of the test. v2: Print GT as well (Ashutosh) v3: Minor commit message correction (Ashutosh) Reviewed-by: Ashutosh Dixit Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index 522abee35..a7bbd4896 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -55,6 +55,7 @@ static void test_freq_basic_api(int dirfd, int gt) rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_debug("GT: %d, RPn: %d, RPe: %d, RP0: %d", gt, rpn, rpe, rp0); /* * Negative bound tests @@ -90,21 +91,18 @@ static void test_reset(int i915, int dirfd, int gt, int count) int fd; for (int i = 0; i < count; i++) { - igt_assert_f(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0, -"Failed after %d good cycles\n", i); - igt_assert_f(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0, -"Failed after %d good cycles\n", i); + igt_debug("Running cycle: %d", i); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, -"Failed after %d good cycles\n", i); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); /* Manually trigger a GT reset */ fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); igt_require(fd >= 0); igt_ignore_warn(write(fd, "1\n", 2)); - igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, -"Failed after %d good cycles\n", i); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); } close(fd); } @@ -116,13 +114,13 @@ static void test_suspend(int i915, int dirfd, int gt) igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); /* Manually trigger a suspend */ igt_system_suspend_autoresume(SUSPEND_STATE_S3, SUSPEND_TEST_NONE); - igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); } int i915 = -1; -- 2.38.1
[Intel-gfx] [PATCH v2 i-g-t] i915_pm_freq_api: Add some debug to tests
Some subtests seem to be failing in CI, use igt_assert_(lt/eq) which print the values being compared and some additional debug as well. v2: Print GT as well (Ashutosh) Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index 522abee35..a7bbd4896 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -55,6 +55,7 @@ static void test_freq_basic_api(int dirfd, int gt) rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_debug("GT: %d, RPn: %d, RPe: %d, RP0: %d", gt, rpn, rpe, rp0); /* * Negative bound tests @@ -90,21 +91,18 @@ static void test_reset(int i915, int dirfd, int gt, int count) int fd; for (int i = 0; i < count; i++) { - igt_assert_f(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0, -"Failed after %d good cycles\n", i); - igt_assert_f(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0, -"Failed after %d good cycles\n", i); + igt_debug("Running cycle: %d", i); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, -"Failed after %d good cycles\n", i); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); /* Manually trigger a GT reset */ fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); igt_require(fd >= 0); igt_ignore_warn(write(fd, "1\n", 2)); - igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, -"Failed after %d good cycles\n", i); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); } close(fd); } @@ -116,13 +114,13 @@ static void test_suspend(int i915, int dirfd, int gt) igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); /* Manually trigger a suspend */ igt_system_suspend_autoresume(SUSPEND_STATE_S3, SUSPEND_TEST_NONE); - igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); } int i915 = -1; -- 2.38.1
[Intel-gfx] [PATCH i-g-t] i915_pm_freq_api: Add some debug to tests
Some subtests seem to be failing in CI, use igt_assert_(lt/eq) which print the values being compared and some additional debug as well. Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index 522abee35..cdb2e70ca 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -55,6 +55,7 @@ static void test_freq_basic_api(int dirfd, int gt) rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_debug("RPn: %d, RPe: %d, RP0: %d", rpn, rpe, rp0); /* * Negative bound tests @@ -90,21 +91,18 @@ static void test_reset(int i915, int dirfd, int gt, int count) int fd; for (int i = 0; i < count; i++) { - igt_assert_f(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0, -"Failed after %d good cycles\n", i); - igt_assert_f(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0, -"Failed after %d good cycles\n", i); + igt_debug("Running cycle: %d", i); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, -"Failed after %d good cycles\n", i); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); /* Manually trigger a GT reset */ fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); igt_require(fd >= 0); igt_ignore_warn(write(fd, "1\n", 2)); - igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, -"Failed after %d good cycles\n", i); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); } close(fd); } @@ -116,13 +114,13 @@ static void test_suspend(int i915, int dirfd, int gt) igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); /* Manually trigger a suspend */ igt_system_suspend_autoresume(SUSPEND_STATE_S3, SUSPEND_TEST_NONE); - igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); + igt_assert_eq(get_freq(dirfd, RPS_CUR_FREQ_MHZ), rpn); } int i915 = -1; -- 2.38.1
[Intel-gfx] [PATCH v2] drm/i915/guc: Dump perf_limit_reasons for debug
GuC load takes longer sometimes due to GT frequency not ramping up. Add perf_limit_reasons to the existing warn print to see if frequency is being throttled. v2: Review comments (Ashutosh) Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 364d0d546ec8..0f79cb658518 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -251,9 +251,11 @@ static int guc_wait_ucode(struct intel_guc *guc) if (ret == 0) ret = -ENXIO; } else if (delta_ms > 200) { - guc_warn(guc, "excessive init time: %lldms! [freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d]\n", -delta_ms, intel_rps_read_actual_frequency(&uncore->gt->rps), -before_freq, status, count, ret); + guc_warn(guc, "excessive init time: %lldms! [status = 0x%08X, count = %d, ret = %d]\n", +delta_ms, status, count, ret); + guc_warn(guc, "excessive init time: [freq = %dMHz, before = %dMHz, perf_limit_reasons = 0x%08X]\n", +intel_rps_read_actual_frequency(&uncore->gt->rps), before_freq, +intel_uncore_read(uncore, intel_gt_perf_limit_reasons_reg(gt))); } else { guc_dbg(guc, "init took %lldms, freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d\n", delta_ms, intel_rps_read_actual_frequency(&uncore->gt->rps), -- 2.38.1
[Intel-gfx] [PATCH] drm/i915/guc: Dump perf_limit_reasons for debug
GuC load takes longer sometimes due to GT frequency not ramping up. Add perf_limit_reasons to the existing warn print to see if frequency is being throttled. Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 364d0d546ec8..73911536a8e7 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -254,6 +254,8 @@ static int guc_wait_ucode(struct intel_guc *guc) guc_warn(guc, "excessive init time: %lldms! [freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d]\n", delta_ms, intel_rps_read_actual_frequency(&uncore->gt->rps), before_freq, status, count, ret); + guc_warn(guc, "perf limit reasons = 0x%08X\n", +intel_uncore_read(uncore, intel_gt_perf_limit_reasons_reg(gt))); } else { guc_dbg(guc, "init took %lldms, freq = %dMHz, before = %dMHz, status = 0x%08X, count = %d, ret = %d\n", delta_ms, intel_rps_read_actual_frequency(&uncore->gt->rps), -- 2.38.1
[Intel-gfx] [PATCH v2] drm/i915/guc/slpc: Apply min softlimit correctly
The scenario being fixed here is depicted in the following sequence- modprobe i915 echo 1 > /sys/class/drm/card0/gt/gt0/slpc_ignore_eff_freq echo 300 > /sys/class/drm/card0/gt_min_freq_mhz (RPn) cat /sys/class/drm/card0/gt_cur_freq_mhz --> cur == RPn as expected echo 1 > /sys/kernel/debug/dri/0/gt0/reset --> reset cat /sys/class/drm/card0/gt_min_freq_mhz --> cached freq is RPn cat /sys/class/drm/card0/gt_cur_freq_mhz --> it's not RPn, but RPe!! When SLPC reinitializes, it sets SLPC min freq to efficient frequency. Even if we disable efficient freq post that, we should restore the cached min freq (via H2G) for it to take effect. v2: Clarify commit message (Ashutosh) Fixes: 95ccf312a1e4 ("drm/i915/guc/slpc: Allow SLPC to use efficient frequency") Reviewed-by: Ashutosh Dixit Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 01b75529311c..ee9f83af7cf6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -606,7 +606,7 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc) if (unlikely(ret)) return ret; slpc_to_gt(slpc)->defaults.min_freq = slpc->min_freq_softlimit; - } else if (slpc->min_freq_softlimit != slpc->min_freq) { + } else { return intel_guc_slpc_set_min_freq(slpc, slpc->min_freq_softlimit); } -- 2.38.1
[Intel-gfx] [PATCH v3 i-g-t] tests/i915_pm_freq_api: Add a suspend subtest
Verify that SLPC API works as expected after a suspend. Added another subtest that does multiple GT resets and checks freq api works as expected after each one. We now check requested frequency instead of soft min/max after a reset or suspend. That ensures the soft limits got applied correctly at init. Also, disable efficient freq before starting the test which allows current freq to be consistent with SLPC min freq. v2: Restore freq in exit handler (Ashutosh) v3: Free the allocated stash arrays Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 92 +++ 1 file changed, 71 insertions(+), 21 deletions(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index 9005cd220..522abee35 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -18,6 +18,12 @@ * * SUBTEST: freq-reset * Description: Test basic freq API works after a reset + * + * SUBTEST: freq-reset-multiple + * Description: Test basic freq API works after multiple resets + * + * SUBTEST: freq-suspend + * Description: Test basic freq API works after a runtime suspend */ IGT_TEST_DESCRIPTION("Test SLPC freq API"); @@ -49,7 +55,6 @@ static void test_freq_basic_api(int dirfd, int gt) rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); - igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0); /* * Negative bound tests @@ -79,31 +84,66 @@ static void test_freq_basic_api(int dirfd, int gt) } -static void test_reset(int i915, int dirfd, int gt) +static void test_reset(int i915, int dirfd, int gt, int count) { uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); int fd; + for (int i = 0; i < count; i++) { + igt_assert_f(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0, +"Failed after %d good cycles\n", i); + igt_assert_f(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0, +"Failed after %d good cycles\n", i); + usleep(ACT_FREQ_LATENCY_US); + igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, +"Failed after %d good cycles\n", i); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + + igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, +"Failed after %d good cycles\n", i); + } + close(fd); +} + +static void test_suspend(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); - /* Manually trigger a GT reset */ - fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); - igt_require(fd >= 0); - igt_ignore_warn(write(fd, "1\n", 2)); - close(fd); + /* Manually trigger a suspend */ + igt_system_suspend_autoresume(SUSPEND_STATE_S3, + SUSPEND_TEST_NONE); - igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); - igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); } -igt_main +int i915 = -1; +uint32_t *stash_min, *stash_max; + +static void restore_sysfs_freq(int sig) { - int i915 = -1; - uint32_t *stash_min, *stash_max; + int dirfd, gt; + /* Restore frequencies */ + for_each_sysfs_gt_dirfd(i915, dirfd, gt) { + igt_pm_ignore_slpc_efficient_freq(i915, dirfd, false); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, stash_max[gt]) > 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, stash_min[gt]) > 0); + } + free(stash_min); + free(stash_max); + close(i915); +} +igt_main +{ igt_fixture { int num_gts, dirfd, gt; @@ -122,7 +162,9 @@ igt_main for_each_sysfs_gt_dirfd(i915, dirfd, gt) { stash_min[gt] = get_freq(dirfd, RPS_MIN_FREQ_MHZ); stash_max[gt] = get_freq(dirfd, RPS_MAX_FREQ_MHZ); + igt_pm_ignore_slpc_efficient_freq(i915, dirfd, true); } + igt_install_exit_handler(restore_sysfs_freq); } igt_describe("Test basic API for controlling min/max GT frequency"); @
[Intel-gfx] [PATCH v2 i-g-t] tests/i915_pm_freq_api: Add a suspend subtest
Verify that SLPC API works as expected after a suspend. Added another subtest that does multiple GT resets and checks freq api works as expected after each one. We now check requested frequency instead of soft min/max after a reset or suspend. That ensures the soft limits got applied correctly at init. Also, disable efficient freq before starting the test which allows current freq to be consistent with SLPC min freq. v2: Restore freq in exit handler (Ashutosh) Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 89 +++ 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index 9005cd220..4e1d4edca 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -18,6 +18,12 @@ * * SUBTEST: freq-reset * Description: Test basic freq API works after a reset + * + * SUBTEST: freq-reset-multiple + * Description: Test basic freq API works after multiple resets + * + * SUBTEST: freq-suspend + * Description: Test basic freq API works after a runtime suspend */ IGT_TEST_DESCRIPTION("Test SLPC freq API"); @@ -79,31 +85,64 @@ static void test_freq_basic_api(int dirfd, int gt) } -static void test_reset(int i915, int dirfd, int gt) +static void test_reset(int i915, int dirfd, int gt, int count) { uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); int fd; + for (int i = 0; i < count; i++) { + igt_assert_f(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0, +"Failed after %d good cycles\n", i); + igt_assert_f(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0, +"Failed after %d good cycles\n", i); + usleep(ACT_FREQ_LATENCY_US); + igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, +"Failed after %d good cycles\n", i); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + + igt_assert_f(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn, +"Failed after %d good cycles\n", i); + } + close(fd); +} + +static void test_suspend(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); usleep(ACT_FREQ_LATENCY_US); - igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); - /* Manually trigger a GT reset */ - fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); - igt_require(fd >= 0); - igt_ignore_warn(write(fd, "1\n", 2)); - close(fd); + /* Manually trigger a suspend */ + igt_system_suspend_autoresume(SUSPEND_STATE_S3, + SUSPEND_TEST_NONE); - igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); - igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_CUR_FREQ_MHZ) == rpn); } -igt_main +int i915 = -1; +uint32_t *stash_min, *stash_max; + +static void restore_sysfs_freq(int sig) { - int i915 = -1; - uint32_t *stash_min, *stash_max; + int dirfd, gt; + /* Restore frequencies */ + for_each_sysfs_gt_dirfd(i915, dirfd, gt) { + igt_pm_ignore_slpc_efficient_freq(i915, dirfd, false); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, stash_max[gt]) > 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, stash_min[gt]) > 0); + } + close(i915); +} +igt_main +{ igt_fixture { int num_gts, dirfd, gt; @@ -122,7 +161,9 @@ igt_main for_each_sysfs_gt_dirfd(i915, dirfd, gt) { stash_min[gt] = get_freq(dirfd, RPS_MIN_FREQ_MHZ); stash_max[gt] = get_freq(dirfd, RPS_MAX_FREQ_MHZ); + igt_pm_ignore_slpc_efficient_freq(i915, dirfd, true); } + igt_install_exit_handler(restore_sysfs_freq); } igt_describe("Test basic API for controlling min/max GT frequency"); @@ -140,16 +181,24 @@ igt_main for_each_sysfs_gt_dirfd(i915, dirfd, gt) igt_dynamic_f("gt%u", gt) - test_reset(i915, dirfd, gt); + test_reset(i915, dirfd, gt, 1); } - igt_fixture { + igt_describe("Test basic freq API works after multiple resets"); + igt_subtest_with_dynamic_f("freq-reset-multiple") {
[Intel-gfx] [PATCH] drm/i915/guc/slpc: Apply min softlimit correctly
We were skipping when min_softlimit was equal to RPn. We need to apply it rergardless as efficient frequency will push the SLPC min to RPe. This will break scenarios where user sets a min softlimit < RPe before reset and then performs a GT reset. Fixes: 95ccf312a1e4 ("drm/i915/guc/slpc: Allow SLPC to use efficient frequency") Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 01b75529311c..ee9f83af7cf6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -606,7 +606,7 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc) if (unlikely(ret)) return ret; slpc_to_gt(slpc)->defaults.min_freq = slpc->min_freq_softlimit; - } else if (slpc->min_freq_softlimit != slpc->min_freq) { + } else { return intel_guc_slpc_set_min_freq(slpc, slpc->min_freq_softlimit); } -- 2.38.1
[Intel-gfx] [PATCH v2 i-g-t] tests/gem_ctx_persistence: Skip hang subtest with GuC
Hang scenarios are not supported with persistent contexts when GuC submission is enabled. Cc: Kamil Konieczny Reviewed-by: Andrzej Hajda Signed-off-by: Vinay Belgaumkar --- tests/i915/gem_ctx_persistence.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/i915/gem_ctx_persistence.c b/tests/i915/gem_ctx_persistence.c index df9b1c491..d2558354e 100644 --- a/tests/i915/gem_ctx_persistence.c +++ b/tests/i915/gem_ctx_persistence.c @@ -577,6 +577,8 @@ static void test_nohangcheck_hang(int i915, const intel_ctx_cfg_t *cfg) int testable_engines = 0; int dir; + igt_require(!gem_using_guc_submission(i915)); + cleanup(i915); /* -- 2.38.1
[Intel-gfx] [PATCH i-g-t] tests/gem_ctx_persistence: Skip hang subtest with GuC
Hang subtest is not supported with GuC submission enabled. Cc: Kamil Konieczny Signed-off-by: Vinay Belgaumkar --- tests/i915/gem_ctx_persistence.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/i915/gem_ctx_persistence.c b/tests/i915/gem_ctx_persistence.c index df9b1c491..d2558354e 100644 --- a/tests/i915/gem_ctx_persistence.c +++ b/tests/i915/gem_ctx_persistence.c @@ -577,6 +577,8 @@ static void test_nohangcheck_hang(int i915, const intel_ctx_cfg_t *cfg) int testable_engines = 0; int dir; + igt_require(!gem_using_guc_submission(i915)); + cleanup(i915); /* -- 2.38.1
[Intel-gfx] [PATCH i-g-t] tests/i915_pm_freq_api: Add a suspend subtest
Verify that SLPC API works as expected after a suspend. Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 30 ++ 1 file changed, 30 insertions(+) diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c index 9005cd220..f35f1f8e0 100644 --- a/tests/i915/i915_pm_freq_api.c +++ b/tests/i915/i915_pm_freq_api.c @@ -18,6 +18,9 @@ * * SUBTEST: freq-reset * Description: Test basic freq API works after a reset + * + * SUBTEST: freq-suspend + * Description: Test basic freq API works after a runtime suspend */ IGT_TEST_DESCRIPTION("Test SLPC freq API"); @@ -99,6 +102,24 @@ static void test_reset(int i915, int dirfd, int gt) igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); } +static void test_suspend(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + usleep(ACT_FREQ_LATENCY_US); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + + /* Manually trigger a suspend */ + igt_system_suspend_autoresume(SUSPEND_STATE_S3, + SUSPEND_TEST_NONE); + + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); +} + igt_main { int i915 = -1; @@ -143,6 +164,15 @@ igt_main test_reset(i915, dirfd, gt); } + igt_describe("Test basic freq API works after suspend"); + igt_subtest_with_dynamic_f("freq-suspend") { + int dirfd, gt; + + for_each_sysfs_gt_dirfd(i915, dirfd, gt) + igt_dynamic_f("gt%u", gt) + test_suspend(i915, dirfd, gt); + } + igt_fixture { int dirfd, gt; /* Restore frequencies */ -- 2.38.1
[Intel-gfx] [PATCH i-g-t] tests/i915/gem_ctx_persistence: Skip some subtests
Hang and heartbeat subtests are not supported with GuC submission enabled. Signed-off-by: Vinay Belgaumkar --- tests/i915/gem_ctx_persistence.c | 32 +++- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/tests/i915/gem_ctx_persistence.c b/tests/i915/gem_ctx_persistence.c index 42cf96329..1e122535e 100644 --- a/tests/i915/gem_ctx_persistence.c +++ b/tests/i915/gem_ctx_persistence.c @@ -1366,19 +1366,25 @@ igt_main igt_subtest("hostile") test_nohangcheck_hostile(i915, &empty_cfg); - igt_subtest("hang") - test_nohangcheck_hang(i915, &empty_cfg); - - igt_subtest("heartbeat-stop") - test_noheartbeat_many(i915, 1, 0); - igt_subtest("heartbeat-hang") - test_noheartbeat_many(i915, 1, IGT_SPIN_NO_PREEMPTION); - igt_subtest("heartbeat-many") - test_noheartbeat_many(i915, 16, 0); - igt_subtest("heartbeat-close") - test_noheartbeat_close(i915, 0); - igt_subtest("heartbeat-hostile") - test_noheartbeat_close(i915, IGT_SPIN_NO_PREEMPTION); + + igt_subtest_group { + igt_fixture + igt_skip_on(gem_using_guc_submission(i915)); + + igt_subtest("hang") + test_nohangcheck_hang(i915, &empty_cfg); + + igt_subtest("heartbeat-stop") + test_noheartbeat_many(i915, 1, 0); + igt_subtest("heartbeat-hang") + test_noheartbeat_many(i915, 1, IGT_SPIN_NO_PREEMPTION); + igt_subtest("heartbeat-many") + test_noheartbeat_many(i915, 16, 0); + igt_subtest("heartbeat-close") + test_noheartbeat_close(i915, 0); + igt_subtest("heartbeat-hostile") + test_noheartbeat_close(i915, IGT_SPIN_NO_PREEMPTION); + } igt_subtest_group { igt_fixture -- 2.38.1
[Intel-gfx] [PATCH] drm/i915/guc/slpc: Disable rps_boost debugfs
rps_boost debugfs shows host turbo related info. This is not valid when SLPC is enabled. guc_slpc_info already shows the number of boosts. Add num_waiters there as well and disable rps_boost when SLPC is enabled. v2: Replace Bug with Link to resolve checkpatch warning Link: https://gitlab.freedesktop.org/drm/intel/-/issues/7632 Reviewed-by: Ashutosh Dixit Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 5 - drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 80dbbef86b1d..357e2f865727 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -539,7 +539,10 @@ static bool rps_eval(void *data) { struct intel_gt *gt = data; - return HAS_RPS(gt->i915); + if (intel_guc_slpc_is_used(>->uc.guc)) + return false; + else + return HAS_RPS(gt->i915); } DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(rps_boost); 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 56dbba1ef668..01b75529311c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -837,6 +837,8 @@ int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p slpc_decode_min_freq(slpc)); drm_printf(p, "\twaitboosts: %u\n", slpc->num_boosts); + drm_printf(p, "\tBoosts outstanding: %u\n", + atomic_read(&slpc->num_waiters)); } } -- 2.38.1
[Intel-gfx] [PATCH] drm/i915/guc/slpc: Disable rps_boost debugfs
rps_boost debugfs shows host turbo related info. This is not valid when SLPC is enabled. guc_slpc_info already shows the number of boosts. Add num_waiters there as well and disable rps_boost when SLPC is enabled. Bug: https://gitlab.freedesktop.org/drm/intel/-/issues/7632 Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 5 - drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 80dbbef86b1d..357e2f865727 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -539,7 +539,10 @@ static bool rps_eval(void *data) { struct intel_gt *gt = data; - return HAS_RPS(gt->i915); + if (intel_guc_slpc_is_used(>->uc.guc)) + return false; + else + return HAS_RPS(gt->i915); } DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(rps_boost); 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 56dbba1ef668..01b75529311c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -837,6 +837,8 @@ int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p slpc_decode_min_freq(slpc)); drm_printf(p, "\twaitboosts: %u\n", slpc->num_boosts); + drm_printf(p, "\tBoosts outstanding: %u\n", + atomic_read(&slpc->num_waiters)); } } -- 2.38.1
[Intel-gfx] [PATCH v6 2/2] drm/i915/selftest: Update the SLPC selftest
Use the new efficient frequency toggling interface. Also create a helper function to restore the frequencies after the test is done. v2: Restore max freq first and then min. Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/selftest_slpc.c | 42 ++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c index bd44ce73a504..952c8d52d68a 100644 --- a/drivers/gpu/drm/i915/gt/selftest_slpc.c +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c @@ -70,6 +70,31 @@ static int slpc_set_freq(struct intel_gt *gt, u32 freq) return err; } +static int slpc_restore_freq(struct intel_guc_slpc *slpc, u32 min, u32 max) +{ + int err; + + err = slpc_set_max_freq(slpc, max); + if (err) { + pr_err("Unable to restore max freq"); + return err; + } + + err = slpc_set_min_freq(slpc, min); + if (err) { + pr_err("Unable to restore min freq"); + return err; + } + + err = intel_guc_slpc_set_ignore_eff_freq(slpc, false); + if (err) { + pr_err("Unable to restore efficient freq"); + return err; + } + + return 0; +} + static u64 measure_power_at_freq(struct intel_gt *gt, int *freq, u64 *power) { int err = 0; @@ -268,8 +293,7 @@ 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. +* range of RPn-RP0. */ err = slpc_set_min_freq(slpc, slpc->min_freq); if (err) { @@ -277,6 +301,15 @@ static int run_test(struct intel_gt *gt, int test_type) return err; } + /* +* Turn off efficient frequency so RPn/RP0 ranges are obeyed. +*/ + err = intel_guc_slpc_set_ignore_eff_freq(slpc, true); + if (err) { + pr_err("Unable to turn off efficient freq!"); + return err; + } + intel_gt_pm_wait_for_idle(gt); intel_gt_pm_get(gt); for_each_engine(engine, gt, id) { @@ -358,9 +391,8 @@ static int run_test(struct intel_gt *gt, int test_type) break; } - /* Restore min/max frequencies */ - slpc_set_max_freq(slpc, slpc_max_freq); - slpc_set_min_freq(slpc, slpc_min_freq); + /* Restore min/max/efficient frequencies */ + err = slpc_restore_freq(slpc, slpc_min_freq, slpc_max_freq); if (igt_flush_test(gt->i915)) err = -EIO; -- 2.38.1
[Intel-gfx] [PATCH v6 1/2] drm/i915/guc/slpc: Provide sysfs for efficient freq
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 v5: Review comments (Andi) and add a separate patch for selftest updates Fixes: 95ccf312a1e4 ("drm/i915/guc/slpc: Allow SLPC to use efficient frequency") Signed-off-by: Vinay Belgaumkar Reviewed-by: Rodrigo Vivi Reviewed-by: Ashutosh Dixit --- drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 35 + drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 38 +-- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 1 + 4 files changed, 64 insertions(+), 11 deletions(-) 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 = >->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 = >->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(>->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/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 026d73855f36..56dbba1ef668 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,29 @@ 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; + + 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", +
[Intel-gfx] [PATCH i-g-t 3/4] i915_pm_freq_api: Add some basic SLPC igt tests
Validate basic api for GT freq control. Also test interaction with GT reset. We skip rps tests with SLPC enabled, this will re-introduce some coverage. SLPC selftests are already covering some other workload related scenarios. v2: Rename test (Rodrigo) v3: Review comments (Ashutosh) v4: Skip when SLPC is disabled. Check for enable_guc is not sufficient as kernel config may have it but the platform doesn't actually support it. v5: Use the updated SLPC helper v6: Check for guc enabled as well as slpc debugfs Reviewed-by: Ashutosh Dixit Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 153 ++ tests/meson.build | 1 + 2 files changed, 154 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c new file mode 100644 index ..17adacbc --- /dev/null +++ b/tests/i915/i915_pm_freq_api.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmtest.h" +#include "i915/gem.h" +#include "igt_sysfs.h" +#include "igt.h" + +IGT_TEST_DESCRIPTION("Test SLPC freq API"); +/* + * Too many intermediate components and steps before freq is adjusted + * Specially if workload is under execution, so let's wait 100 ms. + */ +#define ACT_FREQ_LATENCY_US 10 + +static uint32_t get_freq(int dirfd, uint8_t id) +{ + uint32_t val; + + igt_assert(igt_sysfs_rps_scanf(dirfd, id, "%u", &val) == 1); + + return val; +} + +static int set_freq(int dirfd, uint8_t id, uint32_t val) +{ + return igt_sysfs_rps_printf(dirfd, id, "%u", val); +} + +static void test_freq_basic_api(int dirfd, int gt) +{ + uint32_t rpn, rp0, rpe; + + /* Save frequencies */ + rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); + rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0); + + /* +* Negative bound tests +* RPn is the floor +* RP0 is the ceiling +*/ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0 + 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0 + 1) < 0); + + /* Assert min requests are respected from rp0 to rpn */ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rp0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Assert max requests are respected from rpn to rp0 */ + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rp0); + +} + +static void test_reset(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + int fd; + + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + usleep(ACT_FREQ_LATENCY_US); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + close(fd); + + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); +} + +igt_main +{ + int i915 = -1; + uint32_t *stash_min, *stash_max; + + igt_fixture { + int num_gts, dirfd, gt; + + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + /* i915_pm_rps already covers execlist path */ + igt_require_f(gem_using_guc_submission(i915) && + i915_is_slpc_enabled(i915), + "This test is supported only with SLPC enabled\n"); + + num_gts = igt_sysfs_get_num_gt(i915); + stash_min = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + +
[Intel-gfx] [PATCH i-g-t 4/4] HAX: tests/i915: Try out the SLPC IGT tests
Trying out for CI. Do not review. Signed-off-by: Vinay Belgaumkar --- tests/intel-ci/fast-feedback.testlist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist index d9fcb62d..653668dd 100644 --- a/tests/intel-ci/fast-feedback.testlist +++ b/tests/intel-ci/fast-feedback.testlist @@ -139,6 +139,8 @@ igt@prime_self_import@basic-with_fd_dup igt@prime_self_import@basic-with_one_bo igt@prime_self_import@basic-with_one_bo_two_files igt@prime_self_import@basic-with_two_bos +igt@i915_pm_freq_api@freq-basic-api +igt@i915_pm_freq_api@freq-reset igt@prime_vgem@basic-fence-flip igt@prime_vgem@basic-fence-mmap igt@prime_vgem@basic-fence-read -- 2.38.1
[Intel-gfx] [PATCH v7 i-g-t 0/4] tests/slpc: Add basic IGT test
Borrow some subtests from xe_guc_pc. Also add per GT debugfs helpers. v3: Review comments and add HAX patch v4: Modify the condition for skipping the test v5: Update the SLPC helper to per GT v6: Review comments (Ashutosh) Signed-off-by: Vinay Belgaumkar Vinay Belgaumkar (4): lib/debugfs: Add per GT debugfs helpers lib: Make SLPC helper function per GT i915_pm_freq_api: Add some basic SLPC igt tests HAX: tests/i915: Try out the SLPC IGT tests lib/igt_debugfs.c | 60 ++ lib/igt_debugfs.h | 4 + lib/igt_pm.c | 37 +-- lib/igt_pm.h | 3 +- tests/i915/i915_pm_freq_api.c | 153 ++ tests/intel-ci/fast-feedback.testlist | 2 + tests/meson.build | 1 + 7 files changed, 250 insertions(+), 10 deletions(-) create mode 100644 tests/i915/i915_pm_freq_api.c -- 2.38.1
[Intel-gfx] [PATCH i-g-t 1/4] lib/debugfs: Add per GT debugfs helpers
These can be used to open per-gt debugfs files. Reviewed-by: Ashutosh Dixit Signed-off-by: Tvrtko Ursulin Signed-off-by: Vinay Belgaumkar --- lib/igt_debugfs.c | 60 +++ lib/igt_debugfs.h | 4 2 files changed, 64 insertions(+) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 05889bbe..afde2da6 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -217,6 +217,37 @@ int igt_debugfs_dir(int device) return open(path, O_RDONLY); } +/** + * igt_debugfs_gt_dir: + * @device: fd of the device + * @gt: GT instance number + * + * This opens the debugfs directory corresponding to device for use + * with igt_sysfs_get() and related functions. + * + * Returns: + * The directory fd, or -1 on failure. + */ +int igt_debugfs_gt_dir(int device, unsigned int gt) +{ + int debugfs_gt_dir_fd; + char path[PATH_MAX]; + char gtpath[16]; + int ret; + + if (!igt_debugfs_path(device, path, sizeof(path))) + return -1; + + ret = snprintf(gtpath, sizeof(gtpath), "/gt%u", gt); + igt_assert(ret < sizeof(gtpath)); + strncat(path, gtpath, sizeof(path) - 1); + + debugfs_gt_dir_fd = open(path, O_RDONLY); + igt_debug_on_f(debugfs_gt_dir_fd < 0, "path: %s\n", path); + + return debugfs_gt_dir_fd; +} + /** * igt_debugfs_connector_dir: * @device: fd of the device @@ -313,6 +344,35 @@ bool igt_debugfs_exists(int device, const char *filename, int mode) return false; } +/** + * igt_debugfs_gt_open: + * @device: open i915 drm fd + * @gt: gt instance number + * @filename: name of the debugfs node to open + * @mode: mode bits as used by open() + * + * This opens a debugfs file as a Unix file descriptor. The filename should be + * relative to the drm device's root, i.e. without "drm/$minor". + * + * Returns: + * The Unix file descriptor for the debugfs file or -1 if that didn't work out. + */ +int +igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, int mode) +{ + int dir, ret; + + dir = igt_debugfs_gt_dir(device, gt); + if (dir < 0) + return dir; + + ret = openat(dir, filename, mode); + + close(dir); + + return ret; +} + /** * igt_debugfs_simple_read: * @dir: fd of the debugfs directory diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 4824344a..3e6194ad 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -45,6 +45,10 @@ void __igt_debugfs_write(int fd, const char *filename, const char *buf, int size int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int size); bool igt_debugfs_search(int fd, const char *filename, const char *substring); +int igt_debugfs_gt_dir(int device, unsigned int gt); +int igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, + int mode); + /** * igt_debugfs_read: * @filename: name of the debugfs file -- 2.38.1
[Intel-gfx] [PATCH i-g-t 2/4] lib: Make SLPC helper function per GT
Use default of 0 where GT id is not being used. Fixes: https://gitlab.freedesktop.org/drm/intel/-/issues/8308 v2: Add a helper for GT 0 (Ashutosh) v3: Additional review comments (Ashutosh) v4: Return false if slpc debugfs is not found Signed-off-by: Vinay Belgaumkar Reviewed-by: Ashutosh Dixit --- lib/igt_pm.c | 37 - lib/igt_pm.h | 3 ++- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/lib/igt_pm.c b/lib/igt_pm.c index 704acf7d..e60b09a7 100644 --- a/lib/igt_pm.c +++ b/lib/igt_pm.c @@ -1329,21 +1329,40 @@ void igt_pm_print_pci_card_runtime_status(void) } } -bool i915_is_slpc_enabled(int fd) +/** + * i915_is_slpc_enabled_gt: + * @drm_fd: DRM file descriptor + * @gt: GT id + * Check if SLPC is enabled on a GT + */ +bool i915_is_slpc_enabled_gt(int drm_fd, int gt) { - int debugfs_fd = igt_debugfs_dir(fd); + int dir, debugfs_fd; char buf[4096] = {}; - int len; - igt_require(debugfs_fd != -1); + dir = igt_debugfs_gt_dir(drm_fd, gt); + igt_require(dir); + + debugfs_fd = openat(dir, "uc/guc_slpc_info", O_RDONLY); + /* if guc_slpc_info not present then return false */ + if (debugfs_fd < 0) + return false; + + read(debugfs_fd, buf, sizeof(buf)-1); - len = igt_debugfs_simple_read(debugfs_fd, "gt/uc/guc_slpc_info", buf, sizeof(buf)); close(debugfs_fd); - if (len < 0) - return false; - else - return strstr(buf, "SLPC state: running"); + return strstr(buf, "SLPC state: running"); +} + +/** + * i915_is_slpc_enabled: + * @drm_fd: DRM file descriptor + * Check if SLPC is enabled for the device + */ +bool i915_is_slpc_enabled(int drm_fd) +{ + return i915_is_slpc_enabled_gt(drm_fd, 0); } int igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev) diff --git a/lib/igt_pm.h b/lib/igt_pm.h index d0d6d673..448cf42d 100644 --- a/lib/igt_pm.h +++ b/lib/igt_pm.h @@ -84,7 +84,8 @@ void igt_pm_set_d3cold_allowed(struct igt_device_card *card, const char *val); void igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev); void igt_pm_restore_pci_card_runtime_pm(void); void igt_pm_print_pci_card_runtime_status(void); -bool i915_is_slpc_enabled(int fd); +bool i915_is_slpc_enabled_gt(int drm_fd, int gt); +bool i915_is_slpc_enabled(int drm_fd); int igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev); int igt_pm_get_runtime_usage(struct pci_device *pci_dev); -- 2.38.1
[Intel-gfx] [PATCH i-g-t 3/4] i915_pm_freq_api: Add some basic SLPC igt tests
Validate basic api for GT freq control. Also test interaction with GT reset. We skip rps tests with SLPC enabled, this will re-introduce some coverage. SLPC selftests are already covering some other workload related scenarios. v2: Rename test (Rodrigo) v3: Review comments (Ashutosh) v4: Skip when SLPC is disabled. Check for enable_guc is not sufficient as kernel config may have it but the platform doesn't actually support it. v5: Use the updated SLPC helper Reviewed-by: Ashutosh Dixit Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 152 ++ tests/meson.build | 1 + 2 files changed, 153 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c new file mode 100644 index ..f0f4e3f9 --- /dev/null +++ b/tests/i915/i915_pm_freq_api.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmtest.h" +#include "i915/gem.h" +#include "igt_sysfs.h" +#include "igt.h" + +IGT_TEST_DESCRIPTION("Test SLPC freq API"); +/* + * Too many intermediate components and steps before freq is adjusted + * Specially if workload is under execution, so let's wait 100 ms. + */ +#define ACT_FREQ_LATENCY_US 10 + +static uint32_t get_freq(int dirfd, uint8_t id) +{ + uint32_t val; + + igt_assert(igt_sysfs_rps_scanf(dirfd, id, "%u", &val) == 1); + + return val; +} + +static int set_freq(int dirfd, uint8_t id, uint32_t val) +{ + return igt_sysfs_rps_printf(dirfd, id, "%u", val); +} + +static void test_freq_basic_api(int dirfd, int gt) +{ + uint32_t rpn, rp0, rpe; + + /* Save frequencies */ + rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); + rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0); + + /* +* Negative bound tests +* RPn is the floor +* RP0 is the ceiling +*/ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0 + 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0 + 1) < 0); + + /* Assert min requests are respected from rp0 to rpn */ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rp0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Assert max requests are respected from rpn to rp0 */ + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rp0); + +} + +static void test_reset(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + int fd; + + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + usleep(ACT_FREQ_LATENCY_US); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + close(fd); + + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); +} + +igt_main +{ + int i915 = -1; + uint32_t *stash_min, *stash_max; + + igt_fixture { + int num_gts, dirfd, gt; + + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + /* i915_pm_rps already covers execlist path */ + igt_skip_on_f(!i915_is_slpc_enabled(i915), + "This test is supported only with SLPC enabled\n"); + + num_gts = igt_sysfs_get_num_gt(i915); + stash_min = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + + /* Save curr min and max across GTs */ + for_each_sysfs_gt_dirfd(i91
[Intel-gfx] [PATCH i-g-t 4/4] HAX: tests/i915: Try out the SLPC IGT tests
Trying out for CI. Do not review. Signed-off-by: Vinay Belgaumkar --- tests/intel-ci/fast-feedback.testlist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist index d9fcb62d..653668dd 100644 --- a/tests/intel-ci/fast-feedback.testlist +++ b/tests/intel-ci/fast-feedback.testlist @@ -139,6 +139,8 @@ igt@prime_self_import@basic-with_fd_dup igt@prime_self_import@basic-with_one_bo igt@prime_self_import@basic-with_one_bo_two_files igt@prime_self_import@basic-with_two_bos +igt@i915_pm_freq_api@freq-basic-api +igt@i915_pm_freq_api@freq-reset igt@prime_vgem@basic-fence-flip igt@prime_vgem@basic-fence-mmap igt@prime_vgem@basic-fence-read -- 2.38.1
[Intel-gfx] [PATCH i-g-t 2/4] lib: Make SLPC helper function per GT
Use default of 0 where GT id is not being used. Fixes: https://gitlab.freedesktop.org/drm/intel/-/issues/8308 v2: Add a helper for GT 0 (Ashutosh) v3: Additional review comments (Ashutosh) Signed-off-by: Vinay Belgaumkar Reviewed-by: Ashutosh Dixit --- lib/igt_pm.c | 34 +- lib/igt_pm.h | 3 ++- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/lib/igt_pm.c b/lib/igt_pm.c index 704acf7d..15a9cf81 100644 --- a/lib/igt_pm.c +++ b/lib/igt_pm.c @@ -1329,21 +1329,37 @@ void igt_pm_print_pci_card_runtime_status(void) } } -bool i915_is_slpc_enabled(int fd) +/** + * i915_is_slpc_enabled_gt: + * @drm_fd: DRM file descriptor + * @gt: GT id + * Check if SLPC is enabled on a GT + */ +bool i915_is_slpc_enabled_gt(int drm_fd, int gt) { - int debugfs_fd = igt_debugfs_dir(fd); + int debugfs_fd; char buf[4096] = {}; - int len; - igt_require(debugfs_fd != -1); + debugfs_fd = igt_debugfs_gt_open(drm_fd, gt, "uc/guc_slpc_info", O_RDONLY); + + /* if guc_slpc_info not present then return false */ + igt_require(debugfs_fd >= 0); + + read(debugfs_fd, buf, sizeof(buf)-1); - len = igt_debugfs_simple_read(debugfs_fd, "gt/uc/guc_slpc_info", buf, sizeof(buf)); close(debugfs_fd); - if (len < 0) - return false; - else - return strstr(buf, "SLPC state: running"); + return strstr(buf, "SLPC state: running"); +} + +/** + * i915_is_slpc_enabled: + * @drm_fd: DRM file descriptor + * Check if SLPC is enabled for the device + */ +bool i915_is_slpc_enabled(int drm_fd) +{ + return i915_is_slpc_enabled_gt(drm_fd, 0); } int igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev) diff --git a/lib/igt_pm.h b/lib/igt_pm.h index d0d6d673..448cf42d 100644 --- a/lib/igt_pm.h +++ b/lib/igt_pm.h @@ -84,7 +84,8 @@ void igt_pm_set_d3cold_allowed(struct igt_device_card *card, const char *val); void igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev); void igt_pm_restore_pci_card_runtime_pm(void); void igt_pm_print_pci_card_runtime_status(void); -bool i915_is_slpc_enabled(int fd); +bool i915_is_slpc_enabled_gt(int drm_fd, int gt); +bool i915_is_slpc_enabled(int drm_fd); int igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev); int igt_pm_get_runtime_usage(struct pci_device *pci_dev); -- 2.38.1
[Intel-gfx] [PATCH i-g-t 1/4] lib/debugfs: Add per GT debugfs helpers
These can be used to open per-gt debugfs files. Reviewed-by: Ashutosh Dixit Signed-off-by: Tvrtko Ursulin Signed-off-by: Vinay Belgaumkar --- lib/igt_debugfs.c | 60 +++ lib/igt_debugfs.h | 4 2 files changed, 64 insertions(+) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 05889bbe..afde2da6 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -217,6 +217,37 @@ int igt_debugfs_dir(int device) return open(path, O_RDONLY); } +/** + * igt_debugfs_gt_dir: + * @device: fd of the device + * @gt: GT instance number + * + * This opens the debugfs directory corresponding to device for use + * with igt_sysfs_get() and related functions. + * + * Returns: + * The directory fd, or -1 on failure. + */ +int igt_debugfs_gt_dir(int device, unsigned int gt) +{ + int debugfs_gt_dir_fd; + char path[PATH_MAX]; + char gtpath[16]; + int ret; + + if (!igt_debugfs_path(device, path, sizeof(path))) + return -1; + + ret = snprintf(gtpath, sizeof(gtpath), "/gt%u", gt); + igt_assert(ret < sizeof(gtpath)); + strncat(path, gtpath, sizeof(path) - 1); + + debugfs_gt_dir_fd = open(path, O_RDONLY); + igt_debug_on_f(debugfs_gt_dir_fd < 0, "path: %s\n", path); + + return debugfs_gt_dir_fd; +} + /** * igt_debugfs_connector_dir: * @device: fd of the device @@ -313,6 +344,35 @@ bool igt_debugfs_exists(int device, const char *filename, int mode) return false; } +/** + * igt_debugfs_gt_open: + * @device: open i915 drm fd + * @gt: gt instance number + * @filename: name of the debugfs node to open + * @mode: mode bits as used by open() + * + * This opens a debugfs file as a Unix file descriptor. The filename should be + * relative to the drm device's root, i.e. without "drm/$minor". + * + * Returns: + * The Unix file descriptor for the debugfs file or -1 if that didn't work out. + */ +int +igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, int mode) +{ + int dir, ret; + + dir = igt_debugfs_gt_dir(device, gt); + if (dir < 0) + return dir; + + ret = openat(dir, filename, mode); + + close(dir); + + return ret; +} + /** * igt_debugfs_simple_read: * @dir: fd of the debugfs directory diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 4824344a..3e6194ad 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -45,6 +45,10 @@ void __igt_debugfs_write(int fd, const char *filename, const char *buf, int size int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int size); bool igt_debugfs_search(int fd, const char *filename, const char *substring); +int igt_debugfs_gt_dir(int device, unsigned int gt); +int igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, + int mode); + /** * igt_debugfs_read: * @filename: name of the debugfs file -- 2.38.1
[Intel-gfx] [PATCH v7 i-g-t 0/4] tests/slpc: Add basic IGT test
Borrow some subtests from xe_guc_pc. Also add per GT SLPC debugfs helpers. v3: Review comments and add HAX patch v4: Modify the condition for skipping the test v5: Update the SLPC helper to per GT v6: Review comments (Ashutosh) v6: Review comments for SLPC debugfs patch (Ashutosh) v7: More comments (Ashutosh) Signed-off-by: Vinay Belgaumkar Reviewed-by: Ashutosh Dixit Vinay Belgaumkar (4): lib/debugfs: Add per GT debugfs helpers lib: Make SLPC helper function per GT i915_pm_freq_api: Add some basic SLPC igt tests HAX: tests/i915: Try out the SLPC IGT tests lib/igt_debugfs.c | 60 ++ lib/igt_debugfs.h | 4 + lib/igt_pm.c | 34 -- lib/igt_pm.h | 3 +- tests/i915/i915_pm_freq_api.c | 152 ++ tests/intel-ci/fast-feedback.testlist | 2 + tests/meson.build | 1 + 7 files changed, 246 insertions(+), 10 deletions(-) create mode 100644 tests/i915/i915_pm_freq_api.c -- 2.38.1
[Intel-gfx] [PATCH v5 2/2] drm/i915/selftest: Update the SLPC selftest
Use the new efficient frequency toggling interface. Also create a helper function to restore the frequencies after the test is done. Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/selftest_slpc.c | 42 ++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c index bd44ce73a504..248646b3d3e8 100644 --- a/drivers/gpu/drm/i915/gt/selftest_slpc.c +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c @@ -70,6 +70,31 @@ static int slpc_set_freq(struct intel_gt *gt, u32 freq) return err; } +static int slpc_restore_freq(struct intel_guc_slpc *slpc, u32 min, u32 max) +{ + int err; + + err = slpc_set_min_freq(slpc, min); + if (err) { + pr_err("Unable to restore min freq"); + return err; + } + + err = slpc_set_max_freq(slpc, max); + if (err) { + pr_err("Unable to restore min freq"); + return err; + } + + err = intel_guc_slpc_set_ignore_eff_freq(slpc, false); + if (err) { + pr_err("Unable to restore efficient freq"); + return err; + } + + return 0; +} + static u64 measure_power_at_freq(struct intel_gt *gt, int *freq, u64 *power) { int err = 0; @@ -268,8 +293,7 @@ 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. +* range of RPn-RP0. */ err = slpc_set_min_freq(slpc, slpc->min_freq); if (err) { @@ -277,6 +301,15 @@ static int run_test(struct intel_gt *gt, int test_type) return err; } + /* +* Turn off efficient frequency so RPn/RP0 ranges are obeyed. +*/ + err = intel_guc_slpc_set_ignore_eff_freq(slpc, true); + if (err) { + pr_err("Unable to turn off efficient freq!"); + return err; + } + intel_gt_pm_wait_for_idle(gt); intel_gt_pm_get(gt); for_each_engine(engine, gt, id) { @@ -358,9 +391,8 @@ static int run_test(struct intel_gt *gt, int test_type) break; } - /* Restore min/max frequencies */ - slpc_set_max_freq(slpc, slpc_max_freq); - slpc_set_min_freq(slpc, slpc_min_freq); + /* Restore min/max/efficient frequencies */ + err = slpc_restore_freq(slpc, slpc_min_freq, slpc_max_freq); if (igt_flush_test(gt->i915)) err = -EIO; -- 2.38.1
[Intel-gfx] [PATCH v5 1/2] drm/i915/guc/slpc: Provide sysfs for efficient freq
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 v5: Review comments (Andi) and add a separate patch for selftest updates Fixes: 95ccf312a1e4 ("drm/i915/guc/slpc: Allow SLPC to use efficient frequency") Signed-off-by: Vinay Belgaumkar Reviewed-by: Rodrigo Vivi Reviewed-by: Ashutosh Dixit --- drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 35 + drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 38 +-- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 1 + 4 files changed, 64 insertions(+), 11 deletions(-) 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 = >->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 = >->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(>->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/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 026d73855f36..56dbba1ef668 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,29 @@ 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; + + 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", +
[Intel-gfx] [PATCH] drm/i915/guc/slpc: Provide sysfs for efficient freq
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 Reviewed-by: Rodrigo Vivi Reviewed-by: Ashutosh Dixit --- 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(-) 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 = >->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 = >->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(>->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_
[Intel-gfx] [PATCH v3] drm/i915/guc/slpc: Provide sysfs for efficient freq
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: Fix compile error Fixes: 95ccf312a1e4 ("drm/i915/guc/slpc: Allow SLPC to use efficient frequency") Signed-off-by: Vinay Belgaumkar Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 35 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 43 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 1 + 4 files changed, 69 insertions(+), 11 deletions(-) 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..7496de5be580 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 = >->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 = >->uc.guc.slpc; + int err; + uint32_t 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(>->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/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 026d73855f36..5668f00f02e6 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,34 @@ 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; + + /* Need a lock now since waitboost can be modifying min as well */ + 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); + if (ret) { + guc_probe_error(slpc_to_guc(slpc), "Failed to set efficient freq(%d): %pe\n", + val, ERR_PTR(ret)); + goto out; +
[Intel-gfx] [PATCH v2] drm/i915/guc/slpc: Provide sysfs for efficient freq
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) Signed-off-by: Vinay Belgaumkar Fixes: 95ccf312a1e4 ("drm/i915/guc/slpc: Allow SLPC to use efficient frequency") --- drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 35 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 44 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 1 + 4 files changed, 70 insertions(+), 11 deletions(-) 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..7496de5be580 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 = >->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 = >->uc.guc.slpc; + int err; + uint32_t 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(>->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/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 026d73855f36..f214a9d533f7 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,34 @@ 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; + + /* Need a lock now since waitboost can be modifying min as well */ + 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); + if (ret) { + guc_probe_error(slpc_to_guc(slpc), "Failed to set efficient freq(%d): %pe\n", + val, ERR_PTR(ret)); + goto out; + } + + slp
[Intel-gfx] [PATCH i-g-t 4/4] HAX: tests/i915: Try out the SLPC IGT tests
Trying out for CI. Do not review. Signed-off-by: Vinay Belgaumkar --- tests/intel-ci/fast-feedback.testlist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist index d9fcb62d..653668dd 100644 --- a/tests/intel-ci/fast-feedback.testlist +++ b/tests/intel-ci/fast-feedback.testlist @@ -139,6 +139,8 @@ igt@prime_self_import@basic-with_fd_dup igt@prime_self_import@basic-with_one_bo igt@prime_self_import@basic-with_one_bo_two_files igt@prime_self_import@basic-with_two_bos +igt@i915_pm_freq_api@freq-basic-api +igt@i915_pm_freq_api@freq-reset igt@prime_vgem@basic-fence-flip igt@prime_vgem@basic-fence-mmap igt@prime_vgem@basic-fence-read -- 2.38.1
[Intel-gfx] [PATCH i-g-t 3/4] i915_pm_freq_api: Add some basic SLPC igt tests
Validate basic api for GT freq control. Also test interaction with GT reset. We skip rps tests with SLPC enabled, this will re-introduce some coverage. SLPC selftests are already covering some other workload related scenarios. v2: Rename test (Rodrigo) v3: Review comments (Ashutosh) v4: Skip when SLPC is disabled. Check for enable_guc is not sufficient as kernel config may have it but the platform doesn't actually support it. v5: Use the updated SLPC helper Reviewed-by: Ashutosh Dixit Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 152 ++ tests/meson.build | 1 + 2 files changed, 153 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c new file mode 100644 index ..f0f4e3f9 --- /dev/null +++ b/tests/i915/i915_pm_freq_api.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmtest.h" +#include "i915/gem.h" +#include "igt_sysfs.h" +#include "igt.h" + +IGT_TEST_DESCRIPTION("Test SLPC freq API"); +/* + * Too many intermediate components and steps before freq is adjusted + * Specially if workload is under execution, so let's wait 100 ms. + */ +#define ACT_FREQ_LATENCY_US 10 + +static uint32_t get_freq(int dirfd, uint8_t id) +{ + uint32_t val; + + igt_assert(igt_sysfs_rps_scanf(dirfd, id, "%u", &val) == 1); + + return val; +} + +static int set_freq(int dirfd, uint8_t id, uint32_t val) +{ + return igt_sysfs_rps_printf(dirfd, id, "%u", val); +} + +static void test_freq_basic_api(int dirfd, int gt) +{ + uint32_t rpn, rp0, rpe; + + /* Save frequencies */ + rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); + rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0); + + /* +* Negative bound tests +* RPn is the floor +* RP0 is the ceiling +*/ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0 + 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0 + 1) < 0); + + /* Assert min requests are respected from rp0 to rpn */ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rp0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Assert max requests are respected from rpn to rp0 */ + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rp0); + +} + +static void test_reset(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + int fd; + + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + usleep(ACT_FREQ_LATENCY_US); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + close(fd); + + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); +} + +igt_main +{ + int i915 = -1; + uint32_t *stash_min, *stash_max; + + igt_fixture { + int num_gts, dirfd, gt; + + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + /* i915_pm_rps already covers execlist path */ + igt_skip_on_f(!i915_is_slpc_enabled(i915), + "This test is supported only with SLPC enabled\n"); + + num_gts = igt_sysfs_get_num_gt(i915); + stash_min = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + + /* Save curr min and max across GTs */ + for_each_sysfs_gt_dirfd(i91
[Intel-gfx] [PATCH i-g-t 2/4] lib: Make SLPC helper function per GT
Use default of 0 where GT id is not being used. v2: Add a helper for GT 0 (Ashutosh) Signed-off-by: Vinay Belgaumkar --- lib/igt_pm.c | 36 ++-- lib/igt_pm.h | 3 ++- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/lib/igt_pm.c b/lib/igt_pm.c index 704acf7d..8a30bb3b 100644 --- a/lib/igt_pm.c +++ b/lib/igt_pm.c @@ -1329,21 +1329,37 @@ void igt_pm_print_pci_card_runtime_status(void) } } -bool i915_is_slpc_enabled(int fd) +/** + * i915_is_slpc_enabled_gt: + * @drm_fd: DRM file descriptor + * @gt: GT id + * Check if SLPC is enabled on a GT + */ +bool i915_is_slpc_enabled_gt(int drm_fd, int gt) { - int debugfs_fd = igt_debugfs_dir(fd); - char buf[4096] = {}; - int len; + int debugfs_fd; + char buf[256] = {}; - igt_require(debugfs_fd != -1); + debugfs_fd = igt_debugfs_gt_open(drm_fd, gt, "uc/guc_slpc_info", O_RDONLY); + + /* if guc_slpc_info not present then return false */ + if (debugfs_fd < 0) + return false; + read(debugfs_fd, buf, sizeof(buf)-1); - len = igt_debugfs_simple_read(debugfs_fd, "gt/uc/guc_slpc_info", buf, sizeof(buf)); close(debugfs_fd); - if (len < 0) - return false; - else - return strstr(buf, "SLPC state: running"); + return strstr(buf, "SLPC state: running"); +} + +/** + * i915_is_slpc_enabled: + * @drm_fd: DRM file descriptor + * Check if SLPC is enabled on GT 0 + */ +bool i915_is_slpc_enabled(int drm_fd) +{ + return i915_is_slpc_enabled_gt(drm_fd, 0); } int igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev) diff --git a/lib/igt_pm.h b/lib/igt_pm.h index d0d6d673..448cf42d 100644 --- a/lib/igt_pm.h +++ b/lib/igt_pm.h @@ -84,7 +84,8 @@ void igt_pm_set_d3cold_allowed(struct igt_device_card *card, const char *val); void igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev); void igt_pm_restore_pci_card_runtime_pm(void); void igt_pm_print_pci_card_runtime_status(void); -bool i915_is_slpc_enabled(int fd); +bool i915_is_slpc_enabled_gt(int drm_fd, int gt); +bool i915_is_slpc_enabled(int drm_fd); int igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev); int igt_pm_get_runtime_usage(struct pci_device *pci_dev); -- 2.38.1
[Intel-gfx] [PATCH i-g-t 1/4] lib/debugfs: Add per GT debugfs helpers
These can be used to open per-gt debugfs files. Reviewed-by: Ashutosh Dixit Signed-off-by: Tvrtko Ursulin Signed-off-by: Vinay Belgaumkar --- lib/igt_debugfs.c | 60 +++ lib/igt_debugfs.h | 4 2 files changed, 64 insertions(+) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 05889bbe..afde2da6 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -217,6 +217,37 @@ int igt_debugfs_dir(int device) return open(path, O_RDONLY); } +/** + * igt_debugfs_gt_dir: + * @device: fd of the device + * @gt: GT instance number + * + * This opens the debugfs directory corresponding to device for use + * with igt_sysfs_get() and related functions. + * + * Returns: + * The directory fd, or -1 on failure. + */ +int igt_debugfs_gt_dir(int device, unsigned int gt) +{ + int debugfs_gt_dir_fd; + char path[PATH_MAX]; + char gtpath[16]; + int ret; + + if (!igt_debugfs_path(device, path, sizeof(path))) + return -1; + + ret = snprintf(gtpath, sizeof(gtpath), "/gt%u", gt); + igt_assert(ret < sizeof(gtpath)); + strncat(path, gtpath, sizeof(path) - 1); + + debugfs_gt_dir_fd = open(path, O_RDONLY); + igt_debug_on_f(debugfs_gt_dir_fd < 0, "path: %s\n", path); + + return debugfs_gt_dir_fd; +} + /** * igt_debugfs_connector_dir: * @device: fd of the device @@ -313,6 +344,35 @@ bool igt_debugfs_exists(int device, const char *filename, int mode) return false; } +/** + * igt_debugfs_gt_open: + * @device: open i915 drm fd + * @gt: gt instance number + * @filename: name of the debugfs node to open + * @mode: mode bits as used by open() + * + * This opens a debugfs file as a Unix file descriptor. The filename should be + * relative to the drm device's root, i.e. without "drm/$minor". + * + * Returns: + * The Unix file descriptor for the debugfs file or -1 if that didn't work out. + */ +int +igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, int mode) +{ + int dir, ret; + + dir = igt_debugfs_gt_dir(device, gt); + if (dir < 0) + return dir; + + ret = openat(dir, filename, mode); + + close(dir); + + return ret; +} + /** * igt_debugfs_simple_read: * @dir: fd of the debugfs directory diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 4824344a..3e6194ad 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -45,6 +45,10 @@ void __igt_debugfs_write(int fd, const char *filename, const char *buf, int size int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int size); bool igt_debugfs_search(int fd, const char *filename, const char *substring); +int igt_debugfs_gt_dir(int device, unsigned int gt); +int igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, + int mode); + /** * igt_debugfs_read: * @filename: name of the debugfs file -- 2.38.1
[Intel-gfx] [PATCH v6 i-g-t 0/4] tests/slpc: Add basic IGT test
Borrow some subtests from xe_guc_pc. Also add per GT debugfs helpers. v3: Review comments and add HAX patch v4: Modify the condition for skipping the test v5: Update the SLPC helper to per GT v6: Review comments (Ashutosh) Signed-off-by: Vinay Belgaumkar Vinay Belgaumkar (4): lib/debugfs: Add per GT debugfs helpers lib: Make SLPC helper function per GT i915_pm_freq_api: Add some basic SLPC igt tests HAX: tests/i915: Try out the SLPC IGT tests lib/igt_debugfs.c | 60 ++ lib/igt_debugfs.h | 4 + lib/igt_pm.c | 36 -- lib/igt_pm.h | 3 +- tests/i915/i915_pm_freq_api.c | 152 ++ tests/intel-ci/fast-feedback.testlist | 2 + tests/meson.build | 1 + 7 files changed, 247 insertions(+), 11 deletions(-) create mode 100644 tests/i915/i915_pm_freq_api.c -- 2.38.1
[Intel-gfx] [PATCH i-g-t 4/4] HAX: tests/i915: Try out the SLPC IGT tests
Trying out for CI. Do not review. Signed-off-by: Vinay Belgaumkar --- tests/intel-ci/fast-feedback.testlist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist index d9fcb62d..653668dd 100644 --- a/tests/intel-ci/fast-feedback.testlist +++ b/tests/intel-ci/fast-feedback.testlist @@ -139,6 +139,8 @@ igt@prime_self_import@basic-with_fd_dup igt@prime_self_import@basic-with_one_bo igt@prime_self_import@basic-with_one_bo_two_files igt@prime_self_import@basic-with_two_bos +igt@i915_pm_freq_api@freq-basic-api +igt@i915_pm_freq_api@freq-reset igt@prime_vgem@basic-fence-flip igt@prime_vgem@basic-fence-mmap igt@prime_vgem@basic-fence-read -- 2.38.1
[Intel-gfx] [PATCH i-g-t 3/4] i915_pm_freq_api: Add some basic SLPC igt tests
Validate basic api for GT freq control. Also test interaction with GT reset. We skip rps tests with SLPC enabled, this will re-introduce some coverage. SLPC selftests are already covering some other workload related scenarios. v2: Rename test (Rodrigo) v3: Review comments (Ashutosh) v4: Skip when SLPC is disabled. Check for enable_guc is not sufficient as kernel config may have it but the platform doesn't actually support it. v5: Use the updated SLPC helper Reviewed-by: Ashutosh Dixit Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 152 ++ tests/meson.build | 1 + 2 files changed, 153 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c new file mode 100644 index ..d42b3a2b --- /dev/null +++ b/tests/i915/i915_pm_freq_api.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmtest.h" +#include "i915/gem.h" +#include "igt_sysfs.h" +#include "igt.h" + +IGT_TEST_DESCRIPTION("Test SLPC freq API"); +/* + * Too many intermediate components and steps before freq is adjusted + * Specially if workload is under execution, so let's wait 100 ms. + */ +#define ACT_FREQ_LATENCY_US 10 + +static uint32_t get_freq(int dirfd, uint8_t id) +{ + uint32_t val; + + igt_assert(igt_sysfs_rps_scanf(dirfd, id, "%u", &val) == 1); + + return val; +} + +static int set_freq(int dirfd, uint8_t id, uint32_t val) +{ + return igt_sysfs_rps_printf(dirfd, id, "%u", val); +} + +static void test_freq_basic_api(int dirfd, int gt) +{ + uint32_t rpn, rp0, rpe; + + /* Save frequencies */ + rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); + rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0); + + /* +* Negative bound tests +* RPn is the floor +* RP0 is the ceiling +*/ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0 + 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0 + 1) < 0); + + /* Assert min requests are respected from rp0 to rpn */ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rp0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Assert max requests are respected from rpn to rp0 */ + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rp0); + +} + +static void test_reset(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + int fd; + + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + usleep(ACT_FREQ_LATENCY_US); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + close(fd); + + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); +} + +igt_main +{ + int i915 = -1; + uint32_t *stash_min, *stash_max; + + igt_fixture { + int num_gts, dirfd, gt; + + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + /* i915_pm_rps already covers execlist path */ + igt_skip_on_f(!i915_is_slpc_enabled(i915, 0), + "This test is supported only with SLPC enabled\n"); + + num_gts = igt_sysfs_get_num_gt(i915); + stash_min = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + + /* Save curr min and max across GTs */ + for_each_sysfs_gt_dirfd(i91
[Intel-gfx] [PATCH i-g-t 2/4] lib: Make SLPC helper function per GT
Use default of 0 where GT id is not being used. Signed-off-by: Vinay Belgaumkar --- lib/igt_pm.c | 20 ++-- lib/igt_pm.h | 2 +- tests/i915/i915_pm_rps.c | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/igt_pm.c b/lib/igt_pm.c index 704acf7d..8ca7c181 100644 --- a/lib/igt_pm.c +++ b/lib/igt_pm.c @@ -1329,21 +1329,21 @@ void igt_pm_print_pci_card_runtime_status(void) } } -bool i915_is_slpc_enabled(int fd) +bool i915_is_slpc_enabled(int drm_fd, int gt) { - int debugfs_fd = igt_debugfs_dir(fd); - char buf[4096] = {}; - int len; + int debugfs_fd; + char buf[256] = {}; + + debugfs_fd = igt_debugfs_gt_open(drm_fd, gt, "uc/guc_slpc_info", O_RDONLY); - igt_require(debugfs_fd != -1); + /* if guc_slpc_info not present then return false */ + if (debugfs_fd < 0) + return false; + read(debugfs_fd, buf, sizeof(buf)-1); - len = igt_debugfs_simple_read(debugfs_fd, "gt/uc/guc_slpc_info", buf, sizeof(buf)); close(debugfs_fd); - if (len < 0) - return false; - else - return strstr(buf, "SLPC state: running"); + return strstr(buf, "SLPC state: running"); } int igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev) diff --git a/lib/igt_pm.h b/lib/igt_pm.h index d0d6d673..1b054dce 100644 --- a/lib/igt_pm.h +++ b/lib/igt_pm.h @@ -84,7 +84,7 @@ void igt_pm_set_d3cold_allowed(struct igt_device_card *card, const char *val); void igt_pm_setup_pci_card_runtime_pm(struct pci_device *pci_dev); void igt_pm_restore_pci_card_runtime_pm(void); void igt_pm_print_pci_card_runtime_status(void); -bool i915_is_slpc_enabled(int fd); +bool i915_is_slpc_enabled(int fd, int gt); int igt_pm_get_runtime_suspended_time(struct pci_device *pci_dev); int igt_pm_get_runtime_usage(struct pci_device *pci_dev); diff --git a/tests/i915/i915_pm_rps.c b/tests/i915/i915_pm_rps.c index d4ee2d58..85dae449 100644 --- a/tests/i915/i915_pm_rps.c +++ b/tests/i915/i915_pm_rps.c @@ -916,21 +916,21 @@ igt_main } igt_subtest("basic-api") { - igt_skip_on_f(i915_is_slpc_enabled(drm_fd), + igt_skip_on_f(i915_is_slpc_enabled(drm_fd, 0), "This subtest is not supported when SLPC is enabled\n"); min_max_config(basic_check, false); } /* Verify the constraints, check if we can reach idle */ igt_subtest("min-max-config-idle") { - igt_skip_on_f(i915_is_slpc_enabled(drm_fd), + igt_skip_on_f(i915_is_slpc_enabled(drm_fd, 0), "This subtest is not supported when SLPC is enabled\n"); min_max_config(idle_check, true); } /* Verify the constraints with high load, check if we can reach max */ igt_subtest("min-max-config-loaded") { - igt_skip_on_f(i915_is_slpc_enabled(drm_fd), + igt_skip_on_f(i915_is_slpc_enabled(drm_fd, 0), "This subtest is not supported when SLPC is enabled\n"); load_helper_run(HIGH); min_max_config(loaded_check, false); -- 2.38.1
[Intel-gfx] [PATCH i-g-t 1/4] lib/debugfs: Add per GT debugfs helpers
These can be used to open per-gt debugfs files. Reviewed-by: Ashutosh Dixit Signed-off-by: Tvrtko Ursulin Signed-off-by: Vinay Belgaumkar --- lib/igt_debugfs.c | 60 +++ lib/igt_debugfs.h | 4 2 files changed, 64 insertions(+) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 05889bbe..afde2da6 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -217,6 +217,37 @@ int igt_debugfs_dir(int device) return open(path, O_RDONLY); } +/** + * igt_debugfs_gt_dir: + * @device: fd of the device + * @gt: GT instance number + * + * This opens the debugfs directory corresponding to device for use + * with igt_sysfs_get() and related functions. + * + * Returns: + * The directory fd, or -1 on failure. + */ +int igt_debugfs_gt_dir(int device, unsigned int gt) +{ + int debugfs_gt_dir_fd; + char path[PATH_MAX]; + char gtpath[16]; + int ret; + + if (!igt_debugfs_path(device, path, sizeof(path))) + return -1; + + ret = snprintf(gtpath, sizeof(gtpath), "/gt%u", gt); + igt_assert(ret < sizeof(gtpath)); + strncat(path, gtpath, sizeof(path) - 1); + + debugfs_gt_dir_fd = open(path, O_RDONLY); + igt_debug_on_f(debugfs_gt_dir_fd < 0, "path: %s\n", path); + + return debugfs_gt_dir_fd; +} + /** * igt_debugfs_connector_dir: * @device: fd of the device @@ -313,6 +344,35 @@ bool igt_debugfs_exists(int device, const char *filename, int mode) return false; } +/** + * igt_debugfs_gt_open: + * @device: open i915 drm fd + * @gt: gt instance number + * @filename: name of the debugfs node to open + * @mode: mode bits as used by open() + * + * This opens a debugfs file as a Unix file descriptor. The filename should be + * relative to the drm device's root, i.e. without "drm/$minor". + * + * Returns: + * The Unix file descriptor for the debugfs file or -1 if that didn't work out. + */ +int +igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, int mode) +{ + int dir, ret; + + dir = igt_debugfs_gt_dir(device, gt); + if (dir < 0) + return dir; + + ret = openat(dir, filename, mode); + + close(dir); + + return ret; +} + /** * igt_debugfs_simple_read: * @dir: fd of the debugfs directory diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 4824344a..3e6194ad 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -45,6 +45,10 @@ void __igt_debugfs_write(int fd, const char *filename, const char *buf, int size int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int size); bool igt_debugfs_search(int fd, const char *filename, const char *substring); +int igt_debugfs_gt_dir(int device, unsigned int gt); +int igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, + int mode); + /** * igt_debugfs_read: * @filename: name of the debugfs file -- 2.38.1
[Intel-gfx] [PATCH v5 i-g-t 0/4] tests/slpc: Add basic IGT test
Borrow some subtests from xe_guc_pc. Also add per GT debugfs helpers. v3: Review comments and add HAX patch v4: Modify the condition for skipping the test v5: Update the SLPC helper to per GT Signed-off-by: Vinay Belgaumkar Vinay Belgaumkar (4): lib/debugfs: Add per GT debugfs helpers lib: Make SLPC helper function per GT i915_pm_freq_api: Add some basic SLPC igt tests HAX: tests/i915: Try out the SLPC IGT tests lib/igt_debugfs.c | 60 ++ lib/igt_debugfs.h | 4 + lib/igt_pm.c | 20 ++-- lib/igt_pm.h | 2 +- tests/i915/i915_pm_freq_api.c | 152 ++ tests/i915/i915_pm_rps.c | 6 +- tests/intel-ci/fast-feedback.testlist | 2 + tests/meson.build | 1 + 8 files changed, 233 insertions(+), 14 deletions(-) create mode 100644 tests/i915/i915_pm_freq_api.c -- 2.38.1
[Intel-gfx] [PATCH i-g-t 3/3] HAX: tests/i915: Try out the SLPC IGT tests
Trying out for CI. Do not review. Signed-off-by: Vinay Belgaumkar --- tests/intel-ci/fast-feedback.testlist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist index d9fcb62d..653668dd 100644 --- a/tests/intel-ci/fast-feedback.testlist +++ b/tests/intel-ci/fast-feedback.testlist @@ -139,6 +139,8 @@ igt@prime_self_import@basic-with_fd_dup igt@prime_self_import@basic-with_one_bo igt@prime_self_import@basic-with_one_bo_two_files igt@prime_self_import@basic-with_two_bos +igt@i915_pm_freq_api@freq-basic-api +igt@i915_pm_freq_api@freq-reset igt@prime_vgem@basic-fence-flip igt@prime_vgem@basic-fence-mmap igt@prime_vgem@basic-fence-read -- 2.38.1
[Intel-gfx] [PATCH i-g-t 2/3] i915_pm_freq_api: Add some basic SLPC igt tests
Validate basic api for GT freq control. Also test interaction with GT reset. We skip rps tests with SLPC enabled, this will re-introduce some coverage. SLPC selftests are already covering some other workload related scenarios. v2: Rename test (Rodrigo) v3: Review comments (Ashutosh) v4: Skip when SLPC is disabled. Check for enable_guc is not sufficient as kernel config may have it but the platform doesn't actually support it. Reviewed-by: Ashutosh Dixit Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 152 ++ tests/meson.build | 1 + 2 files changed, 153 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c new file mode 100644 index ..f0f4e3f9 --- /dev/null +++ b/tests/i915/i915_pm_freq_api.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmtest.h" +#include "i915/gem.h" +#include "igt_sysfs.h" +#include "igt.h" + +IGT_TEST_DESCRIPTION("Test SLPC freq API"); +/* + * Too many intermediate components and steps before freq is adjusted + * Specially if workload is under execution, so let's wait 100 ms. + */ +#define ACT_FREQ_LATENCY_US 10 + +static uint32_t get_freq(int dirfd, uint8_t id) +{ + uint32_t val; + + igt_assert(igt_sysfs_rps_scanf(dirfd, id, "%u", &val) == 1); + + return val; +} + +static int set_freq(int dirfd, uint8_t id, uint32_t val) +{ + return igt_sysfs_rps_printf(dirfd, id, "%u", val); +} + +static void test_freq_basic_api(int dirfd, int gt) +{ + uint32_t rpn, rp0, rpe; + + /* Save frequencies */ + rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); + rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0); + + /* +* Negative bound tests +* RPn is the floor +* RP0 is the ceiling +*/ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0 + 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0 + 1) < 0); + + /* Assert min requests are respected from rp0 to rpn */ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rp0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Assert max requests are respected from rpn to rp0 */ + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rp0); + +} + +static void test_reset(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + int fd; + + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + usleep(ACT_FREQ_LATENCY_US); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + close(fd); + + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); +} + +igt_main +{ + int i915 = -1; + uint32_t *stash_min, *stash_max; + + igt_fixture { + int num_gts, dirfd, gt; + + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + /* i915_pm_rps already covers execlist path */ + igt_skip_on_f(!i915_is_slpc_enabled(i915), + "This test is supported only with SLPC enabled\n"); + + num_gts = igt_sysfs_get_num_gt(i915); + stash_min = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + + /* Save curr min and max across GTs */ + for_each_sysfs_gt_dirfd(i915, dirfd, gt) { + stash_min[gt] = get_freq(dirf
[Intel-gfx] [PATCH i-g-t 1/3] lib/debugfs: Add per GT debugfs helpers
These can be used to open per-gt debugfs files. Reviewed-by: Ashutosh Dixit Signed-off-by: Tvrtko Ursulin Signed-off-by: Vinay Belgaumkar --- lib/igt_debugfs.c | 60 +++ lib/igt_debugfs.h | 4 2 files changed, 64 insertions(+) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 05889bbe..afde2da6 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -217,6 +217,37 @@ int igt_debugfs_dir(int device) return open(path, O_RDONLY); } +/** + * igt_debugfs_gt_dir: + * @device: fd of the device + * @gt: GT instance number + * + * This opens the debugfs directory corresponding to device for use + * with igt_sysfs_get() and related functions. + * + * Returns: + * The directory fd, or -1 on failure. + */ +int igt_debugfs_gt_dir(int device, unsigned int gt) +{ + int debugfs_gt_dir_fd; + char path[PATH_MAX]; + char gtpath[16]; + int ret; + + if (!igt_debugfs_path(device, path, sizeof(path))) + return -1; + + ret = snprintf(gtpath, sizeof(gtpath), "/gt%u", gt); + igt_assert(ret < sizeof(gtpath)); + strncat(path, gtpath, sizeof(path) - 1); + + debugfs_gt_dir_fd = open(path, O_RDONLY); + igt_debug_on_f(debugfs_gt_dir_fd < 0, "path: %s\n", path); + + return debugfs_gt_dir_fd; +} + /** * igt_debugfs_connector_dir: * @device: fd of the device @@ -313,6 +344,35 @@ bool igt_debugfs_exists(int device, const char *filename, int mode) return false; } +/** + * igt_debugfs_gt_open: + * @device: open i915 drm fd + * @gt: gt instance number + * @filename: name of the debugfs node to open + * @mode: mode bits as used by open() + * + * This opens a debugfs file as a Unix file descriptor. The filename should be + * relative to the drm device's root, i.e. without "drm/$minor". + * + * Returns: + * The Unix file descriptor for the debugfs file or -1 if that didn't work out. + */ +int +igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, int mode) +{ + int dir, ret; + + dir = igt_debugfs_gt_dir(device, gt); + if (dir < 0) + return dir; + + ret = openat(dir, filename, mode); + + close(dir); + + return ret; +} + /** * igt_debugfs_simple_read: * @dir: fd of the debugfs directory diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 4824344a..3e6194ad 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -45,6 +45,10 @@ void __igt_debugfs_write(int fd, const char *filename, const char *buf, int size int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int size); bool igt_debugfs_search(int fd, const char *filename, const char *substring); +int igt_debugfs_gt_dir(int device, unsigned int gt); +int igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, + int mode); + /** * igt_debugfs_read: * @filename: name of the debugfs file -- 2.38.1
[Intel-gfx] [PATCH v4 i-g-t 0/3] tests/slpc: Add basic IGT test
Borrow some subtests from xe_guc_pc. Also add per GT debugfs helpers. v3: Review comments and add HAX patch v4: Modify the condition for skipping the test Signed-off-by: Vinay Belgaumkar Vinay Belgaumkar (3): lib/debugfs: Add per GT debugfs helpers i915_pm_freq_api: Add some basic SLPC igt tests HAX: tests/i915: Try out the SLPC IGT tests lib/igt_debugfs.c | 60 ++ lib/igt_debugfs.h | 4 + tests/i915/i915_pm_freq_api.c | 152 ++ tests/intel-ci/fast-feedback.testlist | 2 + tests/meson.build | 1 + 5 files changed, 219 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c -- 2.38.1
[Intel-gfx] [PATCH i-g-t 3/3] HAX: tests/i915: Try out the SLPC IGT tests
Trying out for CI. Do not review. Signed-off-by: Vinay Belgaumkar --- tests/intel-ci/fast-feedback.testlist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist index d9fcb62d..653668dd 100644 --- a/tests/intel-ci/fast-feedback.testlist +++ b/tests/intel-ci/fast-feedback.testlist @@ -139,6 +139,8 @@ igt@prime_self_import@basic-with_fd_dup igt@prime_self_import@basic-with_one_bo igt@prime_self_import@basic-with_one_bo_two_files igt@prime_self_import@basic-with_two_bos +igt@i915_pm_freq_api@freq-basic-api +igt@i915_pm_freq_api@freq-reset igt@prime_vgem@basic-fence-flip igt@prime_vgem@basic-fence-mmap igt@prime_vgem@basic-fence-read -- 2.38.1
[Intel-gfx] [PATCH i-g-t 2/3] i915_pm_freq_api: Add some basic SLPC igt tests
Validate basic api for GT freq control. Also test interaction with GT reset. We skip rps tests with SLPC enabled, this will re-introduce some coverage. SLPC selftests are already covering some other workload related scenarios. v2: Rename test (Rodrigo) v3: Review comments (Ashutosh) Reviewed-by: Ashutosh Dixit Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 151 ++ tests/meson.build | 1 + 2 files changed, 152 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c new file mode 100644 index ..bfa90005 --- /dev/null +++ b/tests/i915/i915_pm_freq_api.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmtest.h" +#include "i915/gem.h" +#include "igt_sysfs.h" +#include "igt.h" + +IGT_TEST_DESCRIPTION("Test SLPC freq API"); +/* + * Too many intermediate components and steps before freq is adjusted + * Specially if workload is under execution, so let's wait 100 ms. + */ +#define ACT_FREQ_LATENCY_US 10 + +static uint32_t get_freq(int dirfd, uint8_t id) +{ + uint32_t val; + + igt_assert(igt_sysfs_rps_scanf(dirfd, id, "%u", &val) == 1); + + return val; +} + +static int set_freq(int dirfd, uint8_t id, uint32_t val) +{ + return igt_sysfs_rps_printf(dirfd, id, "%u", val); +} + +static void test_freq_basic_api(int dirfd, int gt) +{ + uint32_t rpn, rp0, rpe; + + /* Save frequencies */ + rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); + rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0); + + /* +* Negative bound tests +* RPn is the floor +* RP0 is the ceiling +*/ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0 + 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0 + 1) < 0); + + /* Assert min requests are respected from rp0 to rpn */ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rp0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Assert max requests are respected from rpn to rp0 */ + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rp0); + +} + +static void test_reset(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + int fd; + + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + usleep(ACT_FREQ_LATENCY_US); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + close(fd); + + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); +} + +igt_main +{ + int i915 = -1; + uint32_t *stash_min, *stash_max; + + igt_fixture { + int num_gts, dirfd, gt; + + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + /* i915_pm_rps already covers execlist path */ + igt_require(gem_using_guc_submission(i915)); + + num_gts = igt_sysfs_get_num_gt(i915); + stash_min = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + + /* Save curr min and max across GTs */ + for_each_sysfs_gt_dirfd(i915, dirfd, gt) { + stash_min[gt] = get_freq(dirfd, RPS_MIN_FREQ_MHZ); + stash_max[gt] = get_freq(dirfd, RPS_MAX_FREQ_MHZ); + } + } + + igt_describe("Test basic API for controlling min/max GT frequency"); + igt_subtest_with_dyn
[Intel-gfx] [PATCH i-g-t 1/3] lib/debugfs: Add per GT debugfs helpers
These can be used to open per-gt debugfs files. Reviewed-by: Ashutosh Dixit Signed-off-by: Tvrtko Ursulin Signed-off-by: Vinay Belgaumkar --- lib/igt_debugfs.c | 60 +++ lib/igt_debugfs.h | 4 2 files changed, 64 insertions(+) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 05889bbe..afde2da6 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -217,6 +217,37 @@ int igt_debugfs_dir(int device) return open(path, O_RDONLY); } +/** + * igt_debugfs_gt_dir: + * @device: fd of the device + * @gt: GT instance number + * + * This opens the debugfs directory corresponding to device for use + * with igt_sysfs_get() and related functions. + * + * Returns: + * The directory fd, or -1 on failure. + */ +int igt_debugfs_gt_dir(int device, unsigned int gt) +{ + int debugfs_gt_dir_fd; + char path[PATH_MAX]; + char gtpath[16]; + int ret; + + if (!igt_debugfs_path(device, path, sizeof(path))) + return -1; + + ret = snprintf(gtpath, sizeof(gtpath), "/gt%u", gt); + igt_assert(ret < sizeof(gtpath)); + strncat(path, gtpath, sizeof(path) - 1); + + debugfs_gt_dir_fd = open(path, O_RDONLY); + igt_debug_on_f(debugfs_gt_dir_fd < 0, "path: %s\n", path); + + return debugfs_gt_dir_fd; +} + /** * igt_debugfs_connector_dir: * @device: fd of the device @@ -313,6 +344,35 @@ bool igt_debugfs_exists(int device, const char *filename, int mode) return false; } +/** + * igt_debugfs_gt_open: + * @device: open i915 drm fd + * @gt: gt instance number + * @filename: name of the debugfs node to open + * @mode: mode bits as used by open() + * + * This opens a debugfs file as a Unix file descriptor. The filename should be + * relative to the drm device's root, i.e. without "drm/$minor". + * + * Returns: + * The Unix file descriptor for the debugfs file or -1 if that didn't work out. + */ +int +igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, int mode) +{ + int dir, ret; + + dir = igt_debugfs_gt_dir(device, gt); + if (dir < 0) + return dir; + + ret = openat(dir, filename, mode); + + close(dir); + + return ret; +} + /** * igt_debugfs_simple_read: * @dir: fd of the debugfs directory diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 4824344a..3e6194ad 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -45,6 +45,10 @@ void __igt_debugfs_write(int fd, const char *filename, const char *buf, int size int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int size); bool igt_debugfs_search(int fd, const char *filename, const char *substring); +int igt_debugfs_gt_dir(int device, unsigned int gt); +int igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, + int mode); + /** * igt_debugfs_read: * @filename: name of the debugfs file -- 2.38.1
[Intel-gfx] [PATCH i-g-t v3 0/3] tests/slpc: Add basic IGT test
Borrow some subtests from xe_guc_pc. Also add per GT debugfs helpers. v3: Review comments and add HAX patch Signed-off-by: Vinay Belgaumkar Vinay Belgaumkar (3): lib/debugfs: Add per GT debugfs helpers i915_pm_freq_api: Add some basic SLPC igt tests HAX: tests/i915: Try out the SLPC IGT tests lib/igt_debugfs.c | 60 ++ lib/igt_debugfs.h | 4 + tests/i915/i915_pm_freq_api.c | 151 ++ tests/intel-ci/fast-feedback.testlist | 2 + tests/meson.build | 1 + 5 files changed, 218 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c -- 2.38.1
[Intel-gfx] [PATCH] i915/guc/slpc: Provide sysfs for efficient freq
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. Another way to disable it is to set min frequency below the efficient level. Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 35 + drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 49 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 1 + .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 1 + 4 files changed, 75 insertions(+), 11 deletions(-) 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..7496de5be580 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 = >->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 = >->uc.guc.slpc; + int err; + uint32_t 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(>->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/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 026d73855f36..eaa73c1fba6d 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,34 @@ 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; + + /* Need a lock now since waitboost can be modifying min as well */ + 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); + 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. *
[Intel-gfx] [PATCH i-g-t 2/2] i915_pm_freq_api: Add some basic SLPC igt tests
Validate basic api for GT freq control. Also test interaction with GT reset. We skip rps tests with SLPC enabled, this will re-introduce some coverage. SLPC selftests are already covering some other workload related scenarios. v2: Rename test (Rodrigo) Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_freq_api.c | 151 ++ tests/meson.build | 1 + 2 files changed, 152 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c diff --git a/tests/i915/i915_pm_freq_api.c b/tests/i915/i915_pm_freq_api.c new file mode 100644 index ..f1027d1c --- /dev/null +++ b/tests/i915/i915_pm_freq_api.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmtest.h" +#include "i915/gem.h" +#include "igt_sysfs.h" +#include "igt.h" + +IGT_TEST_DESCRIPTION("Test SLPC freq API"); +/* + * Too many intermediate components and steps before freq is adjusted + * Specially if workload is under execution, so let's wait 100 ms. + */ +#define ACT_FREQ_LATENCY_US 10 + +static uint32_t get_freq(int dirfd, uint8_t id) +{ + uint32_t val; + + igt_require(igt_sysfs_rps_scanf(dirfd, id, "%u", &val) == 1); + + return val; +} + +static int set_freq(int dirfd, uint8_t id, uint32_t val) +{ + return igt_sysfs_rps_printf(dirfd, id, "%u", val); +} + +static void test_freq_basic_api(int dirfd, int gt) +{ + uint32_t rpn, rp0, rpe; + + /* Save frequencies */ + rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); + rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0); + + /* +* Negative bound tests +* RPn is the floor +* RP0 is the ceiling +*/ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0 + 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0 + 1) < 0); + + /* Assert min requests are respected from rp0 to rpn */ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rp0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Assert max requests are respected from rpn to rp0 */ + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rp0); + +} + +static void test_reset(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + int fd; + + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + usleep(ACT_FREQ_LATENCY_US); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + close(fd); + + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); +} + +igt_main +{ + int i915 = -1; + uint32_t *stash_min, *stash_max; + + igt_fixture { + int num_gts, dirfd, gt; + + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + /* i915_pm_rps already covers execlist path */ + igt_require(gem_using_guc_submission(i915)); + + num_gts = igt_sysfs_get_num_gt(i915); + stash_min = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + + /* Save curr min and max across GTs */ + for_each_sysfs_gt_dirfd(i915, dirfd, gt) { + stash_min[gt] = get_freq(dirfd, RPS_MIN_FREQ_MHZ); + stash_max[gt] = get_freq(dirfd, RPS_MAX_FREQ_MHZ); + } + } + + igt_describe("Test basic API for controlling min/max GT frequency"); + igt_subtest_with_dynamic_f("freq-basic-api") { + int dir
[Intel-gfx] [PATCH i-g-t 1/2] lib/debugfs: Add per GT debugfs helpers
These can be used to open per-gt debugfs files. Signed-off-by: Tvrtko Ursulin Signed-off-by: Vinay Belgaumkar --- lib/igt_debugfs.c | 60 +++ lib/igt_debugfs.h | 4 2 files changed, 64 insertions(+) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 05889bbe..afde2da6 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -217,6 +217,37 @@ int igt_debugfs_dir(int device) return open(path, O_RDONLY); } +/** + * igt_debugfs_gt_dir: + * @device: fd of the device + * @gt: GT instance number + * + * This opens the debugfs directory corresponding to device for use + * with igt_sysfs_get() and related functions. + * + * Returns: + * The directory fd, or -1 on failure. + */ +int igt_debugfs_gt_dir(int device, unsigned int gt) +{ + int debugfs_gt_dir_fd; + char path[PATH_MAX]; + char gtpath[16]; + int ret; + + if (!igt_debugfs_path(device, path, sizeof(path))) + return -1; + + ret = snprintf(gtpath, sizeof(gtpath), "/gt%u", gt); + igt_assert(ret < sizeof(gtpath)); + strncat(path, gtpath, sizeof(path) - 1); + + debugfs_gt_dir_fd = open(path, O_RDONLY); + igt_debug_on_f(debugfs_gt_dir_fd < 0, "path: %s\n", path); + + return debugfs_gt_dir_fd; +} + /** * igt_debugfs_connector_dir: * @device: fd of the device @@ -313,6 +344,35 @@ bool igt_debugfs_exists(int device, const char *filename, int mode) return false; } +/** + * igt_debugfs_gt_open: + * @device: open i915 drm fd + * @gt: gt instance number + * @filename: name of the debugfs node to open + * @mode: mode bits as used by open() + * + * This opens a debugfs file as a Unix file descriptor. The filename should be + * relative to the drm device's root, i.e. without "drm/$minor". + * + * Returns: + * The Unix file descriptor for the debugfs file or -1 if that didn't work out. + */ +int +igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, int mode) +{ + int dir, ret; + + dir = igt_debugfs_gt_dir(device, gt); + if (dir < 0) + return dir; + + ret = openat(dir, filename, mode); + + close(dir); + + return ret; +} + /** * igt_debugfs_simple_read: * @dir: fd of the debugfs directory diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 4824344a..3e6194ad 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -45,6 +45,10 @@ void __igt_debugfs_write(int fd, const char *filename, const char *buf, int size int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int size); bool igt_debugfs_search(int fd, const char *filename, const char *substring); +int igt_debugfs_gt_dir(int device, unsigned int gt); +int igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, + int mode); + /** * igt_debugfs_read: * @filename: name of the debugfs file -- 2.38.1
[Intel-gfx] [PATCH i-g-t 0/2] tests/slpc: Add basic IGT test
Borrow some subtests from xe_guc_pc. Also add per GT debugfs helpers. Signed-off-by: Vinay Belgaumkar Vinay Belgaumkar (2): lib/debugfs: Add per GT debugfs helpers i915_pm_freq_api: Add some basic SLPC igt tests lib/igt_debugfs.c | 60 ++ lib/igt_debugfs.h | 4 + tests/i915/i915_pm_freq_api.c | 151 ++ tests/meson.build | 1 + 4 files changed, 216 insertions(+) create mode 100644 tests/i915/i915_pm_freq_api.c -- 2.38.1
[Intel-gfx] [PATCH i-g-t] tests/xe_guc_pc: Restore max freq first
When min/max are both at RPn, restoring min back to 300 will not work. Max needs to be increased first. Also, add igt_assert() here, which would have caught the issue. Cc: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- tests/xe/xe_guc_pc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/xe/xe_guc_pc.c b/tests/xe/xe_guc_pc.c index 60c93288..43bf6f48 100644 --- a/tests/xe/xe_guc_pc.c +++ b/tests/xe/xe_guc_pc.c @@ -489,8 +489,8 @@ igt_main igt_fixture { xe_for_each_gt(fd, gt) { - set_freq(sysfs, gt, "min", stash_min); - set_freq(sysfs, gt, "max", stash_max); + igt_assert(set_freq(sysfs, gt, "max", stash_max) > 0); + igt_assert(set_freq(sysfs, gt, "min", stash_min) > 0); } close(sysfs); xe_device_put(fd); -- 2.38.1
[Intel-gfx] [PATCH i-g-t 1/2] lib/debugfs: Add per GT debugfs helpers
These can be used to open per-gt debugfs files. Signed-off-by: Tvrtko Ursulin Signed-off-by: Vinay Belgaumkar --- lib/igt_debugfs.c | 60 +++ lib/igt_debugfs.h | 4 2 files changed, 64 insertions(+) diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c index 05889bbe..afde2da6 100644 --- a/lib/igt_debugfs.c +++ b/lib/igt_debugfs.c @@ -217,6 +217,37 @@ int igt_debugfs_dir(int device) return open(path, O_RDONLY); } +/** + * igt_debugfs_gt_dir: + * @device: fd of the device + * @gt: GT instance number + * + * This opens the debugfs directory corresponding to device for use + * with igt_sysfs_get() and related functions. + * + * Returns: + * The directory fd, or -1 on failure. + */ +int igt_debugfs_gt_dir(int device, unsigned int gt) +{ + int debugfs_gt_dir_fd; + char path[PATH_MAX]; + char gtpath[16]; + int ret; + + if (!igt_debugfs_path(device, path, sizeof(path))) + return -1; + + ret = snprintf(gtpath, sizeof(gtpath), "/gt%u", gt); + igt_assert(ret < sizeof(gtpath)); + strncat(path, gtpath, sizeof(path) - 1); + + debugfs_gt_dir_fd = open(path, O_RDONLY); + igt_debug_on_f(debugfs_gt_dir_fd < 0, "path: %s\n", path); + + return debugfs_gt_dir_fd; +} + /** * igt_debugfs_connector_dir: * @device: fd of the device @@ -313,6 +344,35 @@ bool igt_debugfs_exists(int device, const char *filename, int mode) return false; } +/** + * igt_debugfs_gt_open: + * @device: open i915 drm fd + * @gt: gt instance number + * @filename: name of the debugfs node to open + * @mode: mode bits as used by open() + * + * This opens a debugfs file as a Unix file descriptor. The filename should be + * relative to the drm device's root, i.e. without "drm/$minor". + * + * Returns: + * The Unix file descriptor for the debugfs file or -1 if that didn't work out. + */ +int +igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, int mode) +{ + int dir, ret; + + dir = igt_debugfs_gt_dir(device, gt); + if (dir < 0) + return dir; + + ret = openat(dir, filename, mode); + + close(dir); + + return ret; +} + /** * igt_debugfs_simple_read: * @dir: fd of the debugfs directory diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h index 4824344a..3e6194ad 100644 --- a/lib/igt_debugfs.h +++ b/lib/igt_debugfs.h @@ -45,6 +45,10 @@ void __igt_debugfs_write(int fd, const char *filename, const char *buf, int size int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int size); bool igt_debugfs_search(int fd, const char *filename, const char *substring); +int igt_debugfs_gt_dir(int device, unsigned int gt); +int igt_debugfs_gt_open(int device, unsigned int gt, const char *filename, + int mode); + /** * igt_debugfs_read: * @filename: name of the debugfs file -- 2.38.1
[Intel-gfx] [PATCH i-g-t 2/2] i915_guc_pc: Add some basic SLPC igt tests
Use the xe_guc_pc test for i915 as well. Validate basic api for GT freq control. Also test interaction with GT reset. We skip rps tests with SLPC enabled, this will re-introduce some coverage. SLPC selftests are already covering some other workload related scenarios. Signed-off-by: Rodrigo Vivi Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_guc_pc.c | 151 +++ tests/meson.build| 1 + 2 files changed, 152 insertions(+) create mode 100644 tests/i915/i915_guc_pc.c diff --git a/tests/i915/i915_guc_pc.c b/tests/i915/i915_guc_pc.c new file mode 100644 index ..f9a0ed83 --- /dev/null +++ b/tests/i915/i915_guc_pc.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drmtest.h" +#include "i915/gem.h" +#include "igt_sysfs.h" +#include "igt.h" + +IGT_TEST_DESCRIPTION("Test GuC PM features like SLPC and its interactions"); +/* + * Too many intermediate components and steps before freq is adjusted + * Specially if workload is under execution, so let's wait 100 ms. + */ +#define ACT_FREQ_LATENCY_US 10 + +static uint32_t get_freq(int dirfd, uint8_t id) +{ + uint32_t val; + + igt_require(igt_sysfs_rps_scanf(dirfd, id, "%u", &val) == 1); + + return val; +} + +static int set_freq(int dirfd, uint8_t id, uint32_t val) +{ + return igt_sysfs_rps_printf(dirfd, id, "%u", val); +} + +static void test_freq_basic_api(int dirfd, int gt) +{ + uint32_t rpn, rp0, rpe; + + /* Save frequencies */ + rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + rp0 = get_freq(dirfd, RPS_RP0_FREQ_MHZ); + rpe = get_freq(dirfd, RPS_RP1_FREQ_MHZ); + igt_info("System min freq: %dMHz; max freq: %dMHz\n", rpn, rp0); + + /* +* Negative bound tests +* RPn is the floor +* RP0 is the ceiling +*/ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0 + 1) < 0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn - 1) < 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0 + 1) < 0); + + /* Assert min requests are respected from rp0 to rpn */ + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rp0); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Assert max requests are respected from rpn to rp0 */ + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpe) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpe); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rp0) > 0); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rp0); + +} + +static void test_reset(int i915, int dirfd, int gt) +{ + uint32_t rpn = get_freq(dirfd, RPS_RPn_FREQ_MHZ); + int fd; + + igt_assert(set_freq(dirfd, RPS_MIN_FREQ_MHZ, rpn) > 0); + igt_assert(set_freq(dirfd, RPS_MAX_FREQ_MHZ, rpn) > 0); + usleep(ACT_FREQ_LATENCY_US); + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + + /* Manually trigger a GT reset */ + fd = igt_debugfs_gt_open(i915, gt, "reset", O_WRONLY); + igt_require(fd >= 0); + igt_ignore_warn(write(fd, "1\n", 2)); + close(fd); + + igt_assert(get_freq(dirfd, RPS_MIN_FREQ_MHZ) == rpn); + igt_assert(get_freq(dirfd, RPS_MAX_FREQ_MHZ) == rpn); +} + +igt_main +{ + int i915 = -1; + uint32_t *stash_min, *stash_max; + + igt_fixture { + int num_gts, dirfd, gt; + + i915 = drm_open_driver(DRIVER_INTEL); + igt_require_gem(i915); + /* i915_pm_rps already covers execlist path */ + igt_require(gem_using_guc_submission(i915)); + + num_gts = igt_sysfs_get_num_gt(i915); + stash_min = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + stash_max = (uint32_t*)malloc(sizeof(uint32_t) * num_gts); + + /* Save curr min and max across GTs */ + for_each_sysfs_gt_dirfd(i915, dirfd, gt) { + stash_min[gt] = get_freq(dirfd, RPS_MIN_FREQ_MHZ); + stash_max[gt] = get_freq(dirfd, RPS_MAX_FREQ_MHZ); + } + } + + igt_describe("Test basic API for controlling min/max GT frequency"); + igt_subtest_with_dynamic_f(
[Intel-gfx] [PATCH i-g-t 0/2] tests/i915/slpc: Add basic IGT test
Borrow some subtests from xe_guc_pc. Also add per GT debugfs helpers. Signed-off-by: Vinay Belgaumkar Vinay Belgaumkar (2): lib/debugfs: Add per GT debugfs helpers i915_guc_pc: Add some basic SLPC igt tests lib/igt_debugfs.c| 60 lib/igt_debugfs.h| 4 ++ tests/i915/i915_guc_pc.c | 151 +++ tests/meson.build| 1 + 4 files changed, 216 insertions(+) create mode 100644 tests/i915/i915_guc_pc.c -- 2.38.1
[Intel-gfx] [PATCH] drm/i915: Fix format for perf_limit_reasons
Use hex format so that it is easier to decode. Fixes: fe5979665f64 ('Add perf_limit_reasons in debugfs') Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 83df4cd5e06c..80dbbef86b1d 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -580,7 +580,7 @@ static bool perf_limit_reasons_eval(void *data) } DEFINE_SIMPLE_ATTRIBUTE(perf_limit_reasons_fops, perf_limit_reasons_get, - perf_limit_reasons_clear, "%llu\n"); + perf_limit_reasons_clear, "0x%llx\n"); void intel_gt_pm_debugfs_register(struct intel_gt *gt, struct dentry *root) { -- 2.38.1
[Intel-gfx] [PATCH i-g-t] i915_pm_rps: Enable waitboost tests for SLPC
Waitboost is supported with SLPC. Re-enable the tests so we have coverage. Signed-off-by: Vinay Belgaumkar --- tests/i915/i915_pm_rps.c | 8 1 file changed, 8 deletions(-) diff --git a/tests/i915/i915_pm_rps.c b/tests/i915/i915_pm_rps.c index 4865ed1f..d4ee2d58 100644 --- a/tests/i915/i915_pm_rps.c +++ b/tests/i915/i915_pm_rps.c @@ -939,30 +939,22 @@ igt_main /* Checks if we achieve boost using gem_wait */ igt_subtest("waitboost") { - igt_skip_on_f(i915_is_slpc_enabled(drm_fd), - "This subtest is not supported when SLPC is enabled\n"); waitboost(drm_fd, false); } igt_describe("Check if the order of fences does not affect waitboosting"); igt_subtest("fence-order") { - igt_skip_on_f(i915_is_slpc_enabled(drm_fd), - "This subtest is not supported when SLPC is enabled\n"); fence_order(drm_fd); } igt_describe("Check if context reuse does not affect waitboosting"); igt_subtest("engine-order") { - igt_skip_on_f(i915_is_slpc_enabled(drm_fd), - "This subtest is not supported when SLPC is enabled\n"); engine_order(drm_fd); } /* Test boost frequency after GPU reset */ igt_subtest("reset") { igt_hang_t hang; - igt_skip_on_f(i915_is_slpc_enabled(drm_fd), - "This subtest is not supported when SLPC is enabled\n"); hang = igt_allow_hang(drm_fd, 0, 0); waitboost(drm_fd, true); igt_disallow_hang(drm_fd, hang); -- 2.38.1
[Intel-gfx] [PATCH i-g-t] gem_ctx_freq: Remove reference to non-existent sysfs entry
The entry for gt_idle_freq_mhz does not exist. Fixes: d1ea62b3f759 (igt: Add gem_ctx_freq to exercise requesting freq via sysfs) Cc: Umesh Nerlige Ramappa Signed-off-by: Vinay Belgaumkar --- tests/i915/gem_ctx_freq.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/i915/gem_ctx_freq.c b/tests/i915/gem_ctx_freq.c index a29fe68b..18e736c7 100644 --- a/tests/i915/gem_ctx_freq.c +++ b/tests/i915/gem_ctx_freq.c @@ -174,10 +174,8 @@ static void restore_sysfs_freq(int sig) { char buf[256]; - if (igt_sysfs_read(sysfs, "gt_RPn_freq_mhz", buf, sizeof(buf)) > 0) { - igt_sysfs_set(sysfs, "gt_idle_freq_mhz", buf); + if (igt_sysfs_read(sysfs, "gt_RPn_freq_mhz", buf, sizeof(buf)) > 0) igt_sysfs_set(sysfs, "gt_min_freq_mhz", buf); - } if (igt_sysfs_read(sysfs, "gt_RP0_freq_mhz", buf, sizeof(buf)) > 0) { igt_sysfs_set(sysfs, "gt_max_freq_mhz", buf); -- 2.38.1
[Intel-gfx] [PATCH] drm/i915/mtl: Connect root sysfs entries to GT0
Reading current root sysfs entries gives a min/max of all GTs. Updating this so we return default (GT0) values when root level sysfs entries are accessed, instead of min/max for the card. Tests that are not multi GT capable will read incorrect sysfs values without this change on multi-GT platforms like MTL. Fixes: a8a4f0467d70 ("drm/i915: Fix CFI violations in gt_sysfs") Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 47 +++-- 1 file changed, 6 insertions(+), 41 deletions(-) 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 cf71305ad586..395ae47483a7 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c @@ -28,77 +28,42 @@ sysfs_gt_attribute_w_func(struct kobject *kobj, struct attribute *attr, int (func)(struct intel_gt *gt, u32 val), u32 val) { struct intel_gt *gt; - int ret; if (!is_object_gt(kobj)) { - int i; struct device *dev = kobj_to_dev(kobj); struct drm_i915_private *i915 = kdev_minor_to_i915(dev); - for_each_gt(gt, i915, i) { - ret = func(gt, val); - if (ret) - break; - } + gt = to_gt(i915); } else { gt = intel_gt_sysfs_get_drvdata(kobj, attr->name); - ret = func(gt, val); } - return ret; + return func(gt, val); } static u32 sysfs_gt_attribute_r_func(struct kobject *kobj, struct attribute *attr, - u32 (func)(struct intel_gt *gt), - enum intel_gt_sysfs_op op) + u32 (func)(struct intel_gt *gt)) { struct intel_gt *gt; - u32 ret; - - ret = (op == INTEL_GT_SYSFS_MAX) ? 0 : (u32) -1; if (!is_object_gt(kobj)) { - int i; struct device *dev = kobj_to_dev(kobj); struct drm_i915_private *i915 = kdev_minor_to_i915(dev); - for_each_gt(gt, i915, i) { - u32 val = func(gt); - - switch (op) { - case INTEL_GT_SYSFS_MIN: - if (val < ret) - ret = val; - break; - - case INTEL_GT_SYSFS_MAX: - if (val > ret) - ret = val; - break; - } - } + gt = to_gt(i915); } else { gt = intel_gt_sysfs_get_drvdata(kobj, attr->name); - ret = func(gt); } - return ret; + return func(gt); } -/* RC6 interfaces will show the minimum RC6 residency value */ -#define sysfs_gt_attribute_r_min_func(d, a, f) \ - sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MIN) - -/* Frequency interfaces will show the maximum frequency value */ -#define sysfs_gt_attribute_r_max_func(d, a, f) \ - sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MAX) - #define INTEL_GT_SYSFS_SHOW(_name, _attr_type) \ static ssize_t _name##_show_common(struct kobject *kobj, \ struct attribute *attr, char *buff) \ { \ - u32 val = sysfs_gt_attribute_r_##_attr_type##_func(kobj, attr, \ + u32 val = sysfs_gt_attribute_r_func(kobj, attr, \ __##_name##_show); \ \ return sysfs_emit(buff, "%u\n", val); \ -- 2.38.1
[Intel-gfx] [PATCH v4] drm/i915/slpc: Use platform limits for min/max frequency
GuC will set the min/max frequencies to theoretical max on ATS-M. This will break kernel ABI, so limit min/max frequency to RP0(platform max) instead. Also modify the SLPC selftest to update the min frequency when we have a server part so that we can iterate between platform min and max. v2: Check softlimits instead of platform limits (Riana) v3: More review comments (Ashutosh) v4: No need to use saved_min_freq and other comments (Ashutosh) Bug: https://gitlab.freedesktop.org/drm/intel/-/issues/7030 Acked-by: Nirmoy Das Reviewed-by: Riana Tauro Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/selftest_slpc.c | 20 +- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 37 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 3 ++ 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c index 4c6e9257e593..82ec95a299f6 100644 --- a/drivers/gpu/drm/i915/gt/selftest_slpc.c +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c @@ -239,6 +239,11 @@ static int run_test(struct intel_gt *gt, int test_type) if (!intel_uc_uses_guc_slpc(>->uc)) return 0; + if (slpc->min_freq == slpc->rp0_freq) { + pr_err("Min/Max are fused to the same value\n"); + return -EINVAL; + } + if (igt_spinner_init(&spin, gt)) return -ENOMEM; @@ -253,17 +258,14 @@ static int run_test(struct intel_gt *gt, int test_type) } /* -* 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. +* 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. */ err = slpc_set_min_freq(slpc, slpc->min_freq); - if (err) + if (err) { + pr_err("Unable to update min freq!"); return err; - - if (slpc->min_freq == slpc->rp0_freq) { - pr_err("Min/Max are fused to the same value\n"); - return -EINVAL; } intel_gt_pm_wait_for_idle(gt); @@ -330,7 +332,7 @@ static int run_test(struct intel_gt *gt, int test_type) engine->name, max_act_freq); /* Actual frequency should rise above min */ - if (max_act_freq <= slpc_min_freq) { + if (max_act_freq <= slpc->min_freq) { pr_err("Actual freq did not rise above min\n"); pr_err("Perf Limit Reasons: 0x%x\n", intel_uncore_read(gt->uncore, GT0_PERF_LIMIT_REASONS)); 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..c7e568af1e9c 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,39 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc) return 0; } +static bool is_slpc_min_freq_rpmax(struct intel_guc_slpc *slpc) +{ + struct drm_i915_private *i915 = slpc_to_i915(slpc); + int slpc_min_freq; + int ret; + + ret = intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq); + if (ret) { + drm_err(&i915->drm, + "Failed to get min freq: (%d)\n", + ret); + return false; + } + + 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 (!slpc->min_freq_softlimit && + is_slpc_min_freq_rpmax(slpc)) { + 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 +681,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) slpc_get_rp_values(slpc); + /* Handle the case wh
[Intel-gfx] [PATCH v5] drm/i915/slpc: Optmize waitboost for SLPC
Waitboost (when SLPC is enabled) results in a H2G message. This can result in thousands of messages during a stress test and fill up an already full CTB. There is no need to request for boost if min softlimit is equal or greater than it. v2: Add the tracing back, and check requested freq in the worker thread (Tvrtko) v3: Check requested freq in dec_waiters as well v4: Only check min_softlimit against boost_freq. Limit this optimization for server parts for now. v5: min_softlimit can be greater than boost (Ashutosh) Reviewed-by: Ashutosh Dixit Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_rps.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index fc23c562d9b2..2ece7a559cde 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1016,9 +1016,15 @@ void intel_rps_boost(struct i915_request *rq) if (rps_uses_slpc(rps)) { slpc = rps_to_slpc(rps); + if (slpc->min_freq_softlimit >= slpc->boost_freq) + return; + /* Return if old value is non zero */ - if (!atomic_fetch_inc(&slpc->num_waiters)) + if (!atomic_fetch_inc(&slpc->num_waiters)) { + GT_TRACE(rps_to_gt(rps), "boost fence:%llx:%llx\n", +rq->fence.context, rq->fence.seqno); schedule_work(&slpc->boost_work); + } return; } -- 2.35.1
[Intel-gfx] [PATCH v4] drm/i915/slpc: Optmize waitboost for SLPC
Waitboost (when SLPC is enabled) results in a H2G message. This can result in thousands of messages during a stress test and fill up an already full CTB. There is no need to request for RP0 if boost_freq and the min softlimit are the same. v2: Add the tracing back, and check requested freq in the worker thread (Tvrtko) v3: Check requested freq in dec_waiters as well v4: Only check min_softlimit against boost_freq. Limit this optimization for server parts for now. Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_rps.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index fc23c562d9b2..32e1f5dde5bb 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1016,9 +1016,15 @@ void intel_rps_boost(struct i915_request *rq) if (rps_uses_slpc(rps)) { slpc = rps_to_slpc(rps); + if (slpc->min_freq_softlimit == slpc->boost_freq) + return; + /* Return if old value is non zero */ - if (!atomic_fetch_inc(&slpc->num_waiters)) + if (!atomic_fetch_inc(&slpc->num_waiters)) { + GT_TRACE(rps_to_gt(rps), "boost fence:%llx:%llx\n", +rq->fence.context, rq->fence.seqno); schedule_work(&slpc->boost_work); + } return; } -- 2.35.1
[Intel-gfx] [PATCH v3] drm/i915/slpc: Optmize waitboost for SLPC
Waitboost (when SLPC is enabled) results in a H2G message. This can result in thousands of messages during a stress test and fill up an already full CTB. There is no need to request for RP0 if GuC is already requesting the same. v2: Add the tracing back, and check requested freq in the worker thread (Tvrtko) v3: Check requested freq in dec_waiters as well Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_rps.c | 3 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 14 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index fc23c562d9b2..18b75cf08d1b 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1016,6 +1016,9 @@ void intel_rps_boost(struct i915_request *rq) if (rps_uses_slpc(rps)) { slpc = rps_to_slpc(rps); + GT_TRACE(rps_to_gt(rps), "boost fence:%llx:%llx\n", +rq->fence.context, rq->fence.seqno); + /* Return if old value is non zero */ if (!atomic_fetch_inc(&slpc->num_waiters)) schedule_work(&slpc->boost_work); 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 b7cdeec44bd3..9dbdbab1515a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -227,14 +227,19 @@ static int slpc_force_min_freq(struct intel_guc_slpc *slpc, u32 freq) static void slpc_boost_work(struct work_struct *work) { struct intel_guc_slpc *slpc = container_of(work, typeof(*slpc), boost_work); + struct intel_rps *rps = &slpc_to_gt(slpc)->rps; int err; /* * Raise min freq to boost. It's possible that * this is greater than current max. But it will * certainly be limited by RP0. An error setting -* the min param is not fatal. +* the min param is not fatal. No need to boost +* if we are already requesting it. */ + if (intel_rps_get_requested_frequency(rps) == slpc->boost_freq) + return; + mutex_lock(&slpc->lock); if (atomic_read(&slpc->num_waiters)) { err = slpc_force_min_freq(slpc, slpc->boost_freq); @@ -728,6 +733,7 @@ int intel_guc_slpc_set_boost_freq(struct intel_guc_slpc *slpc, u32 val) void intel_guc_slpc_dec_waiters(struct intel_guc_slpc *slpc) { + struct intel_rps *rps = &slpc_to_gt(slpc)->rps; /* * Return min back to the softlimit. * This is called during request retire, @@ -735,8 +741,10 @@ void intel_guc_slpc_dec_waiters(struct intel_guc_slpc *slpc) * set_param fails. */ mutex_lock(&slpc->lock); - if (atomic_dec_and_test(&slpc->num_waiters)) - slpc_force_min_freq(slpc, slpc->min_freq_softlimit); + if (atomic_dec_and_test(&slpc->num_waiters)) { + if (intel_rps_get_requested_frequency(rps) != slpc->min_freq_softlimit) + slpc_force_min_freq(slpc, slpc->min_freq_softlimit); + } mutex_unlock(&slpc->lock); } -- 2.35.1
[Intel-gfx] [PATCH v2] drm/i915/slpc: Optmize waitboost for SLPC
Waitboost (when SLPC is enabled) results in a H2G message. This can result in thousands of messages during a stress test and fill up an already full CTB. There is no need to request for RP0 if GuC is already requesting the same. v2: Add the tracing back, and check requested freq in the worker thread (Tvrtko) Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_rps.c | 3 +++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 7 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index fc23c562d9b2..18b75cf08d1b 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1016,6 +1016,9 @@ void intel_rps_boost(struct i915_request *rq) if (rps_uses_slpc(rps)) { slpc = rps_to_slpc(rps); + GT_TRACE(rps_to_gt(rps), "boost fence:%llx:%llx\n", +rq->fence.context, rq->fence.seqno); + /* Return if old value is non zero */ if (!atomic_fetch_inc(&slpc->num_waiters)) schedule_work(&slpc->boost_work); 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 b7cdeec44bd3..7ab96221be7e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -227,14 +227,19 @@ static int slpc_force_min_freq(struct intel_guc_slpc *slpc, u32 freq) static void slpc_boost_work(struct work_struct *work) { struct intel_guc_slpc *slpc = container_of(work, typeof(*slpc), boost_work); + struct intel_rps *rps = &slpc_to_gt(slpc)->rps; int err; /* * Raise min freq to boost. It's possible that * this is greater than current max. But it will * certainly be limited by RP0. An error setting -* the min param is not fatal. +* the min param is not fatal. No need to boost +* if we are already requesting it. */ + if (intel_rps_get_requested_frequency(rps) == slpc->boost_freq) + return; + mutex_lock(&slpc->lock); if (atomic_read(&slpc->num_waiters)) { err = slpc_force_min_freq(slpc, slpc->boost_freq); -- 2.35.1
[Intel-gfx] [PATCH] drm/i915/slpc: Optmize waitboost for SLPC
Waitboost (when SLPC is enabled) results in a H2G message. This can result in thousands of messages during a stress test and fill up an already full CTB. There is no need to request for RP0 if GuC is already requesting the same. Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/intel_rps.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index fc23c562d9b2..a20ae4fceac8 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -1005,13 +1005,20 @@ void intel_rps_dec_waiters(struct intel_rps *rps) void intel_rps_boost(struct i915_request *rq) { struct intel_guc_slpc *slpc; + struct intel_rps *rps = &READ_ONCE(rq->engine)->gt->rps; if (i915_request_signaled(rq) || i915_request_has_waitboost(rq)) return; + /* If GuC is already requesting RP0, skip */ + if (rps_uses_slpc(rps)) { + slpc = rps_to_slpc(rps); + if (intel_rps_get_requested_frequency(rps) == slpc->rp0_freq) + return; + } + /* Serializes with i915_request_retire() */ 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); -- 2.35.1
[Intel-gfx] [PATCH v3] drm/i915/slpc: Use platform limits for min/max frequency
GuC will set the min/max frequencies to theoretical max on ATS-M. This will break kernel ABI, so limit min/max frequency to RP0(platform max) instead. Also modify the SLPC selftest to update the min frequency when we have a server part so that we can iterate between platform min and max. v2: Check softlimits instead of platform limits (Riana) v3: More review comments (Ashutosh) Bug: https://gitlab.freedesktop.org/drm/intel/-/issues/7030 Acked-by: Nirmoy Das Reviewed-by: Riana Tauro Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/selftest_slpc.c | 40 +-- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 30 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h | 2 + .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 3 ++ 4 files changed, 63 insertions(+), 12 deletions(-) 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; + } + } 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; } + saved_min_freq = slpc_min_freq; + + /* New temp min freq = RPn */ + slpc_min_freq = slpc->min_freq; + 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; + + 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) { + slpc->min_is_rpmax = true; + slpc->min_freq_softlimit = slpc->rp0_freq; + (slpc_to_gt(slpc))->defaults.min_freq = slpc->min_freq_softlimit; + } +
[Intel-gfx] [PATCH v2] drm/i915/slpc: Use platform limits for min/max frequency
GuC will set the min/max frequencies to theoretical max on ATS-M. This will break kernel ABI, so limit min/max frequency to RP0(platform max) instead. Also modify the SLPC selftest to update the min frequency when we have a server part so that we can iterate between platform min and max. v2: Check softlimits instead of platform limits(Riana) Bug: https://gitlab.freedesktop.org/drm/intel/-/issues/7030 Acked-by: Nirmoy Das Signed-off-by: Vinay Belgaumkar --- drivers/gpu/drm/i915/gt/selftest_slpc.c | 40 +-- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 29 ++ .../gpu/drm/i915/gt/uc/intel_guc_slpc_types.h | 3 ++ 3 files changed, 60 insertions(+), 12 deletions(-) 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; + } + } 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; } + saved_min_freq = slpc_min_freq; + + /* New temp min freq = RPn */ + slpc_min_freq = slpc->min_freq; + 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..11613d373a49 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,31 @@ 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; + + if (slpc_min_freq > slpc->rp0_freq) + 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) { + slpc->min_is_rpmax = true; + slpc->min_freq_softlimit = slpc->rp0_freq; + } +} + static int slpc_use_fused_rp0(struct intel_guc_slpc *slpc) { /* Force SLPC to used platform rp0 */ @@ -647,6 +673,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) slpc_get_