intel_uc_fw.c 18.0 KB
Newer Older
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 13
#include "i915_drv.h"

14 15
static inline struct intel_gt *
____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 19
		return container_of(uc_fw, struct intel_gt, uc.guc.fw);

20
	GEM_BUG_ON(type != INTEL_UC_FW_TYPE_HUC);
21 22 23
	return container_of(uc_fw, struct intel_gt, uc.huc.fw);
}

24 25 26 27 28 29
static inline struct intel_gt *__uc_fw_to_gt(struct intel_uc_fw *uc_fw)
{
	GEM_BUG_ON(uc_fw->status == INTEL_UC_FIRMWARE_UNINITIALIZED);
	return ____uc_fw_to_gt(uc_fw, uc_fw->type);
}

30
#ifdef CONFIG_DRM_I915_DEBUG_GUC
31 32 33 34
void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
			       enum intel_uc_fw_status status)
{
	uc_fw->__status =  status;
35 36 37 38 39
	drm_dbg(&__uc_fw_to_gt(uc_fw)->i915->drm,
		"%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 42
}
#endif

43 44 45
/*
 * List of required GuC and HuC binaries per-platform.
 * Must be ordered based on platform + revid, from newer to older.
46 47 48 49
 *
 * TGL 35.2 is interface-compatible with 33.0 for previous Gens. The deltas
 * between 33.0 and 35.2 are only related to new additions to support new Gen12
 * 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) \
54 55
	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)) \
56
	fw_def(JASPERLAKE,  0, guc_def(ehl, 33, 0, 4), huc_def(ehl,  9, 0, 0)) \
57 58
	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)) \
59
	fw_def(COMETLAKE,   5, guc_def(cml, 33, 0, 0), huc_def(cml,  4, 0, 0)) \
60 61 62 63 64
	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))
65

66
#define __MAKE_UC_FW_PATH(prefix_, name_, major_, minor_, patch_) \
67 68
	"i915/" \
	__stringify(prefix_) name_ \
69 70
	__stringify(major_) "." \
	__stringify(minor_) "." \
71 72 73
	__stringify(patch_) ".bin"

#define MAKE_GUC_FW_PATH(prefix_, major_, minor_, patch_) \
74
	__MAKE_UC_FW_PATH(prefix_, "_guc_", major_, minor_, patch_)
75 76

#define MAKE_HUC_FW_PATH(prefix_, major_, minor_, bld_num_) \
77
	__MAKE_UC_FW_PATH(prefix_, "_huc_", major_, minor_, bld_num_)
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118

/* All blobs need to be declared via MODULE_FIRMWARE() */
#define INTEL_UC_MODULE_FW(platform_, revid_, guc_, huc_) \
	MODULE_FIRMWARE(guc_); \
	MODULE_FIRMWARE(huc_);

INTEL_UC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH, MAKE_HUC_FW_PATH)

/* The below structs and macros are used to iterate across the list of blobs */
struct __packed uc_fw_blob {
	u8 major;
	u8 minor;
	const char *path;
};

#define UC_FW_BLOB(major_, minor_, path_) \
	{ .major = major_, .minor = minor_, .path = path_ }

#define GUC_FW_BLOB(prefix_, major_, minor_, patch_) \
	UC_FW_BLOB(major_, minor_, \
		   MAKE_GUC_FW_PATH(prefix_, major_, minor_, patch_))

#define HUC_FW_BLOB(prefix_, major_, minor_, bld_num_) \
	UC_FW_BLOB(major_, minor_, \
		   MAKE_HUC_FW_PATH(prefix_, major_, minor_, bld_num_))

struct __packed uc_fw_platform_requirement {
	enum intel_platform p;
	u8 rev; /* first platform rev using this FW */
	const struct uc_fw_blob blobs[INTEL_UC_FW_NUM_TYPES];
};

#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_, \
},

static void
119
__uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
120 121 122 123
{
	static const struct uc_fw_platform_requirement fw_blobs[] = {
		INTEL_UC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, HUC_FW_BLOB)
	};
