drm/i915/uc: Unify uC FW selection
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Thu, 25 Jul 2019 00:18:08 +0000 (17:18 -0700)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 25 Jul 2019 06:30:41 +0000 (07:30 +0100)
Instead of having 2 identical functions for GuC and HuC firmware
selection, we can unify the selection logic and just use different lists
based on FW type.

Note that the revid is not relevant for current blobs, but the upcoming
CML will be identified as CFL rev 5, so by considering the revid we're
ready for that.

v2: rework blob list defs (Michal), add order check (Chris), fuse GuC
    and HuC lists into one.

v3: remove difference between no uC HW and no uC FW, simplify related
    selection code, check the whole fw list (Michal)

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Anusha Srivatsa <anusha.srivatsa@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> #v2
Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20190725001813.4740-4-daniele.ceraolospurio@intel.com
drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c
drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c
drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h

index 17ce78240cf8287072242547ad5e08e9ec4b0bf7..99f44d8ae0266a127c9976fa2a5a3b8904c0861c 100644 (file)
 #include "intel_guc_fw.h"
 #include "i915_drv.h"
 
-#define __MAKE_GUC_FW_PATH(KEY) \
-       "i915/" \
-       __stringify(KEY##_GUC_FW_PREFIX) "_guc_" \
-       __stringify(KEY##_GUC_FW_MAJOR) "." \
-       __stringify(KEY##_GUC_FW_MINOR) "." \
-       __stringify(KEY##_GUC_FW_PATCH) ".bin"
-
-#define SKL_GUC_FW_PREFIX skl
-#define SKL_GUC_FW_MAJOR 33
-#define SKL_GUC_FW_MINOR 0
-#define SKL_GUC_FW_PATCH 0
-#define SKL_GUC_FIRMWARE_PATH __MAKE_GUC_FW_PATH(SKL)
-MODULE_FIRMWARE(SKL_GUC_FIRMWARE_PATH);
-
-#define BXT_GUC_FW_PREFIX bxt
-#define BXT_GUC_FW_MAJOR 33
-#define BXT_GUC_FW_MINOR 0
-#define BXT_GUC_FW_PATCH 0
-#define BXT_GUC_FIRMWARE_PATH __MAKE_GUC_FW_PATH(BXT)
-MODULE_FIRMWARE(BXT_GUC_FIRMWARE_PATH);
-
-#define KBL_GUC_FW_PREFIX kbl
-#define KBL_GUC_FW_MAJOR 33
-#define KBL_GUC_FW_MINOR 0
-#define KBL_GUC_FW_PATCH 0
-#define KBL_GUC_FIRMWARE_PATH __MAKE_GUC_FW_PATH(KBL)
-MODULE_FIRMWARE(KBL_GUC_FIRMWARE_PATH);
-
-#define GLK_GUC_FW_PREFIX glk
-#define GLK_GUC_FW_MAJOR 33
-#define GLK_GUC_FW_MINOR 0
-#define GLK_GUC_FW_PATCH 0
-#define GLK_GUC_FIRMWARE_PATH __MAKE_GUC_FW_PATH(GLK)
-MODULE_FIRMWARE(GLK_GUC_FIRMWARE_PATH);
-
-#define ICL_GUC_FW_PREFIX icl
-#define ICL_GUC_FW_MAJOR 33
-#define ICL_GUC_FW_MINOR 0
-#define ICL_GUC_FW_PATCH 0
-#define ICL_GUC_FIRMWARE_PATH __MAKE_GUC_FW_PATH(ICL)
-MODULE_FIRMWARE(ICL_GUC_FIRMWARE_PATH);
-
-static void guc_fw_select(struct intel_uc_fw *guc_fw)
-{
-       struct intel_guc *guc = container_of(guc_fw, struct intel_guc, fw);
-       struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
-
-       GEM_BUG_ON(guc_fw->type != INTEL_UC_FW_TYPE_GUC);
-
-       guc_fw->fetch_status = INTEL_UC_FIRMWARE_NOT_SUPPORTED;
-
-       if (!HAS_GT_UC(i915))
-               return;
-
-       if (i915_modparams.guc_firmware_path) {
-               guc_fw->path = i915_modparams.guc_firmware_path;
-               guc_fw->major_ver_wanted = 0;
-               guc_fw->minor_ver_wanted = 0;
-       } else if (IS_ICELAKE(i915)) {
-               guc_fw->path = ICL_GUC_FIRMWARE_PATH;
-               guc_fw->major_ver_wanted = ICL_GUC_FW_MAJOR;
-               guc_fw->minor_ver_wanted = ICL_GUC_FW_MINOR;
-       } else if (IS_GEMINILAKE(i915)) {
-               guc_fw->path = GLK_GUC_FIRMWARE_PATH;
-               guc_fw->major_ver_wanted = GLK_GUC_FW_MAJOR;
-               guc_fw->minor_ver_wanted = GLK_GUC_FW_MINOR;
-       } else if (IS_KABYLAKE(i915) || IS_COFFEELAKE(i915)) {
-               guc_fw->path = KBL_GUC_FIRMWARE_PATH;
-               guc_fw->major_ver_wanted = KBL_GUC_FW_MAJOR;
-               guc_fw->minor_ver_wanted = KBL_GUC_FW_MINOR;
-       } else if (IS_BROXTON(i915)) {
-               guc_fw->path = BXT_GUC_FIRMWARE_PATH;
-               guc_fw->major_ver_wanted = BXT_GUC_FW_MAJOR;
-               guc_fw->minor_ver_wanted = BXT_GUC_FW_MINOR;
-       } else if (IS_SKYLAKE(i915)) {
-               guc_fw->path = SKL_GUC_FIRMWARE_PATH;
-               guc_fw->major_ver_wanted = SKL_GUC_FW_MAJOR;
-               guc_fw->minor_ver_wanted = SKL_GUC_FW_MINOR;
-       }
-
-       if (guc_fw->path)
-               guc_fw->fetch_status = INTEL_UC_FIRMWARE_NOT_STARTED;
-}
-
 /**
  * intel_guc_fw_init_early() - initializes GuC firmware struct
  * @guc: intel_guc struct
@@ -123,10 +39,7 @@ static void guc_fw_select(struct intel_uc_fw *guc_fw)
  */
 void intel_guc_fw_init_early(struct intel_guc *guc)
 {
-       struct intel_uc_fw *guc_fw = &guc->fw;
-
-       intel_uc_fw_init_early(guc_fw, INTEL_UC_FW_TYPE_GUC);
-       guc_fw_select(guc_fw);
+       intel_uc_fw_init_early(&guc->fw, INTEL_UC_FW_TYPE_GUC, guc_to_gt(guc)->i915);
 }
 
 static void guc_prepare_xfer(struct intel_guc *guc)
index c3a7bd57fb55a5177470362c32596029fc766962..ba2e1a8358308074ab4e4307603cb3df9668dc9d 100644 (file)
  * Note that HuC firmware loading must be done before GuC loading.
  */
 
-#define BXT_HUC_FW_MAJOR 01
-#define BXT_HUC_FW_MINOR 8
-#define BXT_BLD_NUM 2893
-
-#define SKL_HUC_FW_MAJOR 01
-#define SKL_HUC_FW_MINOR 07
-#define SKL_BLD_NUM 1398
-
-#define KBL_HUC_FW_MAJOR 02
-#define KBL_HUC_FW_MINOR 00
-#define KBL_BLD_NUM 1810
-
-#define GLK_HUC_FW_MAJOR 03
-#define GLK_HUC_FW_MINOR 01
-#define GLK_BLD_NUM 2893
-
-#define ICL_HUC_FW_MAJOR 8
-#define ICL_HUC_FW_MINOR 4
-#define ICL_BLD_NUM 3238
-
-#define HUC_FW_PATH(platform, major, minor, bld_num) \
-       "i915/" __stringify(platform) "_huc_ver" __stringify(major) "_" \
-       __stringify(minor) "_" __stringify(bld_num) ".bin"
-
-#define I915_SKL_HUC_UCODE HUC_FW_PATH(skl, SKL_HUC_FW_MAJOR, \
-       SKL_HUC_FW_MINOR, SKL_BLD_NUM)
-MODULE_FIRMWARE(I915_SKL_HUC_UCODE);
-
-#define I915_BXT_HUC_UCODE HUC_FW_PATH(bxt, BXT_HUC_FW_MAJOR, \
-       BXT_HUC_FW_MINOR, BXT_BLD_NUM)
-MODULE_FIRMWARE(I915_BXT_HUC_UCODE);
-
-#define I915_KBL_HUC_UCODE HUC_FW_PATH(kbl, KBL_HUC_FW_MAJOR, \
-       KBL_HUC_FW_MINOR, KBL_BLD_NUM)
-MODULE_FIRMWARE(I915_KBL_HUC_UCODE);
-
-#define I915_GLK_HUC_UCODE HUC_FW_PATH(glk, GLK_HUC_FW_MAJOR, \
-       GLK_HUC_FW_MINOR, GLK_BLD_NUM)
-MODULE_FIRMWARE(I915_GLK_HUC_UCODE);
-
-#define I915_ICL_HUC_UCODE HUC_FW_PATH(icl, ICL_HUC_FW_MAJOR, \
-       ICL_HUC_FW_MINOR, ICL_BLD_NUM)
-MODULE_FIRMWARE(I915_ICL_HUC_UCODE);
-
-static void huc_fw_select(struct intel_uc_fw *huc_fw)
-{
-       struct intel_huc *huc = container_of(huc_fw, struct intel_huc, fw);
-       struct drm_i915_private *dev_priv = huc_to_gt(huc)->i915;
-
-       GEM_BUG_ON(huc_fw->type != INTEL_UC_FW_TYPE_HUC);
-
-       huc_fw->fetch_status = INTEL_UC_FIRMWARE_NOT_SUPPORTED;
-
-       if (!HAS_GT_UC(dev_priv))
-               return;
-
-       if (i915_modparams.huc_firmware_path) {
-               huc_fw->path = i915_modparams.huc_firmware_path;
-               huc_fw->major_ver_wanted = 0;
-               huc_fw->minor_ver_wanted = 0;
-       } else if (IS_SKYLAKE(dev_priv)) {
-               huc_fw->path = I915_SKL_HUC_UCODE;
-               huc_fw->major_ver_wanted = SKL_HUC_FW_MAJOR;
-               huc_fw->minor_ver_wanted = SKL_HUC_FW_MINOR;
-       } else if (IS_BROXTON(dev_priv)) {
-               huc_fw->path = I915_BXT_HUC_UCODE;
-               huc_fw->major_ver_wanted = BXT_HUC_FW_MAJOR;
-               huc_fw->minor_ver_wanted = BXT_HUC_FW_MINOR;
-       } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) {
-               huc_fw->path = I915_KBL_HUC_UCODE;
-               huc_fw->major_ver_wanted = KBL_HUC_FW_MAJOR;
-               huc_fw->minor_ver_wanted = KBL_HUC_FW_MINOR;
-       } else if (IS_GEMINILAKE(dev_priv)) {
-               huc_fw->path = I915_GLK_HUC_UCODE;
-               huc_fw->major_ver_wanted = GLK_HUC_FW_MAJOR;
-               huc_fw->minor_ver_wanted = GLK_HUC_FW_MINOR;
-       } else if (IS_ICELAKE(dev_priv)) {
-               huc_fw->path = I915_ICL_HUC_UCODE;
-               huc_fw->major_ver_wanted = ICL_HUC_FW_MAJOR;
-               huc_fw->minor_ver_wanted = ICL_HUC_FW_MINOR;
-       }
-
-       if (huc_fw->path)
-               huc_fw->fetch_status = INTEL_UC_FIRMWARE_NOT_STARTED;
-}
-
 /**
  * intel_huc_fw_init_early() - initializes HuC firmware struct
  * @huc: intel_huc struct
@@ -117,10 +31,7 @@ static void huc_fw_select(struct intel_uc_fw *huc_fw)
  */
 void intel_huc_fw_init_early(struct intel_huc *huc)
 {
-       struct intel_uc_fw *huc_fw = &huc->fw;
-
-       intel_uc_fw_init_early(huc_fw, INTEL_UC_FW_TYPE_HUC);
-       huc_fw_select(huc_fw);
+       intel_uc_fw_init_early(&huc->fw, INTEL_UC_FW_TYPE_HUC, huc_to_gt(huc)->i915);
 }
 
 static void huc_xfer_rsa(struct intel_huc *huc)
