diff --git a/include/amd_smi/amdsmi.h b/include/amd_smi/amdsmi.h index 5a3ff936ab..82e72af16d 100644 --- a/include/amd_smi/amdsmi.h +++ b/include/amd_smi/amdsmi.h @@ -1003,6 +1003,15 @@ typedef enum { AMDSMI_GPU_BLOCK_RESERVED = 0x8000000000000000 } amdsmi_gpu_block_t; + +/** + * @brief The clk limit type + */ +typedef enum { + CLK_LIMIT_MIN, + CLK_LIMIT_MAX +} amdsmi_clk_limit_type_t; + /** * @brief The current ECC state */ @@ -3122,6 +3131,9 @@ amdsmi_status_t amdsmi_get_gpu_reg_table_info( * @brief This function sets the clock range information. It is not supported on virtual * machine guest * + * @deprecated ::amdsmi_set_gpu_clk_limit() should be used, with an + * interface that set the min_value and then max_value. + * * @platform{gpu_bm_linux} * * @details Given a processor handle @p processor_handle, a minimum clock value @p minclkvalue, @@ -3145,6 +3157,31 @@ amdsmi_status_t amdsmi_set_gpu_clk_range(amdsmi_processor_handle processor_handl uint64_t maxclkvalue, amdsmi_clk_type_t clkType); +/** + * @brief This function sets the clock sets the clock min/max level + * + * @platform{gpu_bm_linux} @platform{guest_1vf} + * + * @details Given a processor handle @p processor_handle, a clock type @p clk_type, + * a value @p clk_value needs to be set, and the @p level indicates min or max + * clock you want to set, this function the clock limit. + * + * @param[in] processor_handle a processor handle + * + * @param[in] clk_type AMDSMI_CLK_TYPE_SYS, AMDSMI_CLK_TYPE_MEM and so on + * + * @param[in] limit_type AMDSMI_FREQ_IND_MIN|AMDSMI_FREQ_IND_MAX to set the + * minimum (0) or maximum (1) speed. + * + * @param[in] clk_value value to apply to. Frequency values are in MHz. + * + * @return ::amdsmi_status_t | ::AMDSMI_STATUS_SUCCESS on success, non-zero on fail + */ +amdsmi_status_t amdsmi_set_gpu_clk_limit(amdsmi_processor_handle processor_handle, + amdsmi_clk_type_t clk_type, + amdsmi_clk_limit_type_t limit_type, + uint64_t clk_value); + /** * @brief This function sets the clock frequency information. It is not supported on * virtual machine guest diff --git a/rocm_smi/include/rocm_smi/rocm_smi.h b/rocm_smi/include/rocm_smi/rocm_smi.h index acbd678232..e53527b1ce 100755 --- a/rocm_smi/include/rocm_smi/rocm_smi.h +++ b/rocm_smi/include/rocm_smi/rocm_smi.h @@ -3033,6 +3033,32 @@ rsmi_status_t rsmi_dev_clk_range_set(uint32_t dv_ind, uint64_t minclkvalue, uint64_t maxclkvalue, rsmi_clk_type_t clkType); +/** + * @brief This function sets the clock min/max level + * + * @details Given a device index @p dv_ind, a clock value @p minclkvalue, + * a maximum clock value @p maxclkvalue and a clock type @p clkType this function + * will set the sclk|mclk range + * + * @param[in] dv_ind a device index + * + * @param[in] level RSMI_FREQ_IND_MIN|RSMI_FREQ_IND_MAX + * + * @param[in] clkvalue value to apply to the clock level. Frequency values + * are in MHz. + * + * @param[in] clkType RSMI_CLK_TYPE_SYS | RSMI_CLK_TYPE_MEM level type + * + * @retval ::RSMI_STATUS_SUCCESS call was successful + * @retval ::RSMI_STATUS_NOT_SUPPORTED installed software or hardware does not + * support this function with the given arguments + * @retval ::RSMI_STATUS_INVALID_ARGS the provided arguments are not valid + */ +rsmi_status_t rsmi_dev_clk_extremum_set(uint32_t dv_ind, rsmi_freq_ind_t level, + uint64_t clkvalue, + rsmi_clk_type_t clkType); + + /** * @brief This function sets the clock frequency information * diff --git a/rocm_smi/src/rocm_smi.cc b/rocm_smi/src/rocm_smi.cc index fd4ace7f9f..c38d97480a 100755 --- a/rocm_smi/src/rocm_smi.cc +++ b/rocm_smi/src/rocm_smi.cc @@ -1532,6 +1532,58 @@ static rsmi_status_t get_od_clk_volt_info(uint32_t dv_ind, CATCH } +rsmi_status_t rsmi_dev_clk_extremum_set(uint32_t dv_ind, rsmi_freq_ind_t level, + uint64_t clkvalue, + rsmi_clk_type_t clkType) { + TRY + rsmi_status_t ret; + std::ostringstream ss; + ss << __PRETTY_FUNCTION__ << "| ======= start ======="; + LOG_TRACE(ss); + + if (clkType != RSMI_CLK_TYPE_SYS && clkType != RSMI_CLK_TYPE_MEM) { + return RSMI_STATUS_INVALID_ARGS; + } + if (level != RSMI_FREQ_IND_MIN && level != RSMI_FREQ_IND_MAX) { + return RSMI_STATUS_INVALID_ARGS; + } + + std::map clk_char_map = { + {RSMI_CLK_TYPE_SYS, "s"}, + {RSMI_CLK_TYPE_MEM, "m"}, + }; + DEVICE_MUTEX + + // Set perf. level to manual so that we can then set the power profile + ret = rsmi_dev_perf_level_set_v1(dv_ind, RSMI_DEV_PERF_LEVEL_MANUAL); + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } + // For clock frequency setting, enter a new value by writing a string that + // contains "s/m index clock" to the file. The index should be 0 if to set + // minimum clock. And 1 if to set maximum clock. E.g., "s 0 500" will update + // minimum sclk to be 500 MHz. "m 1 800" will update maximum mclk to 800Mhz. + + std::string sysvalue = clk_char_map[clkType]; + sysvalue += ' ' + std::to_string(level); + sysvalue += ' ' + std::to_string(clkvalue); + sysvalue += '\n'; + + ret = set_dev_range(dv_ind, sysvalue); + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } + + ret = set_dev_range(dv_ind, "c"); + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } + + return RSMI_STATUS_SUCCESS; + CATCH +} + + rsmi_status_t rsmi_dev_clk_range_set(uint32_t dv_ind, uint64_t minclkvalue, uint64_t maxclkvalue, rsmi_clk_type_t clkType) { diff --git a/src/amd_smi/amd_smi.cc b/src/amd_smi/amd_smi.cc index 0ae2114762..794d79a697 100644 --- a/src/amd_smi/amd_smi.cc +++ b/src/amd_smi/amd_smi.cc @@ -1552,6 +1552,16 @@ amdsmi_status_t amdsmi_set_gpu_clk_range(amdsmi_processor_handle processor_handl static_cast(clkType)); } +amdsmi_status_t amdsmi_set_gpu_clk_limit(amdsmi_processor_handle processor_handle, + amdsmi_clk_type_t clk_type, + amdsmi_clk_limit_type_t limit_type, + uint64_t clk_value) { + return rsmi_wrapper(rsmi_dev_clk_extremum_set, processor_handle, + static_cast(limit_type), + clk_value, + static_cast(clk_type)); +} + amdsmi_status_t amdsmi_reset_gpu(amdsmi_processor_handle processor_handle) { return rsmi_wrapper(rsmi_dev_gpu_reset, processor_handle); }