]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/xe3p_xpc: Setup PAT table
authorMatt Roper <matthew.d.roper@intel.com>
Fri, 17 Oct 2025 02:26:42 +0000 (19:26 -0700)
committerLucas De Marchi <lucas.demarchi@intel.com>
Sun, 19 Oct 2025 02:45:14 +0000 (19:45 -0700)
Xe3p_XPC IP requires a new PAT table; note that this table has one fewer
column than the Xe2/Xe3 tables since compression is not supported.
There's also no "WT" entry (which we wouldn't have used on a platform
without display anyway).

Bspec: 71582
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
Link: https://lore.kernel.org/r/20251016-xe3p-v3-23-3dd173a3097a@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
drivers/gpu/drm/xe/xe_pat.c

index 6e48ff84ad0a0c85317227fb2d68847ff95044b6..7649b554942aa5241cd366404785b91235062fda 100644 (file)
@@ -154,6 +154,41 @@ static const struct xe_pat_table_entry xe2_pat_table[] = {
 static const struct xe_pat_table_entry xe2_pat_ats = XE2_PAT( 0, 0, 0, 0, 3, 3 );
 static const struct xe_pat_table_entry xe2_pat_pta = XE2_PAT( 0, 0, 0, 0, 3, 0 );
 
+/*
+ * Xe3p_XPC PAT table uses the same layout as Xe2/Xe3, except that there's no
+ * option for compression.  Also note that the "L3" and "L4" register fields
+ * actually control L2 and L3 cache respectively on this platform.
+ */
+#define XE3P_XPC_PAT(no_promote, l3clos, l3_policy, l4_policy, __coh_mode) \
+       XE2_PAT(no_promote, 0, l3clos, l3_policy, l4_policy, __coh_mode)
+
+static const struct xe_pat_table_entry xe3p_xpc_pat_ats = XE3P_XPC_PAT( 0, 0, 0, 0, 3 );
+static const struct xe_pat_table_entry xe3p_xpc_pat_pta = XE3P_XPC_PAT( 0, 0, 0, 0, 0 );
+
+static const struct xe_pat_table_entry xe3p_xpc_pat_table[] = {
+       [ 0] = XE3P_XPC_PAT( 0, 0, 0, 0, 0 ),
+       [ 1] = XE3P_XPC_PAT( 0, 0, 0, 0, 2 ),
+       [ 2] = XE3P_XPC_PAT( 0, 0, 0, 0, 3 ),
+       [ 3] = XE3P_XPC_PAT( 0, 0, 3, 3, 0 ),
+       [ 4] = XE3P_XPC_PAT( 0, 0, 3, 3, 2 ),
+       [ 5] = XE3P_XPC_PAT( 0, 0, 3, 0, 0 ),
+       [ 6] = XE3P_XPC_PAT( 0, 0, 3, 0, 2 ),
+       [ 7] = XE3P_XPC_PAT( 0, 0, 3, 0, 3 ),
+       [ 8] = XE3P_XPC_PAT( 0, 0, 0, 3, 0 ),
+       [ 9] = XE3P_XPC_PAT( 0, 0, 0, 3, 2 ),
+       [10] = XE3P_XPC_PAT( 0, 0, 0, 3, 3 ),
+       /* 11..22 are reserved; leave set to all 0's */
+       [23] = XE3P_XPC_PAT( 0, 1, 0, 0, 0 ),
+       [24] = XE3P_XPC_PAT( 0, 1, 0, 0, 2 ),
+       [25] = XE3P_XPC_PAT( 0, 1, 0, 0, 3 ),
+       [26] = XE3P_XPC_PAT( 0, 2, 0, 0, 0 ),
+       [27] = XE3P_XPC_PAT( 0, 2, 0, 0, 2 ),
+       [28] = XE3P_XPC_PAT( 0, 2, 0, 0, 3 ),
+       [29] = XE3P_XPC_PAT( 0, 3, 0, 0, 0 ),
+       [30] = XE3P_XPC_PAT( 0, 3, 0, 0, 2 ),
+       [31] = XE3P_XPC_PAT( 0, 3, 0, 0, 3 ),
+};
+
 u16 xe_pat_index_get_coh_mode(struct xe_device *xe, u16 pat_index)
 {
        WARN_ON(pat_index >= xe->pat.n_entries);
@@ -380,9 +415,68 @@ static const struct xe_pat_ops xe2_pat_ops = {
        .dump = xe2_dump,
 };
 
+static int xe3p_xpc_dump(struct xe_gt *gt, struct drm_printer *p)
+{
+       struct xe_device *xe = gt_to_xe(gt);
+       unsigned int fw_ref;
+       u32 pat;
+       int i;
+
+       fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
+       if (!fw_ref)
+               return -ETIMEDOUT;
+
+       drm_printf(p, "PAT table:\n");
+
+       for (i = 0; i < xe->pat.n_entries; i++) {
+               pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_INDEX(i)));
+
+               drm_printf(p, "PAT[%2d] = [ %u, %u, %u, %u, %u ]  (%#8x)\n", i,
+                          !!(pat & XE2_NO_PROMOTE),
+                          REG_FIELD_GET(XE2_L3_CLOS, pat),
+                          REG_FIELD_GET(XE2_L3_POLICY, pat),
+                          REG_FIELD_GET(XE2_L4_POLICY, pat),
+                          REG_FIELD_GET(XE2_COH_MODE, pat),
+                          pat);
+       }
+
+       /*
+        * Also print PTA_MODE, which describes how the hardware accesses
+        * PPGTT entries.
+        */
+       pat = xe_gt_mcr_unicast_read_any(gt, XE_REG_MCR(_PAT_PTA));
+
+       drm_printf(p, "Page Table Access:\n");
+       drm_printf(p, "PTA_MODE= [ %u, %u, %u, %u, %u ]  (%#8x)\n",
+                  !!(pat & XE2_NO_PROMOTE),
+                  REG_FIELD_GET(XE2_L3_CLOS, pat),
+                  REG_FIELD_GET(XE2_L3_POLICY, pat),
+                  REG_FIELD_GET(XE2_L4_POLICY, pat),
+                  REG_FIELD_GET(XE2_COH_MODE, pat),
+                  pat);
+
+       xe_force_wake_put(gt_to_fw(gt), fw_ref);
+       return 0;
+}
+
+static const struct xe_pat_ops xe3p_xpc_pat_ops = {
+       .program_graphics = program_pat_mcr,
+       .program_media = program_pat,
+       .dump = xe3p_xpc_dump,
+};
+
 void xe_pat_init_early(struct xe_device *xe)
 {
-       if (GRAPHICS_VER(xe) == 30 || GRAPHICS_VER(xe) == 20) {
+       if (GRAPHICS_VERx100(xe) == 3511) {
+               xe->pat.ops = &xe3p_xpc_pat_ops;
+               xe->pat.table = xe3p_xpc_pat_table;
+               xe->pat.pat_ats = &xe3p_xpc_pat_ats;
+               xe->pat.pat_pta = &xe3p_xpc_pat_pta;
+               xe->pat.n_entries = ARRAY_SIZE(xe3p_xpc_pat_table);
+               xe->pat.idx[XE_CACHE_NONE] = 3;
+               xe->pat.idx[XE_CACHE_WT] = 3;   /* N/A (no display); use UC */
+               xe->pat.idx[XE_CACHE_WB] = 2;
+       } else if (GRAPHICS_VER(xe) == 30 || GRAPHICS_VER(xe) == 20) {
                xe->pat.ops = &xe2_pat_ops;
                xe->pat.table = xe2_pat_table;
                xe->pat.pat_ats = &xe2_pat_ats;