124 125
	enum intel_platform p = INTEL_INFO(i915)->platform;
	u8 rev = INTEL_REVID(i915);
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
	int i;

	for (i = 0; i < ARRAY_SIZE(fw_blobs) && p <= fw_blobs[i].p; i++) {
		if (p == fw_blobs[i].p && rev >= fw_blobs[i].rev) {
			const struct uc_fw_blob *blob =
					&fw_blobs[i].blobs[uc_fw->type];
			uc_fw->path = blob->path;
			uc_fw->major_ver_wanted = blob->major;
			uc_fw->minor_ver_wanted = blob->minor;
			break;
		}
	}

	/* make sure the list is ordered as expected */
	if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST)) {
		for (i = 1; i < ARRAY_SIZE(fw_blobs); i++) {
			if (fw_blobs[i].p < fw_blobs[i - 1].p)
				continue;

			if (fw_blobs[i].p == fw_blobs[i - 1].p &&
			    fw_blobs[i].rev < fw_blobs[i - 1].rev)
				continue;

			pr_err("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);

			uc_fw->path = NULL;
		}
	}
158 159

	/* We don't want to enable GuC/HuC on pre-Gen11 by default */
160
	if (i915->params.enable_guc == -1 && p < INTEL_ICELAKE)
161 162 163
		uc_fw->path = NULL;
}

164
static const char *__override_guc_firmware_path(struct drm_i915_private *i915)
165
{
166 167 168
	if (i915->params.enable_guc & (ENABLE_GUC_SUBMISSION |
				       ENABLE_GUC_LOAD_HUC))
		return i915->params.guc_firmware_path;
169 170 171
	return "";
}

172
static const char *__override_huc_firmware_path(struct drm_i915_private *i915)
173
{
174 175
	if (i915->params.enable_guc & ENABLE_GUC_LOAD_HUC)
		return i915->params.huc_firmware_path;
176
	return "";
177 178
}

179
static void __uc_fw_user_override(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
180
{
181 182
	const char *path = NULL;

183 184
	switch (uc_fw->type) {
	case INTEL_UC_FW_TYPE_GUC:
185
		path = __override_guc_firmware_path(i915);
186 187
		break;
	case INTEL_UC_FW_TYPE_HUC:
188
		path = __override_huc_firmware_path(i915);
189 190 191
		break;
	}

192 193 194 195
	if (unlikely(path)) {
		uc_fw->path = path;
		uc_fw->user_overridden = true;
	}
196 197 198 199 200 201 202 203 204 205 206
}

/**
 * intel_uc_fw_init_early - initialize the uC object and select the firmware
 * @uc_fw: uC firmware
 * @type: type of uC
 *
 * Initialize the state of our uC object and relevant tracking and select the
 * firmware to fetch and load.
 */
void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
207
			    enum intel_uc_fw_type type)
208
{
209 210
	struct drm_i915_private *i915 = ____uc_fw_to_gt(uc_fw, type)->i915;

211
	/*
212
	 * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status
213 214 215
	 * before we're looked at the HW caps to see if we have uc support
	 */
	BUILD_BUG_ON(INTEL_UC_FIRMWARE_UNINITIALIZED);
216
	GEM_BUG_ON(uc_fw->status);
217 218 219 220
	GEM_BUG_ON(uc_fw->path);

	uc_fw->type = type;

221
	if (HAS_GT_UC(i915)) {
222 223
		__uc_fw_auto_select(i915, uc_fw);
		__uc_fw_user_override(i915, uc_fw);
224
	}
225

226
	intel_uc_fw_change_status(uc_fw, uc_fw->path ? *uc_fw->path ?
227
				  INTEL_UC_FIRMWARE_SELECTED :
228
				  INTEL_UC_FIRMWARE_DISABLED :
229
				  INTEL_UC_FIRMWARE_NOT_SUPPORTED);
230 231
}

232
static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw, int e)
233
{
234
	struct drm_i915_private *i915 = __uc_fw_to_gt(uc_fw)->i915;
235 236
	bool user = e == -EINVAL;

237
	if (i915_inject_probe_error(i915, e)) {
238 239 240
		/* non-existing blob */
		uc_fw->path = "<invalid>";
		uc_fw->user_overridden = user;
241
	} else if (i915_inject_probe_error(i915, e)) {
242 243 244 245
		/* require next major version */
		uc_fw->major_ver_wanted += 1;
		uc_fw->minor_ver_wanted = 0;
		uc_fw->user_overridden = user;
246
	} else if (i915_inject_probe_error(i915, e)) {
247 248 249
		/* require next minor version */
		uc_fw->minor_ver_wanted += 1;
		uc_fw->user_overridden = user;
250 251
	} else if (uc_fw->major_ver_wanted &&
		   i915_inject_probe_error(i915, e)) {
252 253 254 255
		/* require prev major version */
		uc_fw->major_ver_wanted -= 1;
		uc_fw->minor_ver_wanted = 0;
		uc_fw->user_overridden = user;
256 257
	} else if (uc_fw->minor_ver_wanted &&
		   i915_inject_probe_error(i915, e)) {
258 259 260
		/* require prev minor version - hey, this should work! */
		uc_fw->minor_ver_wanted -= 1;
		uc_fw->user_overridden = user;
261
	} else if (user && i915_inject_probe_error(i915, e)) {
262 263 264 265 266 267 268
		/* officially unsupported platform */
		uc_fw->major_ver_wanted = 0;
		uc_fw->minor_ver_wanted = 0;
		uc_fw->user_overridden = true;
	}
}

