File: | dev/pci/drm/i915/gt/uc/intel_uc_fw.c |
Warning: | line 233, column 27 Value stored to 'i915' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright © 2016-2019 Intel Corporation |
4 | */ |
5 | |
6 | #include <linux/bitfield.h> |
7 | #include <linux/firmware.h> |
8 | #include <drm/drm_print.h> |
9 | |
10 | #include "intel_uc_fw.h" |
11 | #include "intel_uc_fw_abi.h" |
12 | #include "i915_drv.h" |
13 | |
14 | static inline struct intel_gt * |
15 | ____uc_fw_to_gt(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type) |
16 | { |
17 | if (type == INTEL_UC_FW_TYPE_GUC) |
18 | return container_of(uc_fw, struct intel_gt, uc.guc.fw)({ const __typeof( ((struct intel_gt *)0)->uc.guc.fw ) *__mptr = (uc_fw); (struct intel_gt *)( (char *)__mptr - __builtin_offsetof (struct intel_gt, uc.guc.fw) );}); |
19 | |
20 | GEM_BUG_ON(type != INTEL_UC_FW_TYPE_HUC)((void)0); |
21 | return container_of(uc_fw, struct intel_gt, uc.huc.fw)({ const __typeof( ((struct intel_gt *)0)->uc.huc.fw ) *__mptr = (uc_fw); (struct intel_gt *)( (char *)__mptr - __builtin_offsetof (struct intel_gt, uc.huc.fw) );}); |
22 | } |
23 | |
24 | static inline struct intel_gt *__uc_fw_to_gt(struct intel_uc_fw *uc_fw) |
25 | { |
26 | GEM_BUG_ON(uc_fw->status == INTEL_UC_FIRMWARE_UNINITIALIZED)((void)0); |
27 | return ____uc_fw_to_gt(uc_fw, uc_fw->type); |
28 | } |
29 | |
30 | #ifdef CONFIG_DRM_I915_DEBUG_GUC |
31 | void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, |
32 | enum intel_uc_fw_status status) |
33 | { |
34 | uc_fw->__status = status; |
35 | drm_dbg(&__uc_fw_to_gt(uc_fw)->i915->drm,drm_dev_dbg((&__uc_fw_to_gt(uc_fw)->i915->drm)-> dev, DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr (uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw ->path : intel_uc_fw_status_repr(status)) |
36 | "%s firmware -> %s\n",drm_dev_dbg((&__uc_fw_to_gt(uc_fw)->i915->drm)-> dev, DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr (uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw ->path : intel_uc_fw_status_repr(status)) |
37 | intel_uc_fw_type_repr(uc_fw->type),drm_dev_dbg((&__uc_fw_to_gt(uc_fw)->i915->drm)-> dev, DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr (uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw ->path : intel_uc_fw_status_repr(status)) |
38 | status == INTEL_UC_FIRMWARE_SELECTED ?drm_dev_dbg((&__uc_fw_to_gt(uc_fw)->i915->drm)-> dev, DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr (uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw ->path : intel_uc_fw_status_repr(status)) |
39 | uc_fw->path : intel_uc_fw_status_repr(status))drm_dev_dbg((&__uc_fw_to_gt(uc_fw)->i915->drm)-> dev, DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr (uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw ->path : intel_uc_fw_status_repr(status)); |
40 | } |
41 | #endif |
42 | |
43 | /* |
44 | * List of required GuC and HuC binaries per-platform. |
45 | * Must be ordered based on platform + revid, from newer to older. |
46 | * |
47 | * TGL 35.2 is interface-compatible with 33.0 for previous Gens. The deltas |
48 | * between 33.0 and 35.2 are only related to new additions to support new Gen12 |
49 | * features. |
50 | * |
51 | * Note that RKL uses the same firmware as TGL. |
52 | */ |
53 | #define INTEL_UC_FIRMWARE_DEFS(fw_def, guc_def, huc_def)fw_def(ROCKETLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 5, 0)) fw_def(TIGERLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def( tgl, 7, 5, 0)) fw_def(ELKHARTLAKE, 0, guc_def(ehl, 33, 0, 4), huc_def(ehl, 9, 0, 0)) fw_def(ICELAKE, 0, guc_def(icl, 33, 0 , 0), huc_def(icl, 9, 0, 0)) fw_def(COMETLAKE, 5, guc_def(cml , 33, 0, 0), huc_def(cml, 4, 0, 0)) fw_def(COFFEELAKE, 0, guc_def (kbl, 33, 0, 0), huc_def(kbl, 4, 0, 0)) fw_def(GEMINILAKE, 0, guc_def(glk, 33, 0, 0), huc_def(glk, 4, 0, 0)) fw_def(KABYLAKE , 0, guc_def(kbl, 33, 0, 0), huc_def(kbl, 4, 0, 0)) fw_def(BROXTON , 0, guc_def(bxt, 33, 0, 0), huc_def(bxt, 2, 0, 0)) fw_def(SKYLAKE , 0, guc_def(skl, 33, 0, 0), huc_def(skl, 2, 0, 0)) \ |
54 | fw_def(ROCKETLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 5, 0)) \ |
55 | fw_def(TIGERLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 5, 0)) \ |
56 | fw_def(ELKHARTLAKE, 0, guc_def(ehl, 33, 0, 4), huc_def(ehl, 9, 0, 0)) \ |
57 | fw_def(ICELAKE, 0, guc_def(icl, 33, 0, 0), huc_def(icl, 9, 0, 0)) \ |
58 | fw_def(COMETLAKE, 5, guc_def(cml, 33, 0, 0), huc_def(cml, 4, 0, 0)) \ |
59 | fw_def(COFFEELAKE, 0, guc_def(kbl, 33, 0, 0), huc_def(kbl, 4, 0, 0)) \ |
60 | fw_def(GEMINILAKE, 0, guc_def(glk, 33, 0, 0), huc_def(glk, 4, 0, 0)) \ |
61 | fw_def(KABYLAKE, 0, guc_def(kbl, 33, 0, 0), huc_def(kbl, 4, 0, 0)) \ |
62 | fw_def(BROXTON, 0, guc_def(bxt, 33, 0, 0), huc_def(bxt, 2, 0, 0)) \ |
63 | fw_def(SKYLAKE, 0, guc_def(skl, 33, 0, 0), huc_def(skl, 2, 0, 0)) |
64 | |
65 | #define __MAKE_UC_FW_PATH(prefix_, name_, major_, minor_, patch_)"i915/" "prefix_" name_ "major_" "." "minor_" "." "patch_" ".bin" \ |
66 | "i915/" \ |
67 | __stringify(prefix_)"prefix_" name_ \ |
68 | __stringify(major_)"major_" "." \ |
69 | __stringify(minor_)"minor_" "." \ |
70 | __stringify(patch_)"patch_" ".bin" |
71 | |
72 | #define MAKE_GUC_FW_PATH(prefix_, major_, minor_, patch_)"i915/" "prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin" \ |
73 | __MAKE_UC_FW_PATH(prefix_, "_guc_", major_, minor_, patch_)"i915/" "prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin" |
74 | |
75 | #define MAKE_HUC_FW_PATH(prefix_, major_, minor_, bld_num_)"i915/" "prefix_" "_huc_" "major_" "." "minor_" "." "bld_num_" ".bin" \ |
76 | __MAKE_UC_FW_PATH(prefix_, "_huc_", major_, minor_, bld_num_)"i915/" "prefix_" "_huc_" "major_" "." "minor_" "." "bld_num_" ".bin" |
77 | |
78 | /* All blobs need to be declared via MODULE_FIRMWARE() */ |
79 | #define INTEL_UC_MODULE_FW(platform_, revid_, guc_, huc_); ; \ |
80 | MODULE_FIRMWARE(guc_); \ |
81 | MODULE_FIRMWARE(huc_); |
82 | |
83 | INTEL_UC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH, MAKE_HUC_FW_PATH); ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; |
84 | |
85 | /* The below structs and macros are used to iterate across the list of blobs */ |
86 | struct __packed__attribute__((__packed__)) uc_fw_blob { |
87 | u8 major; |
88 | u8 minor; |
89 | const char *path; |
90 | }; |
91 | |
92 | #define UC_FW_BLOB(major_, minor_, path_){ .major = major_, .minor = minor_, .path = path_ } \ |
93 | { .major = major_, .minor = minor_, .path = path_ } |
94 | |
95 | #define GUC_FW_BLOB(prefix_, major_, minor_, patch_){ .major = major_, .minor = minor_, .path = "i915/" "prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin" } \ |
96 | UC_FW_BLOB(major_, minor_, \{ .major = major_, .minor = minor_, .path = "i915/" "prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin" } |
97 | MAKE_GUC_FW_PATH(prefix_, major_, minor_, patch_)){ .major = major_, .minor = minor_, .path = "i915/" "prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin" } |
98 | |
99 | #define HUC_FW_BLOB(prefix_, major_, minor_, bld_num_){ .major = major_, .minor = minor_, .path = "i915/" "prefix_" "_huc_" "major_" "." "minor_" "." "bld_num_" ".bin" } \ |
100 | UC_FW_BLOB(major_, minor_, \{ .major = major_, .minor = minor_, .path = "i915/" "prefix_" "_huc_" "major_" "." "minor_" "." "bld_num_" ".bin" } |
101 | MAKE_HUC_FW_PATH(prefix_, major_, minor_, bld_num_)){ .major = major_, .minor = minor_, .path = "i915/" "prefix_" "_huc_" "major_" "." "minor_" "." "bld_num_" ".bin" } |
102 | |
103 | struct __packed__attribute__((__packed__)) uc_fw_platform_requirement { |
104 | enum intel_platform p; |
105 | u8 rev; /* first platform rev using this FW */ |
106 | const struct uc_fw_blob blobs[INTEL_UC_FW_NUM_TYPES2]; |
107 | }; |
108 | |
109 | #define MAKE_FW_LIST(platform_, revid_, guc_, huc_){ .p = INTEL_platform_, .rev = revid_, .blobs[INTEL_UC_FW_TYPE_GUC ] = guc_, .blobs[INTEL_UC_FW_TYPE_HUC] = huc_, }, \ |
110 | { \ |
111 | .p = INTEL_##platform_, \ |
112 | .rev = revid_, \ |
113 | .blobs[INTEL_UC_FW_TYPE_GUC] = guc_, \ |
114 | .blobs[INTEL_UC_FW_TYPE_HUC] = huc_, \ |
115 | }, |
116 | |
117 | static void |
118 | __uc_fw_auto_select(struct drm_i915_privateinteldrm_softc *i915, struct intel_uc_fw *uc_fw) |
119 | { |
120 | static const struct uc_fw_platform_requirement fw_blobs[] = { |
121 | INTEL_UC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, HUC_FW_BLOB){ .p = INTEL_ROCKETLAKE, .rev = 0, .blobs[INTEL_UC_FW_TYPE_GUC ] = { .major = 35, .minor = 2, .path = "i915/" "tgl" "_guc_" "35" "." "2" "." "0" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC] = { . major = 7, .minor = 5, .path = "i915/" "tgl" "_huc_" "7" "." "5" "." "0" ".bin" }, }, { .p = INTEL_TIGERLAKE, .rev = 0, .blobs [INTEL_UC_FW_TYPE_GUC] = { .major = 35, .minor = 2, .path = "i915/" "tgl" "_guc_" "35" "." "2" "." "0" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC ] = { .major = 7, .minor = 5, .path = "i915/" "tgl" "_huc_" "7" "." "5" "." "0" ".bin" }, }, { .p = INTEL_ELKHARTLAKE, .rev = 0, .blobs[INTEL_UC_FW_TYPE_GUC] = { .major = 33, .minor = 0, .path = "i915/" "ehl" "_guc_" "33" "." "0" "." "4" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC] = { .major = 9, .minor = 0, .path = "i915/" "ehl" "_huc_" "9" "." "0" "." "0" ".bin" }, }, { . p = INTEL_ICELAKE, .rev = 0, .blobs[INTEL_UC_FW_TYPE_GUC] = { .major = 33, .minor = 0, .path = "i915/" "icl" "_guc_" "33" "." "0" "." "0" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC] = { .major = 9, .minor = 0, .path = "i915/" "icl" "_huc_" "9" "." "0" "." "0" ".bin" }, }, { .p = INTEL_COMETLAKE, .rev = 5, .blobs[INTEL_UC_FW_TYPE_GUC ] = { .major = 33, .minor = 0, .path = "i915/" "cml" "_guc_" "33" "." "0" "." "0" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC] = { . major = 4, .minor = 0, .path = "i915/" "cml" "_huc_" "4" "." "0" "." "0" ".bin" }, }, { .p = INTEL_COFFEELAKE, .rev = 0, .blobs [INTEL_UC_FW_TYPE_GUC] = { .major = 33, .minor = 0, .path = "i915/" "kbl" "_guc_" "33" "." "0" "." "0" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC ] = { .major = 4, .minor = 0, .path = "i915/" "kbl" "_huc_" "4" "." "0" "." "0" ".bin" }, }, { .p = INTEL_GEMINILAKE, .rev = 0, .blobs[INTEL_UC_FW_TYPE_GUC] = { .major = 33, .minor = 0, .path = "i915/" "glk" "_guc_" "33" "." "0" "." "0" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC] = { .major = 4, .minor = 0, .path = "i915/" "glk" "_huc_" "4" "." "0" "." "0" ".bin" }, }, { . p = INTEL_KABYLAKE, .rev = 0, .blobs[INTEL_UC_FW_TYPE_GUC] = { .major = 33, .minor = 0, .path = "i915/" "kbl" "_guc_" "33" "." "0" "." "0" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC] = { .major = 4, .minor = 0, .path = "i915/" "kbl" "_huc_" "4" "." "0" "." "0" ".bin" }, }, { .p = INTEL_BROXTON, .rev = 0, .blobs[INTEL_UC_FW_TYPE_GUC ] = { .major = 33, .minor = 0, .path = "i915/" "bxt" "_guc_" "33" "." "0" "." "0" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC] = { . major = 2, .minor = 0, .path = "i915/" "bxt" "_huc_" "2" "." "0" "." "0" ".bin" }, }, { .p = INTEL_SKYLAKE, .rev = 0, .blobs[ INTEL_UC_FW_TYPE_GUC] = { .major = 33, .minor = 0, .path = "i915/" "skl" "_guc_" "33" "." "0" "." "0" ".bin" }, .blobs[INTEL_UC_FW_TYPE_HUC ] = { .major = 2, .minor = 0, .path = "i915/" "skl" "_huc_" "2" "." "0" "." "0" ".bin" }, }, |
122 | }; |
123 | enum intel_platform p = INTEL_INFO(i915)(&(i915)->__info)->platform; |
124 | u8 rev = INTEL_REVID(i915)((i915)->drm.pdev->revision); |
125 | int i; |
126 | |
127 | for (i = 0; i < ARRAY_SIZE(fw_blobs)(sizeof((fw_blobs)) / sizeof((fw_blobs)[0])) && p <= fw_blobs[i].p; i++) { |
128 | if (p == fw_blobs[i].p && rev >= fw_blobs[i].rev) { |
129 | const struct uc_fw_blob *blob = |
130 | &fw_blobs[i].blobs[uc_fw->type]; |
131 | uc_fw->path = blob->path; |
132 | uc_fw->major_ver_wanted = blob->major; |
133 | uc_fw->minor_ver_wanted = blob->minor; |
134 | break; |
135 | } |
136 | } |
137 | |
138 | /* make sure the list is ordered as expected */ |
139 | if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST)0) { |
140 | for (i = 1; i < ARRAY_SIZE(fw_blobs)(sizeof((fw_blobs)) / sizeof((fw_blobs)[0])); i++) { |
141 | if (fw_blobs[i].p < fw_blobs[i - 1].p) |
142 | continue; |
143 | |
144 | if (fw_blobs[i].p == fw_blobs[i - 1].p && |
145 | fw_blobs[i].rev < fw_blobs[i - 1].rev) |
146 | continue; |
147 | |
148 | pr_err("invalid FW blob order: %s r%u comes before %s r%u\n",printk("\0013" "invalid FW blob order: %s r%u comes before %s r%u\n" , intel_platform_name(fw_blobs[i - 1].p), fw_blobs[i - 1].rev , intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev) |
149 | intel_platform_name(fw_blobs[i - 1].p),printk("\0013" "invalid FW blob order: %s r%u comes before %s r%u\n" , intel_platform_name(fw_blobs[i - 1].p), fw_blobs[i - 1].rev , intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev) |
150 | fw_blobs[i - 1].rev,printk("\0013" "invalid FW blob order: %s r%u comes before %s r%u\n" , intel_platform_name(fw_blobs[i - 1].p), fw_blobs[i - 1].rev , intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev) |
151 | intel_platform_name(fw_blobs[i].p),printk("\0013" "invalid FW blob order: %s r%u comes before %s r%u\n" , intel_platform_name(fw_blobs[i - 1].p), fw_blobs[i - 1].rev , intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev) |
152 | fw_blobs[i].rev)printk("\0013" "invalid FW blob order: %s r%u comes before %s r%u\n" , intel_platform_name(fw_blobs[i - 1].p), fw_blobs[i - 1].rev , intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev); |
153 | |
154 | uc_fw->path = NULL((void *)0); |
155 | } |
156 | } |
157 | |
158 | /* We don't want to enable GuC/HuC on pre-Gen11 by default */ |
159 | if (i915->params.enable_guc == -1 && p < INTEL_ICELAKE) |
160 | uc_fw->path = NULL((void *)0); |
161 | } |
162 | |
163 | static const char *__override_guc_firmware_path(struct drm_i915_privateinteldrm_softc *i915) |
164 | { |
165 | if (i915->params.enable_guc & (ENABLE_GUC_SUBMISSION(1UL << (0)) | |
166 | ENABLE_GUC_LOAD_HUC(1UL << (1)))) |
167 | return i915->params.guc_firmware_path; |
168 | return ""; |
169 | } |
170 | |
171 | static const char *__override_huc_firmware_path(struct drm_i915_privateinteldrm_softc *i915) |
172 | { |
173 | if (i915->params.enable_guc & ENABLE_GUC_LOAD_HUC(1UL << (1))) |
174 | return i915->params.huc_firmware_path; |
175 | return ""; |
176 | } |
177 | |
178 | static void __uc_fw_user_override(struct drm_i915_privateinteldrm_softc *i915, struct intel_uc_fw *uc_fw) |
179 | { |
180 | const char *path = NULL((void *)0); |
181 | |
182 | switch (uc_fw->type) { |
183 | case INTEL_UC_FW_TYPE_GUC: |
184 | path = __override_guc_firmware_path(i915); |
185 | break; |
186 | case INTEL_UC_FW_TYPE_HUC: |
187 | path = __override_huc_firmware_path(i915); |
188 | break; |
189 | } |
190 | |
191 | if (unlikely(path)__builtin_expect(!!(path), 0)) { |
192 | uc_fw->path = path; |
193 | uc_fw->user_overridden = true1; |
194 | } |
195 | } |
196 | |
197 | /** |
198 | * intel_uc_fw_init_early - initialize the uC object and select the firmware |
199 | * @uc_fw: uC firmware |
200 | * @type: type of uC |
201 | * |
202 | * Initialize the state of our uC object and relevant tracking and select the |
203 | * firmware to fetch and load. |
204 | */ |
205 | void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw, |
206 | enum intel_uc_fw_type type) |
207 | { |
208 | struct drm_i915_privateinteldrm_softc *i915 = ____uc_fw_to_gt(uc_fw, type)->i915; |
209 | |
210 | /* |
211 | * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status |
212 | * before we're looked at the HW caps to see if we have uc support |
213 | */ |
214 | BUILD_BUG_ON(INTEL_UC_FIRMWARE_UNINITIALIZED)extern char _ctassert[(!(INTEL_UC_FIRMWARE_UNINITIALIZED)) ? 1 : -1 ] __attribute__((__unused__)); |
215 | GEM_BUG_ON(uc_fw->status)((void)0); |
216 | GEM_BUG_ON(uc_fw->path)((void)0); |
217 | |
218 | uc_fw->type = type; |
219 | |
220 | if (HAS_GT_UC(i915)((&(i915)->__info)->has_gt_uc)) { |
221 | __uc_fw_auto_select(i915, uc_fw); |
222 | __uc_fw_user_override(i915, uc_fw); |
223 | } |
224 | |
225 | intel_uc_fw_change_status(uc_fw, uc_fw->path ? *uc_fw->path ? |
226 | INTEL_UC_FIRMWARE_SELECTED : |
227 | INTEL_UC_FIRMWARE_DISABLED : |
228 | INTEL_UC_FIRMWARE_NOT_SUPPORTED); |
229 | } |
230 | |
231 | static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, int e) |
232 | { |
233 | struct drm_i915_privateinteldrm_softc *i915 = __uc_fw_to_gt(uc_fw)->i915; |
Value stored to 'i915' during its initialization is never read | |
234 | bool_Bool user = e == -EINVAL22; |
235 | |
236 | if (i915_inject_probe_error(i915, e)({ ((void)0); 0; })) { |
237 | /* non-existing blob */ |
238 | uc_fw->path = "<invalid>"; |
239 | uc_fw->user_overridden = user; |
240 | } else if (i915_inject_probe_error(i915, e)({ ((void)0); 0; })) { |
241 | /* require next major version */ |
242 | uc_fw->major_ver_wanted += 1; |
243 | uc_fw->minor_ver_wanted = 0; |
244 | uc_fw->user_overridden = user; |
245 | } else if (i915_inject_probe_error(i915, e)({ ((void)0); 0; })) { |
246 | /* require next minor version */ |
247 | uc_fw->minor_ver_wanted += 1; |
248 | uc_fw->user_overridden = user; |
249 | } else if (uc_fw->major_ver_wanted && |
250 | i915_inject_probe_error(i915, e)({ ((void)0); 0; })) { |
251 | /* require prev major version */ |
252 | uc_fw->major_ver_wanted -= 1; |
253 | uc_fw->minor_ver_wanted = 0; |
254 | uc_fw->user_overridden = user; |
255 | } else if (uc_fw->minor_ver_wanted && |
256 | i915_inject_probe_error(i915, e)({ ((void)0); 0; })) { |
257 | /* require prev minor version - hey, this should work! */ |
258 | uc_fw->minor_ver_wanted -= 1; |
259 | uc_fw->user_overridden = user; |
260 | } else if (user && i915_inject_probe_error(i915, e)({ ((void)0); 0; })) { |
261 | /* officially unsupported platform */ |
262 | uc_fw->major_ver_wanted = 0; |
263 | uc_fw->minor_ver_wanted = 0; |
264 | uc_fw->user_overridden = true1; |
265 | } |
266 | } |
267 | |
268 | /** |
269 | * intel_uc_fw_fetch - fetch uC firmware |
270 | * @uc_fw: uC firmware |
271 | * |
272 | * Fetch uC firmware into GEM obj. |
273 | * |
274 | * Return: 0 on success, a negative errno code on failure. |
275 | */ |
276 | int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) |
277 | { |
278 | struct drm_i915_privateinteldrm_softc *i915 = __uc_fw_to_gt(uc_fw)->i915; |
279 | struct device *dev = i915->drm.dev; |
280 | struct drm_i915_gem_object *obj; |
281 | const struct firmware *fw = NULL((void *)0); |
282 | struct uc_css_header *css; |
283 | size_t size; |
284 | int err; |
285 | |
286 | GEM_BUG_ON(!i915->wopcm.size)((void)0); |
287 | GEM_BUG_ON(!intel_uc_fw_is_enabled(uc_fw))((void)0); |
288 | |
289 | err = i915_inject_probe_error(i915, -ENXIO)({ ((void)0); 0; }); |
290 | if (err) |
291 | goto fail; |
292 | |
293 | __force_fw_fetch_failures(uc_fw, -EINVAL22); |
294 | __force_fw_fetch_failures(uc_fw, -ESTALE70); |
295 | |
296 | err = request_firmware(&fw, uc_fw->path, dev); |
297 | if (err) |
298 | goto fail; |
299 | |
300 | /* Check the size of the blob before examining buffer contents */ |
301 | if (unlikely(fw->size < sizeof(struct uc_css_header))__builtin_expect(!!(fw->size < sizeof(struct uc_css_header )), 0)) { |
302 | drm_warn(&i915->drm, "%s firmware %s: invalid size: %zu < %zu\n",printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: invalid size: %zu < %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, sizeof(struct uc_css_header )) |
303 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: invalid size: %zu < %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, sizeof(struct uc_css_header )) |
304 | fw->size, sizeof(struct uc_css_header))printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: invalid size: %zu < %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, sizeof(struct uc_css_header )); |
305 | err = -ENODATA91; |
306 | goto fail; |
307 | } |
308 | |
309 | css = (struct uc_css_header *)fw->data; |
310 | |
311 | /* Check integrity of size values inside CSS header */ |
312 | size = (css->header_size_dw - css->key_size_dw - css->modulus_size_dw - |
313 | css->exponent_size_dw) * sizeof(u32); |
314 | if (unlikely(size != sizeof(struct uc_css_header))__builtin_expect(!!(size != sizeof(struct uc_css_header)), 0)) { |
315 | drm_warn(&i915->drm,printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: unexpected header size: %zu != %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, sizeof(struct uc_css_header )) |
316 | "%s firmware %s: unexpected header size: %zu != %zu\n",printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: unexpected header size: %zu != %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, sizeof(struct uc_css_header )) |
317 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: unexpected header size: %zu != %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, sizeof(struct uc_css_header )) |
318 | fw->size, sizeof(struct uc_css_header))printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: unexpected header size: %zu != %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, sizeof(struct uc_css_header )); |
319 | err = -EPROTO95; |
320 | goto fail; |
321 | } |
322 | |
323 | /* uCode size must calculated from other sizes */ |
324 | uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32); |
325 | |
326 | /* now RSA */ |
327 | if (unlikely(css->key_size_dw != UOS_RSA_SCRATCH_COUNT)__builtin_expect(!!(css->key_size_dw != 64), 0)) { |
328 | drm_warn(&i915->drm, "%s firmware %s: unexpected key size: %u != %u\n",printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: unexpected key size: %u != %u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, css->key_size_dw, 64) |
329 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: unexpected key size: %u != %u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, css->key_size_dw, 64) |
330 | css->key_size_dw, UOS_RSA_SCRATCH_COUNT)printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: unexpected key size: %u != %u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, css->key_size_dw, 64); |
331 | err = -EPROTO95; |
332 | goto fail; |
333 | } |
334 | uc_fw->rsa_size = css->key_size_dw * sizeof(u32); |
335 | |
336 | /* At least, it should have header, uCode and RSA. Size of all three. */ |
337 | size = sizeof(struct uc_css_header) + uc_fw->ucode_size + uc_fw->rsa_size; |
338 | if (unlikely(fw->size < size)__builtin_expect(!!(fw->size < size), 0)) { |
339 | drm_warn(&i915->drm, "%s firmware %s: invalid size: %zu < %zu\n",printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: invalid size: %zu < %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, size) |
340 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: invalid size: %zu < %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, size) |
341 | fw->size, size)printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: invalid size: %zu < %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, fw->size, size); |
342 | err = -ENOEXEC8; |
343 | goto fail; |
344 | } |
345 | |
346 | /* Sanity check whether this fw is not larger than whole WOPCM memory */ |
347 | size = __intel_uc_fw_get_upload_size(uc_fw); |
348 | if (unlikely(size >= i915->wopcm.size)__builtin_expect(!!(size >= i915->wopcm.size), 0)) { |
349 | drm_warn(&i915->drm, "%s firmware %s: invalid size: %zu > %zu\n",printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: invalid size: %zu > %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, size, (size_t)i915->wopcm .size) |
350 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: invalid size: %zu > %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, size, (size_t)i915->wopcm .size) |
351 | size, (size_t)i915->wopcm.size)printf("drm:pid%d:%s *WARNING* " "[drm] " "%s firmware %s: invalid size: %zu > %zu\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, size, (size_t)i915->wopcm .size); |
352 | err = -E2BIG7; |
353 | goto fail; |
354 | } |
355 | |
356 | /* Get version numbers from the CSS header */ |
357 | uc_fw->major_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,((typeof((0xFF << 16)))(((css->sw_version) & ((0xFF << 16))) >> (__builtin_ffsll((0xFF << 16)) - 1))) |
358 | css->sw_version)((typeof((0xFF << 16)))(((css->sw_version) & ((0xFF << 16))) >> (__builtin_ffsll((0xFF << 16)) - 1))); |
359 | uc_fw->minor_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MINOR,((typeof((0xFF << 8)))(((css->sw_version) & ((0xFF << 8))) >> (__builtin_ffsll((0xFF << 8)) - 1))) |
360 | css->sw_version)((typeof((0xFF << 8)))(((css->sw_version) & ((0xFF << 8))) >> (__builtin_ffsll((0xFF << 8)) - 1))); |
361 | |
362 | if (uc_fw->major_ver_found != uc_fw->major_ver_wanted || |
363 | uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) { |
364 | drm_notice(&i915->drm, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s: unexpected version: %u.%u != %u.%u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, uc_fw->major_ver_found, uc_fw ->minor_ver_found, uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted ) |
365 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s: unexpected version: %u.%u != %u.%u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, uc_fw->major_ver_found, uc_fw ->minor_ver_found, uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted ) |
366 | uc_fw->major_ver_found, uc_fw->minor_ver_found,printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s: unexpected version: %u.%u != %u.%u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, uc_fw->major_ver_found, uc_fw ->minor_ver_found, uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted ) |
367 | uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted)printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s: unexpected version: %u.%u != %u.%u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, uc_fw->major_ver_found, uc_fw ->minor_ver_found, uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted ); |
368 | if (!intel_uc_fw_is_overridden(uc_fw)) { |
369 | err = -ENOEXEC8; |
370 | goto fail; |
371 | } |
372 | } |
373 | |
374 | obj = i915_gem_object_create_shmem_from_data(i915, fw->data, fw->size); |
375 | if (IS_ERR(obj)) { |
376 | err = PTR_ERR(obj); |
377 | goto fail; |
378 | } |
379 | |
380 | uc_fw->obj = obj; |
381 | uc_fw->size = fw->size; |
382 | intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE); |
383 | |
384 | release_firmware(fw); |
385 | return 0; |
386 | |
387 | fail: |
388 | intel_uc_fw_change_status(uc_fw, err == -ENOENT2 ? |
389 | INTEL_UC_FIRMWARE_MISSING : |
390 | INTEL_UC_FIRMWARE_ERROR); |
391 | |
392 | drm_notice(&i915->drm, "%s firmware %s: fetch failed with error %d\n",printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s: fetch failed with error %d\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, err) |
393 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err)printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s: fetch failed with error %d\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), uc_fw->path, err); |
394 | #ifdef __linux__ |
395 | drm_info(&i915->drm, "%s firmware(s) can be downloaded from %s\n",do { } while(0) |
396 | intel_uc_fw_type_repr(uc_fw->type), INTEL_UC_FIRMWARE_URL)do { } while(0); |
397 | #endif |
398 | |
399 | release_firmware(fw); /* OK even if fw is NULL */ |
400 | return err; |
401 | } |
402 | |
403 | static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw) |
404 | { |
405 | struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; |
406 | struct drm_mm_node *node = &ggtt->uc_fw; |
407 | |
408 | GEM_BUG_ON(!drm_mm_node_allocated(node))((void)0); |
409 | GEM_BUG_ON(upper_32_bits(node->start))((void)0); |
410 | GEM_BUG_ON(upper_32_bits(node->start + node->size - 1))((void)0); |
411 | |
412 | return lower_32_bits(node->start)((u32)(node->start)); |
413 | } |
414 | |
415 | static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw) |
416 | { |
417 | struct drm_i915_gem_object *obj = uc_fw->obj; |
418 | struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; |
419 | struct i915_vma dummy = { |
420 | .node.start = uc_fw_ggtt_offset(uc_fw), |
421 | .node.size = obj->base.size, |
422 | .pages = obj->mm.pages, |
423 | .vm = &ggtt->vm, |
424 | }; |
425 | |
426 | GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj))((void)0); |
427 | GEM_BUG_ON(dummy.node.size > ggtt->uc_fw.size)((void)0); |
428 | |
429 | /* uc_fw->obj cache domains were not controlled across suspend */ |
430 | drm_clflush_sg(dummy.pages); |
431 | |
432 | ggtt->vm.insert_entries(&ggtt->vm, &dummy, I915_CACHE_NONE, 0); |
433 | } |
434 | |
435 | static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw) |
436 | { |
437 | struct drm_i915_gem_object *obj = uc_fw->obj; |
438 | struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt; |
439 | u64 start = uc_fw_ggtt_offset(uc_fw); |
440 | |
441 | ggtt->vm.clear_range(&ggtt->vm, start, obj->base.size); |
442 | } |
443 | |
444 | static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags) |
445 | { |
446 | struct intel_gt *gt = __uc_fw_to_gt(uc_fw); |
447 | struct intel_uncore *uncore = gt->uncore; |
448 | u64 offset; |
449 | int ret; |
450 | |
451 | ret = i915_inject_probe_error(gt->i915, -ETIMEDOUT)({ ((void)0); 0; }); |
452 | if (ret) |
453 | return ret; |
454 | |
455 | intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); |
456 | |
457 | /* Set the source address for the uCode */ |
458 | offset = uc_fw_ggtt_offset(uc_fw); |
459 | GEM_BUG_ON(upper_32_bits(offset) & 0xFFFF0000)((void)0); |
460 | intel_uncore_write_fw(uncore, DMA_ADDR_0_LOW, lower_32_bits(offset))__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc300 ) }), ((u32)(offset))); |
461 | intel_uncore_write_fw(uncore, DMA_ADDR_0_HIGH, upper_32_bits(offset))__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc304 ) }), ((u32)(((offset) >> 16) >> 16))); |
462 | |
463 | /* Set the DMA destination */ |
464 | intel_uncore_write_fw(uncore, DMA_ADDR_1_LOW, dst_offset)__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc308 ) }), dst_offset); |
465 | intel_uncore_write_fw(uncore, DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM)__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc30c ) }), (7 << 16)); |
466 | |
467 | /* |
468 | * Set the transfer size. The header plus uCode will be copied to WOPCM |
469 | * via DMA, excluding any other components |
470 | */ |
471 | intel_uncore_write_fw(uncore, DMA_COPY_SIZE,__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc310 ) }), sizeof(struct uc_css_header) + uc_fw->ucode_size) |
472 | sizeof(struct uc_css_header) + uc_fw->ucode_size)__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc310 ) }), sizeof(struct uc_css_header) + uc_fw->ucode_size); |
473 | |
474 | /* Start the DMA */ |
475 | intel_uncore_write_fw(uncore, DMA_CTRL,__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc314 ) }), ({ typeof(dma_flags | (1<<0)) _a = (dma_flags | ( 1<<0)); ({ if (__builtin_constant_p(_a)) do { } while ( 0); if (__builtin_constant_p(_a)) do { } while (0); if (__builtin_constant_p (_a) && __builtin_constant_p(_a)) do { } while (0); ( (_a) << 16 | (_a)); }); })) |
476 | _MASKED_BIT_ENABLE(dma_flags | START_DMA))__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc314 ) }), ({ typeof(dma_flags | (1<<0)) _a = (dma_flags | ( 1<<0)); ({ if (__builtin_constant_p(_a)) do { } while ( 0); if (__builtin_constant_p(_a)) do { } while (0); if (__builtin_constant_p (_a) && __builtin_constant_p(_a)) do { } while (0); ( (_a) << 16 | (_a)); }); })); |
477 | |
478 | /* Wait for DMA to finish */ |
479 | ret = intel_wait_for_register_fw(uncore, DMA_CTRL((const i915_reg_t){ .reg = (0xc314) }), START_DMA(1<<0), 0, 100); |
480 | if (ret) |
481 | drm_err(>->i915->drm, "DMA for %s fw failed, DMA_CTRL=%u\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMA for %s fw failed, DMA_CTRL=%u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), __raw_uncore_read32(uncore, ((const i915_reg_t ){ .reg = (0xc314) }))) |
482 | intel_uc_fw_type_repr(uc_fw->type),printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMA for %s fw failed, DMA_CTRL=%u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), __raw_uncore_read32(uncore, ((const i915_reg_t ){ .reg = (0xc314) }))) |
483 | intel_uncore_read_fw(uncore, DMA_CTRL))printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "DMA for %s fw failed, DMA_CTRL=%u\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__ , intel_uc_fw_type_repr (uc_fw->type), __raw_uncore_read32(uncore, ((const i915_reg_t ){ .reg = (0xc314) }))); |
484 | |
485 | /* Disable the bits once DMA is over */ |
486 | intel_uncore_write_fw(uncore, DMA_CTRL, _MASKED_BIT_DISABLE(dma_flags))__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc314 ) }), (({ if (__builtin_constant_p((dma_flags))) do { } while (0); if (__builtin_constant_p(0)) do { } while (0); if (__builtin_constant_p ((dma_flags)) && __builtin_constant_p(0)) do { } while (0); (((dma_flags)) << 16 | (0)); }))); |
487 | |
488 | intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL); |
489 | |
490 | return ret; |
491 | } |
492 | |
493 | /** |
494 | * intel_uc_fw_upload - load uC firmware using custom loader |
495 | * @uc_fw: uC firmware |
496 | * @dst_offset: destination offset |
497 | * @dma_flags: flags for flags for dma ctrl |
498 | * |
499 | * Loads uC firmware and updates internal flags. |
500 | * |
501 | * Return: 0 on success, non-zero on failure. |
502 | */ |
503 | int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags) |
504 | { |
505 | struct intel_gt *gt = __uc_fw_to_gt(uc_fw); |
506 | int err; |
507 | |
508 | /* make sure the status was cleared the last time we reset the uc */ |
509 | GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw))((void)0); |
510 | |
511 | err = i915_inject_probe_error(gt->i915, -ENOEXEC)({ ((void)0); 0; }); |
512 | if (err) |
513 | return err; |
514 | |
515 | if (!intel_uc_fw_is_loadable(uc_fw)) |
516 | return -ENOEXEC8; |
517 | |
518 | /* Call custom loader */ |
519 | uc_fw_bind_ggtt(uc_fw); |
520 | err = uc_fw_xfer(uc_fw, dst_offset, dma_flags); |
521 | uc_fw_unbind_ggtt(uc_fw); |
522 | if (err) |
523 | goto fail; |
524 | |
525 | intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_TRANSFERRED); |
526 | return 0; |
527 | |
528 | fail: |
529 | i915_probe_error(gt->i915, "Failed to load %s firmware %s (%d)\n",__i915_printk(gt->i915, 0 ? "\0017" : "\0013", "Failed to load %s firmware %s (%d)\n" , intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err) |
530 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,__i915_printk(gt->i915, 0 ? "\0017" : "\0013", "Failed to load %s firmware %s (%d)\n" , intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err) |
531 | err)__i915_printk(gt->i915, 0 ? "\0017" : "\0013", "Failed to load %s firmware %s (%d)\n" , intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err); |
532 | intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_FAIL); |
533 | return err; |
534 | } |
535 | |
536 | int intel_uc_fw_init(struct intel_uc_fw *uc_fw) |
537 | { |
538 | int err; |
539 | |
540 | /* this should happen before the load! */ |
541 | GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw))((void)0); |
542 | |
543 | if (!intel_uc_fw_is_available(uc_fw)) |
544 | return -ENOEXEC8; |
545 | |
546 | err = i915_gem_object_pin_pages(uc_fw->obj); |
547 | if (err) { |
548 | DRM_DEBUG_DRIVER("%s fw pin-pages err=%d\n",__drm_dbg(DRM_UT_DRIVER, "%s fw pin-pages err=%d\n", intel_uc_fw_type_repr (uc_fw->type), err) |
549 | intel_uc_fw_type_repr(uc_fw->type), err)__drm_dbg(DRM_UT_DRIVER, "%s fw pin-pages err=%d\n", intel_uc_fw_type_repr (uc_fw->type), err); |
550 | intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_FAIL); |
551 | } |
552 | |
553 | return err; |
554 | } |
555 | |
556 | void intel_uc_fw_fini(struct intel_uc_fw *uc_fw) |
557 | { |
558 | if (i915_gem_object_has_pinned_pages(uc_fw->obj)) |
559 | i915_gem_object_unpin_pages(uc_fw->obj); |
560 | |
561 | intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE); |
562 | } |
563 | |
564 | /** |
565 | * intel_uc_fw_cleanup_fetch - cleanup uC firmware |
566 | * @uc_fw: uC firmware |
567 | * |
568 | * Cleans up uC firmware by releasing the firmware GEM obj. |
569 | */ |
570 | void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw) |
571 | { |
572 | if (!intel_uc_fw_is_available(uc_fw)) |
573 | return; |
574 | |
575 | i915_gem_object_put(fetch_and_zero(&uc_fw->obj)({ typeof(*&uc_fw->obj) __T = *(&uc_fw->obj); * (&uc_fw->obj) = (typeof(*&uc_fw->obj))0; __T; } )); |
576 | |
577 | intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_SELECTED); |
578 | } |
579 | |
580 | /** |
581 | * intel_uc_fw_copy_rsa - copy fw RSA to buffer |
582 | * |
583 | * @uc_fw: uC firmware |
584 | * @dst: dst buffer |
585 | * @max_len: max number of bytes to copy |
586 | * |
587 | * Return: number of copied bytes. |
588 | */ |
589 | size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len) |
590 | { |
591 | STUB()do { printf("%s: stub\n", __func__); } while(0); |
592 | return 0; |
593 | #ifdef notyet |
594 | struct sg_table *pages = uc_fw->obj->mm.pages; |
595 | u32 size = min_t(u32, uc_fw->rsa_size, max_len)({ u32 __min_a = (uc_fw->rsa_size); u32 __min_b = (max_len ); __min_a < __min_b ? __min_a : __min_b; }); |
596 | u32 offset = sizeof(struct uc_css_header) + uc_fw->ucode_size; |
597 | |
598 | GEM_BUG_ON(!intel_uc_fw_is_available(uc_fw))((void)0); |
599 | |
600 | return sg_pcopy_to_buffer(pages->sgl, pages->nents, dst, size, offset); |
601 | #endif |
602 | } |
603 | |
604 | /** |
605 | * intel_uc_fw_dump - dump information about uC firmware |
606 | * @uc_fw: uC firmware |
607 | * @p: the &drm_printer |
608 | * |
609 | * Pretty printer for uC firmware. |
610 | */ |
611 | void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p) |
612 | { |
613 | drm_printf(p, "%s firmware: %s\n", |
614 | intel_uc_fw_type_repr(uc_fw->type), uc_fw->path); |
615 | drm_printf(p, "\tstatus: %s\n", |
616 | intel_uc_fw_status_repr(uc_fw->status)); |
617 | drm_printf(p, "\tversion: wanted %u.%u, found %u.%u\n", |
618 | uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted, |
619 | uc_fw->major_ver_found, uc_fw->minor_ver_found); |
620 | drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size); |
621 | drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size); |
622 | } |