913 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2022 Intel Corporation4 */5 6#include <linux/bitfield.h>7#include <linux/firmware.h>8 9#include <drm/drm_managed.h>10 11#include "regs/xe_guc_regs.h"12#include "xe_bo.h"13#include "xe_device_types.h"14#include "xe_force_wake.h"15#include "xe_gsc.h"16#include "xe_gt.h"17#include "xe_gt_printk.h"18#include "xe_guc.h"19#include "xe_map.h"20#include "xe_mmio.h"21#include "xe_module.h"22#include "xe_sriov.h"23#include "xe_uc_fw.h"24 25/*26 * List of required GuC and HuC binaries per-platform. They must be ordered27 * based on platform, from newer to older.28 *29 * Versioning follows the guidelines from30 * Documentation/driver-api/firmware/firmware-usage-guidelines.rst. There is a31 * distinction for platforms being officially supported by the driver or not.32 * Platforms not available publicly or not yet officially supported by the33 * driver (under force-probe), use the mmp_ver(): the firmware autoselect logic34 * will select the firmware from disk with filename that matches the full35 * "mpp version", i.e. major.minor.patch. mmp_ver() should only be used for36 * this case.37 *38 * For platforms officially supported by the driver, the filename always only39 * ever contains the major version (GuC) or no version at all (HuC).40 *41 * After loading the file, the driver parses the versions embedded in the blob.42 * The major version needs to match a major version supported by the driver (if43 * any). The minor version is also checked and a notice emitted to the log if44 * the version found is smaller than the version wanted. This is done only for45 * informational purposes so users may have a chance to upgrade, but the driver46 * still loads and use the older firmware.47 *48 * Examples:49 *50 * 1) Platform officially supported by i915 - using Tigerlake as example.51 * Driver loads the following firmware blobs from disk:52 *53 * - i915/tgl_guc_<major>.bin54 * - i915/tgl_huc.bin55 *56 * <major> number for GuC is checked that it matches the version inside57 * the blob. <minor> version is checked and if smaller than the expected58 * an info message is emitted about that.59 *60 * 1) XE_<FUTUREINTELPLATFORM>, still under require_force_probe. Using61 * "wipplat" as a short-name. Driver loads the following firmware blobs62 * from disk:63 *64 * - xe/wipplat_guc_<major>.<minor>.<patch>.bin65 * - xe/wipplat_huc_<major>.<minor>.<patch>.bin66 *67 * <major> and <minor> are checked that they match the version inside68 * the blob. Both of them need to match exactly what the driver is69 * expecting, otherwise it fails.70 *71 * 3) Platform officially supported by xe and out of force-probe. Using72 * "plat" as a short-name. Except for the different directory, the73 * behavior is the same as (1). Driver loads the following firmware74 * blobs from disk:75 *76 * - xe/plat_guc_<major>.bin77 * - xe/plat_huc.bin78 *79 * <major> number for GuC is checked that it matches the version inside80 * the blob. <minor> version is checked and if smaller than the expected81 * an info message is emitted about that.82 *83 * For the platforms already released with a major version, they should never be84 * removed from the table. Instead new entries with newer versions may be added85 * before them, so they take precedence.86 *87 * TODO: Currently there's no fallback on major version. That's because xe88 * driver only supports the one major version of each firmware in the table.89 * This needs to be fixed when the major version of GuC is updated.90 */91 92struct uc_fw_entry {93 enum xe_platform platform;94 struct {95 const char *path;96 u16 major;97 u16 minor;98 u16 patch;99 bool full_ver_required;100 };101};102 103struct fw_blobs_by_type {104 const struct uc_fw_entry *entries;105 u32 count;106};107 108#define XE_GUC_FIRMWARE_DEFS(fw_def, mmp_ver, major_ver) \109 fw_def(BATTLEMAGE, major_ver(xe, guc, bmg, 70, 29, 2)) \110 fw_def(LUNARLAKE, major_ver(xe, guc, lnl, 70, 29, 2)) \111 fw_def(METEORLAKE, major_ver(i915, guc, mtl, 70, 29, 2)) \112 fw_def(DG2, major_ver(i915, guc, dg2, 70, 29, 2)) \113 fw_def(DG1, major_ver(i915, guc, dg1, 70, 29, 2)) \114 fw_def(ALDERLAKE_N, major_ver(i915, guc, tgl, 70, 29, 2)) \115 fw_def(ALDERLAKE_P, major_ver(i915, guc, adlp, 70, 29, 2)) \116 fw_def(ALDERLAKE_S, major_ver(i915, guc, tgl, 70, 29, 2)) \117 fw_def(ROCKETLAKE, major_ver(i915, guc, tgl, 70, 29, 2)) \118 fw_def(TIGERLAKE, major_ver(i915, guc, tgl, 70, 29, 2))119 120#define XE_HUC_FIRMWARE_DEFS(fw_def, mmp_ver, no_ver) \121 fw_def(BATTLEMAGE, no_ver(xe, huc, bmg)) \122 fw_def(LUNARLAKE, no_ver(xe, huc, lnl)) \123 fw_def(METEORLAKE, no_ver(i915, huc_gsc, mtl)) \124 fw_def(DG1, no_ver(i915, huc, dg1)) \125 fw_def(ALDERLAKE_P, no_ver(i915, huc, tgl)) \126 fw_def(ALDERLAKE_S, no_ver(i915, huc, tgl)) \127 fw_def(ROCKETLAKE, no_ver(i915, huc, tgl)) \128 fw_def(TIGERLAKE, no_ver(i915, huc, tgl))129 130/* for the GSC FW we match the compatibility version and not the release one */131#define XE_GSC_FIRMWARE_DEFS(fw_def, major_ver) \132 fw_def(LUNARLAKE, major_ver(xe, gsc, lnl, 104, 1, 0)) \133 fw_def(METEORLAKE, major_ver(i915, gsc, mtl, 102, 1, 0))134 135#define MAKE_FW_PATH(dir__, uc__, shortname__, version__) \136 __stringify(dir__) "/" __stringify(shortname__) "_" __stringify(uc__) version__ ".bin"137 138#define fw_filename_mmp_ver(dir_, uc_, shortname_, a, b, c) \139 MAKE_FW_PATH(dir_, uc_, shortname_, "_" __stringify(a ## . ## b ## . ## c))140#define fw_filename_major_ver(dir_, uc_, shortname_, a, b, c) \141 MAKE_FW_PATH(dir_, uc_, shortname_, "_" __stringify(a))142#define fw_filename_no_ver(dir_, uc_, shortname_) \143 MAKE_FW_PATH(dir_, uc_, shortname_, "")144#define fw_filename_gsc(dir_, uc_, shortname_, a, b, c) \145 MAKE_FW_PATH(dir_, uc_, shortname_, "_" __stringify(b))146 147#define uc_fw_entry_mmp_ver(dir_, uc_, shortname_, a, b, c) \148 { fw_filename_mmp_ver(dir_, uc_, shortname_, a, b, c), \149 a, b, c, true }150#define uc_fw_entry_major_ver(dir_, uc_, shortname_, a, b, c) \151 { fw_filename_major_ver(dir_, uc_, shortname_, a, b, c), \152 a, b, c }153#define uc_fw_entry_no_ver(dir_, uc_, shortname_) \154 { fw_filename_no_ver(dir_, uc_, shortname_), \155 0, 0 }156#define uc_fw_entry_gsc(dir_, uc_, shortname_, a, b, c) \157 { fw_filename_gsc(dir_, uc_, shortname_, a, b, c), \158 a, b, c }159 160/* All blobs need to be declared via MODULE_FIRMWARE() */161#define XE_UC_MODULE_FIRMWARE(platform__, fw_filename) \162 MODULE_FIRMWARE(fw_filename);163 164#define XE_UC_FW_ENTRY(platform__, entry__) \165 { \166 .platform = XE_ ## platform__, \167 entry__, \168 },169 170XE_GUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,171 fw_filename_mmp_ver, fw_filename_major_ver)172XE_HUC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE,173 fw_filename_mmp_ver, fw_filename_no_ver)174XE_GSC_FIRMWARE_DEFS(XE_UC_MODULE_FIRMWARE, fw_filename_gsc)175 176static struct xe_gt *177__uc_fw_to_gt(struct xe_uc_fw *uc_fw, enum xe_uc_fw_type type)178{179 XE_WARN_ON(type >= XE_UC_FW_NUM_TYPES);180 181 switch (type) {182 case XE_UC_FW_TYPE_GUC:183 return container_of(uc_fw, struct xe_gt, uc.guc.fw);184 case XE_UC_FW_TYPE_HUC:185 return container_of(uc_fw, struct xe_gt, uc.huc.fw);186 case XE_UC_FW_TYPE_GSC:187 return container_of(uc_fw, struct xe_gt, uc.gsc.fw);188 default:189 return NULL;190 }191}192 193static struct xe_gt *uc_fw_to_gt(struct xe_uc_fw *uc_fw)194{195 return __uc_fw_to_gt(uc_fw, uc_fw->type);196}197 198static struct xe_device *uc_fw_to_xe(struct xe_uc_fw *uc_fw)199{200 return gt_to_xe(uc_fw_to_gt(uc_fw));201}202 203static void204uc_fw_auto_select(struct xe_device *xe, struct xe_uc_fw *uc_fw)205{206 static const struct uc_fw_entry entries_guc[] = {207 XE_GUC_FIRMWARE_DEFS(XE_UC_FW_ENTRY,208 uc_fw_entry_mmp_ver,209 uc_fw_entry_major_ver)210 };211 static const struct uc_fw_entry entries_huc[] = {212 XE_HUC_FIRMWARE_DEFS(XE_UC_FW_ENTRY,213 uc_fw_entry_mmp_ver,214 uc_fw_entry_no_ver)215 };216 static const struct uc_fw_entry entries_gsc[] = {217 XE_GSC_FIRMWARE_DEFS(XE_UC_FW_ENTRY, uc_fw_entry_gsc)218 };219 static const struct fw_blobs_by_type blobs_all[XE_UC_FW_NUM_TYPES] = {220 [XE_UC_FW_TYPE_GUC] = { entries_guc, ARRAY_SIZE(entries_guc) },221 [XE_UC_FW_TYPE_HUC] = { entries_huc, ARRAY_SIZE(entries_huc) },222 [XE_UC_FW_TYPE_GSC] = { entries_gsc, ARRAY_SIZE(entries_gsc) },223 };224 static const struct uc_fw_entry *entries;225 enum xe_platform p = xe->info.platform;226 u32 count;227 int i;228 229 xe_assert(xe, uc_fw->type < ARRAY_SIZE(blobs_all));230 entries = blobs_all[uc_fw->type].entries;231 count = blobs_all[uc_fw->type].count;232 233 for (i = 0; i < count && p <= entries[i].platform; i++) {234 if (p == entries[i].platform) {235 uc_fw->path = entries[i].path;236 uc_fw->versions.wanted.major = entries[i].major;237 uc_fw->versions.wanted.minor = entries[i].minor;238 uc_fw->versions.wanted.patch = entries[i].patch;239 uc_fw->full_ver_required = entries[i].full_ver_required;240 241 if (uc_fw->type == XE_UC_FW_TYPE_GSC)242 uc_fw->versions.wanted_type = XE_UC_FW_VER_COMPATIBILITY;243 else244 uc_fw->versions.wanted_type = XE_UC_FW_VER_RELEASE;245 246 break;247 }248 }249}250 251static void252uc_fw_override(struct xe_uc_fw *uc_fw)253{254 char *path_override = NULL;255 256 /* empty string disables, but it's not allowed for GuC */257 switch (uc_fw->type) {258 case XE_UC_FW_TYPE_GUC:259 if (xe_modparam.guc_firmware_path && *xe_modparam.guc_firmware_path)260 path_override = xe_modparam.guc_firmware_path;261 break;262 case XE_UC_FW_TYPE_HUC:263 path_override = xe_modparam.huc_firmware_path;264 break;265 case XE_UC_FW_TYPE_GSC:266 path_override = xe_modparam.gsc_firmware_path;267 break;268 default:269 break;270 }271 272 if (path_override) {273 uc_fw->path = path_override;274 uc_fw->user_overridden = true;275 }276}277 278/**279 * xe_uc_fw_copy_rsa - copy fw RSA to buffer280 *281 * @uc_fw: uC firmware282 * @dst: dst buffer283 * @max_len: max number of bytes to copy284 *285 * Return: number of copied bytes.286 */287size_t xe_uc_fw_copy_rsa(struct xe_uc_fw *uc_fw, void *dst, u32 max_len)288{289 struct xe_device *xe = uc_fw_to_xe(uc_fw);290 u32 size = min_t(u32, uc_fw->rsa_size, max_len);291 292 xe_assert(xe, !(size % 4));293 xe_assert(xe, xe_uc_fw_is_available(uc_fw));294 295 xe_map_memcpy_from(xe, dst, &uc_fw->bo->vmap,296 xe_uc_fw_rsa_offset(uc_fw), size);297 298 return size;299}300 301static void uc_fw_fini(struct drm_device *drm, void *arg)302{303 struct xe_uc_fw *uc_fw = arg;304 305 if (!xe_uc_fw_is_available(uc_fw))306 return;307 308 xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_SELECTED);309}310 311static int guc_read_css_info(struct xe_uc_fw *uc_fw, struct uc_css_header *css)312{313 struct xe_gt *gt = uc_fw_to_gt(uc_fw);314 struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];315 struct xe_uc_fw_version *compatibility = &uc_fw->versions.found[XE_UC_FW_VER_COMPATIBILITY];316 317 xe_gt_assert(gt, uc_fw->type == XE_UC_FW_TYPE_GUC);318 319 /* We don't support GuC releases older than 70.29.2 */320 if (MAKE_GUC_VER_STRUCT(*release) < MAKE_GUC_VER(70, 29, 2)) {321 xe_gt_err(gt, "Unsupported GuC v%u.%u.%u! v70.29.2 or newer is required\n",322 release->major, release->minor, release->patch);323 return -EINVAL;324 }325 326 compatibility->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, css->submission_version);327 compatibility->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, css->submission_version);328 compatibility->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, css->submission_version);329 330 uc_fw->private_data_size = css->private_data_size;331 332 return 0;333}334 335int xe_uc_fw_check_version_requirements(struct xe_uc_fw *uc_fw)336{337 struct xe_device *xe = uc_fw_to_xe(uc_fw);338 struct xe_uc_fw_version *wanted = &uc_fw->versions.wanted;339 struct xe_uc_fw_version *found = &uc_fw->versions.found[uc_fw->versions.wanted_type];340 341 /* Driver has no requirement on any version, any is good. */342 if (!wanted->major)343 return 0;344 345 /*346 * If full version is required, both major and minor should match.347 * Otherwise, at least the major version.348 */349 if (wanted->major != found->major ||350 (uc_fw->full_ver_required &&351 ((wanted->minor != found->minor) ||352 (wanted->patch != found->patch)))) {353 drm_notice(&xe->drm, "%s firmware %s: unexpected version: %u.%u.%u != %u.%u.%u\n",354 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,355 found->major, found->minor, found->patch,356 wanted->major, wanted->minor, wanted->patch);357 goto fail;358 }359 360 if (wanted->minor > found->minor ||361 (wanted->minor == found->minor && wanted->patch > found->patch)) {362 drm_notice(&xe->drm, "%s firmware (%u.%u.%u) is recommended, but only (%u.%u.%u) was found in %s\n",363 xe_uc_fw_type_repr(uc_fw->type),364 wanted->major, wanted->minor, wanted->patch,365 found->major, found->minor, found->patch,366 uc_fw->path);367 drm_info(&xe->drm, "Consider updating your linux-firmware pkg or downloading from %s\n",368 XE_UC_FIRMWARE_URL);369 }370 371 return 0;372 373fail:374 if (xe_uc_fw_is_overridden(uc_fw))375 return 0;376 377 return -ENOEXEC;378}379 380/* Refer to the "CSS-based Firmware Layout" documentation entry for details */381static int parse_css_header(struct xe_uc_fw *uc_fw, const void *fw_data, size_t fw_size)382{383 struct xe_device *xe = uc_fw_to_xe(uc_fw);384 struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];385 struct uc_css_header *css;386 size_t size;387 388 /* Check the size of the blob before examining buffer contents */389 if (unlikely(fw_size < sizeof(struct uc_css_header))) {390 drm_warn(&xe->drm, "%s firmware %s: invalid size: %zu < %zu\n",391 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,392 fw_size, sizeof(struct uc_css_header));393 return -ENODATA;394 }395 396 css = (struct uc_css_header *)fw_data;397 398 /* Check integrity of size values inside CSS header */399 size = (css->header_size_dw - css->key_size_dw - css->modulus_size_dw -400 css->exponent_size_dw) * sizeof(u32);401 if (unlikely(size != sizeof(struct uc_css_header))) {402 drm_warn(&xe->drm,403 "%s firmware %s: unexpected header size: %zu != %zu\n",404 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,405 fw_size, sizeof(struct uc_css_header));406 return -EPROTO;407 }408 409 /* uCode size must calculated from other sizes */410 uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);411 412 /* now RSA */413 uc_fw->rsa_size = css->key_size_dw * sizeof(u32);414 415 /* At least, it should have header, uCode and RSA. Size of all three. */416 size = sizeof(struct uc_css_header) + uc_fw->ucode_size +417 uc_fw->rsa_size;418 if (unlikely(fw_size < size)) {419 drm_warn(&xe->drm, "%s firmware %s: invalid size: %zu < %zu\n",420 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,421 fw_size, size);422 return -ENOEXEC;423 }424 425 /* Get version numbers from the CSS header */426 release->major = FIELD_GET(CSS_SW_VERSION_UC_MAJOR, css->sw_version);427 release->minor = FIELD_GET(CSS_SW_VERSION_UC_MINOR, css->sw_version);428 release->patch = FIELD_GET(CSS_SW_VERSION_UC_PATCH, css->sw_version);429 430 if (uc_fw->type == XE_UC_FW_TYPE_GUC)431 return guc_read_css_info(uc_fw, css);432 433 return 0;434}435 436static bool is_cpd_header(const void *data)437{438 const u32 *marker = data;439 440 return *marker == GSC_CPD_HEADER_MARKER;441}442 443static u32 entry_offset(const struct gsc_cpd_header_v2 *header, const char *name)444{445 const struct gsc_cpd_entry *entry;446 int i;447 448 entry = (void *)header + header->header_length;449 450 for (i = 0; i < header->num_of_entries; i++, entry++)451 if (strcmp(entry->name, name) == 0)452 return entry->offset & GSC_CPD_ENTRY_OFFSET_MASK;453 454 return 0;455}456 457/* Refer to the "GSC-based Firmware Layout" documentation entry for details */458static int parse_cpd_header(struct xe_uc_fw *uc_fw, const void *data, size_t size,459 const char *manifest_entry, const char *css_entry)460{461 struct xe_gt *gt = uc_fw_to_gt(uc_fw);462 struct xe_device *xe = gt_to_xe(gt);463 const struct gsc_cpd_header_v2 *header = data;464 struct xe_uc_fw_version *release = &uc_fw->versions.found[XE_UC_FW_VER_RELEASE];465 const struct gsc_manifest_header *manifest;466 size_t min_size = sizeof(*header);467 u32 offset;468 469 /* manifest_entry is mandatory, css_entry is optional */470 xe_assert(xe, manifest_entry);471 472 if (size < min_size || !is_cpd_header(header))473 return -ENOENT;474 475 if (header->header_length < sizeof(struct gsc_cpd_header_v2)) {476 xe_gt_err(gt, "invalid CPD header length %u!\n", header->header_length);477 return -EINVAL;478 }479 480 min_size = header->header_length + sizeof(struct gsc_cpd_entry) * header->num_of_entries;481 if (size < min_size) {482 xe_gt_err(gt, "FW too small! %zu < %zu\n", size, min_size);483 return -ENODATA;484 }485 486 /* Look for the manifest first */487 offset = entry_offset(header, manifest_entry);488 if (!offset) {489 xe_gt_err(gt, "Failed to find %s manifest!\n",490 xe_uc_fw_type_repr(uc_fw->type));491 return -ENODATA;492 }493 494 min_size = offset + sizeof(struct gsc_manifest_header);495 if (size < min_size) {496 xe_gt_err(gt, "FW too small! %zu < %zu\n", size, min_size);497 return -ENODATA;498 }499 500 manifest = data + offset;501 502 release->major = manifest->fw_version.major;503 release->minor = manifest->fw_version.minor;504 release->patch = manifest->fw_version.hotfix;505 506 if (uc_fw->type == XE_UC_FW_TYPE_GSC) {507 struct xe_gsc *gsc = container_of(uc_fw, struct xe_gsc, fw);508 509 release->build = manifest->fw_version.build;510 gsc->security_version = manifest->security_version;511 }512 513 /* then optionally look for the css header */514 if (css_entry) {515 int ret;516 517 /*518 * This section does not contain a CSS entry on DG2. We519 * don't support DG2 HuC right now, so no need to handle520 * it, just add a reminder in case that changes.521 */522 xe_assert(xe, xe->info.platform != XE_DG2);523 524 offset = entry_offset(header, css_entry);525 526 /* the CSS header parser will check that the CSS header fits */527 if (offset > size) {528 xe_gt_err(gt, "FW too small! %zu < %u\n", size, offset);529 return -ENODATA;530 }531 532 ret = parse_css_header(uc_fw, data + offset, size - offset);533 if (ret)534 return ret;535 536 uc_fw->css_offset = offset;537 }538 539 uc_fw->has_gsc_headers = true;540 541 return 0;542}543 544static int parse_gsc_layout(struct xe_uc_fw *uc_fw, const void *data, size_t size)545{546 struct xe_gt *gt = uc_fw_to_gt(uc_fw);547 const struct gsc_layout_pointers *layout = data;548 const struct gsc_bpdt_header *bpdt_header = NULL;549 const struct gsc_bpdt_entry *bpdt_entry = NULL;550 size_t min_size = sizeof(*layout);551 int i;552 553 if (size < min_size) {554 xe_gt_err(gt, "GSC FW too small! %zu < %zu\n", size, min_size);555 return -ENODATA;556 }557 558 min_size = layout->boot1.offset + layout->boot1.size;559 if (size < min_size) {560 xe_gt_err(gt, "GSC FW too small for boot section! %zu < %zu\n",561 size, min_size);562 return -ENODATA;563 }564 565 min_size = sizeof(*bpdt_header);566 if (layout->boot1.size < min_size) {567 xe_gt_err(gt, "GSC FW boot section too small for BPDT header: %u < %zu\n",568 layout->boot1.size, min_size);569 return -ENODATA;570 }571 572 bpdt_header = data + layout->boot1.offset;573 if (bpdt_header->signature != GSC_BPDT_HEADER_SIGNATURE) {574 xe_gt_err(gt, "invalid signature for BPDT header: 0x%08x!\n",575 bpdt_header->signature);576 return -EINVAL;577 }578 579 min_size += sizeof(*bpdt_entry) * bpdt_header->descriptor_count;580 if (layout->boot1.size < min_size) {581 xe_gt_err(gt, "GSC FW boot section too small for BPDT entries: %u < %zu\n",582 layout->boot1.size, min_size);583 return -ENODATA;584 }585 586 bpdt_entry = (void *)bpdt_header + sizeof(*bpdt_header);587 for (i = 0; i < bpdt_header->descriptor_count; i++, bpdt_entry++) {588 if ((bpdt_entry->type & GSC_BPDT_ENTRY_TYPE_MASK) !=589 GSC_BPDT_ENTRY_TYPE_GSC_RBE)590 continue;591 592 min_size = bpdt_entry->sub_partition_offset;593 594 /* the CPD header parser will check that the CPD header fits */595 if (layout->boot1.size < min_size) {596 xe_gt_err(gt, "GSC FW boot section too small for CPD offset: %u < %zu\n",597 layout->boot1.size, min_size);598 return -ENODATA;599 }600 601 return parse_cpd_header(uc_fw,602 (void *)bpdt_header + min_size,603 layout->boot1.size - min_size,604 "RBEP.man", NULL);605 }606 607 xe_gt_err(gt, "couldn't find CPD header in GSC binary!\n");608 return -ENODATA;609}610 611static int parse_headers(struct xe_uc_fw *uc_fw, const struct firmware *fw)612{613 int ret;614 615 /*616 * All GuC releases and older HuC ones use CSS headers, while newer HuC617 * releases use GSC CPD headers.618 */619 switch (uc_fw->type) {620 case XE_UC_FW_TYPE_GSC:621 return parse_gsc_layout(uc_fw, fw->data, fw->size);622 case XE_UC_FW_TYPE_HUC:623 ret = parse_cpd_header(uc_fw, fw->data, fw->size, "HUCP.man", "huc_fw");624 if (!ret || ret != -ENOENT)625 return ret;626 fallthrough;627 case XE_UC_FW_TYPE_GUC:628 return parse_css_header(uc_fw, fw->data, fw->size);629 default:630 return -EINVAL;631 }632 633 return 0;634}635 636#define print_uc_fw_version(p_, version_, prefix_, ...) \637do { \638 struct xe_uc_fw_version *ver_ = (version_); \639 if (ver_->build) \640 drm_printf(p_, prefix_ " version %u.%u.%u.%u\n", ##__VA_ARGS__, \641 ver_->major, ver_->minor, \642 ver_->patch, ver_->build); \643 else \644 drm_printf(p_, prefix_ " version %u.%u.%u\n", ##__VA_ARGS__, \645 ver_->major, ver_->minor, ver_->patch); \646} while (0)647 648static int uc_fw_request(struct xe_uc_fw *uc_fw, const struct firmware **firmware_p)649{650 struct xe_device *xe = uc_fw_to_xe(uc_fw);651 struct device *dev = xe->drm.dev;652 struct drm_printer p = drm_info_printer(dev);653 const struct firmware *fw = NULL;654 int err;655 656 /*657 * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status658 * before we're looked at the HW caps to see if we have uc support659 */660 BUILD_BUG_ON(XE_UC_FIRMWARE_UNINITIALIZED);661 xe_assert(xe, !uc_fw->status);662 xe_assert(xe, !uc_fw->path);663 664 uc_fw_auto_select(xe, uc_fw);665 666 if (IS_SRIOV_VF(xe)) {667 /* Only GuC/HuC are supported */668 if (uc_fw->type != XE_UC_FW_TYPE_GUC &&669 uc_fw->type != XE_UC_FW_TYPE_HUC)670 uc_fw->path = NULL;671 /* VF will support only firmwares that driver can autoselect */672 xe_uc_fw_change_status(uc_fw, uc_fw->path ?673 XE_UC_FIRMWARE_PRELOADED :674 XE_UC_FIRMWARE_NOT_SUPPORTED);675 return 0;676 }677 678 uc_fw_override(uc_fw);679 680 xe_uc_fw_change_status(uc_fw, uc_fw->path ?681 XE_UC_FIRMWARE_SELECTED :682 XE_UC_FIRMWARE_NOT_SUPPORTED);683 684 if (!xe_uc_fw_is_supported(uc_fw)) {685 if (uc_fw->type == XE_UC_FW_TYPE_GUC) {686 drm_err(&xe->drm, "No GuC firmware defined for platform\n");687 return -ENOENT;688 }689 return 0;690 }691 692 /* an empty path means the firmware is disabled */693 if (!xe_device_uc_enabled(xe) || !(*uc_fw->path)) {694 xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_DISABLED);695 drm_dbg(&xe->drm, "%s disabled", xe_uc_fw_type_repr(uc_fw->type));696 return 0;697 }698 699 err = request_firmware(&fw, uc_fw->path, dev);700 if (err)701 goto fail;702 703 err = parse_headers(uc_fw, fw);704 if (err)705 goto fail;706 707 print_uc_fw_version(&p,708 &uc_fw->versions.found[XE_UC_FW_VER_RELEASE],709 "Using %s firmware from %s",710 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);711 712 /* for GSC FW we want the compatibility version, which we query after load */713 if (uc_fw->type != XE_UC_FW_TYPE_GSC) {714 err = xe_uc_fw_check_version_requirements(uc_fw);715 if (err)716 goto fail;717 }718 719 *firmware_p = fw;720 721 return 0;722 723fail:724 xe_uc_fw_change_status(uc_fw, err == -ENOENT ?725 XE_UC_FIRMWARE_MISSING :726 XE_UC_FIRMWARE_ERROR);727 728 drm_notice(&xe->drm, "%s firmware %s: fetch failed with error %d\n",729 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);730 drm_info(&xe->drm, "%s firmware(s) can be downloaded from %s\n",731 xe_uc_fw_type_repr(uc_fw->type), XE_UC_FIRMWARE_URL);732 733 release_firmware(fw); /* OK even if fw is NULL */734 735 return err;736}737 738static void uc_fw_release(const struct firmware *fw)739{740 release_firmware(fw);741}742 743static int uc_fw_copy(struct xe_uc_fw *uc_fw, const void *data, size_t size, u32 flags)744{745 struct xe_device *xe = uc_fw_to_xe(uc_fw);746 struct xe_gt *gt = uc_fw_to_gt(uc_fw);747 struct xe_tile *tile = gt_to_tile(gt);748 struct xe_bo *obj;749 int err;750 751 obj = xe_managed_bo_create_from_data(xe, tile, data, size, flags);752 if (IS_ERR(obj)) {753 drm_notice(&xe->drm, "%s firmware %s: failed to create / populate bo",754 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);755 err = PTR_ERR(obj);756 goto fail;757 }758 759 uc_fw->bo = obj;760 uc_fw->size = size;761 762 xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_AVAILABLE);763 764 err = drmm_add_action_or_reset(&xe->drm, uc_fw_fini, uc_fw);765 if (err)766 goto fail;767 768 return 0;769 770fail:771 xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_ERROR);772 drm_notice(&xe->drm, "%s firmware %s: copy failed with error %d\n",773 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);774 775 return err;776}777 778int xe_uc_fw_init(struct xe_uc_fw *uc_fw)779{780 const struct firmware *fw = NULL;781 int err;782 783 err = uc_fw_request(uc_fw, &fw);784 if (err)785 return err;786 787 /* no error and no firmware means nothing to copy */788 if (!fw)789 return 0;790 791 err = uc_fw_copy(uc_fw, fw->data, fw->size,792 XE_BO_FLAG_SYSTEM | XE_BO_FLAG_GGTT |793 XE_BO_FLAG_GGTT_INVALIDATE);794 795 uc_fw_release(fw);796 797 return err;798}799 800static u32 uc_fw_ggtt_offset(struct xe_uc_fw *uc_fw)801{802 return xe_bo_ggtt_addr(uc_fw->bo);803}804 805static int uc_fw_xfer(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags)806{807 struct xe_device *xe = uc_fw_to_xe(uc_fw);808 struct xe_gt *gt = uc_fw_to_gt(uc_fw);809 u64 src_offset;810 u32 dma_ctrl;811 int ret;812 813 xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT);814 815 /* Set the source address for the uCode */816 src_offset = uc_fw_ggtt_offset(uc_fw) + uc_fw->css_offset;817 xe_mmio_write32(gt, DMA_ADDR_0_LOW, lower_32_bits(src_offset));818 xe_mmio_write32(gt, DMA_ADDR_0_HIGH,819 upper_32_bits(src_offset) | DMA_ADDRESS_SPACE_GGTT);820 821 /* Set the DMA destination */822 xe_mmio_write32(gt, DMA_ADDR_1_LOW, offset);823 xe_mmio_write32(gt, DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);824 825 /*826 * Set the transfer size. The header plus uCode will be copied to WOPCM827 * via DMA, excluding any other components828 */829 xe_mmio_write32(gt, DMA_COPY_SIZE,830 sizeof(struct uc_css_header) + uc_fw->ucode_size);831 832 /* Start the DMA */833 xe_mmio_write32(gt, DMA_CTRL,834 _MASKED_BIT_ENABLE(dma_flags | START_DMA));835 836 /* Wait for DMA to finish */837 ret = xe_mmio_wait32(gt, DMA_CTRL, START_DMA, 0, 100000, &dma_ctrl,838 false);839 if (ret)840 drm_err(&xe->drm, "DMA for %s fw failed, DMA_CTRL=%u\n",841 xe_uc_fw_type_repr(uc_fw->type), dma_ctrl);842 843 /* Disable the bits once DMA is over */844 xe_mmio_write32(gt, DMA_CTRL, _MASKED_BIT_DISABLE(dma_flags));845 846 return ret;847}848 849int xe_uc_fw_upload(struct xe_uc_fw *uc_fw, u32 offset, u32 dma_flags)850{851 struct xe_device *xe = uc_fw_to_xe(uc_fw);852 int err;853 854 /* make sure the status was cleared the last time we reset the uc */855 xe_assert(xe, !xe_uc_fw_is_loaded(uc_fw));856 857 if (!xe_uc_fw_is_loadable(uc_fw))858 return -ENOEXEC;859 860 /* Call custom loader */861 err = uc_fw_xfer(uc_fw, offset, dma_flags);862 if (err)863 goto fail;864 865 xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_TRANSFERRED);866 return 0;867 868fail:869 drm_err(&xe->drm, "Failed to load %s firmware %s (%d)\n",870 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path,871 err);872 xe_uc_fw_change_status(uc_fw, XE_UC_FIRMWARE_LOAD_FAIL);873 return err;874}875 876static const char *version_type_repr(enum xe_uc_fw_version_types type)877{878 switch (type) {879 case XE_UC_FW_VER_RELEASE:880 return "release";881 case XE_UC_FW_VER_COMPATIBILITY:882 return "compatibility";883 default:884 return "Unknown version type";885 }886}887 888void xe_uc_fw_print(struct xe_uc_fw *uc_fw, struct drm_printer *p)889{890 int i;891 892 drm_printf(p, "%s firmware: %s\n",893 xe_uc_fw_type_repr(uc_fw->type), uc_fw->path);894 drm_printf(p, "\tstatus: %s\n",895 xe_uc_fw_status_repr(uc_fw->status));896 897 print_uc_fw_version(p, &uc_fw->versions.wanted, "\twanted %s",898 version_type_repr(uc_fw->versions.wanted_type));899 900 for (i = 0; i < XE_UC_FW_VER_TYPE_COUNT; i++) {901 struct xe_uc_fw_version *ver = &uc_fw->versions.found[i];902 903 if (ver->major)904 print_uc_fw_version(p, ver, "\tfound %s",905 version_type_repr(i));906 }907 908 if (uc_fw->ucode_size)909 drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);910 if (uc_fw->rsa_size)911 drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);912}913