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

drm/i915/guc: GuC virtual engines



Implement GuC virtual engines. Rather simple implementation, basically
just allocate an engine, setup context enter / exit function to virtual
engine specific functions, set all other variables / functions to guc
versions, and set the engine mask to that of all the siblings.

v2: Update to work with proto-ctx
v3:
 (Daniele)
  - Drop include, add comment to intel_virtual_engine_has_heartbeat

Cc: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Signed-off-by: default avatarMatthew Brost <matthew.brost@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-2-matthew.brost@intel.com
parent 13d29c82
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -74,7 +74,6 @@
#include "gt/intel_context_param.h"
#include "gt/intel_engine_heartbeat.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_execlists_submission.h" /* virtual_engine */
#include "gt/intel_gpu_commands.h"
#include "gt/intel_ring.h"

@@ -363,9 +362,6 @@ set_proto_ctx_engines_balance(struct i915_user_extension __user *base,
	if (!HAS_EXECLISTS(i915))
		return -ENODEV;

	if (intel_uc_uses_guc_submission(&i915->gt.uc))
		return -ENODEV; /* not implement yet */

	if (get_user(idx, &ext->engine_index))
		return -EFAULT;

@@ -950,7 +946,7 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx,
			break;

		case I915_GEM_ENGINE_TYPE_BALANCED:
			ce = intel_execlists_create_virtual(pe[n].siblings,
			ce = intel_engine_create_virtual(pe[n].siblings,
							 pe[n].num_siblings);
			break;

+6 −0
Original line number Diff line number Diff line
@@ -47,6 +47,12 @@ struct intel_context_ops {

	void (*reset)(struct intel_context *ce);
	void (*destroy)(struct kref *kref);

	/* virtual engine/context interface */
	struct intel_context *(*create_virtual)(struct intel_engine_cs **engine,
						unsigned int count);
	struct intel_engine_cs *(*get_sibling)(struct intel_engine_cs *engine,
					       unsigned int sibling);
};

struct intel_context {
+29 −1
Original line number Diff line number Diff line
@@ -273,13 +273,41 @@ intel_engine_has_preempt_reset(const struct intel_engine_cs *engine)
	return intel_engine_has_preemption(engine);
}

struct intel_context *
intel_engine_create_virtual(struct intel_engine_cs **siblings,
			    unsigned int count);

static inline bool
intel_virtual_engine_has_heartbeat(const struct intel_engine_cs *engine)
{
	/*
	 * For non-GuC submission we expect the back-end to look at the
	 * heartbeat status of the actual physical engine that the work
	 * has been (or is being) scheduled on, so we should only reach
	 * here with GuC submission enabled.
	 */
	GEM_BUG_ON(!intel_engine_uses_guc(engine));

	return intel_guc_virtual_engine_has_heartbeat(engine);
}

static inline bool
intel_engine_has_heartbeat(const struct intel_engine_cs *engine)
{
	if (!IS_ACTIVE(CONFIG_DRM_I915_HEARTBEAT_INTERVAL))
		return false;

	if (intel_engine_is_virtual(engine))
		return intel_virtual_engine_has_heartbeat(engine);
	else
		return READ_ONCE(engine->props.heartbeat_interval_ms);
}

static inline struct intel_engine_cs *
intel_engine_get_sibling(struct intel_engine_cs *engine, unsigned int sibling)
{
	GEM_BUG_ON(!intel_engine_is_virtual(engine));
	return engine->cops->get_sibling(engine, sibling);
}

#endif /* _INTEL_RINGBUFFER_H_ */
+14 −0
Original line number Diff line number Diff line
@@ -1796,6 +1796,20 @@ ktime_t intel_engine_get_busy_time(struct intel_engine_cs *engine, ktime_t *now)
	return total;
}

struct intel_context *
intel_engine_create_virtual(struct intel_engine_cs **siblings,
			    unsigned int count)
{
	if (count == 0)
		return ERR_PTR(-EINVAL);

	if (count == 1)
		return intel_context_create(siblings[0]);

	GEM_BUG_ON(!siblings[0]->cops->create_virtual);
	return siblings[0]->cops->create_virtual(siblings, count);
}

static bool match_ring(struct i915_request *rq)
{
	u32 ring = ENGINE_READ(rq->engine, RING_START);
+20 −9
Original line number Diff line number Diff line
@@ -199,6 +199,9 @@ static struct virtual_engine *to_virtual_engine(struct intel_engine_cs *engine)
	return container_of(engine, struct virtual_engine, base);
}

static struct intel_context *
execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count);

static struct i915_request *
__active_request(const struct intel_timeline * const tl,
		 struct i915_request *rq,
@@ -2599,6 +2602,8 @@ static const struct intel_context_ops execlists_context_ops = {

	.reset = lrc_reset,
	.destroy = lrc_destroy,

	.create_virtual = execlists_create_virtual,
};

static int emit_pdps(struct i915_request *rq)
@@ -3549,6 +3554,17 @@ static void virtual_context_exit(struct intel_context *ce)
		intel_engine_pm_put(ve->siblings[n]);
}

static struct intel_engine_cs *
virtual_get_sibling(struct intel_engine_cs *engine, unsigned int sibling)
{
	struct virtual_engine *ve = to_virtual_engine(engine);

	if (sibling >= ve->num_siblings)
		return NULL;

	return ve->siblings[sibling];
}

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

@@ -3563,6 +3579,8 @@ static const struct intel_context_ops virtual_context_ops = {
	.exit = virtual_context_exit,

	.destroy = virtual_context_destroy,

	.get_sibling = virtual_get_sibling,
};

static intel_engine_mask_t virtual_submission_mask(struct virtual_engine *ve)
@@ -3711,20 +3729,13 @@ static void virtual_submit_request(struct i915_request *rq)
	spin_unlock_irqrestore(&ve->base.sched_engine->lock, flags);
}

struct intel_context *
intel_execlists_create_virtual(struct intel_engine_cs **siblings,
			       unsigned int count)
static struct intel_context *
execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count)
{
	struct virtual_engine *ve;
	unsigned int n;
	int err;

	if (count == 0)
		return ERR_PTR(-EINVAL);

	if (count == 1)
		return intel_context_create(siblings[0]);

	ve = kzalloc(struct_size(ve, siblings, count), GFP_KERNEL);
	if (!ve)
		return ERR_PTR(-ENOMEM);
Loading