drm/i915/uc: Introduce GSC FW
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Thu, 8 Dec 2022 20:05:16 +0000 (12:05 -0800)
committerDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Fri, 9 Dec 2022 16:28:41 +0000 (08:28 -0800)
On MTL the GSC FW needs to be loaded on the media GT by the graphics
driver. We're going to treat it like a new uc_fw, so add the initial
defs and init/fini functions for it.

Similarly to the other FWs, the GSC FW path can be overridden via
modparam. The modparam can also be used to disable the GSC FW loading by
setting it to an empty string.

Note that the new structure has been called intel_gsc_uc to avoid
confusion with the existing intel_gsc, which instead represents the heci
gsc interfaces.

v2: re-order Makefile list to be properly sorted (Jani, Alan), better
    comment (alan)

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Alan Previn <alan.previn.teres.alexis@intel.com>
Cc: John Harrison <John.C.Harrison@Intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Reviewed-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221208200521.2928378-2-daniele.ceraolospurio@intel.com
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/gt/intel_gt.h
drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c [new file with mode: 0644]
drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h [new file with mode: 0644]
drivers/gpu/drm/i915/gt/uc/intel_uc.c
drivers/gpu/drm/i915/gt/uc/intel_uc.h
drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
drivers/gpu/drm/i915/i915_params.c
drivers/gpu/drm/i915/i915_params.h

index d09248c3b1764386a9ea73b4f7c62b88fa2a09d5..83cd12341d977c14a29d44afafd23e9ecced1381 100644 (file)
@@ -188,9 +188,8 @@ i915-y += \
          i915_vma_resource.o
 
 # general-purpose microcontroller (GuC) support
-i915-y += gt/uc/intel_uc.o \
-         gt/uc/intel_uc_debugfs.o \
-         gt/uc/intel_uc_fw.o \
+i915-y += \
+         gt/uc/intel_gsc_uc.o \
          gt/uc/intel_guc.o \
          gt/uc/intel_guc_ads.o \
          gt/uc/intel_guc_capture.o \
@@ -205,7 +204,10 @@ i915-y += gt/uc/intel_uc.o \
          gt/uc/intel_guc_submission.o \
          gt/uc/intel_huc.o \
          gt/uc/intel_huc_debugfs.o \
-         gt/uc/intel_huc_fw.o
+         gt/uc/intel_huc_fw.o \
+         gt/uc/intel_uc.o \
+         gt/uc/intel_uc_debugfs.o \
+         gt/uc/intel_uc_fw.o
 
 # graphics system controller (GSC) support
 i915-y += gt/intel_gsc.o
index e0365d55624846c09fa024be3d0f4ba72b768aea..d2f4fbde5f9f0de2021b5bdbb32e9cc09ae1385f 100644 (file)
@@ -39,6 +39,11 @@ static inline struct intel_gt *huc_to_gt(struct intel_huc *huc)
        return container_of(huc, struct intel_gt, uc.huc);
 }
 
+static inline struct intel_gt *gsc_uc_to_gt(struct intel_gsc_uc *gsc_uc)
+{
+       return container_of(gsc_uc, struct intel_gt, uc.gsc);
+}
+
 static inline struct intel_gt *gsc_to_gt(struct intel_gsc *gsc)
 {
        return container_of(gsc, struct intel_gt, gsc);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c
new file mode 100644 (file)
index 0000000..7abbbb0
--- /dev/null
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#include <linux/types.h>
+
+#include "gt/intel_gt.h"
+#include "intel_gsc_uc.h"
+#include "i915_drv.h"
+
+static bool gsc_engine_supported(struct intel_gt *gt)
+{
+       intel_engine_mask_t mask;
+
+       /*
+        * We reach here from i915_driver_early_probe for the primary GT before
+        * its engine mask is set, so we use the device info engine mask for it.
+        * For other GTs we expect the GT-specific mask to be set before we
+        * call this function.
+        */
+       GEM_BUG_ON(!gt_is_root(gt) && !gt->info.engine_mask);
+
+       if (gt_is_root(gt))
+               mask = RUNTIME_INFO(gt->i915)->platform_engine_mask;
+       else
+               mask = gt->info.engine_mask;
+
+       return __HAS_ENGINE(mask, GSC0);
+}
+
+void intel_gsc_uc_init_early(struct intel_gsc_uc *gsc)
+{
+       intel_uc_fw_init_early(&gsc->fw, INTEL_UC_FW_TYPE_GSC);
+
+       /* we can arrive here from i915_driver_early_probe for primary
+        * GT with it being not fully setup hence check device info's
+        * engine mask
+        */
+       if (!gsc_engine_supported(gsc_uc_to_gt(gsc))) {
+               intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED);
+               return;
+       }
+}
+
+int intel_gsc_uc_init(struct intel_gsc_uc *gsc)
+{
+       struct drm_i915_private *i915 = gsc_uc_to_gt(gsc)->i915;
+       int err;
+
+       err = intel_uc_fw_init(&gsc->fw);
+       if (err)
+               goto out;
+
+       intel_uc_fw_change_status(&gsc->fw, INTEL_UC_FIRMWARE_LOADABLE);
+
+       return 0;
+
+out:
+       i915_probe_error(i915, "failed with %d\n", err);
+       return err;
+}
+
+void intel_gsc_uc_fini(struct intel_gsc_uc *gsc)
+{
+       if (!intel_uc_fw_is_loadable(&gsc->fw))
+               return;
+
+       intel_uc_fw_fini(&gsc->fw);
+}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h
new file mode 100644 (file)
index 0000000..ea2b1c0
--- /dev/null
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef _INTEL_GSC_UC_H_
+#define _INTEL_GSC_UC_H_
+
+#include "intel_uc_fw.h"
+
+struct intel_gsc_uc {
+       /* Generic uC firmware management */
+       struct intel_uc_fw fw;
+};
+
+void intel_gsc_uc_init_early(struct intel_gsc_uc *gsc);
+int intel_gsc_uc_init(struct intel_gsc_uc *gsc);
+void intel_gsc_uc_fini(struct intel_gsc_uc *gsc);
+
+static inline bool intel_gsc_uc_is_supported(struct intel_gsc_uc *gsc)
+{
+       return intel_uc_fw_is_supported(&gsc->fw);
+}
+
+static inline bool intel_gsc_uc_is_wanted(struct intel_gsc_uc *gsc)
+{
+       return intel_uc_fw_is_enabled(&gsc->fw);
+}
+
+static inline bool intel_gsc_uc_is_used(struct intel_gsc_uc *gsc)
+{
+       GEM_BUG_ON(__intel_uc_fw_status(&gsc->fw) == INTEL_UC_FIRMWARE_SELECTED);
+       return intel_uc_fw_is_available(&gsc->fw);
+}
+
+#endif
index 4f4b519e12c1b7c073feac7da8c1b4111abdca31..6f74586f87d80864edf76cdb2ad2a454b412bc8c 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "gt/intel_gt.h"
 #include "gt/intel_reset.h"
