summaryrefslogtreecommitdiff
path: root/tests/perf_pmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/perf_pmu.c')
-rw-r--r--tests/perf_pmu.c115
1 files changed, 55 insertions, 60 deletions
diff --git a/tests/perf_pmu.c b/tests/perf_pmu.c
index 9cb679b2..a19fd2ac 100644
--- a/tests/perf_pmu.c
+++ b/tests/perf_pmu.c
@@ -40,6 +40,7 @@
#include "igt_core.h"
#include "igt_perf.h"
#include "igt_sysfs.h"
+#include "sw_sync.h"
IGT_TEST_DESCRIPTION("Test the i915 pmu perf interface");
@@ -787,18 +788,18 @@ static void cpu_hotplug(int gem_fd)
assert_within_epsilon(val, ref, tolerance);
}
-static unsigned long calibrate_nop(int fd, const unsigned int calibration_us)
+static unsigned long calibrate_nop(int fd, const uint64_t calibration_us)
{
- const unsigned int cal_min_us = calibration_us * 3;
+ const uint64_t cal_min_us = calibration_us * 3;
const unsigned int tolerance_pct = 10;
const uint32_t bbe = MI_BATCH_BUFFER_END;
const unsigned int loops = 17;
struct drm_i915_gem_exec_object2 obj = {};
- struct drm_i915_gem_execbuffer2 eb =
- { .buffer_count = 1, .buffers_ptr = (uintptr_t)&obj};
+ struct drm_i915_gem_execbuffer2 eb = {
+ .buffer_count = 1, .buffers_ptr = to_user_pointer(&obj),
+ };
struct timespec t_begin = { };
- long size, last_size;
- unsigned long ns;
+ uint64_t size, last_size, ns;
igt_nsec_elapsed(&t_begin);
@@ -828,81 +829,75 @@ static unsigned long calibrate_nop(int fd, const unsigned int calibration_us)
} while (igt_nsec_elapsed(&t_begin) / 1000 < cal_min_us ||
abs(size - last_size) > (size * tolerance_pct / 100));
- return size / sizeof(uint32_t);
+ return size;
}
-static void exec_nop(int gem_fd, unsigned long sz)
+static void
+test_interrupts(int gem_fd)
{
- struct drm_i915_gem_exec_object2 obj = {};
- struct drm_i915_gem_execbuffer2 eb =
- { .buffer_count = 1, .buffers_ptr = (uintptr_t)&obj};
const uint32_t bbe = MI_BATCH_BUFFER_END;
+ const unsigned int test_duration_ms = 1000;
+ struct drm_i915_gem_exec_object2 obj = { };
+ struct drm_i915_gem_execbuffer2 eb = {
+ .buffers_ptr = to_user_pointer(&obj),
+ .buffer_count = 1,
+ .flags = I915_EXEC_FENCE_OUT,
+ };
+ unsigned long sz;
+ igt_spin_t *spin;
+ const int target = 30;
struct pollfd pfd;
- int fence;
+ uint64_t idle, busy;
+ int fd;
- sz = ALIGN(sz, sizeof(uint32_t));
+ sz = calibrate_nop(gem_fd, test_duration_ms * 1000 / target);
+ gem_quiescent_gpu(gem_fd);
+
+ fd = open_pmu(I915_PMU_INTERRUPTS);
+ spin = igt_spin_batch_new(gem_fd, 0, 0, 0);
obj.handle = gem_create(gem_fd, sz);
gem_write(gem_fd, obj.handle, sz - sizeof(bbe), &bbe, sizeof(bbe));
- eb.flags = I915_EXEC_RENDER | I915_EXEC_FENCE_OUT;
-
- gem_execbuf_wr(gem_fd, &eb);
- fence = eb.rsvd2 >> 32;
-
- /*
- * Poll on the output fence to ensure user interrupts will be
- * generated and listened to.
- */
- pfd.fd = fence;
pfd.events = POLLIN;
- igt_assert_eq(poll(&pfd, 1, -1), 1);
-
- close(fence);
- gem_close(gem_fd, obj.handle);
-}
-
-static void
-test_interrupts(int gem_fd)
-{
- const unsigned int calibration_us = 250000;
- const unsigned int batch_len_us = 100000;
- const unsigned int batch_count = 3e6 / batch_len_us;
- uint64_t idle, busy, prev;
- unsigned long cal, sz;
- unsigned int i;
- int fd;
-
- fd = open_pmu(I915_PMU_INTERRUPTS);
-
- cal = calibrate_nop(gem_fd, calibration_us);
- sz = batch_len_us * cal / calibration_us;
-
- gem_quiescent_gpu(gem_fd);
+ pfd.fd = -1;
+ for (int i = 0; i < target; i++) {
+ int new;
+
+ /* Merge all the fences together so we can wait on them all */
+ gem_execbuf_wr(gem_fd, &eb);
+ new = eb.rsvd2 >> 32;
+ if (pfd.fd == -1) {
+ pfd.fd = new;
+ } else {
+ int old = pfd.fd;
+ pfd.fd = sync_fence_merge(old, new);
+ close(old);
+ close(new);
+ }
+ }
/* Wait for idle state. */
- prev = pmu_read_single(fd);
- idle = prev + 1;
- while (idle != prev) {
- usleep(1e6);
- prev = idle;
+ idle = pmu_read_single(fd);
+ do {
+ busy = idle;
+ usleep(1e3);
idle = pmu_read_single(fd);
- }
+ } while (idle != busy);
- igt_assert_eq(idle - prev, 0);
+ /* Install the fences and enable signaling */
+ igt_assert_eq(poll(&pfd, 1, 10), 0);
- /*
- * Send some no-op batches waiting on output fences to
- * ensure interrupts.
- */
- for (i = 0; i < batch_count; i++)
- exec_nop(gem_fd, sz);
+ /* Unplug the calibrated queue and wait for all the fences */
+ igt_spin_batch_free(gem_fd, spin);
+ igt_assert_eq(poll(&pfd, 1, 2 * test_duration_ms), 1);
+ close(pfd.fd);
/* Check at least as many interrupts has been generated. */
busy = pmu_read_single(fd) - idle;
close(fd);
- igt_assert(busy >= batch_count);
+ igt_assert_lte(target, busy);
}
static void