intel_uc.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /*
  2. * Copyright © 2016 Intel Corporation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. * IN THE SOFTWARE.
  22. *
  23. */
  24. #include "intel_uc.h"
  25. #include "intel_guc_submission.h"
  26. #include "intel_guc.h"
  27. #include "i915_drv.h"
  28. /* Reset GuC providing us with fresh state for both GuC and HuC.
  29. */
  30. static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv)
  31. {
  32. int ret;
  33. u32 guc_status;
  34. ret = intel_reset_guc(dev_priv);
  35. if (ret) {
  36. DRM_ERROR("Failed to reset GuC, ret = %d\n", ret);
  37. return ret;
  38. }
  39. guc_status = I915_READ(GUC_STATUS);
  40. WARN(!(guc_status & GS_MIA_IN_RESET),
  41. "GuC status: 0x%x, MIA core expected to be in reset\n",
  42. guc_status);
  43. return ret;
  44. }
  45. static int __get_platform_enable_guc(struct drm_i915_private *dev_priv)
  46. {
  47. struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
  48. struct intel_uc_fw *huc_fw = &dev_priv->huc.fw;
  49. int enable_guc = 0;
  50. /* Default is to enable GuC/HuC if we know their firmwares */
  51. if (intel_uc_fw_is_selected(guc_fw))
  52. enable_guc |= ENABLE_GUC_SUBMISSION;
  53. if (intel_uc_fw_is_selected(huc_fw))
  54. enable_guc |= ENABLE_GUC_LOAD_HUC;
  55. /* Any platform specific fine-tuning can be done here */
  56. return enable_guc;
  57. }
  58. /**
  59. * intel_uc_sanitize_options - sanitize uC related modparam options
  60. * @dev_priv: device private
  61. *
  62. * In case of "enable_guc" option this function will attempt to modify
  63. * it only if it was initially set to "auto(-1)". Default value for this
  64. * modparam varies between platforms and it is hardcoded in driver code.
  65. * Any other modparam value is only monitored against availability of the
  66. * related hardware or firmware definitions.
  67. */
  68. void intel_uc_sanitize_options(struct drm_i915_private *dev_priv)
  69. {
  70. struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
  71. struct intel_uc_fw *huc_fw = &dev_priv->huc.fw;
  72. /* A negative value means "use platform default" */
  73. if (i915_modparams.enable_guc < 0)
  74. i915_modparams.enable_guc = __get_platform_enable_guc(dev_priv);
  75. DRM_DEBUG_DRIVER("enable_guc=%d (submission:%s huc:%s)\n",
  76. i915_modparams.enable_guc,
  77. yesno(intel_uc_is_using_guc_submission()),
  78. yesno(intel_uc_is_using_huc()));
  79. /* Verify GuC firmware availability */
  80. if (intel_uc_is_using_guc() && !intel_uc_fw_is_selected(guc_fw)) {
  81. DRM_WARN("Incompatible option detected: enable_guc=%d, %s!\n",
  82. i915_modparams.enable_guc,
  83. !HAS_GUC(dev_priv) ? "no GuC hardware" :
  84. "no GuC firmware");
  85. }
  86. /* Verify HuC firmware availability */
  87. if (intel_uc_is_using_huc() && !intel_uc_fw_is_selected(huc_fw)) {
  88. DRM_WARN("Incompatible option detected: enable_guc=%d, %s!\n",
  89. i915_modparams.enable_guc,
  90. !HAS_HUC(dev_priv) ? "no HuC hardware" :
  91. "no HuC firmware");
  92. }
  93. /* Make sure that sanitization was done */
  94. GEM_BUG_ON(i915_modparams.enable_guc < 0);
  95. }
  96. void intel_uc_init_early(struct drm_i915_private *dev_priv)
  97. {
  98. intel_guc_init_early(&dev_priv->guc);
  99. intel_huc_init_early(&dev_priv->huc);
  100. }
  101. void intel_uc_init_fw(struct drm_i915_private *dev_priv)
  102. {
  103. if (!USES_GUC(dev_priv))
  104. return;
  105. if (USES_HUC(dev_priv))
  106. intel_uc_fw_fetch(dev_priv, &dev_priv->huc.fw);
  107. intel_uc_fw_fetch(dev_priv, &dev_priv->guc.fw);
  108. }
  109. void intel_uc_fini_fw(struct drm_i915_private *dev_priv)
  110. {
  111. if (!USES_GUC(dev_priv))
  112. return;
  113. intel_uc_fw_fini(&dev_priv->guc.fw);
  114. if (USES_HUC(dev_priv))
  115. intel_uc_fw_fini(&dev_priv->huc.fw);
  116. }
  117. /**
  118. * intel_uc_init_mmio - setup uC MMIO access
  119. *
  120. * @dev_priv: device private
  121. *
  122. * Setup minimal state necessary for MMIO accesses later in the
  123. * initialization sequence.
  124. */
  125. void intel_uc_init_mmio(struct drm_i915_private *dev_priv)
  126. {
  127. intel_guc_init_send_regs(&dev_priv->guc);
  128. }
  129. static void guc_capture_load_err_log(struct intel_guc *guc)
  130. {
  131. if (!guc->log.vma || i915_modparams.guc_log_level < 0)
  132. return;
  133. if (!guc->load_err_log)
  134. guc->load_err_log = i915_gem_object_get(guc->log.vma->obj);
  135. return;
  136. }
  137. static void guc_free_load_err_log(struct intel_guc *guc)
  138. {
  139. if (guc->load_err_log)
  140. i915_gem_object_put(guc->load_err_log);
  141. }
  142. static int guc_enable_communication(struct intel_guc *guc)
  143. {
  144. struct drm_i915_private *dev_priv = guc_to_i915(guc);
  145. if (HAS_GUC_CT(dev_priv))
  146. return intel_guc_enable_ct(guc);
  147. guc->send = intel_guc_send_mmio;
  148. return 0;
  149. }
  150. static void guc_disable_communication(struct intel_guc *guc)
  151. {
  152. struct drm_i915_private *dev_priv = guc_to_i915(guc);
  153. if (HAS_GUC_CT(dev_priv))
  154. intel_guc_disable_ct(guc);
  155. guc->send = intel_guc_send_nop;
  156. }
  157. int intel_uc_init_wq(struct drm_i915_private *dev_priv)
  158. {
  159. int ret;
  160. if (!USES_GUC(dev_priv))
  161. return 0;
  162. ret = intel_guc_init_wq(&dev_priv->guc);
  163. if (ret) {
  164. DRM_ERROR("Couldn't allocate workqueues for GuC\n");
  165. return ret;
  166. }
  167. return 0;
  168. }
  169. void intel_uc_fini_wq(struct drm_i915_private *dev_priv)
  170. {
  171. if (!USES_GUC(dev_priv))
  172. return;
  173. GEM_BUG_ON(!HAS_GUC(dev_priv));
  174. intel_guc_fini_wq(&dev_priv->guc);
  175. }
  176. int intel_uc_init(struct drm_i915_private *dev_priv)
  177. {
  178. struct intel_guc *guc = &dev_priv->guc;
  179. int ret;
  180. if (!USES_GUC(dev_priv))
  181. return 0;
  182. if (!HAS_GUC(dev_priv))
  183. return -ENODEV;
  184. ret = intel_guc_init(guc);
  185. if (ret)
  186. return ret;
  187. if (USES_GUC_SUBMISSION(dev_priv)) {
  188. /*
  189. * This is stuff we need to have available at fw load time
  190. * if we are planning to enable submission later
  191. */
  192. ret = intel_guc_submission_init(guc);
  193. if (ret) {
  194. intel_guc_fini(guc);
  195. return ret;
  196. }
  197. }
  198. return 0;
  199. }
  200. void intel_uc_fini(struct drm_i915_private *dev_priv)
  201. {
  202. struct intel_guc *guc = &dev_priv->guc;
  203. if (!USES_GUC(dev_priv))
  204. return;
  205. GEM_BUG_ON(!HAS_GUC(dev_priv));
  206. if (USES_GUC_SUBMISSION(dev_priv))
  207. intel_guc_submission_fini(guc);
  208. intel_guc_fini(guc);
  209. }
  210. int intel_uc_init_hw(struct drm_i915_private *dev_priv)
  211. {
  212. struct intel_guc *guc = &dev_priv->guc;
  213. struct intel_huc *huc = &dev_priv->huc;
  214. int ret, attempts;
  215. if (!USES_GUC(dev_priv))
  216. return 0;
  217. GEM_BUG_ON(!HAS_GUC(dev_priv));
  218. guc_disable_communication(guc);
  219. gen9_reset_guc_interrupts(dev_priv);
  220. /* init WOPCM */
  221. I915_WRITE(GUC_WOPCM_SIZE, intel_guc_wopcm_size(dev_priv));
  222. I915_WRITE(DMA_GUC_WOPCM_OFFSET,
  223. GUC_WOPCM_OFFSET_VALUE | HUC_LOADING_AGENT_GUC);
  224. /* WaEnableuKernelHeaderValidFix:skl */
  225. /* WaEnableGuCBootHashCheckNotSet:skl,bxt,kbl */
  226. if (IS_GEN9(dev_priv))
  227. attempts = 3;
  228. else
  229. attempts = 1;
  230. while (attempts--) {
  231. /*
  232. * Always reset the GuC just before (re)loading, so
  233. * that the state and timing are fairly predictable
  234. */
  235. ret = __intel_uc_reset_hw(dev_priv);
  236. if (ret)
  237. goto err_out;
  238. if (USES_HUC(dev_priv)) {
  239. ret = intel_huc_init_hw(huc);
  240. if (ret)
  241. goto err_out;
  242. }
  243. intel_guc_init_params(guc);
  244. ret = intel_guc_fw_upload(guc);
  245. if (ret == 0 || ret != -EAGAIN)
  246. break;
  247. DRM_DEBUG_DRIVER("GuC fw load failed: %d; will reset and "
  248. "retry %d more time(s)\n", ret, attempts);
  249. }
  250. /* Did we succeded or run out of retries? */
  251. if (ret)
  252. goto err_log_capture;
  253. ret = guc_enable_communication(guc);
  254. if (ret)
  255. goto err_log_capture;
  256. if (USES_HUC(dev_priv)) {
  257. ret = intel_huc_auth(huc);
  258. if (ret)
  259. goto err_communication;
  260. }
  261. if (USES_GUC_SUBMISSION(dev_priv)) {
  262. if (i915_modparams.guc_log_level >= 0)
  263. gen9_enable_guc_interrupts(dev_priv);
  264. ret = intel_guc_submission_enable(guc);
  265. if (ret)
  266. goto err_interrupts;
  267. }
  268. dev_info(dev_priv->drm.dev, "GuC firmware version %u.%u\n",
  269. guc->fw.major_ver_found, guc->fw.minor_ver_found);
  270. dev_info(dev_priv->drm.dev, "GuC submission %s\n",
  271. enableddisabled(USES_GUC_SUBMISSION(dev_priv)));
  272. dev_info(dev_priv->drm.dev, "HuC %s\n",
  273. enableddisabled(USES_HUC(dev_priv)));
  274. return 0;
  275. /*
  276. * We've failed to load the firmware :(
  277. */
  278. err_interrupts:
  279. gen9_disable_guc_interrupts(dev_priv);
  280. err_communication:
  281. guc_disable_communication(guc);
  282. err_log_capture:
  283. guc_capture_load_err_log(guc);
  284. err_out:
  285. /*
  286. * Note that there is no fallback as either user explicitly asked for
  287. * the GuC or driver default option was to run with the GuC enabled.
  288. */
  289. if (GEM_WARN_ON(ret == -EIO))
  290. ret = -EINVAL;
  291. dev_err(dev_priv->drm.dev, "GuC initialization failed %d\n", ret);
  292. return ret;
  293. }
  294. void intel_uc_fini_hw(struct drm_i915_private *dev_priv)
  295. {
  296. struct intel_guc *guc = &dev_priv->guc;
  297. guc_free_load_err_log(guc);
  298. if (!USES_GUC(dev_priv))
  299. return;
  300. GEM_BUG_ON(!HAS_GUC(dev_priv));
  301. if (USES_GUC_SUBMISSION(dev_priv))
  302. intel_guc_submission_disable(guc);
  303. guc_disable_communication(guc);
  304. if (USES_GUC_SUBMISSION(dev_priv))
  305. gen9_disable_guc_interrupts(dev_priv);
  306. }