1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6 #include "xe_uc.h" 7 8 #include "xe_device.h" 9 #include "xe_gsc.h" 10 #include "xe_gsc_proxy.h" 11 #include "xe_gt.h" 12 #include "xe_guc.h" 13 #include "xe_guc_db_mgr.h" 14 #include "xe_guc_pc.h" 15 #include "xe_guc_submit.h" 16 #include "xe_huc.h" 17 #include "xe_uc_fw.h" 18 #include "xe_wopcm.h" 19 20 static struct xe_gt * 21 uc_to_gt(struct xe_uc *uc) 22 { 23 return container_of(uc, struct xe_gt, uc); 24 } 25 26 static struct xe_device * 27 uc_to_xe(struct xe_uc *uc) 28 { 29 return gt_to_xe(uc_to_gt(uc)); 30 } 31 32 /* Should be called once at driver load only */ 33 int xe_uc_init(struct xe_uc *uc) 34 { 35 struct xe_device *xe = uc_to_xe(uc); 36 int ret; 37 38 xe_device_mem_access_get(xe); 39 40 /* 41 * We call the GuC/HuC/GSC init functions even if GuC submission is off 42 * to correctly move our tracking of the FW state to "disabled". 43 */ 44 ret = xe_guc_init(&uc->guc); 45 if (ret) 46 goto err; 47 48 ret = xe_huc_init(&uc->huc); 49 if (ret) 50 goto err; 51 52 ret = xe_gsc_init(&uc->gsc); 53 if (ret) 54 goto err; 55 56 if (!xe_device_uc_enabled(uc_to_xe(uc))) 57 goto err; 58 59 ret = xe_wopcm_init(&uc->wopcm); 60 if (ret) 61 goto err; 62 63 ret = xe_guc_submit_init(&uc->guc); 64 if (ret) 65 goto err; 66 67 ret = xe_guc_db_mgr_init(&uc->guc.dbm, ~0); 68 if (ret) 69 goto err; 70 71 xe_device_mem_access_put(xe); 72 73 return 0; 74 75 err: 76 xe_device_mem_access_put(xe); 77 78 return ret; 79 } 80 81 /** 82 * xe_uc_init_post_hwconfig - init Uc post hwconfig load 83 * @uc: The UC object 84 * 85 * Return: 0 on success, negative error code on error. 86 */ 87 int xe_uc_init_post_hwconfig(struct xe_uc *uc) 88 { 89 int err; 90 91 /* GuC submission not enabled, nothing to do */ 92 if (!xe_device_uc_enabled(uc_to_xe(uc))) 93 return 0; 94 95 err = xe_uc_sanitize_reset(uc); 96 if (err) 97 return err; 98 99 err = xe_guc_init_post_hwconfig(&uc->guc); 100 if (err) 101 return err; 102 103 err = xe_huc_init_post_hwconfig(&uc->huc); 104 if (err) 105 return err; 106 107 return xe_gsc_init_post_hwconfig(&uc->gsc); 108 } 109 110 static int uc_reset(struct xe_uc *uc) 111 { 112 struct xe_device *xe = uc_to_xe(uc); 113 int ret; 114 115 ret = xe_guc_reset(&uc->guc); 116 if (ret) { 117 drm_err(&xe->drm, "Failed to reset GuC, ret = %d\n", ret); 118 return ret; 119 } 120 121 return 0; 122 } 123 124 static void xe_uc_sanitize(struct xe_uc *uc) 125 { 126 xe_huc_sanitize(&uc->huc); 127 xe_guc_sanitize(&uc->guc); 128 } 129 130 int xe_uc_sanitize_reset(struct xe_uc *uc) 131 { 132 xe_uc_sanitize(uc); 133 134 return uc_reset(uc); 135 } 136 137 /** 138 * xe_uc_init_hwconfig - minimally init Uc, read and parse hwconfig 139 * @uc: The UC object 140 * 141 * Return: 0 on success, negative error code on error. 142 */ 143 int xe_uc_init_hwconfig(struct xe_uc *uc) 144 { 145 int ret; 146 147 /* GuC submission not enabled, nothing to do */ 148 if (!xe_device_uc_enabled(uc_to_xe(uc))) 149 return 0; 150 151 ret = xe_guc_min_load_for_hwconfig(&uc->guc); 152 if (ret) 153 return ret; 154 155 return 0; 156 } 157 158 /* 159 * Should be called during driver load, after every GT reset, and after every 160 * suspend to reload / auth the firmwares. 161 */ 162 int xe_uc_init_hw(struct xe_uc *uc) 163 { 164 int ret; 165 166 /* GuC submission not enabled, nothing to do */ 167 if (!xe_device_uc_enabled(uc_to_xe(uc))) 168 return 0; 169 170 ret = xe_huc_upload(&uc->huc); 171 if (ret) 172 return ret; 173 174 ret = xe_guc_upload(&uc->guc); 175 if (ret) 176 return ret; 177 178 ret = xe_guc_enable_communication(&uc->guc); 179 if (ret) 180 return ret; 181 182 ret = xe_gt_record_default_lrcs(uc_to_gt(uc)); 183 if (ret) 184 return ret; 185 186 ret = xe_guc_post_load_init(&uc->guc); 187 if (ret) 188 return ret; 189 190 ret = xe_guc_pc_start(&uc->guc.pc); 191 if (ret) 192 return ret; 193 194 /* We don't fail the driver load if HuC fails to auth, but let's warn */ 195 ret = xe_huc_auth(&uc->huc, XE_HUC_AUTH_VIA_GUC); 196 xe_gt_assert(uc_to_gt(uc), !ret); 197 198 /* GSC load is async */ 199 xe_gsc_load_start(&uc->gsc); 200 201 return 0; 202 } 203 204 int xe_uc_fini_hw(struct xe_uc *uc) 205 { 206 return xe_uc_sanitize_reset(uc); 207 } 208 209 int xe_uc_reset_prepare(struct xe_uc *uc) 210 { 211 /* GuC submission not enabled, nothing to do */ 212 if (!xe_device_uc_enabled(uc_to_xe(uc))) 213 return 0; 214 215 return xe_guc_reset_prepare(&uc->guc); 216 } 217 218 void xe_uc_gucrc_disable(struct xe_uc *uc) 219 { 220 XE_WARN_ON(xe_guc_pc_gucrc_disable(&uc->guc.pc)); 221 } 222 223 void xe_uc_stop_prepare(struct xe_uc *uc) 224 { 225 xe_gsc_wait_for_worker_completion(&uc->gsc); 226 xe_guc_stop_prepare(&uc->guc); 227 } 228 229 int xe_uc_stop(struct xe_uc *uc) 230 { 231 /* GuC submission not enabled, nothing to do */ 232 if (!xe_device_uc_enabled(uc_to_xe(uc))) 233 return 0; 234 235 return xe_guc_stop(&uc->guc); 236 } 237 238 int xe_uc_start(struct xe_uc *uc) 239 { 240 /* GuC submission not enabled, nothing to do */ 241 if (!xe_device_uc_enabled(uc_to_xe(uc))) 242 return 0; 243 244 return xe_guc_start(&uc->guc); 245 } 246 247 static void uc_reset_wait(struct xe_uc *uc) 248 { 249 int ret; 250 251 again: 252 xe_guc_reset_wait(&uc->guc); 253 254 ret = xe_uc_reset_prepare(uc); 255 if (ret) 256 goto again; 257 } 258 259 int xe_uc_suspend(struct xe_uc *uc) 260 { 261 int ret; 262 263 /* GuC submission not enabled, nothing to do */ 264 if (!xe_device_uc_enabled(uc_to_xe(uc))) 265 return 0; 266 267 uc_reset_wait(uc); 268 269 ret = xe_uc_stop(uc); 270 if (ret) 271 return ret; 272 273 return xe_guc_suspend(&uc->guc); 274 } 275 276 /** 277 * xe_uc_remove() - Clean up the UC structures before driver removal 278 * @uc: the UC object 279 * 280 * This function should only act on objects/structures that must be cleaned 281 * before the driver removal callback is complete and therefore can't be 282 * deferred to a drmm action. 283 */ 284 void xe_uc_remove(struct xe_uc *uc) 285 { 286 xe_gsc_remove(&uc->gsc); 287 } 288