1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6 #include <linux/types.h> 7 8 #include "gt/intel_gt.h" 9 #include "gt/intel_gt_print.h" 10 #include "intel_gsc_uc.h" 11 #include "intel_gsc_fw.h" 12 #include "i915_drv.h" 13 #include "intel_gsc_proxy.h" 14 15 static void gsc_work(struct work_struct *work) 16 { 17 struct intel_gsc_uc *gsc = container_of(work, typeof(*gsc), work); 18 struct intel_gt *gt = gsc_uc_to_gt(gsc); 19 intel_wakeref_t wakeref; 20 u32 actions; 21 int ret; 22 23 wakeref = intel_runtime_pm_get(gt->uncore->rpm); 24 25 spin_lock_irq(gt->irq_lock); 26 actions = gsc->gsc_work_actions; 27 gsc->gsc_work_actions = 0; 28 spin_unlock_irq(gt->irq_lock); 29 30 if (actions & GSC_ACTION_FW_LOAD) { 31 ret = intel_gsc_uc_fw_upload(gsc); 32 if (!ret) 33 /* setup proxy on a new load */ 34 actions |= GSC_ACTION_SW_PROXY; 35 else if (ret != -EEXIST) 36 goto out_put; 37 38 /* 39 * The HuC auth can be done both before or after the proxy init; 40 * if done after, a proxy request will be issued and must be 41 * serviced before the authentication can complete. 42 * Since this worker also handles proxy requests, we can't 43 * perform an action that requires the proxy from within it and 44 * then stall waiting for it, because we'd be blocking the 45 * service path. Therefore, it is easier for us to load HuC 46 * first and do proxy later. The GSC will ack the HuC auth and 47 * then send the HuC proxy request as part of the proxy init 48 * flow. 49 * Note that we can only do the GSC auth if the GuC auth was 50 * successful. 51 */ 52 if (intel_uc_uses_huc(>->uc) && 53 intel_huc_is_authenticated(>->uc.huc, INTEL_HUC_AUTH_BY_GUC)) 54 intel_huc_auth(>->uc.huc, INTEL_HUC_AUTH_BY_GSC); 55 } 56 57 if (actions & GSC_ACTION_SW_PROXY) { 58 if (!intel_gsc_uc_fw_init_done(gsc)) { 59 gt_err(gt, "Proxy request received with GSC not loaded!\n"); 60 goto out_put; 61 } 62 63 ret = intel_gsc_proxy_request_handler(gsc); 64 if (ret) 65 goto out_put; 66 67 /* mark the GSC FW init as done the first time we run this */ 68 if (actions & GSC_ACTION_FW_LOAD) { 69 /* 70 * If there is a proxy establishment error, the GSC might still 71 * complete the request handling cleanly, so we need to check the 72 * status register to check if the proxy init was actually successful 73 */ 74 if (intel_gsc_uc_fw_proxy_init_done(gsc)) { 75 drm_dbg(>->i915->drm, "GSC Proxy initialized\n"); 76 intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_RUNNING); 77 } else { 78 drm_err(>->i915->drm, 79 "GSC status reports proxy init not complete\n"); 80 } 81 } 82 } 83 84 out_put: 85 intel_runtime_pm_put(gt->uncore->rpm, wakeref); 86 } 87 88 static bool gsc_engine_supported(struct intel_gt *gt) 89 { 90 intel_engine_mask_t mask; 91 92 /* 93 * We reach here from i915_driver_early_probe for the primary GT before 94 * its engine mask is set, so we use the device info engine mask for it. 95 * For other GTs we expect the GT-specific mask to be set before we 96 * call this function. 97 */ 98 GEM_BUG_ON(!gt_is_root(gt) && !gt->info.engine_mask); 99 100 if (gt_is_root(gt)) 101 mask = RUNTIME_INFO(gt->i915)->platform_engine_mask; 102 else 103 mask = gt->info.engine_mask; 104 105 return __HAS_ENGINE(mask, GSC0); 106 } 107 108 void intel_gsc_uc_init_early(struct intel_gsc_uc *gsc) 109 { 110 struct intel_gt *gt = gsc_uc_to_gt(gsc); 111 112 /* 113 * GSC FW needs to be copied to a dedicated memory allocations for 114 * loading (see gsc->local), so we don't need to GGTT map the FW image 115 * itself into GGTT. 116 */ 117 intel_uc_fw_init_early(&gsc->fw, INTEL_UC_FW_TYPE_GSC, false); 118 INIT_WORK(&gsc->work, gsc_work); 119 120 /* we can arrive here from i915_driver_early_probe for primary 121 * GT with it being not fully setup hence check device info's 122 * engine mask 123 */ 124 if (!gsc_engine_supported(gt)) { 125 intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED); 126 return; 127 } 128 129 gsc->wq = alloc_ordered_workqueue("i915_gsc", 0); 130 if (!gsc->wq) { 131 gt_err(gt, "failed to allocate WQ for GSC, disabling FW\n"); 132 intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED); 133 } 134 } 135 136 int intel_gsc_uc_init(struct intel_gsc_uc *gsc) 137 { 138 static struct lock_class_key gsc_lock; 139 struct intel_gt *gt = gsc_uc_to_gt(gsc); 140 struct intel_engine_cs *engine = gt->engine[GSC0]; 141 struct intel_context *ce; 142 struct i915_vma *vma; 143 int err; 144 145 err = intel_uc_fw_init(&gsc->fw); 146 if (err) 147 goto out; 148 149 vma = intel_guc_allocate_vma(>->uc.guc, SZ_8M); 150 if (IS_ERR(vma)) { 151 err = PTR_ERR(vma); 152 goto out_fw; 153 } 154 155 gsc->local = vma; 156 157 ce = intel_engine_create_pinned_context(engine, engine->gt->vm, SZ_4K, 158 I915_GEM_HWS_GSC_ADDR, 159 &gsc_lock, "gsc_context"); 160 if (IS_ERR(ce)) { 161 gt_err(gt, "failed to create GSC CS ctx for FW communication\n"); 162 err = PTR_ERR(ce); 163 goto out_vma; 164 } 165 166 gsc->ce = ce; 167 168 /* if we fail to init proxy we still want to load GSC for PM */ 169 intel_gsc_proxy_init(gsc); 170 171 intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOADABLE); 172 173 return 0; 174 175 out_vma: 176 i915_vma_unpin_and_release(&gsc->local, 0); 177 out_fw: 178 intel_uc_fw_fini(&gsc->fw); 179 out: 180 gt_probe_error(gt, "GSC init failed %pe\n", ERR_PTR(err)); 181 return err; 182 } 183 184 void intel_gsc_uc_fini(struct intel_gsc_uc *gsc) 185 { 186 if (!intel_uc_fw_is_loadable(&gsc->fw)) 187 return; 188 189 flush_work(&gsc->work); 190 if (gsc->wq) { 191 destroy_workqueue(gsc->wq); 192 gsc->wq = NULL; 193 } 194 195 intel_gsc_proxy_fini(gsc); 196 197 if (gsc->ce) 198 intel_engine_destroy_pinned_context(fetch_and_zero(&gsc->ce)); 199 200 i915_vma_unpin_and_release(&gsc->local, 0); 201 202 intel_uc_fw_fini(&gsc->fw); 203 } 204 205 void intel_gsc_uc_flush_work(struct intel_gsc_uc *gsc) 206 { 207 if (!intel_uc_fw_is_loadable(&gsc->fw)) 208 return; 209 210 flush_work(&gsc->work); 211 } 212 213 void intel_gsc_uc_resume(struct intel_gsc_uc *gsc) 214 { 215 if (!intel_uc_fw_is_loadable(&gsc->fw)) 216 return; 217 218 /* 219 * we only want to start the GSC worker from here in the actual resume 220 * flow and not during driver load. This is because GSC load is slow and 221 * therefore we want to make sure that the default state init completes 222 * first to not slow down the init thread. A separate call to 223 * intel_gsc_uc_load_start will ensure that the GSC is loaded during 224 * driver load. 225 */ 226 if (!gsc_uc_to_gt(gsc)->engine[GSC0]->default_state) 227 return; 228 229 intel_gsc_uc_load_start(gsc); 230 } 231 232 void intel_gsc_uc_load_start(struct intel_gsc_uc *gsc) 233 { 234 struct intel_gt *gt = gsc_uc_to_gt(gsc); 235 236 if (!intel_uc_fw_is_loadable(&gsc->fw)) 237 return; 238 239 if (intel_gsc_uc_fw_init_done(gsc)) 240 return; 241 242 spin_lock_irq(gt->irq_lock); 243 gsc->gsc_work_actions |= GSC_ACTION_FW_LOAD; 244 spin_unlock_irq(gt->irq_lock); 245 246 queue_work(gsc->wq, &gsc->work); 247 } 248