Commit 62eaf0ae authored by Matthew Brost's avatar Matthew Brost Committed by John Harrison
Browse files

drm/i915/guc: Support request cancellation



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: default avatarMatthew Brost <matthew.brost@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Signed-off-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210727002348.97202-26-matthew.brost@intel.com
parent ae8ac10d
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -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)
{
@@ -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);
}
+7 −0
Original line number Diff line number Diff line
@@ -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
+8 −1
Original line number Diff line number Diff line
@@ -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"
@@ -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);

@@ -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
@@ -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 −0
Original line number Diff line number Diff line
@@ -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"
@@ -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,
@@ -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,
+16 −0
Original line number Diff line number Diff line
@@ -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.
@@ -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,
Loading