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

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
......@@ -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);
}
......
......@@ -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__ */
......@@ -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)
......
......@@ -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
......@@ -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;
......
......@@ -4142,6 +4142,7 @@ enum {
FAULT_AND_CONTINUE /* Unsupported */
};
#define CTX_GTT_ADDRESS_MASK GENMASK(31, 12)
#define GEN8_CTX_VALID (1 << 0)
#define GEN8_CTX_FORCE_PD_RESTORE (1 << 1)
#define GEN8_CTX_FORCE_RESTORE (1 << 2)
......
......@@ -407,6 +407,7 @@ bool i915_request_retire(struct i915_request *rq)
*/
if (!list_empty(&rq->sched.link))
remove_from_engine(rq);
atomic_dec(&rq->context->guc_id_ref);
GEM_BUG_ON(!llist_empty(&rq->execute_cb));
__list_del_entry(&rq->link); /* poison neither prev/next (RCU walks) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment