Skip to content

Commit af58ee2

Browse files
kvprathapAndi Shyti
authored andcommitted
drm/i915: Define and use GuC and CTB TLB invalidation routines
The GuC firmware had defined the interface for Translation Look-Aside Buffer (TLB) invalidation. We should use this interface when invalidating the engine and GuC TLBs. Add additional functionality to intel_gt_invalidate_tlb, invalidating the GuC TLBs and falling back to GT invalidation when the GuC is disabled. The invalidation is done by sending a request directly to the GuC tlb_lookup that invalidates the table. The invalidation is submitted as a wait request and is performed in the CT event handler. This means we cannot perform this TLB invalidation path if the CT is not enabled. If the request isn't fulfilled in two seconds, this would constitute an error in the invalidation as that would constitute either a lost request or a severe GuC overload. With this new invalidation routine, we can perform GuC-based GGTT invalidations. GuC-based GGTT invalidation is incompatible with MMIO invalidation so we should not perform MMIO invalidation when GuC-based GGTT invalidation is expected. The additional complexity incurred in this patch will be necessary for range-based tlb invalidations, which will be platformed in the future. Signed-off-by: Prathap Kumar Valsan <[email protected]> Signed-off-by: Bruce Chang <[email protected]> Signed-off-by: Chris Wilson <[email protected]> Signed-off-by: Umesh Nerlige Ramappa <[email protected]> Signed-off-by: Jonathan Cavitt <[email protected]> Signed-off-by: Aravind Iddamsetty <[email protected]> Signed-off-by: Fei Yang <[email protected]> CC: Andi Shyti <[email protected]> Reviewed-by: Andi Shyti <[email protected]> Acked-by: Tvrtko Ursulin <[email protected]> Acked-by: Nirmoy Das <[email protected]> Reviewed-by: John Harrison <[email protected]> Signed-off-by: Andi Shyti <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent ff0dac0 commit af58ee2

File tree

7 files changed

+299
-11
lines changed

7 files changed

+299
-11
lines changed

drivers/gpu/drm/i915/gt/intel_ggtt.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -206,22 +206,36 @@ static void gen8_ggtt_invalidate(struct i915_ggtt *ggtt)
206206
intel_uncore_write_fw(uncore, GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
207207
}
208208

