Bug Summary

File:dev/pci/drm/i915/gt/uc/intel_uc_fw.c
Warning:line 423, column 27
Value stored to 'i915' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name intel_uc_fw.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/drm/i915/gt/uc/intel_uc_fw.c
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 <linux/highmem.h>
9
10#include <drm/drm_cache.h>
11#include <drm/drm_print.h>
12
13#include "gem/i915_gem_lmem.h"
14#include "intel_uc_fw.h"
15#include "intel_uc_fw_abi.h"
16#include "i915_drv.h"
17#include "i915_reg.h"
18
19static inline struct intel_gt *
20____uc_fw_to_gt(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type)
21{
22 if (type == INTEL_UC_FW_TYPE_GUC)
23 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) );})
;
24
25 GEM_BUG_ON(type != INTEL_UC_FW_TYPE_HUC)((void)0);
26 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) );})
;
27}
28
29static inline struct intel_gt *__uc_fw_to_gt(struct intel_uc_fw *uc_fw)
30{
31 GEM_BUG_ON(uc_fw->status == INTEL_UC_FIRMWARE_UNINITIALIZED)((void)0);
32 return ____uc_fw_to_gt(uc_fw, uc_fw->type);
33}
34
35#ifdef CONFIG_DRM_I915_DEBUG_GUC
36void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
37 enum intel_uc_fw_status status)
38{
39 uc_fw->__status = status;
40 drm_dbg(&__uc_fw_to_gt(uc_fw)->i915->drm,__drm_dev_dbg(((void *)0), (&__uc_fw_to_gt(uc_fw)->i915
->drm) ? (&__uc_fw_to_gt(uc_fw)->i915->drm)->
dev : ((void *)0), DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr
(uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw
->file_selected.path : intel_uc_fw_status_repr(status))
41 "%s firmware -> %s\n",__drm_dev_dbg(((void *)0), (&__uc_fw_to_gt(uc_fw)->i915
->drm) ? (&__uc_fw_to_gt(uc_fw)->i915->drm)->
dev : ((void *)0), DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr
(uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw
->file_selected.path : intel_uc_fw_status_repr(status))
42 intel_uc_fw_type_repr(uc_fw->type),__drm_dev_dbg(((void *)0), (&__uc_fw_to_gt(uc_fw)->i915
->drm) ? (&__uc_fw_to_gt(uc_fw)->i915->drm)->
dev : ((void *)0), DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr
(uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw
->file_selected.path : intel_uc_fw_status_repr(status))
43 status == INTEL_UC_FIRMWARE_SELECTED ?__drm_dev_dbg(((void *)0), (&__uc_fw_to_gt(uc_fw)->i915
->drm) ? (&__uc_fw_to_gt(uc_fw)->i915->drm)->
dev : ((void *)0), DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr
(uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw
->file_selected.path : intel_uc_fw_status_repr(status))
44 uc_fw->file_selected.path : intel_uc_fw_status_repr(status))__drm_dev_dbg(((void *)0), (&__uc_fw_to_gt(uc_fw)->i915
->drm) ? (&__uc_fw_to_gt(uc_fw)->i915->drm)->
dev : ((void *)0), DRM_UT_DRIVER, "%s firmware -> %s\n", intel_uc_fw_type_repr
(uc_fw->type), status == INTEL_UC_FIRMWARE_SELECTED ? uc_fw
->file_selected.path : intel_uc_fw_status_repr(status))
;
45}
46#endif
47
48/*
49 * List of required GuC and HuC binaries per-platform.
50 * Must be ordered based on platform + revid, from newer to older.
51 *
52 * Note that RKL and ADL-S have the same GuC/HuC device ID's and use the same
53 * firmware as TGL.
54 *
55 * Version numbers:
56 * Originally, the driver required an exact match major/minor/patch furmware
57 * file and only supported that one version for any given platform. However,
58 * the new direction from upstream is to be backwards compatible with all
59 * prior releases and to be as flexible as possible as to what firmware is
60 * loaded.
61 *
62 * For GuC, the major version number signifies a backwards breaking API change.
63 * So, new format GuC firmware files are labelled by their major version only.
64 * For HuC, there is no KMD interaction, hence no version matching requirement.
65 * So, new format HuC firmware files have no version number at all.
66 *
67 * All of which means that the table below must keep all old format files with
68 * full three point version number. But newer files have reduced requirements.
69 * Having said that, the driver still needs to track the minor version number
70 * for GuC at least. As it is useful to report to the user that they are not
71 * running with a recent enough version for all KMD supported features,
72 * security fixes, etc. to be enabled.
73 */
74#define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp)fw_def(DG2, 0, guc_maj(dg2, 70, 5)) fw_def(ALDERLAKE_P, 0, guc_maj
(adlp, 70, 5)) fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)
) fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) fw_def(ALDERLAKE_S
, 0, guc_maj(tgl, 70, 5)) fw_def(ALDERLAKE_S, 0, guc_mmp(tgl,
70, 1, 1)) fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 69, 0, 3)) fw_def
(DG1, 0, guc_maj(dg1, 70, 5)) fw_def(ROCKETLAKE, 0, guc_mmp(tgl
, 70, 1, 1)) fw_def(TIGERLAKE, 0, guc_mmp(tgl, 70, 1, 1)) fw_def
(JASPERLAKE, 0, guc_mmp(ehl, 70, 1, 1)) fw_def(ELKHARTLAKE, 0
, guc_mmp(ehl, 70, 1, 1)) fw_def(ICELAKE, 0, guc_mmp(icl, 70,
1, 1)) fw_def(COMETLAKE, 5, guc_mmp(cml, 70, 1, 1)) fw_def(COMETLAKE
, 0, guc_mmp(kbl, 70, 1, 1)) fw_def(COFFEELAKE, 0, guc_mmp(kbl
, 70, 1, 1)) fw_def(GEMINILAKE, 0, guc_mmp(glk, 70, 1, 1)) fw_def
(KABYLAKE, 0, guc_mmp(kbl, 70, 1, 1)) fw_def(BROXTON, 0, guc_mmp
(bxt, 70, 1, 1)) fw_def(SKYLAKE, 0, guc_mmp(skl, 70, 1, 1))
\
75 fw_def(DG2, 0, guc_maj(dg2, 70, 5)) \
76 fw_def(ALDERLAKE_P, 0, guc_maj(adlp, 70, 5)) \
77 fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 70, 1, 1)) \
78 fw_def(ALDERLAKE_P, 0, guc_mmp(adlp, 69, 0, 3)) \
79 fw_def(ALDERLAKE_S, 0, guc_maj(tgl, 70, 5)) \
80 fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 70, 1, 1)) \
81 fw_def(ALDERLAKE_S, 0, guc_mmp(tgl, 69, 0, 3)) \
82 fw_def(DG1, 0, guc_maj(dg1, 70, 5)) \
83 fw_def(ROCKETLAKE, 0, guc_mmp(tgl, 70, 1, 1)) \
84 fw_def(TIGERLAKE, 0, guc_mmp(tgl, 70, 1, 1)) \
85 fw_def(JASPERLAKE, 0, guc_mmp(ehl, 70, 1, 1)) \
86 fw_def(ELKHARTLAKE, 0, guc_mmp(ehl, 70, 1, 1)) \
87 fw_def(ICELAKE, 0, guc_mmp(icl, 70, 1, 1)) \
88 fw_def(COMETLAKE, 5, guc_mmp(cml, 70, 1, 1)) \
89 fw_def(COMETLAKE, 0, guc_mmp(kbl, 70, 1, 1)) \
90 fw_def(COFFEELAKE, 0, guc_mmp(kbl, 70, 1, 1)) \
91 fw_def(GEMINILAKE, 0, guc_mmp(glk, 70, 1, 1)) \
92 fw_def(KABYLAKE, 0, guc_mmp(kbl, 70, 1, 1)) \
93 fw_def(BROXTON, 0, guc_mmp(bxt, 70, 1, 1)) \
94 fw_def(SKYLAKE, 0, guc_mmp(skl, 70, 1, 1))
95
96#define INTEL_HUC_FIRMWARE_DEFS(fw_def, huc_raw, huc_mmp)fw_def(ALDERLAKE_P, 0, huc_raw(tgl)) fw_def(ALDERLAKE_P, 0, huc_mmp
(tgl, 7, 9, 3)) fw_def(ALDERLAKE_S, 0, huc_raw(tgl)) fw_def(ALDERLAKE_S
, 0, huc_mmp(tgl, 7, 9, 3)) fw_def(DG1, 0, huc_raw(dg1)) fw_def
(ROCKETLAKE, 0, huc_mmp(tgl, 7, 9, 3)) fw_def(TIGERLAKE, 0, huc_mmp
(tgl, 7, 9, 3)) fw_def(JASPERLAKE, 0, huc_mmp(ehl, 9, 0, 0)) fw_def
(ELKHARTLAKE, 0, huc_mmp(ehl, 9, 0, 0)) fw_def(ICELAKE, 0, huc_mmp
(icl, 9, 0, 0)) fw_def(COMETLAKE, 5, huc_mmp(cml, 4, 0, 0)) fw_def
(COMETLAKE, 0, huc_mmp(kbl, 4, 0, 0)) fw_def(COFFEELAKE, 0, huc_mmp
(kbl, 4, 0, 0)) fw_def(GEMINILAKE, 0, huc_mmp(glk, 4, 0, 0)) fw_def
(KABYLAKE, 0, huc_mmp(kbl, 4, 0, 0)) fw_def(BROXTON, 0, huc_mmp
(bxt, 2, 0, 0)) fw_def(SKYLAKE, 0, huc_mmp(skl, 2, 0, 0))
\
97 fw_def(ALDERLAKE_P, 0, huc_raw(tgl)) \
98 fw_def(ALDERLAKE_P, 0, huc_mmp(tgl, 7, 9, 3)) \
99 fw_def(ALDERLAKE_S, 0, huc_raw(tgl)) \
100 fw_def(ALDERLAKE_S, 0, huc_mmp(tgl, 7, 9, 3)) \
101 fw_def(DG1, 0, huc_raw(dg1)) \
102 fw_def(ROCKETLAKE, 0, huc_mmp(tgl, 7, 9, 3)) \
103 fw_def(TIGERLAKE, 0, huc_mmp(tgl, 7, 9, 3)) \
104 fw_def(JASPERLAKE, 0, huc_mmp(ehl, 9, 0, 0)) \
105 fw_def(ELKHARTLAKE, 0, huc_mmp(ehl, 9, 0, 0)) \
106 fw_def(ICELAKE, 0, huc_mmp(icl, 9, 0, 0)) \
107 fw_def(COMETLAKE, 5, huc_mmp(cml, 4, 0, 0)) \
108 fw_def(COMETLAKE, 0, huc_mmp(kbl, 4, 0, 0)) \
109 fw_def(COFFEELAKE, 0, huc_mmp(kbl, 4, 0, 0)) \
110 fw_def(GEMINILAKE, 0, huc_mmp(glk, 4, 0, 0)) \
111 fw_def(KABYLAKE, 0, huc_mmp(kbl, 4, 0, 0)) \
112 fw_def(BROXTON, 0, huc_mmp(bxt, 2, 0, 0)) \
113 fw_def(SKYLAKE, 0, huc_mmp(skl, 2, 0, 0))
114
115/*
116 * Set of macros for producing a list of filenames from the above table.
117 */
118#define __MAKE_UC_FW_PATH_BLANK(prefix_, name_)"i915/" "prefix_" name_ ".bin" \
119 "i915/" \
120 __stringify(prefix_)"prefix_" name_ ".bin"
121
122#define __MAKE_UC_FW_PATH_MAJOR(prefix_, name_, major_)"i915/" "prefix_" name_ "major_" ".bin" \
123 "i915/" \
124 __stringify(prefix_)"prefix_" name_ \
125 __stringify(major_)"major_" ".bin"
126
127#define __MAKE_UC_FW_PATH_MMP(prefix_, name_, major_, minor_, patch_)"i915/" "prefix_" name_ "major_" "." "minor_" "." "patch_" ".bin" \
128 "i915/" \
129 __stringify(prefix_)"prefix_" name_ \
130 __stringify(major_)"major_" "." \
131 __stringify(minor_)"minor_" "." \
132 __stringify(patch_)"patch_" ".bin"
133
134/* Minor for internal driver use, not part of file name */
135#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_)"i915/" "prefix_" "_guc_" "major_" ".bin" \
136 __MAKE_UC_FW_PATH_MAJOR(prefix_, "_guc_", major_)"i915/" "prefix_" "_guc_" "major_" ".bin"
137
138#define MAKE_GUC_FW_PATH_MMP(prefix_, major_, minor_, patch_)"i915/" "prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin" \
139 __MAKE_UC_FW_PATH_MMP(prefix_, "_guc_", major_, minor_, patch_)"i915/" "prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin"
140
141#define MAKE_HUC_FW_PATH_BLANK(prefix_)"i915/" "prefix_" "_huc" ".bin" \
142 __MAKE_UC_FW_PATH_BLANK(prefix_, "_huc")"i915/" "prefix_" "_huc" ".bin"
143
144#define MAKE_HUC_FW_PATH_MMP(prefix_, major_, minor_, patch_)"i915/" "prefix_" "_huc_" "major_" "." "minor_" "." "patch_" ".bin" \
145 __MAKE_UC_FW_PATH_MMP(prefix_, "_huc_", major_, minor_, patch_)"i915/" "prefix_" "_huc_" "major_" "." "minor_" "." "patch_" ".bin"
146
147/*
148 * All blobs need to be declared via MODULE_FIRMWARE().
149 * This first expansion of the table macros is solely to provide
150 * that declaration.
151 */
152#define INTEL_UC_MODULE_FW(platform_, revid_, uc_); \
153 MODULE_FIRMWARE(uc_);
154
155INTEL_GUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH_MAJOR, MAKE_GUC_FW_PATH_MMP); ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
156INTEL_HUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_HUC_FW_PATH_BLANK, MAKE_HUC_FW_PATH_MMP); ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
157
158/*
159 * The next expansion of the table macros (in __uc_fw_auto_select below) provides
160 * actual data structures with both the filename and the version information.
161 * These structure arrays are then iterated over to the list of suitable files
162 * for the current platform and to then attempt to load those files, in the order
163 * listed, until one is successfully found.
164 */
165struct __packed__attribute__((__packed__)) uc_fw_blob {
166 const char *path;
167 bool_Bool legacy;
168 u8 major;
169 u8 minor;
170 u8 patch;
171};
172
173#define UC_FW_BLOB_BASE(major_, minor_, patch_, path_).major = major_, .minor = minor_, .patch = patch_, .path = path_
,
\
174 .major = major_, \
175 .minor = minor_, \
176 .patch = patch_, \
177 .path = path_,
178
179#define UC_FW_BLOB_NEW(major_, minor_, patch_, path_){ .major = major_, .minor = minor_, .patch = patch_, .path = path_
, .legacy = 0 }
\
180 { UC_FW_BLOB_BASE(major_, minor_, patch_, path_).major = major_, .minor = minor_, .patch = patch_, .path = path_
,
\
181 .legacy = false0 }
182
183#define UC_FW_BLOB_OLD(major_, minor_, patch_, path_){ .major = major_, .minor = minor_, .patch = patch_, .path = path_
, .legacy = 1 }
\
184 { UC_FW_BLOB_BASE(major_, minor_, patch_, path_).major = major_, .minor = minor_, .patch = patch_, .path = path_
,
\
185 .legacy = true1 }
186
187#define GUC_FW_BLOB(prefix_, major_, minor_){ .major = major_, .minor = minor_, .patch = 0, .path = "i915/"
"prefix_" "_guc_" "major_" ".bin", .legacy = 0 }
\
188 UC_FW_BLOB_NEW(major_, minor_, 0, \{ .major = major_, .minor = minor_, .patch = 0, .path = "i915/"
"prefix_" "_guc_" "major_" ".bin", .legacy = 0 }
189 MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_)){ .major = major_, .minor = minor_, .patch = 0, .path = "i915/"
"prefix_" "_guc_" "major_" ".bin", .legacy = 0 }
190
191#define GUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_){ .major = major_, .minor = minor_, .patch = patch_, .path = "i915/"
"prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin",
.legacy = 1 }
\
192 UC_FW_BLOB_OLD(major_, minor_, patch_, \{ .major = major_, .minor = minor_, .patch = patch_, .path = "i915/"
"prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin",
.legacy = 1 }
193 MAKE_GUC_FW_PATH_MMP(prefix_, major_, minor_, patch_)){ .major = major_, .minor = minor_, .patch = patch_, .path = "i915/"
"prefix_" "_guc_" "major_" "." "minor_" "." "patch_" ".bin",
.legacy = 1 }
194
195#define HUC_FW_BLOB(prefix_){ .major = 0, .minor = 0, .patch = 0, .path = "i915/" "prefix_"
"_huc" ".bin", .legacy = 0 }
\
196 UC_FW_BLOB_NEW(0, 0, 0, MAKE_HUC_FW_PATH_BLANK(prefix_)){ .major = 0, .minor = 0, .patch = 0, .path = "i915/" "prefix_"
"_huc" ".bin", .legacy = 0 }
197
198#define HUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_){ .major = major_, .minor = minor_, .patch = patch_, .path = "i915/"
"prefix_" "_huc_" "major_" "." "minor_" "." "patch_" ".bin",
.legacy = 1 }
\
199 UC_FW_BLOB_OLD(major_, minor_, patch_, \{ .major = major_, .minor = minor_, .patch = patch_, .path = "i915/"
"prefix_" "_huc_" "major_" "." "minor_" "." "patch_" ".bin",
.legacy = 1 }
200 MAKE_HUC_FW_PATH_MMP(prefix_, major_, minor_, patch_)){ .major = major_, .minor = minor_, .patch = patch_, .path = "i915/"
"prefix_" "_huc_" "major_" "." "minor_" "." "patch_" ".bin",
.legacy = 1 }
201
202struct __packed__attribute__((__packed__)) uc_fw_platform_requirement {
203 enum intel_platform p;
204 u8 rev; /* first platform rev using this FW */
205 const struct uc_fw_blob blob;
206};
207
208#define MAKE_FW_LIST(platform_, revid_, uc_){ .p = INTEL_platform_, .rev = revid_, .blob = uc_, }, \
209{ \
210 .p = INTEL_##platform_, \
211 .rev = revid_, \
212 .blob = uc_, \
213},
214
215struct fw_blobs_by_type {
216 const struct uc_fw_platform_requirement *blobs;
217 u32 count;
218};
219
220static void
221__uc_fw_auto_select(struct drm_i915_privateinteldrm_softc *i915, struct intel_uc_fw *uc_fw)
222{
223 static const struct uc_fw_platform_requirement blobs_guc[] = {
224 INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, GUC_FW_BLOB_MMP){ .p = INTEL_DG2, .rev = 0, .blob = { .major = 70, .minor = 5
, .patch = 0, .path = "i915/" "dg2" "_guc_" "70" ".bin", .legacy
= 0 }, }, { .p = INTEL_ALDERLAKE_P, .rev = 0, .blob = { .major
= 70, .minor = 5, .patch = 0, .path = "i915/" "adlp" "_guc_"
"70" ".bin", .legacy = 0 }, }, { .p = INTEL_ALDERLAKE_P, .rev
= 0, .blob = { .major = 70, .minor = 1, .patch = 1, .path = "i915/"
"adlp" "_guc_" "70" "." "1" "." "1" ".bin", .legacy = 1 }, }
, { .p = INTEL_ALDERLAKE_P, .rev = 0, .blob = { .major = 69, .
minor = 0, .patch = 3, .path = "i915/" "adlp" "_guc_" "69" "."
"0" "." "3" ".bin", .legacy = 1 }, }, { .p = INTEL_ALDERLAKE_S
, .rev = 0, .blob = { .major = 70, .minor = 5, .patch = 0, .path
= "i915/" "tgl" "_guc_" "70" ".bin", .legacy = 0 }, }, { .p =
INTEL_ALDERLAKE_S, .rev = 0, .blob = { .major = 70, .minor =
1, .patch = 1, .path = "i915/" "tgl" "_guc_" "70" "." "1" "."
"1" ".bin", .legacy = 1 }, }, { .p = INTEL_ALDERLAKE_S, .rev
= 0, .blob = { .major = 69, .minor = 0, .patch = 3, .path = "i915/"
"tgl" "_guc_" "69" "." "0" "." "3" ".bin", .legacy = 1 }, },
{ .p = INTEL_DG1, .rev = 0, .blob = { .major = 70, .minor = 5
, .patch = 0, .path = "i915/" "dg1" "_guc_" "70" ".bin", .legacy
= 0 }, }, { .p = INTEL_ROCKETLAKE, .rev = 0, .blob = { .major
= 70, .minor = 1, .patch = 1, .path = "i915/" "tgl" "_guc_" "70"
"." "1" "." "1" ".bin", .legacy = 1 }, }, { .p = INTEL_TIGERLAKE
, .rev = 0, .blob = { .major = 70, .minor = 1, .patch = 1, .path
= "i915/" "tgl" "_guc_" "70" "." "1" "." "1" ".bin", .legacy
= 1 }, }, { .p = INTEL_JASPERLAKE, .rev = 0, .blob = { .major
= 70, .minor = 1, .patch = 1, .path = "i915/" "ehl" "_guc_" "70"
"." "1" "." "1" ".bin", .legacy = 1 }, }, { .p = INTEL_ELKHARTLAKE
, .rev = 0, .blob = { .major = 70, .minor = 1, .patch = 1, .path
= "i915/" "ehl" "_guc_" "70" "." "1" "." "1" ".bin", .legacy
= 1 }, }, { .p = INTEL_ICELAKE, .rev = 0, .blob = { .major =
70, .minor = 1, .patch = 1, .path = "i915/" "icl" "_guc_" "70"
"." "1" "." "1" ".bin", .legacy = 1 }, }, { .p = INTEL_COMETLAKE
, .rev = 5, .blob = { .major = 70, .minor = 1, .patch = 1, .path
= "i915/" "cml" "_guc_" "70" "." "1" "." "1" ".bin", .legacy
= 1 }, }, { .p = INTEL_COMETLAKE, .rev = 0, .blob = { .major
= 70, .minor = 1, .patch = 1, .path = "i915/" "kbl" "_guc_" "70"
"." "1" "." "1" ".bin", .legacy = 1 }, }, { .p = INTEL_COFFEELAKE
, .rev = 0, .blob = { .major = 70, .minor = 1, .patch = 1, .path
= "i915/" "kbl" "_guc_" "70" "." "1" "." "1" ".bin", .legacy
= 1 }, }, { .p = INTEL_GEMINILAKE, .rev = 0, .blob = { .major
= 70, .minor = 1, .patch = 1, .path = "i915/" "glk" "_guc_" "70"
"." "1" "." "1" ".bin", .legacy = 1 }, }, { .p = INTEL_KABYLAKE
, .rev = 0, .blob = { .major = 70, .minor = 1, .patch = 1, .path
= "i915/" "kbl" "_guc_" "70" "." "1" "." "1" ".bin", .legacy
= 1 }, }, { .p = INTEL_BROXTON, .rev = 0, .blob = { .major =
70, .minor = 1, .patch = 1, .path = "i915/" "bxt" "_guc_" "70"
"." "1" "." "1" ".bin", .legacy = 1 }, }, { .p = INTEL_SKYLAKE
, .rev = 0, .blob = { .major = 70, .minor = 1, .patch = 1, .path
= "i915/" "skl" "_guc_" "70" "." "1" "." "1" ".bin", .legacy
= 1 }, },
225 };
226 static const struct uc_fw_platform_requirement blobs_huc[] = {
227 INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB, HUC_FW_BLOB_MMP){ .p = INTEL_ALDERLAKE_P, .rev = 0, .blob = { .major = 0, .minor
= 0, .patch = 0, .path = "i915/" "tgl" "_huc" ".bin", .legacy
= 0 }, }, { .p = INTEL_ALDERLAKE_P, .rev = 0, .blob = { .major
= 7, .minor = 9, .patch = 3, .path = "i915/" "tgl" "_huc_" "7"
"." "9" "." "3" ".bin", .legacy = 1 }, }, { .p = INTEL_ALDERLAKE_S
, .rev = 0, .blob = { .major = 0, .minor = 0, .patch = 0, .path
= "i915/" "tgl" "_huc" ".bin", .legacy = 0 }, }, { .p = INTEL_ALDERLAKE_S
, .rev = 0, .blob = { .major = 7, .minor = 9, .patch = 3, .path
= "i915/" "tgl" "_huc_" "7" "." "9" "." "3" ".bin", .legacy =
1 }, }, { .p = INTEL_DG1, .rev = 0, .blob = { .major = 0, .minor
= 0, .patch = 0, .path = "i915/" "dg1" "_huc" ".bin", .legacy
= 0 }, }, { .p = INTEL_ROCKETLAKE, .rev = 0, .blob = { .major
= 7, .minor = 9, .patch = 3, .path = "i915/" "tgl" "_huc_" "7"
"." "9" "." "3" ".bin", .legacy = 1 }, }, { .p = INTEL_TIGERLAKE
, .rev = 0, .blob = { .major = 7, .minor = 9, .patch = 3, .path
= "i915/" "tgl" "_huc_" "7" "." "9" "." "3" ".bin", .legacy =
1 }, }, { .p = INTEL_JASPERLAKE, .rev = 0, .blob = { .major =
9, .minor = 0, .patch = 0, .path = "i915/" "ehl" "_huc_" "9"
"." "0" "." "0" ".bin", .legacy = 1 }, }, { .p = INTEL_ELKHARTLAKE
, .rev = 0, .blob = { .major = 9, .minor = 0, .patch = 0, .path
= "i915/" "ehl" "_huc_" "9" "." "0" "." "0" ".bin", .legacy =
1 }, }, { .p = INTEL_ICELAKE, .rev = 0, .blob = { .major = 9
, .minor = 0, .patch = 0, .path = "i915/" "icl" "_huc_" "9" "."
"0" "." "0" ".bin", .legacy = 1 }, }, { .p = INTEL_COMETLAKE
, .rev = 5, .blob = { .major = 4, .minor = 0, .patch = 0, .path
= "i915/" "cml" "_huc_" "4" "." "0" "." "0" ".bin", .legacy =
1 }, }, { .p = INTEL_COMETLAKE, .rev = 0, .blob = { .major =
4, .minor = 0, .patch = 0, .path = "i915/" "kbl" "_huc_" "4"
"." "0" "." "0" ".bin", .legacy = 1 }, }, { .p = INTEL_COFFEELAKE
, .rev = 0, .blob = { .major = 4, .minor = 0, .patch = 0, .path
= "i915/" "kbl" "_huc_" "4" "." "0" "." "0" ".bin", .legacy =
1 }, }, { .p = INTEL_GEMINILAKE, .rev = 0, .blob = { .major =
4, .minor = 0, .patch = 0, .path = "i915/" "glk" "_huc_" "4"
"." "0" "." "0" ".bin", .legacy = 1 }, }, { .p = INTEL_KABYLAKE
, .rev = 0, .blob = { .major = 4, .minor = 0, .patch = 0, .path
= "i915/" "kbl" "_huc_" "4" "." "0" "." "0" ".bin", .legacy =
1 }, }, { .p = INTEL_BROXTON, .rev = 0, .blob = { .major = 2
, .minor = 0, .patch = 0, .path = "i915/" "bxt" "_huc_" "2" "."
"0" "." "0" ".bin", .legacy = 1 }, }, { .p = INTEL_SKYLAKE, .
rev = 0, .blob = { .major = 2, .minor = 0, .patch = 0, .path =
"i915/" "skl" "_huc_" "2" "." "0" "." "0" ".bin", .legacy = 1
}, },
228 };
229 static const struct fw_blobs_by_type blobs_all[INTEL_UC_FW_NUM_TYPES2] = {
230 [INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc)(sizeof((blobs_guc)) / sizeof((blobs_guc)[0])) },
231 [INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc)(sizeof((blobs_huc)) / sizeof((blobs_huc)[0])) },
232 };
233 static bool_Bool verified;
234 const struct uc_fw_platform_requirement *fw_blobs;
235 enum intel_platform p = INTEL_INFO(i915)(&(i915)->__info)->platform;
236 u32 fw_count;
237 u8 rev = INTEL_REVID(i915)((i915)->drm.pdev->revision);
238 int i;
239 bool_Bool found;
240
241 /*
242 * The only difference between the ADL GuC FWs is the HWConfig support.
243 * ADL-N does not support HWConfig, so we should use the same binary as
244 * ADL-S, otherwise the GuC might attempt to fetch a config table that
245 * does not exist.
246 */
247 if (IS_ADLP_N(i915)IS_SUBPLATFORM(i915, INTEL_ALDERLAKE_P, 1))
248 p = INTEL_ALDERLAKE_S;
249
250 GEM_BUG_ON(uc_fw->type >= ARRAY_SIZE(blobs_all))((void)0);
251 fw_blobs = blobs_all[uc_fw->type].blobs;
252 fw_count = blobs_all[uc_fw->type].count;
253
254 found = false0;
255 for (i = 0; i < fw_count && p <= fw_blobs[i].p; i++) {
256 const struct uc_fw_blob *blob = &fw_blobs[i].blob;
257
258 if (p != fw_blobs[i].p)
259 continue;
260
261 if (rev < fw_blobs[i].rev)
262 continue;
263
264 if (uc_fw->file_selected.path) {
265 if (uc_fw->file_selected.path == blob->path)
266 uc_fw->file_selected.path = NULL((void *)0);
267
268 continue;
269 }
270
271 uc_fw->file_selected.path = blob->path;
272 uc_fw->file_wanted.path = blob->path;
273 uc_fw->file_wanted.major_ver = blob->major;
274 uc_fw->file_wanted.minor_ver = blob->minor;
275 found = true1;
276 break;
277 }
278
279 if (!found && uc_fw->file_selected.path) {
280 /* Failed to find a match for the last attempt?! */
281 uc_fw->file_selected.path = NULL((void *)0);
282 }
283
284 /* make sure the list is ordered as expected */
285 if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST)0 && !verified) {
286 verified = true1;
287
288 for (i = 1; i < fw_count; i++) {
289 /* Next platform is good: */
290 if (fw_blobs[i].p < fw_blobs[i - 1].p)
291 continue;
292
293 /* Next platform revision is good: */
294 if (fw_blobs[i].p == fw_blobs[i - 1].p &&
295 fw_blobs[i].rev < fw_blobs[i - 1].rev)
296 continue;
297
298 /* Platform/revision must be in order: */
299 if (fw_blobs[i].p != fw_blobs[i - 1].p ||
300 fw_blobs[i].rev != fw_blobs[i - 1].rev)
301 goto bad;
302
303 /* Next major version is good: */
304 if (fw_blobs[i].blob.major < fw_blobs[i - 1].blob.major)
305 continue;
306
307 /* New must be before legacy: */
308 if (!fw_blobs[i].blob.legacy && fw_blobs[i - 1].blob.legacy)
309 goto bad;
310
311 /* New to legacy also means 0.0 to X.Y (HuC), or X.0 to X.Y (GuC) */
312 if (fw_blobs[i].blob.legacy && !fw_blobs[i - 1].blob.legacy) {
313 if (!fw_blobs[i - 1].blob.major)
314 continue;
315
316 if (fw_blobs[i].blob.major == fw_blobs[i - 1].blob.major)
317 continue;
318 }
319
320 /* Major versions must be in order: */
321 if (fw_blobs[i].blob.major != fw_blobs[i - 1].blob.major)
322 goto bad;
323
324 /* Next minor version is good: */
325 if (fw_blobs[i].blob.minor < fw_blobs[i - 1].blob.minor)
326 continue;
327
328 /* Minor versions must be in order: */
329 if (fw_blobs[i].blob.minor != fw_blobs[i - 1].blob.minor)
330 goto bad;
331
332 /* Patch versions must be in order: */
333 if (fw_blobs[i].blob.patch <= fw_blobs[i - 1].blob.patch)
334 continue;
335
336bad:
337 drm_err(&i915->drm, "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%d\n",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
338 intel_platform_name(fw_blobs[i - 1].p), fw_blobs[i - 1].rev,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
339 fw_blobs[i - 1].blob.legacy ? "L" : "v",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
340 fw_blobs[i - 1].blob.major,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
341 fw_blobs[i - 1].blob.minor,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
342 fw_blobs[i - 1].blob.patch,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
343 intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
344 fw_blobs[i].blob.legacy ? "L" : "v",printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
345 fw_blobs[i].blob.major,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
346 fw_blobs[i].blob.minor,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
347 fw_blobs[i].blob.patch)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Invalid FW blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%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_platform_name
(fw_blobs[i - 1].p), fw_blobs[i - 1].rev, fw_blobs[i - 1].blob
.legacy ? "L" : "v", fw_blobs[i - 1].blob.major, fw_blobs[i -
1].blob.minor, fw_blobs[i - 1].blob.patch, intel_platform_name
(fw_blobs[i].p), fw_blobs[i].rev, fw_blobs[i].blob.legacy ? "L"
: "v", fw_blobs[i].blob.major, fw_blobs[i].blob.minor, fw_blobs
[i].blob.patch)
;
348
349 uc_fw->file_selected.path = NULL((void *)0);
350 }
351 }
352}
353
354static const char *__override_guc_firmware_path(struct drm_i915_privateinteldrm_softc *i915)
355{
356 if (i915->params.enable_guc & ENABLE_GUC_MASK(((~0UL) >> (64 - (1) - 1)) & ((~0UL) << (0))
)
)
357 return i915->params.guc_firmware_path;
358 return "";
359}
360
361static const char *__override_huc_firmware_path(struct drm_i915_privateinteldrm_softc *i915)
362{
363 if (i915->params.enable_guc & ENABLE_GUC_LOAD_HUC(1UL << (1)))
364 return i915->params.huc_firmware_path;
365 return "";
366}
367
368static void __uc_fw_user_override(struct drm_i915_privateinteldrm_softc *i915, struct intel_uc_fw *uc_fw)
369{
370 const char *path = NULL((void *)0);
371
372 switch (uc_fw->type) {
373 case INTEL_UC_FW_TYPE_GUC:
374 path = __override_guc_firmware_path(i915);
375 break;
376 case INTEL_UC_FW_TYPE_HUC:
377 path = __override_huc_firmware_path(i915);
378 break;
379 }
380
381 if (unlikely(path)__builtin_expect(!!(path), 0)) {
382 uc_fw->file_selected.path = path;
383 uc_fw->user_overridden = true1;
384 }
385}
386
387/**
388 * intel_uc_fw_init_early - initialize the uC object and select the firmware
389 * @uc_fw: uC firmware
390 * @type: type of uC
391 *
392 * Initialize the state of our uC object and relevant tracking and select the
393 * firmware to fetch and load.
394 */
395void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
396 enum intel_uc_fw_type type)
397{
398 struct drm_i915_privateinteldrm_softc *i915 = ____uc_fw_to_gt(uc_fw, type)->i915;
399
400 /*
401 * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status
402 * before we're looked at the HW caps to see if we have uc support
403 */
404 BUILD_BUG_ON(INTEL_UC_FIRMWARE_UNINITIALIZED)extern char _ctassert[(!(INTEL_UC_FIRMWARE_UNINITIALIZED)) ? 1
: -1 ] __attribute__((__unused__))
;
405 GEM_BUG_ON(uc_fw->status)((void)0);
406 GEM_BUG_ON(uc_fw->file_selected.path)((void)0);
407
408 uc_fw->type = type;
409
410 if (HAS_GT_UC(i915)((&(i915)->__info)->has_gt_uc)) {
411 __uc_fw_auto_select(i915, uc_fw);
412 __uc_fw_user_override(i915, uc_fw);
413 }
414
415 intel_uc_fw_change_status(uc_fw, uc_fw->file_selected.path ? *uc_fw->file_selected.path ?
416 INTEL_UC_FIRMWARE_SELECTED :
417 INTEL_UC_FIRMWARE_DISABLED :
418 INTEL_UC_FIRMWARE_NOT_SUPPORTED);
419}
420
421static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, int e)
422{
423 struct drm_i915_privateinteldrm_softc *i915 = __uc_fw_to_gt(uc_fw)->i915;
Value stored to 'i915' during its initialization is never read
424 bool_Bool user = e == -EINVAL22;
425
426 if (i915_inject_probe_error(i915, e)({ ((void)0); 0; })) {
427 /* non-existing blob */
428 uc_fw->file_selected.path = "<invalid>";
429 uc_fw->user_overridden = user;
430 } else if (i915_inject_probe_error(i915, e)({ ((void)0); 0; })) {
431 /* require next major version */
432 uc_fw->file_wanted.major_ver += 1;
433 uc_fw->file_wanted.minor_ver = 0;
434 uc_fw->user_overridden = user;
435 } else if (i915_inject_probe_error(i915, e)({ ((void)0); 0; })) {
436 /* require next minor version */
437 uc_fw->file_wanted.minor_ver += 1;
438 uc_fw->user_overridden = user;
439 } else if (uc_fw->file_wanted.major_ver &&
440 i915_inject_probe_error(i915, e)({ ((void)0); 0; })) {
441 /* require prev major version */
442 uc_fw->file_wanted.major_ver -= 1;
443 uc_fw->file_wanted.minor_ver = 0;
444 uc_fw->user_overridden = user;
445 } else if (uc_fw->file_wanted.minor_ver &&
446 i915_inject_probe_error(i915, e)({ ((void)0); 0; })) {
447 /* require prev minor version - hey, this should work! */
448 uc_fw->file_wanted.minor_ver -= 1;
449 uc_fw->user_overridden = user;
450 } else if (user && i915_inject_probe_error(i915, e)({ ((void)0); 0; })) {
451 /* officially unsupported platform */
452 uc_fw->file_wanted.major_ver = 0;
453 uc_fw->file_wanted.minor_ver = 0;
454 uc_fw->user_overridden = true1;
455 }
456}
457
458static int check_gsc_manifest(const struct firmware *fw,
459 struct intel_uc_fw *uc_fw)
460{
461 u32 *dw = (u32 *)fw->data;
462 u32 version_hi = dw[HUC_GSC_VERSION_HI_DW44];
463 u32 version_lo = dw[HUC_GSC_VERSION_LO_DW45];
464
465 uc_fw->file_selected.major_ver = FIELD_GET(HUC_GSC_MAJOR_VER_HI_MASK, version_hi)((typeof((0xFF << 0)))(((version_hi) & ((0xFF <<
0))) >> (__builtin_ffsll((0xFF << 0)) - 1)))
;
466 uc_fw->file_selected.minor_ver = FIELD_GET(HUC_GSC_MINOR_VER_HI_MASK, version_hi)((typeof((0xFF << 16)))(((version_hi) & ((0xFF <<
16))) >> (__builtin_ffsll((0xFF << 16)) - 1)))
;
467 uc_fw->file_selected.patch_ver = FIELD_GET(HUC_GSC_PATCH_VER_LO_MASK, version_lo)((typeof((0xFF << 0)))(((version_lo) & ((0xFF <<
0))) >> (__builtin_ffsll((0xFF << 0)) - 1)))
;
468
469 return 0;
470}
471
472static int check_ccs_header(struct drm_i915_privateinteldrm_softc *i915,
473 const struct firmware *fw,
474 struct intel_uc_fw *uc_fw)
475{
476 struct uc_css_header *css;
477 size_t size;
478
479 /* Check the size of the blob before examining buffer contents */
480 if (unlikely(fw->size < sizeof(struct uc_css_header))__builtin_expect(!!(fw->size < sizeof(struct uc_css_header
)), 0)
) {
481 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->file_selected.path, fw->size, sizeof
(struct uc_css_header))
482 intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.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->file_selected.path, fw->size, sizeof
(struct uc_css_header))
483 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->file_selected.path, fw->size, sizeof
(struct uc_css_header))
;
484 return -ENODATA91;
485 }
486
487 css = (struct uc_css_header *)fw->data;
488
489 /* Check integrity of size values inside CSS header */
490 size = (css->header_size_dw - css->key_size_dw - css->modulus_size_dw -
491 css->exponent_size_dw) * sizeof(u32);
492 if (unlikely(size != sizeof(struct uc_css_header))__builtin_expect(!!(size != sizeof(struct uc_css_header)), 0)) {
493 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->file_selected.path, fw->size, sizeof
(struct uc_css_header))
494 "%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->file_selected.path, fw->size, sizeof
(struct uc_css_header))
495 intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.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->file_selected.path, fw->size, sizeof
(struct uc_css_header))
496 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->file_selected.path, fw->size, sizeof
(struct uc_css_header))
;
497 return -EPROTO95;
498 }
499
500 /* uCode size must calculated from other sizes */
501 uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
502
503 /* now RSA */
504 uc_fw->rsa_size = css->key_size_dw * sizeof(u32);
505
506 /* At least, it should have header, uCode and RSA. Size of all three. */
507 size = sizeof(struct uc_css_header) + uc_fw->ucode_size + uc_fw->rsa_size;
508 if (unlikely(fw->size < size)__builtin_expect(!!(fw->size < size), 0)) {
509 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->file_selected.path, fw->size, size
)
510 intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.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->file_selected.path, fw->size, size
)
511 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->file_selected.path, fw->size, size
)
;
512 return -ENOEXEC8;
513 }
514
515 /* Sanity check whether this fw is not larger than whole WOPCM memory */
516 size = __intel_uc_fw_get_upload_size(uc_fw);
517 if (unlikely(size >= i915->wopcm.size)__builtin_expect(!!(size >= i915->wopcm.size), 0)) {
518 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->file_selected.path, size, (size_t
)i915->wopcm.size)
519 intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.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->file_selected.path, size, (size_t
)i915->wopcm.size)
520 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->file_selected.path, size, (size_t
)i915->wopcm.size)
;
521 return -E2BIG7;
522 }
523
524 /* Get version numbers from the CSS header */
525 uc_fw->file_selected.major_ver = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,((typeof((0xFF << 16)))(((css->sw_version) & ((0xFF
<< 16))) >> (__builtin_ffsll((0xFF << 16))
- 1)))
526 css->sw_version)((typeof((0xFF << 16)))(((css->sw_version) & ((0xFF
<< 16))) >> (__builtin_ffsll((0xFF << 16))
- 1)))
;
527 uc_fw->file_selected.minor_ver = FIELD_GET(CSS_SW_VERSION_UC_MINOR,((typeof((0xFF << 8)))(((css->sw_version) & ((0xFF
<< 8))) >> (__builtin_ffsll((0xFF << 8)) -
1)))
528 css->sw_version)((typeof((0xFF << 8)))(((css->sw_version) & ((0xFF
<< 8))) >> (__builtin_ffsll((0xFF << 8)) -
1)))
;
529 uc_fw->file_selected.patch_ver = FIELD_GET(CSS_SW_VERSION_UC_PATCH,((typeof((0xFF << 0)))(((css->sw_version) & ((0xFF
<< 0))) >> (__builtin_ffsll((0xFF << 0)) -
1)))
530 css->sw_version)((typeof((0xFF << 0)))(((css->sw_version) & ((0xFF
<< 0))) >> (__builtin_ffsll((0xFF << 0)) -
1)))
;
531
532 if (uc_fw->type == INTEL_UC_FW_TYPE_GUC)
533 uc_fw->private_data_size = css->private_data_size;
534
535 return 0;
536}
537
538/**
539 * intel_uc_fw_fetch - fetch uC firmware
540 * @uc_fw: uC firmware
541 *
542 * Fetch uC firmware into GEM obj.
543 *
544 * Return: 0 on success, a negative errno code on failure.
545 */
546int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
547{
548 struct drm_i915_privateinteldrm_softc *i915 = __uc_fw_to_gt(uc_fw)->i915;
549 struct intel_uc_fw_file file_ideal;
550 struct device *dev = i915->drm.dev;
551 struct drm_i915_gem_object *obj;
552 const struct firmware *fw = NULL((void *)0);
553 bool_Bool old_ver = false0;
554 int err;
555
556 GEM_BUG_ON(!i915->wopcm.size)((void)0);
557 GEM_BUG_ON(!intel_uc_fw_is_enabled(uc_fw))((void)0);
558
559 err = i915_inject_probe_error(i915, -ENXIO)({ ((void)0); 0; });
560 if (err)
561 goto fail;
562
563 __force_fw_fetch_failures(uc_fw, -EINVAL22);
564 __force_fw_fetch_failures(uc_fw, -ESTALE70);
565
566 err = firmware_request_nowarn(&fw, uc_fw->file_selected.path, dev);
567 memcpy(&file_ideal, &uc_fw->file_wanted, sizeof(file_ideal))__builtin_memcpy((&file_ideal), (&uc_fw->file_wanted
), (sizeof(file_ideal)))
;
568
569 /* Any error is terminal if overriding. Don't bother searching for older versions */
570 if (err && intel_uc_fw_is_overridden(uc_fw))
571 goto fail;
572
573 while (err == -ENOENT2) {
574 old_ver = true1;
575
576 __uc_fw_auto_select(i915, uc_fw);
577 if (!uc_fw->file_selected.path) {
578 /*
579 * No more options! But set the path back to something
580 * valid just in case it gets dereferenced.
581 */
582 uc_fw->file_selected.path = file_ideal.path;
583
584 /* Also, preserve the version that was really wanted */
585 memcpy(&uc_fw->file_wanted, &file_ideal, sizeof(uc_fw->file_wanted))__builtin_memcpy((&uc_fw->file_wanted), (&file_ideal
), (sizeof(uc_fw->file_wanted)))
;
586 break;
587 }
588
589 err = firmware_request_nowarn(&fw, uc_fw->file_selected.path, dev);
590 }
591
592 if (err)
593 goto fail;
594
595 if (uc_fw->loaded_via_gsc)
596 err = check_gsc_manifest(fw, uc_fw);
597 else
598 err = check_ccs_header(i915, fw, uc_fw);
599 if (err)
600 goto fail;
601
602 if (uc_fw->file_wanted.major_ver) {
603 /* Check the file's major version was as it claimed */
604 if (uc_fw->file_selected.major_ver != uc_fw->file_wanted.major_ver) {
605 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->file_selected.path, uc_fw->file_selected
.major_ver, uc_fw->file_selected.minor_ver, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver)
606 intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.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->file_selected.path, uc_fw->file_selected
.major_ver, uc_fw->file_selected.minor_ver, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver)
607 uc_fw->file_selected.major_ver, uc_fw->file_selected.minor_ver,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->file_selected.path, uc_fw->file_selected
.major_ver, uc_fw->file_selected.minor_ver, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver)
608 uc_fw->file_wanted.major_ver, uc_fw->file_wanted.minor_ver)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->file_selected.path, uc_fw->file_selected
.major_ver, uc_fw->file_selected.minor_ver, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver)
;
609 if (!intel_uc_fw_is_overridden(uc_fw)) {
610 err = -ENOEXEC8;
611 goto fail;
612 }
613 } else {
614 if (uc_fw->file_selected.minor_ver < uc_fw->file_wanted.minor_ver)
615 old_ver = true1;
616 }
617 }
618
619 if (old_ver) {
620 /* Preserve the version that was really wanted */
621 memcpy(&uc_fw->file_wanted, &file_ideal, sizeof(uc_fw->file_wanted))__builtin_memcpy((&uc_fw->file_wanted), (&file_ideal
), (sizeof(uc_fw->file_wanted)))
;
622
623 drm_notice(&i915->drm,printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\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->file_wanted.path, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver, uc_fw->file_selected
.path, uc_fw->file_selected.major_ver, uc_fw->file_selected
.minor_ver)
624 "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\n",printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\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->file_wanted.path, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver, uc_fw->file_selected
.path, uc_fw->file_selected.major_ver, uc_fw->file_selected
.minor_ver)
625 intel_uc_fw_type_repr(uc_fw->type),printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\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->file_wanted.path, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver, uc_fw->file_selected
.path, uc_fw->file_selected.major_ver, uc_fw->file_selected
.minor_ver)
626 uc_fw->file_wanted.path,printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\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->file_wanted.path, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver, uc_fw->file_selected
.path, uc_fw->file_selected.major_ver, uc_fw->file_selected
.minor_ver)
627 uc_fw->file_wanted.major_ver, uc_fw->file_wanted.minor_ver,printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\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->file_wanted.path, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver, uc_fw->file_selected
.path, uc_fw->file_selected.major_ver, uc_fw->file_selected
.minor_ver)
628 uc_fw->file_selected.path,printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\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->file_wanted.path, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver, uc_fw->file_selected
.path, uc_fw->file_selected.major_ver, uc_fw->file_selected
.minor_ver)
629 uc_fw->file_selected.major_ver, uc_fw->file_selected.minor_ver)printf("drm:pid%d:%s *NOTICE* " "[drm] " "%s firmware %s (%d.%d) is recommended, but only %s (%d.%d) was found\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->file_wanted.path, uc_fw->file_wanted
.major_ver, uc_fw->file_wanted.minor_ver, uc_fw->file_selected
.path, uc_fw->file_selected.major_ver, uc_fw->file_selected
.minor_ver)
;
630 drm_info(&i915->drm,do { } while(0)
631 "Consider updating your linux-firmware pkg or downloading from %s\n",do { } while(0)
632 INTEL_UC_FIRMWARE_URL)do { } while(0);
633 }
634
635 if (HAS_LMEM(i915)((&(i915)->__runtime)->memory_regions & ((1UL <<
(INTEL_REGION_LMEM_0))))
) {
636 obj = i915_gem_object_create_lmem_from_data(i915, fw->data, fw->size);
637 if (!IS_ERR(obj))
638 obj->flags |= I915_BO_ALLOC_PM_EARLY(1UL << (5));
639 } else {
640 obj = i915_gem_object_create_shmem_from_data(i915, fw->data, fw->size);
641 }
642
643 if (IS_ERR(obj)) {
644 err = PTR_ERR(obj);
645 goto fail;
646 }
647
648 uc_fw->obj = obj;
649 uc_fw->size = fw->size;
650 intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
651
652 release_firmware(fw);
653 return 0;
654
655fail:
656 intel_uc_fw_change_status(uc_fw, err == -ENOENT2 ?
657 INTEL_UC_FIRMWARE_MISSING :
658 INTEL_UC_FIRMWARE_ERROR);
659
660 i915_probe_error(i915, "%s firmware %s: fetch failed with error %d\n",__i915_printk(i915, 0 ? "\0017" : "\0013", "%s firmware %s: fetch failed with error %d\n"
, intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected
.path, err)
661 intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path, err)__i915_printk(i915, 0 ? "\0017" : "\0013", "%s firmware %s: fetch failed with error %d\n"
, intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected
.path, err)
;
662#ifdef __linux__
663 drm_info(&i915->drm, "%s firmware(s) can be downloaded from %s\n",do { } while(0)
664 intel_uc_fw_type_repr(uc_fw->type), INTEL_UC_FIRMWARE_URL)do { } while(0);
665#endif
666
667 release_firmware(fw); /* OK even if fw is NULL */
668 return err;
669}
670
671static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw)
672{
673 struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
674 struct drm_mm_node *node = &ggtt->uc_fw;
675
676 GEM_BUG_ON(!drm_mm_node_allocated(node))((void)0);
677 GEM_BUG_ON(upper_32_bits(node->start))((void)0);
678 GEM_BUG_ON(upper_32_bits(node->start + node->size - 1))((void)0);
679
680 return lower_32_bits(node->start)((u32)(node->start));
681}
682
683static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw)
684{
685 struct drm_i915_gem_object *obj = uc_fw->obj;
686 struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
687 struct i915_vma_resource *dummy = &uc_fw->dummy;
688 u32 pte_flags = 0;
689
690 dummy->start = uc_fw_ggtt_offset(uc_fw);
691 dummy->node_size = obj->base.size;
692 dummy->bi.pages = obj->mm.pages;
693
694 GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj))((void)0);
695 GEM_BUG_ON(dummy->node_size > ggtt->uc_fw.size)((void)0);
696
697 /* uc_fw->obj cache domains were not controlled across suspend */
698 if (i915_gem_object_has_struct_page(obj))
699 drm_clflush_sg(dummy->bi.pages);
700
701 if (i915_gem_object_is_lmem(obj))
702 pte_flags |= PTE_LM(1UL << (1));
703
704 if (ggtt->vm.raw_insert_entries)
705 ggtt->vm.raw_insert_entries(&ggtt->vm, dummy, I915_CACHE_NONE, pte_flags);
706 else
707 ggtt->vm.insert_entries(&ggtt->vm, dummy, I915_CACHE_NONE, pte_flags);
708}
709
710static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw)
711{
712 struct drm_i915_gem_object *obj = uc_fw->obj;
713 struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
714 u64 start = uc_fw_ggtt_offset(uc_fw);
715
716 ggtt->vm.clear_range(&ggtt->vm, start, obj->base.size);
717}
718
719static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
720{
721 struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
722 struct intel_uncore *uncore = gt->uncore;
723 u64 offset;
724 int ret;
725
726 ret = i915_inject_probe_error(gt->i915, -ETIMEDOUT)({ ((void)0); 0; });
727 if (ret)
728 return ret;
729
730 intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
731
732 /* Set the source address for the uCode */
733 offset = uc_fw_ggtt_offset(uc_fw);
734 GEM_BUG_ON(upper_32_bits(offset) & 0xFFFF0000)((void)0);
735 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)))
;
736 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)))
;
737
738 /* Set the DMA destination */
739 intel_uncore_write_fw(uncore, DMA_ADDR_1_LOW, dst_offset)__raw_uncore_write32(uncore, ((const i915_reg_t){ .reg = (0xc308
) }), dst_offset)
;
740 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))
;
741
742 /*
743 * Set the transfer size. The header plus uCode will be copied to WOPCM
744 * via DMA, excluding any other components
745 */
746 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)
747 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)
;
748
749 /* Start the DMA */
750 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)); }); }))
751 _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)); }); }))
;
752
753 /* Wait for DMA to finish */
754 ret = intel_wait_for_register_fw(uncore, DMA_CTRL((const i915_reg_t){ .reg = (0xc314) }), START_DMA(1<<0), 0, 100);
755 if (ret)
756 drm_err(&gt->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) })))
757 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) })))
758 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) })))
;
759
760 /* Disable the bits once DMA is over */
761 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)); })))
;
762
763 intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
764
765 return ret;
766}
767
768/**
769 * intel_uc_fw_upload - load uC firmware using custom loader
770 * @uc_fw: uC firmware
771 * @dst_offset: destination offset
772 * @dma_flags: flags for flags for dma ctrl
773 *
774 * Loads uC firmware and updates internal flags.
775 *
776 * Return: 0 on success, non-zero on failure.
777 */
778int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
779{
780 struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
781 int err;
782
783 /* make sure the status was cleared the last time we reset the uc */
784 GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw))((void)0);
785
786 err = i915_inject_probe_error(gt->i915, -ENOEXEC)({ ((void)0); 0; });
787 if (err)
788 return err;
789
790 if (!intel_uc_fw_is_loadable(uc_fw))
791 return -ENOEXEC8;
792
793 /* Call custom loader */
794 uc_fw_bind_ggtt(uc_fw);
795 err = uc_fw_xfer(uc_fw, dst_offset, dma_flags);
796 uc_fw_unbind_ggtt(uc_fw);
797 if (err)
798 goto fail;
799
800 intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_TRANSFERRED);
801 return 0;
802
803fail:
804 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->file_selected
.path, err)
805 intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.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->file_selected
.path, err)
806 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->file_selected
.path, err)
;
807 intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
808 return err;
809}
810
811static inline bool_Bool uc_fw_need_rsa_in_memory(struct intel_uc_fw *uc_fw)
812{
813 /*
814 * The HW reads the GuC RSA from memory if the key size is > 256 bytes,
815 * while it reads it from the 64 RSA registers if it is smaller.
816 * The HuC RSA is always read from memory.
817 */
818 return uc_fw->type == INTEL_UC_FW_TYPE_HUC || uc_fw->rsa_size > 256;
819}
820
821static int uc_fw_rsa_data_create(struct intel_uc_fw *uc_fw)
822{
823 struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
824 struct i915_vma *vma;
825 size_t copied;
826 void *vaddr;
827 int err;
828
829 err = i915_inject_probe_error(gt->i915, -ENXIO)({ ((void)0); 0; });
830 if (err)
831 return err;
832
833 if (!uc_fw_need_rsa_in_memory(uc_fw))
834 return 0;
835
836 /*
837 * uC firmwares will sit above GUC_GGTT_TOP and will not map through
838 * GGTT. Unfortunately, this means that the GuC HW cannot perform the uC
839 * authentication from memory, as the RSA offset now falls within the
840 * GuC inaccessible range. We resort to perma-pinning an additional vma
841 * within the accessible range that only contains the RSA signature.
842 * The GuC HW can use this extra pinning to perform the authentication
843 * since its GGTT offset will be GuC accessible.
844 */
845 GEM_BUG_ON(uc_fw->rsa_size > PAGE_SIZE)((void)0);
846 vma = intel_guc_allocate_vma(&gt->uc.guc, PAGE_SIZE(1 << 12));
847 if (IS_ERR(vma))
848 return PTR_ERR(vma);
849
850 vaddr = i915_gem_object_pin_map_unlocked(vma->obj,
851 i915_coherent_map_type(gt->i915, vma->obj, true1));
852 if (IS_ERR(vaddr)) {
853 i915_vma_unpin_and_release(&vma, 0);
854 err = PTR_ERR(vaddr);
855 goto unpin_out;
856 }
857
858 copied = intel_uc_fw_copy_rsa(uc_fw, vaddr, vma->size);
859 i915_gem_object_unpin_map(vma->obj);
860
861 if (copied < uc_fw->rsa_size) {
862 err = -ENOMEM12;
863 goto unpin_out;
864 }
865
866 uc_fw->rsa_data = vma;
867
868 return 0;
869
870unpin_out:
871 i915_vma_unpin_and_release(&vma, 0);
872 return err;
873}
874
875static void uc_fw_rsa_data_destroy(struct intel_uc_fw *uc_fw)
876{
877 i915_vma_unpin_and_release(&uc_fw->rsa_data, 0);
878}
879
880int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
881{
882 int err;
883
884 /* this should happen before the load! */
885 GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw))((void)0);
886
887 if (!intel_uc_fw_is_available(uc_fw))
888 return -ENOEXEC8;
889
890 err = i915_gem_object_pin_pages_unlocked(uc_fw->obj);
891 if (err) {
892 DRM_DEBUG_DRIVER("%s fw pin-pages err=%d\n",___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s fw pin-pages err=%d\n"
, intel_uc_fw_type_repr(uc_fw->type), err)
893 intel_uc_fw_type_repr(uc_fw->type), err)___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s fw pin-pages err=%d\n"
, intel_uc_fw_type_repr(uc_fw->type), err)
;
894 goto out;
895 }
896
897 err = uc_fw_rsa_data_create(uc_fw);
898 if (err) {
899 DRM_DEBUG_DRIVER("%s fw rsa data creation failed, err=%d\n",___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s fw rsa data creation failed, err=%d\n"
, intel_uc_fw_type_repr(uc_fw->type), err)
900 intel_uc_fw_type_repr(uc_fw->type), err)___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s fw rsa data creation failed, err=%d\n"
, intel_uc_fw_type_repr(uc_fw->type), err)
;
901 goto out_unpin;
902 }
903
904 return 0;
905
906out_unpin:
907 i915_gem_object_unpin_pages(uc_fw->obj);
908out:
909 intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_INIT_FAIL);
910 return err;
911}
912
913void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
914{
915 uc_fw_rsa_data_destroy(uc_fw);
916
917 if (i915_gem_object_has_pinned_pages(uc_fw->obj))
918 i915_gem_object_unpin_pages(uc_fw->obj);
919
920 intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
921}
922
923/**
924 * intel_uc_fw_cleanup_fetch - cleanup uC firmware
925 * @uc_fw: uC firmware
926 *
927 * Cleans up uC firmware by releasing the firmware GEM obj.
928 */
929void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw)
930{
931 if (!intel_uc_fw_is_available(uc_fw))
932 return;
933
934 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; }
)
);
935
936 intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_SELECTED);
937}
938
939/**
940 * intel_uc_fw_copy_rsa - copy fw RSA to buffer
941 *
942 * @uc_fw: uC firmware
943 * @dst: dst buffer
944 * @max_len: max number of bytes to copy
945 *
946 * Return: number of copied bytes.
947 */
948size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len)
949{
950 STUB()do { printf("%s: stub\n", __func__); } while(0);
951 return 0;
952#ifdef notyet
953 struct intel_memory_region *mr = uc_fw->obj->mm.region;
954 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; })
;
955 u32 offset = sizeof(struct uc_css_header) + uc_fw->ucode_size;
956 struct sgt_iter iter;
957 size_t count = 0;
958 int idx;
959
960 /* Called during reset handling, must be atomic [no fs_reclaim] */
961 GEM_BUG_ON(!intel_uc_fw_is_available(uc_fw))((void)0);
962
963 idx = offset >> PAGE_SHIFT12;
964 offset = offset_in_page(offset)((vaddr_t)(offset) & ((1 << 12) - 1));
965 if (i915_gem_object_has_struct_page(uc_fw->obj)) {
966 struct page *page;
967
968 for_each_sgt_page(page, iter, uc_fw->obj->mm.pages)for ((iter) = __sgt_iter((uc_fw->obj->mm.pages)->sgl
, 0); ((page) = (iter).pfn == 0 ? ((void *)0) : (PHYS_TO_VM_PAGE
(((paddr_t)((iter).pfn + ((iter).curr >> 12)) << 12
)))); (((iter).curr += (1 << 12)) >= (iter).max) ? (
iter) = __sgt_iter(__sg_next((iter).sgp), 0), 0 : 0)
{
969 u32 len = min_t(u32, size, PAGE_SIZE - offset)({ u32 __min_a = (size); u32 __min_b = ((1 << 12) - offset
); __min_a < __min_b ? __min_a : __min_b; })
;
970 void *vaddr;
971
972 if (idx > 0) {
973 idx--;
974 continue;
975 }
976
977 vaddr = kmap_atomic(page);
978 memcpy(dst, vaddr + offset, len)__builtin_memcpy((dst), (vaddr + offset), (len));
979 kunmap_atomic(vaddr);
980
981 offset = 0;
982 dst += len;
983 size -= len;
984 count += len;
985 if (!size)
986 break;
987 }
988 } else {
989 dma_addr_t addr;
990
991 for_each_sgt_daddr(addr, iter, uc_fw->obj->mm.pages)for ((iter) = __sgt_iter((uc_fw->obj->mm.pages)->sgl
, 1); ((addr) = (iter).dma + (iter).curr), (iter).sgp; (((iter
).curr += ((1ULL << (12)))) >= (iter).max) ? (iter) =
__sgt_iter(__sg_next((iter).sgp), 1), 0 : 0)
{
992 u32 len = min_t(u32, size, PAGE_SIZE - offset)({ u32 __min_a = (size); u32 __min_b = ((1 << 12) - offset
); __min_a < __min_b ? __min_a : __min_b; })
;
993 void __iomem *vaddr;
994
995 if (idx > 0) {
996 idx--;
997 continue;
998 }
999
1000 vaddr = io_mapping_map_atomic_wc(&mr->iomap,
1001 addr - mr->region.start);
1002 memcpy_fromio(dst, vaddr + offset, len)__builtin_memcpy((dst), (vaddr + offset), (len));
1003 io_mapping_unmap_atomic(vaddr);
1004
1005 offset = 0;
1006 dst += len;
1007 size -= len;
1008 count += len;
1009 if (!size)
1010 break;
1011 }
1012 }
1013
1014 return count;
1015#endif
1016}
1017
1018/**
1019 * intel_uc_fw_dump - dump information about uC firmware
1020 * @uc_fw: uC firmware
1021 * @p: the &drm_printer
1022 *
1023 * Pretty printer for uC firmware.
1024 */
1025void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p)
1026{
1027 u32 ver_sel, ver_want;
1028
1029 drm_printf(p, "%s firmware: %s\n",
1030 intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path);
1031 if (uc_fw->file_selected.path != uc_fw->file_wanted.path)
1032 drm_printf(p, "%s firmware wanted: %s\n",
1033 intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_wanted.path);
1034 drm_printf(p, "\tstatus: %s\n",
1035 intel_uc_fw_status_repr(uc_fw->status));
1036 ver_sel = MAKE_UC_VER(uc_fw->file_selected.major_ver,((uc_fw->file_selected.patch_ver) | ((uc_fw->file_selected
.minor_ver) << 8) | ((uc_fw->file_selected.major_ver
) << 16))
1037 uc_fw->file_selected.minor_ver,((uc_fw->file_selected.patch_ver) | ((uc_fw->file_selected
.minor_ver) << 8) | ((uc_fw->file_selected.major_ver
) << 16))
1038 uc_fw->file_selected.patch_ver)((uc_fw->file_selected.patch_ver) | ((uc_fw->file_selected
.minor_ver) << 8) | ((uc_fw->file_selected.major_ver
) << 16))
;
1039 ver_want = MAKE_UC_VER(uc_fw->file_wanted.major_ver,((uc_fw->file_wanted.patch_ver) | ((uc_fw->file_wanted.
minor_ver) << 8) | ((uc_fw->file_wanted.major_ver) <<
16))
1040 uc_fw->file_wanted.minor_ver,((uc_fw->file_wanted.patch_ver) | ((uc_fw->file_wanted.
minor_ver) << 8) | ((uc_fw->file_wanted.major_ver) <<
16))
1041 uc_fw->file_wanted.patch_ver)((uc_fw->file_wanted.patch_ver) | ((uc_fw->file_wanted.
minor_ver) << 8) | ((uc_fw->file_wanted.major_ver) <<
16))
;
1042 if (ver_sel < ver_want)
1043 drm_printf(p, "\tversion: wanted %u.%u.%u, found %u.%u.%u\n",
1044 uc_fw->file_wanted.major_ver,
1045 uc_fw->file_wanted.minor_ver,
1046 uc_fw->file_wanted.patch_ver,
1047 uc_fw->file_selected.major_ver,
1048 uc_fw->file_selected.minor_ver,
1049 uc_fw->file_selected.patch_ver);
1050 else
1051 drm_printf(p, "\tversion: found %u.%u.%u\n",
1052 uc_fw->file_selected.major_ver,
1053 uc_fw->file_selected.minor_ver,
1054 uc_fw->file_selected.patch_ver);
1055 drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
1056 drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
1057}