269 270 271 272 273
/**
 * intel_uc_fw_fetch - fetch uC firmware
 * @uc_fw: uC firmware
 *
 * Fetch uC firmware into GEM obj.
274 275
 *
 * Return: 0 on success, a negative errno code on failure.
276
 */
277
int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
278
{
279
	struct drm_i915_private *i915 = __uc_fw_to_gt(uc_fw)->i915;
280
	struct device *dev = i915->drm.dev;
281 282 283 284 285 286
	struct drm_i915_gem_object *obj;
	const struct firmware *fw = NULL;
	struct uc_css_header *css;
	size_t size;
	int err;

287
	GEM_BUG_ON(!i915->wopcm.size);
288
	GEM_BUG_ON(!intel_uc_fw_is_enabled(uc_fw));
289

290
	err = i915_inject_probe_error(i915, -ENXIO);
291
	if (err)
292
		goto fail;
293

294 295
	__force_fw_fetch_failures(uc_fw, -EINVAL);
	__force_fw_fetch_failures(uc_fw, -ESTALE);
296 297 298 299

	err = request_firmware(&fw, uc_fw->path, dev);
	if (err)
		goto fail;
300 301

	/* Check the size of the blob before examining buffer contents */
302
	if (unlikely(fw->size < sizeof(struct uc_css_header))) {
303
		drm_warn(&i915->drm, "%s firmware %s: invalid size: %zu < %zu\n",
304
			 intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
305 306
			 fw->size, sizeof(struct uc_css_header));
		err = -ENODATA;
307 308 309 310 311
		goto fail;
	}

	css = (struct uc_css_header *)fw->data;

312 313 314
	/* Check integrity of size values inside CSS header */
	size = (css->header_size_dw - css->key_size_dw - css->modulus_size_dw -
		css->exponent_size_dw) * sizeof(u32);
315
	if (unlikely(size != sizeof(struct uc_css_header))) {
316
		drm_warn(&i915->drm,
317 318 319 320
			 "%s firmware %s: unexpected header size: %zu != %zu\n",
			 intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
			 fw->size, sizeof(struct uc_css_header));
		err = -EPROTO;
321 322 323
		goto fail;
	}

324
	/* uCode size must calculated from other sizes */
325 326 327
	uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);

	/* now RSA */
328
	if (unlikely(css->key_size_dw != UOS_RSA_SCRATCH_COUNT)) {
329
		drm_warn(&i915->drm, "%s firmware %s: unexpected key size: %u != %u\n",
330 331 332
			 intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
			 css->key_size_dw, UOS_RSA_SCRATCH_COUNT);
		err = -EPROTO;
333 334 335 336 337
		goto fail;
	}
	uc_fw->rsa_size = css->key_size_dw * sizeof(u32);

	/* At least, it should have header, uCode and RSA. Size of all three. */
338
	size = sizeof(struct uc_css_header) + uc_fw->ucode_size + uc_fw->rsa_size;
339
	if (unlikely(fw->size < size)) {
340
		drm_warn(&i915->drm, "%s firmware %s: invalid size: %zu < %zu\n",
341 342
			 intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
			 fw->size, size);
343
		err = -ENOEXEC;
344 345 346
		goto fail;
	}

347 348 349
	/* Sanity check whether this fw is not larger than whole WOPCM memory */
	size = __intel_uc_fw_get_upload_size(uc_fw);
	if (unlikely(size >= i915->wopcm.size)) {
350
		drm_warn(&i915->drm, "%s firmware %s: invalid size: %zu > %zu\n",
351 352 353 354 355 356
			 intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
			 size, (size_t)i915->wopcm.size);
		err = -E2BIG;
		goto fail;
	}

357
	/* Get version numbers from the CSS header */
358 359 360 361
	uc_fw->major_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MAJOR,
					   css->sw_version);
	uc_fw->minor_ver_found = FIELD_GET(CSS_SW_VERSION_UC_MINOR,
					   css->sw_version);
362

