amdgpu/pm: Implement new API function "emit" that accepts buffer base and write offset
authorDarren Powell <darren.powell@amd.com>
Sat, 4 Dec 2021 05:23:52 +0000 (00:23 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 2 Feb 2022 23:27:58 +0000 (18:27 -0500)
   (v3)
     Rewrote patchset to order patches as (API, hw impl, usecase)

     - added API for new power management function emit_clk_levels
       This function should duplicate the functionality of print_clk_levels,
       but this solution passes the buffer base and write offset down the stack.
     - new powerplay function emit_clock_levels, implemented by smu_emit_ppclk_levels()
       This function parallels the implementation of smu_print_ppclk_levels and
       calls emit_clk_levels, and allows the returns of errors
     - new helper function smu_convert_to_smuclk called by smu_print_ppclk_levels and
       smu_emit_ppclk_levels

Signed-off-by: Darren Powell <darren.powell@amd.com>
Reviewed-By: Evan Quan <evan.quan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/include/kgd_pp_interface.h
drivers/gpu/drm/amd/pm/amdgpu_dpm.c
drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h

index 38712009949333737db133516e4d2fc3d989f938..a4c267f159591898b95feff32df06e6bcf8efd54 100644 (file)
@@ -321,6 +321,7 @@ struct amd_pm_funcs {
        int (*get_fan_speed_pwm)(void *handle, u32 *speed);
        int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask);
        int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf);
+       int (*emit_clock_levels)(void *handle, enum pp_clock_type type, char *buf, int *offset);
        int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level);
        int (*get_sclk_od)(void *handle);
        int (*set_sclk_od)(void *handle, uint32_t value);
index ef574c96b41ca14edda6483fb2e318bb83fa1020..1d63f1e8884c3eab665f7d373c1ac319591d13b1 100644 (file)
@@ -890,6 +890,27 @@ int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev,
        return ret;
 }
 
+int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev,
+                                 enum pp_clock_type type,
+                                 char *buf,
+                                 int *offset)
+{
+       const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+       int ret = 0;
+
+       if (!pp_funcs->emit_clock_levels)
+               return -ENOENT;
+
+       mutex_lock(&adev->pm.mutex);
+       ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle,
+                                          type,
+                                          buf,
+                                          offset);
+       mutex_unlock(&adev->pm.mutex);
+
+       return ret;
+}
+
 int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev,
                                    uint64_t ppfeature_masks)
 {
index 5cc05110cdae6f5dcc93a2120717d0a0e63301cc..1ed0ef898eb05d99c3bbaf6c752c98c9a13f430a 100644 (file)
@@ -441,6 +441,10 @@ int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev,
 int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev,
                                  enum pp_clock_type type,
                                  char *buf);
+int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev,
+                                 enum pp_clock_type type,
+                                 char *buf,
+                                 int *offset);
 int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev,
                                    uint64_t ppfeature_masks);
 int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf);
index 9861d70a5dada1d3f48832bc0063cc4d76223554..af368aa1fd0ae164c1a28557b16fe81b03ab896d 100644 (file)
@@ -2216,11 +2216,8 @@ static int smu_print_smuclk_levels(struct smu_context *smu, enum smu_clk_type cl
        return ret;
 }
 
-static int smu_print_ppclk_levels(void *handle,
-                                 enum pp_clock_type type,
-                                 char *buf)
+static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type)
 {
-       struct smu_context *smu = handle;
        enum smu_clk_type clk_type;
 
        switch (type) {
@@ -2253,12 +2250,46 @@ static int smu_print_ppclk_levels(void *handle,
        case OD_CCLK:
                clk_type = SMU_OD_CCLK; break;
        default:
-               return -EINVAL;
+               clk_type = SMU_CLK_COUNT; break;
        }
 
+       return clk_type;
+}
+
+static int smu_print_ppclk_levels(void *handle,
+                                 enum pp_clock_type type,
+                                 char *buf)
+{
+       struct smu_context *smu = handle;
+       enum smu_clk_type clk_type;
+
+       clk_type = smu_convert_to_smuclk(type);
+       if (clk_type == SMU_CLK_COUNT)
+               return -EINVAL;
+
        return smu_print_smuclk_levels(smu, clk_type, buf);
 }
 
+static int smu_emit_ppclk_levels(void *handle, enum pp_clock_type type, char *buf, int *offset)
+{
+       struct smu_context *smu = handle;
+       enum smu_clk_type clk_type;
+       int ret = 0;
+
+       clk_type = smu_convert_to_smuclk(type);
+       if (clk_type == SMU_CLK_COUNT)
+               return -EINVAL;
+
+       if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
+               return -EOPNOTSUPP;
+
+       if (!smu->ppt_funcs->emit_clk_levels)
+               ret = -ENOENT;
+
+       return smu->ppt_funcs->emit_clk_levels(smu, clk_type, buf, offset);
+
+}
+
 static int smu_od_edit_dpm_table(void *handle,
                                 enum PP_OD_DPM_TABLE_COMMAND type,
                                 long *input, uint32_t size)
@@ -2824,6 +2855,7 @@ static const struct amd_pm_funcs swsmu_pm_funcs = {
        .get_fan_speed_pwm   = smu_get_fan_speed_pwm,
        .force_clock_level       = smu_force_ppclk_levels,
        .print_clock_levels      = smu_print_ppclk_levels,
+       .emit_clock_levels       = smu_emit_ppclk_levels,
        .force_performance_level = smu_force_performance_level,
        .read_sensor             = smu_read_sensor,
        .get_performance_level   = smu_get_performance_level,
index 4c585241ef66a9a6c310d9c1d16031f5cd643813..79c7cb1a92d77968954a08f1d6f7717581fd65b5 100644 (file)
@@ -605,9 +605,23 @@ struct pptable_funcs {
         *                    to buffer. Star current level.
         *
         * Used for sysfs interfaces.
+        * Return: Number of characters written to the buffer
         */
        int (*print_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf);
 
+       /**
+        * @emit_clk_levels: Print DPM clock levels for a clock domain
+        *                    to buffer using sysfs_emit_at. Star current level.
+        *
+        * Used for sysfs interfaces.
+        * &buf: sysfs buffer
+        * &offset: offset within buffer to start printing, which is updated by the
+        * function.
+        *
+        * Return: 0 on Success or Negative to indicate an error occurred.
+        */
+       int (*emit_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf, int *offset);
+
        /**
         * @force_clk_levels: Set a range of allowed DPM levels for a clock
         *                    domain.