Bug Summary

File:dev/pci/drm/i915/gt/uc/intel_uc_fw.c
Warning:line 301, column 6
Access to field 'size' results in a dereference of a null pointer (loaded from variable 'fw')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name intel_uc_fw.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -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 -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/lib/clang/13.0.0 -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/swsmu -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/powerplay -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/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 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 -D CONFIG_DRM_AMD_DC_DCN3_0 -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 -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 /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pci/drm/i915/gt/uc/intel_uc_fw.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 <drm/drm_print.h>
9
10#include "intel_uc_fw.h"
11#include "intel_uc_fw_abi.h"
12#include "i915_drv.h"
13
14static 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
24static 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
31void 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
83INTEL_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 */
86struct __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
103struct __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
117static 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
163static 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
171static 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
178static 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 */
205void 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
231static 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;
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 */
276int 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
0.1
'err' is 0
0.1
'err' is 0
)
1
Taking false branch
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);
2
Calling 'request_firmware'
6
Returning from 'request_firmware'
297 if (err)
7
Assuming 'err' is 0
8
Taking false branch
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)
) {
9
Access to field 'size' results in a dereference of a null pointer (loaded from variable 'fw')
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
387fail:
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
403static 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
415static 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
435static 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
444static 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(&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) })))
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 */
503int 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
528fail:
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
536int 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
556void 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 */
570void 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 */
589size_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 */
611void 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}

/usr/src/sys/dev/pci/drm/include/linux/firmware.h

1/* Public domain. */
2
3#ifndef _LINUX_FIRMWARE_H
4#define _LINUX_FIRMWARE_H
5
6#include <sys/types.h>
7#include <sys/malloc.h>
8#include <sys/device.h>
9#include <linux/types.h>
10#include <linux/gfp.h>
11
12#ifndef __DECONST
13#define __DECONST(type, var)((type)(__uintptr_t)(const void *)(var)) ((type)(__uintptr_t)(const void *)(var))
14#endif
15
16struct firmware {
17 size_t size;
18 const u8 *data;
19};
20
21static inline int
22request_firmware(const struct firmware **fw, const char *name,
23 struct device *device)
24{
25 int r;
26 struct firmware *f = malloc(sizeof(struct firmware), M_DRM145,
27 M_WAITOK0x0001 | M_ZERO0x0008);
28 r = loadfirmware(name, __DECONST(u_char **, &f->data)((u_char **)(__uintptr_t)(const void *)(&f->data)), &f->size);
29 if (r != 0) {
3
Assuming 'r' is not equal to 0
4
Taking true branch
30 free(f, M_DRM145, sizeof(struct firmware));
31 *fw = NULL((void *)0);
5
Null pointer value stored to 'fw'
32 return -r;
33 } else {
34 *fw = f;
35 return 0;
36 }
37}
38
39static inline int
40request_firmware_direct(const struct firmware **fw, const char *name,
41 struct device *device)
42{
43 return request_firmware(fw, name, device);
44}
45
46#define request_firmware_nowait(a, b, c, d, e, f, g)-22 -EINVAL22
47
48static inline void
49release_firmware(const struct firmware *fw)
50{
51 if (fw)
52 free(__DECONST(u_char *, fw->data)((u_char *)(__uintptr_t)(const void *)(fw->data)), M_DEVBUF2, fw->size);
53 free(__DECONST(struct firmware *, fw)((struct firmware *)(__uintptr_t)(const void *)(fw)), M_DRM145, sizeof(*fw));
54}
55
56#endif