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

drm/i915/guc: Direct all breadcrumbs for a class to single breadcrumbs



With GuC virtual engines the physical engine which a request executes
and completes on isn't known to the i915. Therefore we can't attach a
request to a physical engines breadcrumbs. To work around this we create
a single breadcrumbs per engine class when using GuC submission and
direct all physical engine interrupts to this breadcrumbs.

v2:
 (John H)
  - Rework header file structure so intel_engine_mask_t can be in
    intel_engine_types.h

Signed-off-by: default avatarMatthew Brost <matthew.brost@intel.com>
CC: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Signed-off-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210727002348.97202-6-matthew.brost@intel.com
parent b02d86b9
Loading
Loading
Loading
Loading
+17 −24
Original line number Diff line number Diff line
@@ -15,28 +15,14 @@
#include "intel_gt_pm.h"
#include "intel_gt_requests.h"

static bool irq_enable(struct intel_engine_cs *engine)
static bool irq_enable(struct intel_breadcrumbs *b)
{
	if (!engine->irq_enable)
		return false;

	/* Caller disables interrupts */
	spin_lock(&engine->gt->irq_lock);
	engine->irq_enable(engine);
	spin_unlock(&engine->gt->irq_lock);

	return true;
	return intel_engine_irq_enable(b->irq_engine);
}

static void irq_disable(struct intel_engine_cs *engine)
static void irq_disable(struct intel_breadcrumbs *b)
{
	if (!engine->irq_disable)
		return;

	/* Caller disables interrupts */
	spin_lock(&engine->gt->irq_lock);
	engine->irq_disable(engine);
	spin_unlock(&engine->gt->irq_lock);
	intel_engine_irq_disable(b->irq_engine);
}

static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
@@ -57,7 +43,7 @@ static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b)
	WRITE_ONCE(b->irq_armed, true);

	/* Requests may have completed before we could enable the interrupt. */
	if (!b->irq_enabled++ && irq_enable(b->irq_engine))
	if (!b->irq_enabled++ && b->irq_enable(b))
		irq_work_queue(&b->irq_work);
}

@@ -76,7 +62,7 @@ static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b)
{
	GEM_BUG_ON(!b->irq_enabled);
	if (!--b->irq_enabled)
		irq_disable(b->irq_engine);
		b->irq_disable(b);

	WRITE_ONCE(b->irq_armed, false);
	intel_gt_pm_put_async(b->irq_engine->gt);
@@ -281,7 +267,7 @@ intel_breadcrumbs_create(struct intel_engine_cs *irq_engine)
	if (!b)
		return NULL;

	b->irq_engine = irq_engine;
	kref_init(&b->ref);

	spin_lock_init(&b->signalers_lock);
	INIT_LIST_HEAD(&b->signalers);
@@ -290,6 +276,10 @@ intel_breadcrumbs_create(struct intel_engine_cs *irq_engine)
	spin_lock_init(&b->irq_lock);
	init_irq_work(&b->irq_work, signal_irq_work);

	b->irq_engine = irq_engine;
	b->irq_enable = irq_enable;
	b->irq_disable = irq_disable;

	return b;
}

@@ -303,9 +293,9 @@ void intel_breadcrumbs_reset(struct intel_breadcrumbs *b)
	spin_lock_irqsave(&b->irq_lock, flags);

	if (b->irq_enabled)
		irq_enable(b->irq_engine);
		b->irq_enable(b);
	else
		irq_disable(b->irq_engine);
		b->irq_disable(b);

	spin_unlock_irqrestore(&b->irq_lock, flags);
}
@@ -325,11 +315,14 @@ void __intel_breadcrumbs_park(struct intel_breadcrumbs *b)
	}
}

void intel_breadcrumbs_free(struct intel_breadcrumbs *b)
void intel_breadcrumbs_free(struct kref *kref)
{
	struct intel_breadcrumbs *b = container_of(kref, typeof(*b), ref);

	irq_work_sync(&b->irq_work);
	GEM_BUG_ON(!list_empty(&b->signalers));
	GEM_BUG_ON(b->irq_armed);

	kfree(b);
}

+14 −2
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
#include <linux/atomic.h>
#include <linux/irq_work.h>

#include "intel_engine_types.h"
#include "intel_breadcrumbs_types.h"

struct drm_printer;
struct i915_request;
@@ -17,7 +17,7 @@ struct intel_breadcrumbs;

