pm_rps: Add load helper for loading gpu
authorJeff McGee <jeff.mcgee@intel.com>
Wed, 29 Jan 2014 00:25:05 +0000 (18:25 -0600)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 6 Feb 2014 06:46:06 +0000 (07:46 +0100)
The load helper submits repeated dword store commands to keep the
gpu loaded while subtests running in the parent process check for
expected rps response.

Signed-off-by: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
tests/pm_rps.c

index dabc2ba..555bb7c 100644 (file)
 #include <unistd.h>
 #include <getopt.h>
 #include "drmtest.h"
+#include "intel_gpu_tools.h"
+#include "intel_bufmgr.h"
+#include "intel_batchbuffer.h"
 
 static bool verbose = false;
 
+static int drm_fd;
+
 static const char sysfs_base_path[] = "/sys/class/drm/card%d/gt_%s_freq_mhz";
 enum {
        CUR,
@@ -137,6 +142,131 @@ static void dumpit(const int *freqs)
 #define dump(x) if (verbose) dumpit(x)
 #define log(...) if (verbose) printf(__VA_ARGS__)
 
+static struct load_helper {
+       int devid;
+       int has_ppgtt;
+       drm_intel_bufmgr *bufmgr;
+       struct intel_batchbuffer *batch;
+       drm_intel_bo *target_buffer;
+       bool ready;
+       bool exit;
+       struct igt_helper_process igt_proc;
+} lh;
+
+static void load_helper_signal_handler(int sig)
+{
+       lh.exit = true;
+}
+
+static void emit_store_dword_imm(uint32_t val)
+{
+       int cmd;
+       struct intel_batchbuffer *batch = lh.batch;
+
+       cmd = MI_STORE_DWORD_IMM;
+       if (!lh.has_ppgtt)
+               cmd |= MI_MEM_VIRTUAL;
+
+       if (intel_gen(lh.devid) >= 8) {
+               BEGIN_BATCH(4);
+               OUT_BATCH(cmd);
+               OUT_RELOC(lh.target_buffer, I915_GEM_DOMAIN_INSTRUCTION,
+                         I915_GEM_DOMAIN_INSTRUCTION, 0);
+               OUT_BATCH(0);
+               OUT_BATCH(val);
+               ADVANCE_BATCH();
+       } else {
+               BEGIN_BATCH(4);
+               OUT_BATCH(cmd);
+               OUT_BATCH(0); /* reserved */
+               OUT_RELOC(lh.target_buffer, I915_GEM_DOMAIN_INSTRUCTION,
+                         I915_GEM_DOMAIN_INSTRUCTION, 0);
+               OUT_BATCH(val);
+               ADVANCE_BATCH();
+       }
+}
+
+static void load_helper_run(void)
+{
+       assert(!lh.igt_proc.running);
+
+       igt_require(lh.ready == true);
+
+       igt_fork_helper(&lh.igt_proc) {
+               uint32_t val = 0;
+
+               signal(SIGUSR1, load_helper_signal_handler);
+
+               while (!lh.exit) {
+                       emit_store_dword_imm(val);
+                       intel_batchbuffer_flush_on_ring(lh.batch, 0);
+                       val++;
+               }
+
+               log("load helper sent %u dword writes\n", val);
+       }
+}
+
+static void load_helper_stop(void)
+{
+       assert(lh.igt_proc.running);
+       kill(lh.igt_proc.pid, SIGUSR1);
+       igt_wait_helper(&lh.igt_proc);
+}
+
+/* The load helper resource is used by only some subtests. We attempt to
+ * initialize in igt_fixture but do our igt_require check only if a
+ * subtest attempts to run it */
+static void load_helper_init(void)
+{
+       lh.devid = intel_get_drm_devid(drm_fd);
+       lh.has_ppgtt = gem_uses_aliasing_ppgtt(drm_fd);
+
+       /* MI_STORE_DATA can only use GTT address on gen4+/g33 and needs
+        * snoopable mem on pre-gen6. */
+       if (intel_gen(lh.devid) < 6) {
+               log("load helper init failed: pre-gen6 not supported\n");
+               return;
+       }
+
+       lh.bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
+       if (!lh.bufmgr) {
+               log("load helper init failed: buffer manager init\n");
+               return;
+       }
+       drm_intel_bufmgr_gem_enable_reuse(lh.bufmgr);
+
+       lh.batch = intel_batchbuffer_alloc(lh.bufmgr, lh.devid);
+       if (!lh.batch) {
+               log("load helper init failed: batch buffer alloc\n");
+               return;
+       }
+
+       lh.target_buffer = drm_intel_bo_alloc(lh.bufmgr, "target bo",
+                                             4096, 4096);
+       if (!lh.target_buffer) {
+               log("load helper init failed: target buffer alloc\n");
+               return;
+       }
+
+       lh.ready = true;
+}
+
+static void load_helper_deinit(void)
+{
+       if (lh.igt_proc.running)
+               load_helper_stop();
+
+       if (lh.target_buffer)
+               drm_intel_bo_unreference(lh.target_buffer);
+
+       if (lh.batch)
+               intel_batchbuffer_free(lh.batch);
+
+       if (lh.bufmgr)
+               drm_intel_bufmgr_destroy(lh.bufmgr);
+}
+
 static void min_max_config(void (*check)(void))
 {
        int fmid = (origfreqs[RPn] + origfreqs[RP0]) / 2;
@@ -250,6 +380,9 @@ static void pm_rps_exit_handler(int sig)
                writeval(stuff[MIN].filp, origfreqs[MIN]);
                writeval(stuff[MAX].filp, origfreqs[MAX]);
        }
+
+       load_helper_deinit();
+       close(drm_fd);
 }
 
 static int opt_handler(int opt, int opt_index)
@@ -291,11 +424,10 @@ int main(int argc, char **argv)
        igt_fixture {
                const int device = drm_get_card();
                struct junk *junk = stuff;
-               int fd, ret;
+               int ret;
 
                /* Use drm_open_any to verify device existence */
-               fd = drm_open_any();
-               close(fd);
+               drm_fd = drm_open_any();
 
                do {
                        int val = -1;
@@ -314,6 +446,8 @@ int main(int argc, char **argv)
                read_freqs(origfreqs);
 
                igt_install_exit_handler(pm_rps_exit_handler);
+
+               load_helper_init();
        }
 
        igt_subtest("basic-api")