intel_uc_fw.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Copyright © 2016-2017 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 <linux/firmware.h>
  25. #include <drm/drm_print.h>
  26. #include "intel_uc_fw.h"
  27. #include "i915_drv.h"
  28. /**
  29. * intel_uc_fw_fetch - fetch uC firmware
  30. *
  31. * @dev_priv: device private
  32. * @uc_fw: uC firmware
  33. *
  34. * Fetch uC firmware into GEM obj.
  35. */
  36. void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
  37. struct intel_uc_fw *uc_fw)
  38. {
  39. struct pci_dev *pdev = dev_priv->drm.pdev;
  40. struct drm_i915_gem_object *obj;
  41. const struct firmware *fw = NULL;
  42. struct uc_css_header *css;
  43. size_t size;
  44. int err;
  45. DRM_DEBUG_DRIVER("%s fw fetch %s\n",
  46. intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
  47. if (!uc_fw->path)
  48. return;
  49. uc_fw->fetch_status = INTEL_UC_FIRMWARE_PENDING;
  50. DRM_DEBUG_DRIVER("%s fw fetch %s\n",
  51. intel_uc_fw_type_repr(uc_fw->type),
  52. intel_uc_fw_status_repr(uc_fw->fetch_status));
  53. err = request_firmware(&fw, uc_fw->path, &pdev->dev);
  54. if (err) {
  55. DRM_DEBUG_DRIVER("%s fw request_firmware err=%d\n",
  56. intel_uc_fw_type_repr(uc_fw->type), err);
  57. goto fail;
  58. }
  59. DRM_DEBUG_DRIVER("%s fw size %zu ptr %p\n",
  60. intel_uc_fw_type_repr(uc_fw->type), fw->size, fw);
  61. /* Check the size of the blob before examining buffer contents */
  62. if (fw->size < sizeof(struct uc_css_header)) {
  63. DRM_WARN("%s: Unexpected firmware size (%zu, min %zu)\n",
  64. intel_uc_fw_type_repr(uc_fw->type),
  65. fw->size, sizeof(struct uc_css_header));
  66. err = -ENODATA;
  67. goto fail;
  68. }
  69. css = (struct uc_css_header *)fw->data;
  70. /* Firmware bits always start from header */
  71. uc_fw->header_offset = 0;
  72. uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
  73. css->key_size_dw - css->exponent_size_dw) *
  74. sizeof(u32);
  75. if (uc_fw->header_size != sizeof(struct uc_css_header)) {
  76. DRM_WARN("%s: Mismatched firmware header definition\n",
  77. intel_uc_fw_type_repr(uc_fw->type));
  78. err = -ENOEXEC;
  79. goto fail;
  80. }
  81. /* then, uCode */
  82. uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size;
  83. uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
  84. /* now RSA */
  85. if (css->key_size_dw != UOS_RSA_SCRATCH_COUNT) {
  86. DRM_WARN("%s: Mismatched firmware RSA key size (%u)\n",
  87. intel_uc_fw_type_repr(uc_fw->type), css->key_size_dw);
  88. err = -ENOEXEC;
  89. goto fail;
  90. }
  91. uc_fw->rsa_offset = uc_fw->ucode_offset + uc_fw->ucode_size;
  92. uc_fw->rsa_size = css->key_size_dw * sizeof(u32);
  93. /* At least, it should have header, uCode and RSA. Size of all three. */
  94. size = uc_fw->header_size + uc_fw->ucode_size + uc_fw->rsa_size;
  95. if (fw->size < size) {
  96. DRM_WARN("%s: Truncated firmware (%zu, expected %zu)\n",
  97. intel_uc_fw_type_repr(uc_fw->type), fw->size, size);
  98. err = -ENOEXEC;
  99. goto fail;
  100. }
  101. /*
  102. * The GuC firmware image has the version number embedded at a
  103. * well-known offset within the firmware blob; note that major / minor
  104. * version are TWO bytes each (i.e. u16), although all pointers and
  105. * offsets are defined in terms of bytes (u8).
  106. */
  107. switch (uc_fw->type) {
  108. case INTEL_UC_FW_TYPE_GUC:
  109. uc_fw->major_ver_found = css->guc.sw_version >> 16;
  110. uc_fw->minor_ver_found = css->guc.sw_version & 0xFFFF;
  111. break;
  112. case INTEL_UC_FW_TYPE_HUC:
  113. uc_fw->major_ver_found = css->huc.sw_version >> 16;
  114. uc_fw->minor_ver_found = css->huc.sw_version & 0xFFFF;
  115. break;
  116. default:
  117. MISSING_CASE(uc_fw->type);
  118. break;
  119. }
  120. DRM_DEBUG_DRIVER("%s fw version %u.%u (wanted %u.%u)\n",
  121. intel_uc_fw_type_repr(uc_fw->type),
  122. uc_fw->major_ver_found, uc_fw->minor_ver_found,
  123. uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
  124. if (uc_fw->major_ver_wanted == 0 && uc_fw->minor_ver_wanted == 0) {
  125. DRM_NOTE("%s: Skipping firmware version check\n",
  126. intel_uc_fw_type_repr(uc_fw->type));
  127. } else if (uc_fw->major_ver_found != uc_fw->major_ver_wanted ||
  128. uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) {
  129. DRM_NOTE("%s: Wrong firmware version (%u.%u, required %u.%u)\n",
  130. intel_uc_fw_type_repr(uc_fw->type),
  131. uc_fw->major_ver_found, uc_fw->minor_ver_found,
  132. uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
  133. err = -ENOEXEC;
  134. goto fail;
  135. }
  136. obj = i915_gem_object_create_from_data(dev_priv, fw->data, fw->size);
  137. if (IS_ERR(obj)) {
  138. err = PTR_ERR(obj);
  139. DRM_DEBUG_DRIVER("%s fw object_create err=%d\n",
  140. intel_uc_fw_type_repr(uc_fw->type), err);
  141. goto fail;
  142. }
  143. uc_fw->obj = obj;
  144. uc_fw->size = fw->size;
  145. uc_fw->fetch_status = INTEL_UC_FIRMWARE_SUCCESS;
  146. DRM_DEBUG_DRIVER("%s fw fetch %s\n",
  147. intel_uc_fw_type_repr(uc_fw->type),
  148. intel_uc_fw_status_repr(uc_fw->fetch_status));
  149. release_firmware(fw);
  150. return;
  151. fail:
  152. uc_fw->fetch_status = INTEL_UC_FIRMWARE_FAIL;
  153. DRM_DEBUG_DRIVER("%s fw fetch %s\n",
  154. intel_uc_fw_type_repr(uc_fw->type),
  155. intel_uc_fw_status_repr(uc_fw->fetch_status));
  156. DRM_WARN("%s: Failed to fetch firmware %s (error %d)\n",
  157. intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
  158. DRM_INFO("%s: Firmware can be downloaded from %s\n",
  159. intel_uc_fw_type_repr(uc_fw->type), INTEL_UC_FIRMWARE_URL);
  160. release_firmware(fw); /* OK even if fw is NULL */
  161. }
  162. /**
  163. * intel_uc_fw_upload - load uC firmware using custom loader
  164. * @uc_fw: uC firmware
  165. * @xfer: custom uC firmware loader function
  166. *
  167. * Loads uC firmware using custom loader and updates internal flags.
  168. *
  169. * Return: 0 on success, non-zero on failure.
  170. */
  171. int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,
  172. int (*xfer)(struct intel_uc_fw *uc_fw,
  173. struct i915_vma *vma))
  174. {
  175. struct i915_vma *vma;
  176. u32 ggtt_pin_bias;
  177. int err;
  178. DRM_DEBUG_DRIVER("%s fw load %s\n",
  179. intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
  180. if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS)
  181. return -ENOEXEC;
  182. uc_fw->load_status = INTEL_UC_FIRMWARE_PENDING;
  183. DRM_DEBUG_DRIVER("%s fw load %s\n",
  184. intel_uc_fw_type_repr(uc_fw->type),
  185. intel_uc_fw_status_repr(uc_fw->load_status));
  186. /* Pin object with firmware */
  187. err = i915_gem_object_set_to_gtt_domain(uc_fw->obj, false);
  188. if (err) {
  189. DRM_DEBUG_DRIVER("%s fw set-domain err=%d\n",
  190. intel_uc_fw_type_repr(uc_fw->type), err);
  191. goto fail;
  192. }
  193. ggtt_pin_bias = to_i915(uc_fw->obj->base.dev)->guc.ggtt_pin_bias;
  194. vma = i915_gem_object_ggtt_pin(uc_fw->obj, NULL, 0, 0,
  195. PIN_OFFSET_BIAS | ggtt_pin_bias);
  196. if (IS_ERR(vma)) {
  197. err = PTR_ERR(vma);
  198. DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n",
  199. intel_uc_fw_type_repr(uc_fw->type), err);
  200. goto fail;
  201. }
  202. /* Call custom loader */
  203. err = xfer(uc_fw, vma);
  204. /*
  205. * We keep the object pages for reuse during resume. But we can unpin it
  206. * now that DMA has completed, so it doesn't continue to take up space.
  207. */
  208. i915_vma_unpin(vma);
  209. if (err)
  210. goto fail;
  211. uc_fw->load_status = INTEL_UC_FIRMWARE_SUCCESS;
  212. DRM_DEBUG_DRIVER("%s fw load %s\n",
  213. intel_uc_fw_type_repr(uc_fw->type),
  214. intel_uc_fw_status_repr(uc_fw->load_status));
  215. DRM_INFO("%s: Loaded firmware %s (version %u.%u)\n",
  216. intel_uc_fw_type_repr(uc_fw->type),
  217. uc_fw->path,
  218. uc_fw->major_ver_found, uc_fw->minor_ver_found);
  219. return 0;
  220. fail:
  221. uc_fw->load_status = INTEL_UC_FIRMWARE_FAIL;
  222. DRM_DEBUG_DRIVER("%s fw load %s\n",
  223. intel_uc_fw_type_repr(uc_fw->type),
  224. intel_uc_fw_status_repr(uc_fw->load_status));
  225. DRM_WARN("%s: Failed to load firmware %s (error %d)\n",
  226. intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
  227. return err;
  228. }
  229. /**
  230. * intel_uc_fw_fini - cleanup uC firmware
  231. *
  232. * @uc_fw: uC firmware
  233. *
  234. * Cleans up uC firmware by releasing the firmware GEM obj.
  235. */
  236. void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
  237. {
  238. struct drm_i915_gem_object *obj;
  239. obj = fetch_and_zero(&uc_fw->obj);
  240. if (obj)
  241. i915_gem_object_put(obj);
  242. uc_fw->fetch_status = INTEL_UC_FIRMWARE_NONE;
  243. }
  244. /**
  245. * intel_uc_fw_dump - dump information about uC firmware
  246. * @uc_fw: uC firmware
  247. * @p: the &drm_printer
  248. *
  249. * Pretty printer for uC firmware.
  250. */
  251. void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p)
  252. {
  253. drm_printf(p, "%s firmware: %s\n",
  254. intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
  255. drm_printf(p, "\tstatus: fetch %s, load %s\n",
  256. intel_uc_fw_status_repr(uc_fw->fetch_status),
  257. intel_uc_fw_status_repr(uc_fw->load_status));
  258. drm_printf(p, "\tversion: wanted %u.%u, found %u.%u\n",
  259. uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
  260. uc_fw->major_ver_found, uc_fw->minor_ver_found);
  261. drm_printf(p, "\theader: offset %u, size %u\n",
  262. uc_fw->header_offset, uc_fw->header_size);
  263. drm_printf(p, "\tuCode: offset %u, size %u\n",
  264. uc_fw->ucode_offset, uc_fw->ucode_size);
  265. drm_printf(p, "\tRSA: offset %u, size %u\n",
  266. uc_fw->rsa_offset, uc_fw->rsa_size);
  267. }