File Index
Files and directories
Sign in
FILE

intel_uc_fw.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c 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 "gt/intel_gt.h"
  15#include "gt/intel_gt_print.h"
  16#include "intel_gsc_binary_headers.h"
  17#include "intel_gsc_fw.h"
  18#include "intel_uc_fw.h"
  19#include "intel_uc_fw_abi.h"
  20#include "i915_drv.h"
  21#include "i915_reg.h"
  22
  23#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
  24#define UNEXPECTED	gt_probe_error
  25#else
  26#define UNEXPECTED	gt_notice
  27#endif
  28
  29static inline struct intel_gt *
  30____uc_fw_to_gt(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type)
  31{
  32	GEM_BUG_ON(type >= INTEL_UC_FW_NUM_TYPES);
  33
  34	switch (type) {
  35	case INTEL_UC_FW_TYPE_GUC:
  36		return container_of(uc_fw, struct intel_gt, uc.guc.fw);
  37	case INTEL_UC_FW_TYPE_HUC:
  38		return container_of(uc_fw, struct intel_gt, uc.huc.fw);
  39	case INTEL_UC_FW_TYPE_GSC:
  40		return container_of(uc_fw, struct intel_gt, uc.gsc.fw);
  41	}
  42
  43	return NULL;
  44}
  45
  46static inline struct intel_gt *__uc_fw_to_gt(struct intel_uc_fw *uc_fw)
  47{
  48	GEM_BUG_ON(uc_fw->status == INTEL_UC_FIRMWARE_UNINITIALIZED);
  49	return ____uc_fw_to_gt(uc_fw, uc_fw->type);
  50}
  51
  52#ifdef CONFIG_DRM_I915_DEBUG_GUC
  53void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
  54			       enum intel_uc_fw_status status)
  55{
  56	uc_fw->__status =  status;
  57	gt_dbg(__uc_fw_to_gt(uc_fw), "%s firmware -> %s\n",
  58	       intel_uc_fw_type_repr(uc_fw->type),
  59	       status == INTEL_UC_FIRMWARE_SELECTED ?
  60	       uc_fw->file_selected.path : intel_uc_fw_status_repr(status));
  61}
  62#endif
  63
  64/*
  65 * List of required GuC and HuC binaries per-platform.
  66 * Must be ordered based on platform + revid, from newer to older.
  67 *
  68 * Note that RKL and ADL-S have the same GuC/HuC device ID's and use the same
  69 * firmware as TGL.
  70 *
  71 * Version numbers:
  72 * Originally, the driver required an exact match major/minor/patch furmware
  73 * file and only supported that one version for any given platform. However,
  74 * the new direction from upstream is to be backwards compatible with all
  75 * prior releases and to be as flexible as possible as to what firmware is
  76 * loaded.
  77 *
  78 * For GuC, the major version number signifies a backwards breaking API change.
  79 * So, new format GuC firmware files are labelled by their major version only.
  80 * For HuC, there is no KMD interaction, hence no version matching requirement.
  81 * So, new format HuC firmware files have no version number at all.
  82 *
  83 * All of which means that the table below must keep all old format files with
  84 * full three point version number. But newer files have reduced requirements.
  85 * Having said that, the driver still needs to track the minor version number
  86 * for GuC at least. As it is useful to report to the user that they are not
  87 * running with a recent enough version for all KMD supported features,
  88 * security fixes, etc. to be enabled.
  89 */
  90#define INTEL_GUC_FIRMWARE_DEFS(fw_def, guc_maj, guc_mmp) \
  91	fw_def(METEORLAKE,   0, guc_maj(mtl,  70, 12, 1)) \
  92	fw_def(DG2,          0, guc_maj(dg2,  70, 12, 1)) \
  93	fw_def(ALDERLAKE_P,  0, guc_maj(adlp, 70, 12, 1)) \
  94	fw_def(ALDERLAKE_P,  0, guc_mmp(adlp, 70, 1, 1)) \
  95	fw_def(ALDERLAKE_P,  0, guc_mmp(adlp, 69, 0, 3)) \
  96	fw_def(ALDERLAKE_S,  0, guc_maj(tgl,  70, 12, 1)) \
  97	fw_def(ALDERLAKE_S,  0, guc_mmp(tgl,  70, 1, 1)) \
  98	fw_def(ALDERLAKE_S,  0, guc_mmp(tgl,  69, 0, 3)) \
  99	fw_def(DG1,          0, guc_maj(dg1,  70, 5, 1)) \
 100	fw_def(ROCKETLAKE,   0, guc_mmp(tgl,  70, 1, 1)) \
 101	fw_def(TIGERLAKE,    0, guc_mmp(tgl,  70, 1, 1)) \
 102	fw_def(JASPERLAKE,   0, guc_mmp(ehl,  70, 1, 1)) \
 103	fw_def(ELKHARTLAKE,  0, guc_mmp(ehl,  70, 1, 1)) \
 104	fw_def(ICELAKE,      0, guc_mmp(icl,  70, 1, 1)) \
 105	fw_def(COMETLAKE,    5, guc_mmp(cml,  70, 1, 1)) \
 106	fw_def(COMETLAKE,    0, guc_mmp(kbl,  70, 1, 1)) \
 107	fw_def(COFFEELAKE,   0, guc_mmp(kbl,  70, 1, 1)) \
 108	fw_def(GEMINILAKE,   0, guc_mmp(glk,  70, 1, 1)) \
 109	fw_def(KABYLAKE,     0, guc_mmp(kbl,  70, 1, 1)) \
 110	fw_def(BROXTON,      0, guc_mmp(bxt,  70, 1, 1)) \
 111	fw_def(SKYLAKE,      0, guc_mmp(skl,  70, 1, 1))
 112
 113#define INTEL_HUC_FIRMWARE_DEFS(fw_def, huc_raw, huc_mmp, huc_gsc) \
 114	fw_def(METEORLAKE,   0, huc_gsc(mtl)) \
 115	fw_def(DG2,          0, huc_gsc(dg2)) \
 116	fw_def(ALDERLAKE_P,  0, huc_raw(tgl)) \
 117	fw_def(ALDERLAKE_P,  0, huc_mmp(tgl,  7, 9, 3)) \
 118	fw_def(ALDERLAKE_S,  0, huc_raw(tgl)) \
 119	fw_def(ALDERLAKE_S,  0, huc_mmp(tgl,  7, 9, 3)) \
 120	fw_def(DG1,          0, huc_raw(dg1)) \
 121	fw_def(ROCKETLAKE,   0, huc_mmp(tgl,  7, 9, 3)) \
 122	fw_def(TIGERLAKE,    0, huc_mmp(tgl,  7, 9, 3)) \
 123	fw_def(JASPERLAKE,   0, huc_mmp(ehl,  9, 0, 0)) \
 124	fw_def(ELKHARTLAKE,  0, huc_mmp(ehl,  9, 0, 0)) \
 125	fw_def(ICELAKE,      0, huc_mmp(icl,  9, 0, 0)) \
 126	fw_def(COMETLAKE,    5, huc_mmp(cml,  4, 0, 0)) \
 127	fw_def(COMETLAKE,    0, huc_mmp(kbl,  4, 0, 0)) \
 128	fw_def(COFFEELAKE,   0, huc_mmp(kbl,  4, 0, 0)) \
 129	fw_def(GEMINILAKE,   0, huc_mmp(glk,  4, 0, 0)) \
 130	fw_def(KABYLAKE,     0, huc_mmp(kbl,  4, 0, 0)) \
 131	fw_def(BROXTON,      0, huc_mmp(bxt,  2, 0, 0)) \
 132	fw_def(SKYLAKE,      0, huc_mmp(skl,  2, 0, 0))
 133
 134/*
 135 * The GSC FW has multiple version (see intel_gsc_uc.h for details); since what
 136 * we care about is the interface, we use the compatibility version in the
 137 * binary names.
 138 * Same as with the GuC, a major version bump indicate a
 139 * backward-incompatible change, while a minor version bump indicates a
 140 * backward-compatible one, so we use only the former in the file name.
 141 */
 142#define INTEL_GSC_FIRMWARE_DEFS(fw_def, gsc_def) \
 143	fw_def(METEORLAKE,   0, gsc_def(mtl, 1, 0))
 144
 145/*
 146 * Set of macros for producing a list of filenames from the above table.
 147 */
 148#define __MAKE_UC_FW_PATH_BLANK(prefix_, name_) \
 149	"i915/" \
 150	__stringify(prefix_) "_" name_ ".bin"
 151
 152#define __MAKE_UC_FW_PATH_MAJOR(prefix_, name_, major_) \
 153	"i915/" \
 154	__stringify(prefix_) "_" name_ "_" \
 155	__stringify(major_) ".bin"
 156
 157#define __MAKE_UC_FW_PATH_MMP(prefix_, name_, major_, minor_, patch_) \
 158	"i915/" \
 159	__stringify(prefix_) "_" name_  "_" \
 160	__stringify(major_) "." \
 161	__stringify(minor_) "." \
 162	__stringify(patch_) ".bin"
 163
 164/* Minor for internal driver use, not part of file name */
 165#define MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_) \
 166	__MAKE_UC_FW_PATH_MAJOR(prefix_, "guc", major_)
 167
 168#define MAKE_GUC_FW_PATH_MMP(prefix_, major_, minor_, patch_) \
 169	__MAKE_UC_FW_PATH_MMP(prefix_, "guc", major_, minor_, patch_)
 170
 171#define MAKE_HUC_FW_PATH_BLANK(prefix_) \
 172	__MAKE_UC_FW_PATH_BLANK(prefix_, "huc")
 173
 174#define MAKE_HUC_FW_PATH_GSC(prefix_) \
 175	__MAKE_UC_FW_PATH_BLANK(prefix_, "huc_gsc")
 176
 177#define MAKE_HUC_FW_PATH_MMP(prefix_, major_, minor_, patch_) \
 178	__MAKE_UC_FW_PATH_MMP(prefix_, "huc", major_, minor_, patch_)
 179
 180#define MAKE_GSC_FW_PATH(prefix_, major_, minor_) \
 181	__MAKE_UC_FW_PATH_MAJOR(prefix_, "gsc", major_)
 182
 183/*
 184 * All blobs need to be declared via MODULE_FIRMWARE().
 185 * This first expansion of the table macros is solely to provide
 186 * that declaration.
 187 */
 188#define INTEL_UC_MODULE_FW(platform_, revid_, uc_) \
 189	MODULE_FIRMWARE(uc_);
 190
 191INTEL_GUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH_MAJOR, MAKE_GUC_FW_PATH_MMP)
 192INTEL_HUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_HUC_FW_PATH_BLANK, MAKE_HUC_FW_PATH_MMP, MAKE_HUC_FW_PATH_GSC)
 193INTEL_GSC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_GSC_FW_PATH)
 194
 195/*
 196 * The next expansion of the table macros (in __uc_fw_auto_select below) provides
 197 * actual data structures with both the filename and the version information.
 198 * These structure arrays are then iterated over to the list of suitable files
 199 * for the current platform and to then attempt to load those files, in the order
 200 * listed, until one is successfully found.
 201 */
 202struct __packed uc_fw_blob {
 203	const char *path;
 204	bool legacy;
 205	u8 major;
 206	u8 minor;
 207	u8 patch;
 208	bool has_gsc_headers;
 209};
 210
 211#define UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
 212	.major = major_, \
 213	.minor = minor_, \
 214	.patch = patch_, \
 215	.path = path_,
 216
 217#define UC_FW_BLOB_NEW(major_, minor_, patch_, gsc_, path_) \
 218	{ UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
 219	  .legacy = false, .has_gsc_headers = gsc_ }
 220
 221#define UC_FW_BLOB_OLD(major_, minor_, patch_, path_) \
 222	{ UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
 223	  .legacy = true }
 224
 225#define GUC_FW_BLOB(prefix_, major_, minor_, patch_) \
 226	UC_FW_BLOB_NEW(major_, minor_, patch_, false, \
 227		       MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_, patch_))
 228
 229#define GUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_) \
 230	UC_FW_BLOB_OLD(major_, minor_, patch_, \
 231		       MAKE_GUC_FW_PATH_MMP(prefix_, major_, minor_, patch_))
 232
 233#define HUC_FW_BLOB(prefix_) \
 234	UC_FW_BLOB_NEW(0, 0, 0, false, MAKE_HUC_FW_PATH_BLANK(prefix_))
 235
 236#define HUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_) \
 237	UC_FW_BLOB_OLD(major_, minor_, patch_, \
 238		       MAKE_HUC_FW_PATH_MMP(prefix_, major_, minor_, patch_))
 239
 240#define HUC_FW_BLOB_GSC(prefix_) \
 241	UC_FW_BLOB_NEW(0, 0, 0, true, MAKE_HUC_FW_PATH_GSC(prefix_))
 242
 243#define GSC_FW_BLOB(prefix_, major_, minor_) \
 244	UC_FW_BLOB_NEW(major_, minor_, 0, true, \
 245		       MAKE_GSC_FW_PATH(prefix_, major_, minor_))
 246
 247struct __packed uc_fw_platform_requirement {
 248	enum intel_platform p;
 249	u8 rev; /* first platform rev using this FW */
 250	const struct uc_fw_blob blob;
 251};
 252
 253#define MAKE_FW_LIST(platform_, revid_, uc_) \
 254{ \
 255	.p = INTEL_##platform_, \
 256	.rev = revid_, \
 257	.blob = uc_, \
 258},
 259
 260struct fw_blobs_by_type {
 261	const struct uc_fw_platform_requirement *blobs;
 262	u32 count;
 263};
 264
 265static const struct uc_fw_platform_requirement blobs_guc[] = {
 266	INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, GUC_FW_BLOB_MMP)
 267};
 268
 269static const struct uc_fw_platform_requirement blobs_huc[] = {
 270	INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB, HUC_FW_BLOB_MMP, HUC_FW_BLOB_GSC)
 271};
 272
 273static const struct uc_fw_platform_requirement blobs_gsc[] = {
 274	INTEL_GSC_FIRMWARE_DEFS(MAKE_FW_LIST, GSC_FW_BLOB)
 275};
 276
 277static const struct fw_blobs_by_type blobs_all[INTEL_UC_FW_NUM_TYPES] = {
 278	[INTEL_UC_FW_TYPE_GUC] = { blobs_guc, ARRAY_SIZE(blobs_guc) },
 279	[INTEL_UC_FW_TYPE_HUC] = { blobs_huc, ARRAY_SIZE(blobs_huc) },
 280	[INTEL_UC_FW_TYPE_GSC] = { blobs_gsc, ARRAY_SIZE(blobs_gsc) },
 281};
 282
 283static void
 284__uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
 285{
 286	const struct uc_fw_platform_requirement *fw_blobs;
 287	enum intel_platform p = INTEL_INFO(i915)->platform;
 288	u32 fw_count;
 289	u8 rev = INTEL_REVID(i915);
 290	int i;
 291	bool found;
 292
 293	/*
 294	 * The only difference between the ADL GuC FWs is the HWConfig support.
 295	 * ADL-N does not support HWConfig, so we should use the same binary as
 296	 * ADL-S, otherwise the GuC might attempt to fetch a config table that
 297	 * does not exist.
 298	 */
 299	if (IS_ALDERLAKE_P_N(i915))
 300		p = INTEL_ALDERLAKE_S;
 301
 302	GEM_BUG_ON(uc_fw->type >= ARRAY_SIZE(blobs_all));
 303	fw_blobs = blobs_all[uc_fw->type].blobs;
 304	fw_count = blobs_all[uc_fw->type].count;
 305
 306	found = false;
 307	for (i = 0; i < fw_count && p <= fw_blobs[i].p; i++) {
 308		const struct uc_fw_blob *blob = &fw_blobs[i].blob;
 309
 310		if (p != fw_blobs[i].p)
 311			continue;
 312
 313		if (rev < fw_blobs[i].rev)
 314			continue;
 315
 316		if (uc_fw->file_selected.path) {
 317			/*
 318			 * Continuing an earlier search after a found blob failed to load.
 319			 * Once the previously chosen path has been found, clear it out
 320			 * and let the search continue from there.
 321			 */
 322			if (uc_fw->file_selected.path == blob->path)
 323				uc_fw->file_selected.path = NULL;
 324
 325			continue;
 326		}
 327
 328		uc_fw->file_selected.path = blob->path;
 329		uc_fw->file_wanted.path = blob->path;
 330		uc_fw->file_wanted.ver.major = blob->major;
 331		uc_fw->file_wanted.ver.minor = blob->minor;
 332		uc_fw->file_wanted.ver.patch = blob->patch;
 333		uc_fw->has_gsc_headers = blob->has_gsc_headers;
 334		found = true;
 335		break;
 336	}
 337
 338	if (!found && uc_fw->file_selected.path) {
 339		/* Failed to find a match for the last attempt?! */
 340		uc_fw->file_selected.path = NULL;
 341	}
 342}
 343
 344static bool validate_fw_table_type(struct drm_i915_private *i915, enum intel_uc_fw_type type)
 345{
 346	const struct uc_fw_platform_requirement *fw_blobs;
 347	u32 fw_count;
 348	int i, j;
 349
 350	if (type >= ARRAY_SIZE(blobs_all)) {
 351		drm_err(&i915->drm, "No blob array for %s\n", intel_uc_fw_type_repr(type));
 352		return false;
 353	}
 354
 355	fw_blobs = blobs_all[type].blobs;
 356	fw_count = blobs_all[type].count;
 357
 358	if (!fw_count)
 359		return true;
 360
 361	/* make sure the list is ordered as expected */
 362	for (i = 1; i < fw_count; i++) {
 363		/* Versionless file names must be unique per platform: */
 364		for (j = i + 1; j < fw_count; j++) {
 365			/* Same platform? */
 366			if (fw_blobs[i].p != fw_blobs[j].p)
 367				continue;
 368
 369			if (fw_blobs[i].blob.path != fw_blobs[j].blob.path)
 370				continue;
 371
 372			drm_err(&i915->drm, "Duplicate %s blobs: %s r%u %s%d.%d.%d [%s] matches %s%d.%d.%d [%s]\n",
 373				intel_uc_fw_type_repr(type),
 374				intel_platform_name(fw_blobs[j].p), fw_blobs[j].rev,
 375				fw_blobs[j].blob.legacy ? "L" : "v",
 376				fw_blobs[j].blob.major, fw_blobs[j].blob.minor,
 377				fw_blobs[j].blob.patch, fw_blobs[j].blob.path,
 378				fw_blobs[i].blob.legacy ? "L" : "v",
 379				fw_blobs[i].blob.major, fw_blobs[i].blob.minor,
 380				fw_blobs[i].blob.patch, fw_blobs[i].blob.path);
 381		}
 382
 383		/* Next platform is good: */
 384		if (fw_blobs[i].p < fw_blobs[i - 1].p)
 385			continue;
 386
 387		/* Next platform revision is good: */
 388		if (fw_blobs[i].p == fw_blobs[i - 1].p &&
 389		    fw_blobs[i].rev < fw_blobs[i - 1].rev)
 390			continue;
 391
 392		/* Platform/revision must be in order: */
 393		if (fw_blobs[i].p != fw_blobs[i - 1].p ||
 394		    fw_blobs[i].rev != fw_blobs[i - 1].rev)
 395			goto bad;
 396
 397		/* Next major version is good: */
 398		if (fw_blobs[i].blob.major < fw_blobs[i - 1].blob.major)
 399			continue;
 400
 401		/* New must be before legacy: */
 402		if (!fw_blobs[i].blob.legacy && fw_blobs[i - 1].blob.legacy)
 403			goto bad;
 404
 405		/* New to legacy also means 0.0 to X.Y (HuC), or X.0 to X.Y (GuC) */
 406		if (fw_blobs[i].blob.legacy && !fw_blobs[i - 1].blob.legacy) {
 407			if (!fw_blobs[i - 1].blob.major)
 408				continue;
 409
 410			if (fw_blobs[i].blob.major == fw_blobs[i - 1].blob.major)
 411				continue;
 412		}
 413
 414		/* Major versions must be in order: */
 415		if (fw_blobs[i].blob.major != fw_blobs[i - 1].blob.major)
 416			goto bad;
 417
 418		/* Next minor version is good: */
 419		if (fw_blobs[i].blob.minor < fw_blobs[i - 1].blob.minor)
 420			continue;
 421
 422		/* Minor versions must be in order: */
 423		if (fw_blobs[i].blob.minor != fw_blobs[i - 1].blob.minor)
 424			goto bad;
 425
 426		/* Patch versions must be in order and unique: */
 427		if (fw_blobs[i].blob.patch < fw_blobs[i - 1].blob.patch)
 428			continue;
 429
 430bad:
 431		drm_err(&i915->drm, "Invalid %s blob order: %s r%u %s%d.%d.%d comes before %s r%u %s%d.%d.%d\n",
 432			intel_uc_fw_type_repr(type),
 433			intel_platform_name(fw_blobs[i - 1].p), fw_blobs[i - 1].rev,
 434			fw_blobs[i - 1].blob.legacy ? "L" : "v",
 435			fw_blobs[i - 1].blob.major,
 436			fw_blobs[i - 1].blob.minor,
 437			fw_blobs[i - 1].blob.patch,
 438			intel_platform_name(fw_blobs[i].p), fw_blobs[i].rev,
 439			fw_blobs[i].blob.legacy ? "L" : "v",
 440			fw_blobs[i].blob.major,
 441			fw_blobs[i].blob.minor,
 442			fw_blobs[i].blob.patch);
 443		return false;
 444	}
 445
 446	return true;
 447}
 448
 449static const char *__override_guc_firmware_path(struct drm_i915_private *i915)
 450{
 451	if (i915->params.enable_guc & ENABLE_GUC_MASK)
 452		return i915->params.guc_firmware_path;
 453	return "";
 454}
 455
 456static const char *__override_huc_firmware_path(struct drm_i915_private *i915)
 457{
 458	if (i915->params.enable_guc & ENABLE_GUC_LOAD_HUC)
 459		return i915->params.huc_firmware_path;
 460	return "";
 461}
 462
 463static const char *__override_gsc_firmware_path(struct drm_i915_private *i915)
 464{
 465	return i915->params.gsc_firmware_path;
 466}
 467
 468static void __uc_fw_user_override(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
 469{
 470	const char *path = NULL;
 471
 472	switch (uc_fw->type) {
 473	case INTEL_UC_FW_TYPE_GUC:
 474		path = __override_guc_firmware_path(i915);
 475		break;
 476	case INTEL_UC_FW_TYPE_HUC:
 477		path = __override_huc_firmware_path(i915);
 478		break;
 479	case INTEL_UC_FW_TYPE_GSC:
 480		path = __override_gsc_firmware_path(i915);
 481		break;
 482	}
 483
 484	if (unlikely(path)) {
 485		uc_fw->file_selected.path = path;
 486		uc_fw->user_overridden = true;
 487	}
 488}
 489
 490void intel_uc_fw_version_from_gsc_manifest(struct intel_uc_fw_ver *ver,
 491					   const void *data)
 492{
 493	const struct intel_gsc_manifest_header *manifest = data;
 494
 495	ver->major = manifest->fw_version.major;
 496	ver->minor = manifest->fw_version.minor;
 497	ver->patch = manifest->fw_version.hotfix;
 498	ver->build = manifest->fw_version.build;
 499}
 500
 501/**
 502 * intel_uc_fw_init_early - initialize the uC object and select the firmware
 503 * @uc_fw: uC firmware
 504 * @type: type of uC
 505 * @needs_ggtt_mapping: whether the FW needs to be GGTT mapped for loading
 506 *
 507 * Initialize the state of our uC object and relevant tracking and select the
 508 * firmware to fetch and load.
 509 */
 510void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
 511			    enum intel_uc_fw_type type,
 512			    bool needs_ggtt_mapping)
 513{
 514	struct intel_gt *gt = ____uc_fw_to_gt(uc_fw, type);
 515	struct drm_i915_private *i915 = gt->i915;
 516
 517	/*
 518	 * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status
 519	 * before we're looked at the HW caps to see if we have uc support
 520	 */
 521	BUILD_BUG_ON(INTEL_UC_FIRMWARE_UNINITIALIZED);
 522	GEM_BUG_ON(uc_fw->status);
 523	GEM_BUG_ON(uc_fw->file_selected.path);
 524
 525	uc_fw->type = type;
 526	uc_fw->needs_ggtt_mapping = needs_ggtt_mapping;
 527
 528	if (HAS_GT_UC(i915)) {
 529		if (!validate_fw_table_type(i915, type)) {
 530			gt->uc.fw_table_invalid = true;
 531			intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED);
 532			return;
 533		}
 534
 535		__uc_fw_auto_select(i915, uc_fw);
 536		__uc_fw_user_override(i915, uc_fw);
 537	}
 538
 539	intel_uc_fw_change_status(uc_fw, uc_fw->file_selected.path ? *uc_fw->file_selected.path ?
 540				  INTEL_UC_FIRMWARE_SELECTED :
 541				  INTEL_UC_FIRMWARE_DISABLED :
 542				  INTEL_UC_FIRMWARE_NOT_SUPPORTED);
 543}
 544
 545static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, int e)
 546{
 547	struct drm_i915_private *i915 = __uc_fw_to_gt(uc_fw)->i915;
 548	bool user = e == -EINVAL;
 549
 550	if (i915_inject_probe_error(i915, e)) {
 551		/* non-existing blob */
 552		uc_fw->file_selected.path = "<invalid>";
 553		uc_fw->user_overridden = user;
 554	} else if (i915_inject_probe_error(i915, e)) {
 555		/* require next major version */
 556		uc_fw->file_wanted.ver.major += 1;
 557		uc_fw->file_wanted.ver.minor = 0;
 558		uc_fw->user_overridden = user;
 559	} else if (i915_inject_probe_error(i915, e)) {
 560		/* require next minor version */
 561		uc_fw->file_wanted.ver.minor += 1;
 562		uc_fw->user_overridden = user;
 563	} else if (uc_fw->file_wanted.ver.major &&
 564		   i915_inject_probe_error(i915, e)) {
 565		/* require prev major version */
 566		uc_fw->file_wanted.ver.major -= 1;
 567		uc_fw->file_wanted.ver.minor = 0;
 568		uc_fw->user_overridden = user;
 569	} else if (uc_fw->file_wanted.ver.minor &&
 570		   i915_inject_probe_error(i915, e)) {
 571		/* require prev minor version - hey, this should work! */
 572		uc_fw->file_wanted.ver.minor -= 1;
 573		uc_fw->user_overridden = user;
 574	} else if (user && i915_inject_probe_error(i915, e)) {
 575		/* officially unsupported platform */
 576		uc_fw->file_wanted.ver.major = 0;
 577		uc_fw->file_wanted.ver.minor = 0;
 578		uc_fw->user_overridden = true;
 579	}
 580}
 581
 582static void uc_unpack_css_version(struct intel_uc_fw_ver *ver, u32 css_value)
 583{
 584	/* Get version numbers from the CSS header */
 585	ver->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, css_value);
 586	ver->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, css_value);
 587	ver->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, css_value);
 588}
 589
 590static void guc_read_css_info(struct intel_uc_fw *uc_fw, struct uc_css_header *css)
 591{
 592	struct intel_guc *guc = container_of(uc_fw, struct intel_guc, fw);
 593
 594	/*
 595	 * The GuC firmware includes an extra version number to specify the
 596	 * submission API level. This allows submission code to work with
 597	 * multiple GuC versions without having to know the absolute firmware
 598	 * version number (there are likely to be multiple firmware releases
 599	 * which all support the same submission API level).
 600	 *
 601	 * Note that the spec for the CSS header defines this version number
 602	 * as 'vf_version' as it was originally intended for virtualisation.
 603	 * However, it is applicable to native submission as well.
 604	 *
 605	 * Unfortunately, due to an oversight, this version number was only
 606	 * exposed in the CSS header from v70.6.0.
 607	 */
 608	if (uc_fw->file_selected.ver.major >= 70) {
 609		if (uc_fw->file_selected.ver.minor >= 6) {
 610			/* v70.6.0 adds CSS header support */
 611			uc_unpack_css_version(&guc->submission_version, css->vf_version);
 612		} else if (uc_fw->file_selected.ver.minor >= 3) {
 613			/* v70.3.0 introduced v1.1.0 */
 614			guc->submission_version.major = 1;
 615			guc->submission_version.minor = 1;
 616			guc->submission_version.patch = 0;
 617		} else {
 618			/* v70.0.0 introduced v1.0.0 */
 619			guc->submission_version.major = 1;
 620			guc->submission_version.minor = 0;
 621			guc->submission_version.patch = 0;
 622		}
 623	} else if (uc_fw->file_selected.ver.major >= 69) {
 624		/* v69.0.0 introduced v0.10.0 */
 625		guc->submission_version.major = 0;
 626		guc->submission_version.minor = 10;
 627		guc->submission_version.patch = 0;
 628	} else {
 629		/* Prior versions were v0.1.0 */
 630		guc->submission_version.major = 0;
 631		guc->submission_version.minor = 1;
 632		guc->submission_version.patch = 0;
 633	}
 634
 635	uc_fw->private_data_size = css->private_data_size;
 636}
 637
 638static int __check_ccs_header(struct intel_gt *gt,
 639			      const void *fw_data, size_t fw_size,
 640			      struct intel_uc_fw *uc_fw)
 641{
 642	struct uc_css_header *css;
 643	size_t size;
 644
 645	/* Check the size of the blob before examining buffer contents */
 646	if (unlikely(fw_size < sizeof(struct uc_css_header))) {
 647		gt_warn(gt, "%s firmware %s: invalid size: %zu < %zu\n",
 648			intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
 649			fw_size, sizeof(struct uc_css_header));
 650		return -ENODATA;
 651	}
 652
 653	css = (struct uc_css_header *)fw_data;
 654
 655	/* Check integrity of size values inside CSS header */
 656	size = (css->header_size_dw - css->key_size_dw - css->modulus_size_dw -
 657		css->exponent_size_dw) * sizeof(u32);
 658	if (unlikely(size != sizeof(struct uc_css_header))) {
 659		gt_warn(gt, "%s firmware %s: unexpected header size: %zu != %zu\n",
 660			intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
 661			fw_size, sizeof(struct uc_css_header));
 662		return -EPROTO;
 663	}
 664
 665	/* uCode size must calculated from other sizes */
 666	uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
 667
 668	/* now RSA */
 669	uc_fw->rsa_size = css->key_size_dw * sizeof(u32);
 670
 671	/* At least, it should have header, uCode and RSA. Size of all three. */
 672	size = sizeof(struct uc_css_header) + uc_fw->ucode_size + uc_fw->rsa_size;
 673	if (unlikely(fw_size < size)) {
 674		gt_warn(gt, "%s firmware %s: invalid size: %zu < %zu\n",
 675			intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
 676			fw_size, size);
 677		return -ENOEXEC;
 678	}
 679
 680	/* Sanity check whether this fw is not larger than whole WOPCM memory */
 681	size = __intel_uc_fw_get_upload_size(uc_fw);
 682	if (unlikely(size >= gt->wopcm.size)) {
 683		gt_warn(gt, "%s firmware %s: invalid size: %zu > %zu\n",
 684			intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
 685			size, (size_t)gt->wopcm.size);
 686		return -E2BIG;
 687	}
 688
 689	uc_unpack_css_version(&uc_fw->file_selected.ver, css->sw_version);
 690
 691	if (uc_fw->type == INTEL_UC_FW_TYPE_GUC)
 692		guc_read_css_info(uc_fw, css);
 693
 694	return 0;
 695}
 696
 697static int check_gsc_manifest(struct intel_gt *gt,
 698			      const struct firmware *fw,
 699			      struct intel_uc_fw *uc_fw)
 700{
 701	int ret;
 702
 703	switch (uc_fw->type) {
 704	case INTEL_UC_FW_TYPE_HUC:
 705		ret = intel_huc_fw_get_binary_info(uc_fw, fw->data, fw->size);
 706		if (ret)
 707			return ret;
 708		break;
 709	case INTEL_UC_FW_TYPE_GSC:
 710		ret = intel_gsc_fw_get_binary_info(uc_fw, fw->data, fw->size);
 711		if (ret)
 712			return ret;
 713		break;
 714	default:
 715		MISSING_CASE(uc_fw->type);
 716		return -EINVAL;
 717	}
 718
 719	if (uc_fw->dma_start_offset) {
 720		u32 delta = uc_fw->dma_start_offset;
 721
 722		__check_ccs_header(gt, fw->data + delta, fw->size - delta, uc_fw);
 723	}
 724
 725	return 0;
 726}
 727
 728static int check_ccs_header(struct intel_gt *gt,
 729			    const struct firmware *fw,
 730			    struct intel_uc_fw *uc_fw)
 731{
 732	return __check_ccs_header(gt, fw->data, fw->size, uc_fw);
 733}
 734
 735static bool is_ver_8bit(struct intel_uc_fw_ver *ver)
 736{
 737	return ver->major < 0xFF && ver->minor < 0xFF && ver->patch < 0xFF;
 738}
 739
 740static int guc_check_version_range(struct intel_uc_fw *uc_fw)
 741{
 742	struct intel_guc *guc = container_of(uc_fw, struct intel_guc, fw);
 743	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
 744
 745	/*
 746	 * GuC version number components are defined as being 8-bits.
 747	 * The submission code relies on this to optimise version comparison
 748	 * tests. So enforce the restriction here.
 749	 */
 750
 751	if (!is_ver_8bit(&uc_fw->file_selected.ver)) {
 752		gt_warn(gt, "%s firmware: invalid file version: 0x%02X:%02X:%02X\n",
 753			intel_uc_fw_type_repr(uc_fw->type),
 754			uc_fw->file_selected.ver.major,
 755			uc_fw->file_selected.ver.minor,
 756			uc_fw->file_selected.ver.patch);
 757		return -EINVAL;
 758	}
 759
 760	if (!is_ver_8bit(&guc->submission_version)) {
 761		gt_warn(gt, "%s firmware: invalid submit version: 0x%02X:%02X:%02X\n",
 762			intel_uc_fw_type_repr(uc_fw->type),
 763			guc->submission_version.major,
 764			guc->submission_version.minor,
 765			guc->submission_version.patch);
 766		return -EINVAL;
 767	}
 768
 769	return i915_inject_probe_error(gt->i915, -EINVAL);
 770}
 771
 772static int check_fw_header(struct intel_gt *gt,
 773			   const struct firmware *fw,
 774			   struct intel_uc_fw *uc_fw)
 775{
 776	int err = 0;
 777
 778	if (uc_fw->has_gsc_headers)
 779		err = check_gsc_manifest(gt, fw, uc_fw);
 780	else
 781		err = check_ccs_header(gt, fw, uc_fw);
 782	if (err)
 783		return err;
 784
 785	return 0;
 786}
 787
 788static int try_firmware_load(struct intel_uc_fw *uc_fw, const struct firmware **fw)
 789{
 790	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
 791	struct device *dev = gt->i915->drm.dev;
 792	int err;
 793
 794	err = firmware_request_nowarn(fw, uc_fw->file_selected.path, dev);
 795
 796	if (err)
 797		return err;
 798
 799	if (uc_fw->needs_ggtt_mapping && (*fw)->size > INTEL_UC_RSVD_GGTT_PER_FW) {
 800		gt_err(gt, "%s firmware %s: size (%zuKB) exceeds max supported size (%uKB)\n",
 801		       intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
 802		       (*fw)->size / SZ_1K, INTEL_UC_RSVD_GGTT_PER_FW / SZ_1K);
 803
 804		/* try to find another blob to load */
 805		release_firmware(*fw);
 806		*fw = NULL;
 807		return -ENOENT;
 808	}
 809
 810	return 0;
 811}
 812
 813static int check_mtl_huc_guc_compatibility(struct intel_gt *gt,
 814					   struct intel_uc_fw_file *huc_selected)
 815{
 816	struct intel_uc_fw_file *guc_selected = &gt_to_guc(gt)->fw.file_selected;
 817	struct intel_uc_fw_ver *huc_ver = &huc_selected->ver;
 818	struct intel_uc_fw_ver *guc_ver = &guc_selected->ver;
 819	bool new_huc, new_guc;
 820
 821	/* we can only do this check after having fetched both GuC and HuC */
 822	GEM_BUG_ON(!huc_selected->path || !guc_selected->path);
 823
 824	/*
 825	 * Due to changes in the authentication flow for MTL, HuC 8.5.1 or newer
 826	 * requires GuC 70.7.0 or newer. Older HuC binaries will instead require
 827	 * GuC < 70.7.0.
 828	 */
 829	new_huc = huc_ver->major > 8 ||
 830		  (huc_ver->major == 8 && huc_ver->minor > 5) ||
 831		  (huc_ver->major == 8 && huc_ver->minor == 5 && huc_ver->patch >= 1);
 832
 833	new_guc = guc_ver->major > 70 ||
 834		  (guc_ver->major == 70 && guc_ver->minor >= 7);
 835
 836	if (new_huc != new_guc) {
 837		UNEXPECTED(gt, "HuC %u.%u.%u is incompatible with GuC %u.%u.%u\n",
 838			   huc_ver->major, huc_ver->minor, huc_ver->patch,
 839			   guc_ver->major, guc_ver->minor, guc_ver->patch);
 840		gt_info(gt, "MTL GuC 70.7.0+ and HuC 8.5.1+ don't work with older releases\n");
 841		return -ENOEXEC;
 842	}
 843
 844	return 0;
 845}
 846
 847int intel_uc_check_file_version(struct intel_uc_fw *uc_fw, bool *old_ver)
 848{
 849	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
 850	struct intel_uc_fw_file *wanted = &uc_fw->file_wanted;
 851	struct intel_uc_fw_file *selected = &uc_fw->file_selected;
 852	int ret;
 853
 854	/*
 855	 * MTL has some compatibility issues with early GuC/HuC binaries
 856	 * not working with newer ones. This is specific to MTL and we
 857	 * don't expect it to extend to other platforms.
 858	 */
 859	if (IS_METEORLAKE(gt->i915) && uc_fw->type == INTEL_UC_FW_TYPE_HUC) {
 860		ret = check_mtl_huc_guc_compatibility(gt, selected);
 861		if (ret)
 862			return ret;
 863	}
 864
 865	if (!wanted->ver.major || !selected->ver.major)
 866		return 0;
 867
 868	/* Check the file's major version was as it claimed */
 869	if (selected->ver.major != wanted->ver.major) {
 870		UNEXPECTED(gt, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
 871			   intel_uc_fw_type_repr(uc_fw->type), selected->path,
 872			   selected->ver.major, selected->ver.minor,
 873			   wanted->ver.major, wanted->ver.minor);
 874		if (!intel_uc_fw_is_overridden(uc_fw))
 875			return -ENOEXEC;
 876	} else if (old_ver) {
 877		if (selected->ver.minor < wanted->ver.minor)
 878			*old_ver = true;
 879		else if ((selected->ver.minor == wanted->ver.minor) &&
 880			 (selected->ver.patch < wanted->ver.patch))
 881			*old_ver = true;
 882	}
 883
 884	return 0;
 885}
 886
 887/**
 888 * intel_uc_fw_fetch - fetch uC firmware
 889 * @uc_fw: uC firmware
 890 *
 891 * Fetch uC firmware into GEM obj.
 892 *
 893 * Return: 0 on success, a negative errno code on failure.
 894 */
 895int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
 896{
 897	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
 898	struct drm_i915_private *i915 = gt->i915;
 899	struct intel_uc_fw_file file_ideal;
 900	struct drm_i915_gem_object *obj;
 901	const struct firmware *fw = NULL;
 902	bool old_ver = false;
 903	int err;
 904
 905	GEM_BUG_ON(!gt->wopcm.size);
 906	GEM_BUG_ON(!intel_uc_fw_is_enabled(uc_fw));
 907
 908	err = i915_inject_probe_error(i915, -ENXIO);
 909	if (err)
 910		goto fail;
 911
 912	__force_fw_fetch_failures(uc_fw, -EINVAL);
 913	__force_fw_fetch_failures(uc_fw, -ESTALE);
 914
 915	err = try_firmware_load(uc_fw, &fw);
 916	memcpy(&file_ideal, &uc_fw->file_wanted, sizeof(file_ideal));
 917
 918	/* Any error is terminal if overriding. Don't bother searching for older versions */
 919	if (err && intel_uc_fw_is_overridden(uc_fw))
 920		goto fail;
 921
 922	while (err == -ENOENT) {
 923		old_ver = true;
 924
 925		__uc_fw_auto_select(i915, uc_fw);
 926		if (!uc_fw->file_selected.path) {
 927			/*
 928			 * No more options! But set the path back to something
 929			 * valid just in case it gets dereferenced.
 930			 */
 931			uc_fw->file_selected.path = file_ideal.path;
 932
 933			/* Also, preserve the version that was really wanted */
 934			memcpy(&uc_fw->file_wanted, &file_ideal, sizeof(uc_fw->file_wanted));
 935			break;
 936		}
 937
 938		err = try_firmware_load(uc_fw, &fw);
 939	}
 940
 941	if (err)
 942		goto fail;
 943
 944	err = check_fw_header(gt, fw, uc_fw);
 945	if (err)
 946		goto fail;
 947
 948	if (uc_fw->type == INTEL_UC_FW_TYPE_GUC) {
 949		err = guc_check_version_range(uc_fw);
 950		if (err)
 951			goto fail;
 952	}
 953
 954	err = intel_uc_check_file_version(uc_fw, &old_ver);
 955	if (err)
 956		goto fail;
 957
 958	if (old_ver && uc_fw->file_selected.ver.major) {
 959		/* Preserve the version that was really wanted */
 960		memcpy(&uc_fw->file_wanted, &file_ideal, sizeof(uc_fw->file_wanted));
 961
 962		UNEXPECTED(gt, "%s firmware %s (%d.%d.%d) is recommended, but only %s (%d.%d.%d) was found\n",
 963			   intel_uc_fw_type_repr(uc_fw->type),
 964			   uc_fw->file_wanted.path,
 965			   uc_fw->file_wanted.ver.major,
 966			   uc_fw->file_wanted.ver.minor,
 967			   uc_fw->file_wanted.ver.patch,
 968			   uc_fw->file_selected.path,
 969			   uc_fw->file_selected.ver.major,
 970			   uc_fw->file_selected.ver.minor,
 971			   uc_fw->file_selected.ver.patch);
 972		gt_info(gt, "Consider updating your linux-firmware pkg or downloading from %s\n",
 973			INTEL_UC_FIRMWARE_URL);
 974	}
 975
 976	if (HAS_LMEM(i915)) {
 977		obj = i915_gem_object_create_lmem_from_data(i915, fw->data, fw->size);
 978		if (!IS_ERR(obj))
 979			obj->flags |= I915_BO_ALLOC_PM_EARLY;
 980	} else {
 981		obj = i915_gem_object_create_shmem_from_data(i915, fw->data, fw->size);
 982	}
 983
 984	if (IS_ERR(obj)) {
 985		err = PTR_ERR(obj);
 986		goto fail;
 987	}
 988
 989	uc_fw->obj = obj;
 990	uc_fw->size = fw->size;
 991	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
 992
 993	release_firmware(fw);
 994	return 0;
 995
 996fail:
 997	intel_uc_fw_change_status(uc_fw, err == -ENOENT ?
 998				  INTEL_UC_FIRMWARE_MISSING :
 999				  INTEL_UC_FIRMWARE_ERROR);
1000
1001	gt_probe_error(gt, "%s firmware %s: fetch failed %pe\n",
1002		       intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path, ERR_PTR(err));
1003	gt_info(gt, "%s firmware(s) can be downloaded from %s\n",
1004		intel_uc_fw_type_repr(uc_fw->type), INTEL_UC_FIRMWARE_URL);
1005
1006	release_firmware(fw);		/* OK even if fw is NULL */
1007	return err;
1008}
1009
1010static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw)
1011{
1012	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
1013	struct i915_ggtt *ggtt = gt->ggtt;
1014	struct drm_mm_node *node = &ggtt->uc_fw;
1015	u32 offset = uc_fw->type * INTEL_UC_RSVD_GGTT_PER_FW;
1016
1017	/*
1018	 * The media GT shares the GGTT with the root GT, which means that
1019	 * we need to use different offsets for the binaries on the media GT.
1020	 * To keep the math simple, we use 8MB for the root tile and 8MB for
1021	 * the media one. This will need to be updated if we ever have more
1022	 * than 1 media GT.
1023	 */
1024	BUILD_BUG_ON(INTEL_UC_FW_NUM_TYPES * INTEL_UC_RSVD_GGTT_PER_FW > SZ_8M);
1025	GEM_BUG_ON(gt->type == GT_MEDIA && gt->info.id > 1);
1026	if (gt->type == GT_MEDIA)
1027		offset += SZ_8M;
1028
1029	GEM_BUG_ON(!drm_mm_node_allocated(node));
1030	GEM_BUG_ON(upper_32_bits(node->start));
1031	GEM_BUG_ON(upper_32_bits(node->start + node->size - 1));
1032	GEM_BUG_ON(offset + uc_fw->obj->base.size > node->size);
1033	GEM_BUG_ON(uc_fw->obj->base.size > INTEL_UC_RSVD_GGTT_PER_FW);
1034
1035	return lower_32_bits(node->start + offset);
1036}
1037
1038static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw)
1039{
1040	struct drm_i915_gem_object *obj = uc_fw->obj;
1041	struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
1042	struct i915_vma_resource *vma_res = &uc_fw->vma_res;
1043	u32 pte_flags = 0;
1044
1045	if (!uc_fw->needs_ggtt_mapping)
1046		return;
1047
1048	vma_res->start = uc_fw_ggtt_offset(uc_fw);
1049	vma_res->node_size = obj->base.size;
1050	vma_res->bi.pages = obj->mm.pages;
1051
1052	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
1053
1054	/* uc_fw->obj cache domains were not controlled across suspend */
1055	if (i915_gem_object_has_struct_page(obj))
1056		drm_clflush_sg(vma_res->bi.pages);
1057
1058	if (i915_gem_object_is_lmem(obj))
1059		pte_flags |= PTE_LM;
1060
1061	if (ggtt->vm.raw_insert_entries)
1062		ggtt->vm.raw_insert_entries(&ggtt->vm, vma_res,
1063					    i915_gem_get_pat_index(ggtt->vm.i915,
1064								   I915_CACHE_NONE),
1065					    pte_flags);
1066	else
1067		ggtt->vm.insert_entries(&ggtt->vm, vma_res,
1068					i915_gem_get_pat_index(ggtt->vm.i915,
1069							       I915_CACHE_NONE),
1070					pte_flags);
1071}
1072
1073static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw)
1074{
1075	struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
1076	struct i915_vma_resource *vma_res = &uc_fw->vma_res;
1077
1078	if (!vma_res->node_size)
1079		return;
1080
1081	ggtt->vm.clear_range(&ggtt->vm, vma_res->start, vma_res->node_size);
1082}
1083
1084static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
1085{
1086	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
1087	struct intel_uncore *uncore = gt->uncore;
1088	u64 offset;
1089	int ret;
1090
1091	ret = i915_inject_probe_error(gt->i915, -ETIMEDOUT);
1092	if (ret)
1093		return ret;
1094
1095	intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
1096
1097	/* Set the source address for the uCode */
1098	offset = uc_fw->vma_res.start + uc_fw->dma_start_offset;
1099	GEM_BUG_ON(upper_32_bits(offset) & 0xFFFF0000);
1100	intel_uncore_write_fw(uncore, DMA_ADDR_0_LOW, lower_32_bits(offset));
1101	intel_uncore_write_fw(uncore, DMA_ADDR_0_HIGH, upper_32_bits(offset));
1102
1103	/* Set the DMA destination */
1104	intel_uncore_write_fw(uncore, DMA_ADDR_1_LOW, dst_offset);
1105	intel_uncore_write_fw(uncore, DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
1106
1107	/*
1108	 * Set the transfer size. The header plus uCode will be copied to WOPCM
1109	 * via DMA, excluding any other components
1110	 */
1111	intel_uncore_write_fw(uncore, DMA_COPY_SIZE,
1112			      sizeof(struct uc_css_header) + uc_fw->ucode_size);
1113
1114	/* Start the DMA */
1115	intel_uncore_write_fw(uncore, DMA_CTRL,
1116			      _MASKED_BIT_ENABLE(dma_flags | START_DMA));
1117
1118	/* Wait for DMA to finish */
1119	ret = intel_wait_for_register_fw(uncore, DMA_CTRL, START_DMA, 0, 100, NULL);
1120	if (ret)
1121		gt_err(gt, "DMA for %s fw failed, DMA_CTRL=%u\n",
1122		       intel_uc_fw_type_repr(uc_fw->type),
1123		       intel_uncore_read_fw(uncore, DMA_CTRL));
1124
1125	/* Disable the bits once DMA is over */
1126	intel_uncore_write_fw(uncore, DMA_CTRL, _MASKED_BIT_DISABLE(dma_flags));
1127
1128	intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
1129
1130	return ret;
1131}
1132
1133int intel_uc_fw_mark_load_failed(struct intel_uc_fw *uc_fw, int err)
1134{
1135	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
1136
1137	GEM_BUG_ON(!intel_uc_fw_is_loadable(uc_fw));
1138
1139	gt_probe_error(gt, "Failed to load %s firmware %s %pe\n",
1140		       intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path, ERR_PTR(err));
1141	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
1142
1143	return err;
1144}
1145
1146/**
1147 * intel_uc_fw_upload - load uC firmware using custom loader
1148 * @uc_fw: uC firmware
1149 * @dst_offset: destination offset
1150 * @dma_flags: flags for flags for dma ctrl
1151 *
1152 * Loads uC firmware and updates internal flags.
1153 *
1154 * Return: 0 on success, non-zero on failure.
1155 */
1156int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
1157{
1158	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
1159	int err;
1160
1161	/* make sure the status was cleared the last time we reset the uc */
1162	GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw));
1163
1164	err = i915_inject_probe_error(gt->i915, -ENOEXEC);
1165	if (err)
1166		return err;
1167
1168	if (!intel_uc_fw_is_loadable(uc_fw))
1169		return -ENOEXEC;
1170
1171	/* Call custom loader */
1172	err = uc_fw_xfer(uc_fw, dst_offset, dma_flags);
1173	if (err)
1174		goto fail;
1175
1176	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_TRANSFERRED);
1177	return 0;
1178
1179fail:
1180	return intel_uc_fw_mark_load_failed(uc_fw, err);
1181}
1182
1183static inline bool uc_fw_need_rsa_in_memory(struct intel_uc_fw *uc_fw)
1184{
1185	/*
1186	 * The HW reads the GuC RSA from memory if the key size is > 256 bytes,
1187	 * while it reads it from the 64 RSA registers if it is smaller.
1188	 * The HuC RSA is always read from memory.
1189	 */
1190	return uc_fw->type == INTEL_UC_FW_TYPE_HUC || uc_fw->rsa_size > 256;
1191}
1192
1193static int uc_fw_rsa_data_create(struct intel_uc_fw *uc_fw)
1194{
1195	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
1196	struct i915_vma *vma;
1197	size_t copied;
1198	void *vaddr;
1199	int err;
1200
1201	err = i915_inject_probe_error(gt->i915, -ENXIO);
1202	if (err)
1203		return err;
1204
1205	if (!uc_fw_need_rsa_in_memory(uc_fw))
1206		return 0;
1207
1208	/*
1209	 * uC firmwares will sit above GUC_GGTT_TOP and will not map through
1210	 * GGTT. Unfortunately, this means that the GuC HW cannot perform the uC
1211	 * authentication from memory, as the RSA offset now falls within the
1212	 * GuC inaccessible range. We resort to perma-pinning an additional vma
1213	 * within the accessible range that only contains the RSA signature.
1214	 * The GuC HW can use this extra pinning to perform the authentication
1215	 * since its GGTT offset will be GuC accessible.
1216	 */
1217	GEM_BUG_ON(uc_fw->rsa_size > PAGE_SIZE);
1218	vma = intel_guc_allocate_vma(gt_to_guc(gt), PAGE_SIZE);
1219	if (IS_ERR(vma))
1220		return PTR_ERR(vma);
1221
1222	vaddr = i915_gem_object_pin_map_unlocked(vma->obj,
1223						 intel_gt_coherent_map_type(gt, vma->obj, true));
1224	if (IS_ERR(vaddr)) {
1225		i915_vma_unpin_and_release(&vma, 0);
1226		err = PTR_ERR(vaddr);
1227		goto unpin_out;
1228	}
1229
1230	copied = intel_uc_fw_copy_rsa(uc_fw, vaddr, vma->size);
1231	i915_gem_object_unpin_map(vma->obj);
1232
1233	if (copied < uc_fw->rsa_size) {
1234		err = -ENOMEM;
1235		goto unpin_out;
1236	}
1237
1238	uc_fw->rsa_data = vma;
1239
1240	return 0;
1241
1242unpin_out:
1243	i915_vma_unpin_and_release(&vma, 0);
1244	return err;
1245}
1246
1247static void uc_fw_rsa_data_destroy(struct intel_uc_fw *uc_fw)
1248{
1249	i915_vma_unpin_and_release(&uc_fw->rsa_data, 0);
1250}
1251
1252int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
1253{
1254	int err;
1255
1256	/* this should happen before the load! */
1257	GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw));
1258
1259	if (!intel_uc_fw_is_available(uc_fw))
1260		return -ENOEXEC;
1261
1262	err = i915_gem_object_pin_pages_unlocked(uc_fw->obj);
1263	if (err) {
1264		gt_dbg(__uc_fw_to_gt(uc_fw), "%s fw pin-pages failed %pe\n",
1265		       intel_uc_fw_type_repr(uc_fw->type), ERR_PTR(err));
1266		goto out;
1267	}
1268
1269	err = uc_fw_rsa_data_create(uc_fw);
1270	if (err) {
1271		gt_dbg(__uc_fw_to_gt(uc_fw), "%s fw rsa data creation failed %pe\n",
1272		       intel_uc_fw_type_repr(uc_fw->type), ERR_PTR(err));
1273		goto out_unpin;
1274	}
1275
1276	uc_fw_bind_ggtt(uc_fw);
1277
1278	return 0;
1279
1280out_unpin:
1281	i915_gem_object_unpin_pages(uc_fw->obj);
1282out:
1283	return err;
1284}
1285
1286void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
1287{
1288	uc_fw_unbind_ggtt(uc_fw);
1289	uc_fw_rsa_data_destroy(uc_fw);
1290
1291	if (i915_gem_object_has_pinned_pages(uc_fw->obj))
1292		i915_gem_object_unpin_pages(uc_fw->obj);
1293
1294	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
1295}
1296
1297void intel_uc_fw_resume_mapping(struct intel_uc_fw *uc_fw)
1298{
1299	if (!intel_uc_fw_is_available(uc_fw))
1300		return;
1301
1302	if (!i915_gem_object_has_pinned_pages(uc_fw->obj))
1303		return;
1304
1305	uc_fw_bind_ggtt(uc_fw);
1306}
1307
1308/**
1309 * intel_uc_fw_cleanup_fetch - cleanup uC firmware
1310 * @uc_fw: uC firmware
1311 *
1312 * Cleans up uC firmware by releasing the firmware GEM obj.
1313 */
1314void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw)
1315{
1316	if (!intel_uc_fw_is_available(uc_fw))
1317		return;
1318
1319	i915_gem_object_put(fetch_and_zero(&uc_fw->obj));
1320
1321	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_SELECTED);
1322}
1323
1324/**
1325 * intel_uc_fw_copy_rsa - copy fw RSA to buffer
1326 *
1327 * @uc_fw: uC firmware
1328 * @dst: dst buffer
1329 * @max_len: max number of bytes to copy
1330 *
1331 * Return: number of copied bytes.
1332 */
1333size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len)
1334{
1335	struct intel_memory_region *mr = uc_fw->obj->mm.region;
1336	u32 size = min_t(u32, uc_fw->rsa_size, max_len);
1337	u32 offset = uc_fw->dma_start_offset + sizeof(struct uc_css_header) + uc_fw->ucode_size;
1338	struct sgt_iter iter;
1339	size_t count = 0;
1340	int idx;
1341
1342	/* Called during reset handling, must be atomic [no fs_reclaim] */
1343	GEM_BUG_ON(!intel_uc_fw_is_available(uc_fw));
1344
1345	idx = offset >> PAGE_SHIFT;
1346	offset = offset_in_page(offset);
1347	if (i915_gem_object_has_struct_page(uc_fw->obj)) {
1348		struct page *page;
1349
1350		for_each_sgt_page(page, iter, uc_fw->obj->mm.pages) {
1351			u32 len = min_t(u32, size, PAGE_SIZE - offset);
1352
1353			if (idx > 0) {
1354				idx--;
1355				continue;
1356			}
1357
1358			memcpy_from_page(dst, page, offset, len);
1359
1360			offset = 0;
1361			dst += len;
1362			size -= len;
1363			count += len;
1364			if (!size)
1365				break;
1366		}
1367	} else {
1368		dma_addr_t addr;
1369
1370		for_each_sgt_daddr(addr, iter, uc_fw->obj->mm.pages) {
1371			u32 len = min_t(u32, size, PAGE_SIZE - offset);
1372			void __iomem *vaddr;
1373
1374			if (idx > 0) {
1375				idx--;
1376				continue;
1377			}
1378
1379			vaddr = io_mapping_map_atomic_wc(&mr->iomap,
1380							 addr - mr->region.start);
1381			memcpy_fromio(dst, vaddr + offset, len);
1382			io_mapping_unmap_atomic(vaddr);
1383
1384			offset = 0;
1385			dst += len;
1386			size -= len;
1387			count += len;
1388			if (!size)
1389				break;
1390		}
1391	}
1392
1393	return count;
1394}
1395
1396/**
1397 * intel_uc_fw_dump - dump information about uC firmware
1398 * @uc_fw: uC firmware
1399 * @p: the &drm_printer
1400 *
1401 * Pretty printer for uC firmware.
1402 */
1403void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p)
1404{
1405	bool got_wanted;
1406
1407	drm_printf(p, "%s firmware: %s\n",
1408		   intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path);
1409	if (uc_fw->file_selected.path != uc_fw->file_wanted.path)
1410		drm_printf(p, "%s firmware wanted: %s\n",
1411			   intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_wanted.path);
1412	drm_printf(p, "\tstatus: %s\n",
1413		   intel_uc_fw_status_repr(uc_fw->status));
1414
1415	if (uc_fw->file_selected.ver.major < uc_fw->file_wanted.ver.major)
1416		got_wanted = false;
1417	else if ((uc_fw->file_selected.ver.major == uc_fw->file_wanted.ver.major) &&
1418		 (uc_fw->file_selected.ver.minor < uc_fw->file_wanted.ver.minor))
1419		got_wanted = false;
1420	else if ((uc_fw->file_selected.ver.major == uc_fw->file_wanted.ver.major) &&
1421		 (uc_fw->file_selected.ver.minor == uc_fw->file_wanted.ver.minor) &&
1422		 (uc_fw->file_selected.ver.patch < uc_fw->file_wanted.ver.patch))
1423		got_wanted = false;
1424	else
1425		got_wanted = true;
1426
1427	if (!got_wanted)
1428		drm_printf(p, "\tversion: wanted %u.%u.%u, found %u.%u.%u\n",
1429			   uc_fw->file_wanted.ver.major,
1430			   uc_fw->file_wanted.ver.minor,
1431			   uc_fw->file_wanted.ver.patch,
1432			   uc_fw->file_selected.ver.major,
1433			   uc_fw->file_selected.ver.minor,
1434			   uc_fw->file_selected.ver.patch);
1435	else
1436		drm_printf(p, "\tversion: found %u.%u.%u\n",
1437			   uc_fw->file_selected.ver.major,
1438			   uc_fw->file_selected.ver.minor,
1439			   uc_fw->file_selected.ver.patch);
1440	drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
1441	drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
1442}
~/ Read-only file preview.