2 * Copyright © 2016-2017 Intel Corporation
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:
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
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
25 #include <linux/firmware.h>
26 #include <drm/drm_print.h>
28 #include "intel_uc_fw.h"
32 * intel_uc_fw_fetch - fetch uC firmware
34 * @dev_priv: device private
37 * Fetch uC firmware into GEM obj.
39 void intel_uc_fw_fetch(struct drm_i915_private
*dev_priv
,
40 struct intel_uc_fw
*uc_fw
)
42 struct pci_dev
*pdev
= dev_priv
->drm
.pdev
;
43 struct drm_i915_gem_object
*obj
;
44 const struct firmware
*fw
= NULL
;
45 struct uc_css_header
*css
;
50 dev_info(dev_priv
->drm
.dev
,
51 "%s: No firmware was defined for %s!\n",
52 intel_uc_fw_type_repr(uc_fw
->type
),
53 intel_platform_name(INTEL_INFO(dev_priv
)->platform
));
57 DRM_DEBUG_DRIVER("%s fw fetch %s\n",
58 intel_uc_fw_type_repr(uc_fw
->type
), uc_fw
->path
);
60 uc_fw
->fetch_status
= INTEL_UC_FIRMWARE_PENDING
;
61 DRM_DEBUG_DRIVER("%s fw fetch %s\n",
62 intel_uc_fw_type_repr(uc_fw
->type
),
63 intel_uc_fw_status_repr(uc_fw
->fetch_status
));
65 err
= request_firmware(&fw
, uc_fw
->path
, &pdev
->dev
);
67 DRM_DEBUG_DRIVER("%s fw request_firmware err=%d\n",
68 intel_uc_fw_type_repr(uc_fw
->type
), err
);
72 DRM_DEBUG_DRIVER("%s fw size %zu ptr %p\n",
73 intel_uc_fw_type_repr(uc_fw
->type
), fw
->size
, fw
);
75 /* Check the size of the blob before examining buffer contents */
76 if (fw
->size
< sizeof(struct uc_css_header
)) {
77 DRM_WARN("%s: Unexpected firmware size (%zu, min %zu)\n",
78 intel_uc_fw_type_repr(uc_fw
->type
),
79 fw
->size
, sizeof(struct uc_css_header
));
84 css
= (struct uc_css_header
*)fw
->data
;
86 /* Firmware bits always start from header */
87 uc_fw
->header_offset
= 0;
88 uc_fw
->header_size
= (css
->header_size_dw
- css
->modulus_size_dw
-
89 css
->key_size_dw
- css
->exponent_size_dw
) *
92 if (uc_fw
->header_size
!= sizeof(struct uc_css_header
)) {
93 DRM_WARN("%s: Mismatched firmware header definition\n",
94 intel_uc_fw_type_repr(uc_fw
->type
));
100 uc_fw
->ucode_offset
= uc_fw
->header_offset
+ uc_fw
->header_size
;
101 uc_fw
->ucode_size
= (css
->size_dw
- css
->header_size_dw
) * sizeof(u32
);
104 if (css
->key_size_dw
!= UOS_RSA_SCRATCH_COUNT
) {
105 DRM_WARN("%s: Mismatched firmware RSA key size (%u)\n",
106 intel_uc_fw_type_repr(uc_fw
->type
), css
->key_size_dw
);
110 uc_fw
->rsa_offset
= uc_fw
->ucode_offset
+ uc_fw
->ucode_size
;
111 uc_fw
->rsa_size
= css
->key_size_dw
* sizeof(u32
);
113 /* At least, it should have header, uCode and RSA. Size of all three. */
114 size
= uc_fw
->header_size
+ uc_fw
->ucode_size
+ uc_fw
->rsa_size
;
115 if (fw
->size
< size
) {
116 DRM_WARN("%s: Truncated firmware (%zu, expected %zu)\n",
117 intel_uc_fw_type_repr(uc_fw
->type
), fw
->size
, size
);
123 * The GuC firmware image has the version number embedded at a
124 * well-known offset within the firmware blob; note that major / minor
125 * version are TWO bytes each (i.e. u16), although all pointers and
126 * offsets are defined in terms of bytes (u8).
128 switch (uc_fw
->type
) {
129 case INTEL_UC_FW_TYPE_GUC
:
130 uc_fw
->major_ver_found
= css
->guc
.sw_version
>> 16;
131 uc_fw
->minor_ver_found
= css
->guc
.sw_version
& 0xFFFF;
134 case INTEL_UC_FW_TYPE_HUC
:
135 uc_fw
->major_ver_found
= css
->huc
.sw_version
>> 16;
136 uc_fw
->minor_ver_found
= css
->huc
.sw_version
& 0xFFFF;
140 MISSING_CASE(uc_fw
->type
);
144 DRM_DEBUG_DRIVER("%s fw version %u.%u (wanted %u.%u)\n",
145 intel_uc_fw_type_repr(uc_fw
->type
),
146 uc_fw
->major_ver_found
, uc_fw
->minor_ver_found
,
147 uc_fw
->major_ver_wanted
, uc_fw
->minor_ver_wanted
);
149 if (uc_fw
->major_ver_wanted
== 0 && uc_fw
->minor_ver_wanted
== 0) {
150 DRM_NOTE("%s: Skipping firmware version check\n",
151 intel_uc_fw_type_repr(uc_fw
->type
));
152 } else if (uc_fw
->major_ver_found
!= uc_fw
->major_ver_wanted
||
153 uc_fw
->minor_ver_found
< uc_fw
->minor_ver_wanted
) {
154 DRM_NOTE("%s: Wrong firmware version (%u.%u, required %u.%u)\n",
155 intel_uc_fw_type_repr(uc_fw
->type
),
156 uc_fw
->major_ver_found
, uc_fw
->minor_ver_found
,
157 uc_fw
->major_ver_wanted
, uc_fw
->minor_ver_wanted
);
162 obj
= i915_gem_object_create_from_data(dev_priv
, fw
->data
, fw
->size
);
165 DRM_DEBUG_DRIVER("%s fw object_create err=%d\n",
166 intel_uc_fw_type_repr(uc_fw
->type
), err
);
171 uc_fw
->size
= fw
->size
;
172 uc_fw
->fetch_status
= INTEL_UC_FIRMWARE_SUCCESS
;
173 DRM_DEBUG_DRIVER("%s fw fetch %s\n",
174 intel_uc_fw_type_repr(uc_fw
->type
),
175 intel_uc_fw_status_repr(uc_fw
->fetch_status
));
177 release_firmware(fw
);
181 uc_fw
->fetch_status
= INTEL_UC_FIRMWARE_FAIL
;
182 DRM_DEBUG_DRIVER("%s fw fetch %s\n",
183 intel_uc_fw_type_repr(uc_fw
->type
),
184 intel_uc_fw_status_repr(uc_fw
->fetch_status
));
186 DRM_WARN("%s: Failed to fetch firmware %s (error %d)\n",
187 intel_uc_fw_type_repr(uc_fw
->type
), uc_fw
->path
, err
);
188 DRM_INFO("%s: Firmware can be downloaded from %s\n",
189 intel_uc_fw_type_repr(uc_fw
->type
), INTEL_UC_FIRMWARE_URL
);
191 release_firmware(fw
); /* OK even if fw is NULL */
195 * intel_uc_fw_upload - load uC firmware using custom loader
196 * @uc_fw: uC firmware
197 * @xfer: custom uC firmware loader function
199 * Loads uC firmware using custom loader and updates internal flags.
201 * Return: 0 on success, non-zero on failure.
203 int intel_uc_fw_upload(struct intel_uc_fw
*uc_fw
,
204 int (*xfer
)(struct intel_uc_fw
*uc_fw
,
205 struct i915_vma
*vma
))
207 struct i915_vma
*vma
;
211 DRM_DEBUG_DRIVER("%s fw load %s\n",
212 intel_uc_fw_type_repr(uc_fw
->type
), uc_fw
->path
);
214 if (uc_fw
->fetch_status
!= INTEL_UC_FIRMWARE_SUCCESS
)
217 uc_fw
->load_status
= INTEL_UC_FIRMWARE_PENDING
;
218 DRM_DEBUG_DRIVER("%s fw load %s\n",
219 intel_uc_fw_type_repr(uc_fw
->type
),
220 intel_uc_fw_status_repr(uc_fw
->load_status
));
222 /* Pin object with firmware */
223 err
= i915_gem_object_set_to_gtt_domain(uc_fw
->obj
, false);
225 DRM_DEBUG_DRIVER("%s fw set-domain err=%d\n",
226 intel_uc_fw_type_repr(uc_fw
->type
), err
);
230 ggtt_pin_bias
= to_i915(uc_fw
->obj
->base
.dev
)->ggtt
.pin_bias
;
231 vma
= i915_gem_object_ggtt_pin(uc_fw
->obj
, NULL
, 0, 0,
232 PIN_OFFSET_BIAS
| ggtt_pin_bias
);
235 DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n",
236 intel_uc_fw_type_repr(uc_fw
->type
), err
);
240 /* Call custom loader */
241 err
= xfer(uc_fw
, vma
);
244 * We keep the object pages for reuse during resume. But we can unpin it
245 * now that DMA has completed, so it doesn't continue to take up space.
252 uc_fw
->load_status
= INTEL_UC_FIRMWARE_SUCCESS
;
253 DRM_DEBUG_DRIVER("%s fw load %s\n",
254 intel_uc_fw_type_repr(uc_fw
->type
),
255 intel_uc_fw_status_repr(uc_fw
->load_status
));
257 DRM_INFO("%s: Loaded firmware %s (version %u.%u)\n",
258 intel_uc_fw_type_repr(uc_fw
->type
),
260 uc_fw
->major_ver_found
, uc_fw
->minor_ver_found
);
265 uc_fw
->load_status
= INTEL_UC_FIRMWARE_FAIL
;
266 DRM_DEBUG_DRIVER("%s fw load %s\n",
267 intel_uc_fw_type_repr(uc_fw
->type
),
268 intel_uc_fw_status_repr(uc_fw
->load_status
));
270 DRM_WARN("%s: Failed to load firmware %s (error %d)\n",
271 intel_uc_fw_type_repr(uc_fw
->type
), uc_fw
->path
, err
);
277 * intel_uc_fw_fini - cleanup uC firmware
279 * @uc_fw: uC firmware
281 * Cleans up uC firmware by releasing the firmware GEM obj.
283 void intel_uc_fw_fini(struct intel_uc_fw
*uc_fw
)
285 struct drm_i915_gem_object
*obj
;
287 obj
= fetch_and_zero(&uc_fw
->obj
);
289 i915_gem_object_put(obj
);
291 uc_fw
->fetch_status
= INTEL_UC_FIRMWARE_NONE
;
295 * intel_uc_fw_dump - dump information about uC firmware
296 * @uc_fw: uC firmware
297 * @p: the &drm_printer
299 * Pretty printer for uC firmware.
301 void intel_uc_fw_dump(const struct intel_uc_fw
*uc_fw
, struct drm_printer
*p
)
303 drm_printf(p
, "%s firmware: %s\n",
304 intel_uc_fw_type_repr(uc_fw
->type
), uc_fw
->path
);
305 drm_printf(p
, "\tstatus: fetch %s, load %s\n",
306 intel_uc_fw_status_repr(uc_fw
->fetch_status
),
307 intel_uc_fw_status_repr(uc_fw
->load_status
));
308 drm_printf(p
, "\tversion: wanted %u.%u, found %u.%u\n",
309 uc_fw
->major_ver_wanted
, uc_fw
->minor_ver_wanted
,
310 uc_fw
->major_ver_found
, uc_fw
->minor_ver_found
);
311 drm_printf(p
, "\theader: offset %u, size %u\n",
312 uc_fw
->header_offset
, uc_fw
->header_size
);
313 drm_printf(p
, "\tuCode: offset %u, size %u\n",
314 uc_fw
->ucode_offset
, uc_fw
->ucode_size
);
315 drm_printf(p
, "\tRSA: offset %u, size %u\n",
316 uc_fw
->rsa_offset
, uc_fw
->rsa_size
);