[PATCH 10/10] drm/i915/guc: Keep a wq per engine
Chris Wilson
chris at chris-wilson.co.uk
Mon Nov 21 10:13:43 UTC 2016
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_debugfs.c | 6 +-
drivers/gpu/drm/i915/i915_guc_submission.c | 114 ++++++++++++-----------------
drivers/gpu/drm/i915/intel_guc.h | 2 -
drivers/gpu/drm/i915/intel_ringbuffer.h | 2 +
4 files changed, 51 insertions(+), 73 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 2521a91762e7..350d4a849cba 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2478,8 +2478,10 @@ static int i915_guc_info(struct seq_file *m, void *data)
}
seq_printf(m, "\t%s: %llu\n", "Total", total);
- seq_printf(m, "\nGuC execbuf client @ %p:\n", guc->execbuf_client);
- i915_guc_client_info(m, dev_priv, guc->execbuf_client);
+ for_each_engine(engine, dev_priv, id) {
+ seq_printf(m, "\nGuC %s client\n", engine->name);
+ i915_guc_client_info(m, dev_priv, engine->guc_client);
+ }
i915_guc_log_info(m, dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
index e12ff881d38d..31ab64502f48 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -157,8 +157,7 @@ static int host2guc_release_doorbell(struct intel_guc *guc,
return host2guc_action(guc, data, 2);
}
-static int host2guc_sample_forcewake(struct intel_guc *guc,
- struct i915_guc_client *client)
+static int host2guc_sample_forcewake(struct intel_guc *guc)
{
struct drm_i915_private *dev_priv = guc_to_i915(guc);
u32 data[2];
@@ -457,7 +456,7 @@ static void guc_ctx_desc_fini(struct intel_guc *guc,
int i915_guc_wq_reserve(struct drm_i915_gem_request *request)
{
const size_t wqi_size = sizeof(struct guc_wq_item);
- struct i915_guc_client *gc = request->i915->guc.execbuf_client;
+ struct i915_guc_client *gc = request->engine->guc_client;
struct guc_process_desc *desc = gc->vaddr + gc->proc_desc_offset;
u32 freespace;
int ret;
@@ -480,7 +479,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request)
void i915_guc_wq_unreserve(struct drm_i915_gem_request *request)
{
const size_t wqi_size = sizeof(struct guc_wq_item);
- struct i915_guc_client *gc = request->i915->guc.execbuf_client;
+ struct i915_guc_client *gc = request->engine->guc_client;
GEM_BUG_ON(READ_ONCE(gc->wq_rsvd) < wqi_size);
@@ -622,7 +621,7 @@ static void __i915_guc_submit(struct drm_i915_gem_request *rq)
struct intel_engine_cs *engine = rq->engine;
unsigned int engine_id = engine->id;
struct intel_guc *guc = &rq->i915->guc;
- struct i915_guc_client *client = guc->execbuf_client;
+ struct i915_guc_client *client = engine->guc_client;
int b_ret;
spin_lock(&client->wq_lock);
@@ -746,59 +745,28 @@ guc_client_free(struct drm_i915_private *dev_priv,
kfree(client);
}
-/* Check that a doorbell register is in the expected state */
-static bool guc_doorbell_check(struct intel_guc *guc, uint16_t db_id)
+static void guc_init_doorbell_hw(struct intel_guc *guc)
{
struct drm_i915_private *dev_priv = guc_to_i915(guc);
- i915_reg_t drbreg = GEN8_DRBREGL(db_id);
- uint32_t value = I915_READ(drbreg);
- bool enabled = (value & GUC_DOORBELL_ENABLED) != 0;
- bool expected = test_bit(db_id, guc->doorbell_bitmap);
-
- if (enabled == expected)
- return true;
-
- DRM_DEBUG_DRIVER("Doorbell %d (reg 0x%x) 0x%x, should be %s\n",
- db_id, drbreg.reg, value,
- expected ? "active" : "inactive");
-
- return false;
-}
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
-/*
- * Borrow the first client to set up & tear down each unused doorbell
- * in turn, to ensure that all doorbell h/w is (re)initialised.
- */
-static void guc_init_doorbell_hw(struct intel_guc *guc)
-{
- struct i915_guc_client *client = guc->execbuf_client;
- uint16_t db_id;
- int i, err;
+ for_each_engine(engine, dev_priv, id)
+ guc_disable_doorbell(guc, engine->guc_client);
- guc_disable_doorbell(guc, client);
+ for_each_engine(engine, dev_priv, id) {
+ struct i915_guc_client *client = engine->guc_client;
+ uint16_t db_id;
+ int err;
- for (i = 0; i < GUC_MAX_DOORBELLS; ++i) {
- /* Skip if doorbell is OK */
- if (guc_doorbell_check(guc, i))
- continue;
+ db_id = select_doorbell_register(guc, client->priority);
+ WARN_ON(db_id == GUC_INVALID_DOORBELL_ID);
- err = guc_update_doorbell_id(guc, client, i);
+ err = guc_update_doorbell_id(guc, client, db_id);
if (err)
- DRM_DEBUG_DRIVER("Doorbell %d update failed, err %d\n",
- i, err);
+ DRM_WARN("Failed to restore doorbell to %d, err %d\n",
+ db_id, err);
}
-
- db_id = select_doorbell_register(guc, client->priority);
- WARN_ON(db_id == GUC_INVALID_DOORBELL_ID);
-
- err = guc_update_doorbell_id(guc, client, db_id);
- if (err)
- DRM_WARN("Failed to restore doorbell to %d, err %d\n",
- db_id, err);
-
- /* Read back & verify all doorbell registers */
- for (i = 0; i < GUC_MAX_DOORBELLS; ++i)
- (void)guc_doorbell_check(guc, i);
}
/**
@@ -1484,6 +1452,8 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
const size_t poolsize = GUC_MAX_GPU_CONTEXTS * ctxsize;
const size_t gemsize = round_up(poolsize, PAGE_SIZE);
struct intel_guc *guc = &dev_priv->guc;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
struct i915_vma *vma;
if (!HAS_GUC_SCHED(dev_priv))
@@ -1509,13 +1479,16 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv)
guc_log_create(guc);
guc_addon_create(guc);
- guc->execbuf_client = guc_client_alloc(dev_priv,
- INTEL_INFO(dev_priv)->ring_mask,
- GUC_CTX_PRIORITY_KMD_NORMAL,
- dev_priv->kernel_context);
- if (!guc->execbuf_client) {
- DRM_ERROR("Failed to create GuC client for execbuf!\n");
- goto err;
+ for_each_engine(engine, dev_priv, id) {
+ engine->guc_client =
+ guc_client_alloc(dev_priv,
+ intel_engine_flag(engine),
+ GUC_CTX_PRIORITY_KMD_NORMAL,
+ dev_priv->kernel_context);
+ if (!engine->guc_client) {
+ DRM_ERROR("Failed to create GuC client for execbuf!\n");
+ goto err;
+ }
}
return 0;
@@ -1538,25 +1511,25 @@ static void guc_reset_wq(struct i915_guc_client *gc)
int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
{
struct intel_guc *guc = &dev_priv->guc;
- struct i915_guc_client *client = guc->execbuf_client;
struct intel_engine_cs *engine;
enum intel_engine_id id;
- if (!client)
+ if (!HAS_GUC_SCHED(dev_priv))
return -ENODEV;
- guc_reset_wq(client);
- host2guc_sample_forcewake(guc, client);
+ host2guc_sample_forcewake(guc);
guc_init_doorbell_hw(guc);
/* Take over from manual control of ELSP (execlists) */
for_each_engine(engine, dev_priv, id) {
+ struct i915_guc_client *client = engine->guc_client;
struct drm_i915_gem_request *rq;
engine->submit_request = i915_guc_submit;
engine->schedule = NULL;
/* Replay the current set of previously submitted requests */
+ guc_reset_wq(client);
list_for_each_entry(rq, &engine->timeline->requests, link) {
client->wq_rsvd += sizeof(struct guc_wq_item);
__i915_guc_submit(rq);
@@ -1568,9 +1541,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
{
- struct intel_guc *guc = &dev_priv->guc;
-
- if (!guc->execbuf_client)
+ if (!HAS_GUC_SCHED(dev_priv))
return;
/* Revert back to manual ELSP submission */
@@ -1580,13 +1551,18 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
void i915_guc_submission_fini(struct drm_i915_private *dev_priv)
{
struct intel_guc *guc = &dev_priv->guc;
- struct i915_guc_client *client;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
- client = fetch_and_zero(&guc->execbuf_client);
- if (!client)
- return;
+ for_each_engine(engine, dev_priv, id) {
+ struct i915_guc_client *client;
- guc_client_free(dev_priv, client);
+ client = fetch_and_zero(&engine->guc_client);
+ if (!client)
+ continue;
+
+ guc_client_free(dev_priv, client);
+ }
i915_vma_unpin_and_release(&guc->ads_vma);
i915_vma_unpin_and_release(&guc->log.vma);
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index dc570a6d612e..6c0bf7f1202e 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -150,8 +150,6 @@ struct intel_guc {
struct i915_vma *ctx_pool_vma;
struct ida ctx_ids;
- struct i915_guc_client *execbuf_client;
-
DECLARE_BITMAP(doorbell_bitmap, GUC_MAX_DOORBELLS);
uint32_t db_cacheline; /* Cyclic counter mod pagesize */
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 3466b4e77e7c..bf22efad97ae 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -355,6 +355,8 @@ struct intel_engine_cs {
bool preempt_wa;
u32 ctx_desc_template;
+ struct i915_guc_client *guc_client;
+
struct i915_gem_context *last_context;
struct intel_engine_hangcheck hangcheck;
--
2.10.2
More information about the Intel-gfx-trybot
mailing list