[PATCH v2] drm/xe/mocs: Add debugfs node to dump mocs

Lucas De Marchi lucas.demarchi at intel.com
Thu Apr 25 16:11:51 UTC 2024


On Mon, Apr 22, 2024 at 03:35:50PM GMT, Janga Rahul Kumar wrote:
>This is useful to check mocs configuration. Tests/Tools can use
>this debugfs entry to get mocs info.
>
>v2: Address review comments. Change debugfs output style similar
>to pat debugfs. (Lucas De Marchi)

it looks like there's an igt series that is supposed to use this?

Please add a "Test-with: <msgid>" to point out to that series

>
>Cc: Matt Roper <matthew.d.roper at intel.com>
>Cc: Lucas De Marchi <lucas.demarchi at intel.com>
>Signed-off-by: Janga Rahul Kumar <janga.rahul.kumar at intel.com>
>---
> drivers/gpu/drm/xe/xe_gt_debugfs.c |  11 ++
> drivers/gpu/drm/xe/xe_mocs.c       | 274 +++++++++++++++++++++++++++--
> drivers/gpu/drm/xe/xe_mocs.h       |   8 +
> 3 files changed, 283 insertions(+), 10 deletions(-)
>
>diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c
>index ff7f4cf52fa9..041eef92b705 100644
>--- a/drivers/gpu/drm/xe/xe_gt_debugfs.c
>+++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c
>@@ -17,6 +17,7 @@
> #include "xe_hw_engine.h"
> #include "xe_lrc.h"
> #include "xe_macros.h"
>+#include "xe_mocs.h"
> #include "xe_pat.h"
> #include "xe_pm.h"
> #include "xe_reg_sr.h"
>@@ -198,6 +199,15 @@ static int pat(struct xe_gt *gt, struct drm_printer *p)
> 	return 0;
> }
>
>+static int mocs(struct xe_gt *gt, struct drm_printer *p)
>+{
>+	xe_pm_runtime_get(gt_to_xe(gt));
>+	xe_mocs_dump(gt, p);
>+	xe_pm_runtime_put(gt_to_xe(gt));
>+
>+	return 0;
>+}
>+
> static int rcs_default_lrc(struct xe_gt *gt, struct drm_printer *p)
> {
> 	xe_pm_runtime_get(gt_to_xe(gt));
>@@ -253,6 +263,7 @@ static const struct drm_info_list debugfs_list[] = {
> 	{"register-save-restore", .show = xe_gt_debugfs_simple_show, .data = register_save_restore},
> 	{"workarounds", .show = xe_gt_debugfs_simple_show, .data = workarounds},
> 	{"pat", .show = xe_gt_debugfs_simple_show, .data = pat},
>+	{"mocs", .show = xe_gt_debugfs_simple_show, .data = mocs},
> 	{"default_lrc_rcs", .show = xe_gt_debugfs_simple_show, .data = rcs_default_lrc},
> 	{"default_lrc_ccs", .show = xe_gt_debugfs_simple_show, .data = ccs_default_lrc},
> 	{"default_lrc_bcs", .show = xe_gt_debugfs_simple_show, .data = bcs_default_lrc},
>diff --git a/drivers/gpu/drm/xe/xe_mocs.c b/drivers/gpu/drm/xe/xe_mocs.c
>index 1e92f8ee07ba..e45d2b2caadf 100644
>--- a/drivers/gpu/drm/xe/xe_mocs.c
>+++ b/drivers/gpu/drm/xe/xe_mocs.c
>@@ -43,6 +43,8 @@ struct xe_mocs_info {
> 	u8 uc_index;
> 	u8 wb_index;
> 	u8 unused_entries_index;
>+	void (*dump)(struct xe_mocs_info *mocs, unsigned int flags,
>+		     struct xe_gt *gt, struct drm_printer *p);

please follow the same pattern as xe_pat.c. Everywhere we use function
pointers we put them into a ops struct.

> };
>
> /* Defines for the tables (XXX_MOCS_0 - XXX_MOCS_63) */
>@@ -57,6 +59,17 @@ struct xe_mocs_info {
> #define LE_COS(value)		((value) << 15)
> #define LE_SSE(value)		((value) << 17)
>
>+#define LE_CACHEABILITY_MASK	REG_GENMASK(1, 0)
>+#define LE_TGT_CACHE_MASK	REG_GENMASK(3, 2)
>+#define LE_LRUM_MASK		REG_GENMASK(5, 4)
>+#define LE_AOM_MASK		REG_BIT(6)
>+#define LE_RSC_MASK		REG_BIT(7)
>+#define LE_SCC_MASK		REG_GENMASK(10, 8)
>+#define LE_PFM_MASK		REG_GENMASK(13, 11)
>+#define LE_SCF_MASK		REG_BIT(14)
>+#define LE_COS_MASK		REG_GENMASK(16, 15)
>+#define LE_SSE_MASK		REG_GENMASK(18, 17)

convention for register in regs/ is:

  * Define the register contents (i.e. bit and bit field macros) from most
  * significant to least significant bit. Indent the register content macros
  * using two extra spaces between ``#define`` and the macro name.

it would be good to follow it here too, even if not technically in the
regs/ dir. So, let's define those masks with LE_SSE_MASK first.
However.... are we too verbose here? Main use for this is to double
check with the spec. Do we need to spell out each field individually? We
were already logging them to kernel log:

	mocs_dbg(gt, "GLOB_MOCS[%d] 0x%x 0x%x\n", i,
		 XELP_GLOBAL_MOCS(i).addr, mocs);

Similarly to xe_pat.c, I think the output should match and the only
difference being the time in which we are outputing it. +Matt who added
the PAT ones for his opinion... it seems the PAT ones are also a little
verbose, but we don't print to kernel log on probe.

>+
> /* Defines for the tables (LNCFMOCS0 - LNCFMOCS31) - two entries per word */
> #define L3_ESC(value)		((value) << 0)
> #define L3_SCC(value)		((value) << 1)
>@@ -64,6 +77,17 @@ struct xe_mocs_info {
> #define L3_GLBGO(value)		((value) << 6)
> #define L3_LKUP(value)		((value) << 7)
>
>+#define L3_ESC_MASK			REG_BIT(0)
>+#define L3_SCC_MASK			REG_GENMASK(3, 1)
>+#define L3_CACHEABILITY_MASK		REG_GENMASK(5, 4)
>+#define L3_GLBGO_MASK			REG_BIT(6)
>+#define L3_LKUP_MASK			REG_BIT(7)
>+#define L3_UPPER_IDX_ESC_MASK		REG_BIT(16)
>+#define L3_UPPER_IDX_SCC_MASK		REG_GENMASK(19, 17)
>+#define L3_UPPER_IDX_CACHEABILITY_MASK	REG_GENMASK(21, 20)
>+#define L3_UPPER_GLBGO_MASK		REG_BIT(22)
>+#define L3_UPPER_LKUP_MASK		REG_BIT(23)
>+
> /* Defines for the tables (GLOB_MOCS_0 - GLOB_MOCS_16) */
> #define IG_PAT				REG_BIT(8)
> #define L3_CACHE_POLICY_MASK		REG_GENMASK(5, 4)
>@@ -107,6 +131,8 @@ struct xe_mocs_info {
> #define XE2_L3_1_XD		REG_FIELD_PREP(L3_CACHE_POLICY_MASK, 1)
> #define XE2_L3_3_UC		REG_FIELD_PREP(L3_CACHE_POLICY_MASK, 3)
>
>+#define XE2_L3_CLOS_MASK	REG_GENMASK(7, 6)
>+
> #define MOCS_ENTRY(__idx, __control_value, __l3cc_value) \
> 	[__idx] = { \
> 		.control_value = __control_value, \
>@@ -255,6 +281,82 @@ static const struct xe_mocs_entry gen12_mocs_desc[] = {
> 		   L3_1_UC)
> };
>
>+static bool regs_are_mcr(struct xe_gt *gt)
>+{
>+	struct xe_device *xe = gt_to_xe(gt);
>+
>+	if (xe_gt_is_media_type(gt))
>+		return MEDIA_VER(xe) >= 20;
>+	else
>+		return GRAPHICS_VERx100(xe) >= 1250;
>+}

this is a prep patch moving the function

>+
>+static void xelp_lncf_dump(struct xe_mocs_info *info, struct xe_gt *gt, struct drm_printer *p)
>+{
>+	unsigned int i, j;
>+	u32 reg_val;
>+
>+	drm_printf(p, "LNCFCMOCS[idx] = [ESC, SCC, L3CC] (value)\n\n");
>+
>+	for (i = 0, j = 0; i < (info->n_entries + 1) / 2; i++, j++) {
>+		if (regs_are_mcr(gt))
>+			reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
>+		else
>+			reg_val = xe_mmio_read32(gt, XELP_LNCFCMOCS(i));
>+
>+		drm_printf(p, "LNCFCMOCS[%2d] = [%u, %u, %u] (%#8x)\n",
>+			   j++,
>+			   !!(reg_val & L3_ESC_MASK),
>+			   REG_FIELD_GET(L3_SCC_MASK, reg_val),
>+			   REG_FIELD_GET(L3_CACHEABILITY_MASK, reg_val),
>+			   reg_val);
>+
>+		drm_printf(p, "LNCFCMOCS[%2d] = [%u, %u, %u] (%#8x)\n",
>+			   j,
>+			   !!(reg_val & L3_UPPER_IDX_ESC_MASK),
>+			   REG_FIELD_GET(L3_UPPER_IDX_SCC_MASK, reg_val),
>+			   REG_FIELD_GET(L3_UPPER_IDX_CACHEABILITY_MASK, reg_val),
>+			   reg_val);
>+	}
>+}
>+
>+static void gen12_mocs_dump(struct xe_mocs_info *info, unsigned int flags,

s/gen12/xelp/

>+			    struct xe_gt *gt, struct drm_printer *p)
>+{
>+	unsigned int i;
>+	u32 reg_val;
>+
>+	if (flags & HAS_GLOBAL_MOCS) {
>+		drm_printf(p, "Global mocs table configuration:\n");
>+		drm_printf(p, "GLOB_MOCS[idx] = [LeCC, TC, LRUM, AOM, RSC, SCC, PFM, SCF, CoS, SSE] (value)\n\n");
>+
>+		for (i = 0; i < info->n_entries; i++) {
>+			if (regs_are_mcr(gt))
>+				reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
>+			else
>+				reg_val = xe_mmio_read32(gt, XELP_GLOBAL_MOCS(i));
>+
>+		drm_printf(p, "GLOB_MOCS[%2d] = [%u, %u, %u, %u, %u, %u, %u, %u, %u, %u ] (%#8x)\n",
>+			   i,
>+			   REG_FIELD_GET(LE_CACHEABILITY_MASK, reg_val),
>+			   REG_FIELD_GET(LE_TGT_CACHE_MASK, reg_val),
>+			   REG_FIELD_GET(LE_LRUM_MASK, reg_val),
>+			   !!(reg_val & LE_AOM_MASK),
>+			   !!(reg_val & LE_RSC_MASK),
>+			   REG_FIELD_GET(LE_SCC_MASK, reg_val),
>+			   REG_FIELD_GET(LE_PFM_MASK, reg_val),
>+			   !!(reg_val & LE_SCF_MASK),
>+			   REG_FIELD_GET(LE_COS_MASK, reg_val),
>+			   REG_FIELD_GET(LE_SSE_MASK, reg_val),
>+			   reg_val);
>+		}
>+	}
>+
>+	if (flags & HAS_LNCF_MOCS) {

watch out for coding style... shouldn't have the { }, here and in other
places.

>+		xelp_lncf_dump(info, gt, p);
>+	}
>+}
>+
> static const struct xe_mocs_entry dg1_mocs_desc[] = {
> 	/* UC */
> 	MOCS_ENTRY(1, 0, L3_1_UC),
>@@ -279,6 +381,14 @@ static const struct xe_mocs_entry dg1_mocs_desc[] = {
> 	MOCS_ENTRY(63, 0, L3_1_UC),
> };
>
>+static void dg1_mocs_dump(struct xe_mocs_info *info, unsigned int flags, struct xe_gt *gt,
>+			  struct drm_printer *p)
>+{
>+	if (flags & HAS_LNCF_MOCS) {

you should eather uses flags or use the function pointers to
differentiate these. From flags we have:

	if (!IS_DGFX(xe) || GRAPHICS_VER(xe) >= 20)
		flags |= HAS_GLOBAL_MOCS;
         if (GRAPHICS_VER(xe) < 20)
                 flags |= HAS_LNCF_MOCS;

So if keeping the flags, dg1_mocs_dump() would be gone and you'd simply
use xelp_mocs_dump()

>+		xelp_lncf_dump(info, gt, p);
>+	}
>+}
>+
> static const struct xe_mocs_entry dg2_mocs_desc[] = {
> 	/* UC - Coherent; GO:L3 */
> 	MOCS_ENTRY(0, 0, L3_1_UC | L3_LKUP(1)),
>@@ -291,6 +401,43 @@ static const struct xe_mocs_entry dg2_mocs_desc[] = {
> 	MOCS_ENTRY(3, 0, L3_3_WB | L3_LKUP(1)),
> };
>
>+static void xehp_lncf_dump(struct xe_mocs_info *info, struct xe_gt *gt, struct drm_printer *p)
>+{
>+	unsigned int i, j;
>+	u32 reg_val;
>+
>+	drm_printf(p, "LNCFCMOCS[idx] = [UCL3LOOKUP, GLBGO, L3CC] (value)\n\n");
>+
>+	for (i = 0, j = 0; i < (info->n_entries + 1) / 2; i++, j++) {
>+		if (regs_are_mcr(gt))
>+			reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
>+		else
>+			reg_val = xe_mmio_read32(gt, XELP_LNCFCMOCS(i));
>+
>+		drm_printf(p, "LNCFCMOCS[%2d] = [%u, %u, %u] (%#8x)\n",
>+			   j++,
>+			   !!(reg_val & L3_LKUP_MASK),
>+			   !!(reg_val & L3_GLBGO_MASK),
>+			   REG_FIELD_GET(L3_CACHEABILITY_MASK, reg_val),
>+			   reg_val);
>+
>+		drm_printf(p, "LNCFCMOCS[%2d] = [%u, %u, %u] (%#8x)\n",
>+			   j,
>+			   !!(reg_val & L3_UPPER_LKUP_MASK),
>+			   !!(reg_val & L3_UPPER_GLBGO_MASK),
>+			   REG_FIELD_GET(L3_UPPER_IDX_CACHEABILITY_MASK, reg_val),
>+			   reg_val);
>+	}
>+}
>+
>+static void dg2_mocs_dump(struct xe_mocs_info *info, unsigned int flags, struct xe_gt *gt,
>+			  struct drm_printer *p)
>+{
>+	if (flags & HAS_LNCF_MOCS) {

same comment as for DG1

>+		xehp_lncf_dump(info, gt, p);
>+	}
>+}
>+
> static const struct xe_mocs_entry pvc_mocs_desc[] = {
> 	/* Error */
> 	MOCS_ENTRY(0, 0, L3_3_WB),
>@@ -302,6 +449,34 @@ static const struct xe_mocs_entry pvc_mocs_desc[] = {
> 	MOCS_ENTRY(2, 0, L3_3_WB),
> };
>
>+static void pvc_mocs_dump(struct xe_mocs_info *info, unsigned int flags, struct xe_gt *gt,
>+			  struct drm_printer *p)
>+{
>+	unsigned int i, j;
>+	u32 reg_val;
>+
>+	if (flags & HAS_LNCF_MOCS) {

if it's a pvc-only function, we know what it has, no need to check
flags.

>+		drm_printf(p, "LNCFCMOCS[idx] = [ L3CC ] (value)\n\n");
>+
>+		for (i = 0, j = 0; i < (info->n_entries + 1) / 2; i++, j++) {
>+			if (regs_are_mcr(gt))
>+				reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
>+			else
>+				reg_val = xe_mmio_read32(gt, XELP_LNCFCMOCS(i));
>+
>+			drm_printf(p, "LNCFCMOCS[%2d] = [ %u ] (%#8x)\n",
>+				   j++,
>+				   REG_FIELD_GET(L3_CACHEABILITY_MASK, reg_val),
>+				   reg_val);
>+
>+			drm_printf(p, "LNCFCMOCS[%2d] = [ %u ] (%#8x)\n",
>+				   j,
>+				   REG_FIELD_GET(L3_UPPER_IDX_CACHEABILITY_MASK, reg_val),
>+				   reg_val);
>+		}
>+	}
>+}
>+
> static const struct xe_mocs_entry mtl_mocs_desc[] = {
> 	/* Error - Reserved for Non-Use */
> 	MOCS_ENTRY(0,
>@@ -353,6 +528,36 @@ static const struct xe_mocs_entry mtl_mocs_desc[] = {
> 		   L3_GLBGO(1) | L3_1_UC),
> };
>
>+static void mtl_mocs_dump(struct xe_mocs_info *info, unsigned int flags,
>+			  struct xe_gt *gt, struct drm_printer *p)
>+{
>+	unsigned int i;
>+	u32 reg_val;
>+
>+	if (flags & HAS_GLOBAL_MOCS) {

ditto... if it's MTL-only function, we know what it has.

>+		drm_printf(p, "Global mocs table configuration:\n");
>+		drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L4_CACHE_POLICY] (value)\n\n");
>+
>+		for (i = 0; i < info->n_entries; i++) {
>+			if (regs_are_mcr(gt))
>+				reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
>+			else
>+				reg_val = xe_mmio_read32(gt, XELP_GLOBAL_MOCS(i));
>+
>+			drm_printf(p, "GLOB_MOCS[%2d] = [%u, %u]  (%#8x)\n",
>+				   i,
>+				   !!(reg_val & IG_PAT),
>+				   REG_FIELD_GET(L4_CACHE_POLICY_MASK, reg_val),
>+				   reg_val);
>+		}
>+	}
>+
>+	if (flags & HAS_LNCF_MOCS) {
>+		/* MTL lncf mocs table pattern is similar to that of xehp */
>+		xehp_lncf_dump(info, gt, p);
>+	}
>+}
>+
> static const struct xe_mocs_entry xe2_mocs_table[] = {
> 	/* Defer to PAT */
> 	MOCS_ENTRY(0, XE2_L3_0_WB | L4_3_UC, 0),
>@@ -366,6 +571,32 @@ static const struct xe_mocs_entry xe2_mocs_table[] = {
> 	MOCS_ENTRY(4, IG_PAT | XE2_L3_0_WB | L4_0_WB, 0),
> };
>
>+static void xe2_mocs_dump(struct xe_mocs_info *info, unsigned int flags,
>+			  struct xe_gt *gt, struct drm_printer *p)
>+{
>+	unsigned int i;
>+	u32 reg_val;
>+
>+	if (flags & HAS_GLOBAL_MOCS) {

xe2 always has global mocs, regardless of dgfx or igfx.

Lucas De Marchi

>+		drm_printf(p, "Global mocs table configuration:\n");
>+		drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L3_CLOS, L3_CACHE_POLICY, L4_CACHE_POLICY] (value)\n\n");
>+
>+		for (i = 0; i < info->n_entries; i++) {
>+			if (regs_are_mcr(gt))
>+				reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
>+			else
>+				reg_val = xe_mmio_read32(gt, XELP_GLOBAL_MOCS(i));
>+
>+			drm_printf(p, "GLOB_MOCS[%2d] = [%u, %u, %u]  (%#8x)\n",
>+				   i,
>+				   !!(reg_val & IG_PAT),
>+				   REG_FIELD_GET(XE2_L3_CLOS_MASK, reg_val),
>+				   REG_FIELD_GET(L4_CACHE_POLICY_MASK, reg_val),
>+				   reg_val);
>+		}
>+	}
>+}
>+
> static unsigned int get_mocs_settings(struct xe_device *xe,
> 				      struct xe_mocs_info *info)
> {
>@@ -382,6 +613,7 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
> 		info->uc_index = 3;
> 		info->wb_index = 4;
> 		info->unused_entries_index = 4;
>+		info->dump = xe2_mocs_dump;
> 		break;
> 	case XE_PVC:
> 		info->size = ARRAY_SIZE(pvc_mocs_desc);
>@@ -390,6 +622,7 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
> 		info->uc_index = 1;
> 		info->wb_index = 2;
> 		info->unused_entries_index = 2;
>+		info->dump = pvc_mocs_dump;
> 		break;
> 	case XE_METEORLAKE:
> 		info->size = ARRAY_SIZE(mtl_mocs_desc);
>@@ -397,6 +630,7 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
> 		info->n_entries = MTL_NUM_MOCS_ENTRIES;
> 		info->uc_index = 9;
> 		info->unused_entries_index = 1;
>+		info->dump = mtl_mocs_dump;
> 		break;
> 	case XE_DG2:
> 		info->size = ARRAY_SIZE(dg2_mocs_desc);
>@@ -408,6 +642,7 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
> 		 */
> 		info->n_entries = XELP_NUM_MOCS_ENTRIES - 1;
> 		info->unused_entries_index = 3;
>+		info->dump = dg2_mocs_dump;
> 		break;
> 	case XE_DG1:
> 		info->size = ARRAY_SIZE(dg1_mocs_desc);
>@@ -415,6 +650,7 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
> 		info->uc_index = 1;
> 		info->n_entries = XELP_NUM_MOCS_ENTRIES;
> 		info->unused_entries_index = 5;
>+		info->dump = dg1_mocs_dump;
> 		break;
> 	case XE_TIGERLAKE:
> 	case XE_ROCKETLAKE:
>@@ -426,6 +662,7 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
> 		info->n_entries = XELP_NUM_MOCS_ENTRIES;
> 		info->uc_index = 3;
> 		info->unused_entries_index = 2;
>+		info->dump = gen12_mocs_dump;
> 		break;
> 	default:
> 		drm_err(&xe->drm, "Platform that should have a MOCS table does not.\n");
>@@ -467,16 +704,6 @@ static u32 get_entry_control(const struct xe_mocs_info *info,
> 	return info->table[info->unused_entries_index].control_value;
> }
>
>-static bool regs_are_mcr(struct xe_gt *gt)
>-{
>-	struct xe_device *xe = gt_to_xe(gt);
>-
>-	if (xe_gt_is_media_type(gt))
>-		return MEDIA_VER(xe) >= 20;
>-	else
>-		return GRAPHICS_VERx100(xe) >= 1250;
>-}
>-
> static void __init_mocs_table(struct xe_gt *gt,
> 			      const struct xe_mocs_info *info)
> {
>@@ -578,6 +805,33 @@ void xe_mocs_init(struct xe_gt *gt)
> 		init_l3cc_table(gt, &table);
> }
>
>+void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p)
>+{
>+	struct xe_mocs_info table;
>+	unsigned int flags;
>+	u32 ret;
>+	struct xe_device *xe = gt_to_xe(gt);
>+
>+	flags = get_mocs_settings(xe, &table);
>+
>+	if (!table.dump)
>+		return;
>+
>+	xe_device_mem_access_get(xe);
>+	ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
>+
>+	if (ret)
>+		goto err_fw;
>+
>+	table.dump(&table, flags, gt, p);
>+
>+	xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
>+
>+err_fw:
>+	xe_assert(xe, !ret);
>+	xe_device_mem_access_put(xe);
>+}
>+
> #if IS_ENABLED(CONFIG_DRM_XE_KUNIT_TEST)
> #include "tests/xe_mocs.c"
> #endif
>diff --git a/drivers/gpu/drm/xe/xe_mocs.h b/drivers/gpu/drm/xe/xe_mocs.h
>index 053754c5a94e..d6fa4485a6e9 100644
>--- a/drivers/gpu/drm/xe/xe_mocs.h
>+++ b/drivers/gpu/drm/xe/xe_mocs.h
>@@ -10,8 +10,16 @@
>
> struct xe_exec_queue;
> struct xe_gt;
>+struct drm_printer;
>
> void xe_mocs_init_early(struct xe_gt *gt);
> void xe_mocs_init(struct xe_gt *gt);
>
>+/**
>+ * xe_mocs_dump - Dump mocs table
>+ * @gt: GT structure
>+ * @p: Printer to dump info to
>+ */
>+void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p);
>+
> #endif
>-- 
>2.25.1
>


More information about the Intel-xe mailing list