xref: /linux/drivers/gpu/drm/xe/xe_mocs.c (revision dd08ebf6c3525a7ea2186e636df064ea47281987)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include "xe_bo.h"
7 #include "xe_device.h"
8 #include "xe_engine.h"
9 #include "xe_gt.h"
10 #include "xe_platform_types.h"
11 #include "xe_mmio.h"
12 #include "xe_mocs.h"
13 #include "xe_step_types.h"
14 
15 #include "gt/intel_gt_regs.h"
16 
17 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
18 #define mocs_dbg drm_dbg
19 #else
20 __printf(2, 3)
21 static inline void mocs_dbg(const struct drm_device *dev,
22 			    const char *format, ...)
23 { /* noop */ }
24 #endif
25 
26 /*
27  * MOCS indexes used for GPU surfaces, defining the cacheability of the
28  * surface data and the coherency for this data wrt. CPU vs. GPU accesses.
29  */
30 enum xe_mocs_info_index {
31 	/*
32 	 * Not cached anywhere, coherency between CPU and GPU accesses is
33 	 * guaranteed.
34 	 */
35 	XE_MOCS_UNCACHED,
36 	/*
37 	 * Cacheability and coherency controlled by the kernel automatically
38 	 * based on the xxxx  IOCTL setting and the current
39 	 * usage of the surface (used for display scanout or not).
40 	 */
41 	XE_MOCS_PTE,
42 	/*
43 	 * Cached in all GPU caches available on the platform.
44 	 * Coherency between CPU and GPU accesses to the surface is not
45 	 * guaranteed without extra synchronization.
46 	 */
47 	XE_MOCS_CACHED,
48 };
49 
50 enum {
51 	HAS_GLOBAL_MOCS = BIT(0),
52 	HAS_RENDER_L3CC = BIT(1),
53 };
54 
55 struct xe_mocs_entry {
56 	u32 control_value;
57 	u16 l3cc_value;
58 	u16 used;
59 };
60 
61 struct xe_mocs_info {
62 	unsigned int size;
63 	unsigned int n_entries;
64 	const struct xe_mocs_entry *table;
65 	u8 uc_index;
66 	u8 wb_index;
67 	u8 unused_entries_index;
68 };
69 
70 /* Defines for the tables (XXX_MOCS_0 - XXX_MOCS_63) */
71 #define _LE_CACHEABILITY(value)	((value) << 0)
72 #define _LE_TGT_CACHE(value)	((value) << 2)
73 #define LE_LRUM(value)		((value) << 4)
74 #define LE_AOM(value)		((value) << 6)
75 #define LE_RSC(value)		((value) << 7)
76 #define LE_SCC(value)		((value) << 8)
77 #define LE_PFM(value)		((value) << 11)
78 #define LE_SCF(value)		((value) << 14)
79 #define LE_COS(value)		((value) << 15)
80 #define LE_SSE(value)		((value) << 17)
81 
82 /* Defines for the tables (LNCFMOCS0 - LNCFMOCS31) - two entries per word */
83 #define L3_ESC(value)		((value) << 0)
84 #define L3_SCC(value)		((value) << 1)
85 #define _L3_CACHEABILITY(value)	((value) << 4)
86 #define L3_GLBGO(value)		((value) << 6)
87 #define L3_LKUP(value)		((value) << 7)
88 
89 /* Helper defines */
90 #define GEN9_NUM_MOCS_ENTRIES	64  /* 63-64 are reserved, but configured. */
91 #define PVC_NUM_MOCS_ENTRIES	3
92 #define MTL_NUM_MOCS_ENTRIES    16
93 
94 /* (e)LLC caching options */
95 /*
96  * Note: LE_0_PAGETABLE works only up to Gen11; for newer gens it means
97  * the same as LE_UC
98  */
99 #define LE_0_PAGETABLE		_LE_CACHEABILITY(0)
100 #define LE_1_UC			_LE_CACHEABILITY(1)
101 #define LE_2_WT			_LE_CACHEABILITY(2)
102 #define LE_3_WB			_LE_CACHEABILITY(3)
103 
104 /* Target cache */
105 #define LE_TC_0_PAGETABLE	_LE_TGT_CACHE(0)
106 #define LE_TC_1_LLC		_LE_TGT_CACHE(1)
107 #define LE_TC_2_LLC_ELLC	_LE_TGT_CACHE(2)
108 #define LE_TC_3_LLC_ELLC_ALT	_LE_TGT_CACHE(3)
109 
110 /* L3 caching options */
111 #define L3_0_DIRECT		_L3_CACHEABILITY(0)
112 #define L3_1_UC			_L3_CACHEABILITY(1)
113 #define L3_2_RESERVED		_L3_CACHEABILITY(2)
114 #define L3_3_WB			_L3_CACHEABILITY(3)
115 
116 #define MOCS_ENTRY(__idx, __control_value, __l3cc_value) \
117 	[__idx] = { \
118 		.control_value = __control_value, \
119 		.l3cc_value = __l3cc_value, \
120 		.used = 1, \
121 	}
122 
123 /*
124  * MOCS tables
125  *
126  * These are the MOCS tables that are programmed across all the rings.
127  * The control value is programmed to all the rings that support the
128  * MOCS registers. While the l3cc_values are only programmed to the
129  * LNCFCMOCS0 - LNCFCMOCS32 registers.
130  *
131  * These tables are intended to be kept reasonably consistent across
132  * HW platforms, and for ICL+, be identical across OSes. To achieve
133  * that, for Icelake and above, list of entries is published as part
134  * of bspec.
135  *
136  * Entries not part of the following tables are undefined as far as
137  * userspace is concerned and shouldn't be relied upon.  For Gen < 12
138  * they will be initialized to PTE. Gen >= 12 don't have a setting for
139  * PTE and those platforms except TGL/RKL will be initialized L3 WB to
140  * catch accidental use of reserved and unused mocs indexes.
141  *
142  * The last few entries are reserved by the hardware. For ICL+ they
143  * should be initialized according to bspec and never used, for older
144  * platforms they should never be written to.
145  *
146  * NOTE1: These tables are part of bspec and defined as part of hardware
147  *       interface for ICL+. For older platforms, they are part of kernel
148  *       ABI. It is expected that, for specific hardware platform, existing
149  *       entries will remain constant and the table will only be updated by
150  *       adding new entries, filling unused positions.
151  *
152  * NOTE2: For GEN >= 12 except TGL and RKL, reserved and unspecified MOCS
153  *       indices have been set to L3 WB. These reserved entries should never
154  *       be used, they may be changed to low performant variants with better
155  *       coherency in the future if more entries are needed.
156  *       For TGL/RKL, all the unspecified MOCS indexes are mapped to L3 UC.
157  */
158 
159 #define GEN11_MOCS_ENTRIES \
160 	/* Entries 0 and 1 are defined per-platform */ \
161 	/* Base - L3 + LLC */ \
162 	MOCS_ENTRY(2, \
163 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \
164 		L3_3_WB), \
165 	/* Base - Uncached */ \
166 	MOCS_ENTRY(3, \
167 		LE_1_UC | LE_TC_1_LLC, \
168 		L3_1_UC), \
169 	/* Base - L3 */ \
170 	MOCS_ENTRY(4, \
171 		LE_1_UC | LE_TC_1_LLC, \
172 		L3_3_WB), \
173 	/* Base - LLC */ \
174 	MOCS_ENTRY(5, \
175 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \
176 		L3_1_UC), \
177 	/* Age 0 - LLC */ \
178 	MOCS_ENTRY(6, \
179 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(1), \
180 		L3_1_UC), \
181 	/* Age 0 - L3 + LLC */ \
182 	MOCS_ENTRY(7, \
183 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(1), \
184 		L3_3_WB), \
185 	/* Age: Don't Chg. - LLC */ \
186 	MOCS_ENTRY(8, \
187 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(2), \
188 		L3_1_UC), \
189 	/* Age: Don't Chg. - L3 + LLC */ \
190 	MOCS_ENTRY(9, \
191 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(2), \
192 		L3_3_WB), \
193 	/* No AOM - LLC */ \
194 	MOCS_ENTRY(10, \
195 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_AOM(1), \
196 		L3_1_UC), \
197 	/* No AOM - L3 + LLC */ \
198 	MOCS_ENTRY(11, \
199 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_AOM(1), \
200 		L3_3_WB), \
201 	/* No AOM; Age 0 - LLC */ \
202 	MOCS_ENTRY(12, \
203 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(1) | LE_AOM(1), \
204 		L3_1_UC), \
205 	/* No AOM; Age 0 - L3 + LLC */ \
206 	MOCS_ENTRY(13, \
207 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(1) | LE_AOM(1), \
208 		L3_3_WB), \
209 	/* No AOM; Age:DC - LLC */ \
210 	MOCS_ENTRY(14, \
211 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(2) | LE_AOM(1), \
212 		L3_1_UC), \
213 	/* No AOM; Age:DC - L3 + LLC */ \
214 	MOCS_ENTRY(15, \
215 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(2) | LE_AOM(1), \
216 		L3_3_WB), \
217 	/* Self-Snoop - L3 + LLC */ \
218 	MOCS_ENTRY(18, \
219 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SSE(3), \
220 		L3_3_WB), \
221 	/* Skip Caching - L3 + LLC(12.5%) */ \
222 	MOCS_ENTRY(19, \
223 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(7), \
224 		L3_3_WB), \
225 	/* Skip Caching - L3 + LLC(25%) */ \
226 	MOCS_ENTRY(20, \
227 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(3), \
228 		L3_3_WB), \
229 	/* Skip Caching - L3 + LLC(50%) */ \
230 	MOCS_ENTRY(21, \
231 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(1), \
232 		L3_3_WB), \
233 	/* Skip Caching - L3 + LLC(75%) */ \
234 	MOCS_ENTRY(22, \
235 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_RSC(1) | LE_SCC(3), \
236 		L3_3_WB), \
237 	/* Skip Caching - L3 + LLC(87.5%) */ \
238 	MOCS_ENTRY(23, \
239 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_RSC(1) | LE_SCC(7), \
240 		L3_3_WB), \
241 	/* HW Reserved - SW program but never use */ \
242 	MOCS_ENTRY(62, \
243 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \
244 		L3_1_UC), \
245 	/* HW Reserved - SW program but never use */ \
246 	MOCS_ENTRY(63, \
247 		LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \
248 		L3_1_UC)
249 
250 static const struct xe_mocs_entry tgl_mocs_desc[] = {
251 	/*
252 	 * NOTE:
253 	 * Reserved and unspecified MOCS indices have been set to (L3 + LCC).
254 	 * These reserved entries should never be used, they may be changed
255 	 * to low performant variants with better coherency in the future if
256 	 * more entries are needed. We are programming index XE_MOCS_PTE(1)
257 	 * only, __init_mocs_table() take care to program unused index with
258 	 * this entry.
259 	 */
260 	MOCS_ENTRY(XE_MOCS_PTE,
261 		   LE_0_PAGETABLE | LE_TC_0_PAGETABLE,
262 		   L3_1_UC),
263 	GEN11_MOCS_ENTRIES,
264 
265 	/* Implicitly enable L1 - HDC:L1 + L3 + LLC */
266 	MOCS_ENTRY(48,
267 		   LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
268 		   L3_3_WB),
269 	/* Implicitly enable L1 - HDC:L1 + L3 */
270 	MOCS_ENTRY(49,
271 		   LE_1_UC | LE_TC_1_LLC,
272 		   L3_3_WB),
273 	/* Implicitly enable L1 - HDC:L1 + LLC */
274 	MOCS_ENTRY(50,
275 		   LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
276 		   L3_1_UC),
277 	/* Implicitly enable L1 - HDC:L1 */
278 	MOCS_ENTRY(51,
279 		   LE_1_UC | LE_TC_1_LLC,
280 		   L3_1_UC),
281 	/* HW Special Case (CCS) */
282 	MOCS_ENTRY(60,
283 		   LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
284 		   L3_1_UC),
285 	/* HW Special Case (Displayable) */
286 	MOCS_ENTRY(61,
287 		   LE_1_UC | LE_TC_1_LLC,
288 		   L3_3_WB),
289 };
290 
291 static const struct xe_mocs_entry dg1_mocs_desc[] = {
292 	/* UC */
293 	MOCS_ENTRY(1, 0, L3_1_UC),
294 	/* WB - L3 */
295 	MOCS_ENTRY(5, 0, L3_3_WB),
296 	/* WB - L3 50% */
297 	MOCS_ENTRY(6, 0, L3_ESC(1) | L3_SCC(1) | L3_3_WB),
298 	/* WB - L3 25% */
299 	MOCS_ENTRY(7, 0, L3_ESC(1) | L3_SCC(3) | L3_3_WB),
300 	/* WB - L3 12.5% */
301 	MOCS_ENTRY(8, 0, L3_ESC(1) | L3_SCC(7) | L3_3_WB),
302 
303 	/* HDC:L1 + L3 */
304 	MOCS_ENTRY(48, 0, L3_3_WB),
305 	/* HDC:L1 */
306 	MOCS_ENTRY(49, 0, L3_1_UC),
307 
308 	/* HW Reserved */
309 	MOCS_ENTRY(60, 0, L3_1_UC),
310 	MOCS_ENTRY(61, 0, L3_1_UC),
311 	MOCS_ENTRY(62, 0, L3_1_UC),
312 	MOCS_ENTRY(63, 0, L3_1_UC),
313 };
314 
315 static const struct xe_mocs_entry gen12_mocs_desc[] = {
316 	GEN11_MOCS_ENTRIES,
317 	/* Implicitly enable L1 - HDC:L1 + L3 + LLC */
318 	MOCS_ENTRY(48,
319 		   LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
320 		   L3_3_WB),
321 	/* Implicitly enable L1 - HDC:L1 + L3 */
322 	MOCS_ENTRY(49,
323 		   LE_1_UC | LE_TC_1_LLC,
324 		   L3_3_WB),
325 	/* Implicitly enable L1 - HDC:L1 + LLC */
326 	MOCS_ENTRY(50,
327 		   LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
328 		   L3_1_UC),
329 	/* Implicitly enable L1 - HDC:L1 */
330 	MOCS_ENTRY(51,
331 		   LE_1_UC | LE_TC_1_LLC,
332 		   L3_1_UC),
333 	/* HW Special Case (CCS) */
334 	MOCS_ENTRY(60,
335 		   LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
336 		   L3_1_UC),
337 	/* HW Special Case (Displayable) */
338 	MOCS_ENTRY(61,
339 		   LE_1_UC | LE_TC_1_LLC,
340 		   L3_3_WB),
341 };
342 
343 static const struct xe_mocs_entry dg2_mocs_desc[] = {
344 	/* UC - Coherent; GO:L3 */
345 	MOCS_ENTRY(0, 0, L3_1_UC | L3_LKUP(1)),
346 	/* UC - Coherent; GO:Memory */
347 	MOCS_ENTRY(1, 0, L3_1_UC | L3_GLBGO(1) | L3_LKUP(1)),
348 	/* UC - Non-Coherent; GO:Memory */
349 	MOCS_ENTRY(2, 0, L3_1_UC | L3_GLBGO(1)),
350 
351 	/* WB - LC */
352 	MOCS_ENTRY(3, 0, L3_3_WB | L3_LKUP(1)),
353 };
354 
355 static const struct xe_mocs_entry dg2_mocs_desc_g10_ax[] = {
356 	/* Wa_14011441408: Set Go to Memory for MOCS#0 */
357 	MOCS_ENTRY(0, 0, L3_1_UC | L3_GLBGO(1) | L3_LKUP(1)),
358 	/* UC - Coherent; GO:Memory */
359 	MOCS_ENTRY(1, 0, L3_1_UC | L3_GLBGO(1) | L3_LKUP(1)),
360 	/* UC - Non-Coherent; GO:Memory */
361 	MOCS_ENTRY(2, 0, L3_1_UC | L3_GLBGO(1)),
362 
363 	/* WB - LC */
364 	MOCS_ENTRY(3, 0, L3_3_WB | L3_LKUP(1)),
365 };
366 
367 static const struct xe_mocs_entry pvc_mocs_desc[] = {
368 	/* Error */
369 	MOCS_ENTRY(0, 0, L3_3_WB),
370 
371 	/* UC */
372 	MOCS_ENTRY(1, 0, L3_1_UC),
373 
374 	/* WB */
375 	MOCS_ENTRY(2, 0, L3_3_WB),
376 };
377 
378 static unsigned int get_mocs_settings(struct xe_device *xe,
379 				      struct xe_mocs_info *info)
380 {
381 	unsigned int flags;
382 
383 	memset(info, 0, sizeof(struct xe_mocs_info));
384 
385 	info->unused_entries_index = XE_MOCS_PTE;
386 	switch (xe->info.platform) {
387 	case XE_PVC:
388 		info->size = ARRAY_SIZE(pvc_mocs_desc);
389 		info->table = pvc_mocs_desc;
390 		info->n_entries = PVC_NUM_MOCS_ENTRIES;
391 		info->uc_index = 1;
392 		info->wb_index = 2;
393 		info->unused_entries_index = 2;
394 		break;
395 	case XE_METEORLAKE:
396 		info->size = ARRAY_SIZE(dg2_mocs_desc);
397 		info->table = dg2_mocs_desc;
398 		info->n_entries = MTL_NUM_MOCS_ENTRIES;
399 		info->uc_index = 1;
400 		info->unused_entries_index = 3;
401 		break;
402 	case XE_DG2:
403 		if (xe->info.subplatform == XE_SUBPLATFORM_DG2_G10 &&
404 		    xe->info.step.graphics >= STEP_A0 &&
405 		    xe->info.step.graphics <= STEP_B0) {
406 			info->size = ARRAY_SIZE(dg2_mocs_desc_g10_ax);
407 			info->table = dg2_mocs_desc_g10_ax;
408 		} else {
409 			info->size = ARRAY_SIZE(dg2_mocs_desc);
410 			info->table = dg2_mocs_desc;
411 		}
412 		info->uc_index = 1;
413 		info->n_entries = GEN9_NUM_MOCS_ENTRIES;
414 		info->unused_entries_index = 3;
415 		break;
416 	case XE_DG1:
417 		info->size = ARRAY_SIZE(dg1_mocs_desc);
418 		info->table = dg1_mocs_desc;
419 		info->uc_index = 1;
420 		info->n_entries = GEN9_NUM_MOCS_ENTRIES;
421 		info->uc_index = 1;
422 		info->unused_entries_index = 5;
423 		break;
424 	case XE_TIGERLAKE:
425 		info->size  = ARRAY_SIZE(tgl_mocs_desc);
426 		info->table = tgl_mocs_desc;
427 		info->n_entries = GEN9_NUM_MOCS_ENTRIES;
428 		info->uc_index = 3;
429 		break;
430 	case XE_ALDERLAKE_S:
431 	case XE_ALDERLAKE_P:
432 		info->size  = ARRAY_SIZE(gen12_mocs_desc);
433 		info->table = gen12_mocs_desc;
434 		info->n_entries = GEN9_NUM_MOCS_ENTRIES;
435 		info->uc_index = 3;
436 		info->unused_entries_index = 2;
437 		break;
438 	default:
439 		drm_err(&xe->drm, "Platform that should have a MOCS table does not.\n");
440 		return 0;
441 	}
442 
443 	if (XE_WARN_ON(info->size > info->n_entries))
444 		return 0;
445 
446 	flags = HAS_RENDER_L3CC;
447 	if (!IS_DGFX(xe))
448 		flags |= HAS_GLOBAL_MOCS;
449 
450 	return flags;
451 }
452 
453 /*
454  * Get control_value from MOCS entry taking into account when it's not used
455  * then if unused_entries_index is non-zero then its value will be returned
456  * otherwise XE_MOCS_PTE's value is returned in this case.
457  */
458 static u32 get_entry_control(const struct xe_mocs_info *info,
459 			     unsigned int index)
460 {
461 	if (index < info->size && info->table[index].used)
462 		return info->table[index].control_value;
463 	return info->table[info->unused_entries_index].control_value;
464 }
465 
466 static void __init_mocs_table(struct xe_gt *gt,
467 			      const struct xe_mocs_info *info,
468 			      u32 addr)
469 {
470 	struct xe_device *xe = gt_to_xe(gt);
471 
472 	unsigned int i;
473 	u32 mocs;
474 
475 	mocs_dbg(&gt->xe->drm, "entries:%d\n", info->n_entries);
476 	drm_WARN_ONCE(&xe->drm, !info->unused_entries_index,
477 		      "Unused entries index should have been defined\n");
478 	for (i = 0;
479 	     i < info->n_entries ? (mocs = get_entry_control(info, i)), 1 : 0;
480 	     i++) {
481 		mocs_dbg(&gt->xe->drm, "%d 0x%x 0x%x\n", i, _MMIO(addr + i * 4).reg, mocs);
482 		xe_mmio_write32(gt, _MMIO(addr + i * 4).reg, mocs);
483 	}
484 }
485 
486 /*
487  * Get l3cc_value from MOCS entry taking into account when it's not used
488  * then if unused_entries_index is not zero then its value will be returned
489  * otherwise I915_MOCS_PTE's value is returned in this case.
490  */
491 static u16 get_entry_l3cc(const struct xe_mocs_info *info,
492 			  unsigned int index)
493 {
494 	if (index < info->size && info->table[index].used)
495 		return info->table[index].l3cc_value;
496 	return info->table[info->unused_entries_index].l3cc_value;
497 }
498 
499 static u32 l3cc_combine(u16 low, u16 high)
500 {
501 	return low | (u32)high << 16;
502 }
503 
504 static void init_l3cc_table(struct xe_gt *gt,
505 			    const struct xe_mocs_info *info)
506 {
507 	unsigned int i;
508 	u32 l3cc;
509 
510 	mocs_dbg(&gt->xe->drm, "entries:%d\n", info->n_entries);
511 	for (i = 0;
512 	     i < (info->n_entries + 1) / 2 ?
513 	     (l3cc = l3cc_combine(get_entry_l3cc(info, 2 * i),
514 				  get_entry_l3cc(info, 2 * i + 1))), 1 : 0;
515 	     i++) {
516 		mocs_dbg(&gt->xe->drm, "%d 0x%x 0x%x\n", i, GEN9_LNCFCMOCS(i).reg, l3cc);
517 		xe_mmio_write32(gt, GEN9_LNCFCMOCS(i).reg, l3cc);
518 	}
519 }
520 
521 void xe_mocs_init_engine(const struct xe_engine *engine)
522 {
523 	struct xe_mocs_info table;
524 	unsigned int flags;
525 
526 	flags = get_mocs_settings(engine->gt->xe, &table);
527 	if (!flags)
528 		return;
529 
530 	if (flags & HAS_RENDER_L3CC && engine->class == XE_ENGINE_CLASS_RENDER)
531 		init_l3cc_table(engine->gt, &table);
532 }
533 
534 void xe_mocs_init(struct xe_gt *gt)
535 {
536 	struct xe_mocs_info table;
537 	unsigned int flags;
538 
539 	/*
540 	 * LLC and eDRAM control values are not applicable to dgfx
541 	 */
542 	flags = get_mocs_settings(gt->xe, &table);
543 	mocs_dbg(&gt->xe->drm, "flag:0x%x\n", flags);
544 	gt->mocs.uc_index = table.uc_index;
545 	gt->mocs.wb_index = table.wb_index;
546 
547 	if (flags & HAS_GLOBAL_MOCS)
548 		__init_mocs_table(gt, &table, GEN12_GLOBAL_MOCS(0).reg);
549 
550 	/*
551 	 * Initialize the L3CC table as part of mocs initalization to make
552 	 * sure the LNCFCMOCSx registers are programmed for the subsequent
553 	 * memory transactions including guc transactions
554 	 */
555 	if (flags & HAS_RENDER_L3CC)
556 		init_l3cc_table(gt, &table);
557 }
558