Skip to content

Commit

Permalink
Merge tag 'drm-intel-gt-next-2023-10-19' of git://anongit.freedesktop…
Browse files Browse the repository at this point in the history
….org/drm/drm-intel into drm-next

Driver Changes:

Fixes/improvements/new stuff:

- Retry gtt fault when out of fence registers (Ville Syrjälä)
- Determine context valid in OA reports [perf] (Umesh Nerlige Ramappa)

Future platform enablement:

- GuC based TLB invalidation for Meteorlake (Jonathan Cavitt, Prathap Kumar Valsan)
- Don't set PIPE_CONTROL_FLUSH_L3 [mtl] (Vinay Belgaumkar)

Miscellaneous:

- Clean up zero initializers [guc,pxp] (Ville Syrjälä)
- Prevent potential null-ptr-deref in engine_init_common (Nirmoy Das)

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ZTFDFSbd/U7YP+hI@tursulin-desk
  • Loading branch information
Dave Airlie committed Oct 20, 2023
2 parents 3ac5fa3 + 7eeaedf commit 55b7285
Showing 21 changed files with 407 additions and 30 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/gem/i915_gem_mman.c
Original file line number Diff line number Diff line change
@@ -235,6 +235,7 @@ static vm_fault_t i915_error_to_vmf_fault(int err)
case 0:
case -EAGAIN:
case -ENOSPC: /* transient failure to evict? */
case -ENOBUFS: /* temporarily out of fences? */
case -ERESTARTSYS:
case -EINTR:
case -EBUSY:
7 changes: 5 additions & 2 deletions drivers/gpu/drm/i915/gt/gen8_engine_cs.c
Original file line number Diff line number Diff line change
@@ -278,7 +278,8 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode)
* deals with Protected Memory which is not needed for
* AUX CCS invalidation and lead to unwanted side effects.
*/
if (mode & EMIT_FLUSH)
if ((mode & EMIT_FLUSH) &&
GRAPHICS_VER_FULL(rq->i915) < IP_VER(12, 70))
bit_group_1 |= PIPE_CONTROL_FLUSH_L3;

bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH;
@@ -812,12 +813,14 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs)
u32 flags = (PIPE_CONTROL_CS_STALL |
PIPE_CONTROL_TLB_INVALIDATE |
PIPE_CONTROL_TILE_CACHE_FLUSH |
PIPE_CONTROL_FLUSH_L3 |
PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
PIPE_CONTROL_DEPTH_CACHE_FLUSH |
PIPE_CONTROL_DC_FLUSH_ENABLE |
PIPE_CONTROL_FLUSH_ENABLE);

if (GRAPHICS_VER_FULL(rq->i915) < IP_VER(12, 70))
flags |= PIPE_CONTROL_FLUSH_L3;

/* Wa_14016712196 */
if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || IS_DG2(i915))
/* dummy PIPE_CONTROL + depth flush */
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/gt/intel_engine_cs.c
Original file line number Diff line number Diff line change
@@ -1491,7 +1491,8 @@ static int engine_init_common(struct intel_engine_cs *engine)
return 0;

err_bce_context:
intel_engine_destroy_pinned_context(bce);
if (bce)
intel_engine_destroy_pinned_context(bce);
err_ce_context:
intel_engine_destroy_pinned_context(ce);
return ret;
30 changes: 22 additions & 8 deletions drivers/gpu/drm/i915/gt/intel_ggtt.c
Original file line number Diff line number Diff line change
@@ -206,22 +206,36 @@ static void gen8_ggtt_invalidate(struct i915_ggtt *ggtt)
intel_uncore_write_fw(uncore, GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
}

static void guc_ggtt_ct_invalidate(struct intel_gt *gt)
{
struct intel_uncore *uncore = gt->uncore;
intel_wakeref_t wakeref;

with_intel_runtime_pm_if_active(uncore->rpm, wakeref) {
struct intel_guc *guc = &gt->uc.guc;

intel_guc_invalidate_tlb_guc(guc);
}
}

