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

drm/i915/guc: Implement GuC context operations for new inteface



Implement GuC context operations which includes GuC specific operations
alloc, pin, unpin, and destroy.

v2:
 (Daniel Vetter)
  - Use msleep_interruptible rather than cond_resched in busy loop
 (Michal)
  - Remove C++ style comment
v3:
 (Matthew Brost)
  - Drop GUC_ID_START
 (John Harrison)
  - Fix a bunch of typos
  - Use drm_err rather than drm_dbg for G2H errors
 (Daniele)
  - Fix ;; typo
  - Clean up sched state functions
  - Add lockdep for guc_id functions
  - Don't call __release_guc_id when guc_id is invalid
  - Use MISSING_CASE
  - Add comment in guc_context_pin
  - Use shorter path to rpm
 (Daniele / CI)
  - Don't call release_guc_id on an invalid guc_id in destroy
v4:
 (Daniel Vetter)
  - Add FIXME comment

Signed-off-by: default avatarJohn Harrison <John.C.Harrison@Intel.com>
Signed-off-by: default avatarMatthew Brost <matthew.brost@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/20210721215101.139794-7-matthew.brost@intel.com
parent 2330923e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -384,6 +384,11 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine)

	mutex_init(&ce->pin_mutex);

	spin_lock_init(&ce->guc_state.lock);

	ce->guc_id = GUC_INVALID_LRC_ID;
	INIT_LIST_HEAD(&ce->guc_id_link);

	i915_active_init(&ce->active,
			 __intel_context_active, __intel_context_retire, 0);
}
+19 −3
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ struct intel_context {
#define CONTEXT_BANNED			6
#define CONTEXT_FORCE_SINGLE_SUBMISSION	7
#define CONTEXT_NOPREEMPT		8
#define CONTEXT_LRCA_DIRTY		9

	struct {
		u64 timeout_us;
@@ -138,14 +139,29 @@ struct intel_context {

	u8 wa_bb_page; /* if set, page num reserved for context workarounds */

	struct {
		/** lock: protects everything in guc_state */
		spinlock_t lock;
		/**
		 * sched_state: scheduling state of this context using GuC
		 * submission
		 */
		u8 sched_state;
	} guc_state;

	/* GuC scheduling state flags that do not require a lock. */
	atomic_t guc_sched_state_no_lock;

	/* GuC LRC descriptor ID */
	u16 guc_id;

	/* GuC LRC descriptor reference count */
	atomic_t guc_id_ref;

	/*
	 * GuC LRC descriptor ID - Not assigned in this patch but future patches
	 * in the series will.
	 * GuC ID link - in list when unpinned but guc_id still valid in GuC
	 */
	u16 guc_id;
	struct list_head guc_id_link;
};

#endif /* __INTEL_CONTEXT_TYPES__ */
+0 −1
Original line number Diff line number Diff line
@@ -87,7 +87,6 @@
#define GEN11_CSB_WRITE_PTR_MASK	(GEN11_CSB_PTR_MASK << 0)

#define MAX_CONTEXT_HW_ID	(1 << 21) /* exclusive */
#define MAX_GUC_CONTEXT_HW_ID	(1 << 20) /* exclusive */
#define GEN11_MAX_CONTEXT_HW_ID	(1 << 11) /* exclusive */
/* in Gen12 ID 0x7FF is reserved to indicate idle */
#define GEN12_MAX_CONTEXT_HW_ID	(GEN11_MAX_CONTEXT_HW_ID - 1)
+47 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#define _INTEL_GUC_H_

#include <linux/xarray.h>
#include <linux/delay.h>

#include "intel_uncore.h"
#include "intel_guc_fw.h"
@@ -44,6 +45,14 @@ struct intel_guc {
		void (*disable)(struct intel_guc *guc);
	} interrupts;

	/*
	 * contexts_lock protects the pool of free guc ids and a linked list of
	 * guc ids available to be stolen
	 */
	spinlock_t contexts_lock;
	struct ida guc_ids;
	struct list_head guc_id_list;

	bool submission_selected;

	struct i915_vma *ads_vma;
@@ -101,6 +110,41 @@ intel_guc_send_and_receive(struct intel_guc *guc, const u32 *action, u32 len,
				 response_buf, response_buf_size, 0);
}

static inline int intel_guc_send_busy_loop(struct intel_guc *guc,
					   const u32 *action,
					   u32 len,
					   bool loop)
{
	int err;
	unsigned int sleep_period_ms = 1;
	bool not_atomic = !in_atomic() && !irqs_disabled();

	/*
	 * FIXME: Have caller pass in if we are in an atomic context to avoid
	 * using in_atomic(). It is likely safe here as we check for irqs
	 * disabled which basically all the spin locks in the i915 do but
	 * regardless this should be cleaned up.
	 */

	/* No sleeping with spin locks, just busy loop */
	might_sleep_if(loop && not_atomic);

retry:
	err = intel_guc_send_nb(guc, action, len);
	if (unlikely(err == -EBUSY && loop)) {
		if (likely(not_atomic)) {
			if (msleep_interruptible(sleep_period_ms))
				return -EINTR;
			sleep_period_ms = sleep_period_ms << 1;
		} else {
			cpu_relax();
		}
		goto retry;
	}

	return err;
}

static inline void intel_guc_to_host_event_handler(struct intel_guc *guc)
{
	intel_guc_ct_event_handler(&guc->ct);
@@ -202,6 +246,9 @@ static inline void intel_guc_disable_msg(struct intel_guc *guc, u32 mask)
int intel_guc_reset_engine(struct intel_guc *guc,
			   struct intel_engine_cs *engine);

int intel_guc_deregister_done_process_msg(struct intel_guc *guc,
					  const u32 *msg, u32 len);

void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p);

#endif
+4 −0
Original line number Diff line number Diff line
@@ -928,6 +928,10 @@ static int ct_process_request(struct intel_guc_ct *ct, struct ct_incoming_msg *r
	case INTEL_GUC_ACTION_DEFAULT:
		ret = intel_guc_to_host_process_recv_msg(guc, payload, len);
		break;
	case INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
		ret = intel_guc_deregister_done_process_msg(guc, payload,
							    len);
		break;
	default:
		ret = -EOPNOTSUPP;
		break;
Loading