Commit e5ca5dc0 authored by Chris Wilson's avatar Chris Wilson 😣

igt/pm_rps: Replace arbitrary HIGH_LOAD blit with a busyspin

Using a blit + sleep does not guarantee generating a high enough load to
keep the GPU busy, a busyspin does. Replace the blit at high load with a
continuous series spins and low load with a mix of spin and sleep.

v2: Maintain a limited queue depth

References: https://bugs.freedesktop.org/show_bug.cgi?id=104060Signed-off-by: Chris Wilson's avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen's avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent 79ac7d54
......@@ -26,7 +26,6 @@
*
*/
#include "igt.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -37,7 +36,8 @@
#include <time.h>
#include <sys/wait.h>
#include "intel_bufmgr.h"
#include "igt.h"
#include "igt_dummyload.h"
IGT_TEST_DESCRIPTION("Render P-States tests - verify GPU frequency changes");
......@@ -181,15 +181,9 @@ enum load {
};
static struct load_helper {
int devid;
int has_ppgtt;
drm_intel_bufmgr *bufmgr;
struct intel_batchbuffer *batch;
drm_intel_bo *target_buffer;
enum load load;
bool exit;
struct igt_helper_process igt_proc;
drm_intel_bo *src, *dst;
} lh;
static void load_helper_signal_handler(int sig)
......@@ -201,29 +195,6 @@ 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;
BEGIN_BATCH(4, 0); /* just ignore the reloc we emit and count dwords */
OUT_BATCH(cmd);
if (batch->gen >= 8) {
OUT_RELOC(lh.target_buffer, I915_GEM_DOMAIN_INSTRUCTION,
I915_GEM_DOMAIN_INSTRUCTION, 0);
} else {
OUT_BATCH(0); /* reserved */
OUT_RELOC(lh.target_buffer, I915_GEM_DOMAIN_INSTRUCTION,
I915_GEM_DOMAIN_INSTRUCTION, 0);
}
OUT_BATCH(val);
ADVANCE_BATCH();
}
#define LOAD_HELPER_PAUSE_USEC 500
#define LOAD_HELPER_BO_SIZE (16*1024*1024)
static void load_helper_set_load(enum load load)
......@@ -252,69 +223,51 @@ static void load_helper_run(enum load load)
lh.load = load;
igt_fork_helper(&lh.igt_proc) {
const uint32_t bbe = MI_BATCH_BUFFER_END;
struct drm_i915_gem_exec_object2 object;
struct drm_i915_gem_execbuffer2 execbuf;
uint32_t fences[3];
uint32_t val = 0;
igt_spin_t *spin[2] = {};
uint32_t handle;
signal(SIGUSR1, load_helper_signal_handler);
signal(SIGUSR2, load_helper_signal_handler);
fences[0] = gem_create(drm_fd, 4096);
gem_write(drm_fd, fences[0], 0, &bbe, sizeof(bbe));
fences[1] = gem_create(drm_fd, 4096);
gem_write(drm_fd, fences[1], 0, &bbe, sizeof(bbe));
fences[2] = gem_create(drm_fd, 4096);
gem_write(drm_fd, fences[2], 0, &bbe, sizeof(bbe));
memset(&execbuf, 0, sizeof(execbuf));
execbuf.buffers_ptr = (uintptr_t)&object;
execbuf.buffer_count = 1;
if (intel_gen(lh.devid) >= 6)
execbuf.flags = I915_EXEC_BLT;
igt_debug("Applying %s load...\n", lh.load ? "high" : "low");
while (!lh.exit) {
memset(&object, 0, sizeof(object));
object.handle = fences[val%3];
while (gem_bo_busy(drm_fd, object.handle))
if (spin[0]) {
handle = spin[0]->handle;
igt_spin_batch_end(spin[0]);
while (gem_bo_busy(drm_fd, handle))
usleep(100);
igt_spin_batch_free(drm_fd, spin[0]);
usleep(100);
}
spin[0] = spin[1];
spin[lh.load == HIGH] =
igt_spin_batch_new(drm_fd, 0, 0, 0);
}
if (lh.load == HIGH)
intel_copy_bo(lh.batch, lh.dst, lh.src,
LOAD_HELPER_BO_SIZE);
emit_store_dword_imm(val);
intel_batchbuffer_flush_on_ring(lh.batch,
I915_EXEC_BLT);
val++;
gem_execbuf(drm_fd, &execbuf);
/* Lower the load by pausing after every submitted
* write. */
if (lh.load == LOW)
usleep(LOAD_HELPER_PAUSE_USEC);
if (spin[0]) {
handle = spin[0]->handle;
igt_spin_batch_end(spin[0]);
}
if (spin[1]) {
handle = spin[1]->handle;
igt_spin_batch_end(spin[1]);
}
/* Wait for completion without boosting */
usleep(1000);
while (gem_bo_busy(drm_fd, lh.target_buffer->handle))
while (gem_bo_busy(drm_fd, handle))
usleep(1000);
igt_debug("load helper sent %u dword writes\n", val);
gem_close(drm_fd, fences[0]);
gem_close(drm_fd, fences[1]);
gem_close(drm_fd, fences[2]);
/* Idle/boost logic is tied with request retirement.
/*
* Idle/boost logic is tied with request retirement.
* Speed up detection of idle state and ensure deboost
* after removing load.
*/
igt_drop_caches_set(drm_fd, DROP_RETIRE);
igt_spin_batch_free(drm_fd, spin[1]);
igt_spin_batch_free(drm_fd, spin[0]);
}
}
......@@ -324,54 +277,6 @@ static void load_helper_stop(void)
igt_assert(igt_wait_helper(&lh.igt_proc) == 0);
}
static void load_helper_init(void)
{
lh.devid = intel_get_drm_devid(drm_fd);
lh.has_ppgtt = gem_uses_ppgtt(drm_fd);
/* MI_STORE_DATA can only use GTT address on gen4+/g33 and needs
* snoopable mem on pre-gen6. Hence load-helper only works on gen6+, but
* that's also all we care about for the rps testcase*/
igt_assert(intel_gen(lh.devid) >= 6);
lh.bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
igt_assert(lh.bufmgr);
drm_intel_bufmgr_gem_enable_reuse(lh.bufmgr);
lh.batch = intel_batchbuffer_alloc(lh.bufmgr, lh.devid);
igt_assert(lh.batch);
lh.target_buffer = drm_intel_bo_alloc(lh.bufmgr, "target bo",
4096, 4096);
igt_assert(lh.target_buffer);
lh.dst = drm_intel_bo_alloc(lh.bufmgr, "dst bo",
LOAD_HELPER_BO_SIZE, 4096);
igt_assert(lh.dst);
lh.src = drm_intel_bo_alloc(lh.bufmgr, "src bo",
LOAD_HELPER_BO_SIZE, 4096);
igt_assert(lh.src);
}
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.src)
drm_intel_bo_unreference(lh.src);
if (lh.dst)
drm_intel_bo_unreference(lh.dst);
if (lh.batch)
intel_batchbuffer_free(lh.batch);
if (lh.bufmgr)
drm_intel_bufmgr_destroy(lh.bufmgr);
}
static void do_load_gpu(void)
{
load_helper_run(LOW);
......@@ -582,13 +487,8 @@ static void boost_freq(int fd, int *boost_freqs)
{
int64_t timeout = 1;
igt_spin_t *load;
unsigned int engine;
/* Put boost on the same engine as low load */
engine = I915_EXEC_RENDER;
if (intel_gen(lh.devid) >= 6)
engine = I915_EXEC_BLT;
load = igt_spin_batch_new(fd, 0, engine, 0);
load = igt_spin_batch_new(fd, 0, 0, 0);
/* Waiting will grant us a boost to maximum */
gem_wait(fd, load->handle, &timeout);
......@@ -655,7 +555,9 @@ static void pm_rps_exit_handler(int sig)
writeval(sysfs_files[MAX].filp, origfreqs[MAX]);
}
load_helper_deinit();
if (lh.igt_proc.running)
load_helper_stop();
close(drm_fd);
}
......@@ -691,8 +593,6 @@ igt_main
read_freqs(origfreqs);
igt_install_exit_handler(pm_rps_exit_handler);
load_helper_init();
}
igt_subtest("basic-api")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment