Branch data Line data Source code
1 : : // SPDX-License-Identifier: MIT 2 : : /* 3 : : * Copyright © 2014-2019 Intel Corporation 4 : : */ 5 : : 6 : : #include "gt/intel_gt.h" 7 : : #include "intel_guc_ads.h" 8 : : #include "intel_uc.h" 9 : : #include "i915_drv.h" 10 : : 11 : : /* 12 : : * The Additional Data Struct (ADS) has pointers for different buffers used by 13 : : * the GuC. One single gem object contains the ADS struct itself (guc_ads), the 14 : : * scheduling policies (guc_policies), a structure describing a collection of 15 : : * register sets (guc_mmio_reg_state) and some extra pages for the GuC to save 16 : : * its internal state for sleep. 17 : : */ 18 : : 19 : 0 : static void guc_policy_init(struct guc_policy *policy) 20 : : { 21 : 0 : policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US; 22 : 0 : policy->preemption_time = POLICY_DEFAULT_PREEMPTION_TIME_US; 23 : 0 : policy->fault_time = POLICY_DEFAULT_FAULT_TIME_US; 24 : 0 : policy->policy_flags = 0; 25 : : } 26 : : 27 : 0 : static void guc_policies_init(struct guc_policies *policies) 28 : : { 29 : 0 : struct guc_policy *policy; 30 : 0 : u32 p, i; 31 : : 32 : 0 : policies->dpc_promote_time = POLICY_DEFAULT_DPC_PROMOTE_TIME_US; 33 : 0 : policies->max_num_work_items = POLICY_MAX_NUM_WI; 34 : : 35 [ # # ]: 0 : for (p = 0; p < GUC_CLIENT_PRIORITY_NUM; p++) { 36 [ # # ]: 0 : for (i = 0; i < GUC_MAX_ENGINE_CLASSES; i++) { 37 : 0 : policy = &policies->policy[p][i]; 38 : : 39 : 0 : guc_policy_init(policy); 40 : : } 41 : : } 42 : : 43 : 0 : policies->is_valid = 1; 44 : : } 45 : : 46 : 0 : static void guc_ct_pool_entries_init(struct guc_ct_pool_entry *pool, u32 num) 47 : : { 48 : 0 : memset(pool, 0, num * sizeof(*pool)); 49 : : } 50 : : 51 : : /* 52 : : * The first 80 dwords of the register state context, containing the 53 : : * execlists and ppgtt registers. 54 : : */ 55 : : #define LR_HW_CONTEXT_SIZE (80 * sizeof(u32)) 56 : : 57 : : /* The ads obj includes the struct itself and buffers passed to GuC */ 58 : : struct __guc_ads_blob { 59 : : struct guc_ads ads; 60 : : struct guc_policies policies; 61 : : struct guc_mmio_reg_state reg_state; 62 : : struct guc_gt_system_info system_info; 63 : : struct guc_clients_info clients_info; 64 : : struct guc_ct_pool_entry ct_pool[GUC_CT_POOL_SIZE]; 65 : : u8 reg_state_buffer[GUC_S3_SAVE_SPACE_PAGES * PAGE_SIZE]; 66 : : } __packed; 67 : : 68 : 0 : static void __guc_ads_init(struct intel_guc *guc) 69 : : { 70 : 0 : struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915; 71 : 0 : struct __guc_ads_blob *blob = guc->ads_blob; 72 : 0 : const u32 skipped_size = LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE; 73 : 0 : u32 base; 74 : 0 : u8 engine_class; 75 : : 76 : : /* GuC scheduling policies */ 77 : 0 : guc_policies_init(&blob->policies); 78 : : 79 : : /* 80 : : * GuC expects a per-engine-class context image and size 81 : : * (minus hwsp and ring context). The context image will be 82 : : * used to reinitialize engines after a reset. It must exist 83 : : * and be pinned in the GGTT, so that the address won't change after 84 : : * we have told GuC where to find it. The context size will be used 85 : : * to validate that the LRC base + size fall within allowed GGTT. 86 : : */ 87 [ # # ]: 0 : for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) { 88 [ # # ]: 0 : if (engine_class == OTHER_CLASS) 89 : 0 : continue; 90 : : /* 91 : : * TODO: Set context pointer to default state to allow 92 : : * GuC to re-init guilty contexts after internal reset. 93 : : */ 94 : 0 : blob->ads.golden_context_lrca[engine_class] = 0; 95 : 0 : blob->ads.eng_state_size[engine_class] = 96 : 0 : intel_engine_context_size(guc_to_gt(guc), 97 : 0 : engine_class) - 98 : : skipped_size; 99 : : } 100 : : 101 : : /* System info */ 102 [ # # ]: 0 : blob->system_info.slice_enabled = hweight8(RUNTIME_INFO(dev_priv)->sseu.slice_mask); 103 : 0 : blob->system_info.rcs_enabled = 1; 104 : 0 : blob->system_info.bcs_enabled = 1; 105 : : 106 : 0 : blob->system_info.vdbox_enable_mask = VDBOX_MASK(dev_priv); 107 : 0 : blob->system_info.vebox_enable_mask = VEBOX_MASK(dev_priv); 108 : 0 : blob->system_info.vdbox_sfc_support_mask = RUNTIME_INFO(dev_priv)->vdbox_sfc_access; 109 : : 110 : 0 : base = intel_guc_ggtt_offset(guc, guc->ads_vma); 111 : : 112 : : /* Clients info */ 113 : 0 : guc_ct_pool_entries_init(blob->ct_pool, ARRAY_SIZE(blob->ct_pool)); 114 : : 115 : 0 : blob->clients_info.clients_num = 1; 116 : 0 : blob->clients_info.ct_pool_addr = base + ptr_offset(blob, ct_pool); 117 : 0 : blob->clients_info.ct_pool_count = ARRAY_SIZE(blob->ct_pool); 118 : : 119 : : /* ADS */ 120 : 0 : blob->ads.scheduler_policies = base + ptr_offset(blob, policies); 121 : 0 : blob->ads.reg_state_buffer = base + ptr_offset(blob, reg_state_buffer); 122 : 0 : blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state); 123 : 0 : blob->ads.gt_system_info = base + ptr_offset(blob, system_info); 124 : 0 : blob->ads.clients_info = base + ptr_offset(blob, clients_info); 125 : : 126 : 0 : i915_gem_object_flush_map(guc->ads_vma->obj); 127 : 0 : } 128 : : 129 : : /** 130 : : * intel_guc_ads_create() - allocates and initializes GuC ADS. 131 : : * @guc: intel_guc struct 132 : : * 133 : : * GuC needs memory block (Additional Data Struct), where it will store 134 : : * some data. Allocate and initialize such memory block for GuC use. 135 : : */ 136 : 0 : int intel_guc_ads_create(struct intel_guc *guc) 137 : : { 138 : 0 : const u32 size = PAGE_ALIGN(sizeof(struct __guc_ads_blob)); 139 : 0 : int ret; 140 : : 141 : 0 : GEM_BUG_ON(guc->ads_vma); 142 : : 143 : 0 : ret = intel_guc_allocate_and_map_vma(guc, size, &guc->ads_vma, 144 : 0 : (void **)&guc->ads_blob); 145 : : 146 [ # # ]: 0 : if (ret) 147 : : return ret; 148 : : 149 : 0 : __guc_ads_init(guc); 150 : : 151 : 0 : return 0; 152 : : } 153 : : 154 : 0 : void intel_guc_ads_destroy(struct intel_guc *guc) 155 : : { 156 : 0 : i915_vma_unpin_and_release(&guc->ads_vma, I915_VMA_RELEASE_MAP); 157 : 0 : } 158 : : 159 : : /** 160 : : * intel_guc_ads_reset() - prepares GuC Additional Data Struct for reuse 161 : : * @guc: intel_guc struct 162 : : * 163 : : * GuC stores some data in ADS, which might be stale after a reset. 164 : : * Reinitialize whole ADS in case any part of it was corrupted during 165 : : * previous GuC run. 166 : : */ 167 : 0 : void intel_guc_ads_reset(struct intel_guc *guc) 168 : : { 169 [ # # ]: 0 : if (!guc->ads_vma) 170 : : return; 171 : 0 : __guc_ads_init(guc); 172 : : }