@@ -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
@@ -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);
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -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
@@ -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);
}
@@ -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
@@ -19,11 +19,18 @@
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)) {
@@ -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";
}
@@ -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)");
@@ -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) \