drm/amd/pm: Add ih for SMU v13.0.6 thermal throttling
authorAsad kamal <asad.kamal@amd.com>
Wed, 15 Feb 2023 07:53:15 +0000 (15:53 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 9 Jun 2023 13:54:34 +0000 (09:54 -0400)
Add interrupt handler for thermal throttler events from
PMFW on SMUv13.0.6

Signed-off-by: Asad kamal <asad.kamal@amd.com>
Acked-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c

index b08608c..43a855d 100644 (file)
@@ -1297,6 +1297,109 @@ static int smu_v13_0_6_set_power_limit(struct smu_context *smu,
        return smu_v13_0_set_power_limit(smu, limit_type, limit);
 }
 
+static int smu_v13_0_6_irq_process(struct amdgpu_device *adev,
+                                  struct amdgpu_irq_src *source,
+                                  struct amdgpu_iv_entry *entry)
+{
+       struct smu_context *smu = adev->powerplay.pp_handle;
+       uint32_t client_id = entry->client_id;
+       uint32_t src_id = entry->src_id;
+       /*
+        * ctxid is used to distinguish different
+        * events for SMCToHost interrupt
+        */
+       uint32_t ctxid = entry->src_data[0];
+       uint32_t data;
+
+       if (client_id == SOC15_IH_CLIENTID_MP1) {
+               if (src_id == IH_INTERRUPT_ID_TO_DRIVER) {
+                       /* ACK SMUToHost interrupt */
+                       data = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+                       data = REG_SET_FIELD(data, MP1_SMN_IH_SW_INT_CTRL, INT_ACK, 1);
+                       WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, data);
+
+                       switch (ctxid) {
+                       case IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING:
+                               /*
+                                * Increment the throttle interrupt counter
+                                */
+                               atomic64_inc(&smu->throttle_int_counter);
+
+                               if (!atomic_read(&adev->throttling_logging_enabled))
+                                       return 0;
+
+                               if (__ratelimit(&adev->throttling_logging_rs))
+                                       schedule_work(&smu->throttling_logging_work);
+
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int smu_v13_0_6_set_irq_state(struct amdgpu_device *adev,
+                             struct amdgpu_irq_src *source,
+                             unsigned tyep,
+                             enum amdgpu_interrupt_state state)
+{
+       uint32_t val = 0;
+
+       switch (state) {
+       case AMDGPU_IRQ_STATE_DISABLE:
+               /* For MP1 SW irqs */
+               val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+               val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1);
+               WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val);
+
+               break;
+       case AMDGPU_IRQ_STATE_ENABLE:
+               /* For MP1 SW irqs */
+               val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT);
+               val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE);
+               val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0);
+               WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT, val);
+
+               val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL);
+               val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0);
+               WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val);
+
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static const struct amdgpu_irq_src_funcs smu_v13_0_6_irq_funcs =
+{
+       .set = smu_v13_0_6_set_irq_state,
+       .process = smu_v13_0_6_irq_process,
+};
+
+int smu_v13_0_6_register_irq_handler(struct smu_context *smu)
+{
+       struct amdgpu_device *adev = smu->adev;
+       struct amdgpu_irq_src *irq_src = &smu->irq_source;
+       int ret = 0;
+
+       if (amdgpu_sriov_vf(adev))
+               return 0;
+
+       irq_src->num_types = 1;
+       irq_src->funcs = &smu_v13_0_6_irq_funcs;
+
+       ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_MP1,
+                               IH_INTERRUPT_ID_TO_DRIVER,
+                               irq_src);
+       if (ret)
+               return ret;
+
+       return ret;
+}
+
 static int smu_v13_0_6_system_features_control(struct smu_context *smu,
                                               bool enable)
 {
@@ -2042,11 +2145,9 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = {
        .feature_is_enabled = smu_cmn_feature_is_enabled,
        .set_power_limit = smu_v13_0_6_set_power_limit,
        .set_xgmi_pstate = smu_v13_0_set_xgmi_pstate,
-       /* TODO: Thermal limits unknown, skip these for now
-       .register_irq_handler = smu_v13_0_register_irq_handler,
+       .register_irq_handler = smu_v13_0_6_register_irq_handler,
        .enable_thermal_alert = smu_v13_0_enable_thermal_alert,
        .disable_thermal_alert = smu_v13_0_disable_thermal_alert,
-       */
        .setup_pptable = smu_v13_0_6_setup_pptable,
        .baco_is_support = smu_v13_0_6_is_baco_supported,
        .get_dpm_ultimate_freq = smu_v13_0_6_get_dpm_ultimate_freq,