Commit 5e2a0419 authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915: Switch back to an array of logical per-engine HW contexts



We switched to a tree of per-engine HW context to accommodate the
introduction of virtual engines. However, we plan to also support
multiple instances of the same engine within the GEM context, defeating
our use of the engine as a key to looking up the HW context. Just
allocate a logical per-engine instance and always use an index into the
ctx->engines[]. Later on, this ctx->engines[] may be replaced by a user
specified map.

v2: Add for_each_gem_engine() helper to iterator within the engines lock
v3: intel_context_create_request() helper
v4: s/unsigned long/unsigned int/ 4 billion engines is quite enough.
v5: Push iterator locking to caller

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190426163336.15906-7-chris@chris-wilson.co.uk
parent 11334c6a
Loading
Loading
Loading
Loading
+21 −91
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ static struct i915_global_context {
	struct kmem_cache *slab_ce;
} global;

struct intel_context *intel_context_alloc(void)
static struct intel_context *intel_context_alloc(void)
{
	return kmem_cache_zalloc(global.slab_ce, GFP_KERNEL);
}
@@ -28,104 +28,17 @@ void intel_context_free(struct intel_context *ce)
}

struct intel_context *
intel_context_lookup(struct i915_gem_context *ctx,
intel_context_create(struct i915_gem_context *ctx,
		     struct intel_engine_cs *engine)
{
	struct intel_context *ce = NULL;
	struct rb_node *p;

	spin_lock(&ctx->hw_contexts_lock);
	p = ctx->hw_contexts.rb_node;
	while (p) {
		struct intel_context *this =
			rb_entry(p, struct intel_context, node);

		if (this->engine == engine) {
			GEM_BUG_ON(this->gem_context != ctx);
			ce = this;
			break;
		}

		if (this->engine < engine)
			p = p->rb_right;
		else
			p = p->rb_left;
	}
	spin_unlock(&ctx->hw_contexts_lock);

	return ce;
}

struct intel_context *
__intel_context_insert(struct i915_gem_context *ctx,
		       struct intel_engine_cs *engine,
		       struct intel_context *ce)
{
	struct rb_node **p, *parent;
	int err = 0;

	spin_lock(&ctx->hw_contexts_lock);

	parent = NULL;
	p = &ctx->hw_contexts.rb_node;
	while (*p) {
		struct intel_context *this;

		parent = *p;
		this = rb_entry(parent, struct intel_context, node);

		if (this->engine == engine) {
			err = -EEXIST;
			ce = this;
			break;
		}

		if (this->engine < engine)
			p = &parent->rb_right;
		else
			p = &parent->rb_left;
	}
	if (!err) {
		rb_link_node(&ce->node, parent, p);
		rb_insert_color(&ce->node, &ctx->hw_contexts);
	}

	spin_unlock(&ctx->hw_contexts_lock);

	return ce;
}

void __intel_context_remove(struct intel_context *ce)
{
	struct i915_gem_context *ctx = ce->gem_context;

	spin_lock(&ctx->hw_contexts_lock);
	rb_erase(&ce->node, &ctx->hw_contexts);
	spin_unlock(&ctx->hw_contexts_lock);
}

struct intel_context *
intel_context_instance(struct i915_gem_context *ctx,
		       struct intel_engine_cs *engine)
{
	struct intel_context *ce, *pos;

	ce = intel_context_lookup(ctx, engine);
	if (likely(ce))
		return intel_context_get(ce);
	struct intel_context *ce;

	ce = intel_context_alloc();
	if (!ce)
		return ERR_PTR(-ENOMEM);

	intel_context_init(ce, ctx, engine);

	pos = __intel_context_insert(ctx, engine, ce);
	if (unlikely(pos != ce)) /* Beaten! Use their HW context instead */
		intel_context_free(ce);

	GEM_BUG_ON(intel_context_lookup(ctx, engine) != pos);
	return intel_context_get(pos);
	return ce;
}

int __intel_context_do_pin(struct intel_context *ce)
@@ -204,6 +117,8 @@ intel_context_init(struct intel_context *ce,
		   struct i915_gem_context *ctx,
		   struct intel_engine_cs *engine)
{
	GEM_BUG_ON(!engine->cops);

	kref_init(&ce->ref);

	ce->gem_context = ctx;
@@ -254,3 +169,18 @@ void intel_context_exit_engine(struct intel_context *ce)
{
	intel_engine_pm_put(ce->engine);
}

struct i915_request *intel_context_create_request(struct intel_context *ce)
{
	struct i915_request *rq;
	int err;

	err = intel_context_pin(ce);
	if (unlikely(err))
		return ERR_PTR(err);

	rq = i915_request_create(ce);
	intel_context_unpin(ce);

	return rq;
}
+5 −22
Original line number Diff line number Diff line
@@ -12,24 +12,16 @@
#include "intel_context_types.h"
#include "intel_engine_types.h"

struct intel_context *intel_context_alloc(void);
void intel_context_free(struct intel_context *ce);

void intel_context_init(struct intel_context *ce,
			struct i915_gem_context *ctx,
			struct intel_engine_cs *engine);

/**
 * intel_context_lookup - Find the matching HW context for this (ctx, engine)
 * @ctx - the parent GEM context
 * @engine - the target HW engine
 *
 * May return NULL if the HW context hasn't been instantiated (i.e. unused).
 */
struct intel_context *
intel_context_lookup(struct i915_gem_context *ctx,
intel_context_create(struct i915_gem_context *ctx,
		     struct intel_engine_cs *engine);

void intel_context_free(struct intel_context *ce);

/**
 * intel_context_lock_pinned - Stablises the 'pinned' status of the HW context
 * @ce - the context
@@ -71,17 +63,6 @@ static inline void intel_context_unlock_pinned(struct intel_context *ce)
	mutex_unlock(&ce->pin_mutex);
}

struct intel_context *
__intel_context_insert(struct i915_gem_context *ctx,
		       struct intel_engine_cs *engine,
		       struct intel_context *ce);
void
__intel_context_remove(struct intel_context *ce);

struct intel_context *
intel_context_instance(struct i915_gem_context *ctx,
		       struct intel_engine_cs *engine);

int __intel_context_do_pin(struct intel_context *ce);

static inline int intel_context_pin(struct intel_context *ce)
@@ -144,4 +125,6 @@ static inline void intel_context_timeline_unlock(struct intel_context *ce)
	mutex_unlock(&ce->ring->timeline->mutex);
}

struct i915_request *intel_context_create_request(struct intel_context *ce);

#endif /* __INTEL_CONTEXT_H__ */
+0 −2
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/rbtree.h>
#include <linux/types.h>

#include "i915_active_types.h"
@@ -61,7 +60,6 @@ struct intel_context {
	struct i915_active_request active_tracker;

	const struct intel_context_ops *ops;
	struct rb_node node;

	/** sseu: Control eu/slice partitioning */
	struct intel_sseu sseu;
+1 −1
Original line number Diff line number Diff line
@@ -732,7 +732,7 @@ static int pin_context(struct i915_gem_context *ctx,
	struct intel_context *ce;
	int err;

	ce = intel_context_instance(ctx, engine);
	ce = i915_gem_context_get_engine(ctx, engine->id);
	if (IS_ERR(ce))
		return PTR_ERR(ce);

+2 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
 */

#include "i915_drv.h"
#include "i915_gem_context.h"
#include "intel_context.h"
#include "intel_engine_pm.h"

@@ -286,7 +287,7 @@ int mock_engine_init(struct intel_engine_cs *engine)
	i915_timeline_set_subclass(&engine->timeline, TIMELINE_ENGINE);

	engine->kernel_context =
		intel_context_instance(i915->kernel_context, engine);
		i915_gem_context_get_engine(i915->kernel_context, engine->id);
	if (IS_ERR(engine->kernel_context))
		goto err_timeline;

Loading