aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/gpu/drm/xe/xe_guc_pc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/xe/xe_guc_pc.c')
-rw-r--r--drivers/gpu/drm/xe/xe_guc_pc.c97
1 files changed, 87 insertions, 10 deletions
diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c
index b995d1d51aed..85215313976c 100644
--- a/drivers/gpu/drm/xe/xe_guc_pc.c
+++ b/drivers/gpu/drm/xe/xe_guc_pc.c
@@ -9,6 +9,7 @@
#include <linux/ktime.h>
#include <drm/drm_managed.h>
+#include <drm/drm_print.h>
#include <generated/xe_wa_oob.h>
#include "abi/guc_actions_slpc_abi.h"
@@ -371,16 +372,17 @@ static void tgl_update_rpa_value(struct xe_guc_pc *pc)
u32 reg;
/*
- * For PVC we still need to use fused RP1 as the approximation for RPe
- * For other platforms than PVC we get the resolved RPe directly from
+ * For PVC we still need to use fused RP0 as the approximation for RPa
+ * For other platforms than PVC we get the resolved RPa directly from
* PCODE at a different register
*/
- if (xe->info.platform == XE_PVC)
+ if (xe->info.platform == XE_PVC) {
reg = xe_mmio_read32(&gt->mmio, PVC_RP_STATE_CAP);
- else
+ pc->rpa_freq = REG_FIELD_GET(RP0_MASK, reg) * GT_FREQUENCY_MULTIPLIER;
+ } else {
reg = xe_mmio_read32(&gt->mmio, FREQ_INFO_REC);
-
- pc->rpa_freq = REG_FIELD_GET(RPA_MASK, reg) * GT_FREQUENCY_MULTIPLIER;
+ pc->rpa_freq = REG_FIELD_GET(RPA_MASK, reg) * GT_FREQUENCY_MULTIPLIER;
+ }
}
static void tgl_update_rpe_value(struct xe_guc_pc *pc)
@@ -394,12 +396,13 @@ static void tgl_update_rpe_value(struct xe_guc_pc *pc)
* For other platforms than PVC we get the resolved RPe directly from
* PCODE at a different register
*/
- if (xe->info.platform == XE_PVC)
+ if (xe->info.platform == XE_PVC) {
reg = xe_mmio_read32(&gt->mmio, PVC_RP_STATE_CAP);
- else
+ pc->rpe_freq = REG_FIELD_GET(RP1_MASK, reg) * GT_FREQUENCY_MULTIPLIER;
+ } else {
reg = xe_mmio_read32(&gt->mmio, FREQ_INFO_REC);
-
- pc->rpe_freq = REG_FIELD_GET(RPE_MASK, reg) * GT_FREQUENCY_MULTIPLIER;
+ pc->rpe_freq = REG_FIELD_GET(RPE_MASK, reg) * GT_FREQUENCY_MULTIPLIER;
+ }
}
static void pc_update_rp_values(struct xe_guc_pc *pc)
@@ -1007,6 +1010,17 @@ out:
return ret;
}
+static int pc_action_set_strategy(struct xe_guc_pc *pc, u32 val)
+{
+ int ret = 0;
+
+ ret = pc_action_set_param(pc,
+ SLPC_PARAM_STRATEGIES,
+ val);
+
+ return ret;
+}
+
/**
* xe_guc_pc_start - Start GuC's Power Conservation component
* @pc: Xe_GuC_PC instance
@@ -1078,6 +1092,11 @@ int xe_guc_pc_start(struct xe_guc_pc *pc)
}
ret = pc_action_setup_gucrc(pc, GUCRC_FIRMWARE_CONTROL);
+ if (ret)
+ goto out;
+
+ /* Enable SLPC Optimized Strategy for compute */
+ ret = pc_action_set_strategy(pc, SLPC_OPTIMIZED_STRATEGY_COMPUTE);
out:
xe_force_wake_put(gt_to_fw(gt), fw_ref);
@@ -1158,3 +1177,61 @@ int xe_guc_pc_init(struct xe_guc_pc *pc)
return devm_add_action_or_reset(xe->drm.dev, xe_guc_pc_fini_hw, pc);
}
+
+static const char *pc_get_state_string(struct xe_guc_pc *pc)
+{
+ switch (slpc_shared_data_read(pc, header.global_state)) {
+ case SLPC_GLOBAL_STATE_NOT_RUNNING:
+ return "not running";
+ case SLPC_GLOBAL_STATE_INITIALIZING:
+ return "initializing";
+ case SLPC_GLOBAL_STATE_RESETTING:
+ return "resetting";
+ case SLPC_GLOBAL_STATE_RUNNING:
+ return "running";
+ case SLPC_GLOBAL_STATE_SHUTTING_DOWN:
+ return "shutting down";
+ case SLPC_GLOBAL_STATE_ERROR:
+ return "error";
+ default:
+ return "unknown";
+ }
+}
+
+/**
+ * xe_guc_pc_print - Print GuC's Power Conservation information for debug
+ * @pc: Xe_GuC_PC instance
+ * @p: drm_printer
+ */
+void xe_guc_pc_print(struct xe_guc_pc *pc, struct drm_printer *p)
+{
+ drm_printf(p, "SLPC Shared Data Header:\n");
+ drm_printf(p, "\tSize: %x\n", slpc_shared_data_read(pc, header.size));
+ drm_printf(p, "\tGlobal State: %s\n", pc_get_state_string(pc));
+
+ if (pc_action_query_task_state(pc))
+ return;
+
+ drm_printf(p, "\nSLPC Tasks Status:\n");
+ drm_printf(p, "\tGTPERF enabled: %s\n",
+ str_yes_no(slpc_shared_data_read(pc, task_state_data.status) &
+ SLPC_GTPERF_TASK_ENABLED));
+ drm_printf(p, "\tDCC enabled: %s\n",
+ str_yes_no(slpc_shared_data_read(pc, task_state_data.status) &
+ SLPC_DCC_TASK_ENABLED));
+ drm_printf(p, "\tDCC in use: %s\n",
+ str_yes_no(slpc_shared_data_read(pc, task_state_data.status) &
+ SLPC_IN_DCC));
+ drm_printf(p, "\tBalancer enabled: %s\n",
+ str_yes_no(slpc_shared_data_read(pc, task_state_data.status) &
+ SLPC_BALANCER_ENABLED));
+ drm_printf(p, "\tIBC enabled: %s\n",
+ str_yes_no(slpc_shared_data_read(pc, task_state_data.status) &
+ SLPC_IBC_TASK_ENABLED));
+ drm_printf(p, "\tBalancer IA LMT enabled: %s\n",
+ str_yes_no(slpc_shared_data_read(pc, task_state_data.status) &
+ SLPC_BALANCER_IA_LMT_ENABLED));
+ drm_printf(p, "\tBalancer IA LMT active: %s\n",
+ str_yes_no(slpc_shared_data_read(pc, task_state_data.status) &
+ SLPC_BALANCER_IA_LMT_ACTIVE));
+}