root/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __uc_fw_to_gt
  2. intel_uc_fw_change_status
  3. INTEL_UC_FIRMWARE_DEFS
  4. __uc_fw_auto_select
  5. __override_guc_firmware_path
  6. __override_huc_firmware_path
  7. __uc_fw_user_override
  8. intel_uc_fw_init_early
  9. __force_fw_fetch_failures
  10. intel_uc_fw_fetch
  11. uc_fw_ggtt_offset
  12. intel_uc_fw_ggtt_bind
  13. intel_uc_fw_ggtt_unbind
  14. uc_fw_xfer
  15. intel_uc_fw_upload
  16. intel_uc_fw_init
  17. intel_uc_fw_fini
  18. intel_uc_fw_cleanup_fetch
  19. intel_uc_fw_copy_rsa
  20. intel_uc_fw_dump

   1 // SPDX-License-Identifier: MIT
   2 /*
   3  * Copyright © 2016-2019 Intel Corporation
   4  */
   5 
   6 #include <linux/bitfield.h>
   7 #include <linux/firmware.h>
   8 #include <drm/drm_print.h>
   9 
  10 #include "intel_uc_fw.h"
  11 #include "intel_uc_fw_abi.h"
  12 #include "i915_drv.h"
  13 
  14 #ifdef CONFIG_DRM_I915_DEBUG_GUC
  15 static inline struct intel_gt *__uc_fw_to_gt(struct intel_uc_fw *uc_fw)
  16 {
  17         GEM_BUG_ON(uc_fw->status == INTEL_UC_FIRMWARE_UNINITIALIZED);
  18         if (uc_fw->type == INTEL_UC_FW_TYPE_GUC)
  19                 return container_of(uc_fw, struct intel_gt, uc.guc.fw);
  20 
  21         GEM_BUG_ON(uc_fw->type != INTEL_UC_FW_TYPE_HUC);
  22         return container_of(uc_fw, struct intel_gt, uc.huc.fw);
  23 }
  24 
  25 void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
  26                                enum intel_uc_fw_status status)
  27 {
  28         uc_fw->__status =  status;
  29         DRM_DEV_DEBUG_DRIVER(__uc_fw_to_gt(uc_fw)->i915->drm.dev,
  30                              "%s firmware -> %s\n",
  31                              intel_uc_fw_type_repr(uc_fw->type),
  32                              status == INTEL_UC_FIRMWARE_SELECTED ?
  33                              uc_fw->path : intel_uc_fw_status_repr(status));
  34 }
  35 #endif
  36 
  37 /*
  38  * List of required GuC and HuC binaries per-platform.
  39  * Must be ordered based on platform + revid, from newer to older.
  40  */
  41 #define INTEL_UC_FIRMWARE_DEFS(fw_def, guc_def, huc_def) \
  42         fw_def(ICELAKE,    0, guc_def(icl, 33, 0, 0), huc_def(icl,  8,  4, 3238)) \
  43         fw_def(COFFEELAKE, 0, guc_def(kbl, 33, 0, 0), huc_def(kbl, 02, 00, 1810)) \
  44         fw_def(GEMINILAKE, 0, guc_def(glk, 33, 0, 0), huc_def(glk, 03, 01, 2893)) \
  45         fw_def(KABYLAKE,   0, guc_def(kbl, 33, 0, 0), huc_def(kbl, 02, 00, 1810)) \
  46         fw_def(BROXTON,    0, guc_def(bxt, 33, 0, 0), huc_def(bxt, 01,  8, 2893)) \
  47         fw_def(SKYLAKE,    0, guc_def(skl, 33, 0, 0), huc_def(skl, 01, 07, 1398))
  48 
  49 #define __MAKE_UC_FW_PATH(prefix_, name_, separator_, major_, minor_, patch_) \
  50         "i915/" \
  51         __stringify(prefix_) name_ \
  52         __stringify(major_) separator_ \
  53         __stringify(minor_) separator_ \
  54         __stringify(patch_) ".bin"
  55 
  56 #define MAKE_GUC_FW_PATH(prefix_, major_, minor_, patch_) \
  57         __MAKE_UC_FW_PATH(prefix_, "_guc_", ".", major_, minor_, patch_)
  58 
  59 #define MAKE_HUC_FW_PATH(prefix_, major_, minor_, bld_num_) \
  60         __MAKE_UC_FW_PATH(prefix_, "_huc_ver", "_", major_, minor_, bld_num_)
  61 
  62 /* All blobs need to be declared via MODULE_FIRMWARE() */
  63 #define INTEL_UC_MODULE_FW(platform_, revid_, guc_, huc_) \
  64         MODULE_FIRMWARE(guc_); \
  65         MODULE_FIRMWARE(huc_);
  66 
  67 INTEL_UC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH, MAKE_HUC_FW_PATH)
  68 
  69 /* The below structs and macros are used to iterate across the list of blobs */
  70 struct __packed uc_fw_blob {
  71         u8 major;
  72         u8 minor;
  73         const char *path;
  74 };
  75 
  76 #define UC_FW_BLOB(major_, minor_, path_) \
  77         { .major = major_, .minor = minor_, .path = path_ }
  78 
  79 #define GUC_FW_BLOB(prefix_, major_, minor_, patch_) \
  80         UC_FW_BLOB(major_, minor_, \
  81                    MAKE_GUC_FW_PATH(prefix_, major_, minor_, patch_))
  82 
  83 #define HUC_FW_BLOB(prefix_, major_, minor_, bld_num_) \
  84         UC_FW_BLOB(major_, minor_, \
  85                    MAKE_HUC_FW_PATH(prefix_, major_, minor_, bld_num_))
  86 
  87 struct __packed uc_fw_platform_requirement {
  88         enum intel_platform p;
  89         u8 rev; /* first platform rev using this FW */
  90         const struct uc_fw_blob blobs[INTEL_UC_FW_NUM_TYPES];
  91 };
  92 
  93 #define MAKE_FW_LIST(platform_, revid_, guc_, huc_) \
  94 { \
  95         .p = INTEL_##platform_, \
  96         .rev = revid_, \
  97         .blobs[INTEL_UC_FW_TYPE_GUC] = guc_, \
  98         .blobs[INTEL_UC_FW_TYPE_HUC] = huc_, \
  99 },
 100 
 101 static void
 102 __uc_fw_auto_select(struct intel_uc_fw *uc_fw, enum intel_platform p, u8 rev)
 103 {
 104         static const struct uc_fw_platform_requirement fw_blobs[] = {
 105                 INTEL_UC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, HUC_FW_BLOB)
 106         };
 107         int i;
 108 
 109         for (i = 0; i < ARRAY_SIZE(fw_blobs) && p <= fw_blobs[i].p; i++) {
 110                 if (p == fw_blobs[i].p && rev >= fw_blobs[i].rev) {
 111                         const struct uc_fw_blob *blob =
 112                                         &fw_blobs[i].blobs[uc_fw->type];
 113                         uc_fw->path = blob->path;
 114                         uc_fw->major_ver_wanted = blob->major;
 115                         uc_fw->minor_ver_wanted = blob->minor;
 116                         break;
 117                 }
 118         }
 119 
 120         /* make sure the list is ordered as expected */
 121         if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST)) {
 122                 for (i = 1; i < ARRAY_SIZE(fw_blobs); i++) {
 123                         if (fw_blobs[i].p < fw_blobs[i - 1].p)
 124                                 continue;
 125 
 126                         if (fw_blobs[i].p == fw_blobs[i - 1].p &&
 127                             fw_blobs[i].rev < fw_blobs[i - 1].rev)
 128                                 continue;
 129 
 130                         pr_err("invalid FW blob order: %s r%u comes before %s r%u\n",
 131                                intel_platform_name(fw_blobs[i - 1].p),
 132                                fw_blobs[i - 1].rev,
 133                                intel_platform_name(fw_blobs[i].p),
 134                                fw_blobs[i].rev);
 135 
 136                         uc_fw->path = NULL;
 137                 }
 138         }
 139 
 140         /* We don't want to enable GuC/HuC on pre-Gen11 by default */
 141         if (i915_modparams.enable_guc == -1 && p < INTEL_ICELAKE)
 142                 uc_fw->path = NULL;
 143 }
 144 
 145 static const char *__override_guc_firmware_path(void)
 146 {
 147         if (i915_modparams.enable_guc & (ENABLE_GUC_SUBMISSION |
 148                                          ENABLE_GUC_LOAD_HUC))
 149                 return i915_modparams.guc_firmware_path;
 150         return "";
 151 }
 152 
 153 static const char *__override_huc_firmware_path(void)
 154 {
 155         if (i915_modparams.enable_guc & ENABLE_GUC_LOAD_HUC)
 156                 return i915_modparams.huc_firmware_path;
 157         return "";
 158 }
 159 
 160 static void __uc_fw_user_override(struct intel_uc_fw *uc_fw)
 161 {
 162         const char *path = NULL;
 163 
 164         switch (uc_fw->type) {
 165         case INTEL_UC_FW_TYPE_GUC:
 166                 path = __override_guc_firmware_path();
 167                 break;
 168         case INTEL_UC_FW_TYPE_HUC:
 169                 path = __override_huc_firmware_path();
 170                 break;
 171         }
 172 
 173         if (unlikely(path)) {
 174                 uc_fw->path = path;
 175                 uc_fw->user_overridden = true;
 176         }
 177 }
 178 
 179 /**
 180  * intel_uc_fw_init_early - initialize the uC object and select the firmware
 181  * @uc_fw: uC firmware
 182  * @type: type of uC
 183  * @supported: is uC support possible
 184  * @platform: platform identifier
 185  * @rev: hardware revision
 186  *
 187  * Initialize the state of our uC object and relevant tracking and select the
 188  * firmware to fetch and load.
 189  */
 190 void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
 191                             enum intel_uc_fw_type type, bool supported,
 192                             enum intel_platform platform, u8 rev)
 193 {
 194         /*
 195          * we use FIRMWARE_UNINITIALIZED to detect checks against uc_fw->status
 196          * before we're looked at the HW caps to see if we have uc support
 197          */
 198         BUILD_BUG_ON(INTEL_UC_FIRMWARE_UNINITIALIZED);
 199         GEM_BUG_ON(uc_fw->status);
 200         GEM_BUG_ON(uc_fw->path);
 201 
 202         uc_fw->type = type;
 203 
 204         if (supported) {
 205                 __uc_fw_auto_select(uc_fw, platform, rev);
 206                 __uc_fw_user_override(uc_fw);
 207         }
 208 
 209         intel_uc_fw_change_status(uc_fw, uc_fw->path ? *uc_fw->path ?
 210                                   INTEL_UC_FIRMWARE_SELECTED :
 211                                   INTEL_UC_FIRMWARE_DISABLED :
 212                                   INTEL_UC_FIRMWARE_NOT_SUPPORTED);
 213 }
 214 
 215 static void __force_fw_fetch_failures(struct intel_uc_fw *uc_fw,
 216                                       struct drm_i915_private *i915,
 217                                       int e)
 218 {
 219         bool user = e == -EINVAL;
 220 
 221         if (i915_inject_load_error(i915, e)) {
 222                 /* non-existing blob */
 223                 uc_fw->path = "<invalid>";
 224                 uc_fw->user_overridden = user;
 225         } else if (i915_inject_load_error(i915, e)) {
 226                 /* require next major version */
 227                 uc_fw->major_ver_wanted += 1;
 228                 uc_fw->minor_ver_wanted = 0;
 229                 uc_fw->user_overridden = user;
 230         } else if (i915_inject_load_error(i915, e)) {
 231                 /* require next minor version */
 232                 uc_fw->minor_ver_wanted += 1;
 233                 uc_fw->user_overridden = user;
 234         } else if (uc_fw->major_ver_wanted && i915_inject_load_error(i915, e)) {
 235                 /* require prev major version */
 236                 uc_fw->major_ver_wanted -= 1;
 237                 uc_fw->minor_ver_wanted = 0;
 238                 uc_fw->user_overridden = user;
 239         } else if (uc_fw->minor_ver_wanted && i915_inject_load_error(i915, e)) {
 240                 /* require prev minor version - hey, this should work! */
 241                 uc_fw->minor_ver_wanted -= 1;
 242                 uc_fw->user_overridden = user;
 243         } else if (user && i915_inject_load_error(i915, e)) {
 244                 /* officially unsupported platform */
 245                 uc_fw->major_ver_wanted = 0;
 246                 uc_fw->minor_ver_wanted = 0;
 247                 uc_fw->user_overridden = true;
 248         }
 249 }
 250 
 251 /**
 252  * intel_uc_fw_fetch - fetch uC firmware
 253  * @uc_fw: uC firmware
 254  * @i915: device private
 255  *
 256  * Fetch uC firmware into GEM obj.
 257  *
 258  * Return: 0 on success, a negative errno code on failure.
 259  */
 260 int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw, struct drm_i915_private *i915)
 261 {
 262         struct device *dev = i915->drm.dev;
 263         struct drm_i915_gem_object *obj;
 264         const struct firmware *fw = NULL;
 265         struct uc_css_header *css;
 266         size_t size;
 267         int err;
 268 
 269         GEM_BUG_ON(!i915->wopcm.size);
 270         GEM_BUG_ON(!intel_uc_fw_is_enabled(uc_fw));
 271 
 272         err = i915_inject_load_error(i915, -ENXIO);
 273         if (err)
 274                 return err;
 275 
 276         __force_fw_fetch_failures(uc_fw, i915, -EINVAL);
 277         __force_fw_fetch_failures(uc_fw, i915, -ESTALE);
 278 
 279         err = request_firmware(&fw, uc_fw->path, dev);
 280         if (err)
 281                 goto fail;
 282 
 283         /* Check the size of the blob before examining buffer contents */
 284         if (unlikely(fw->size < sizeof(struct uc_css_header))) {
 285                 dev_warn(dev, "%s firmware %s: invalid size: %zu < %zu\n",
 286                          intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
 287                          fw->size, sizeof(struct uc_css_header));
 288                 err = -ENODATA;
 289                 goto fail;
 290         }
 291 
 292         css = (struct uc_css_header *)fw->data;
 293 
 294         /* Check integrity of size values inside CSS header */
 295         size = (css->header_size_dw - css->key_size_dw - css->modulus_size_dw -
 296                 css->exponent_size_dw) * sizeof(u32);
 297         if (unlikely(size != sizeof(struct uc_css_header))) {
 298                 dev_warn(dev,
 299                          "%s firmware %s: unexpected header size: %zu != %zu\n",
 300                          intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
 301                          fw->size, sizeof(struct uc_css_header));
 302                 err = -EPROTO;
 303                 goto fail;
 304         }
 305 
 306         /* uCode size must calculated from other sizes */
 307         uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
 308 
 309         /* now RSA */
 310         if (unlikely(css->key_size_dw != UOS_RSA_SCRATCH_COUNT)) {
 311                 dev_warn(dev, "%s firmware %s: unexpected key size: %u != %u\n",
 312                          intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
 313                          css->key_size_dw, UOS_RSA_SCRATCH_COUNT);
 314                 err = -EPROTO;
 315                 goto fail;
 316         }
 317         uc_fw->rsa_size = css->key_size_dw * sizeof(u32);
 318 
 319         /* At least, it should have header, uCode and RSA. Size of all three. */
 320         size = sizeof(struct uc_css_header) + uc_fw->ucode_size + uc_fw->rsa_size;
 321         if (unlikely(fw->size < size)) {
 322                 dev_warn(dev, "%s firmware %s: invalid size: %zu < %zu\n",
 323                          intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
 324                          fw->size, size);
 325                 err = -ENOEXEC;
 326                 goto fail;
 327         }
 328 
 329         /* Sanity check whether this fw is not larger than whole WOPCM memory */
 330         size = __intel_uc_fw_get_upload_size(uc_fw);
 331         if (unlikely(size >= i915->wopcm.size)) {
 332                 dev_warn(dev, "%s firmware %s: invalid size: %zu > %zu\n",
 333                          intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
 334                          size, (size_t)i915->wopcm.size);
 335                 err = -E2BIG;
 336                 goto fail;
 337         }
 338 
 339         /* Get version numbers from the CSS header */
 340         switch (uc_fw->type) {
 341         case INTEL_UC_FW_TYPE_GUC:
 342                 uc_fw->major_ver_found = FIELD_GET(CSS_SW_VERSION_GUC_MAJOR,
 343                                                    css->sw_version);
 344                 uc_fw->minor_ver_found = FIELD_GET(CSS_SW_VERSION_GUC_MINOR,
 345                                                    css->sw_version);
 346                 break;
 347 
 348         case INTEL_UC_FW_TYPE_HUC:
 349                 uc_fw->major_ver_found = FIELD_GET(CSS_SW_VERSION_HUC_MAJOR,
 350                                                    css->sw_version);
 351                 uc_fw->minor_ver_found = FIELD_GET(CSS_SW_VERSION_HUC_MINOR,
 352                                                    css->sw_version);
 353                 break;
 354 
 355         default:
 356                 MISSING_CASE(uc_fw->type);
 357                 break;
 358         }
 359 
 360         if (uc_fw->major_ver_found != uc_fw->major_ver_wanted ||
 361             uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) {
 362                 dev_notice(dev, "%s firmware %s: unexpected version: %u.%u != %u.%u\n",
 363                            intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
 364                            uc_fw->major_ver_found, uc_fw->minor_ver_found,
 365                            uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted);
 366                 if (!intel_uc_fw_is_overridden(uc_fw)) {
 367                         err = -ENOEXEC;
 368                         goto fail;
 369                 }
 370         }
 371 
 372         obj = i915_gem_object_create_shmem_from_data(i915, fw->data, fw->size);
 373         if (IS_ERR(obj)) {
 374                 err = PTR_ERR(obj);
 375                 goto fail;
 376         }
 377 
 378         uc_fw->obj = obj;
 379         uc_fw->size = fw->size;
 380         intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_AVAILABLE);
 381 
 382         release_firmware(fw);
 383         return 0;
 384 
 385 fail:
 386         intel_uc_fw_change_status(uc_fw, err == -ENOENT ?
 387                                   INTEL_UC_FIRMWARE_MISSING :
 388                                   INTEL_UC_FIRMWARE_ERROR);
 389 
 390         dev_notice(dev, "%s firmware %s: fetch failed with error %d\n",
 391                    intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err);
 392         dev_info(dev, "%s firmware(s) can be downloaded from %s\n",
 393                  intel_uc_fw_type_repr(uc_fw->type), INTEL_UC_FIRMWARE_URL);
 394 
 395         release_firmware(fw);           /* OK even if fw is NULL */
 396         return err;
 397 }
 398 
 399 static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw, struct i915_ggtt *ggtt)
 400 {
 401         struct drm_mm_node *node = &ggtt->uc_fw;
 402 
 403         GEM_BUG_ON(!node->allocated);
 404         GEM_BUG_ON(upper_32_bits(node->start));
 405         GEM_BUG_ON(upper_32_bits(node->start + node->size - 1));
 406 
 407         return lower_32_bits(node->start);
 408 }
 409 
 410 static void intel_uc_fw_ggtt_bind(struct intel_uc_fw *uc_fw,
 411                                   struct intel_gt *gt)
 412 {
 413         struct drm_i915_gem_object *obj = uc_fw->obj;
 414         struct i915_ggtt *ggtt = gt->ggtt;
 415         struct i915_vma dummy = {
 416                 .node.start = uc_fw_ggtt_offset(uc_fw, ggtt),
 417                 .node.size = obj->base.size,
 418                 .pages = obj->mm.pages,
 419                 .vm = &ggtt->vm,
 420         };
 421 
 422         GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
 423         GEM_BUG_ON(dummy.node.size > ggtt->uc_fw.size);
 424 
 425         /* uc_fw->obj cache domains were not controlled across suspend */
 426         drm_clflush_sg(dummy.pages);
 427 
 428         ggtt->vm.insert_entries(&ggtt->vm, &dummy, I915_CACHE_NONE, 0);
 429 }
 430 
 431 static void intel_uc_fw_ggtt_unbind(struct intel_uc_fw *uc_fw,
 432                                     struct intel_gt *gt)
 433 {
 434         struct drm_i915_gem_object *obj = uc_fw->obj;
 435         struct i915_ggtt *ggtt = gt->ggtt;
 436         u64 start = uc_fw_ggtt_offset(uc_fw, ggtt);
 437 
 438         ggtt->vm.clear_range(&ggtt->vm, start, obj->base.size);
 439 }
 440 
 441 static int uc_fw_xfer(struct intel_uc_fw *uc_fw, struct intel_gt *gt,
 442                       u32 wopcm_offset, u32 dma_flags)
 443 {
 444         struct intel_uncore *uncore = gt->uncore;
 445         u64 offset;
 446         int ret;
 447 
 448         ret = i915_inject_load_error(gt->i915, -ETIMEDOUT);
 449         if (ret)
 450                 return ret;
 451 
 452         intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
 453 
 454         /* Set the source address for the uCode */
 455         offset = uc_fw_ggtt_offset(uc_fw, gt->ggtt);
 456         GEM_BUG_ON(upper_32_bits(offset) & 0xFFFF0000);
 457         intel_uncore_write_fw(uncore, DMA_ADDR_0_LOW, lower_32_bits(offset));
 458         intel_uncore_write_fw(uncore, DMA_ADDR_0_HIGH, upper_32_bits(offset));
 459 
 460         /* Set the DMA destination */
 461         intel_uncore_write_fw(uncore, DMA_ADDR_1_LOW, wopcm_offset);
 462         intel_uncore_write_fw(uncore, DMA_ADDR_1_HIGH, DMA_ADDRESS_SPACE_WOPCM);
 463 
 464         /*
 465          * Set the transfer size. The header plus uCode will be copied to WOPCM
 466          * via DMA, excluding any other components
 467          */
 468         intel_uncore_write_fw(uncore, DMA_COPY_SIZE,
 469                               sizeof(struct uc_css_header) + uc_fw->ucode_size);
 470 
 471         /* Start the DMA */
 472         intel_uncore_write_fw(uncore, DMA_CTRL,
 473                               _MASKED_BIT_ENABLE(dma_flags | START_DMA));
 474 
 475         /* Wait for DMA to finish */
 476         ret = intel_wait_for_register_fw(uncore, DMA_CTRL, START_DMA, 0, 100);
 477         if (ret)
 478                 dev_err(gt->i915->drm.dev, "DMA for %s fw failed, DMA_CTRL=%u\n",
 479                         intel_uc_fw_type_repr(uc_fw->type),
 480                         intel_uncore_read_fw(uncore, DMA_CTRL));
 481 
 482         /* Disable the bits once DMA is over */
 483         intel_uncore_write_fw(uncore, DMA_CTRL, _MASKED_BIT_DISABLE(dma_flags));
 484 
 485         intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
 486 
 487         return ret;
 488 }
 489 
 490 /**
 491  * intel_uc_fw_upload - load uC firmware using custom loader
 492  * @uc_fw: uC firmware
 493  * @gt: the intel_gt structure
 494  * @wopcm_offset: destination offset in wopcm
 495  * @dma_flags: flags for flags for dma ctrl
 496  *
 497  * Loads uC firmware and updates internal flags.
 498  *
 499  * Return: 0 on success, non-zero on failure.
 500  */
 501 int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, struct intel_gt *gt,
 502                        u32 wopcm_offset, u32 dma_flags)
 503 {
 504         int err;
 505 
 506         /* make sure the status was cleared the last time we reset the uc */
 507         GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw));
 508 
 509         err = i915_inject_load_error(gt->i915, -ENOEXEC);
 510         if (err)
 511                 return err;
 512 
 513         if (!intel_uc_fw_is_available(uc_fw))
 514                 return -ENOEXEC;
 515 
 516         /* Call custom loader */
 517         intel_uc_fw_ggtt_bind(uc_fw, gt);
 518         err = uc_fw_xfer(uc_fw, gt, wopcm_offset, dma_flags);
 519         intel_uc_fw_ggtt_unbind(uc_fw, gt);
 520         if (err)
 521                 goto fail;
 522 
 523         intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_TRANSFERRED);
 524         return 0;
 525 
 526 fail:
 527         i915_probe_error(gt->i915, "Failed to load %s firmware %s (%d)\n",
 528                          intel_uc_fw_type_repr(uc_fw->type), uc_fw->path,
 529                          err);
 530         intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_FAIL);
 531         return err;
 532 }
 533 
 534 int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
 535 {
 536         int err;
 537 
 538         /* this should happen before the load! */
 539         GEM_BUG_ON(intel_uc_fw_is_loaded(uc_fw));
 540 
 541         if (!intel_uc_fw_is_available(uc_fw))
 542                 return -ENOEXEC;
 543 
 544         err = i915_gem_object_pin_pages(uc_fw->obj);
 545         if (err) {
 546                 DRM_DEBUG_DRIVER("%s fw pin-pages err=%d\n",
 547                                  intel_uc_fw_type_repr(uc_fw->type), err);
 548                 intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_FAIL);
 549         }
 550 
 551         return err;
 552 }
 553 
 554 void intel_uc_fw_fini(struct intel_uc_fw *uc_fw)
 555 {
 556         if (!intel_uc_fw_is_available(uc_fw))
 557                 return;
 558 
 559         i915_gem_object_unpin_pages(uc_fw->obj);
 560 }
 561 
 562 /**
 563  * intel_uc_fw_cleanup_fetch - cleanup uC firmware
 564  * @uc_fw: uC firmware
 565  *
 566  * Cleans up uC firmware by releasing the firmware GEM obj.
 567  */
 568 void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw)
 569 {
 570         if (!intel_uc_fw_is_available(uc_fw))
 571                 return;
 572 
 573         i915_gem_object_put(fetch_and_zero(&uc_fw->obj));
 574 
 575         intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_SELECTED);
 576 }
 577 
 578 /**
 579  * intel_uc_fw_copy_rsa - copy fw RSA to buffer
 580  *
 581  * @uc_fw: uC firmware
 582  * @dst: dst buffer
 583  * @max_len: max number of bytes to copy
 584  *
 585  * Return: number of copied bytes.
 586  */
 587 size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len)
 588 {
 589         struct sg_table *pages = uc_fw->obj->mm.pages;
 590         u32 size = min_t(u32, uc_fw->rsa_size, max_len);
 591         u32 offset = sizeof(struct uc_css_header) + uc_fw->ucode_size;
 592 
 593         GEM_BUG_ON(!intel_uc_fw_is_available(uc_fw));
 594 
 595         return sg_pcopy_to_buffer(pages->sgl, pages->nents, dst, size, offset);
 596 }
 597 
 598 /**
 599  * intel_uc_fw_dump - dump information about uC firmware
 600  * @uc_fw: uC firmware
 601  * @p: the &drm_printer
 602  *
 603  * Pretty printer for uC firmware.
 604  */
 605 void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p)
 606 {
 607         drm_printf(p, "%s firmware: %s\n",
 608                    intel_uc_fw_type_repr(uc_fw->type), uc_fw->path);
 609         drm_printf(p, "\tstatus: %s\n",
 610                    intel_uc_fw_status_repr(uc_fw->status));
 611         drm_printf(p, "\tversion: wanted %u.%u, found %u.%u\n",
 612                    uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted,
 613                    uc_fw->major_ver_found, uc_fw->minor_ver_found);
 614         drm_printf(p, "\tuCode: %u bytes\n", uc_fw->ucode_size);
 615         drm_printf(p, "\tRSA: %u bytes\n", uc_fw->rsa_size);
 616 }

/* [<][>][^][v][top][bottom][index][help] */