struct intel_breadcrumbs *
intel_breadcrumbs_create(struct intel_engine_cs *irq_engine);
void intel_breadcrumbs_free(struct intel_breadcrumbs *b);
void intel_breadcrumbs_free(struct kref *kref);

void intel_breadcrumbs_reset(struct intel_breadcrumbs *b);
void __intel_breadcrumbs_park(struct intel_breadcrumbs *b);
@@ -48,4 +48,16 @@ void i915_request_cancel_breadcrumb(struct i915_request *request);
void intel_context_remove_breadcrumbs(struct intel_context *ce,
				      struct intel_breadcrumbs *b);

static inline struct intel_breadcrumbs *
intel_breadcrumbs_get(struct intel_breadcrumbs *b)
{
	kref_get(&b->ref);
	return b;
}

static inline void intel_breadcrumbs_put(struct intel_breadcrumbs *b)
{
	kref_put(&b->ref, intel_breadcrumbs_free);
}

#endif /* __INTEL_BREADCRUMBS__ */
+7 −0
Original line number Diff line number Diff line
@@ -7,10 +7,13 @@
#define __INTEL_BREADCRUMBS_TYPES__

#include <linux/irq_work.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/types.h>

#include "intel_engine_types.h"

/*
 * Rather than have every client wait upon all user interrupts,
 * with the herd waking after every interrupt and each doing the
@@ -29,6 +32,7 @@
 * the overhead of waking that client is much preferred.
 */
struct intel_breadcrumbs {
	struct kref ref;
	atomic_t active;

	spinlock_t signalers_lock; /* protects the list of signalers */
@@ -42,7 +46,10 @@ struct intel_breadcrumbs {
	bool irq_armed;

	/* Not all breadcrumbs are attached to physical HW */
	intel_engine_mask_t	engine_mask;
	struct intel_engine_cs *irq_engine;
	bool	(*irq_enable)(struct intel_breadcrumbs *b);
	void	(*irq_disable)(struct intel_breadcrumbs *b);
};

#endif /* __INTEL_BREADCRUMBS_TYPES__ */
+3 −0
Original line number Diff line number Diff line
@@ -212,6 +212,9 @@ void intel_engine_get_instdone(const struct intel_engine_cs *engine,

void intel_engine_init_execlists(struct intel_engine_cs *engine);

bool intel_engine_irq_enable(struct intel_engine_cs *engine);
void intel_engine_irq_disable(struct intel_engine_cs *engine);

static inline void __intel_engine_reset(struct intel_engine_cs *engine,
					bool stalled)
{
+26 −2
Original line number Diff line number Diff line
@@ -798,7 +798,7 @@ static int engine_setup_common(struct intel_engine_cs *engine)
err_cmd_parser:
	i915_sched_engine_put(engine->sched_engine);
err_sched_engine:
	intel_breadcrumbs_free(engine->breadcrumbs);
	intel_breadcrumbs_put(engine->breadcrumbs);
err_status:
	cleanup_status_page(engine);
	return err;
@@ -1007,7 +1007,7 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
	GEM_BUG_ON(!list_empty(&engine->sched_engine->requests));

	i915_sched_engine_put(engine->sched_engine);
	intel_breadcrumbs_free(engine->breadcrumbs);
	intel_breadcrumbs_put(engine->breadcrumbs);

	intel_engine_fini_retire(engine);
	intel_engine_cleanup_cmd_parser(engine);
@@ -1324,6 +1324,30 @@ bool intel_engines_are_idle(struct intel_gt *gt)
	return true;
}

bool intel_engine_irq_enable(struct intel_engine_cs *engine)
{
	if (!engine->irq_enable)
		return false;

	/* Caller disables interrupts */
	spin_lock(&engine->gt->irq_lock);
	engine->irq_enable(engine);
	spin_unlock(&engine->gt->irq_lock);

	return true;
}

void intel_engine_irq_disable(struct intel_engine_cs *engine)
{
	if (!engine->irq_disable)
		return;

	/* Caller disables interrupts */
	spin_lock(&engine->gt->irq_lock);
	engine->irq_disable(engine);
	spin_unlock(&engine->gt->irq_lock);
}

void intel_engines_reset_default_submission(struct intel_gt *gt)
{
	struct intel_engine_cs *engine;
Loading