xref: /linux/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c (revision de848da12f752170c2ebe114804a985314fd5a6a)
13ea58029SMichal Wajdeczko // SPDX-License-Identifier: MIT
20f261b24SDaniele Ceraolo Spurio /*
33ea58029SMichal Wajdeczko  * Copyright © 2014-2019 Intel Corporation
40f261b24SDaniele Ceraolo Spurio  */
50f261b24SDaniele Ceraolo Spurio 
66de12da1SJohn Harrison #include <linux/bsearch.h>
76de12da1SJohn Harrison 
8d09aa852SJani Nikula #include "gem/i915_gem_lmem.h"
9202b1f4cSMatt Roper #include "gt/intel_engine_regs.h"
10a8120bc2SDaniele Ceraolo Spurio #include "gt/intel_gt.h"
11e7858254SMatt Roper #include "gt/intel_gt_mcr.h"
120d6419e9SMatt Roper #include "gt/intel_gt_regs.h"
13a0d3fdb6SChris Wilson #include "gt/intel_lrc.h"
14481d458cSJohn Harrison #include "gt/shmem_utils.h"
150f261b24SDaniele Ceraolo Spurio #include "intel_guc_ads.h"
1624492514SAlan Previn #include "intel_guc_capture.h"
1784bdf457SDaniele Ceraolo Spurio #include "intel_guc_fwif.h"
18140f9309SMichal Wajdeczko #include "intel_guc_print.h"
190f261b24SDaniele Ceraolo Spurio #include "intel_uc.h"
200f261b24SDaniele Ceraolo Spurio #include "i915_drv.h"
210f261b24SDaniele Ceraolo Spurio 
220f261b24SDaniele Ceraolo Spurio /*
230f261b24SDaniele Ceraolo Spurio  * The Additional Data Struct (ADS) has pointers for different buffers used by
24c784e524SJohn Harrison  * the GuC. One single gem object contains the ADS struct itself (guc_ads) and
25c784e524SJohn Harrison  * all the extra buffers indirectly linked via the ADS struct's entries.
26c784e524SJohn Harrison  *
27c784e524SJohn Harrison  * Layout of the ADS blob allocated for the GuC:
28c784e524SJohn Harrison  *
29c784e524SJohn Harrison  *      +---------------------------------------+ <== base
30c784e524SJohn Harrison  *      | guc_ads                               |
31c784e524SJohn Harrison  *      +---------------------------------------+
32c784e524SJohn Harrison  *      | guc_policies                          |
33c784e524SJohn Harrison  *      +---------------------------------------+
34c784e524SJohn Harrison  *      | guc_gt_system_info                    |
3577cdd054SUmesh Nerlige Ramappa  *      +---------------------------------------+
3677cdd054SUmesh Nerlige Ramappa  *      | guc_engine_usage                      |
376de12da1SJohn Harrison  *      +---------------------------------------+ <== static
386de12da1SJohn Harrison  *      | guc_mmio_reg[countA] (engine 0.0)     |
396de12da1SJohn Harrison  *      | guc_mmio_reg[countB] (engine 0.1)     |
406de12da1SJohn Harrison  *      | guc_mmio_reg[countC] (engine 1.0)     |
416de12da1SJohn Harrison  *      |   ...                                 |
426de12da1SJohn Harrison  *      +---------------------------------------+ <== dynamic
43c784e524SJohn Harrison  *      | padding                               |
44c784e524SJohn Harrison  *      +---------------------------------------+ <== 4K aligned
45481d458cSJohn Harrison  *      | golden contexts                       |
46481d458cSJohn Harrison  *      +---------------------------------------+
47481d458cSJohn Harrison  *      | padding                               |
48481d458cSJohn Harrison  *      +---------------------------------------+ <== 4K aligned
496cc7a5c7SJohn Harrison  *      | w/a KLVs                              |
506cc7a5c7SJohn Harrison  *      +---------------------------------------+
516cc7a5c7SJohn Harrison  *      | padding                               |
526cc7a5c7SJohn Harrison  *      +---------------------------------------+ <== 4K aligned
5377b6f79dSJohn Harrison  *      | capture lists                         |
5477b6f79dSJohn Harrison  *      +---------------------------------------+
5577b6f79dSJohn Harrison  *      | padding                               |
5677b6f79dSJohn Harrison  *      +---------------------------------------+ <== 4K aligned
57c784e524SJohn Harrison  *      | private data                          |
58c784e524SJohn Harrison  *      +---------------------------------------+
59c784e524SJohn Harrison  *      | padding                               |
60c784e524SJohn Harrison  *      +---------------------------------------+ <== 4K aligned
610f261b24SDaniele Ceraolo Spurio  */
62c784e524SJohn Harrison struct __guc_ads_blob {
63c784e524SJohn Harrison 	struct guc_ads ads;
64c784e524SJohn Harrison 	struct guc_policies policies;
65c784e524SJohn Harrison 	struct guc_gt_system_info system_info;
6677cdd054SUmesh Nerlige Ramappa 	struct guc_engine_usage engine_usage;
676de12da1SJohn Harrison 	/* From here on, location is dynamic! Refer to above diagram. */
685224f790SGustavo A. R. Silva 	struct guc_mmio_reg regset[];
69c784e524SJohn Harrison } __packed;
70c784e524SJohn Harrison 
7191a33f7eSLucas De Marchi #define ads_blob_read(guc_, field_)					\
7291a33f7eSLucas De Marchi 	iosys_map_rd_field(&(guc_)->ads_map, 0, struct __guc_ads_blob, field_)
7391a33f7eSLucas De Marchi 
7491a33f7eSLucas De Marchi #define ads_blob_write(guc_, field_, val_)				\
7591a33f7eSLucas De Marchi 	iosys_map_wr_field(&(guc_)->ads_map, 0, struct __guc_ads_blob,	\
7691a33f7eSLucas De Marchi 			   field_, val_)
7791a33f7eSLucas De Marchi 
78d9a5696eSLucas De Marchi #define info_map_write(map_, field_, val_) \
79d9a5696eSLucas De Marchi 	iosys_map_wr_field(map_, 0, struct guc_gt_system_info, field_, val_)
80d9a5696eSLucas De Marchi 
81d9a5696eSLucas De Marchi #define info_map_read(map_, field_) \
82d9a5696eSLucas De Marchi 	iosys_map_rd_field(map_, 0, struct guc_gt_system_info, field_)
83d9a5696eSLucas De Marchi 
846de12da1SJohn Harrison static u32 guc_ads_regset_size(struct intel_guc *guc)
856de12da1SJohn Harrison {
866de12da1SJohn Harrison 	GEM_BUG_ON(!guc->ads_regset_size);
876de12da1SJohn Harrison 	return guc->ads_regset_size;
886de12da1SJohn Harrison }
896de12da1SJohn Harrison 
90481d458cSJohn Harrison static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc)
91481d458cSJohn Harrison {
92481d458cSJohn Harrison 	return PAGE_ALIGN(guc->ads_golden_ctxt_size);
93481d458cSJohn Harrison }
94481d458cSJohn Harrison 
956cc7a5c7SJohn Harrison static u32 guc_ads_waklv_size(struct intel_guc *guc)
966cc7a5c7SJohn Harrison {
976cc7a5c7SJohn Harrison 	return PAGE_ALIGN(guc->ads_waklv_size);
986cc7a5c7SJohn Harrison }
996cc7a5c7SJohn Harrison 
10077b6f79dSJohn Harrison static u32 guc_ads_capture_size(struct intel_guc *guc)
10177b6f79dSJohn Harrison {
10224492514SAlan Previn 	return PAGE_ALIGN(guc->ads_capture_size);
10377b6f79dSJohn Harrison }
10477b6f79dSJohn Harrison 
105c784e524SJohn Harrison static u32 guc_ads_private_data_size(struct intel_guc *guc)
106c784e524SJohn Harrison {
107c784e524SJohn Harrison 	return PAGE_ALIGN(guc->fw.private_data_size);
108c784e524SJohn Harrison }
109c784e524SJohn Harrison 
1106de12da1SJohn Harrison static u32 guc_ads_regset_offset(struct intel_guc *guc)
1116de12da1SJohn Harrison {
1126de12da1SJohn Harrison 	return offsetof(struct __guc_ads_blob, regset);
1136de12da1SJohn Harrison }
1146de12da1SJohn Harrison 
115481d458cSJohn Harrison static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc)
116c784e524SJohn Harrison {
1176de12da1SJohn Harrison 	u32 offset;
1186de12da1SJohn Harrison 
1196de12da1SJohn Harrison 	offset = guc_ads_regset_offset(guc) +
1206de12da1SJohn Harrison 		 guc_ads_regset_size(guc);
121481d458cSJohn Harrison 
122481d458cSJohn Harrison 	return PAGE_ALIGN(offset);
123481d458cSJohn Harrison }
124481d458cSJohn Harrison 
1256cc7a5c7SJohn Harrison static u32 guc_ads_waklv_offset(struct intel_guc *guc)
126481d458cSJohn Harrison {
127481d458cSJohn Harrison 	u32 offset;
128481d458cSJohn Harrison 
129481d458cSJohn Harrison 	offset = guc_ads_golden_ctxt_offset(guc) +
130481d458cSJohn Harrison 		 guc_ads_golden_ctxt_size(guc);
131481d458cSJohn Harrison 
1326de12da1SJohn Harrison 	return PAGE_ALIGN(offset);
133c784e524SJohn Harrison }
134c784e524SJohn Harrison 
1356cc7a5c7SJohn Harrison static u32 guc_ads_capture_offset(struct intel_guc *guc)
1366cc7a5c7SJohn Harrison {
1376cc7a5c7SJohn Harrison 	u32 offset;
1386cc7a5c7SJohn Harrison 
1396cc7a5c7SJohn Harrison 	offset = guc_ads_waklv_offset(guc) +
1406cc7a5c7SJohn Harrison 		 guc_ads_waklv_size(guc);
1416cc7a5c7SJohn Harrison 
1426cc7a5c7SJohn Harrison 	return PAGE_ALIGN(offset);
1436cc7a5c7SJohn Harrison }
1446cc7a5c7SJohn Harrison 
14577b6f79dSJohn Harrison static u32 guc_ads_private_data_offset(struct intel_guc *guc)
14677b6f79dSJohn Harrison {
14777b6f79dSJohn Harrison 	u32 offset;
14877b6f79dSJohn Harrison 
14977b6f79dSJohn Harrison 	offset = guc_ads_capture_offset(guc) +
15077b6f79dSJohn Harrison 		 guc_ads_capture_size(guc);
15177b6f79dSJohn Harrison 
15277b6f79dSJohn Harrison 	return PAGE_ALIGN(offset);
15377b6f79dSJohn Harrison }
15477b6f79dSJohn Harrison 
155c784e524SJohn Harrison static u32 guc_ads_blob_size(struct intel_guc *guc)
156c784e524SJohn Harrison {
157c784e524SJohn Harrison 	return guc_ads_private_data_offset(guc) +
158c784e524SJohn Harrison 	       guc_ads_private_data_size(guc);
159c784e524SJohn Harrison }
1600f261b24SDaniele Ceraolo Spurio 
1612dce68faSLucas De Marchi static void guc_policies_init(struct intel_guc *guc)
1620f261b24SDaniele Ceraolo Spurio {
16379357852SJohn Harrison 	struct intel_gt *gt = guc_to_gt(guc);
16479357852SJohn Harrison 	struct drm_i915_private *i915 = gt->i915;
1652dce68faSLucas De Marchi 	u32 global_flags = 0;
16679357852SJohn Harrison 
1672dce68faSLucas De Marchi 	ads_blob_write(guc, policies.dpc_promote_time,
1682dce68faSLucas De Marchi 		       GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US);
1692dce68faSLucas De Marchi 	ads_blob_write(guc, policies.max_num_work_items,
1702dce68faSLucas De Marchi 		       GLOBAL_POLICY_MAX_NUM_WI);
17179357852SJohn Harrison 
17279357852SJohn Harrison 	if (i915->params.reset < 2)
1732dce68faSLucas De Marchi 		global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET;
17479357852SJohn Harrison 
1752dce68faSLucas De Marchi 	ads_blob_write(guc, policies.global_flags, global_flags);
1762dce68faSLucas De Marchi 	ads_blob_write(guc, policies.is_valid, 1);
1770f261b24SDaniele Ceraolo Spurio }
1780f261b24SDaniele Ceraolo Spurio 
179731c2ad5SJohn Harrison void intel_guc_ads_print_policy_info(struct intel_guc *guc,
180731c2ad5SJohn Harrison 				     struct drm_printer *dp)
181731c2ad5SJohn Harrison {
1822dce68faSLucas De Marchi 	if (unlikely(iosys_map_is_null(&guc->ads_map)))
183731c2ad5SJohn Harrison 		return;
184731c2ad5SJohn Harrison 
185731c2ad5SJohn Harrison 	drm_printf(dp, "Global scheduling policies:\n");
1862dce68faSLucas De Marchi 	drm_printf(dp, "  DPC promote time   = %u\n",
1872dce68faSLucas De Marchi 		   ads_blob_read(guc, policies.dpc_promote_time));
1882dce68faSLucas De Marchi 	drm_printf(dp, "  Max num work items = %u\n",
1892dce68faSLucas De Marchi 		   ads_blob_read(guc, policies.max_num_work_items));
1902dce68faSLucas De Marchi 	drm_printf(dp, "  Flags              = %u\n",
1912dce68faSLucas De Marchi 		   ads_blob_read(guc, policies.global_flags));
192731c2ad5SJohn Harrison }
193731c2ad5SJohn Harrison 
19479357852SJohn Harrison static int guc_action_policies_update(struct intel_guc *guc, u32 policy_offset)
19579357852SJohn Harrison {
19679357852SJohn Harrison 	u32 action[] = {
19779357852SJohn Harrison 		INTEL_GUC_ACTION_GLOBAL_SCHED_POLICY_CHANGE,
19879357852SJohn Harrison 		policy_offset
19979357852SJohn Harrison 	};
20079357852SJohn Harrison 
201cb6cc815SJohn Harrison 	return intel_guc_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true);
20279357852SJohn Harrison }
20379357852SJohn Harrison 
20479357852SJohn Harrison int intel_guc_global_policies_update(struct intel_guc *guc)
20579357852SJohn Harrison {
20679357852SJohn Harrison 	struct intel_gt *gt = guc_to_gt(guc);
2072dce68faSLucas De Marchi 	u32 scheduler_policies;
20879357852SJohn Harrison 	intel_wakeref_t wakeref;
20979357852SJohn Harrison 	int ret;
21079357852SJohn Harrison 
2112dce68faSLucas De Marchi 	if (iosys_map_is_null(&guc->ads_map))
21279357852SJohn Harrison 		return -EOPNOTSUPP;
21379357852SJohn Harrison 
2142dce68faSLucas De Marchi 	scheduler_policies = ads_blob_read(guc, ads.scheduler_policies);
2152dce68faSLucas De Marchi 	GEM_BUG_ON(!scheduler_policies);
21679357852SJohn Harrison 
2172dce68faSLucas De Marchi 	guc_policies_init(guc);
21879357852SJohn Harrison 
21979357852SJohn Harrison 	if (!intel_guc_is_ready(guc))
22079357852SJohn Harrison 		return 0;
22179357852SJohn Harrison 
22279357852SJohn Harrison 	with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref)
2232dce68faSLucas De Marchi 		ret = guc_action_policies_update(guc, scheduler_policies);
22479357852SJohn Harrison 
22579357852SJohn Harrison 	return ret;
22679357852SJohn Harrison }
22779357852SJohn Harrison 
228c784e524SJohn Harrison static void guc_mapping_table_init(struct intel_gt *gt,
229c723b8eeSLucas De Marchi 				   struct iosys_map *info_map)
230c784e524SJohn Harrison {
231c784e524SJohn Harrison 	unsigned int i, j;
232c784e524SJohn Harrison 	struct intel_engine_cs *engine;
233c784e524SJohn Harrison 	enum intel_engine_id id;
234c784e524SJohn Harrison 
235c784e524SJohn Harrison 	/* Table must be set to invalid values for entries not used */
236c784e524SJohn Harrison 	for (i = 0; i < GUC_MAX_ENGINE_CLASSES; ++i)
237c784e524SJohn Harrison 		for (j = 0; j < GUC_MAX_INSTANCES_PER_CLASS; ++j)
238c723b8eeSLucas De Marchi 			info_map_write(info_map, mapping_table[i][j],
239c723b8eeSLucas De Marchi 				       GUC_MAX_INSTANCES_PER_CLASS);
240c784e524SJohn Harrison 
241c784e524SJohn Harrison 	for_each_engine(engine, gt, id) {
24284bdf457SDaniele Ceraolo Spurio 		u8 guc_class = engine_class_to_guc_class(engine->class);
243c784e524SJohn Harrison 
244c723b8eeSLucas De Marchi 		info_map_write(info_map, mapping_table[guc_class][ilog2(engine->logical_mask)],
245c723b8eeSLucas De Marchi 			       engine->instance);
246c784e524SJohn Harrison 	}
247c784e524SJohn Harrison }
248c784e524SJohn Harrison 
2490f261b24SDaniele Ceraolo Spurio /*
2506de12da1SJohn Harrison  * The save/restore register list must be pre-calculated to a temporary
251bf890040SLucas De Marchi  * buffer before it can be copied inside the ADS.
2526de12da1SJohn Harrison  */
2536de12da1SJohn Harrison struct temp_regset {
254bf890040SLucas De Marchi 	/*
255bf890040SLucas De Marchi 	 * ptr to the section of the storage for the engine currently being
256bf890040SLucas De Marchi 	 * worked on
257bf890040SLucas De Marchi 	 */
2586de12da1SJohn Harrison 	struct guc_mmio_reg *registers;
259bf890040SLucas De Marchi 	/* ptr to the base of the allocated storage for all engines */
260bf890040SLucas De Marchi 	struct guc_mmio_reg *storage;
261bf890040SLucas De Marchi 	u32 storage_used;
262bf890040SLucas De Marchi 	u32 storage_max;
2636de12da1SJohn Harrison };
2646de12da1SJohn Harrison 
2656de12da1SJohn Harrison static int guc_mmio_reg_cmp(const void *a, const void *b)
2666de12da1SJohn Harrison {
2676de12da1SJohn Harrison 	const struct guc_mmio_reg *ra = a;
2686de12da1SJohn Harrison 	const struct guc_mmio_reg *rb = b;
2696de12da1SJohn Harrison 
2706de12da1SJohn Harrison 	return (int)ra->offset - (int)rb->offset;
2716de12da1SJohn Harrison }
2726de12da1SJohn Harrison 
273bf890040SLucas De Marchi static struct guc_mmio_reg * __must_check
274bf890040SLucas De Marchi __mmio_reg_add(struct temp_regset *regset, struct guc_mmio_reg *reg)
275bf890040SLucas De Marchi {
276bf890040SLucas De Marchi 	u32 pos = regset->storage_used;
277bf890040SLucas De Marchi 	struct guc_mmio_reg *slot;
278bf890040SLucas De Marchi 
279bf890040SLucas De Marchi 	if (pos >= regset->storage_max) {
280bf890040SLucas De Marchi 		size_t size = ALIGN((pos + 1) * sizeof(*slot), PAGE_SIZE);
281bf890040SLucas De Marchi 		struct guc_mmio_reg *r = krealloc(regset->storage,
282bf890040SLucas De Marchi 						  size, GFP_KERNEL);
283bf890040SLucas De Marchi 		if (!r) {
284bf890040SLucas De Marchi 			WARN_ONCE(1, "Incomplete regset list: can't add register (%d)\n",
285bf890040SLucas De Marchi 				  -ENOMEM);
286bf890040SLucas De Marchi 			return ERR_PTR(-ENOMEM);
287bf890040SLucas De Marchi 		}
288bf890040SLucas De Marchi 
289bf890040SLucas De Marchi 		regset->registers = r + (regset->registers - regset->storage);
290bf890040SLucas De Marchi 		regset->storage = r;
291bf890040SLucas De Marchi 		regset->storage_max = size / sizeof(*slot);
292bf890040SLucas De Marchi 	}
293bf890040SLucas De Marchi 
294bf890040SLucas De Marchi 	slot = &regset->storage[pos];
295bf890040SLucas De Marchi 	regset->storage_used++;
296bf890040SLucas De Marchi 	*slot = *reg;
297bf890040SLucas De Marchi 
298bf890040SLucas De Marchi 	return slot;
299bf890040SLucas De Marchi }
300bf890040SLucas De Marchi 
30110343606SDaniele Ceraolo Spurio static long __must_check guc_mmio_reg_add(struct intel_gt *gt,
30210343606SDaniele Ceraolo Spurio 					  struct temp_regset *regset,
303cf35f6afSMatt Roper 					  u32 offset, u32 flags)
3046de12da1SJohn Harrison {
305bf890040SLucas De Marchi 	u32 count = regset->storage_used - (regset->registers - regset->storage);
30610343606SDaniele Ceraolo Spurio 	struct guc_mmio_reg entry = {
3076de12da1SJohn Harrison 		.offset = offset,
3086de12da1SJohn Harrison 		.flags = flags,
3096de12da1SJohn Harrison 	};
3106de12da1SJohn Harrison 	struct guc_mmio_reg *slot;
3116de12da1SJohn Harrison 
3126de12da1SJohn Harrison 	/*
3136de12da1SJohn Harrison 	 * The mmio list is built using separate lists within the driver.
3146de12da1SJohn Harrison 	 * It's possible that at some point we may attempt to add the same
3156de12da1SJohn Harrison 	 * register more than once. Do not consider this an error; silently
3166de12da1SJohn Harrison 	 * move on if the register is already in the list.
3176de12da1SJohn Harrison 	 */
31810343606SDaniele Ceraolo Spurio 	if (bsearch(&entry, regset->registers, count,
31910343606SDaniele Ceraolo Spurio 		    sizeof(entry), guc_mmio_reg_cmp))
320f4044ca1SLucas De Marchi 		return 0;
3216de12da1SJohn Harrison 
32210343606SDaniele Ceraolo Spurio 	slot = __mmio_reg_add(regset, &entry);
323bf890040SLucas De Marchi 	if (IS_ERR(slot))
324bf890040SLucas De Marchi 		return PTR_ERR(slot);
3256de12da1SJohn Harrison 
3266de12da1SJohn Harrison 	while (slot-- > regset->registers) {
3276de12da1SJohn Harrison 		GEM_BUG_ON(slot[0].offset == slot[1].offset);
3286de12da1SJohn Harrison 		if (slot[1].offset > slot[0].offset)
3296de12da1SJohn Harrison 			break;
3306de12da1SJohn Harrison 
3316de12da1SJohn Harrison 		swap(slot[1], slot[0]);
3326de12da1SJohn Harrison 	}
333f4044ca1SLucas De Marchi 
334f4044ca1SLucas De Marchi 	return 0;
3356de12da1SJohn Harrison }
3366de12da1SJohn Harrison 
33710343606SDaniele Ceraolo Spurio #define GUC_MMIO_REG_ADD(gt, regset, reg, masked) \
33810343606SDaniele Ceraolo Spurio 	guc_mmio_reg_add(gt, \
33910343606SDaniele Ceraolo Spurio 			 regset, \
340cf35f6afSMatt Roper 			 i915_mmio_reg_offset(reg), \
341cf35f6afSMatt Roper 			 (masked) ? GUC_REGSET_MASKED : 0)
342cf35f6afSMatt Roper 
343cf35f6afSMatt Roper #define GUC_REGSET_STEERING(group, instance) ( \
344cf35f6afSMatt Roper 	FIELD_PREP(GUC_REGSET_STEERING_GROUP, (group)) | \
345cf35f6afSMatt Roper 	FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, (instance)) | \
346cf35f6afSMatt Roper 	GUC_REGSET_NEEDS_STEERING \
347cf35f6afSMatt Roper )
348cf35f6afSMatt Roper 
349cf35f6afSMatt Roper static long __must_check guc_mcr_reg_add(struct intel_gt *gt,
350cf35f6afSMatt Roper 					 struct temp_regset *regset,
35158bc2453SMatt Roper 					 i915_mcr_reg_t reg, u32 flags)
352cf35f6afSMatt Roper {
353cf35f6afSMatt Roper 	u8 group, inst;
354cf35f6afSMatt Roper 
355cf35f6afSMatt Roper 	/*
356cf35f6afSMatt Roper 	 * The GuC doesn't have a default steering, so we need to explicitly
357cf35f6afSMatt Roper 	 * steer all registers that need steering. However, we do not keep track
358cf35f6afSMatt Roper 	 * of all the steering ranges, only of those that have a chance of using
359cf35f6afSMatt Roper 	 * a non-default steering from the i915 pov. Instead of adding such
360cf35f6afSMatt Roper 	 * tracking, it is easier to just program the default steering for all
361cf35f6afSMatt Roper 	 * regs that don't need a non-default one.
362cf35f6afSMatt Roper 	 */
363cf35f6afSMatt Roper 	intel_gt_mcr_get_nonterminated_steering(gt, reg, &group, &inst);
364cf35f6afSMatt Roper 	flags |= GUC_REGSET_STEERING(group, inst);
365cf35f6afSMatt Roper 
366cf35f6afSMatt Roper 	return guc_mmio_reg_add(gt, regset, i915_mmio_reg_offset(reg), flags);
367cf35f6afSMatt Roper }
368cf35f6afSMatt Roper 
369cf35f6afSMatt Roper #define GUC_MCR_REG_ADD(gt, regset, reg, masked) \
370cf35f6afSMatt Roper 	guc_mcr_reg_add(gt, \
371cf35f6afSMatt Roper 			 regset, \
37210343606SDaniele Ceraolo Spurio 			 (reg), \
3736de12da1SJohn Harrison 			 (masked) ? GUC_REGSET_MASKED : 0)
3746de12da1SJohn Harrison 
375f4044ca1SLucas De Marchi static int guc_mmio_regset_init(struct temp_regset *regset,
3766de12da1SJohn Harrison 				struct intel_engine_cs *engine)
3776de12da1SJohn Harrison {
37810343606SDaniele Ceraolo Spurio 	struct intel_gt *gt = engine->gt;
3796de12da1SJohn Harrison 	const u32 base = engine->mmio_base;
3806de12da1SJohn Harrison 	struct i915_wa_list *wal = &engine->wa_list;
3816de12da1SJohn Harrison 	struct i915_wa *wa;
3826de12da1SJohn Harrison 	unsigned int i;
383f4044ca1SLucas De Marchi 	int ret = 0;
3846de12da1SJohn Harrison 
385bf890040SLucas De Marchi 	/*
386bf890040SLucas De Marchi 	 * Each engine's registers point to a new start relative to
387bf890040SLucas De Marchi 	 * storage
388bf890040SLucas De Marchi 	 */
389bf890040SLucas De Marchi 	regset->registers = regset->storage + regset->storage_used;
3906de12da1SJohn Harrison 
39110343606SDaniele Ceraolo Spurio 	ret |= GUC_MMIO_REG_ADD(gt, regset, RING_MODE_GEN7(base), true);
39210343606SDaniele Ceraolo Spurio 	ret |= GUC_MMIO_REG_ADD(gt, regset, RING_HWS_PGA(base), false);
39310343606SDaniele Ceraolo Spurio 	ret |= GUC_MMIO_REG_ADD(gt, regset, RING_IMR(base), false);
3946de12da1SJohn Harrison 
395f9576e36SMatt Roper 	if ((engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) &&
39687cb6d80SMatt Roper 	    CCS_MASK(engine->gt))
39710343606SDaniele Ceraolo Spurio 		ret |= GUC_MMIO_REG_ADD(gt, regset, GEN12_RCU_MODE, true);
39887cb6d80SMatt Roper 
399835e4d9bSShuicheng Lin 	/*
400835e4d9bSShuicheng Lin 	 * some of the WA registers are MCR registers. As it is safe to
401835e4d9bSShuicheng Lin 	 * use MCR form for non-MCR registers, for code simplicity, all
402835e4d9bSShuicheng Lin 	 * WA registers are added with MCR form.
403835e4d9bSShuicheng Lin 	 */
4046de12da1SJohn Harrison 	for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
405835e4d9bSShuicheng Lin 		ret |= GUC_MCR_REG_ADD(gt, regset, wa->mcr_reg, wa->masked_reg);
4066de12da1SJohn Harrison 
4076de12da1SJohn Harrison 	/* Be extra paranoid and include all whitelist registers. */
4086de12da1SJohn Harrison 	for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++)
40910343606SDaniele Ceraolo Spurio 		ret |= GUC_MMIO_REG_ADD(gt, regset,
4106de12da1SJohn Harrison 					RING_FORCE_TO_NONPRIV(base, i),
4116de12da1SJohn Harrison 					false);
4126de12da1SJohn Harrison 
4136de12da1SJohn Harrison 	/* add in local MOCS registers */
41477fa9efcSMatt Roper 	for (i = 0; i < LNCFCMOCS_REG_COUNT; i++)
41548ba4a6dSLucas De Marchi 		if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55))
416cf35f6afSMatt Roper 			ret |= GUC_MCR_REG_ADD(gt, regset, XEHP_LNCFCMOCS(i), false);
41777fa9efcSMatt Roper 		else
41810343606SDaniele Ceraolo Spurio 			ret |= GUC_MMIO_REG_ADD(gt, regset, GEN9_LNCFCMOCS(i), false);
419f4044ca1SLucas De Marchi 
420fa569804SUmesh Nerlige Ramappa 	if (GRAPHICS_VER(engine->i915) >= 12) {
421835e4d9bSShuicheng Lin 		ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL0)), false);
422835e4d9bSShuicheng Lin 		ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL1)), false);
423835e4d9bSShuicheng Lin 		ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL2)), false);
424835e4d9bSShuicheng Lin 		ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL3)), false);
425835e4d9bSShuicheng Lin 		ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL4)), false);
426835e4d9bSShuicheng Lin 		ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL5)), false);
427835e4d9bSShuicheng Lin 		ret |= GUC_MCR_REG_ADD(gt, regset, MCR_REG(i915_mmio_reg_offset(EU_PERF_CNTL6)), false);
428fa569804SUmesh Nerlige Ramappa 	}
429fa569804SUmesh Nerlige Ramappa 
430f4044ca1SLucas De Marchi 	return ret ? -1 : 0;
4316de12da1SJohn Harrison }
4326de12da1SJohn Harrison 
433bf890040SLucas De Marchi static long guc_mmio_reg_state_create(struct intel_guc *guc)
4346de12da1SJohn Harrison {
4356de12da1SJohn Harrison 	struct intel_gt *gt = guc_to_gt(guc);
4366de12da1SJohn Harrison 	struct intel_engine_cs *engine;
4376de12da1SJohn Harrison 	enum intel_engine_id id;
438bf890040SLucas De Marchi 	struct temp_regset temp_set = {};
439bf890040SLucas De Marchi 	long total = 0;
440bf890040SLucas De Marchi 	long ret;
4416de12da1SJohn Harrison 
4426de12da1SJohn Harrison 	for_each_engine(engine, gt, id) {
443bf890040SLucas De Marchi 		u32 used = temp_set.storage_used;
444bf890040SLucas De Marchi 
445bf890040SLucas De Marchi 		ret = guc_mmio_regset_init(&temp_set, engine);
446bf890040SLucas De Marchi 		if (ret < 0)
447bf890040SLucas De Marchi 			goto fail_regset_init;
448bf890040SLucas De Marchi 
449bf890040SLucas De Marchi 		guc->ads_regset_count[id] = temp_set.storage_used - used;
450bf890040SLucas De Marchi 		total += guc->ads_regset_count[id];
4516de12da1SJohn Harrison 	}
4526de12da1SJohn Harrison 
453bf890040SLucas De Marchi 	guc->ads_regset = temp_set.storage;
454bf890040SLucas De Marchi 
455140f9309SMichal Wajdeczko 	guc_dbg(guc, "Used %zu KB for temporary ADS regset\n",
456bf890040SLucas De Marchi 		(temp_set.storage_max * sizeof(struct guc_mmio_reg)) >> 10);
4576de12da1SJohn Harrison 
4586de12da1SJohn Harrison 	return total * sizeof(struct guc_mmio_reg);
459bf890040SLucas De Marchi 
460bf890040SLucas De Marchi fail_regset_init:
461bf890040SLucas De Marchi 	kfree(temp_set.storage);
462bf890040SLucas De Marchi 	return ret;
4636de12da1SJohn Harrison }
4646de12da1SJohn Harrison 
4655fc83950SLucas De Marchi static void guc_mmio_reg_state_init(struct intel_guc *guc)
4666de12da1SJohn Harrison {
4676de12da1SJohn Harrison 	struct intel_gt *gt = guc_to_gt(guc);
4686de12da1SJohn Harrison 	struct intel_engine_cs *engine;
4696de12da1SJohn Harrison 	enum intel_engine_id id;
4706de12da1SJohn Harrison 	u32 addr_ggtt, offset;
4716de12da1SJohn Harrison 
4726de12da1SJohn Harrison 	offset = guc_ads_regset_offset(guc);
4736de12da1SJohn Harrison 	addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset;
474bf890040SLucas De Marchi 
4755fc83950SLucas De Marchi 	iosys_map_memcpy_to(&guc->ads_map, offset, guc->ads_regset,
4765fc83950SLucas De Marchi 			    guc->ads_regset_size);
4776de12da1SJohn Harrison 
4786de12da1SJohn Harrison 	for_each_engine(engine, gt, id) {
479bf890040SLucas De Marchi 		u32 count = guc->ads_regset_count[id];
480bf890040SLucas De Marchi 		u8 guc_class;
481bf890040SLucas De Marchi 
4826de12da1SJohn Harrison 		/* Class index is checked in class converter */
4836de12da1SJohn Harrison 		GEM_BUG_ON(engine->instance >= GUC_MAX_INSTANCES_PER_CLASS);
4846de12da1SJohn Harrison 
4856de12da1SJohn Harrison 		guc_class = engine_class_to_guc_class(engine->class);
4866de12da1SJohn Harrison 
487bf890040SLucas De Marchi 		if (!count) {
4885fc83950SLucas De Marchi 			ads_blob_write(guc,
4895fc83950SLucas De Marchi 				       ads.reg_state_list[guc_class][engine->instance].address,
4905fc83950SLucas De Marchi 				       0);
4915fc83950SLucas De Marchi 			ads_blob_write(guc,
4925fc83950SLucas De Marchi 				       ads.reg_state_list[guc_class][engine->instance].count,
4935fc83950SLucas De Marchi 				       0);
4946de12da1SJohn Harrison 			continue;
4956de12da1SJohn Harrison 		}
4966de12da1SJohn Harrison 
4975fc83950SLucas De Marchi 		ads_blob_write(guc,
4985fc83950SLucas De Marchi 			       ads.reg_state_list[guc_class][engine->instance].address,
4995fc83950SLucas De Marchi 			       addr_ggtt);
5005fc83950SLucas De Marchi 		ads_blob_write(guc,
5015fc83950SLucas De Marchi 			       ads.reg_state_list[guc_class][engine->instance].count,
5025fc83950SLucas De Marchi 			       count);
5036de12da1SJohn Harrison 
504bf890040SLucas De Marchi 		addr_ggtt += count * sizeof(struct guc_mmio_reg);
5056de12da1SJohn Harrison 	}
5066de12da1SJohn Harrison }
5076de12da1SJohn Harrison 
508481d458cSJohn Harrison static void fill_engine_enable_masks(struct intel_gt *gt,
509d9a5696eSLucas De Marchi 				     struct iosys_map *info_map)
510481d458cSJohn Harrison {
51118ac067bSStuart Summers 	info_map_write(info_map, engine_enabled_masks[GUC_RENDER_CLASS], RCS_MASK(gt));
512ea4ca894SDaniele Ceraolo Spurio 	info_map_write(info_map, engine_enabled_masks[GUC_COMPUTE_CLASS], CCS_MASK(gt));
513e41388d5SMatt Roper 	info_map_write(info_map, engine_enabled_masks[GUC_BLITTER_CLASS], BCS_MASK(gt));
514d9a5696eSLucas De Marchi 	info_map_write(info_map, engine_enabled_masks[GUC_VIDEO_CLASS], VDBOX_MASK(gt));
515d9a5696eSLucas De Marchi 	info_map_write(info_map, engine_enabled_masks[GUC_VIDEOENHANCE_CLASS], VEBOX_MASK(gt));
516c9c12ba7SDaniele Ceraolo Spurio 
517c9c12ba7SDaniele Ceraolo Spurio 	/* The GSC engine is an instance (6) of OTHER_CLASS */
518c9c12ba7SDaniele Ceraolo Spurio 	if (gt->engine[GSC0])
519c9c12ba7SDaniele Ceraolo Spurio 		info_map_write(info_map, engine_enabled_masks[GUC_GSC_OTHER_CLASS],
520c9c12ba7SDaniele Ceraolo Spurio 			       BIT(gt->engine[GSC0]->instance));
521481d458cSJohn Harrison }
5220f261b24SDaniele Ceraolo Spurio 
523d135865cSMatthew Brost #define LR_HW_CONTEXT_SIZE (80 * sizeof(u32))
52452d4cfdcSMatthew Brost #define XEHP_LR_HW_CONTEXT_SIZE (96 * sizeof(u32))
52548ba4a6dSLucas De Marchi #define LR_HW_CONTEXT_SZ(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55) ? \
52652d4cfdcSMatthew Brost 				    XEHP_LR_HW_CONTEXT_SIZE : \
52752d4cfdcSMatthew Brost 				    LR_HW_CONTEXT_SIZE)
52852d4cfdcSMatthew Brost #define LRC_SKIP_SIZE(i915) (LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SZ(i915))
529d9a5696eSLucas De Marchi static int guc_prep_golden_context(struct intel_guc *guc)
5300f261b24SDaniele Ceraolo Spurio {
531242613afSDaniele Ceraolo Spurio 	struct intel_gt *gt = guc_to_gt(guc);
532481d458cSJohn Harrison 	u32 addr_ggtt, offset;
533481d458cSJohn Harrison 	u32 total_size = 0, alloc_size, real_size;
53484bdf457SDaniele Ceraolo Spurio 	u8 engine_class, guc_class;
535d9a5696eSLucas De Marchi 	struct guc_gt_system_info local_info;
536d9a5696eSLucas De Marchi 	struct iosys_map info_map;
5370f261b24SDaniele Ceraolo Spurio 
5380f261b24SDaniele Ceraolo Spurio 	/*
539481d458cSJohn Harrison 	 * Reserve the memory for the golden contexts and point GuC at it but
540481d458cSJohn Harrison 	 * leave it empty for now. The context data will be filled in later
541481d458cSJohn Harrison 	 * once there is something available to put there.
542481d458cSJohn Harrison 	 *
543481d458cSJohn Harrison 	 * Note that the HWSP and ring context are not included.
544481d458cSJohn Harrison 	 *
545481d458cSJohn Harrison 	 * Note also that the storage must be pinned in the GGTT, so that the
546481d458cSJohn Harrison 	 * address won't change after GuC has been told where to find it. The
547481d458cSJohn Harrison 	 * GuC will also validate that the LRC base + size fall within the
548481d458cSJohn Harrison 	 * allowed GGTT range.
5490f261b24SDaniele Ceraolo Spurio 	 */
550d9a5696eSLucas De Marchi 	if (!iosys_map_is_null(&guc->ads_map)) {
551481d458cSJohn Harrison 		offset = guc_ads_golden_ctxt_offset(guc);
552481d458cSJohn Harrison 		addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset;
553d9a5696eSLucas De Marchi 		info_map = IOSYS_MAP_INIT_OFFSET(&guc->ads_map,
554d9a5696eSLucas De Marchi 						 offsetof(struct __guc_ads_blob, system_info));
555481d458cSJohn Harrison 	} else {
556481d458cSJohn Harrison 		memset(&local_info, 0, sizeof(local_info));
557d9a5696eSLucas De Marchi 		iosys_map_set_vaddr(&info_map, &local_info);
558d9a5696eSLucas De Marchi 		fill_engine_enable_masks(gt, &info_map);
559481d458cSJohn Harrison 	}
560481d458cSJohn Harrison 
5610f261b24SDaniele Ceraolo Spurio 	for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) {
56284bdf457SDaniele Ceraolo Spurio 		guc_class = engine_class_to_guc_class(engine_class);
56384bdf457SDaniele Ceraolo Spurio 
564d9a5696eSLucas De Marchi 		if (!info_map_read(&info_map, engine_enabled_masks[guc_class]))
565481d458cSJohn Harrison 			continue;
566481d458cSJohn Harrison 
567481d458cSJohn Harrison 		real_size = intel_engine_context_size(gt, engine_class);
568481d458cSJohn Harrison 		alloc_size = PAGE_ALIGN(real_size);
569481d458cSJohn Harrison 		total_size += alloc_size;
570481d458cSJohn Harrison 
571d9a5696eSLucas De Marchi 		if (iosys_map_is_null(&guc->ads_map))
572481d458cSJohn Harrison 			continue;
573481d458cSJohn Harrison 
574d135865cSMatthew Brost 		/*
575d135865cSMatthew Brost 		 * This interface is slightly confusing. We need to pass the
576d135865cSMatthew Brost 		 * base address of the full golden context and the size of just
577d135865cSMatthew Brost 		 * the engine state, which is the section of the context image
578d135865cSMatthew Brost 		 * that starts after the execlists context. This is required to
579d135865cSMatthew Brost 		 * allow the GuC to restore just the engine state when a
580d135865cSMatthew Brost 		 * watchdog reset occurs.
581d135865cSMatthew Brost 		 * We calculate the engine state size by removing the size of
582d135865cSMatthew Brost 		 * what comes before it in the context image (which is identical
583d135865cSMatthew Brost 		 * on all engines).
584d135865cSMatthew Brost 		 */
585d9a5696eSLucas De Marchi 		ads_blob_write(guc, ads.eng_state_size[guc_class],
58652d4cfdcSMatthew Brost 			       real_size - LRC_SKIP_SIZE(gt->i915));
587d9a5696eSLucas De Marchi 		ads_blob_write(guc, ads.golden_context_lrca[guc_class],
588d9a5696eSLucas De Marchi 			       addr_ggtt);
589d9a5696eSLucas De Marchi 
590481d458cSJohn Harrison 		addr_ggtt += alloc_size;
5910f261b24SDaniele Ceraolo Spurio 	}
5920f261b24SDaniele Ceraolo Spurio 
59358fb284cSLucas De Marchi 	/* Make sure current size matches what we calculated previously */
59458fb284cSLucas De Marchi 	if (guc->ads_golden_ctxt_size)
595481d458cSJohn Harrison 		GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size);
59658fb284cSLucas De Marchi 
597481d458cSJohn Harrison 	return total_size;
598481d458cSJohn Harrison }
599481d458cSJohn Harrison 
600481d458cSJohn Harrison static struct intel_engine_cs *find_engine_state(struct intel_gt *gt, u8 engine_class)
601481d458cSJohn Harrison {
602481d458cSJohn Harrison 	struct intel_engine_cs *engine;
603481d458cSJohn Harrison 	enum intel_engine_id id;
604481d458cSJohn Harrison 
605481d458cSJohn Harrison 	for_each_engine(engine, gt, id) {
606481d458cSJohn Harrison 		if (engine->class != engine_class)
607481d458cSJohn Harrison 			continue;
608481d458cSJohn Harrison 
609481d458cSJohn Harrison 		if (!engine->default_state)
610481d458cSJohn Harrison 			continue;
611481d458cSJohn Harrison 
612481d458cSJohn Harrison 		return engine;
613481d458cSJohn Harrison 	}
614481d458cSJohn Harrison 
615481d458cSJohn Harrison 	return NULL;
616481d458cSJohn Harrison }
617481d458cSJohn Harrison 
618481d458cSJohn Harrison static void guc_init_golden_context(struct intel_guc *guc)
619481d458cSJohn Harrison {
620481d458cSJohn Harrison 	struct intel_engine_cs *engine;
621481d458cSJohn Harrison 	struct intel_gt *gt = guc_to_gt(guc);
622219aada2SLucas De Marchi 	unsigned long offset;
623219aada2SLucas De Marchi 	u32 addr_ggtt, total_size = 0, alloc_size, real_size;
624481d458cSJohn Harrison 	u8 engine_class, guc_class;
625481d458cSJohn Harrison 
626481d458cSJohn Harrison 	if (!intel_uc_uses_guc_submission(&gt->uc))
627481d458cSJohn Harrison 		return;
628481d458cSJohn Harrison 
629219aada2SLucas De Marchi 	GEM_BUG_ON(iosys_map_is_null(&guc->ads_map));
630481d458cSJohn Harrison 
631481d458cSJohn Harrison 	/*
632481d458cSJohn Harrison 	 * Go back and fill in the golden context data now that it is
633481d458cSJohn Harrison 	 * available.
634481d458cSJohn Harrison 	 */
635481d458cSJohn Harrison 	offset = guc_ads_golden_ctxt_offset(guc);
636481d458cSJohn Harrison 	addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset;
637481d458cSJohn Harrison 
638481d458cSJohn Harrison 	for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) {
639481d458cSJohn Harrison 		guc_class = engine_class_to_guc_class(engine_class);
640219aada2SLucas De Marchi 		if (!ads_blob_read(guc, system_info.engine_enabled_masks[guc_class]))
641481d458cSJohn Harrison 			continue;
642481d458cSJohn Harrison 
643481d458cSJohn Harrison 		real_size = intel_engine_context_size(gt, engine_class);
644481d458cSJohn Harrison 		alloc_size = PAGE_ALIGN(real_size);
645481d458cSJohn Harrison 		total_size += alloc_size;
646481d458cSJohn Harrison 
647481d458cSJohn Harrison 		engine = find_engine_state(gt, engine_class);
648481d458cSJohn Harrison 		if (!engine) {
649140f9309SMichal Wajdeczko 			guc_err(guc, "No engine state recorded for class %d!\n",
650481d458cSJohn Harrison 				engine_class);
651219aada2SLucas De Marchi 			ads_blob_write(guc, ads.eng_state_size[guc_class], 0);
652219aada2SLucas De Marchi 			ads_blob_write(guc, ads.golden_context_lrca[guc_class], 0);
653481d458cSJohn Harrison 			continue;
654481d458cSJohn Harrison 		}
655481d458cSJohn Harrison 
656219aada2SLucas De Marchi 		GEM_BUG_ON(ads_blob_read(guc, ads.eng_state_size[guc_class]) !=
65752d4cfdcSMatthew Brost 			   real_size - LRC_SKIP_SIZE(gt->i915));
658219aada2SLucas De Marchi 		GEM_BUG_ON(ads_blob_read(guc, ads.golden_context_lrca[guc_class]) != addr_ggtt);
659219aada2SLucas De Marchi 
660481d458cSJohn Harrison 		addr_ggtt += alloc_size;
661481d458cSJohn Harrison 
662219aada2SLucas De Marchi 		shmem_read_to_iosys_map(engine->default_state, 0, &guc->ads_map,
663219aada2SLucas De Marchi 					offset, real_size);
664219aada2SLucas De Marchi 		offset += alloc_size;
665481d458cSJohn Harrison 	}
666481d458cSJohn Harrison 
667481d458cSJohn Harrison 	GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size);
668481d458cSJohn Harrison }
669481d458cSJohn Harrison 
6708ba3ba99SJohn Harrison static u32 guc_get_capture_engine_mask(struct iosys_map *info_map, u32 capture_class)
6718ba3ba99SJohn Harrison {
6728ba3ba99SJohn Harrison 	u32 mask;
6738ba3ba99SJohn Harrison 
6748ba3ba99SJohn Harrison 	switch (capture_class) {
6758ba3ba99SJohn Harrison 	case GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE:
6768ba3ba99SJohn Harrison 		mask = info_map_read(info_map, engine_enabled_masks[GUC_RENDER_CLASS]);
6778ba3ba99SJohn Harrison 		mask |= info_map_read(info_map, engine_enabled_masks[GUC_COMPUTE_CLASS]);
6788ba3ba99SJohn Harrison 		break;
6798ba3ba99SJohn Harrison 
6808ba3ba99SJohn Harrison 	case GUC_CAPTURE_LIST_CLASS_VIDEO:
6818ba3ba99SJohn Harrison 		mask = info_map_read(info_map, engine_enabled_masks[GUC_VIDEO_CLASS]);
6828ba3ba99SJohn Harrison 		break;
6838ba3ba99SJohn Harrison 
6848ba3ba99SJohn Harrison 	case GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE:
6858ba3ba99SJohn Harrison 		mask = info_map_read(info_map, engine_enabled_masks[GUC_VIDEOENHANCE_CLASS]);
6868ba3ba99SJohn Harrison 		break;
6878ba3ba99SJohn Harrison 
6888ba3ba99SJohn Harrison 	case GUC_CAPTURE_LIST_CLASS_BLITTER:
6898ba3ba99SJohn Harrison 		mask = info_map_read(info_map, engine_enabled_masks[GUC_BLITTER_CLASS]);
6908ba3ba99SJohn Harrison 		break;
6918ba3ba99SJohn Harrison 
6928ba3ba99SJohn Harrison 	case GUC_CAPTURE_LIST_CLASS_GSC_OTHER:
6938ba3ba99SJohn Harrison 		mask = info_map_read(info_map, engine_enabled_masks[GUC_GSC_OTHER_CLASS]);
6948ba3ba99SJohn Harrison 		break;
6958ba3ba99SJohn Harrison 
6968ba3ba99SJohn Harrison 	default:
6978ba3ba99SJohn Harrison 		mask = 0;
6988ba3ba99SJohn Harrison 	}
6998ba3ba99SJohn Harrison 
7008ba3ba99SJohn Harrison 	return mask;
7018ba3ba99SJohn Harrison }
7028ba3ba99SJohn Harrison 
70324492514SAlan Previn static int
70424492514SAlan Previn guc_capture_prep_lists(struct intel_guc *guc)
70577b6f79dSJohn Harrison {
70624492514SAlan Previn 	struct intel_gt *gt = guc_to_gt(guc);
70724492514SAlan Previn 	u32 ads_ggtt, capture_offset, null_ggtt, total_size = 0;
70824492514SAlan Previn 	struct guc_gt_system_info local_info;
70924492514SAlan Previn 	struct iosys_map info_map;
71024492514SAlan Previn 	bool ads_is_mapped;
71124492514SAlan Previn 	size_t size = 0;
71224492514SAlan Previn 	void *ptr;
71377b6f79dSJohn Harrison 	int i, j;
71477b6f79dSJohn Harrison 
71524492514SAlan Previn 	ads_is_mapped = !iosys_map_is_null(&guc->ads_map);
71624492514SAlan Previn 	if (ads_is_mapped) {
71724492514SAlan Previn 		capture_offset = guc_ads_capture_offset(guc);
71824492514SAlan Previn 		ads_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma);
71924492514SAlan Previn 		info_map = IOSYS_MAP_INIT_OFFSET(&guc->ads_map,
72024492514SAlan Previn 						 offsetof(struct __guc_ads_blob, system_info));
72124492514SAlan Previn 	} else {
72224492514SAlan Previn 		memset(&local_info, 0, sizeof(local_info));
72324492514SAlan Previn 		iosys_map_set_vaddr(&info_map, &local_info);
72424492514SAlan Previn 		fill_engine_enable_masks(gt, &info_map);
72524492514SAlan Previn 	}
72677b6f79dSJohn Harrison 
72724492514SAlan Previn 	/* first, set aside the first page for a capture_list with zero descriptors */
72824492514SAlan Previn 	total_size = PAGE_SIZE;
72924492514SAlan Previn 	if (ads_is_mapped) {
73024492514SAlan Previn 		if (!intel_guc_capture_getnullheader(guc, &ptr, &size))
73124492514SAlan Previn 			iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size);
73224492514SAlan Previn 		null_ggtt = ads_ggtt + capture_offset;
73324492514SAlan Previn 		capture_offset += PAGE_SIZE;
73424492514SAlan Previn 	}
73577b6f79dSJohn Harrison 
73677b6f79dSJohn Harrison 	for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) {
73777b6f79dSJohn Harrison 		for (j = 0; j < GUC_MAX_ENGINE_CLASSES; j++) {
7388ba3ba99SJohn Harrison 			u32 engine_mask = guc_get_capture_engine_mask(&info_map, j);
73924492514SAlan Previn 
74024492514SAlan Previn 			/* null list if we dont have said engine or list */
7418ba3ba99SJohn Harrison 			if (!engine_mask) {
74224492514SAlan Previn 				if (ads_is_mapped) {
74324492514SAlan Previn 					ads_blob_write(guc, ads.capture_class[i][j], null_ggtt);
74424492514SAlan Previn 					ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt);
74524492514SAlan Previn 				}
74624492514SAlan Previn 				continue;
74724492514SAlan Previn 			}
74824492514SAlan Previn 			if (intel_guc_capture_getlistsize(guc, i,
74924492514SAlan Previn 							  GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
75024492514SAlan Previn 							  j, &size)) {
75124492514SAlan Previn 				if (ads_is_mapped)
75224492514SAlan Previn 					ads_blob_write(guc, ads.capture_class[i][j], null_ggtt);
75324492514SAlan Previn 				goto engine_instance_list;
75424492514SAlan Previn 			}
75524492514SAlan Previn 			total_size += size;
75624492514SAlan Previn 			if (ads_is_mapped) {
75724492514SAlan Previn 				if (total_size > guc->ads_capture_size ||
75824492514SAlan Previn 				    intel_guc_capture_getlist(guc, i,
75924492514SAlan Previn 							      GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
76024492514SAlan Previn 							      j, &ptr)) {
76124492514SAlan Previn 					ads_blob_write(guc, ads.capture_class[i][j], null_ggtt);
76224492514SAlan Previn 					continue;
76324492514SAlan Previn 				}
76424492514SAlan Previn 				ads_blob_write(guc, ads.capture_class[i][j], ads_ggtt +
76524492514SAlan Previn 					       capture_offset);
76624492514SAlan Previn 				iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size);
76724492514SAlan Previn 				capture_offset += size;
76824492514SAlan Previn 			}
76924492514SAlan Previn engine_instance_list:
77024492514SAlan Previn 			if (intel_guc_capture_getlistsize(guc, i,
77124492514SAlan Previn 							  GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
77224492514SAlan Previn 							  j, &size)) {
77324492514SAlan Previn 				if (ads_is_mapped)
77424492514SAlan Previn 					ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt);
77524492514SAlan Previn 				continue;
77624492514SAlan Previn 			}
77724492514SAlan Previn 			total_size += size;
77824492514SAlan Previn 			if (ads_is_mapped) {
77924492514SAlan Previn 				if (total_size > guc->ads_capture_size ||
78024492514SAlan Previn 				    intel_guc_capture_getlist(guc, i,
78124492514SAlan Previn 							      GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
78224492514SAlan Previn 							      j, &ptr)) {
78324492514SAlan Previn 					ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt);
78424492514SAlan Previn 					continue;
78524492514SAlan Previn 				}
78624492514SAlan Previn 				ads_blob_write(guc, ads.capture_instance[i][j], ads_ggtt +
78724492514SAlan Previn 					       capture_offset);
78824492514SAlan Previn 				iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size);
78924492514SAlan Previn 				capture_offset += size;
79024492514SAlan Previn 			}
79124492514SAlan Previn 		}
79224492514SAlan Previn 		if (intel_guc_capture_getlistsize(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &size)) {
79324492514SAlan Previn 			if (ads_is_mapped)
79424492514SAlan Previn 				ads_blob_write(guc, ads.capture_global[i], null_ggtt);
79524492514SAlan Previn 			continue;
79624492514SAlan Previn 		}
79724492514SAlan Previn 		total_size += size;
79824492514SAlan Previn 		if (ads_is_mapped) {
79924492514SAlan Previn 			if (total_size > guc->ads_capture_size ||
80024492514SAlan Previn 			    intel_guc_capture_getlist(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0,
80124492514SAlan Previn 						      &ptr)) {
80224492514SAlan Previn 				ads_blob_write(guc, ads.capture_global[i], null_ggtt);
80324492514SAlan Previn 				continue;
80424492514SAlan Previn 			}
80524492514SAlan Previn 			ads_blob_write(guc, ads.capture_global[i], ads_ggtt + capture_offset);
80624492514SAlan Previn 			iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size);
80724492514SAlan Previn 			capture_offset += size;
80824492514SAlan Previn 		}
80977b6f79dSJohn Harrison 	}
81077b6f79dSJohn Harrison 
81124492514SAlan Previn 	if (guc->ads_capture_size && guc->ads_capture_size != PAGE_ALIGN(total_size))
812140f9309SMichal Wajdeczko 		guc_warn(guc, "ADS capture alloc size changed from %d to %d\n",
81324492514SAlan Previn 			 guc->ads_capture_size, PAGE_ALIGN(total_size));
81424492514SAlan Previn 
81524492514SAlan Previn 	return PAGE_ALIGN(total_size);
81677b6f79dSJohn Harrison }
81777b6f79dSJohn Harrison 
818*e4a0251dSJohn Harrison static void guc_waklv_enable_simple(struct intel_guc *guc, u32 *offset, u32 *remain, u32 klv_id)
8197ad6a8faSJohn Harrison {
8207ad6a8faSJohn Harrison 	u32 size;
8217ad6a8faSJohn Harrison 	u32 klv_entry[] = {
8227ad6a8faSJohn Harrison 		/* 16:16 key/length */
8236ef07838SJohn Harrison 		FIELD_PREP(GUC_KLV_0_KEY, klv_id) |
8247ad6a8faSJohn Harrison 		FIELD_PREP(GUC_KLV_0_LEN, 0),
8257ad6a8faSJohn Harrison 		/* 0 dwords data */
8267ad6a8faSJohn Harrison 	};
8277ad6a8faSJohn Harrison 
8287ad6a8faSJohn Harrison 	size = sizeof(klv_entry);
8296ef07838SJohn Harrison 	GEM_BUG_ON(*remain < size);
8307ad6a8faSJohn Harrison 
8316ef07838SJohn Harrison 	iosys_map_memcpy_to(&guc->ads_map, *offset, klv_entry, size);
8326ef07838SJohn Harrison 	*offset += size;
8336ef07838SJohn Harrison 	*remain -= size;
8347ad6a8faSJohn Harrison }
8357ad6a8faSJohn Harrison 
8366cc7a5c7SJohn Harrison static void guc_waklv_init(struct intel_guc *guc)
8376cc7a5c7SJohn Harrison {
8386cc7a5c7SJohn Harrison 	struct intel_gt *gt = guc_to_gt(guc);
8396cc7a5c7SJohn Harrison 	u32 offset, addr_ggtt, remain, size;
8406cc7a5c7SJohn Harrison 
8416cc7a5c7SJohn Harrison 	if (!intel_uc_uses_guc_submission(&gt->uc))
8426cc7a5c7SJohn Harrison 		return;
8436cc7a5c7SJohn Harrison 
8446cc7a5c7SJohn Harrison 	if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 10, 0))
8456cc7a5c7SJohn Harrison 		return;
8466cc7a5c7SJohn Harrison 
8476cc7a5c7SJohn Harrison 	GEM_BUG_ON(iosys_map_is_null(&guc->ads_map));
8486cc7a5c7SJohn Harrison 	offset = guc_ads_waklv_offset(guc);
8496cc7a5c7SJohn Harrison 	remain = guc_ads_waklv_size(guc);
8506cc7a5c7SJohn Harrison 
8517ad6a8faSJohn Harrison 	/* Wa_14019159160 */
852*e4a0251dSJohn Harrison 	if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) {
853*e4a0251dSJohn Harrison 		guc_waklv_enable_simple(guc, &offset, &remain,
854*e4a0251dSJohn Harrison 					GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE);
855*e4a0251dSJohn Harrison 		guc_waklv_enable_simple(guc, &offset, &remain,
856*e4a0251dSJohn Harrison 					GUC_WORKAROUND_KLV_AVOID_GFX_CLEAR_WHILE_ACTIVE);
857*e4a0251dSJohn Harrison 	}
8586ef07838SJohn Harrison 
8596ef07838SJohn Harrison 	/* Wa_16021333562 */
8606ef07838SJohn Harrison 	if ((GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 21, 1)) &&
8616ef07838SJohn Harrison 	    (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74)) ||
8626ef07838SJohn Harrison 	     IS_MEDIA_GT_IP_RANGE(gt, IP_VER(13, 0), IP_VER(13, 0)) ||
8636ef07838SJohn Harrison 	     IS_DG2(gt->i915)))
864*e4a0251dSJohn Harrison 		guc_waklv_enable_simple(guc, &offset, &remain,
865*e4a0251dSJohn Harrison 					GUC_WORKAROUND_KLV_BLOCK_INTERRUPTS_WHEN_MGSR_BLOCKED);
8666cc7a5c7SJohn Harrison 
8676cc7a5c7SJohn Harrison 	size = guc_ads_waklv_size(guc) - remain;
8686cc7a5c7SJohn Harrison 	if (!size)
8696cc7a5c7SJohn Harrison 		return;
8706cc7a5c7SJohn Harrison 
8716cc7a5c7SJohn Harrison 	offset = guc_ads_waklv_offset(guc);
8726cc7a5c7SJohn Harrison 	addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset;
8736cc7a5c7SJohn Harrison 
8746cc7a5c7SJohn Harrison 	ads_blob_write(guc, ads.wa_klv_addr_lo, addr_ggtt);
8756cc7a5c7SJohn Harrison 	ads_blob_write(guc, ads.wa_klv_addr_hi, 0);
8766cc7a5c7SJohn Harrison 	ads_blob_write(guc, ads.wa_klv_size, size);
8776cc7a5c7SJohn Harrison }
8786cc7a5c7SJohn Harrison 
8796cc7a5c7SJohn Harrison static int guc_prep_waklv(struct intel_guc *guc)
8806cc7a5c7SJohn Harrison {
8816cc7a5c7SJohn Harrison 	/* Fudge something chunky for now: */
8826cc7a5c7SJohn Harrison 	return PAGE_SIZE;
8836cc7a5c7SJohn Harrison }
8846cc7a5c7SJohn Harrison 
885481d458cSJohn Harrison static void __guc_ads_init(struct intel_guc *guc)
886481d458cSJohn Harrison {
887481d458cSJohn Harrison 	struct intel_gt *gt = guc_to_gt(guc);
888481d458cSJohn Harrison 	struct drm_i915_private *i915 = gt->i915;
889d9a5696eSLucas De Marchi 	struct iosys_map info_map = IOSYS_MAP_INIT_OFFSET(&guc->ads_map,
890d9a5696eSLucas De Marchi 			offsetof(struct __guc_ads_blob, system_info));
891481d458cSJohn Harrison 	u32 base;
892481d458cSJohn Harrison 
893481d458cSJohn Harrison 	/* GuC scheduling policies */
8942dce68faSLucas De Marchi 	guc_policies_init(guc);
895481d458cSJohn Harrison 
8960f261b24SDaniele Ceraolo Spurio 	/* System info */
897d9a5696eSLucas De Marchi 	fill_engine_enable_masks(gt, &info_map);
8980f261b24SDaniele Ceraolo Spurio 
899691ebb11SLucas De Marchi 	ads_blob_write(guc, system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_SLICE_ENABLED],
900691ebb11SLucas De Marchi 		       hweight8(gt->info.sseu.slice_mask));
901691ebb11SLucas De Marchi 	ads_blob_write(guc, system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_VDBOX_SFC_SUPPORT_MASK],
902691ebb11SLucas De Marchi 		       gt->info.vdbox_sfc_access);
903c784e524SJohn Harrison 
904c816723bSLucas De Marchi 	if (GRAPHICS_VER(i915) >= 12 && !IS_DGFX(i915)) {
905c784e524SJohn Harrison 		u32 distdbreg = intel_uncore_read(gt->uncore,
906c784e524SJohn Harrison 						  GEN12_DIST_DBS_POPULATED);
907691ebb11SLucas De Marchi 		ads_blob_write(guc,
908691ebb11SLucas De Marchi 			       system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_DOORBELL_COUNT_PER_SQIDI],
909691ebb11SLucas De Marchi 			       ((distdbreg >> GEN12_DOORBELLS_PER_SQIDI_SHIFT)
910691ebb11SLucas De Marchi 				& GEN12_DOORBELLS_PER_SQIDI) + 1);
911c784e524SJohn Harrison 	}
912c784e524SJohn Harrison 
913481d458cSJohn Harrison 	/* Golden contexts for re-initialising after a watchdog reset */
914d9a5696eSLucas De Marchi 	guc_prep_golden_context(guc);
915481d458cSJohn Harrison 
916c723b8eeSLucas De Marchi 	guc_mapping_table_init(guc_to_gt(guc), &info_map);
9170f261b24SDaniele Ceraolo Spurio 
9180f261b24SDaniele Ceraolo Spurio 	base = intel_guc_ggtt_offset(guc, guc->ads_vma);
9190f261b24SDaniele Ceraolo Spurio 
92024492514SAlan Previn 	/* Lists for error capture debug */
92124492514SAlan Previn 	guc_capture_prep_lists(guc);
92277b6f79dSJohn Harrison 
9230f261b24SDaniele Ceraolo Spurio 	/* ADS */
924691ebb11SLucas De Marchi 	ads_blob_write(guc, ads.scheduler_policies, base +
925691ebb11SLucas De Marchi 		       offsetof(struct __guc_ads_blob, policies));
926691ebb11SLucas De Marchi 	ads_blob_write(guc, ads.gt_system_info, base +
927691ebb11SLucas De Marchi 		       offsetof(struct __guc_ads_blob, system_info));
9280f261b24SDaniele Ceraolo Spurio 
9296de12da1SJohn Harrison 	/* MMIO save/restore list */
9305fc83950SLucas De Marchi 	guc_mmio_reg_state_init(guc);
9316de12da1SJohn Harrison 
9326cc7a5c7SJohn Harrison 	/* Workaround KLV list */
9336cc7a5c7SJohn Harrison 	guc_waklv_init(guc);
9346cc7a5c7SJohn Harrison 
935c784e524SJohn Harrison 	/* Private Data */
936691ebb11SLucas De Marchi 	ads_blob_write(guc, ads.private_data, base +
937691ebb11SLucas De Marchi 		       guc_ads_private_data_offset(guc));
938c784e524SJohn Harrison 
9390f261b24SDaniele Ceraolo Spurio 	i915_gem_object_flush_map(guc->ads_vma->obj);
9400f261b24SDaniele Ceraolo Spurio }
9410f261b24SDaniele Ceraolo Spurio 
9420f261b24SDaniele Ceraolo Spurio /**
9430f261b24SDaniele Ceraolo Spurio  * intel_guc_ads_create() - allocates and initializes GuC ADS.
9440f261b24SDaniele Ceraolo Spurio  * @guc: intel_guc struct
9450f261b24SDaniele Ceraolo Spurio  *
9460f261b24SDaniele Ceraolo Spurio  * GuC needs memory block (Additional Data Struct), where it will store
9470f261b24SDaniele Ceraolo Spurio  * some data. Allocate and initialize such memory block for GuC use.
9480f261b24SDaniele Ceraolo Spurio  */
9490f261b24SDaniele Ceraolo Spurio int intel_guc_ads_create(struct intel_guc *guc)
9500f261b24SDaniele Ceraolo Spurio {
9510df0c76cSLucas De Marchi 	void *ads_blob;
952c784e524SJohn Harrison 	u32 size;
9530f261b24SDaniele Ceraolo Spurio 	int ret;
9540f261b24SDaniele Ceraolo Spurio 
9550f261b24SDaniele Ceraolo Spurio 	GEM_BUG_ON(guc->ads_vma);
9560f261b24SDaniele Ceraolo Spurio 
957bf890040SLucas De Marchi 	/*
958bf890040SLucas De Marchi 	 * Create reg state size dynamically on system memory to be copied to
959bf890040SLucas De Marchi 	 * the final ads blob on gt init/reset
960bf890040SLucas De Marchi 	 */
961bf890040SLucas De Marchi 	ret = guc_mmio_reg_state_create(guc);
9626de12da1SJohn Harrison 	if (ret < 0)
9636de12da1SJohn Harrison 		return ret;
9646de12da1SJohn Harrison 	guc->ads_regset_size = ret;
9656de12da1SJohn Harrison 
966481d458cSJohn Harrison 	/* Likewise the golden contexts: */
967d9a5696eSLucas De Marchi 	ret = guc_prep_golden_context(guc);
968481d458cSJohn Harrison 	if (ret < 0)
969481d458cSJohn Harrison 		return ret;
970481d458cSJohn Harrison 	guc->ads_golden_ctxt_size = ret;
971481d458cSJohn Harrison 
97224492514SAlan Previn 	/* Likewise the capture lists: */
97324492514SAlan Previn 	ret = guc_capture_prep_lists(guc);
97424492514SAlan Previn 	if (ret < 0)
97524492514SAlan Previn 		return ret;
97624492514SAlan Previn 	guc->ads_capture_size = ret;
97724492514SAlan Previn 
9786cc7a5c7SJohn Harrison 	/* And don't forget the workaround KLVs: */
9796cc7a5c7SJohn Harrison 	ret = guc_prep_waklv(guc);
9806cc7a5c7SJohn Harrison 	if (ret < 0)
9816cc7a5c7SJohn Harrison 		return ret;
9826cc7a5c7SJohn Harrison 	guc->ads_waklv_size = ret;
9836cc7a5c7SJohn Harrison 
984481d458cSJohn Harrison 	/* Now the total size can be determined: */
985c784e524SJohn Harrison 	size = guc_ads_blob_size(guc);
986c784e524SJohn Harrison 
98718c094b3SDaniele Ceraolo Spurio 	ret = intel_guc_allocate_and_map_vma(guc, size, &guc->ads_vma,
9880df0c76cSLucas De Marchi 					     &ads_blob);
98918c094b3SDaniele Ceraolo Spurio 	if (ret)
99018c094b3SDaniele Ceraolo Spurio 		return ret;
9910f261b24SDaniele Ceraolo Spurio 
9921c0b1175SLucas De Marchi 	if (i915_gem_object_is_lmem(guc->ads_vma->obj))
9930df0c76cSLucas De Marchi 		iosys_map_set_vaddr_iomem(&guc->ads_map, (void __iomem *)ads_blob);
9941c0b1175SLucas De Marchi 	else
9950df0c76cSLucas De Marchi 		iosys_map_set_vaddr(&guc->ads_map, ads_blob);
9961c0b1175SLucas De Marchi 
9970f261b24SDaniele Ceraolo Spurio 	__guc_ads_init(guc);
9980f261b24SDaniele Ceraolo Spurio 
9990f261b24SDaniele Ceraolo Spurio 	return 0;
10000f261b24SDaniele Ceraolo Spurio }
10010f261b24SDaniele Ceraolo Spurio 
1002481d458cSJohn Harrison void intel_guc_ads_init_late(struct intel_guc *guc)
1003481d458cSJohn Harrison {
1004481d458cSJohn Harrison 	/*
1005481d458cSJohn Harrison 	 * The golden context setup requires the saved engine state from
1006481d458cSJohn Harrison 	 * __engines_record_defaults(). However, that requires engines to be
1007481d458cSJohn Harrison 	 * operational which means the ADS must already have been configured.
1008481d458cSJohn Harrison 	 * Fortunately, the golden context state is not needed until a hang
1009481d458cSJohn Harrison 	 * occurs, so it can be filled in during this late init phase.
1010481d458cSJohn Harrison 	 */
1011481d458cSJohn Harrison 	guc_init_golden_context(guc);
1012481d458cSJohn Harrison }
1013481d458cSJohn Harrison 
10140f261b24SDaniele Ceraolo Spurio void intel_guc_ads_destroy(struct intel_guc *guc)
10150f261b24SDaniele Ceraolo Spurio {
10160f261b24SDaniele Ceraolo Spurio 	i915_vma_unpin_and_release(&guc->ads_vma, I915_VMA_RELEASE_MAP);
10171c0b1175SLucas De Marchi 	iosys_map_clear(&guc->ads_map);
1018bf890040SLucas De Marchi 	kfree(guc->ads_regset);
10190f261b24SDaniele Ceraolo Spurio }
10200f261b24SDaniele Ceraolo Spurio 
1021c784e524SJohn Harrison static void guc_ads_private_data_reset(struct intel_guc *guc)
1022c784e524SJohn Harrison {
1023c784e524SJohn Harrison 	u32 size;
1024c784e524SJohn Harrison 
1025c784e524SJohn Harrison 	size = guc_ads_private_data_size(guc);
1026c784e524SJohn Harrison 	if (!size)
1027c784e524SJohn Harrison 		return;
1028c784e524SJohn Harrison 
102998529e95SLucas De Marchi 	iosys_map_memset(&guc->ads_map, guc_ads_private_data_offset(guc),
103098529e95SLucas De Marchi 			 0, size);
1031c784e524SJohn Harrison }
1032c784e524SJohn Harrison 
10330f261b24SDaniele Ceraolo Spurio /**
10340f261b24SDaniele Ceraolo Spurio  * intel_guc_ads_reset() - prepares GuC Additional Data Struct for reuse
10350f261b24SDaniele Ceraolo Spurio  * @guc: intel_guc struct
10360f261b24SDaniele Ceraolo Spurio  *
10370f261b24SDaniele Ceraolo Spurio  * GuC stores some data in ADS, which might be stale after a reset.
10380f261b24SDaniele Ceraolo Spurio  * Reinitialize whole ADS in case any part of it was corrupted during
10390f261b24SDaniele Ceraolo Spurio  * previous GuC run.
10400f261b24SDaniele Ceraolo Spurio  */
10410f261b24SDaniele Ceraolo Spurio void intel_guc_ads_reset(struct intel_guc *guc)
10420f261b24SDaniele Ceraolo Spurio {
10430f261b24SDaniele Ceraolo Spurio 	if (!guc->ads_vma)
10440f261b24SDaniele Ceraolo Spurio 		return;
1045c784e524SJohn Harrison 
10460f261b24SDaniele Ceraolo Spurio 	__guc_ads_init(guc);
1047c784e524SJohn Harrison 
1048c784e524SJohn Harrison 	guc_ads_private_data_reset(guc);
10490f261b24SDaniele Ceraolo Spurio }
105077cdd054SUmesh Nerlige Ramappa 
105177cdd054SUmesh Nerlige Ramappa u32 intel_guc_engine_usage_offset(struct intel_guc *guc)
105277cdd054SUmesh Nerlige Ramappa {
10534801b995SLucas De Marchi 	return intel_guc_ggtt_offset(guc, guc->ads_vma) +
10544801b995SLucas De Marchi 		offsetof(struct __guc_ads_blob, engine_usage);
105577cdd054SUmesh Nerlige Ramappa }
105677cdd054SUmesh Nerlige Ramappa 
10574801b995SLucas De Marchi struct iosys_map intel_guc_engine_usage_record_map(struct intel_engine_cs *engine)
105877cdd054SUmesh Nerlige Ramappa {
10593f2f20daSAndi Shyti 	struct intel_guc *guc = gt_to_guc(engine->gt);
106077cdd054SUmesh Nerlige Ramappa 	u8 guc_class = engine_class_to_guc_class(engine->class);
10614801b995SLucas De Marchi 	size_t offset = offsetof(struct __guc_ads_blob,
10624801b995SLucas De Marchi 				 engine_usage.engines[guc_class][ilog2(engine->logical_mask)]);
106377cdd054SUmesh Nerlige Ramappa 
10644801b995SLucas De Marchi 	return IOSYS_MAP_INIT_OFFSET(&guc->ads_map, offset);
106577cdd054SUmesh Nerlige Ramappa }
1066