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(>->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 = ®set->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(>->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(>->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