drm/xe: Use vfunc to initialize PAT
authorLucas De Marchi <lucas.demarchi@intel.com>
Wed, 27 Sep 2023 19:38:56 +0000 (12:38 -0700)
committerRodrigo Vivi <rodrigo.vivi@intel.com>
Thu, 21 Dec 2023 16:41:20 +0000 (11:41 -0500)
Split the PAT initialization between SW-only and HW. The _early() only
sets up the ops and data structure that are used later to program the
tables. This allows the PAT to be easily extended to other platforms.

Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
Link: https://lore.kernel.org/r/20230927193902.2849159-6-lucas.demarchi@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
drivers/gpu/drm/xe/xe_device.c
drivers/gpu/drm/xe/xe_device_types.h
drivers/gpu/drm/xe/xe_pat.c
drivers/gpu/drm/xe/xe_pat.h

index 67ec55810ca359a860b573cd077c590541513abb..113fca462141fd78a2c8b7ead9648ba0a3eb001a 100644 (file)
@@ -25,6 +25,7 @@
 #include "xe_irq.h"
 #include "xe_mmio.h"
 #include "xe_module.h"
+#include "xe_pat.h"
 #include "xe_pcode.h"
 #include "xe_pm.h"
 #include "xe_query.h"
@@ -268,6 +269,8 @@ int xe_device_probe(struct xe_device *xe)
        int err;
        u8 id;
 
+       xe_pat_init_early(xe);
+
        xe->info.mem_region_mask = 1;
 
        for_each_tile(tile, xe, id) {
index aa9935ff6d84ed2f8ebb9caf7ea3571f3107bfe3..c4920631677bd10b1923cedfb54243909f1f6355 100644 (file)
@@ -19,6 +19,7 @@
 #include "xe_step_types.h"
 
 struct xe_ggtt;
+struct xe_pat_ops;
 
 #define XE_BO_INVALID_OFFSET   LONG_MAX
 
@@ -310,6 +311,18 @@ struct xe_device {
                atomic_t ref;
        } mem_access;
 
+       /**
+        * @pat: Encapsulate PAT related stuff
+        */
+       struct {
+               /** Internal operations to abstract platforms */
+               const struct xe_pat_ops *ops;
+               /** PAT table to program in the HW */
+               const u32 *table;
+               /** Number of PAT entries */
+               int n_entries;
+       } pat;
+
        /** @d3cold: Encapsulate d3cold related stuff */
        struct {
                /** capable: Indicates if root port is d3cold capable */
index 71e0e047fff3b998fabdae9e07d2213493156b54..28f401c500d8fa1d1c9b5e006c75c797b5be7148 100644 (file)
 #define TGL_PAT_WC                             REG_FIELD_PREP(TGL_MEM_TYPE_MASK, 1)
 #define TGL_PAT_UC                             REG_FIELD_PREP(TGL_MEM_TYPE_MASK, 0)
 
+struct xe_pat_ops {
+       void (*program_graphics)(struct xe_gt *gt, const u32 table[], int n_entries);
+       void (*program_media)(struct xe_gt *gt, const u32 table[], int n_entries);
+};
+
 static const u32 tgl_pat_table[] = {
        [0] = TGL_PAT_WB,
        [1] = TGL_PAT_WC,
@@ -80,24 +85,37 @@ static void program_pat_mcr(struct xe_gt *gt, const u32 table[], int n_entries)
        }
 }
 
-void xe_pat_init(struct xe_gt *gt)
-{
-       struct xe_device *xe = gt_to_xe(gt);
+static const struct xe_pat_ops tgl_pat_ops = {
+       .program_graphics = program_pat,
+};
+
+static const struct xe_pat_ops dg2_pat_ops = {
+       .program_graphics = program_pat_mcr,
+};
+
+/*
+ * SAMedia register offsets are adjusted by the write methods and they target
+ * registers that are not MCR, while for normal GT they are MCR
+ */
+static const struct xe_pat_ops mtl_pat_ops = {
+       .program_graphics = program_pat,
+       .program_media = program_pat_mcr,
+};
 
+void xe_pat_init_early(struct xe_device *xe)
+{
        if (xe->info.platform == XE_METEORLAKE) {
-               /*
-                * SAMedia register offsets are adjusted by the write methods
-                * and they target registers that are not MCR, while for normal
-                * GT they are MCR
-                */
-               if (xe_gt_is_media_type(gt))
-                       program_pat(gt, mtl_pat_table, ARRAY_SIZE(mtl_pat_table));
-               else
-                       program_pat_mcr(gt, mtl_pat_table, ARRAY_SIZE(mtl_pat_table));
+               xe->pat.ops = &mtl_pat_ops;
+               xe->pat.table = mtl_pat_table;
+               xe->pat.n_entries = ARRAY_SIZE(mtl_pat_table);
        } else if (xe->info.platform == XE_PVC || xe->info.platform == XE_DG2) {
-               program_pat_mcr(gt, pvc_pat_table, ARRAY_SIZE(pvc_pat_table));
+               xe->pat.ops = &dg2_pat_ops;
+               xe->pat.table = pvc_pat_table;
+               xe->pat.n_entries = ARRAY_SIZE(pvc_pat_table);
        } else if (GRAPHICS_VERx100(xe) <= 1210) {
-               program_pat(gt, tgl_pat_table, ARRAY_SIZE(tgl_pat_table));
+               xe->pat.ops = &tgl_pat_ops;
+               xe->pat.table = tgl_pat_table;
+               xe->pat.n_entries = ARRAY_SIZE(tgl_pat_table);
        } else {
                /*
                 * Going forward we expect to need new PAT settings for most
@@ -111,3 +129,16 @@ void xe_pat_init(struct xe_gt *gt)
                        GRAPHICS_VER(xe), GRAPHICS_VERx100(xe) % 100);
        }
 }
+
+void xe_pat_init(struct xe_gt *gt)
+{
+       struct xe_device *xe = gt_to_xe(gt);
+
+       if (!xe->pat.ops)
+               return;
+
+       if (xe_gt_is_media_type(gt))
+               xe->pat.ops->program_media(gt, xe->pat.table, xe->pat.n_entries);
+       else
+               xe->pat.ops->program_graphics(gt, xe->pat.table, xe->pat.n_entries);
+}
index 659de40081316e49f751a8cb72d266842448aabd..168e80e63809a331d45696fc0458ca38ec0b97d4 100644 (file)
@@ -7,7 +7,18 @@
 #define _XE_PAT_H_
 
 struct xe_gt;
+struct xe_device;
 
+/**
+ * xe_pat_init_early - SW initialization, setting up data based on device
+ * @xe: xe device
+ */
+void xe_pat_init_early(struct xe_device *xe);
+
+/**
+ * xe_pat_init - Program HW PAT table
+ * @gt: GT structure
+ */
 void xe_pat_init(struct xe_gt *gt);
 
 #endif