+#include "intel_gsc_uc.h"
 #include "intel_guc.h"
 #include "intel_guc_ads.h"
 #include "intel_guc_submission.h"
@@ -126,6 +127,7 @@ void intel_uc_init_early(struct intel_uc *uc)
 
        intel_guc_init_early(&uc->guc);
        intel_huc_init_early(&uc->huc);
+       intel_gsc_uc_init_early(&uc->gsc);
 
        __confirm_options(uc);
 
@@ -296,15 +298,26 @@ static void __uc_fetch_firmwares(struct intel_uc *uc)
                                                  INTEL_UC_FIRMWARE_ERROR);
                }
 
+               if (intel_uc_wants_gsc_uc(uc)) {
+                       drm_dbg(&uc_to_gt(uc)->i915->drm,
+                               "Failed to fetch GuC: %d disabling GSC\n", err);
+                       intel_uc_fw_change_status(&uc->gsc.fw,
+                                                 INTEL_UC_FIRMWARE_ERROR);
+               }
+
                return;
        }
 
        if (intel_uc_wants_huc(uc))
                intel_uc_fw_fetch(&uc->huc.fw);
+
+       if (intel_uc_wants_gsc_uc(uc))
+               intel_uc_fw_fetch(&uc->gsc.fw);
 }
 
 static void __uc_cleanup_firmwares(struct intel_uc *uc)
 {
+       intel_uc_fw_cleanup_fetch(&uc->gsc.fw);
        intel_uc_fw_cleanup_fetch(&uc->huc.fw);
        intel_uc_fw_cleanup_fetch(&uc->guc.fw);
 }
@@ -330,11 +343,15 @@ static int __uc_init(struct intel_uc *uc)
        if (intel_uc_uses_huc(uc))
                intel_huc_init(huc);
 
+       if (intel_uc_uses_gsc_uc(uc))
+               intel_gsc_uc_init(&uc->gsc);
+
        return 0;
 }
 
 static void __uc_fini(struct intel_uc *uc)
 {
+       intel_gsc_uc_fini(&uc->gsc);
        intel_huc_fini(&uc->huc);
        intel_guc_fini(&uc->guc);
 }
index a8f38c2c60e23f2d5bb298aaead52a6214298032..5d0f1bcc381e82a2af5cb484d1180cb16e6e6f74 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef _INTEL_UC_H_
 #define _INTEL_UC_H_
 
+#include "intel_gsc_uc.h"
 #include "intel_guc.h"
 #include "intel_guc_rc.h"
 #include "intel_guc_submission.h"