363 364
	if (uc_fw->major_ver_found != uc_fw->major_ver_wanted ||
	    uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) {
365
		drm_notice(&i915->drm, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
366 367 368 369 370 371 372
			   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);
		if (!intel_uc_fw_is_overridden(uc_fw)) {
			err = -ENOEXEC;
			goto fail;
		}
373 374
	}

375
	obj = i915_gem_object_create_shmem_from_data(i915, fw->data, fw->size);
376 377 378 379 380 381 382
	if (IS_ERR(obj)) {
		err = PTR_ERR(obj);
		goto fail;
	}

	uc_fw->obj = obj;
	uc_fw->size = fw->size;
383
	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
384

385
	release_firmware(fw);
386
	return 0;
387 388

fail:
389 390 391
	intel_uc_fw_change_status(uc_fw, err == -ENOENT ?
				  INTEL_UC_FIRMWARE_MISSING :
				  INTEL_UC_FIRMWARE_ERROR);
392

393
	drm_notice(&i915->drm, "%s firmware %s: fetch failed with error %d\n",
394
		   intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
395
	drm_info(&i915->drm, "%s firmware(s) can be downloaded from %s\n",
396
		 intel_uc_fw_type_repr(uc_fw->type), INTEL_UC_FIRMWARE_URL);
397 398

	release_firmware(fw);		/* OK even if fw is NULL */
399
	return err;
400 401
}

402
static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw)
403
{
404
	struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
405 406
	struct drm_mm_node *node = &ggtt->uc_fw;

407
	GEM_BUG_ON(!drm_mm_node_allocated(node));
408 409 410 411 412 413
	GEM_BUG_ON(upper_32_bits(node->start));
	GEM_BUG_ON(upper_32_bits(node->start + node->size - 1));

	return lower_32_bits(node->start);
}

414
static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw)
415 416
{
	struct drm_i915_gem_object *obj = uc_fw->obj;
417
	struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
418
	struct i915_vma dummy = {
419
		.node.start = uc_fw_ggtt_offset(uc_fw),
420 421 422 423 424 425 426 427 428 429 430 431 432 433
		.node.size = obj->base.size,
		.pages = obj->mm.pages,
		.vm = &ggtt->vm,
	};

	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
	GEM_BUG_ON(dummy.node.size > ggtt->uc_fw.size);

	/* uc_fw->obj cache domains were not controlled across suspend */
	drm_clflush_sg(dummy.pages);

	ggtt->vm.insert_entries(&ggtt->vm, &dummy, I915_CACHE_NONE, 0);
}

434
static void uc_fw_unbind_ggtt(struct intel_uc_fw *uc_fw)
435 436
{
	struct drm_i915_gem_object *obj = uc_fw->obj;
437
	struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
438
	u64 start = uc_fw_ggtt_offset(uc_fw);
439 440 441 442

	ggtt->vm.clear_range(&ggtt->vm, start, obj->base.size);
}

443
static int uc_fw_xfer(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
444
{
445
	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
446 447 448 449
	struct intel_uncore *uncore = gt->uncore;
	u64 offset;
	int ret;

450
	ret = i915_inject_probe_error(gt->i915, -ETIMEDOUT);
451 452 453
	if (ret)
		return ret;

454 455 456
	intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);

	/* Set the source address for the uCode */
457
	offset = uc_fw_ggtt_offset(uc_fw);
458 459 460 461 462
	GEM_BUG_ON(upper_32_bits(offset) & 0xFFFF0000);
	intel_uncore_write_fw(uncore, DMA_ADDR_0_LOW, lower_32_bits(offset));
	intel_uncore_write_fw(uncore, DMA_ADDR_0_HIGH, upper_32_bits(offset));

	/* Set the DMA destination */
463
	intel_uncore_write_fw(uncore, DMA_ADDR_1_LOW, dst_offset);
464 465 466 467 468 469 470
	intel_uncore_write_fw(uncore, DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);

	/*
	 * Set the transfer size. The header plus uCode will be copied to WOPCM
	 * via DMA, excluding any other components
	 */
	intel_uncore_write_fw(uncore, DMA_COPY_SIZE,
471
			      sizeof(struct uc_css_header) + uc_fw->ucode_size);
472 473 474 475 476 477 478 479

	/* Start the DMA */
	intel_uncore_write_fw(uncore, DMA_CTRL,
			      _MASKED_BIT_ENABLE(dma_flags | START_DMA));

	/* Wait for DMA to finish */
	ret = intel_wait_for_register_fw(uncore, DMA_CTRL, START_DMA, 0, 100);
	if (ret)
480
		drm_err(&gt->i915->drm, "DMA for %s fw failed, DMA_CTRL=%u\n",
481 482 483 484 485 486 487 488 489 490 491
			intel_uc_fw_type_repr(uc_fw->type),
			intel_uncore_read_fw(uncore, DMA_CTRL));

	/* Disable the bits once DMA is over */
	intel_uncore_write_fw(uncore, DMA_CTRL, _MASKED_BIT_DISABLE(dma_flags));

	intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);

	return ret;
}

