amdgpu/pm: Implement new API function "emit" that accepts buffer base and write offset
(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>
This commit is contained in:
parent
4f860edecd
commit
5d64f9bbb6
5 changed files with 77 additions and 5 deletions
|
@ -321,6 +321,7 @@ struct amd_pm_funcs {
|
||||||
int (*get_fan_speed_pwm)(void *handle, u32 *speed);
|
int (*get_fan_speed_pwm)(void *handle, u32 *speed);
|
||||||
int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask);
|
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 (*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 (*force_performance_level)(void *handle, enum amd_dpm_forced_level level);
|
||||||
int (*get_sclk_od)(void *handle);
|
int (*get_sclk_od)(void *handle);
|
||||||
int (*set_sclk_od)(void *handle, uint32_t value);
|
int (*set_sclk_od)(void *handle, uint32_t value);
|
||||||
|
|
|
@ -890,6 +890,27 @@ int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev,
|
||||||
return ret;
|
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,
|
int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev,
|
||||||
uint64_t ppfeature_masks)
|
uint64_t ppfeature_masks)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev,
|
||||||
enum pp_clock_type type,
|
enum pp_clock_type type,
|
||||||
char *buf);
|
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,
|
int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev,
|
||||||
uint64_t ppfeature_masks);
|
uint64_t ppfeature_masks);
|
||||||
int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf);
|
int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf);
|
||||||
|
|
|
@ -2216,11 +2216,8 @@ static int smu_print_smuclk_levels(struct smu_context *smu, enum smu_clk_type cl
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smu_print_ppclk_levels(void *handle,
|
static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type)
|
||||||
enum pp_clock_type type,
|
|
||||||
char *buf)
|
|
||||||
{
|
{
|
||||||
struct smu_context *smu = handle;
|
|
||||||
enum smu_clk_type clk_type;
|
enum smu_clk_type clk_type;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -2253,12 +2250,46 @@ static int smu_print_ppclk_levels(void *handle,
|
||||||
case OD_CCLK:
|
case OD_CCLK:
|
||||||
clk_type = SMU_OD_CCLK; break;
|
clk_type = SMU_OD_CCLK; break;
|
||||||
default:
|
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);
|
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,
|
static int smu_od_edit_dpm_table(void *handle,
|
||||||
enum PP_OD_DPM_TABLE_COMMAND type,
|
enum PP_OD_DPM_TABLE_COMMAND type,
|
||||||
long *input, uint32_t size)
|
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,
|
.get_fan_speed_pwm = smu_get_fan_speed_pwm,
|
||||||
.force_clock_level = smu_force_ppclk_levels,
|
.force_clock_level = smu_force_ppclk_levels,
|
||||||
.print_clock_levels = smu_print_ppclk_levels,
|
.print_clock_levels = smu_print_ppclk_levels,
|
||||||
|
.emit_clock_levels = smu_emit_ppclk_levels,
|
||||||
.force_performance_level = smu_force_performance_level,
|
.force_performance_level = smu_force_performance_level,
|
||||||
.read_sensor = smu_read_sensor,
|
.read_sensor = smu_read_sensor,
|
||||||
.get_performance_level = smu_get_performance_level,
|
.get_performance_level = smu_get_performance_level,
|
||||||
|
|
|
@ -605,9 +605,23 @@ struct pptable_funcs {
|
||||||
* to buffer. Star current level.
|
* to buffer. Star current level.
|
||||||
*
|
*
|
||||||
* Used for sysfs interfaces.
|
* 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);
|
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
|
* @force_clk_levels: Set a range of allowed DPM levels for a clock
|
||||||
* domain.
|
* domain.
|
||||||
|
|
Loading…
Add table
Reference in a new issue