index 432b632b04c0ebca11e91c7793dab0cb3fe2d3da..9206d42217897257ce6db7bd9594436b8d94da7e 100644 (file)
 #include "intel_uc_fw.h"
 #include "i915_drv.h"
 
+/*
+ * List of required GuC and HuC binaries per-platform.
+ * Must be ordered based on platform + revid, from newer to older.
+ */
+#define INTEL_UC_FIRMWARE_DEFS(fw_def, guc_def, huc_def) \
+       fw_def(ICELAKE,    0, guc_def(icl, 33, 0, 0), huc_def(icl,  8,  4, 3238)) \
+       fw_def(COFFEELAKE, 0, guc_def(kbl, 33, 0, 0), huc_def(kbl, 02, 00, 1810)) \
+       fw_def(GEMINILAKE, 0, guc_def(glk, 33, 0, 0), huc_def(glk, 03, 01, 2893)) \
+       fw_def(KABYLAKE,   0, guc_def(kbl, 33, 0, 0), huc_def(kbl, 02, 00, 1810)) \
+       fw_def(BROXTON,    0, guc_def(bxt, 33, 0, 0), huc_def(bxt, 01,  8, 2893)) \
+       fw_def(SKYLAKE,    0, guc_def(skl, 33, 0, 0), huc_def(skl, 01, 07, 1398))
+
+#define __MAKE_UC_FW_PATH(prefix_, name_, separator_, major_, minor_, patch_) \
+       "i915/" \
+       __stringify(prefix_) name_ \
+       __stringify(major_) separator_ \
+       __stringify(minor_) separator_ \
+       __stringify(patch_) ".bin"
+
+#define MAKE_GUC_FW_PATH(prefix_, major_, minor_, patch_) \
+       __MAKE_UC_FW_PATH(prefix_, "_guc_", ".", major_, minor_, patch_)
+
+#define MAKE_HUC_FW_PATH(prefix_, major_, minor_, bld_num_) \
+       __MAKE_UC_FW_PATH(prefix_, "_huc_ver", "_", major_, minor_, bld_num_)
+
+/* 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
+__uc_fw_auto_select(struct intel_uc_fw *uc_fw, enum intel_platform p, u8 rev)
+{
+       static const struct uc_fw_platform_requirement fw_blobs[] = {
+               INTEL_UC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB, HUC_FW_BLOB)
+       };
+       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;
+               }
+       }
+}
+
+static bool
+__uc_fw_override(struct intel_uc_fw *uc_fw)
+{
+       switch (uc_fw->type) {
+       case INTEL_UC_FW_TYPE_GUC:
+               uc_fw->path = i915_modparams.guc_firmware_path;
+               break;
+       case INTEL_UC_FW_TYPE_HUC:
+               uc_fw->path = i915_modparams.huc_firmware_path;
+               break;
+       }
+
+       return uc_fw->path;
+}
+
+/**
+ * intel_uc_fw_init_early - initialize the uC object and select the firmware
+ * @i915: device private
+ * @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,
+                           enum intel_uc_fw_type type,
+                           struct drm_i915_private *i915)
+{
+       /*
+        * we use FIRMWARE_UNINITIALIZED to detect checks against fetch_status
+        * before we're looked at the HW caps to see if we have uc support
+        */
+       BUILD_BUG_ON(INTEL_UC_FIRMWARE_UNINITIALIZED);
+       GEM_BUG_ON(uc_fw->fetch_status);
+       GEM_BUG_ON(uc_fw->load_status);
+       GEM_BUG_ON(uc_fw->path);
+
+       uc_fw->type = type;
+
+       if (HAS_GT_UC(i915) && likely(!__uc_fw_override(uc_fw)))
+               __uc_fw_auto_select(uc_fw, INTEL_INFO(i915)->platform,
+                                   INTEL_REVID(i915));
+
+       if (uc_fw->path) {
+               uc_fw->fetch_status = INTEL_UC_FIRMWARE_NOT_STARTED;
+               uc_fw->load_status = INTEL_UC_FIRMWARE_NOT_STARTED;
+       } else {
+               uc_fw->fetch_status = INTEL_UC_FIRMWARE_NOT_SUPPORTED;
+               uc_fw->load_status = INTEL_UC_FIRMWARE_NOT_SUPPORTED;
+       }
+}
+
 /**
  * intel_uc_fw_fetch - fetch uC firmware
  *
index 55ac9eeab44068a991d5383b7705c929ca3d9c33..c93e271917c9ab6535dfc46737eeee6a6d0f33dd 100644 (file)
@@ -44,9 +44,10 @@ enum intel_uc_fw_status {
 };
 
 enum intel_uc_fw_type {
-       INTEL_UC_FW_TYPE_GUC,
+       INTEL_UC_FW_TYPE_GUC = 0,
        INTEL_UC_FW_TYPE_HUC
 };
+#define INTEL_UC_FW_NUM_TYPES 2
 
 /*
  * This structure encapsulates all the data needed during the process
@@ -109,22 +110,6 @@ static inline const char *intel_uc_fw_type_repr(enum intel_uc_fw_type type)
        return "uC";
 }
 
-static inline
-void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
-                           enum intel_uc_fw_type type)
-{
-       /*
-        * we use FIRMWARE_UNINITIALIZED to detect checks against fetch_status
-        * before we're looked at the HW caps to see if we have uc support
-        */
-       BUILD_BUG_ON(INTEL_UC_FIRMWARE_UNINITIALIZED);
-
-       uc_fw->path = NULL;
-       uc_fw->fetch_status = INTEL_UC_FIRMWARE_UNINITIALIZED;
-       uc_fw->load_status = INTEL_UC_FIRMWARE_NOT_STARTED;
-       uc_fw->type = type;
-}
-
 static inline bool intel_uc_fw_is_loaded(struct intel_uc_fw *uc_fw)
 {
        return uc_fw->load_status == INTEL_UC_FIRMWARE_SUCCESS;
@@ -159,7 +144,10 @@ static inline u32 intel_uc_fw_get_upload_size(struct intel_uc_fw *uc_fw)
        return uc_fw->header_size + uc_fw->ucode_size;
 }
 
-void intel_uc_fw_fetch(struct drm_i915_private *dev_priv,
+void intel_uc_fw_init_early(struct intel_uc_fw *uc_fw,
+                           enum intel_uc_fw_type type,
+                           struct drm_i915_private *i915);
+void intel_uc_fw_fetch(struct drm_i915_private *i915,
                       struct intel_uc_fw *uc_fw);
 void intel_uc_fw_cleanup_fetch(struct intel_uc_fw *uc_fw);
 int intel_uc_fw_upload(struct intel_uc_fw *uc_fw,