On 08/03/18 09:13, Chris Wilson wrote:
Exercise some new API that allows applications to request that individual contexts are executed within a desired frequency range. v2: Split single/continuous set_freq subtests Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Cc: Paneri, Praveen <praveen.paneri@xxxxxxxxx> Cc: Kamble, Sagar A <sagar.a.kamble@xxxxxxxxx> Cc: Antonio Argenziano <antonio.argenziano@xxxxxxxxx> --- tests/Makefile.am | 1 + tests/Makefile.sources | 1 + tests/gem_ctx_freq.c | 604 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/meson.build | 1 + 4 files changed, 607 insertions(+) create mode 100644 tests/gem_ctx_freq.c
+static void single(int fd, const struct intel_execution_engine *e) +{ + const unsigned int engine = e->exec_id | e->flags; + uint32_t ctx = gem_context_create(fd); + uint32_t min, max; + double measured; + igt_spin_t *spin; + int pmu; + + get_freq(fd, ctx, &min, &max); + igt_info("Min freq: %dMHz; Max freq: %dMHz\n", min, max); + + pmu = perf_i915_open(I915_PMU_REQUESTED_FREQUENCY); + igt_require(pmu >= 0); + + for (uint32_t freq = min + 50; freq <= max; freq += 100) {
Although it is done in the smoke test, it would be interesting if freq's values were a bit randomized.
+ uint32_t cur, discard; + + set_freq(fd, ctx, freq, freq); + get_freq(fd, ctx, &cur, &discard);
igt_assert_eq(freq, cur)?
+ + gem_quiescent_gpu(fd); + spin = __igt_spin_batch_new(fd, ctx, engine, 0); + usleep(10000);
I guess here we wait for the frequency changes to take effect, maybe a small comment would help.
+ + measured = measure_frequency(pmu, SAMPLE_PERIOD); + igt_debugfs_dump(fd, "i915_rps_boost_info"); + + igt_spin_batch_free(fd, spin); + igt_info("%s(single): Measured %.1fMHz, expected %dMhz\n", + e->name, measured, cur); + igt_assert(measured > cur - 100 && measured < cur + 100); + } + gem_quiescent_gpu(fd); + + close(pmu); + gem_context_destroy(fd, ctx); +} +
+ +static void sandwich(int fd) +{ + uint32_t ctx = gem_context_create(fd); + unsigned int engine; + uint32_t min, max; + igt_spin_t *spin; + int pmu; + + pmu = perf_i915_open(I915_PMU_REQUESTED_FREQUENCY); + igt_require(pmu >= 0); + + spin = igt_spin_batch_new(fd, ctx, 0, 0); + get_freq(fd, ctx, &min, &max); + set_freq(fd, ctx, min, min); + for_each_physical_engine(fd, engine) { + struct drm_i915_gem_exec_object2 obj = { + .handle = spin->handle, + }; + struct drm_i915_gem_execbuffer2 eb = { + .buffer_count = 1, + .buffers_ptr = to_user_pointer(&obj), + .flags = engine, + .rsvd1 = ctx, + }; + uint32_t cur, discard; + double measured; + + min += 50; + if (min > max) + break; + + set_freq(fd, ctx, min, min); + get_freq(fd, ctx, &cur, &discard); + + gem_execbuf(fd, &eb); + usleep(10000); + + measured = measure_frequency(pmu, SAMPLE_PERIOD); + igt_debugfs_dump(fd, "i915_rps_boost_info"); + + igt_info("Measured %.1fMHz, expected %dMhz\n", measured, cur); + igt_assert(measured > cur - 100 && measured < cur + 100);
Does the frequency change after each execbuf?
+ } + igt_spin_batch_free(fd, spin); + gem_quiescent_gpu(fd); + + gem_context_destroy(fd, ctx); + close(pmu); +} + +static void pwm(int fd, unsigned int *engines, unsigned int nengine, int link) +{ + uint32_t ctx[nengine]; + + fcntl(link, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + + for (unsigned int n = 0; n < nengine; n++) + ctx[n] = gem_context_create(fd); + + do { + igt_spin_t *spin; + struct { + uint32_t engine; + uint32_t min; + uint32_t max; + } req; + + while (read(link, &req, sizeof(req)) > 0) { + if ((req.engine | req.min | req.max) == 0) + goto out; + + igt_assert(req.engine < nengine); + set_freq(fd, ctx[req.engine], req.min, req.max); + } + + /* Create a 20% load using busy spinners */ + spin = __igt_spin_batch_new(fd, ctx[0], engines[0], 0); + for (unsigned int n = 1; n < nengine; n++) { + struct drm_i915_gem_exec_object2 obj = { + .handle = spin->handle, + }; + struct drm_i915_gem_execbuffer2 eb = { + .buffer_count = 1, + .buffers_ptr = to_user_pointer(&obj), + .flags = engines[n], + .rsvd1 = ctx[n], + }; + gem_execbuf(fd, &eb); + } + usleep(100); + igt_spin_batch_end(spin); + + do + usleep(10); + while (gem_bo_busy(fd, spin->handle)); + igt_spin_batch_free(fd, spin); + usleep(400); + } while (1); + +out: + for (unsigned int n = 0; n < nengine; n++) + gem_context_destroy(fd, ctx[n]); +} + +static void smoketest(int fd, int timeout) +{ + unsigned int engines[16];
use a macro instead of magic number 16.
+ unsigned int nengine; + unsigned int engine; + uint32_t min[16], max[16]; + int pmu, link[2]; + + get_freq(fd, 0, &min[0], &max[0]); + + nengine = 0; + for_each_physical_engine(fd, engine) { + if (nengine == ARRAY_SIZE(engines) - 1) + break; + + min[nengine] = min[0]; + max[nengine] = max[0]; + engines[nengine] = engine; + nengine++; + } + igt_require(nengine); + + igt_assert(pipe(link) == 0); + igt_fork(child, 1) + pwm(fd, engines, nengine, link[0]); + close(link[0]); + + pmu = perf_i915_open(I915_PMU_REQUESTED_FREQUENCY); + igt_require(pmu >= 0); + + igt_until_timeout(timeout) { + struct { + uint32_t engine; + uint32_t min; + uint32_t max; + } req; + double measured; + uint32_t ctx; + + req.engine = rand() % nengine; + + ctx = gem_context_create(fd); + get_freq(fd, ctx, &req.min, &req.max); + req.min = rand() % (req.max - req.min) + req.min; + req.max = rand() % (req.max - req.min) + req.min; + set_freq(fd, ctx, req.min, req.max); + get_freq(fd, ctx, &req.min, &req.max); + + igt_debug("Replacing (%d, %d) on engine %x with (%d, %d)\n", + min[req.engine], max[req.engine], req.engine, + req.min, req.max); + igt_assert(write(link[1], &req, sizeof(req)) == sizeof(req)); + gem_context_destroy(fd, ctx); + + min[req.engine] = req.min; + max[req.engine] = req.max; + + for (unsigned int n = 0; n < nengine; n++) { + igt_debug("[%d]: [%d, %d]\n", n, min[n], max[n]); + if (min[n] < req.min) + req.min = min[n]; + if (max[n] > req.max) + req.max = max[n]; + } + igt_assert(req.max >= req.min); + + usleep(50000); + measured = measure_frequency(pmu, SAMPLE_PERIOD); + + if (measured <= req.min - 100 || measured >= req.max + 100) + igt_debugfs_dump(fd, "i915_rps_boost_info"); + igt_info("Measured %.1fMHz, expected [%d, %d]Mhz\n", + measured, req.min, req.max); + igt_assert(measured > req.min - 100 && + measured < req.max + 100); + } + + do { + struct { + uint32_t engine; + uint32_t min; + uint32_t max; + } req = {}; + + write(link[1], &req, sizeof(req)); + close(link[1]); + } while (0); + igt_waitchildren(); + gem_quiescent_gpu(fd); + + close(pmu); +} + +static void invalid_param(int fd) +{
gem_ctx_param is going to be upset again pretty soon ;).
+ uint32_t min, max; + uint32_t cur_min, cur_max; + + get_freq(fd, 0, &min, &max); + + igt_assert_eq(__set_freq(fd, 0, min - 50, max), -EINVAL); + igt_assert_eq(__set_freq(fd, 0, min, max + 50), -EINVAL);
One more case is both are out of boundary. igt_assert_eq(__set_freq(fd, 0, min - 50, max + 50), -EINVAL);
+ igt_assert_eq(__set_freq(fd, 0, min + 50, min), -EINVAL); + igt_assert_eq(__set_freq(fd, 0, max, max - 50), -EINVAL); + + get_freq(fd, 0, &cur_min, &cur_max); + igt_assert_eq(cur_min, min); + igt_assert_eq(cur_max, max);
Check frequency didn't change after each ioctl. Thanks, Antonio _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx