Skip to content

Commit

Permalink
drm/i915/guc: Support request cancellation
Browse files Browse the repository at this point in the history
This adds GuC backend support for i915_request_cancel(), which in turn
makes CONFIG_DRM_I915_REQUEST_TIMEOUT work.

This implementation makes use of fence while there are likely simplier
options. A fence was chosen because of another feature coming soon
which requires a user to block on a context until scheduling is
disabled. In that case we return the fence to the user and the user can
wait on that fence.

v2:
 (Daniele)
  - A comment about locking the blocked incr / decr
  - A comments about the use of the fence
  - Update commit message explaining why fence
  - Delete redundant check blocked count in unblock function
  - Ring buffer implementation
  - Comment about blocked in submission path
  - Shorter rpm path
v3:
 (Checkpatch)
  - Fix typos in commit message
 (Daniel)
  - Rework to simplier locking structure in guc_context_block / unblock

Signed-off-by: Matthew Brost <[email protected]>
Cc: Tvrtko Ursulin <[email protected]>
Reviewed-by: Daniele Ceraolo Spurio <[email protected]>
Signed-off-by: John Harrison <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
  • Loading branch information
mbrost05 authored and johnharr-intel committed Jul 28, 2021
1 parent ae8ac10 commit 62eaf0a
Show file tree
Hide file tree
Showing 7 changed files with 251 additions and 14 deletions.
13 changes: 13 additions & 0 deletions drivers/gpu/drm/i915/gt/intel_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,12 @@ static int __intel_context_active(struct i915_active *active)
return 0;
}

static int sw_fence_dummy_notify(struct i915_sw_fence *sf,
enum i915_sw_fence_notify state)
{
return NOTIFY_DONE;
}

void
intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
{
Expand Down Expand Up @@ -399,6 +405,13 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)
ce->guc_id = GUC_INVALID_LRC_ID;
INIT_LIST_HEAD(&ce->guc_id_link);

/*
* Initialize fence to be complete as this is expected to be complete
* unless there is a pending schedule disable outstanding.
*/
i915_sw_fence_init(&ce->guc_blocked, sw_fence_dummy_notify);
i915_sw_fence_commit(&ce->guc_blocked);

i915_active_init(&ce->active,
__intel_context_active, __intel_context_retire, 0);
}
Expand Down
7 changes: 7 additions & 0 deletions drivers/gpu/drm/i915/gt/intel_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ intel_context_is_pinned(struct intel_context *ce)
return atomic_read(&ce->pin_count);
}

static inline void intel_context_cancel_request(struct intel_context *ce,
struct i915_request *rq)
{
GEM_BUG_ON(!ce->ops->cancel_request);
return ce->ops->cancel_request(ce, rq);
}

/**
* intel_context_unlock_pinned - Releases the earlier locking of 'pinned' status
* @ce - the context
Expand Down
9 changes: 8 additions & 1 deletion drivers/gpu/drm/i915/gt/intel_context_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/types.h>

#include "i915_active_types.h"
#include "i915_sw_fence.h"
#include "i915_utils.h"
#include "intel_engine_types.h"
#include "intel_sseu.h"
Expand Down Expand Up @@ -42,6 +43,9 @@ struct intel_context_ops {
void (*unpin)(struct intel_context *ce);
void (*post_unpin)(struct intel_context *ce);

void (*cancel_request)(struct intel_context *ce,
struct i915_request *rq);

void (*enter)(struct intel_context *ce);
void (*exit)(struct intel_context *ce);

Expand Down Expand Up @@ -156,7 +160,7 @@ struct intel_context {
* sched_state: scheduling state of this context using GuC
* submission
*/
u8 sched_state;
u16 sched_state;
/*
* fences: maintains of list of requests that have a submit
* fence related to GuC submission
Expand Down Expand Up @@ -184,6 +188,9 @@ struct intel_context {
* GuC ID link - in list when unpinned but guc_id still valid in GuC
*/
struct list_head guc_id_link;

/* GuC context blocked fence */
struct i915_sw_fence guc_blocked;
};

#endif /* __INTEL_CONTEXT_TYPES__ */
18 changes: 18 additions & 0 deletions drivers/gpu/drm/i915/gt/intel_execlists_submission.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
#include "gen8_engine_cs.h"
#include "intel_breadcrumbs.h"
#include "intel_context.h"
#include "intel_engine_heartbeat.h"
#include "intel_engine_pm.h"
#include "intel_engine_stats.h"
#include "intel_execlists_submission.h"
Expand Down Expand Up @@ -2587,11 +2588,26 @@ static int execlists_context_alloc(struct intel_context *ce)
return lrc_alloc(ce, ce->engine);
}

static void execlists_context_cancel_request(struct intel_context *ce,
struct i915_request *rq)
{
struct intel_engine_cs *engine = NULL;

i915_request_active_engine(rq, &engine);

if (engine && intel_engine_pulse(engine))
intel_gt_handle_error(engine->gt, engine->mask, 0,
"request cancellation by %s",
current->comm);
}

static const struct intel_context_ops execlists_context_ops = {
.flags = COPS_HAS_INFLIGHT,

.alloc = execlists_context_alloc,

.cancel_request = execlists_context_cancel_request,

.pre_pin = execlists_context_pre_pin,
.pin = execlists_context_pin,
.unpin = lrc_unpin,
Expand Down Expand Up @@ -3608,6 +3624,8 @@ static const struct intel_context_ops virtual_context_ops = {

.alloc = virtual_context_alloc,

.cancel_request = execlists_context_cancel_request,

.pre_pin = virtual_context_pre_pin,
.pin = virtual_context_pin,
.unpin = lrc_unpin,
Expand Down
16 changes: 16 additions & 0 deletions drivers/gpu/drm/i915/gt/intel_ring_submission.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "intel_reset.h"
#include "intel_ring.h"
#include "shmem_utils.h"
#include "intel_engine_heartbeat.h"

/* Rough estimate of the typical request size, performing a flush,
* set-context and then emitting the batch.
Expand Down Expand Up @@ -604,9 +605,24 @@ static void ring_context_ban(struct intel_context *ce,
}
}

static void ring_context_cancel_request(struct intel_context *ce,
struct i915_request *rq)
{
struct intel_engine_cs *engine = NULL;

i915_request_active_engine(rq, &engine);

if (engine && intel_engine_pulse(engine))
intel_gt_handle_error(engine->gt, engine->mask, 0,
"request cancellation by %s",
current->comm);
}

static const struct intel_context_ops ring_context_ops = {
.alloc = ring_context_alloc,

.cancel_request = ring_context_cancel_request,

.ban = ring_context_ban,

.pre_pin = ring_context_pre_pin,
Expand Down
Loading

0 comments on commit 62eaf0a

Please sign in to comment.