492 493 494
/**
 * intel_uc_fw_upload - load uC firmware using custom loader
 * @uc_fw: uC firmware
495
 * @dst_offset: destination offset
496
 * @dma_flags: flags for flags for dma ctrl
497
 *
498
 * Loads uC firmware and updates internal flags.
499 500
 *
 * Return: 0 on success, non-zero on failure.
501
 */
502
int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, u32 dst_offset, u32 dma_flags)
503
{
504
	struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
505 506
	int err;

507 508
	/* make sure the status was cleared the last time we reset the uc */
	GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw));
509

510
	err = i915_inject_probe_error(gt->i915, -ENOEXEC);
511 512 513
	if (err)
		return err;

514
	if (!intel_uc_fw_is_loadable(uc_fw))
515
		return -ENOEXEC;
516

517
	/* Call custom loader */
518 519 520
	uc_fw_bind_ggtt(uc_fw);
	err = uc_fw_xfer(uc_fw, dst_offset, dma_flags);
	uc_fw_unbind_ggtt(uc_fw);
521 522 523
	if (err)
		goto fail;

524
	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_TRANSFERRED);
525 526 527
	return 0;

fail:
528 529 530
	i915_probe_error(gt->i915, "Failed to load %s firmware %s (%d)\n",
			 intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
			 err);
531
	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_FAIL);
532 533 534
	return err;
}

535 536 537 538
int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
{
	int err;

539 540 541 542
	/* this should happen before the load! */
	GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw));

	if (!intel_uc_fw_is_available(uc_fw))
543 544 545
		return -ENOEXEC;

	err = i915_gem_object_pin_pages(uc_fw->obj);
546
	if (err) {
547 548
		DRM_DEBUG_DRIVER("%s fw pin-pages err=%d\n",
				 intel_uc_fw_type_repr(uc_fw->type), err);
549 550
		intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_FAIL);
	}
551 552 553 554 555 556

	return err;
}

void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
{
557 558 559 560
	if (i915_gem_object_has_pinned_pages(uc_fw->obj))
		i915_gem_object_unpin_pages(uc_fw->obj);

	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
561 562
}

563
/**
564
 * intel_uc_fw_cleanup_fetch - cleanup uC firmware
565 566 567 568
 * @uc_fw: uC firmware
 *
 * Cleans up uC firmware by releasing the firmware GEM obj.
 */
569
void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw)
570
{
571 572
	if (!intel_uc_fw_is_available(uc_fw))
		return;
573

574
	i915_gem_object_put(fetch_and_zero(&uc_fw->obj));
575

576
	intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_SELECTED);
577
}
578

579 580 581 582 583 584 585 586 587 588 589 590 591
/**
 * intel_uc_fw_copy_rsa - copy fw RSA to buffer
 *
 * @uc_fw: uC firmware
 * @dst: dst buffer
 * @max_len: max number of bytes to copy
 *
 * Return: number of copied bytes.
 */
size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len)
{
	struct sg_table *pages = uc_fw->obj->mm.pages;
	u32 size = min_t(u32, uc_fw->rsa_size, max_len);
592
	u32 offset = sizeof(struct uc_css_header) + uc_fw->ucode_size;
593 594 595

	GEM_BUG_ON(!intel_uc_fw_is_available(uc_fw));

596
	return sg_pcopy_to_buffer(pages->sgl, pages->nents, dst, size, offset);
597 598
}

599 600 601 602 603 604 605
/**
 * intel_uc_fw_dump - dump information about uC firmware
 * @uc_fw: uC firmware
 * @p: the &drm_printer
 *
 * Pretty printer for uC firmware.
 */
606
void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p)
607 608 609
{
	drm_printf(p, "%s firmware: %s\n",
		   intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
610 611
	drm_printf(p, "\tstatus: %s\n",
		   intel_uc_fw_status_repr(uc_fw->status));
612 613 614
	drm_printf(p, "\tversion: wanted %u.%u, found %u.%u\n",
		   uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
		   uc_fw->major_ver_found, uc_fw->minor_ver_found);
615
	drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
616
	drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
617
}