mirror of
https://github.com/torvalds/linux.git
synced 2024-12-15 23:51:46 +00:00
drm/i915: Subsume intel_ctx_submit_request in to drm_i915_gem_request
Move all remaining elements that were unique to execlists queue items in to the associated request. Issue: VIZ-4274 v2: Rebase. Fixed issue of overzealous freeing of request. v3: Removed re-addition of cleanup work queue (found by Daniel Vetter) v4: Rebase. v5: Actual removal of intel_ctx_submit_request. Update both tail and postfix pointer in __i915_add_request (found by Thomas Daniel) v6: Removed unrelated changes Signed-off-by: Nick Hoath <nicholas.hoath@intel.com> Reviewed-by: Thomas Daniel <thomas.daniel@intel.com> [danvet: Reformat comment with strange linebreaks.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
21076372af
commit
6d3d8274bc
@ -1928,7 +1928,7 @@ static int i915_execlists(struct seq_file *m, void *data)
|
|||||||
intel_runtime_pm_get(dev_priv);
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
for_each_ring(ring, dev_priv, ring_id) {
|
for_each_ring(ring, dev_priv, ring_id) {
|
||||||
struct intel_ctx_submit_request *head_req = NULL;
|
struct drm_i915_gem_request *head_req = NULL;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
@ -1961,18 +1961,18 @@ static int i915_execlists(struct seq_file *m, void *data)
|
|||||||
list_for_each(cursor, &ring->execlist_queue)
|
list_for_each(cursor, &ring->execlist_queue)
|
||||||
count++;
|
count++;
|
||||||
head_req = list_first_entry_or_null(&ring->execlist_queue,
|
head_req = list_first_entry_or_null(&ring->execlist_queue,
|
||||||
struct intel_ctx_submit_request, execlist_link);
|
struct drm_i915_gem_request, execlist_link);
|
||||||
spin_unlock_irqrestore(&ring->execlist_lock, flags);
|
spin_unlock_irqrestore(&ring->execlist_lock, flags);
|
||||||
|
|
||||||
seq_printf(m, "\t%d requests in queue\n", count);
|
seq_printf(m, "\t%d requests in queue\n", count);
|
||||||
if (head_req) {
|
if (head_req) {
|
||||||
struct drm_i915_gem_object *ctx_obj;
|
struct drm_i915_gem_object *ctx_obj;
|
||||||
|
|
||||||
ctx_obj = head_req->request->ctx->engine[ring_id].state;
|
ctx_obj = head_req->ctx->engine[ring_id].state;
|
||||||
seq_printf(m, "\tHead request id: %u\n",
|
seq_printf(m, "\tHead request id: %u\n",
|
||||||
intel_execlists_ctx_id(ctx_obj));
|
intel_execlists_ctx_id(ctx_obj));
|
||||||
seq_printf(m, "\tHead request tail: %u\n",
|
seq_printf(m, "\tHead request tail: %u\n",
|
||||||
head_req->request->tail);
|
head_req->tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_putc(m, '\n');
|
seq_putc(m, '\n');
|
||||||
|
@ -2116,6 +2116,26 @@ struct drm_i915_gem_request {
|
|||||||
struct list_head client_list;
|
struct list_head client_list;
|
||||||
|
|
||||||
uint32_t uniq;
|
uint32_t uniq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ELSP only accepts two elements at a time, so we queue
|
||||||
|
* context/tail pairs on a given queue (ring->execlist_queue) until the
|
||||||
|
* hardware is available. The queue serves a double purpose: we also use
|
||||||
|
* it to keep track of the up to 2 contexts currently in the hardware
|
||||||
|
* (usually one in execution and the other queued up by the GPU): We
|
||||||
|
* only remove elements from the head of the queue when the hardware
|
||||||
|
* informs us that an element has been completed.
|
||||||
|
*
|
||||||
|
* All accesses to the queue are mediated by a spinlock
|
||||||
|
* (ring->execlist_lock).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Execlist link in the submission queue.*/
|
||||||
|
struct list_head execlist_link;
|
||||||
|
|
||||||
|
/** Execlists no. of times this request has been sent to the ELSP */
|
||||||
|
int elsp_submitted;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void i915_gem_request_free(struct kref *req_ref);
|
void i915_gem_request_free(struct kref *req_ref);
|
||||||
|
@ -2414,7 +2414,7 @@ int __i915_add_request(struct intel_engine_cs *ring,
|
|||||||
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
||||||
struct drm_i915_gem_request *request;
|
struct drm_i915_gem_request *request;
|
||||||
struct intel_ringbuffer *ringbuf;
|
struct intel_ringbuffer *ringbuf;
|
||||||
u32 request_ring_position, request_start;
|
u32 request_start;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
request = ring->outstanding_lazy_request;
|
request = ring->outstanding_lazy_request;
|
||||||
@ -2449,7 +2449,7 @@ int __i915_add_request(struct intel_engine_cs *ring,
|
|||||||
* GPU processing the request, we never over-estimate the
|
* GPU processing the request, we never over-estimate the
|
||||||
* position of the head.
|
* position of the head.
|
||||||
*/
|
*/
|
||||||
request_ring_position = intel_ring_get_tail(ringbuf);
|
request->postfix = intel_ring_get_tail(ringbuf);
|
||||||
|
|
||||||
if (i915.enable_execlists) {
|
if (i915.enable_execlists) {
|
||||||
ret = ring->emit_request(ringbuf, request);
|
ret = ring->emit_request(ringbuf, request);
|
||||||
@ -2462,7 +2462,7 @@ int __i915_add_request(struct intel_engine_cs *ring,
|
|||||||
}
|
}
|
||||||
|
|
||||||
request->head = request_start;
|
request->head = request_start;
|
||||||
request->postfix = request_ring_position;
|
request->tail = intel_ring_get_tail(ringbuf);
|
||||||
|
|
||||||
/* Whilst this request exists, batch_obj will be on the
|
/* Whilst this request exists, batch_obj will be on the
|
||||||
* active_list, and so will hold the active reference. Only when this
|
* active_list, and so will hold the active reference. Only when this
|
||||||
@ -2649,14 +2649,14 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
|
|||||||
* pinned in place.
|
* pinned in place.
|
||||||
*/
|
*/
|
||||||
while (!list_empty(&ring->execlist_queue)) {
|
while (!list_empty(&ring->execlist_queue)) {
|
||||||
struct intel_ctx_submit_request *submit_req;
|
struct drm_i915_gem_request *submit_req;
|
||||||
|
|
||||||
submit_req = list_first_entry(&ring->execlist_queue,
|
submit_req = list_first_entry(&ring->execlist_queue,
|
||||||
struct intel_ctx_submit_request,
|
struct drm_i915_gem_request,
|
||||||
execlist_link);
|
execlist_link);
|
||||||
list_del(&submit_req->execlist_link);
|
list_del(&submit_req->execlist_link);
|
||||||
intel_runtime_pm_put(dev_priv);
|
intel_runtime_pm_put(dev_priv);
|
||||||
i915_gem_context_unreference(submit_req->request->ctx);
|
i915_gem_context_unreference(submit_req->ctx);
|
||||||
kfree(submit_req);
|
kfree(submit_req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,8 +404,8 @@ static void execlists_submit_contexts(struct intel_engine_cs *ring,
|
|||||||
|
|
||||||
static void execlists_context_unqueue(struct intel_engine_cs *ring)
|
static void execlists_context_unqueue(struct intel_engine_cs *ring)
|
||||||
{
|
{
|
||||||
struct intel_ctx_submit_request *req0 = NULL, *req1 = NULL;
|
struct drm_i915_gem_request *req0 = NULL, *req1 = NULL;
|
||||||
struct intel_ctx_submit_request *cursor = NULL, *tmp = NULL;
|
struct drm_i915_gem_request *cursor = NULL, *tmp = NULL;
|
||||||
|
|
||||||
assert_spin_locked(&ring->execlist_lock);
|
assert_spin_locked(&ring->execlist_lock);
|
||||||
|
|
||||||
@ -417,7 +417,7 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)
|
|||||||
execlist_link) {
|
execlist_link) {
|
||||||
if (!req0) {
|
if (!req0) {
|
||||||
req0 = cursor;
|
req0 = cursor;
|
||||||
} else if (req0->request->ctx == cursor->request->ctx) {
|
} else if (req0->ctx == cursor->ctx) {
|
||||||
/* Same ctx: ignore first request, as second request
|
/* Same ctx: ignore first request, as second request
|
||||||
* will update tail past first request's workload */
|
* will update tail past first request's workload */
|
||||||
cursor->elsp_submitted = req0->elsp_submitted;
|
cursor->elsp_submitted = req0->elsp_submitted;
|
||||||
@ -433,9 +433,9 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)
|
|||||||
|
|
||||||
WARN_ON(req1 && req1->elsp_submitted);
|
WARN_ON(req1 && req1->elsp_submitted);
|
||||||
|
|
||||||
execlists_submit_contexts(ring, req0->request->ctx, req0->request->tail,
|
execlists_submit_contexts(ring, req0->ctx, req0->tail,
|
||||||
req1 ? req1->request->ctx : NULL,
|
req1 ? req1->ctx : NULL,
|
||||||
req1 ? req1->request->tail : 0);
|
req1 ? req1->tail : 0);
|
||||||
|
|
||||||
req0->elsp_submitted++;
|
req0->elsp_submitted++;
|
||||||
if (req1)
|
if (req1)
|
||||||
@ -445,17 +445,17 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)
|
|||||||
static bool execlists_check_remove_request(struct intel_engine_cs *ring,
|
static bool execlists_check_remove_request(struct intel_engine_cs *ring,
|
||||||
u32 request_id)
|
u32 request_id)
|
||||||
{
|
{
|
||||||
struct intel_ctx_submit_request *head_req;
|
struct drm_i915_gem_request *head_req;
|
||||||
|
|
||||||
assert_spin_locked(&ring->execlist_lock);
|
assert_spin_locked(&ring->execlist_lock);
|
||||||
|
|
||||||
head_req = list_first_entry_or_null(&ring->execlist_queue,
|
head_req = list_first_entry_or_null(&ring->execlist_queue,
|
||||||
struct intel_ctx_submit_request,
|
struct drm_i915_gem_request,
|
||||||
execlist_link);
|
execlist_link);
|
||||||
|
|
||||||
if (head_req != NULL) {
|
if (head_req != NULL) {
|
||||||
struct drm_i915_gem_object *ctx_obj =
|
struct drm_i915_gem_object *ctx_obj =
|
||||||
head_req->request->ctx->engine[ring->id].state;
|
head_req->ctx->engine[ring->id].state;
|
||||||
if (intel_execlists_ctx_id(ctx_obj) == request_id) {
|
if (intel_execlists_ctx_id(ctx_obj) == request_id) {
|
||||||
WARN(head_req->elsp_submitted == 0,
|
WARN(head_req->elsp_submitted == 0,
|
||||||
"Never submitted head request\n");
|
"Never submitted head request\n");
|
||||||
@ -537,15 +537,11 @@ static int execlists_context_queue(struct intel_engine_cs *ring,
|
|||||||
u32 tail,
|
u32 tail,
|
||||||
struct drm_i915_gem_request *request)
|
struct drm_i915_gem_request *request)
|
||||||
{
|
{
|
||||||
struct intel_ctx_submit_request *req = NULL, *cursor;
|
struct drm_i915_gem_request *cursor;
|
||||||
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int num_elements = 0;
|
int num_elements = 0;
|
||||||
|
|
||||||
req = kzalloc(sizeof(*req), GFP_KERNEL);
|
|
||||||
if (req == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
if (to != ring->default_context)
|
if (to != ring->default_context)
|
||||||
intel_lr_context_pin(ring, to);
|
intel_lr_context_pin(ring, to);
|
||||||
|
|
||||||
@ -559,14 +555,13 @@ static int execlists_context_queue(struct intel_engine_cs *ring,
|
|||||||
if (request == NULL)
|
if (request == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
request->ring = ring;
|
request->ring = ring;
|
||||||
|
request->ctx = to;
|
||||||
} else {
|
} else {
|
||||||
WARN_ON(to != request->ctx);
|
WARN_ON(to != request->ctx);
|
||||||
}
|
}
|
||||||
request->ctx = to;
|
|
||||||
request->tail = tail;
|
request->tail = tail;
|
||||||
req->request = request;
|
|
||||||
i915_gem_request_reference(request);
|
i915_gem_request_reference(request);
|
||||||
i915_gem_context_reference(req->request->ctx);
|
i915_gem_context_reference(request->ctx);
|
||||||
|
|
||||||
intel_runtime_pm_get(dev_priv);
|
intel_runtime_pm_get(dev_priv);
|
||||||
|
|
||||||
@ -577,13 +572,13 @@ static int execlists_context_queue(struct intel_engine_cs *ring,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (num_elements > 2) {
|
if (num_elements > 2) {
|
||||||
struct intel_ctx_submit_request *tail_req;
|
struct drm_i915_gem_request *tail_req;
|
||||||
|
|
||||||
tail_req = list_last_entry(&ring->execlist_queue,
|
tail_req = list_last_entry(&ring->execlist_queue,
|
||||||
struct intel_ctx_submit_request,
|
struct drm_i915_gem_request,
|
||||||
execlist_link);
|
execlist_link);
|
||||||
|
|
||||||
if (to == tail_req->request->ctx) {
|
if (to == tail_req->ctx) {
|
||||||
WARN(tail_req->elsp_submitted != 0,
|
WARN(tail_req->elsp_submitted != 0,
|
||||||
"More than 2 already-submitted reqs queued\n");
|
"More than 2 already-submitted reqs queued\n");
|
||||||
list_del(&tail_req->execlist_link);
|
list_del(&tail_req->execlist_link);
|
||||||
@ -592,7 +587,7 @@ static int execlists_context_queue(struct intel_engine_cs *ring,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add_tail(&req->execlist_link, &ring->execlist_queue);
|
list_add_tail(&request->execlist_link, &ring->execlist_queue);
|
||||||
if (num_elements == 0)
|
if (num_elements == 0)
|
||||||
execlists_context_unqueue(ring);
|
execlists_context_unqueue(ring);
|
||||||
|
|
||||||
@ -761,7 +756,7 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,
|
|||||||
|
|
||||||
void intel_execlists_retire_requests(struct intel_engine_cs *ring)
|
void intel_execlists_retire_requests(struct intel_engine_cs *ring)
|
||||||
{
|
{
|
||||||
struct intel_ctx_submit_request *req, *tmp;
|
struct drm_i915_gem_request *req, *tmp;
|
||||||
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct list_head retired_list;
|
struct list_head retired_list;
|
||||||
@ -776,7 +771,7 @@ void intel_execlists_retire_requests(struct intel_engine_cs *ring)
|
|||||||
spin_unlock_irqrestore(&ring->execlist_lock, flags);
|
spin_unlock_irqrestore(&ring->execlist_lock, flags);
|
||||||
|
|
||||||
list_for_each_entry_safe(req, tmp, &retired_list, execlist_link) {
|
list_for_each_entry_safe(req, tmp, &retired_list, execlist_link) {
|
||||||
struct intel_context *ctx = req->request->ctx;
|
struct intel_context *ctx = req->ctx;
|
||||||
struct drm_i915_gem_object *ctx_obj =
|
struct drm_i915_gem_object *ctx_obj =
|
||||||
ctx->engine[ring->id].state;
|
ctx->engine[ring->id].state;
|
||||||
|
|
||||||
@ -784,9 +779,8 @@ void intel_execlists_retire_requests(struct intel_engine_cs *ring)
|
|||||||
intel_lr_context_unpin(ring, ctx);
|
intel_lr_context_unpin(ring, ctx);
|
||||||
intel_runtime_pm_put(dev_priv);
|
intel_runtime_pm_put(dev_priv);
|
||||||
i915_gem_context_unreference(ctx);
|
i915_gem_context_unreference(ctx);
|
||||||
i915_gem_request_unreference(req->request);
|
i915_gem_request_unreference(req);
|
||||||
list_del(&req->execlist_link);
|
list_del(&req->execlist_link);
|
||||||
kfree(req);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,33 +89,6 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,
|
|||||||
u64 exec_start, u32 flags);
|
u64 exec_start, u32 flags);
|
||||||
u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj);
|
u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj);
|
||||||
|
|
||||||
/**
|
|
||||||
* struct intel_ctx_submit_request - queued context submission request
|
|
||||||
* @ctx: Context to submit to the ELSP.
|
|
||||||
* @ring: Engine to submit it to.
|
|
||||||
* @tail: how far in the context's ringbuffer this request goes to.
|
|
||||||
* @execlist_link: link in the submission queue.
|
|
||||||
* @work: workqueue for processing this request in a bottom half.
|
|
||||||
* @elsp_submitted: no. of times this request has been sent to the ELSP.
|
|
||||||
*
|
|
||||||
* The ELSP only accepts two elements at a time, so we queue context/tail
|
|
||||||
* pairs on a given queue (ring->execlist_queue) until the hardware is
|
|
||||||
* available. The queue serves a double purpose: we also use it to keep track
|
|
||||||
* of the up to 2 contexts currently in the hardware (usually one in execution
|
|
||||||
* and the other queued up by the GPU): We only remove elements from the head
|
|
||||||
* of the queue when the hardware informs us that an element has been
|
|
||||||
* completed.
|
|
||||||
*
|
|
||||||
* All accesses to the queue are mediated by a spinlock (ring->execlist_lock).
|
|
||||||
*/
|
|
||||||
struct intel_ctx_submit_request {
|
|
||||||
struct list_head execlist_link;
|
|
||||||
|
|
||||||
int elsp_submitted;
|
|
||||||
|
|
||||||
struct drm_i915_gem_request *request;
|
|
||||||
};
|
|
||||||
|
|
||||||
void intel_lrc_irq_handler(struct intel_engine_cs *ring);
|
void intel_lrc_irq_handler(struct intel_engine_cs *ring);
|
||||||
void intel_execlists_retire_requests(struct intel_engine_cs *ring);
|
void intel_execlists_retire_requests(struct intel_engine_cs *ring);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user