On Mon, 21 Nov 2022, Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx> wrote: > 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 overriden 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. > > Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx> > Cc: Alan Previn <alan.previn.teres.alexis@xxxxxxxxx> > Cc: John Harrison <John.C.Harrison@xxxxxxxxx> > --- > drivers/gpu/drm/i915/Makefile | 3 +- > drivers/gpu/drm/i915/gt/intel_gt.h | 5 ++ > drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c | 70 +++++++++++++++++++++++ > drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h | 36 ++++++++++++ > drivers/gpu/drm/i915/gt/uc/intel_uc.c | 17 ++++++ > drivers/gpu/drm/i915/gt/uc/intel_uc.h | 3 + > drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 25 +++++++- > drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h | 7 ++- > drivers/gpu/drm/i915/i915_params.c | 3 + > drivers/gpu/drm/i915/i915_params.h | 1 + > 10 files changed, 164 insertions(+), 6 deletions(-) > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c > create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index 01974b82d205..92d37cf71e16 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -205,7 +205,8 @@ 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_gsc_uc.o Comment near the top of the file: # Please keep these build lists sorted! > > # graphics system controller (GSC) support > i915-y += gt/intel_gsc.o > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h > index e0365d556248..d2f4fbde5f9f 100644 > --- a/drivers/gpu/drm/i915/gt/intel_gt.h > +++ b/drivers/gpu/drm/i915/gt/intel_gt.h > @@ -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 > index 000000000000..65cbf1ce9fa1 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.c > @@ -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 > index 000000000000..ea2b1c0713b8 > --- /dev/null > +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_uc.h > @@ -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 > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c > index 1d28286e6f06..622935770aa1 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c > @@ -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); > } > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.h b/drivers/gpu/drm/i915/gt/uc/intel_uc.h > index a8f38c2c60e2..5d0f1bcc381e 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.h > @@ -6,6 +6,7 @@ > #ifndef _INTEL_UC_H_ > #define _INTEL_UC_H_ > > +#include "intel_gsc_uc.h" And thus intel_gsc_uc.h becomes another file that causes the entire driver to be rebuilt when modified. *sad trombone* > #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 > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c > index 0c80ba51a4bd..5b2e4503aee7 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c > @@ -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,10 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) > int i; > bool found; > > + /* FW is not defined until all the support is in place */ > + 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 > @@ -374,6 +385,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; > @@ -385,6 +401,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)) { > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h > index bc898ba5355d..5d2a8965a592 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h > +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h > @@ -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 > > /* > * The firmware build process will generate a version header file with major and > @@ -205,6 +206,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"; > } > diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c > index d1e4d528cb17..61578f2860cd 100644 > --- a/drivers/gpu/drm/i915/i915_params.c > +++ b/drivers/gpu/drm/i915/i915_params.c > @@ -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)"); > > diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h > index 2733cb6cfe09..3f51f90145b6 100644 > --- a/drivers/gpu/drm/i915/i915_params.h > +++ b/drivers/gpu/drm/i915/i915_params.h > @@ -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) \ -- Jani Nikula, Intel Open Source Graphics Center