提交 a0991e1d 编写于 作者: M Michał Winiarski 提交者: Chris Wilson

drm/i915/guc: Split guc_wq_item_append

We're using a special preempt context for HW to preempt into. We don't
want to emit any requests there, but we still need to wrap this context
into a valid GuC work item.
Let's cleanup the functions operating on GuC work items.
We can extract guc_request_add - responsible for adding GuC work item and
ringing the doorbell, and guc_wq_item_append - used by the function
above, not tied to the concept of gem request.
Signed-off-by: NMichał Winiarski <michal.winiarski@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Jeff McGee <jeff.mcgee@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: NChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: NJeff McGee <jeff.mcgee@intel.com>
Signed-off-by: NChris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20171025200020.16636-7-michal.winiarski@intel.com
上级 e12ab169
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
* WQ_TYPE_INORDER is needed to support legacy submission via GuC, which * WQ_TYPE_INORDER is needed to support legacy submission via GuC, which
* represents in-order queue. The kernel driver packs ring tail pointer and an * represents in-order queue. The kernel driver packs ring tail pointer and an
* ELSP context descriptor dword into Work Item. * ELSP context descriptor dword into Work Item.
* See guc_wq_item_append() * See guc_add_request()
* *
* ADS: * ADS:
* The Additional Data Struct (ADS) has pointers for different buffers used by * The Additional Data Struct (ADS) has pointers for different buffers used by
...@@ -394,7 +394,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, ...@@ -394,7 +394,7 @@ static void guc_stage_desc_init(struct intel_guc *guc,
* submission or, in other words, not using a direct submission * submission or, in other words, not using a direct submission
* model) the KMD's LRCA is not used for any work submission. * model) the KMD's LRCA is not used for any work submission.
* Instead, the GuC uses the LRCA of the user mode context (see * Instead, the GuC uses the LRCA of the user mode context (see
* guc_wq_item_append below). * guc_add_request below).
*/ */
lrc->context_desc = lower_32_bits(ce->lrc_desc); lrc->context_desc = lower_32_bits(ce->lrc_desc);
...@@ -473,22 +473,18 @@ static void guc_shared_data_destroy(struct intel_guc *guc) ...@@ -473,22 +473,18 @@ static void guc_shared_data_destroy(struct intel_guc *guc)
/* Construct a Work Item and append it to the GuC's Work Queue */ /* Construct a Work Item and append it to the GuC's Work Queue */
static void guc_wq_item_append(struct i915_guc_client *client, static void guc_wq_item_append(struct i915_guc_client *client,
struct drm_i915_gem_request *rq) u32 target_engine, u32 context_desc,
u32 ring_tail, u32 fence_id)
{ {
/* wqi_len is in DWords, and does not include the one-word header */ /* wqi_len is in DWords, and does not include the one-word header */
const size_t wqi_size = sizeof(struct guc_wq_item); const size_t wqi_size = sizeof(struct guc_wq_item);
const u32 wqi_len = wqi_size / sizeof(u32) - 1; const u32 wqi_len = wqi_size / sizeof(u32) - 1;
struct intel_engine_cs *engine = rq->engine;
struct i915_gem_context *ctx = rq->ctx;
struct guc_process_desc *desc = __get_process_desc(client); struct guc_process_desc *desc = __get_process_desc(client);
struct guc_wq_item *wqi; struct guc_wq_item *wqi;
u32 ring_tail, wq_off; u32 wq_off;
lockdep_assert_held(&client->wq_lock); lockdep_assert_held(&client->wq_lock);
ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64);
GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX);
/* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we
* should not have the case where structure wqi is across page, neither * should not have the case where structure wqi is across page, neither
* wrapped to the beginning. This simplifies the implementation below. * wrapped to the beginning. This simplifies the implementation below.
...@@ -510,15 +506,14 @@ static void guc_wq_item_append(struct i915_guc_client *client, ...@@ -510,15 +506,14 @@ static void guc_wq_item_append(struct i915_guc_client *client,
/* Now fill in the 4-word work queue item */ /* Now fill in the 4-word work queue item */
wqi->header = WQ_TYPE_INORDER | wqi->header = WQ_TYPE_INORDER |
(wqi_len << WQ_LEN_SHIFT) | (wqi_len << WQ_LEN_SHIFT) |
(engine->guc_id << WQ_TARGET_SHIFT) | (target_engine << WQ_TARGET_SHIFT) |
WQ_NO_WCFLUSH_WAIT; WQ_NO_WCFLUSH_WAIT;
wqi->context_desc = context_desc;
wqi->context_desc = lower_32_bits(intel_lr_context_descriptor(ctx, engine));
wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT; wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT;
wqi->fence_id = rq->global_seqno; GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX);
wqi->fence_id = fence_id;
/* Postincrement WQ tail for next time. */ /* Make the update visible to GuC */
WRITE_ONCE(desc->tail, (wq_off + wqi_size) & (GUC_WQ_SIZE - 1)); WRITE_ONCE(desc->tail, (wq_off + wqi_size) & (GUC_WQ_SIZE - 1));
} }
...@@ -551,6 +546,25 @@ static void guc_ring_doorbell(struct i915_guc_client *client) ...@@ -551,6 +546,25 @@ static void guc_ring_doorbell(struct i915_guc_client *client)
GEM_BUG_ON(db->db_status != GUC_DOORBELL_ENABLED); GEM_BUG_ON(db->db_status != GUC_DOORBELL_ENABLED);
} }
static void guc_add_request(struct intel_guc *guc,
struct drm_i915_gem_request *rq)
{
struct i915_guc_client *client = guc->execbuf_client;
struct intel_engine_cs *engine = rq->engine;
u32 ctx_desc = lower_32_bits(intel_lr_context_descriptor(rq->ctx, engine));
u32 ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64);
spin_lock(&client->wq_lock);
guc_wq_item_append(client, engine->guc_id, ctx_desc,
ring_tail, rq->global_seqno);
guc_ring_doorbell(client);
client->submissions[engine->id] += 1;
spin_unlock(&client->wq_lock);
}
/** /**
* i915_guc_submit() - Submit commands through GuC * i915_guc_submit() - Submit commands through GuC
* @engine: engine associated with the commands * @engine: engine associated with the commands
...@@ -562,10 +576,8 @@ static void i915_guc_submit(struct intel_engine_cs *engine) ...@@ -562,10 +576,8 @@ static void i915_guc_submit(struct intel_engine_cs *engine)
{ {
struct drm_i915_private *dev_priv = engine->i915; struct drm_i915_private *dev_priv = engine->i915;
struct intel_guc *guc = &dev_priv->guc; struct intel_guc *guc = &dev_priv->guc;
struct i915_guc_client *client = guc->execbuf_client;
struct intel_engine_execlists * const execlists = &engine->execlists; struct intel_engine_execlists * const execlists = &engine->execlists;
struct execlist_port *port = execlists->port; struct execlist_port *port = execlists->port;
const unsigned int engine_id = engine->id;
unsigned int n; unsigned int n;
for (n = 0; n < execlists_num_ports(execlists); n++) { for (n = 0; n < execlists_num_ports(execlists); n++) {
...@@ -579,14 +591,7 @@ static void i915_guc_submit(struct intel_engine_cs *engine) ...@@ -579,14 +591,7 @@ static void i915_guc_submit(struct intel_engine_cs *engine)
if (i915_vma_is_map_and_fenceable(rq->ring->vma)) if (i915_vma_is_map_and_fenceable(rq->ring->vma))
POSTING_READ_FW(GUC_STATUS); POSTING_READ_FW(GUC_STATUS);
spin_lock(&client->wq_lock); guc_add_request(guc, rq);
guc_wq_item_append(client, rq);
guc_ring_doorbell(client);
client->submissions[engine_id] += 1;
spin_unlock(&client->wq_lock);
} }
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册