static void guc_ggtt_invalidate(struct i915_ggtt *ggtt)
{
struct drm_i915_private *i915 = ggtt->vm.i915;
struct intel_gt *gt;

gen8_ggtt_invalidate(ggtt);

if (GRAPHICS_VER(i915) >= 12) {
struct intel_gt *gt;

list_for_each_entry(gt, &ggtt->gt_list, ggtt_link)
list_for_each_entry(gt, &ggtt->gt_list, ggtt_link) {
if (intel_guc_tlb_invalidation_is_available(&gt->uc.guc)) {
guc_ggtt_ct_invalidate(gt);
} else if (GRAPHICS_VER(i915) >= 12) {
intel_uncore_write_fw(gt->uncore,
GEN12_GUC_TLB_INV_CR,
GEN12_GUC_TLB_INV_CR_INVALIDATE);
} else {
intel_uncore_write_fw(ggtt->vm.gt->uncore,
GEN8_GTCR, GEN8_GTCR_INVALIDATE);
} else {
intel_uncore_write_fw(gt->uncore,
GEN8_GTCR, GEN8_GTCR_INVALIDATE);
}
}
}

@@ -1243,7 +1257,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
ggtt->vm.raw_insert_page = gen8_ggtt_insert_page;
}

if (intel_uc_wants_guc(&ggtt->vm.gt->uc))
if (intel_uc_wants_guc_submission(&ggtt->vm.gt->uc))
ggtt->invalidate = guc_ggtt_invalidate;
else
ggtt->invalidate = gen8_ggtt_invalidate;
16 changes: 15 additions & 1 deletion drivers/gpu/drm/i915/gt/intel_tlb.c
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
#include "intel_gt_print.h"
#include "intel_gt_regs.h"
#include "intel_tlb.h"
#include "uc/intel_guc.h"

/*
* HW architecture suggest typical invalidation time at 40us,
@@ -131,11 +132,24 @@ void intel_gt_invalidate_tlb_full(struct intel_gt *gt, u32 seqno)
return;

with_intel_gt_pm_if_awake(gt, wakeref) {
struct intel_guc *guc = &gt->uc.guc;

mutex_lock(&gt->tlb.invalidate_lock);
if (tlb_seqno_passed(gt, seqno))
goto unlock;

mmio_invalidate_full(gt);
if (HAS_GUC_TLB_INVALIDATION(gt->i915)) {
/*
* Only perform GuC TLB invalidation if GuC is ready.
* The only time GuC could not be ready is on GT reset,
* which would clobber all the TLBs anyways, making
* any TLB invalidation path here unnecessary.
*/
if (intel_guc_is_ready(guc))
intel_guc_invalidate_tlb_engines(guc);
} else {
mmio_invalidate_full(gt);
}

