@@ -234,7 +234,8 @@ struct i915_params i915 __read_mostly = {
module_param_named(guc_log_level, i915.guc_log_level, int, 0400);
MODULE_PARM_DESC(guc_log_level,
- "GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
+ "GuC firmware logging level (-1:disabled (default), "
+ "0: Critical Logging enabled, 1-4:Normal Logging enabled)");
module_param_named_unsafe(guc_firmware_path, i915.guc_firmware_path, charp, 0400);
MODULE_PARM_DESC(guc_firmware_path,
@@ -122,9 +122,15 @@
#define GUC_LOG_VERBOSITY_MED (1 << GUC_LOG_VERBOSITY_SHIFT)
#define GUC_LOG_VERBOSITY_HIGH (2 << GUC_LOG_VERBOSITY_SHIFT)
#define GUC_LOG_VERBOSITY_ULTRA (3 << GUC_LOG_VERBOSITY_SHIFT)
-/* Verbosity range-check limits, without the shift */
+/*
+ * Verbosity range-check limits, without the shift.
+ * GuC log verbosity supported by firmware are 0 to 3.
+ * However, in order to treat the critical GuC logging similar to
+ * other logging levels we have incresed GuC verbosity levels by 1
+ * with Level 0 corresponding to critical GuC logging.
+ */
#define GUC_LOG_VERBOSITY_MIN 0
-#define GUC_LOG_VERBOSITY_MAX 3
+#define GUC_LOG_VERBOSITY_MAX 4
#define GUC_LOG_VERBOSITY_MASK 0x0000000f
#define GUC_LOG_DESTINATION_MASK (3 << 4)
#define GUC_LOG_DISABLED (1 << 6)
@@ -132,6 +138,7 @@
#define GUC_WQ_TRACK_ENABLED (1 << 8)
#define GUC_ADS_ENABLED (1 << 9)
#define GUC_DEBUG_RESERVED (1 << 10)
+#define GUC_V9_CRITICAL_LOGGING_DISABLED (1 << 10)
#define GUC_ADS_ADDR_SHIFT 11
#define GUC_ADS_ADDR_MASK 0xfffff800
@@ -139,6 +146,16 @@
#define GUC_CTL_MAX_DWORDS (SOFT_SCRATCH_COUNT - 2) /* [1..14] */
+/*
+ * Critical logging in GuC is to be enabled always from GuC v9+.
+ * (for KBL - v9.39+)
+ */
+#define NEEDS_GUC_CRITICAL_LOGGING(dev_priv, guc_fw) \
+ (((IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv)) && \
+ guc_fw->major_ver_found >= 9) || \
+ (IS_KABYLAKE(dev_priv) && guc_fw->major_ver_found >= 9 && \
+ guc_fw->minor_ver_found >= 39))
+
/**
* DOC: GuC Firmware Layout
*
@@ -539,7 +556,8 @@ struct guc_log_buffer_state {
u32 logging_enabled:1;
u32 reserved1:3;
u32 verbosity:4;
- u32 reserved2:24;
+ u32 critical_logging_enabled:1;
+ u32 reserved2:23;
};
u32 value;
} __packed;
@@ -106,6 +106,8 @@ static u32 get_core_family(struct drm_i915_private *dev_priv)
static void guc_params_init(struct drm_i915_private *dev_priv)
{
struct intel_guc *guc = &dev_priv->guc;
+ struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
+ bool enable_critical_logging = false;
u32 params[GUC_CTL_MAX_DWORDS];
int i;
@@ -130,11 +132,32 @@ static void guc_params_init(struct drm_i915_private *dev_priv)
params[GUC_CTL_LOG_PARAMS] = guc->log.flags;
+ params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED;
+
+ /*
+ * GuC has critical logging level which is currently not being enabled
+ * through other log level interfaces. We are emulating that by making
+ * i915.guc_log_level value 1 more than GuC's log level values to make
+ * value 0 correspond to GuC critical logging level. Once GuC fixes
+ * the implementation this needs to be updated.
+ */
if (i915.guc_log_level >= 0) {
- params[GUC_CTL_DEBUG] =
- i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT;
- } else
- params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED;
+ if (i915.guc_log_level >= 1) {
+ params[GUC_CTL_DEBUG] = (i915.guc_log_level-1) <<
+ GUC_LOG_VERBOSITY_SHIFT;
+ params[GUC_CTL_DEBUG] &= ~GUC_LOG_DISABLED;
+ }
+ enable_critical_logging = true;
+ }
+
+ if (NEEDS_GUC_CRITICAL_LOGGING(dev_priv, guc_fw)) {
+ if (enable_critical_logging)
+ params[GUC_CTL_DEBUG] &=
+ ~GUC_V9_CRITICAL_LOGGING_DISABLED;
+ else
+ params[GUC_CTL_DEBUG] |=
+ GUC_V9_CRITICAL_LOGGING_DISABLED;
+ }
/* If GuC submission is enabled, set up additional parameters here */
if (i915.enable_guc_submission) {
@@ -589,8 +589,8 @@ void intel_guc_log_destroy(struct intel_guc *guc)
int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val)
{
struct intel_guc *guc = &dev_priv->guc;
-
- union guc_log_control log_param;
+ struct intel_uc_fw *guc_fw = &dev_priv->guc.fw;
+ union guc_log_control log_param, tmp;
int ret;
log_param.value = control_val;
@@ -603,14 +603,34 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val)
if (!log_param.logging_enabled && (i915.guc_log_level < 0))
return 0;
+ if (NEEDS_GUC_CRITICAL_LOGGING(dev_priv, guc_fw)) {
+ tmp.value = log_param.value;
+ if (log_param.logging_enabled) {
+ log_param.critical_logging_enabled = 1;
+ if (log_param.verbosity == GUC_LOG_VERBOSITY_MIN)
+ log_param.logging_enabled = 0;
+ else
+ log_param.verbosity -= 1;
+ }
+ }
+
ret = guc_log_control(guc, log_param.value);
if (ret < 0) {
DRM_DEBUG_DRIVER("guc_logging_control action failed %d\n", ret);
return ret;
}
+ if (NEEDS_GUC_CRITICAL_LOGGING(dev_priv, guc_fw))
+ log_param.logging_enabled = tmp.logging_enabled;
+
if (log_param.logging_enabled) {
- i915.guc_log_level = log_param.verbosity;
+ if (NEEDS_GUC_CRITICAL_LOGGING(dev_priv, guc_fw)) {
+ if (tmp.verbosity == GUC_LOG_VERBOSITY_MIN)
+ i915.guc_log_level = 0;
+ else
+ i915.guc_log_level = log_param.verbosity + 1;
+ } else
+ i915.guc_log_level = log_param.verbosity;
/* If log_level was set as -1 at boot time, then the relay channel file
* wouldn't have been created by now and interrupts also would not have