1 // SPDX-License-Identifier: MIT
3 * Copyright © 2022 Intel Corporation
8 #include "regs/xe_gt_regs.h"
10 #include "xe_device.h"
11 #include "xe_exec_queue.h"
12 #include "xe_force_wake.h"
14 #include "xe_gt_mcr.h"
15 #include "xe_gt_printk.h"
17 #include "xe_platform_types.h"
20 #include "xe_step_types.h"
22 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
23 #define mocs_dbg xe_gt_dbg
26 static inline void mocs_dbg(const struct xe_gt *gt,
27 const char *format, ...)
32 HAS_GLOBAL_MOCS = BIT(0),
33 HAS_LNCF_MOCS = BIT(1),
36 struct xe_mocs_entry {
45 void (*dump)(struct xe_mocs_info *mocs, unsigned int flags,
46 struct xe_gt *gt, struct drm_printer *p);
51 * Size of the spec's suggested MOCS programming table. The list of
52 * table entries from the spec can potentially be smaller than the
53 * number of hardware registers used to program the MOCS table; in such
54 * cases the registers for the remaining indices will be programmed to
55 * match unused_entries_index.
57 unsigned int table_size;
58 /* Number of MOCS entries supported by the hardware */
59 unsigned int num_mocs_regs;
60 const struct xe_mocs_entry *table;
61 const struct xe_mocs_ops *ops;
64 u8 unused_entries_index;
67 /* Defines for the tables (GLOB_MOCS_0 - GLOB_MOCS_16) */
68 #define IG_PAT REG_BIT(8)
69 #define L3_CACHE_POLICY_MASK REG_GENMASK(5, 4)
70 #define L4_CACHE_POLICY_MASK REG_GENMASK(3, 2)
73 #define XELP_NUM_MOCS_ENTRIES 64 /* 63-64 are reserved, but configured. */
74 #define PVC_NUM_MOCS_ENTRIES 3
75 #define MTL_NUM_MOCS_ENTRIES 16
76 #define XE2_NUM_MOCS_ENTRIES 16
78 /* (e)LLC caching options */
80 * Note: LE_0_PAGETABLE works only up to Gen11; for newer gens it means
83 #define LE_0_PAGETABLE LE_CACHEABILITY(0)
84 #define LE_1_UC LE_CACHEABILITY(1)
85 #define LE_2_WT LE_CACHEABILITY(2)
86 #define LE_3_WB LE_CACHEABILITY(3)
89 #define LE_TC_0_PAGETABLE LE_TGT_CACHE(0)
90 #define LE_TC_1_LLC LE_TGT_CACHE(1)
91 #define LE_TC_2_LLC_ELLC LE_TGT_CACHE(2)
92 #define LE_TC_3_LLC_ELLC_ALT LE_TGT_CACHE(3)
94 /* L3 caching options */
95 #define L3_0_DIRECT L3_CACHEABILITY(0)
96 #define L3_1_UC L3_CACHEABILITY(1)
97 #define L3_2_RESERVED L3_CACHEABILITY(2)
98 #define L3_3_WB L3_CACHEABILITY(3)
100 /* L4 caching options */
101 #define L4_0_WB REG_FIELD_PREP(L4_CACHE_POLICY_MASK, 0)
102 #define L4_1_WT REG_FIELD_PREP(L4_CACHE_POLICY_MASK, 1)
103 #define L4_3_UC REG_FIELD_PREP(L4_CACHE_POLICY_MASK, 3)
105 #define XE2_L3_0_WB REG_FIELD_PREP(L3_CACHE_POLICY_MASK, 0)
106 /* XD: WB Transient Display */
107 #define XE2_L3_1_XD REG_FIELD_PREP(L3_CACHE_POLICY_MASK, 1)
108 #define XE2_L3_3_UC REG_FIELD_PREP(L3_CACHE_POLICY_MASK, 3)
110 #define XE2_L3_CLOS_MASK REG_GENMASK(7, 6)
112 #define MOCS_ENTRY(__idx, __control_value, __l3cc_value) \
114 .control_value = __control_value, \
115 .l3cc_value = __l3cc_value, \
122 * These are the MOCS tables that are programmed across all the rings.
123 * The control value is programmed to all the rings that support the
124 * MOCS registers. While the l3cc_values are only programmed to the
125 * LNCFCMOCS0 - LNCFCMOCS32 registers.
127 * These tables are intended to be kept reasonably consistent across
128 * HW platforms, and for ICL+, be identical across OSes. To achieve
129 * that, the list of entries is published as part of bspec.
131 * Entries not part of the following tables are undefined as far as userspace is
132 * concerned and shouldn't be relied upon. The last few entries are reserved by
133 * the hardware. They should be initialized according to bspec and never used.
135 * NOTE1: These tables are part of bspec and defined as part of the hardware
136 * interface. It is expected that, for specific hardware platform, existing
137 * entries will remain constant and the table will only be updated by adding new
138 * entries, filling unused positions.
140 * NOTE2: Reserved and unspecified MOCS indices have been set to L3 WB. These
141 * reserved entries should never be used. They may be changed to low performant
142 * variants with better coherency in the future if more entries are needed.
145 static const struct xe_mocs_entry gen12_mocs_desc[] = {
146 /* Base - L3 + LLC */
148 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
150 /* Base - Uncached */
152 LE_1_UC | LE_TC_1_LLC,
156 LE_1_UC | LE_TC_1_LLC,
160 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
164 LE_3_WB | LE_TC_1_LLC | LE_LRUM(1),
166 /* Age 0 - L3 + LLC */
168 LE_3_WB | LE_TC_1_LLC | LE_LRUM(1),
170 /* Age: Don't Chg. - LLC */
172 LE_3_WB | LE_TC_1_LLC | LE_LRUM(2),
174 /* Age: Don't Chg. - L3 + LLC */
176 LE_3_WB | LE_TC_1_LLC | LE_LRUM(2),
180 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_AOM(1),
182 /* No AOM - L3 + LLC */
184 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_AOM(1),
186 /* No AOM; Age 0 - LLC */
188 LE_3_WB | LE_TC_1_LLC | LE_LRUM(1) | LE_AOM(1),
190 /* No AOM; Age 0 - L3 + LLC */
192 LE_3_WB | LE_TC_1_LLC | LE_LRUM(1) | LE_AOM(1),
194 /* No AOM; Age:DC - LLC */
196 LE_3_WB | LE_TC_1_LLC | LE_LRUM(2) | LE_AOM(1),
198 /* No AOM; Age:DC - L3 + LLC */
200 LE_3_WB | LE_TC_1_LLC | LE_LRUM(2) | LE_AOM(1),
202 /* Self-Snoop - L3 + LLC */
204 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SSE(3),
206 /* Skip Caching - L3 + LLC(12.5%) */
208 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(7),
210 /* Skip Caching - L3 + LLC(25%) */
212 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(3),
214 /* Skip Caching - L3 + LLC(50%) */
216 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(1),
218 /* Skip Caching - L3 + LLC(75%) */
220 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_RSC(1) | LE_SCC(3),
222 /* Skip Caching - L3 + LLC(87.5%) */
224 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_RSC(1) | LE_SCC(7),
226 /* Implicitly enable L1 - HDC:L1 + L3 + LLC */
228 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
230 /* Implicitly enable L1 - HDC:L1 + L3 */
232 LE_1_UC | LE_TC_1_LLC,
234 /* Implicitly enable L1 - HDC:L1 + LLC */
236 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
238 /* Implicitly enable L1 - HDC:L1 */
240 LE_1_UC | LE_TC_1_LLC,
242 /* HW Special Case (CCS) */
244 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
246 /* HW Special Case (Displayable) */
248 LE_1_UC | LE_TC_1_LLC,
250 /* HW Reserved - SW program but never use */
252 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
254 /* HW Reserved - SW program but never use */
256 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
260 static bool regs_are_mcr(struct xe_gt *gt)
262 struct xe_device *xe = gt_to_xe(gt);
264 if (xe_gt_is_media_type(gt))
265 return MEDIA_VER(xe) >= 20;
267 return GRAPHICS_VERx100(xe) >= 1250;
270 static void xelp_lncf_dump(struct xe_mocs_info *info, struct xe_gt *gt, struct drm_printer *p)
275 drm_printf(p, "LNCFCMOCS[idx] = [ESC, SCC, L3CC] (value)\n\n");
277 for (i = 0, j = 0; i < (info->num_mocs_regs + 1) / 2; i++, j++) {
278 if (regs_are_mcr(gt))
279 reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
281 reg_val = xe_mmio_read32(>->mmio, XELP_LNCFCMOCS(i));
283 drm_printf(p, "LNCFCMOCS[%2d] = [%u, %u, %u] (%#8x)\n",
285 !!(reg_val & L3_ESC_MASK),
286 REG_FIELD_GET(L3_SCC_MASK, reg_val),
287 REG_FIELD_GET(L3_CACHEABILITY_MASK, reg_val),
290 drm_printf(p, "LNCFCMOCS[%2d] = [%u, %u, %u] (%#8x)\n",
292 !!(reg_val & L3_UPPER_IDX_ESC_MASK),
293 REG_FIELD_GET(L3_UPPER_IDX_SCC_MASK, reg_val),
294 REG_FIELD_GET(L3_UPPER_IDX_CACHEABILITY_MASK, reg_val),
299 static void xelp_mocs_dump(struct xe_mocs_info *info, unsigned int flags,
300 struct xe_gt *gt, struct drm_printer *p)
305 if (flags & HAS_GLOBAL_MOCS) {
306 drm_printf(p, "Global mocs table configuration:\n");
307 drm_printf(p, "GLOB_MOCS[idx] = [LeCC, TC, LRUM, AOM, RSC, SCC, PFM, SCF, CoS, SSE] (value)\n\n");
309 for (i = 0; i < info->num_mocs_regs; i++) {
310 if (regs_are_mcr(gt))
311 reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
313 reg_val = xe_mmio_read32(>->mmio, XELP_GLOBAL_MOCS(i));
315 drm_printf(p, "GLOB_MOCS[%2d] = [%u, %u, %u, %u, %u, %u, %u, %u, %u, %u ] (%#8x)\n",
317 REG_FIELD_GET(LE_CACHEABILITY_MASK, reg_val),
318 REG_FIELD_GET(LE_TGT_CACHE_MASK, reg_val),
319 REG_FIELD_GET(LE_LRUM_MASK, reg_val),
320 !!(reg_val & LE_AOM_MASK),
321 !!(reg_val & LE_RSC_MASK),
322 REG_FIELD_GET(LE_SCC_MASK, reg_val),
323 REG_FIELD_GET(LE_PFM_MASK, reg_val),
324 !!(reg_val & LE_SCF_MASK),
325 REG_FIELD_GET(LE_COS_MASK, reg_val),
326 REG_FIELD_GET(LE_SSE_MASK, reg_val),
331 xelp_lncf_dump(info, gt, p);
334 static const struct xe_mocs_ops xelp_mocs_ops = {
335 .dump = xelp_mocs_dump,
338 static const struct xe_mocs_entry dg1_mocs_desc[] = {
340 MOCS_ENTRY(1, 0, L3_1_UC),
342 MOCS_ENTRY(5, 0, L3_3_WB),
344 MOCS_ENTRY(6, 0, L3_ESC(1) | L3_SCC(1) | L3_3_WB),
346 MOCS_ENTRY(7, 0, L3_ESC(1) | L3_SCC(3) | L3_3_WB),
348 MOCS_ENTRY(8, 0, L3_ESC(1) | L3_SCC(7) | L3_3_WB),
351 MOCS_ENTRY(48, 0, L3_3_WB),
353 MOCS_ENTRY(49, 0, L3_1_UC),
356 MOCS_ENTRY(60, 0, L3_1_UC),
357 MOCS_ENTRY(61, 0, L3_1_UC),
358 MOCS_ENTRY(62, 0, L3_1_UC),
359 MOCS_ENTRY(63, 0, L3_1_UC),
362 static const struct xe_mocs_entry dg2_mocs_desc[] = {
363 /* UC - Coherent; GO:L3 */
364 MOCS_ENTRY(0, 0, L3_1_UC | L3_LKUP(1)),
365 /* UC - Coherent; GO:Memory */
366 MOCS_ENTRY(1, 0, L3_1_UC | L3_GLBGO(1) | L3_LKUP(1)),
367 /* UC - Non-Coherent; GO:Memory */
368 MOCS_ENTRY(2, 0, L3_1_UC | L3_GLBGO(1)),
371 MOCS_ENTRY(3, 0, L3_3_WB | L3_LKUP(1)),
374 static void xehp_lncf_dump(struct xe_mocs_info *info, unsigned int flags,
375 struct xe_gt *gt, struct drm_printer *p)
380 drm_printf(p, "LNCFCMOCS[idx] = [UCL3LOOKUP, GLBGO, L3CC] (value)\n\n");
382 for (i = 0, j = 0; i < (info->num_mocs_regs + 1) / 2; i++, j++) {
383 if (regs_are_mcr(gt))
384 reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
386 reg_val = xe_mmio_read32(>->mmio, XELP_LNCFCMOCS(i));
388 drm_printf(p, "LNCFCMOCS[%2d] = [%u, %u, %u] (%#8x)\n",
390 !!(reg_val & L3_LKUP_MASK),
391 !!(reg_val & L3_GLBGO_MASK),
392 REG_FIELD_GET(L3_CACHEABILITY_MASK, reg_val),
395 drm_printf(p, "LNCFCMOCS[%2d] = [%u, %u, %u] (%#8x)\n",
397 !!(reg_val & L3_UPPER_LKUP_MASK),
398 !!(reg_val & L3_UPPER_GLBGO_MASK),
399 REG_FIELD_GET(L3_UPPER_IDX_CACHEABILITY_MASK, reg_val),
404 static const struct xe_mocs_ops xehp_mocs_ops = {
405 .dump = xehp_lncf_dump,
408 static const struct xe_mocs_entry pvc_mocs_desc[] = {
410 MOCS_ENTRY(0, 0, L3_3_WB),
413 MOCS_ENTRY(1, 0, L3_1_UC),
416 MOCS_ENTRY(2, 0, L3_3_WB),
419 static void pvc_mocs_dump(struct xe_mocs_info *info, unsigned int flags, struct xe_gt *gt,
420 struct drm_printer *p)
425 drm_printf(p, "LNCFCMOCS[idx] = [ L3CC ] (value)\n\n");
427 for (i = 0, j = 0; i < (info->num_mocs_regs + 1) / 2; i++, j++) {
428 if (regs_are_mcr(gt))
429 reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
431 reg_val = xe_mmio_read32(>->mmio, XELP_LNCFCMOCS(i));
433 drm_printf(p, "LNCFCMOCS[%2d] = [ %u ] (%#8x)\n",
435 REG_FIELD_GET(L3_CACHEABILITY_MASK, reg_val),
438 drm_printf(p, "LNCFCMOCS[%2d] = [ %u ] (%#8x)\n",
440 REG_FIELD_GET(L3_UPPER_IDX_CACHEABILITY_MASK, reg_val),
445 static const struct xe_mocs_ops pvc_mocs_ops = {
446 .dump = pvc_mocs_dump,
449 static const struct xe_mocs_entry mtl_mocs_desc[] = {
450 /* Error - Reserved for Non-Use */
453 L3_LKUP(1) | L3_3_WB),
454 /* Cached - L3 + L4 */
457 L3_LKUP(1) | L3_3_WB),
461 L3_LKUP(1) | L3_1_UC),
462 /* Uncached - GO:L3 */
465 L3_LKUP(1) | L3_1_UC),
469 L3_LKUP(1) | L3_GLBGO(1) | L3_1_UC),
470 /* Uncached - GO:Mem */
473 L3_LKUP(1) | L3_GLBGO(1) | L3_1_UC),
474 /* L4 - L3:NoLKUP; GO:L3 */
478 /* Uncached - L3:NoLKUP; GO:L3 */
482 /* L4 - L3:NoLKUP; GO:Mem */
485 L3_GLBGO(1) | L3_1_UC),
486 /* Uncached - L3:NoLKUP; GO:Mem */
489 L3_GLBGO(1) | L3_1_UC),
490 /* Display - L3; L4:WT */
493 L3_LKUP(1) | L3_3_WB),
494 /* CCS - Non-Displayable */
497 L3_GLBGO(1) | L3_1_UC),
500 static void mtl_mocs_dump(struct xe_mocs_info *info, unsigned int flags,
501 struct xe_gt *gt, struct drm_printer *p)
506 drm_printf(p, "Global mocs table configuration:\n");
507 drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L4_CACHE_POLICY] (value)\n\n");
509 for (i = 0; i < info->num_mocs_regs; i++) {
510 if (regs_are_mcr(gt))
511 reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
513 reg_val = xe_mmio_read32(>->mmio, XELP_GLOBAL_MOCS(i));
515 drm_printf(p, "GLOB_MOCS[%2d] = [%u, %u] (%#8x)\n",
517 !!(reg_val & IG_PAT),
518 REG_FIELD_GET(L4_CACHE_POLICY_MASK, reg_val),
522 /* MTL lncf mocs table pattern is similar to that of xehp */
523 xehp_lncf_dump(info, flags, gt, p);
526 static const struct xe_mocs_ops mtl_mocs_ops = {
527 .dump = mtl_mocs_dump,
530 static const struct xe_mocs_entry xe2_mocs_table[] = {
532 MOCS_ENTRY(0, XE2_L3_0_WB | L4_3_UC, 0),
533 /* Cached L3, Uncached L4 */
534 MOCS_ENTRY(1, IG_PAT | XE2_L3_0_WB | L4_3_UC, 0),
535 /* Uncached L3, Cached L4 */
536 MOCS_ENTRY(2, IG_PAT | XE2_L3_3_UC | L4_0_WB, 0),
537 /* Uncached L3 + L4 */
538 MOCS_ENTRY(3, IG_PAT | XE2_L3_3_UC | L4_3_UC, 0),
540 MOCS_ENTRY(4, IG_PAT | XE2_L3_0_WB | L4_0_WB, 0),
543 static void xe2_mocs_dump(struct xe_mocs_info *info, unsigned int flags,
544 struct xe_gt *gt, struct drm_printer *p)
549 drm_printf(p, "Global mocs table configuration:\n");
550 drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L3_CLOS, L3_CACHE_POLICY, L4_CACHE_POLICY] (value)\n\n");
552 for (i = 0; i < info->num_mocs_regs; i++) {
553 if (regs_are_mcr(gt))
554 reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
556 reg_val = xe_mmio_read32(>->mmio, XELP_GLOBAL_MOCS(i));
558 drm_printf(p, "GLOB_MOCS[%2d] = [%u, %u, %u] (%#8x)\n",
560 !!(reg_val & IG_PAT),
561 REG_FIELD_GET(XE2_L3_CLOS_MASK, reg_val),
562 REG_FIELD_GET(L4_CACHE_POLICY_MASK, reg_val),
567 static const struct xe_mocs_ops xe2_mocs_ops = {
568 .dump = xe2_mocs_dump,
571 static unsigned int get_mocs_settings(struct xe_device *xe,
572 struct xe_mocs_info *info)
574 unsigned int flags = 0;
576 memset(info, 0, sizeof(struct xe_mocs_info));
578 switch (xe->info.platform) {
582 info->ops = &xe2_mocs_ops;
583 info->table_size = ARRAY_SIZE(xe2_mocs_table);
584 info->table = xe2_mocs_table;
585 info->num_mocs_regs = XE2_NUM_MOCS_ENTRIES;
588 info->unused_entries_index = 4;
591 info->ops = &pvc_mocs_ops;
592 info->table_size = ARRAY_SIZE(pvc_mocs_desc);
593 info->table = pvc_mocs_desc;
594 info->num_mocs_regs = PVC_NUM_MOCS_ENTRIES;
597 info->unused_entries_index = 2;
600 info->ops = &mtl_mocs_ops;
601 info->table_size = ARRAY_SIZE(mtl_mocs_desc);
602 info->table = mtl_mocs_desc;
603 info->num_mocs_regs = MTL_NUM_MOCS_ENTRIES;
605 info->unused_entries_index = 1;
608 info->ops = &xehp_mocs_ops;
609 info->table_size = ARRAY_SIZE(dg2_mocs_desc);
610 info->table = dg2_mocs_desc;
613 * Last entry is RO on hardware, don't bother with what was
614 * written when checking later
616 info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES - 1;
617 info->unused_entries_index = 3;
620 info->ops = &xelp_mocs_ops;
621 info->table_size = ARRAY_SIZE(dg1_mocs_desc);
622 info->table = dg1_mocs_desc;
624 info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES;
625 info->unused_entries_index = 5;
632 info->ops = &xelp_mocs_ops;
633 info->table_size = ARRAY_SIZE(gen12_mocs_desc);
634 info->table = gen12_mocs_desc;
635 info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES;
637 info->unused_entries_index = 2;
640 drm_err(&xe->drm, "Platform that should have a MOCS table does not.\n");
645 * Index 0 is a reserved/unused table entry on most platforms, but
646 * even on those where it does represent a legitimate MOCS entry, it
647 * never represents the "most cached, least coherent" behavior we want
648 * to populate undefined table rows with. So if unused_entries_index
649 * is still 0 at this point, we'll assume that it was omitted by
650 * mistake in the switch statement above.
652 xe_assert(xe, info->unused_entries_index != 0);
654 xe_assert(xe, info->ops && info->ops->dump);
655 xe_assert(xe, info->table_size <= info->num_mocs_regs);
657 if (!IS_DGFX(xe) || GRAPHICS_VER(xe) >= 20)
658 flags |= HAS_GLOBAL_MOCS;
659 if (GRAPHICS_VER(xe) < 20)
660 flags |= HAS_LNCF_MOCS;
666 * Get control_value from MOCS entry. If the table entry is not defined, the
667 * settings from unused_entries_index will be returned.
669 static u32 get_entry_control(const struct xe_mocs_info *info,
672 if (index < info->table_size && info->table[index].used)
673 return info->table[index].control_value;
674 return info->table[info->unused_entries_index].control_value;
677 static void __init_mocs_table(struct xe_gt *gt,
678 const struct xe_mocs_info *info)
683 mocs_dbg(gt, "mocs entries: %d\n", info->num_mocs_regs);
685 for (i = 0; i < info->num_mocs_regs; i++) {
686 mocs = get_entry_control(info, i);
688 mocs_dbg(gt, "GLOB_MOCS[%d] 0x%x 0x%x\n", i,
689 XELP_GLOBAL_MOCS(i).addr, mocs);
691 if (regs_are_mcr(gt))
692 xe_gt_mcr_multicast_write(gt, XEHP_GLOBAL_MOCS(i), mocs);
694 xe_mmio_write32(>->mmio, XELP_GLOBAL_MOCS(i), mocs);
699 * Get l3cc_value from MOCS entry taking into account when it's not used
700 * then if unused_entries_index is not zero then its value will be returned
701 * otherwise I915_MOCS_PTE's value is returned in this case.
703 static u16 get_entry_l3cc(const struct xe_mocs_info *info,
706 if (index < info->table_size && info->table[index].used)
707 return info->table[index].l3cc_value;
708 return info->table[info->unused_entries_index].l3cc_value;
711 static u32 l3cc_combine(u16 low, u16 high)
713 return low | (u32)high << 16;
716 static void init_l3cc_table(struct xe_gt *gt,
717 const struct xe_mocs_info *info)
722 mocs_dbg(gt, "l3cc entries: %d\n", info->num_mocs_regs);
724 for (i = 0; i < (info->num_mocs_regs + 1) / 2; i++) {
725 l3cc = l3cc_combine(get_entry_l3cc(info, 2 * i),
726 get_entry_l3cc(info, 2 * i + 1));
728 mocs_dbg(gt, "LNCFCMOCS[%d] 0x%x 0x%x\n", i,
729 XELP_LNCFCMOCS(i).addr, l3cc);
731 if (regs_are_mcr(gt))
732 xe_gt_mcr_multicast_write(gt, XEHP_LNCFCMOCS(i), l3cc);
734 xe_mmio_write32(>->mmio, XELP_LNCFCMOCS(i), l3cc);
738 void xe_mocs_init_early(struct xe_gt *gt)
740 struct xe_mocs_info table;
742 get_mocs_settings(gt_to_xe(gt), &table);
743 gt->mocs.uc_index = table.uc_index;
744 gt->mocs.wb_index = table.wb_index;
747 void xe_mocs_init(struct xe_gt *gt)
749 struct xe_mocs_info table;
752 if (IS_SRIOV_VF(gt_to_xe(gt)))
756 * MOCS settings are split between "GLOB_MOCS" and/or "LNCFCMOCS"
757 * registers depending on platform.
759 * These registers should be programmed before GuC initialization
760 * since their values will affect some of the memory transactions
761 * performed by the GuC.
763 flags = get_mocs_settings(gt_to_xe(gt), &table);
764 mocs_dbg(gt, "flag:0x%x\n", flags);
766 if (IS_SRIOV_VF(gt_to_xe(gt)))
769 if (flags & HAS_GLOBAL_MOCS)
770 __init_mocs_table(gt, &table);
771 if (flags & HAS_LNCF_MOCS)
772 init_l3cc_table(gt, &table);
775 void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p)
777 struct xe_device *xe = gt_to_xe(gt);
778 struct xe_mocs_info table;
779 unsigned int fw_ref, flags;
781 flags = get_mocs_settings(xe, &table);
783 xe_pm_runtime_get_noresume(xe);
784 fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
788 table.ops->dump(&table, flags, gt, p);
790 xe_force_wake_put(gt_to_fw(gt), fw_ref);
792 xe_pm_runtime_put(xe);
795 #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
796 #include "tests/xe_mocs.c"