File Index
Files and directories
Sign in
FILE

xe_gt_mcr.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/xe/xe_gt_mcr.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2022 Intel Corporation
  4 */
  5
  6#include "xe_gt_mcr.h"
  7
  8#include "regs/xe_gt_regs.h"
  9#include "xe_assert.h"
 10#include "xe_gt.h"
 11#include "xe_gt_printk.h"
 12#include "xe_gt_topology.h"
 13#include "xe_gt_types.h"
 14#include "xe_guc_hwconfig.h"
 15#include "xe_mmio.h"
 16#include "xe_sriov.h"
 17
 18/**
 19 * DOC: GT Multicast/Replicated (MCR) Register Support
 20 *
 21 * Some GT registers are designed as "multicast" or "replicated" registers:
 22 * multiple instances of the same register share a single MMIO offset.  MCR
 23 * registers are generally used when the hardware needs to potentially track
 24 * independent values of a register per hardware unit (e.g., per-subslice,
 25 * per-L3bank, etc.).  The specific types of replication that exist vary
 26 * per-platform.
 27 *
 28 * MMIO accesses to MCR registers are controlled according to the settings
 29 * programmed in the platform's MCR_SELECTOR register(s).  MMIO writes to MCR
 30 * registers can be done in either multicast (a single write updates all
 31 * instances of the register to the same value) or unicast (a write updates only
 32 * one specific instance) form.  Reads of MCR registers always operate in a
 33 * unicast manner regardless of how the multicast/unicast bit is set in
 34 * MCR_SELECTOR.  Selection of a specific MCR instance for unicast operations is
 35 * referred to as "steering."
 36 *
 37 * If MCR register operations are steered toward a hardware unit that is
 38 * fused off or currently powered down due to power gating, the MMIO operation
 39 * is "terminated" by the hardware.  Terminated read operations will return a
 40 * value of zero and terminated unicast write operations will be silently
 41 * ignored. During device initialization, the goal of the various
 42 * ``init_steering_*()`` functions is to apply the platform-specific rules for
 43 * each MCR register type to identify a steering target that will select a
 44 * non-terminated instance.
 45 *
 46 * MCR registers are not available on Virtual Function (VF).
 47 */
 48
 49static inline struct xe_reg to_xe_reg(struct xe_reg_mcr reg_mcr)
 50{
 51	return reg_mcr.__reg;
 52}
 53
 54enum {
 55	MCR_OP_READ,
 56	MCR_OP_WRITE
 57};
 58
 59static const struct xe_mmio_range xelp_l3bank_steering_table[] = {
 60	{ 0x00B100, 0x00B3FF },
 61	{},
 62};
 63
 64static const struct xe_mmio_range xehp_l3bank_steering_table[] = {
 65	{ 0x008C80, 0x008CFF },
 66	{ 0x00B100, 0x00B3FF },
 67	{},
 68};
 69
 70/*
 71 * Although the bspec lists more "MSLICE" ranges than shown here, some of those
 72 * are of a "GAM" subclass that has special rules and doesn't need to be
 73 * included here.
 74 */
 75static const struct xe_mmio_range xehp_mslice_steering_table[] = {
 76	{ 0x00DD00, 0x00DDFF },
 77	{ 0x00E900, 0x00FFFF }, /* 0xEA00 - OxEFFF is unused */
 78	{},
 79};
 80
 81static const struct xe_mmio_range xehp_lncf_steering_table[] = {
 82	{ 0x00B000, 0x00B0FF },
 83	{ 0x00D880, 0x00D8FF },
 84	{},
 85};
 86
 87/*
 88 * We have several types of MCR registers where steering to (0,0) will always
 89 * provide us with a non-terminated value.  We'll stick them all in the same
 90 * table for simplicity.
 91 */
 92static const struct xe_mmio_range xehpc_instance0_steering_table[] = {
 93	{ 0x004000, 0x004AFF },		/* HALF-BSLICE */
 94	{ 0x008800, 0x00887F },		/* CC */
 95	{ 0x008A80, 0x008AFF },		/* TILEPSMI */
 96	{ 0x00B000, 0x00B0FF },		/* HALF-BSLICE */
 97	{ 0x00B100, 0x00B3FF },		/* L3BANK */
 98	{ 0x00C800, 0x00CFFF },		/* HALF-BSLICE */
 99	{ 0x00D800, 0x00D8FF },		/* HALF-BSLICE */
100	{ 0x00DD00, 0x00DDFF },		/* BSLICE */
101	{ 0x00E900, 0x00E9FF },		/* HALF-BSLICE */
102	{ 0x00EC00, 0x00EEFF },		/* HALF-BSLICE */
103	{ 0x00F000, 0x00FFFF },		/* HALF-BSLICE */
104	{ 0x024180, 0x0241FF },		/* HALF-BSLICE */
105	{},
106};
107
108static const struct xe_mmio_range xelpg_instance0_steering_table[] = {
109	{ 0x000B00, 0x000BFF },         /* SQIDI */
110	{ 0x001000, 0x001FFF },         /* SQIDI */
111	{ 0x004000, 0x0048FF },         /* GAM */
112	{ 0x008700, 0x0087FF },         /* SQIDI */
113	{ 0x00B000, 0x00B0FF },         /* NODE */
114	{ 0x00C800, 0x00CFFF },         /* GAM */
115	{ 0x00D880, 0x00D8FF },         /* NODE */
116	{ 0x00DD00, 0x00DDFF },         /* OAAL2 */
117	{},
118};
119
120static const struct xe_mmio_range xelpg_l3bank_steering_table[] = {
121	{ 0x00B100, 0x00B3FF },
122	{},
123};
124
125static const struct xe_mmio_range xelp_dss_steering_table[] = {
126	{ 0x008150, 0x00815F },
127	{ 0x009520, 0x00955F },
128	{ 0x00DE80, 0x00E8FF },
129	{ 0x024A00, 0x024A7F },
130	{},
131};
132
133/* DSS steering is used for GSLICE ranges as well */
134static const struct xe_mmio_range xehp_dss_steering_table[] = {
135	{ 0x005200, 0x0052FF },		/* GSLICE */
136	{ 0x005400, 0x007FFF },		/* GSLICE */
137	{ 0x008140, 0x00815F },		/* GSLICE (0x8140-0x814F), DSS (0x8150-0x815F) */
138	{ 0x008D00, 0x008DFF },		/* DSS */
139	{ 0x0094D0, 0x00955F },		/* GSLICE (0x94D0-0x951F), DSS (0x9520-0x955F) */
140	{ 0x009680, 0x0096FF },		/* DSS */
141	{ 0x00D800, 0x00D87F },		/* GSLICE */
142	{ 0x00DC00, 0x00DCFF },		/* GSLICE */
143	{ 0x00DE80, 0x00E8FF },		/* DSS (0xE000-0xE0FF reserved ) */
144	{ 0x017000, 0x017FFF },		/* GSLICE */
145	{ 0x024A00, 0x024A7F },		/* DSS */
146	{},
147};
148
149/* DSS steering is used for COMPUTE ranges as well */
150static const struct xe_mmio_range xehpc_dss_steering_table[] = {
151	{ 0x008140, 0x00817F },		/* COMPUTE (0x8140-0x814F & 0x8160-0x817F), DSS (0x8150-0x815F) */
152	{ 0x0094D0, 0x00955F },		/* COMPUTE (0x94D0-0x951F), DSS (0x9520-0x955F) */
153	{ 0x009680, 0x0096FF },		/* DSS */
154	{ 0x00DC00, 0x00DCFF },		/* COMPUTE */
155	{ 0x00DE80, 0x00E7FF },		/* DSS (0xDF00-0xE1FF reserved ) */
156	{},
157};
158
159/* DSS steering is used for SLICE ranges as well */
160static const struct xe_mmio_range xelpg_dss_steering_table[] = {
161	{ 0x005200, 0x0052FF },		/* SLICE */
162	{ 0x005500, 0x007FFF },		/* SLICE */
163	{ 0x008140, 0x00815F },		/* SLICE (0x8140-0x814F), DSS (0x8150-0x815F) */
164	{ 0x0094D0, 0x00955F },		/* SLICE (0x94D0-0x951F), DSS (0x9520-0x955F) */
165	{ 0x009680, 0x0096FF },		/* DSS */
166	{ 0x00D800, 0x00D87F },		/* SLICE */
167	{ 0x00DC00, 0x00DCFF },		/* SLICE */
168	{ 0x00DE80, 0x00E8FF },		/* DSS (0xE000-0xE0FF reserved) */
169	{},
170};
171
172static const struct xe_mmio_range xe3p_xpc_xecore_steering_table[] = {
173	{ 0x008140, 0x00817F },         /* SLICE, XeCore, SLICE */
174	{ 0x009480, 0x00955F },         /* SLICE, XeCore */
175	{ 0x00D800, 0x00D87F },		/* SLICE */
176	{ 0x00DC00, 0x00E9FF },         /* SLICE, rsvd, XeCore, rsvd, XeCore, rsvd, XeCore */
177	{ 0x013000, 0x0135FF },         /* XeCore, SLICE */
178	{},
179};
180
181static const struct xe_mmio_range xelpmp_oaddrm_steering_table[] = {
182	{ 0x393200, 0x39323F },
183	{ 0x393400, 0x3934FF },
184	{},
185};
186
187static const struct xe_mmio_range dg2_implicit_steering_table[] = {
188	{ 0x000B00, 0x000BFF },		/* SF (SQIDI replication) */
189	{ 0x001000, 0x001FFF },		/* SF (SQIDI replication) */
190	{ 0x004000, 0x004AFF },		/* GAM (MSLICE replication) */
191	{ 0x008700, 0x0087FF },		/* MCFG (SQIDI replication) */
192	{ 0x00C800, 0x00CFFF },		/* GAM (MSLICE replication) */
193	{ 0x00F000, 0x00FFFF },		/* GAM (MSLICE replication) */
194	{},
195};
196
197static const struct xe_mmio_range xe2lpg_dss_steering_table[] = {
198	{ 0x005200, 0x0052FF },         /* SLICE */
199	{ 0x005500, 0x007FFF },         /* SLICE */
200	{ 0x008140, 0x00815F },         /* SLICE (0x8140-0x814F), DSS (0x8150-0x815F) */
201	{ 0x0094D0, 0x00955F },         /* SLICE (0x94D0-0x951F), DSS (0x9520-0x955F) */
202	{ 0x009680, 0x0096FF },         /* DSS */
203	{ 0x00D800, 0x00D87F },         /* SLICE */
204	{ 0x00DC00, 0x00DCFF },         /* SLICE */
205	{ 0x00DE80, 0x00E8FF },         /* DSS (0xE000-0xE0FF reserved) */
206	{ 0x00E980, 0x00E9FF },         /* SLICE */
207	{ 0x013000, 0x0133FF },         /* DSS (0x13000-0x131FF), SLICE (0x13200-0x133FF) */
208	{},
209};
210
211static const struct xe_mmio_range xe2lpg_sqidi_psmi_steering_table[] = {
212	{ 0x000B00, 0x000BFF },
213	{ 0x001000, 0x001FFF },
214	{},
215};
216
217static const struct xe_mmio_range xe2lpg_instance0_steering_table[] = {
218	{ 0x004000, 0x004AFF },         /* GAM, rsvd, GAMWKR */
219	{ 0x008700, 0x00887F },         /* SQIDI, MEMPIPE */
220	{ 0x00B000, 0x00B3FF },         /* NODE, L3BANK */
221	{ 0x00C800, 0x00CFFF },         /* GAM */
222	{ 0x00D880, 0x00D8FF },         /* NODE */
223	{ 0x00DD00, 0x00DDFF },         /* MEMPIPE */
224	{ 0x00E900, 0x00E97F },         /* MEMPIPE */
225	{ 0x00F000, 0x00FFFF },         /* GAM, GAMWKR */
226	{ 0x013400, 0x0135FF },         /* MEMPIPE */
227	{},
228};
229
230static const struct xe_mmio_range xe2lpm_gpmxmt_steering_table[] = {
231	{ 0x388160, 0x38817F },
232	{ 0x389480, 0x3894CF },
233	{},
234};
235
236static const struct xe_mmio_range xe2lpm_instance0_steering_table[] = {
237	{ 0x384000, 0x3847DF },         /* GAM, rsvd, GAM */
238	{ 0x384900, 0x384AFF },         /* GAM */
239	{ 0x389560, 0x3895FF },         /* MEDIAINF */
240	{ 0x38B600, 0x38B8FF },         /* L3BANK */
241	{ 0x38C800, 0x38D07F },         /* GAM, MEDIAINF */
242	{ 0x38F000, 0x38F0FF },         /* GAM */
243	{ 0x393C00, 0x393C7F },         /* MEDIAINF */
244	{},
245};
246
247static const struct xe_mmio_range xe3lpm_instance0_steering_table[] = {
248	{ 0x384000, 0x3841FF },         /* GAM */
249	{ 0x384400, 0x3847DF },         /* GAM */
250	{ 0x384900, 0x384AFF },         /* GAM */
251	{ 0x389560, 0x3895FF },         /* MEDIAINF */
252	{ 0x38B600, 0x38B8FF },         /* L3BANK */
253	{ 0x38C800, 0x38D07F },         /* GAM, MEDIAINF */
254	{ 0x38D0D0, 0x38F0FF },         /* MEDIAINF, rsvd, GAM */
255	{ 0x393C00, 0x393C7F },         /* MEDIAINF */
256	{},
257};
258
259/*
260 * Different "GAM" ranges have different rules; GAMWKRS, STLB, and GAMREQSTRM
261 * range subtypes need to be steered to (1,0), while all other GAM subtypes
262 * are steered to (0,0) and are included in the "INSTANCE0" table farther
263 * down.
264 */
265static const struct xe_mmio_range xe3p_xpc_gam_grp1_steering_table[] = {
266	{ 0x004000, 0x004AFF },		/* GAMREQSTRM, rsvd, STLB, GAMWKRS, GAMREQSTRM */
267	{ 0x00F100, 0x00FFFF },		/* GAMWKRS */
268	{},
269};
270
271static const struct xe_mmio_range xe3p_xpc_node_steering_table[] = {
272	{ 0x00B000, 0x00B0FF },
273	{ 0x00D880, 0x00D8FF },
274	{},
275};
276
277static const struct xe_mmio_range xe3p_xpc_instance0_steering_table[] = {
278	{ 0x00B500, 0x00B6FF },		/* PSMI */
279	{ 0x00C800, 0x00CFFF },		/* GAMCTRL */
280	{ 0x00F000, 0x00F0FF },		/* GAMCTRL */
281	{},
282};
283
284static void init_steering_l3bank(struct xe_gt *gt)
285{
286	struct xe_device *xe = gt_to_xe(gt);
287	struct xe_mmio *mmio = &gt->mmio;
288
289	if (GRAPHICS_VER(xe) >= 35) {
290		unsigned int first_bank = xe_l3_bank_mask_ffs(gt->fuse_topo.l3_bank_mask);
291		const int banks_per_node = 4;
292		unsigned int node = first_bank / banks_per_node;
293
294		/* L3BANK ranges place node in grpID, bank in instanceid */
295		gt->steering[L3BANK].group_target = node;
296		gt->steering[L3BANK].instance_target = first_bank % banks_per_node;
297
298		/* NODE ranges split the node across grpid and instanceid */
299		gt->steering[NODE].group_target = node >> 1;
300		gt->steering[NODE].instance_target = node & 1;
301	} else if (GRAPHICS_VERx100(xe) >= 1270) {
302		u32 mslice_mask = REG_FIELD_GET(MEML3_EN_MASK,
303						xe_mmio_read32(mmio, MIRROR_FUSE3));
304		u32 bank_mask = REG_FIELD_GET(GT_L3_EXC_MASK,
305					      xe_mmio_read32(mmio, XEHP_FUSE4));
306
307		/*
308		 * Group selects mslice, instance selects bank within mslice.
309		 * Bank 0 is always valid _except_ when the bank mask is 010b.
310		 */
311		gt->steering[L3BANK].group_target = __ffs(mslice_mask);
312		gt->steering[L3BANK].instance_target =
313			bank_mask & BIT(0) ? 0 : 2;
314	} else if (xe->info.platform == XE_DG2) {
315		u32 mslice_mask = REG_FIELD_GET(MEML3_EN_MASK,
316						xe_mmio_read32(mmio, MIRROR_FUSE3));
317		u32 bank = __ffs(mslice_mask) * 8;
318
319		/*
320		 * Like mslice registers, look for a valid mslice and steer to
321		 * the first L3BANK of that quad. Access to the Nth L3 bank is
322		 * split between the first bits of group and instance
323		 */
324		gt->steering[L3BANK].group_target = (bank >> 2) & 0x7;
325		gt->steering[L3BANK].instance_target = bank & 0x3;
326	} else {
327		u32 fuse = REG_FIELD_GET(L3BANK_MASK,
328					 ~xe_mmio_read32(mmio, MIRROR_FUSE3));
329
330		gt->steering[L3BANK].group_target = 0;	/* unused */
331		gt->steering[L3BANK].instance_target = __ffs(fuse);
332	}
333}
334
335static void init_steering_mslice(struct xe_gt *gt)
336{
337	u32 mask = REG_FIELD_GET(MEML3_EN_MASK,
338				 xe_mmio_read32(&gt->mmio, MIRROR_FUSE3));
339
340	/*
341	 * mslice registers are valid (not terminated) if either the meml3
342	 * associated with the mslice is present, or at least one DSS associated
343	 * with the mslice is present.  There will always be at least one meml3
344	 * so we can just use that to find a non-terminated mslice and ignore
345	 * the DSS fusing.
346	 */
347	gt->steering[MSLICE].group_target = __ffs(mask);
348	gt->steering[MSLICE].instance_target = 0;	/* unused */
349
350	/*
351	 * LNCF termination is also based on mslice presence, so we'll set
352	 * it up here.  Either LNCF within a non-terminated mslice will work,
353	 * so we just always pick LNCF 0 here.
354	 */
355	gt->steering[LNCF].group_target = __ffs(mask) << 1;
356	gt->steering[LNCF].instance_target = 0;		/* unused */
357}
358
359static unsigned int dss_per_group(struct xe_gt *gt)
360{
361	struct xe_guc *guc = &gt->uc.guc;
362	u32 max_slices = 0, max_subslices = 0;
363	int ret;
364
365	/*
366	 * Try to query the GuC's hwconfig table for the maximum number of
367	 * slices and subslices.  These don't reflect the platform's actual
368	 * slice/DSS counts, just the physical layout by which we should
369	 * determine the steering targets.  On older platforms with older GuC
370	 * firmware releases it's possible that these attributes may not be
371	 * included in the table, so we can always fall back to the old
372	 * hardcoded layouts.
373	 */
374#define HWCONFIG_ATTR_MAX_SLICES	1
375#define HWCONFIG_ATTR_MAX_SUBSLICES	70
376
377	ret = xe_guc_hwconfig_lookup_u32(guc, HWCONFIG_ATTR_MAX_SLICES,
378					 &max_slices);
379	if (ret < 0 || max_slices == 0)
380		goto fallback;
381
382	ret = xe_guc_hwconfig_lookup_u32(guc, HWCONFIG_ATTR_MAX_SUBSLICES,
383					 &max_subslices);
384	if (ret < 0 || max_subslices == 0)
385		goto fallback;
386
387	return DIV_ROUND_UP(max_subslices, max_slices);
388
389fallback:
390	/*
391	 * Some older platforms don't have tables or don't have complete tables.
392	 * Newer platforms should always have the required info.
393	 */
394	if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 2000 &&
395	    !gt_to_xe(gt)->info.force_execlist)
396		xe_gt_err(gt, "Slice/Subslice counts missing from hwconfig table; using typical fallback values\n");
397
398	if (gt_to_xe(gt)->info.platform == XE_PVC)
399		return 8;
400	else if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1250)
401		return 4;
402	else
403		return 6;
404}
405
406/**
407 * xe_gt_mcr_get_dss_steering - Get the group/instance steering for a DSS
408 * @gt: GT structure
409 * @dss: DSS ID to obtain steering for
410 * @group: pointer to storage for steering group ID
411 * @instance: pointer to storage for steering instance ID
412 */
413void xe_gt_mcr_get_dss_steering(const struct xe_gt *gt, unsigned int dss, u16 *group, u16 *instance)
414{
415	xe_gt_assert(gt, dss < XE_MAX_DSS_FUSE_BITS);
416
417	*group = dss / gt->steering_dss_per_grp;
418	*instance = dss % gt->steering_dss_per_grp;
419}
420
421/**
422 * xe_gt_mcr_steering_info_to_dss_id - Get DSS ID from group/instance steering
423 * @gt: GT structure
424 * @group: steering group ID
425 * @instance: steering instance ID
426 *
427 * Return: the converted DSS id.
428 */
429u32 xe_gt_mcr_steering_info_to_dss_id(struct xe_gt *gt, u16 group, u16 instance)
430{
431	return group * dss_per_group(gt) + instance;
432}
433
434static void init_steering_dss(struct xe_gt *gt)
435{
436	gt->steering_dss_per_grp = dss_per_group(gt);
437
438	xe_gt_mcr_get_dss_steering(gt,
439				   min(xe_dss_mask_group_ffs(gt->fuse_topo.g_dss_mask, 0, 0),
440				       xe_dss_mask_group_ffs(gt->fuse_topo.c_dss_mask, 0, 0)),
441				   &gt->steering[DSS].group_target,
442				   &gt->steering[DSS].instance_target);
443}
444
445static void init_steering_oaddrm(struct xe_gt *gt)
446{
447	/*
448	 * First instance is only terminated if the entire first media slice
449	 * is absent (i.e., no VCS0 or VECS0).
450	 */
451	if (gt->info.engine_mask & (XE_HW_ENGINE_VCS0 | XE_HW_ENGINE_VECS0))
452		gt->steering[OADDRM].group_target = 0;
453	else
454		gt->steering[OADDRM].group_target = 1;
455
456	gt->steering[OADDRM].instance_target = 0;	/* unused */
457}
458
459static void init_steering_sqidi_psmi(struct xe_gt *gt)
460{
461	u32 mask = REG_FIELD_GET(XE2_NODE_ENABLE_MASK,
462				 xe_mmio_read32(&gt->mmio, MIRROR_FUSE3));
463	u32 select = __ffs(mask);
464
465	gt->steering[SQIDI_PSMI].group_target = select >> 1;
466	gt->steering[SQIDI_PSMI].instance_target = select & 0x1;
467}
468
469static void init_steering_gam1(struct xe_gt *gt)
470{
471	gt->steering[GAM1].group_target = 1;
472	gt->steering[GAM1].instance_target = 0;
473}
474
475static const struct {
476	const char *name;
477	void (*init)(struct xe_gt *gt);
478} xe_steering_types[] = {
479	[L3BANK] =	{ "L3BANK",	init_steering_l3bank },
480	[NODE] =	{ "NODE",	NULL }, /* initialized by l3bank init */
481	[MSLICE] =	{ "MSLICE",	init_steering_mslice },
482	[LNCF] =	{ "LNCF",	NULL }, /* initialized by mslice init */
483	[DSS] =		{ "DSS / XeCore", init_steering_dss },
484	[OADDRM] =	{ "OADDRM / GPMXMT", init_steering_oaddrm },
485	[SQIDI_PSMI] =  { "SQIDI_PSMI", init_steering_sqidi_psmi },
486	[GAM1] =	{ "GAMWKRS / STLB / GAMREQSTRM", init_steering_gam1 },
487	[INSTANCE0] =	{ "INSTANCE 0",	NULL },
488	[IMPLICIT_STEERING] = { "IMPLICIT", NULL },
489};
490
491/**
492 * xe_gt_mcr_init_early - Early initialization of the MCR support
493 * @gt: GT structure
494 *
495 * Perform early software only initialization of the MCR lock to allow
496 * the synchronization on accessing the STEER_SEMAPHORE register and
497 * use the xe_gt_mcr_multicast_write() function, plus the minimum
498 * safe MCR registers required for VRAM/CCS probing.
499 */
500void xe_gt_mcr_init_early(struct xe_gt *gt)
501{
502	struct xe_device *xe = gt_to_xe(gt);
503
504	BUILD_BUG_ON(IMPLICIT_STEERING + 1 != NUM_STEERING_TYPES);
505	BUILD_BUG_ON(ARRAY_SIZE(xe_steering_types) != NUM_STEERING_TYPES);
506
507	spin_lock_init(&gt->mcr_lock);
508
509	if (IS_SRIOV_VF(xe))
510		return;
511
512	if (gt->info.type == XE_GT_TYPE_MEDIA) {
513		drm_WARN_ON(&xe->drm, MEDIA_VER(xe) < 13);
514
515		if (MEDIA_VER(xe) >= 30) {
516			gt->steering[OADDRM].ranges = xe2lpm_gpmxmt_steering_table;
517			gt->steering[INSTANCE0].ranges = xe3lpm_instance0_steering_table;
518		} else if (MEDIA_VERx100(xe) >= 1301) {
519			gt->steering[OADDRM].ranges = xe2lpm_gpmxmt_steering_table;
520			gt->steering[INSTANCE0].ranges = xe2lpm_instance0_steering_table;
521		} else {
522			gt->steering[OADDRM].ranges = xelpmp_oaddrm_steering_table;
523		}
524	} else {
525		if (GRAPHICS_VERx100(xe) == 3511) {
526			/*
527			 * TODO: there are some ranges in bspec with missing
528			 * termination: [0x00B000, 0x00B0FF] and
529			 * [0x00D880, 0x00D8FF] (NODE); [0x00B100, 0x00B3FF]
530			 * (L3BANK). Update them here once bspec is updated.
531			 */
532			gt->steering[DSS].ranges = xe3p_xpc_xecore_steering_table;
533			gt->steering[GAM1].ranges = xe3p_xpc_gam_grp1_steering_table;
534			gt->steering[INSTANCE0].ranges = xe3p_xpc_instance0_steering_table;
535			gt->steering[L3BANK].ranges = xelpg_l3bank_steering_table;
536			gt->steering[NODE].ranges = xe3p_xpc_node_steering_table;
537		} else if (GRAPHICS_VER(xe) >= 20) {
538			gt->steering[DSS].ranges = xe2lpg_dss_steering_table;
539			gt->steering[SQIDI_PSMI].ranges = xe2lpg_sqidi_psmi_steering_table;
540			gt->steering[INSTANCE0].ranges = xe2lpg_instance0_steering_table;
541		} else if (GRAPHICS_VERx100(xe) >= 1270) {
542			gt->steering[INSTANCE0].ranges = xelpg_instance0_steering_table;
543			gt->steering[L3BANK].ranges = xelpg_l3bank_steering_table;
544			gt->steering[DSS].ranges = xelpg_dss_steering_table;
545		} else if (xe->info.platform == XE_PVC) {
546			gt->steering[INSTANCE0].ranges = xehpc_instance0_steering_table;
547			gt->steering[DSS].ranges = xehpc_dss_steering_table;
548		} else if (xe->info.platform == XE_DG2) {
549			gt->steering[L3BANK].ranges = xehp_l3bank_steering_table;
550			gt->steering[MSLICE].ranges = xehp_mslice_steering_table;
551			gt->steering[LNCF].ranges = xehp_lncf_steering_table;
552			gt->steering[DSS].ranges = xehp_dss_steering_table;
553			gt->steering[IMPLICIT_STEERING].ranges = dg2_implicit_steering_table;
554		} else {
555			gt->steering[L3BANK].ranges = xelp_l3bank_steering_table;
556			gt->steering[DSS].ranges = xelp_dss_steering_table;
557		}
558	}
559
560	/* Mark instance 0 as initialized, we need this early for VRAM and CCS probe. */
561	gt->steering[INSTANCE0].initialized = true;
562}
563
564/**
565 * xe_gt_mcr_init - Normal initialization of the MCR support
566 * @gt: GT structure
567 *
568 * Perform normal initialization of the MCR for all usages.
569 */
570void xe_gt_mcr_init(struct xe_gt *gt)
571{
572	if (IS_SRIOV_VF(gt_to_xe(gt)))
573		return;
574
575	/* Select non-terminated steering target for each type */
576	for (int i = 0; i < NUM_STEERING_TYPES; i++) {
577		gt->steering[i].initialized = true;
578		if (gt->steering[i].ranges && xe_steering_types[i].init)
579			xe_steering_types[i].init(gt);
580	}
581}
582
583/**
584 * xe_gt_mcr_set_implicit_defaults - Initialize steer control registers
585 * @gt: GT structure
586 *
587 * Some register ranges don't need to have their steering control registers
588 * changed on each access - it's sufficient to set them once on initialization.
589 * This function sets those registers for each platform *
590 */
591void xe_gt_mcr_set_implicit_defaults(struct xe_gt *gt)
592{
593	struct xe_device *xe = gt_to_xe(gt);
594
595	if (IS_SRIOV_VF(xe))
596		return;
597
598	if (xe->info.platform == XE_DG2) {
599		u32 steer_val = REG_FIELD_PREP(MCR_SLICE_MASK, 0) |
600			REG_FIELD_PREP(MCR_SUBSLICE_MASK, 2);
601
602		xe_mmio_write32(&gt->mmio, STEER_SEMAPHORE, steer_val);
603		xe_mmio_write32(&gt->mmio, SF_MCR_SELECTOR, steer_val);
604		/*
605		 * For GAM registers, all reads should be directed to instance 1
606		 * (unicast reads against other instances are not allowed),
607		 * and instance 1 is already the hardware's default steering
608		 * target, which we never change
609		 */
610	}
611}
612
613/*
614 * xe_gt_mcr_get_nonterminated_steering - find group/instance values that
615 *    will steer a register to a non-terminated instance
616 * @gt: GT structure
617 * @reg: register for which the steering is required
618 * @group: return variable for group steering
619 * @instance: return variable for instance steering
620 *
621 * This function returns a group/instance pair that is guaranteed to work for
622 * read steering of the given register. Note that a value will be returned even
623 * if the register is not replicated and therefore does not actually require
624 * steering.
625 *
626 * Returns true if the caller should steer to the @group/@instance values
627 * returned.  Returns false if the caller need not perform any steering
628 */
629bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt,
630					  struct xe_reg_mcr reg_mcr,
631					  u8 *group, u8 *instance)
632{
633	const struct xe_reg reg = to_xe_reg(reg_mcr);
634	const struct xe_mmio_range *implicit_ranges;
635
636	for (int type = 0; type < IMPLICIT_STEERING; type++) {
637		if (!gt->steering[type].ranges)
638			continue;
639
640		for (int i = 0; gt->steering[type].ranges[i].end > 0; i++) {
641			if (xe_mmio_in_range(&gt->mmio, &gt->steering[type].ranges[i], reg)) {
642				drm_WARN(&gt_to_xe(gt)->drm, !gt->steering[type].initialized,
643					 "Uninitialized usage of MCR register %s/%#x\n",
644					 xe_steering_types[type].name, reg.addr);
645
646				*group = gt->steering[type].group_target;
647				*instance = gt->steering[type].instance_target;
648				return true;
649			}
650		}
651	}
652
653	implicit_ranges = gt->steering[IMPLICIT_STEERING].ranges;
654	if (implicit_ranges)
655		for (int i = 0; implicit_ranges[i].end > 0; i++)
656			if (xe_mmio_in_range(&gt->mmio, &implicit_ranges[i], reg))
657				return false;
658
659	/*
660	 * Not found in a steering table and not a register with implicit
661	 * steering. Just steer to 0/0 as a guess and raise a warning.
662	 */
663	drm_WARN(&gt_to_xe(gt)->drm, true,
664		 "Did not find MCR register %#x in any MCR steering table\n",
665		 reg.addr);
666	*group = 0;
667	*instance = 0;
668
669	return true;
670}
671
672/*
673 * Obtain exclusive access to MCR steering.  On MTL and beyond we also need
674 * to synchronize with external clients (e.g., firmware), so a semaphore
675 * register will also need to be taken.
676 */
677static void mcr_lock(struct xe_gt *gt) __acquires(&gt->mcr_lock)
678{
679	struct xe_device *xe = gt_to_xe(gt);
680	int ret = 0;
681
682	spin_lock(&gt->mcr_lock);
683
684	/*
685	 * Starting with MTL we also need to grab a semaphore register
686	 * to synchronize with external agents (e.g., firmware) that now
687	 * shares the same steering control register. The semaphore is obtained
688	 * when a read to the relevant register returns 1.
689	 */
690	if (GRAPHICS_VERx100(xe) >= 1270)
691		ret = xe_mmio_wait32(&gt->mmio, STEER_SEMAPHORE, 0x1, 0x1, 10, NULL,
692				     true);
693
694	drm_WARN_ON_ONCE(&xe->drm, ret == -ETIMEDOUT);
695}
696
697static void mcr_unlock(struct xe_gt *gt) __releases(&gt->mcr_lock)
698{
699	/* Release hardware semaphore - this is done by writing 1 to the register */
700	if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270)
701		xe_mmio_write32(&gt->mmio, STEER_SEMAPHORE, 0x1);
702
703	spin_unlock(&gt->mcr_lock);
704}
705
706/*
707 * Access a register with specific MCR steering
708 *
709 * Caller needs to make sure the relevant forcewake wells are up.
710 */
711static u32 rw_with_mcr_steering(struct xe_gt *gt, struct xe_reg_mcr reg_mcr,
712				u8 rw_flag, int group, int instance, u32 value)
713{
714	const struct xe_reg reg = to_xe_reg(reg_mcr);
715	struct xe_mmio *mmio = &gt->mmio;
716	struct xe_reg steer_reg;
717	u32 steer_val, val = 0;
718
719	lockdep_assert_held(&gt->mcr_lock);
720
721	if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270) {
722		steer_reg = MTL_MCR_SELECTOR;
723		steer_val = REG_FIELD_PREP(MTL_MCR_GROUPID, group) |
724			REG_FIELD_PREP(MTL_MCR_INSTANCEID, instance);
725	} else {
726		steer_reg = MCR_SELECTOR;
727		steer_val = REG_FIELD_PREP(MCR_SLICE_MASK, group) |
728			REG_FIELD_PREP(MCR_SUBSLICE_MASK, instance);
729	}
730
731	/*
732	 * Always leave the hardware in multicast mode when doing reads and only
733	 * change it to unicast mode when doing writes of a specific instance.
734	 *
735	 * The setting of the multicast/unicast bit usually wouldn't matter for
736	 * read operations (which always return the value from a single register
737	 * instance regardless of how that bit is set), but some platforms may
738	 * have workarounds requiring us to remain in multicast mode for reads,
739	 * e.g. Wa_22013088509 on PVC.  There's no real downside to this, so
740	 * we'll just go ahead and do so on all platforms; we'll only clear the
741	 * multicast bit from the mask when explicitly doing a write operation.
742	 *
743	 * No need to save old steering reg value.
744	 */
745	if (rw_flag == MCR_OP_READ)
746		steer_val |= MCR_MULTICAST;
747
748	xe_mmio_write32(mmio, steer_reg, steer_val);
749
750	if (rw_flag == MCR_OP_READ)
751		val = xe_mmio_read32(mmio, reg);
752	else
753		xe_mmio_write32(mmio, reg, value);
754
755	/*
756	 * If we turned off the multicast bit (during a write) we're required
757	 * to turn it back on before finishing.  The group and instance values
758	 * don't matter since they'll be re-programmed on the next MCR
759	 * operation.
760	 */
761	if (rw_flag == MCR_OP_WRITE)
762		xe_mmio_write32(mmio, steer_reg, MCR_MULTICAST);
763
764	return val;
765}
766
767/**
768 * xe_gt_mcr_unicast_read_any - reads a non-terminated instance of an MCR register
769 * @gt: GT structure
770 * @reg_mcr: register to read
771 *
772 * Reads a GT MCR register.  The read will be steered to a non-terminated
773 * instance (i.e., one that isn't fused off or powered down by power gating).
774 * This function assumes the caller is already holding any necessary forcewake
775 * domains.
776 *
777 * Returns the value from a non-terminated instance of @reg.
778 */
779u32 xe_gt_mcr_unicast_read_any(struct xe_gt *gt, struct xe_reg_mcr reg_mcr)
780{
781	const struct xe_reg reg = to_xe_reg(reg_mcr);
782	u8 group, instance;
783	u32 val;
784	bool steer;
785
786	xe_gt_assert(gt, !IS_SRIOV_VF(gt_to_xe(gt)));
787
788	steer = xe_gt_mcr_get_nonterminated_steering(gt, reg_mcr,
789						     &group, &instance);
790
791	if (steer) {
792		mcr_lock(gt);
793		val = rw_with_mcr_steering(gt, reg_mcr, MCR_OP_READ,
794					   group, instance, 0);
795		mcr_unlock(gt);
796	} else {
797		val = xe_mmio_read32(&gt->mmio, reg);
798	}
799
800	return val;
801}
802
803/**
804 * xe_gt_mcr_unicast_read - read a specific instance of an MCR register
805 * @gt: GT structure
806 * @reg_mcr: the MCR register to read
807 * @group: the MCR group
808 * @instance: the MCR instance
809 *
810 * Returns the value read from an MCR register after steering toward a specific
811 * group/instance.
812 */
813u32 xe_gt_mcr_unicast_read(struct xe_gt *gt,
814			   struct xe_reg_mcr reg_mcr,
815			   int group, int instance)
816{
817	u32 val;
818
819	xe_gt_assert(gt, !IS_SRIOV_VF(gt_to_xe(gt)));
820
821	mcr_lock(gt);
822	val = rw_with_mcr_steering(gt, reg_mcr, MCR_OP_READ, group, instance, 0);
823	mcr_unlock(gt);
824
825	return val;
826}
827
828/**
829 * xe_gt_mcr_unicast_write - write a specific instance of an MCR register
830 * @gt: GT structure
831 * @reg_mcr: the MCR register to write
832 * @value: value to write
833 * @group: the MCR group
834 * @instance: the MCR instance
835 *
836 * Write an MCR register in unicast mode after steering toward a specific
837 * group/instance.
838 */
839void xe_gt_mcr_unicast_write(struct xe_gt *gt, struct xe_reg_mcr reg_mcr,
840			     u32 value, int group, int instance)
841{
842	xe_gt_assert(gt, !IS_SRIOV_VF(gt_to_xe(gt)));
843
844	mcr_lock(gt);
845	rw_with_mcr_steering(gt, reg_mcr, MCR_OP_WRITE, group, instance, value);
846	mcr_unlock(gt);
847}
848
849/**
850 * xe_gt_mcr_multicast_write - write a value to all instances of an MCR register
851 * @gt: GT structure
852 * @reg_mcr: the MCR register to write
853 * @value: value to write
854 *
855 * Write an MCR register in multicast mode to update all instances.
856 */
857void xe_gt_mcr_multicast_write(struct xe_gt *gt, struct xe_reg_mcr reg_mcr,
858			       u32 value)
859{
860	struct xe_reg reg = to_xe_reg(reg_mcr);
861
862	xe_gt_assert(gt, !IS_SRIOV_VF(gt_to_xe(gt)));
863
864	/*
865	 * Synchronize with any unicast operations.  Once we have exclusive
866	 * access, the MULTICAST bit should already be set, so there's no need
867	 * to touch the steering register.
868	 */
869	mcr_lock(gt);
870	xe_mmio_write32(&gt->mmio, reg, value);
871	mcr_unlock(gt);
872}
873
874void xe_gt_mcr_steering_dump(struct xe_gt *gt, struct drm_printer *p)
875{
876	for (int i = 0; i < NUM_STEERING_TYPES; i++) {
877		if (gt->steering[i].ranges) {
878			drm_printf(p, "%s steering: group=%#x, instance=%#x\n",
879				   xe_steering_types[i].name,
880				   gt->steering[i].group_target,
881				   gt->steering[i].instance_target);
882			for (int j = 0; gt->steering[i].ranges[j].end; j++)
883				drm_printf(p, "\t0x%06x - 0x%06x\n",
884					   gt->steering[i].ranges[j].start,
885					   gt->steering[i].ranges[j].end);
886		}
887	}
888}
~/ Read-only file preview.