write_seqcount_invalidate(&gt->tlb.seqno);
unlock:
11 changes: 9 additions & 2 deletions drivers/gpu/drm/i915/gt/selftest_tlb.c
Original file line number Diff line number Diff line change
@@ -136,8 +136,15 @@ pte_tlbinv(struct intel_context *ce,
i915_request_get(rq);
i915_request_add(rq);

/* Short sleep to sanitycheck the batch is spinning before we begin */
msleep(10);
/*
* Short sleep to sanitycheck the batch is spinning before we begin.
* FIXME: Why is GSC so slow?
*/
if (ce->engine->class == OTHER_CLASS)
msleep(200);
else
msleep(10);

if (va == vb) {
if (!i915_request_completed(rq)) {
pr_err("%s(%s): Semaphore sanitycheck failed %llx, with alignment %llx, using PTE size %x (phys %x, sg %x)\n",
33 changes: 33 additions & 0 deletions drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
Original file line number Diff line number Diff line change
@@ -138,6 +138,8 @@ enum intel_guc_action {
INTEL_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC = 0x4601,
INTEL_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507,
INTEL_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A,
INTEL_GUC_ACTION_TLB_INVALIDATION = 0x7000,
INTEL_GUC_ACTION_TLB_INVALIDATION_DONE = 0x7001,
INTEL_GUC_ACTION_STATE_CAPTURE_NOTIFICATION = 0x8002,
INTEL_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE = 0x8003,
INTEL_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED = 0x8004,
@@ -181,4 +183,35 @@ enum intel_guc_state_capture_event_status {

#define INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK 0x000000FF

#define INTEL_GUC_TLB_INVAL_TYPE_MASK REG_GENMASK(7, 0)
#define INTEL_GUC_TLB_INVAL_MODE_MASK REG_GENMASK(11, 8)
#define INTEL_GUC_TLB_INVAL_FLUSH_CACHE REG_BIT(31)

enum intel_guc_tlb_invalidation_type {
INTEL_GUC_TLB_INVAL_ENGINES = 0x0,
INTEL_GUC_TLB_INVAL_GUC = 0x3,
};

/*
* 0: Heavy mode of Invalidation:
* The pipeline of the engine(s) for which the invalidation is targeted to is
* blocked, and all the in-flight transactions are guaranteed to be Globally
* Observed before completing the TLB invalidation
* 1: Lite mode of Invalidation:
* TLBs of the targeted engine(s) are immediately invalidated.
* In-flight transactions are NOT guaranteed to be Globally Observed before
* completing TLB invalidation.
* Light Invalidation Mode is to be used only when
* it can be guaranteed (by SW) that the address translations remain invariant
* for the in-flight transactions across the TLB invalidation. In other words,
* this mode can be used when the TLB invalidation is intended to clear out the
* stale cached translations that are no longer in use. Light Invalidation Mode
* is much faster than the Heavy Invalidation Mode, as it does not wait for the
* in-flight transactions to be GOd.
*/
enum intel_guc_tlb_inval_mode {
INTEL_GUC_TLB_INVAL_MODE_HEAVY = 0x0,
INTEL_GUC_TLB_INVAL_MODE_LITE = 0x1,
};

#endif /* _ABI_GUC_ACTIONS_ABI_H */
23 changes: 23 additions & 0 deletions drivers/gpu/drm/i915/gt/uc/intel_guc.h
Original file line number Diff line number Diff line change
@@ -79,6 +79,18 @@ struct intel_guc {
*/
atomic_t outstanding_submission_g2h;

/** @tlb_lookup: xarray to store all pending TLB invalidation requests */
struct xarray tlb_lookup;

/**
* @serial_slot: id to the initial waiter created in tlb_lookup,
* which is used only when failed to allocate new waiter.
*/
u32 serial_slot;

/** @next_seqno: the next id (sequence number) to allocate. */
u32 next_seqno;

/** @interrupts: pointers to GuC interrupt-managing functions. */
struct {
bool enabled;
@@ -288,6 +300,11 @@ struct intel_guc {
#endif
};

struct intel_guc_tlb_wait {
struct wait_queue_head wq;
bool busy;
};

/*
* GuC version number components are only 8-bit, so converting to a 32bit 8.8.8
* integer works.
@@ -515,4 +532,10 @@ void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p);

int intel_guc_sched_disable_gucid_threshold_max(struct intel_guc *guc);

bool intel_guc_tlb_invalidation_is_available(struct intel_guc *guc);
int intel_guc_invalidate_tlb_engines(struct intel_guc *guc);
int intel_guc_invalidate_tlb_guc(struct intel_guc *guc);
int intel_guc_tlb_invalidation_done(struct intel_guc *guc,
const u32 *payload, u32 len);
void wake_up_all_tlb_invalidate(struct intel_guc *guc);
#endif
4 changes: 2 additions & 2 deletions drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
Original file line number Diff line number Diff line change
@@ -1101,8 +1101,8 @@ guc_capture_create_prealloc_nodes(struct intel_guc *guc)
static int
guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstate *buf)
{
struct guc_state_capture_group_header_t ghdr = {0};
struct guc_state_capture_header_t hdr = {0};
struct guc_state_capture_group_header_t ghdr = {};
struct guc_state_capture_header_t hdr = {};
struct __guc_capture_parsed_output *node = NULL;
struct guc_mmio_reg *regs = NULL;
int i, numlists, numregs, ret = 0;
38 changes: 38 additions & 0 deletions drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
Original file line number Diff line number Diff line change
@@ -103,6 +103,33 @@ enum { CTB_SEND = 0, CTB_RECV = 1 };

enum { CTB_OWNER_HOST = 0 };

/*
* Some H2G commands involve a synchronous response that the driver needs
* to wait for. In such cases, a timeout is required to prevent the driver
* from waiting forever in the case of an error (either no error response
* is defined in the protocol or something has died and requires a reset).
* The specific command may be defined as having a time bound response but
* the CT is a queue and that time guarantee only starts from the point
* when the command reaches the head of the queue and is processed by GuC.
*
* Ideally there would be a helper to report the progress of a given
* command through the CT. However, that would require a significant
* amount of work in the CT layer. In the meantime, provide a reasonable
* estimation of the worst case latency it should take for the entire
* queue to drain. And therefore, how long a caller should wait before
* giving up on their request. The current estimate is based on empirical
* measurement of a test that fills the buffer with context creation and
* destruction requests as they seem to be the slowest operation.
*/
long intel_guc_ct_max_queue_time_jiffies(void)
{
/*
* A 4KB buffer full of context destroy commands takes a little
* over a second to process so bump that to 2s to be super safe.
*/
return (CTB_H2G_BUFFER_SIZE * HZ) / SZ_2K;
}

static void ct_receive_tasklet_func(struct tasklet_struct *t);
static void ct_incoming_request_worker_func(struct work_struct *w);

@@ -1115,6 +1142,9 @@ static int ct_process_request(struct intel_guc_ct *ct, struct ct_incoming_msg *r
case INTEL_GUC_ACTION_NOTIFY_EXCEPTION:
ret = intel_guc_crash_process_msg(guc, action);
break;
case INTEL_GUC_ACTION_TLB_INVALIDATION_DONE:
ret = intel_guc_tlb_invalidation_done(guc, payload, len);
break;
default:
ret = -EOPNOTSUPP;
break;
@@ -1186,9 +1216,17 @@ static int ct_handle_event(struct intel_guc_ct *ct, struct ct_incoming_msg *requ
switch (action) {
case INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE:
case INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
case INTEL_GUC_ACTION_TLB_INVALIDATION_DONE:
g2h_release_space(ct, request->size);
}

/*
* TLB invalidation responses must be handled immediately as processing
* of other G2H notifications may be blocked by an invalidation request.
*/
if (action == INTEL_GUC_ACTION_TLB_INVALIDATION_DONE)
return ct_process_request(ct, request);

spin_lock_irqsave(&ct->requests.lock, flags);
list_add_tail(&request->link, &ct->requests.incoming);
spin_unlock_irqrestore(&ct->requests.lock, flags);
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
Original file line number Diff line number Diff line change
@@ -104,6 +104,8 @@ struct intel_guc_ct {
#endif
};

long intel_guc_ct_max_queue_time_jiffies(void);

void intel_guc_ct_init_early(struct intel_guc_ct *ct);
int intel_guc_ct_init(struct intel_guc_ct *ct);
void intel_guc_ct_fini(struct intel_guc_ct *ct);
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
/* Payload length only i.e. don't include G2H header length */
#define G2H_LEN_DW_SCHED_CONTEXT_MODE_SET 2
#define G2H_LEN_DW_DEREGISTER_CONTEXT 1
#define G2H_LEN_DW_INVALIDATE_TLB 1

#define GUC_CONTEXT_DISABLE 0
#define GUC_CONTEXT_ENABLE 1
Loading

0 comments on commit 55b7285

Please sign in to comment.