@@ -27,6 +28,7 @@ struct intel_uc_ops {
 
 struct intel_uc {
        struct intel_uc_ops const *ops;
+       struct intel_gsc_uc gsc;
        struct intel_guc guc;
        struct intel_huc huc;
 
@@ -87,6 +89,7 @@ uc_state_checkers(huc, huc);
 uc_state_checkers(guc, guc_submission);
 uc_state_checkers(guc, guc_slpc);
 uc_state_checkers(guc, guc_rc);
+uc_state_checkers(gsc, gsc_uc);
 
 #undef uc_state_checkers
 #undef __uc_state_checker
index 6c83a8b66c9e3223b6d6ec038c3433eef59e26bf..1d6249d4b8efbcea5bdaa165a809a69c20093e93 100644 (file)
 static inline struct intel_gt *
 ____uc_fw_to_gt(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type)
 {
-       if (type == INTEL_UC_FW_TYPE_GUC)
+       GEM_BUG_ON(type >= INTEL_UC_FW_NUM_TYPES);
+
+       switch (type) {
+       case INTEL_UC_FW_TYPE_GUC:
                return container_of(uc_fw, struct intel_gt, uc.guc.fw);
+       case INTEL_UC_FW_TYPE_HUC:
+               return container_of(uc_fw, struct intel_gt, uc.huc.fw);
+       case INTEL_UC_FW_TYPE_GSC:
+               return container_of(uc_fw, struct intel_gt, uc.gsc.fw);
+       }
 
-       GEM_BUG_ON(type != INTEL_UC_FW_TYPE_HUC);
-       return container_of(uc_fw, struct intel_gt, uc.huc.fw);
+       return NULL;
 }
 
 static inline struct intel_gt *__uc_fw_to_gt(struct intel_uc_fw *uc_fw)
@@ -246,6 +253,14 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
        int i;
        bool found;
 
+       /*
+        * GSC FW support is still not fully in place, so we're not defining
+        * the FW blob yet because we don't want the driver to attempt to load
+        * it until we're ready for it.
+        */
+       if (uc_fw->type == INTEL_UC_FW_TYPE_GSC)
+               return;
+
        /*
         * The only difference between the ADL GuC FWs is the HWConfig support.
         * ADL-N does not support HWConfig, so we should use the same binary as
@@ -375,6 +390,11 @@ static const char *__override_huc_firmware_path(struct drm_i915_private *i915)
        return "";
 }
 
+static const char *__override_gsc_firmware_path(struct drm_i915_private *i915)
+{
+       return i915->params.gsc_firmware_path;
+}
+
 static void __uc_fw_user_override(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
 {
        const char *path = NULL;
@@ -386,6 +406,9 @@ static void __uc_fw_user_override(struct drm_i915_private *i915, struct intel_uc
        case INTEL_UC_FW_TYPE_HUC:
                path = __override_huc_firmware_path(i915);
                break;
+       case INTEL_UC_FW_TYPE_GSC:
+               path = __override_gsc_firmware_path(i915);
+               break;
        }
 
        if (unlikely(path)) {
index 3ab87c54a39874901c914fe85d5081b14a859897..f4310516b3e6a90ae7f8e9108bb80bd5b3c5b50e 100644 (file)
@@ -61,9 +61,10 @@ enum intel_uc_fw_status {
 
 enum intel_uc_fw_type {
        INTEL_UC_FW_TYPE_GUC = 0,
-       INTEL_UC_FW_TYPE_HUC
+       INTEL_UC_FW_TYPE_HUC,
+       INTEL_UC_FW_TYPE_GSC,
 };
-#define INTEL_UC_FW_NUM_TYPES 2
+#define INTEL_UC_FW_NUM_TYPES 3
 
 struct intel_uc_fw_ver {
        u32 major;
@@ -204,6 +205,8 @@ static inline const char *intel_uc_fw_type_repr(enum intel_uc_fw_type type)
                return "GuC";
        case INTEL_UC_FW_TYPE_HUC:
                return "HuC";
+       case INTEL_UC_FW_TYPE_GSC:
+               return "GSC";
        }
        return "uC";
 }
index d1e4d528cb174d68d3c08a7f9d29d38ac4b2ade6..61578f2860cdb62de213a635676699238f40a676 100644 (file)
@@ -192,6 +192,9 @@ i915_param_named_unsafe(huc_firmware_path, charp, 0400,
 i915_param_named_unsafe(dmc_firmware_path, charp, 0400,
        "DMC firmware path to use instead of the default one");
 
+i915_param_named_unsafe(gsc_firmware_path, charp, 0400,
+       "GSC firmware path to use instead of the default one");
+
 i915_param_named_unsafe(enable_dp_mst, bool, 0400,
        "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)");
 
index 2733cb6cfe0941a52c95228237022799e24275ea..3f51f90145b69908f33a84504d3489dccbdd04cc 100644 (file)
@@ -64,6 +64,7 @@ struct drm_printer;
        param(char *, guc_firmware_path, NULL, 0400) \
        param(char *, huc_firmware_path, NULL, 0400) \
        param(char *, dmc_firmware_path, NULL, 0400) \
+       param(char *, gsc_firmware_path, NULL, 0400) \
        param(bool, memtest, false, 0400) \
        param(int, mmio_debug, -IS_ENABLED(CONFIG_DRM_I915_DEBUG_MMIO), 0600) \
        param(int, edp_vswing, 0, 0400) \