209+
static void guc_ggtt_ct_invalidate(struct intel_gt *gt)
210+
{
211+
struct intel_uncore *uncore = gt->uncore;
212+
intel_wakeref_t wakeref;
213+
214+
with_intel_runtime_pm_if_active(uncore->rpm, wakeref) {
215+
struct intel_guc *guc = &gt->uc.guc;
216+
217+
intel_guc_invalidate_tlb_guc(guc);
218+
}
219+
}
220+
209221
static void guc_ggtt_invalidate(struct i915_ggtt *ggtt)
210222
{
211223
struct drm_i915_private *i915 = ggtt->vm.i915;
224+
struct intel_gt *gt;
212225

213226
gen8_ggtt_invalidate(ggtt);
214227

215-
if (GRAPHICS_VER(i915) >= 12) {
216-
struct intel_gt *gt;
217-
218-
list_for_each_entry(gt, &ggtt->gt_list, ggtt_link)
228+
list_for_each_entry(gt, &ggtt->gt_list, ggtt_link) {
229+
if (intel_guc_tlb_invalidation_is_available(&gt->uc.guc)) {
230+
guc_ggtt_ct_invalidate(gt);
231+
} else if (GRAPHICS_VER(i915) >= 12) {
219232
intel_uncore_write_fw(gt->uncore,
220233
GEN12_GUC_TLB_INV_CR,
221234
GEN12_GUC_TLB_INV_CR_INVALIDATE);
222-
} else {
223-
intel_uncore_write_fw(ggtt->vm.gt->uncore,
224-
GEN8_GTCR, GEN8_GTCR_INVALIDATE);
235+
} else {
236+
intel_uncore_write_fw(gt->uncore,
237+
GEN8_GTCR, GEN8_GTCR_INVALIDATE);
238+
}
225239
}
226240
}
227241

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

1246-
if (intel_uc_wants_guc(&ggtt->vm.gt->uc))
1260+
if (intel_uc_wants_guc_submission(&ggtt->vm.gt->uc))
12471261
ggtt->invalidate = guc_ggtt_invalidate;
12481262
else
12491263
ggtt->invalidate = gen8_ggtt_invalidate;

drivers/gpu/drm/i915/gt/intel_tlb.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "intel_gt_print.h"
1313
#include "intel_gt_regs.h"
1414
#include "intel_tlb.h"
15+
#include "uc/intel_guc.h"
1516

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

133134
with_intel_gt_pm_if_awake(gt, wakeref) {
135+
struct intel_guc *guc = &gt->uc.guc;
136+
134137
mutex_lock(&gt->tlb.invalidate_lock);
135138
if (tlb_seqno_passed(gt, seqno))
136139
goto unlock;
137140

138-
mmio_invalidate_full(gt);
141+
if (HAS_GUC_TLB_INVALIDATION(gt->i915)) {
142+
/*
143+
* Only perform GuC TLB invalidation if GuC is ready.
144+
* The only time GuC could not be ready is on GT reset,
145+
* which would clobber all the TLBs anyways, making
146+
* any TLB invalidation path here unnecessary.
147+
*/
148+
if (intel_guc_is_ready(guc))
149+
intel_guc_invalidate_tlb_engines(guc);
150+
} else {
151+
mmio_invalidate_full(gt);
152+
}
139153

140154
write_seqcount_invalidate(&gt->tlb.seqno);
141155
unlock:

drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ enum intel_guc_action {
138138
INTEL_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC = 0x4601,
139139
INTEL_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507,
140140
INTEL_GUC_ACTION_SET_ENG_UTIL_BUFF = 0x550A,
141+
INTEL_GUC_ACTION_TLB_INVALIDATION = 0x7000,
142+
INTEL_GUC_ACTION_TLB_INVALIDATION_DONE = 0x7001,
141143
INTEL_GUC_ACTION_STATE_CAPTURE_NOTIFICATION = 0x8002,
142144
INTEL_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE = 0x8003,
143145
INTEL_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED = 0x8004,
@@ -181,4 +183,35 @@ enum intel_guc_state_capture_event_status {
181183

182184
#define INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK 0x000000FF
183185

186+
#define INTEL_GUC_TLB_INVAL_TYPE_MASK REG_GENMASK(7, 0)
187+
#define INTEL_GUC_TLB_INVAL_MODE_MASK REG_GENMASK(11, 8)
188+
#define INTEL_GUC_TLB_INVAL_FLUSH_CACHE REG_BIT(31)
189+
190+
enum intel_guc_tlb_invalidation_type {
191+
INTEL_GUC_TLB_INVAL_ENGINES = 0x0,
192+
INTEL_GUC_TLB_INVAL_GUC = 0x3,
193+
};
194+
195+
/*
196+
* 0: Heavy mode of Invalidation:
197+
* The pipeline of the engine(s) for which the invalidation is targeted to is
198+
* blocked, and all the in-flight transactions are guaranteed to be Globally
199+
* Observed before completing the TLB invalidation
200+
* 1: Lite mode of Invalidation:
201+
* TLBs of the targeted engine(s) are immediately invalidated.
202+
* In-flight transactions are NOT guaranteed to be Globally Observed before
203+
* completing TLB invalidation.
204+
* Light Invalidation Mode is to be used only when
205+
* it can be guaranteed (by SW) that the address translations remain invariant
206+
* for the in-flight transactions across the TLB invalidation. In other words,
207+
* this mode can be used when the TLB invalidation is intended to clear out the
208+
* stale cached translations that are no longer in use. Light Invalidation Mode
209+
* is much faster than the Heavy Invalidation Mode, as it does not wait for the
210+
* in-flight transactions to be GOd.
211+
*/
212+
enum intel_guc_tlb_inval_mode {
213+
INTEL_GUC_TLB_INVAL_MODE_HEAVY = 0x0,
214+
INTEL_GUC_TLB_INVAL_MODE_LITE = 0x1,
215+
};
216+
184217
#endif /* _ABI_GUC_ACTIONS_ABI_H */

drivers/gpu/drm/i915/gt/uc/intel_guc.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ struct intel_guc {
7979
*/
8080
atomic_t outstanding_submission_g2h;
8181

82+
/** @tlb_lookup: xarray to store all pending TLB invalidation requests */
83+
struct xarray tlb_lookup;
84+
85+
/**
86+
* @serial_slot: id to the initial waiter created in tlb_lookup,
87+
* which is used only when failed to allocate new waiter.
88+
*/
89+
u32 serial_slot;
90+
91+
/** @next_seqno: the next id (sequence number) to allocate. */
92+
u32 next_seqno;
93+
8294
/** @interrupts: pointers to GuC interrupt-managing functions. */
8395
struct {
8496
bool enabled;
@@ -288,6 +300,11 @@ struct intel_guc {
288300
#endif
289301
};
290302

303+
struct intel_guc_tlb_wait {
304+
struct wait_queue_head wq;
305+
bool busy;
306+
};
307+
291308
/*
292309
* GuC version number components are only 8-bit, so converting to a 32bit 8.8.8
293310
* integer works.
@@ -515,4 +532,9 @@ void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p);
515532

516533
int intel_guc_sched_disable_gucid_threshold_max(struct intel_guc *guc);
517534

535+
bool intel_guc_tlb_invalidation_is_available(struct intel_guc *guc);
536+
int intel_guc_invalidate_tlb_engines(struct intel_guc *guc);
537+
int intel_guc_invalidate_tlb_guc(struct intel_guc *guc);
538+
int intel_guc_tlb_invalidation_done(struct intel_guc *guc,
539+
const u32 *payload, u32 len);
518540
#endif

drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,9 @@ static int ct_process_request(struct intel_guc_ct *ct, struct ct_incoming_msg *r
11421142
case INTEL_GUC_ACTION_NOTIFY_EXCEPTION:
11431143
ret = intel_guc_crash_process_msg(guc, action);
11441144
break;
1145+
case INTEL_GUC_ACTION_TLB_INVALIDATION_DONE:
1146+
ret = intel_guc_tlb_invalidation_done(guc, payload, len);
1147+
break;
11451148
default:
11461149
ret = -EOPNOTSUPP;
11471150
break;
@@ -1213,9 +1216,17 @@ static int ct_handle_event(struct intel_guc_ct *ct, struct ct_incoming_msg *requ
12131216
switch (action) {
12141217
case INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE:
12151218
case INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
1219+
case INTEL_GUC_ACTION_TLB_INVALIDATION_DONE:
12161220
g2h_release_space(ct, request->size);
12171221
}
12181222

1223+
/*
1224+
* TLB invalidation responses must be handled immediately as processing
1225+
* of other G2H notifications may be blocked by an invalidation request.
1226+
*/
1227+
if (action == INTEL_GUC_ACTION_TLB_INVALIDATION_DONE)
1228+
return ct_process_request(ct, request);
1229+
12191230
spin_lock_irqsave(&ct->requests.lock, flags);
12201231
list_add_tail(&request->link, &ct->requests.incoming);
12211232
spin_unlock_irqrestore(&ct->requests.lock, flags);

drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
/* Payload length only i.e. don't include G2H header length */
2323
#define G2H_LEN_DW_SCHED_CONTEXT_MODE_SET 2
2424
#define G2H_LEN_DW_DEREGISTER_CONTEXT 1
25+
#define G2H_LEN_DW_INVALIDATE_TLB 1
2526

2627
#define GUC_CONTEXT_DISABLE 0
2728
#define GUC_CONTEXT_ENABLE 1

0 commit comments

Comments
 (0)