@@ -40,6 +40,7 @@
#include "ioctl_wrappers.h"
#include "intel_reg.h"
#include "intel_chipset.h"
+#include "igt_dummyload.h"
/**
* SECTION:igt_gt
@@ -577,6 +578,88 @@ unsigned intel_detect_and_clear_missed_interrupts(int fd)
return missed;
}
+static void alarm_handler(int sig)
+{
+}
+
+/**
+ * intel_measure_ring_size:
+ * @fd: open i915 drm file descriptor
+ * @engine: execbuf engine flag
+ * @new_ctx: use a new context to account for the space used by the lrc init
+ *
+ * This function calculates the maximum number of batches that can be inserted
+ * at the same time in the ring on the selected engine.
+ *
+ * Returns:
+ * Number of batches that fit in the ring
+ */
+unsigned int intel_measure_ring_size(int fd, unsigned int engine, bool new_ctx)
+{
+ struct sigaction old_sa, sa = { .sa_handler = alarm_handler };
+ struct drm_i915_gem_exec_object2 obj[2];
+ struct drm_i915_gem_execbuffer2 execbuf;
+ const uint32_t bbe = MI_BATCH_BUFFER_END;
+ unsigned int count, last;
+ struct itimerval itv;
+ struct igt_cork cork;
+
+ igt_require_intel(fd);
+
+ memset(obj, 0, sizeof(obj));
+ obj[1].handle = gem_create(fd, 4096);
+ gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe));
+
+ memset(&execbuf, 0, sizeof(execbuf));
+ execbuf.buffers_ptr = to_user_pointer(&obj[1]);
+ execbuf.buffer_count = 1;
+ execbuf.flags = engine;
+ gem_execbuf(fd, &execbuf);
+ gem_sync(fd, obj[1].handle);
+
+ obj[0].handle = igt_cork_plug(fd, &cork);
+
+ execbuf.buffers_ptr = to_user_pointer(obj);
+ execbuf.buffer_count = 2;
+
+ if (new_ctx)
+ execbuf.rsvd1 = gem_context_create(fd);
+
+ sigaction(SIGALRM, &sa, &old_sa);
+ itv.it_interval.tv_sec = 0;
+ itv.it_interval.tv_usec = 100;
+ itv.it_value.tv_sec = 0;
+ itv.it_value.tv_usec = 1000;
+ setitimer(ITIMER_REAL, &itv, NULL);
+
+ last = -1;
+ count = 0;
+ do {
+ if (ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf) == 0) {
+ count++;
+ continue;
+ }
+
+ if (last == count)
+ break;
+
+ last = count;
+ } while (1);
+
+ memset(&itv, 0, sizeof(itv));
+ setitimer(ITIMER_REAL, &itv, NULL);
+ sigaction(SIGALRM, &old_sa, NULL);
+
+ igt_cork_unplug(&cork);
+ gem_close(fd, obj[0].handle);
+ gem_close(fd, obj[1].handle);
+
+ if (new_ctx)
+ gem_context_destroy(fd, execbuf.rsvd1);
+
+ return count;
+}
+
const struct intel_execution_engine intel_execution_engines[] = {
{ "default", NULL, 0, 0 },
{ "render", "rcs0", I915_EXEC_RENDER, 0 },
@@ -63,6 +63,8 @@ void igt_clflush_range(void *addr, int size);
unsigned intel_detect_and_clear_missed_interrupts(int fd);
+unsigned int intel_measure_ring_size(int fd, unsigned int engine, bool new_ctx);
+
extern const struct intel_execution_engine {
const char *name;
const char *full_name;
The logic to measure the ring size is replicated almost identically in several tests. Adding it as a common function will make the code cleaner. The tests are updated in follow up patches. Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> --- lib/igt_gt.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/igt_gt.h | 2 ++ 2 files changed, 85 insertions(+)