Add functions that tell what capabilities are supported
The new functions added in this commit allow a caller to tell up front what functions, function variants and monitors are supported. Also, * fixed a few documentation/formatting issues * fixed a process_info test issue Change-Id: I2184ab1a4a6898f847e791f273e2185d556e78e9
This commit is contained in:
+246
-4
@@ -57,6 +57,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "rocm_smi/rocm_smi_common.h" // Should go before rocm_smi.h
|
||||
#include "rocm_smi/rocm_smi.h"
|
||||
#include "rocm_smi/rocm_smi_main.h"
|
||||
#include "rocm_smi/rocm_smi_device.h"
|
||||
@@ -1976,13 +1977,12 @@ rsmi_dev_power_profile_presets_get(uint32_t dv_ind, uint32_t sensor_ind,
|
||||
}
|
||||
|
||||
rsmi_status_t
|
||||
rsmi_dev_power_profile_set(uint32_t dv_ind, uint32_t sensor_ind,
|
||||
rsmi_dev_power_profile_set(uint32_t dv_ind, uint32_t dummy,
|
||||
rsmi_power_profile_preset_masks_t profile) {
|
||||
TRY
|
||||
REQUIRE_ROOT_ACCESS
|
||||
|
||||
++sensor_ind; // power sysfs files have 1-based indices
|
||||
|
||||
(void)dummy;
|
||||
DEVICE_MUTEX
|
||||
rsmi_status_t ret = set_power_profile(dv_ind, profile);
|
||||
return ret;
|
||||
@@ -2498,7 +2498,7 @@ rsmi_compute_process_info_get(rsmi_process_info_t *procs,
|
||||
|
||||
uint32_t procs_found = 0;
|
||||
|
||||
int err = amd::smi:: GetProcessInfo(procs, *num_items, &procs_found);
|
||||
int err = amd::smi::GetProcessInfo(procs, *num_items, &procs_found);
|
||||
|
||||
if (err) {
|
||||
return errno_to_rsmi_status(err);
|
||||
@@ -2666,3 +2666,245 @@ rsmi_dev_xgmi_error_reset(uint32_t dv_ind) {
|
||||
|
||||
CATCH
|
||||
}
|
||||
|
||||
enum iterator_handle_type {
|
||||
FUNC_ITER = 0,
|
||||
VARIANT_ITER,
|
||||
SUBVARIANT_ITER,
|
||||
};
|
||||
|
||||
rsmi_status_t
|
||||
rsmi_dev_supported_func_iterator_open(uint32_t dv_ind,
|
||||
rsmi_func_id_iter_handle_t *handle) {
|
||||
TRY
|
||||
GET_DEV_FROM_INDX
|
||||
|
||||
if (handle == nullptr) {
|
||||
return RSMI_STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
dev->fillSupportedFuncs();
|
||||
|
||||
*handle = new rsmi_func_id_iter_handle;
|
||||
|
||||
if (*handle == nullptr) {
|
||||
return RSMI_STATUS_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
(*handle)->id_type = FUNC_ITER;
|
||||
|
||||
if (dev->supported_funcs()->begin() == dev->supported_funcs()->end()) {
|
||||
return RSMI_STATUS_NO_DATA;
|
||||
} else {
|
||||
SupportedFuncMapIt *supp_func_iter = new SupportedFuncMapIt;
|
||||
|
||||
if (supp_func_iter == nullptr) {
|
||||
return RSMI_STATUS_OUT_OF_RESOURCES;
|
||||
}
|
||||
*supp_func_iter = dev->supported_funcs()->begin();
|
||||
|
||||
(*handle)->func_id_iter = reinterpret_cast<uintptr_t>(supp_func_iter);
|
||||
(*handle)->container_ptr =
|
||||
reinterpret_cast<uintptr_t>(dev->supported_funcs());
|
||||
}
|
||||
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
|
||||
CATCH
|
||||
}
|
||||
|
||||
rsmi_status_t
|
||||
rsmi_dev_supported_variant_iterator_open(
|
||||
rsmi_func_id_iter_handle_t parent_iter,
|
||||
rsmi_func_id_iter_handle_t *var_iter) {
|
||||
TRY
|
||||
|
||||
if (var_iter == nullptr || parent_iter->id_type == SUBVARIANT_ITER) {
|
||||
return RSMI_STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (parent_iter->func_id_iter == 0) {
|
||||
return RSMI_STATUS_NO_DATA;
|
||||
}
|
||||
|
||||
*var_iter = new rsmi_func_id_iter_handle;
|
||||
|
||||
if (*var_iter == nullptr) {
|
||||
return RSMI_STATUS_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
VariantMapIt *variant_itr = nullptr;
|
||||
SubVariantIt *sub_var_itr = nullptr;
|
||||
SupportedFuncMapIt *func_iter;
|
||||
std::shared_ptr<VariantMap> var_map_container;
|
||||
std::shared_ptr<SubVariant> sub_var_map_container;
|
||||
|
||||
switch (parent_iter->id_type) {
|
||||
case FUNC_ITER:
|
||||
func_iter =
|
||||
reinterpret_cast<SupportedFuncMapIt *>(parent_iter->func_id_iter);
|
||||
var_map_container = (*func_iter)->second;
|
||||
|
||||
if (var_map_container == nullptr) {
|
||||
return RSMI_STATUS_NO_DATA;
|
||||
}
|
||||
|
||||
variant_itr = new VariantMapIt;
|
||||
*variant_itr = var_map_container->begin();
|
||||
(*var_iter)->func_id_iter = reinterpret_cast<uintptr_t>(variant_itr);
|
||||
(*var_iter)->container_ptr =
|
||||
reinterpret_cast<uintptr_t>(var_map_container.get());
|
||||
(*var_iter)->id_type = VARIANT_ITER;
|
||||
break;
|
||||
|
||||
case VARIANT_ITER:
|
||||
variant_itr =
|
||||
reinterpret_cast<VariantMapIt *>(parent_iter->func_id_iter);
|
||||
sub_var_map_container = (*variant_itr)->second;
|
||||
|
||||
if (sub_var_map_container == nullptr) {
|
||||
return RSMI_STATUS_NO_DATA;
|
||||
}
|
||||
|
||||
sub_var_itr = new SubVariantIt;
|
||||
*sub_var_itr = sub_var_map_container->begin();
|
||||
(*var_iter)->func_id_iter = reinterpret_cast<uintptr_t>(sub_var_itr);
|
||||
(*var_iter)->container_ptr =
|
||||
reinterpret_cast<uintptr_t>(sub_var_map_container.get());
|
||||
(*var_iter)->id_type = SUBVARIANT_ITER;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"Unexpected iterator type");
|
||||
return RSMI_STATUS_INVALID_ARGS;
|
||||
}
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
|
||||
CATCH
|
||||
}
|
||||
|
||||
rsmi_status_t
|
||||
rsmi_dev_supported_func_iterator_close(rsmi_func_id_iter_handle_t *handle) {
|
||||
TRY
|
||||
|
||||
if (handle == nullptr) {
|
||||
return RSMI_STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if ((*handle)->id_type == FUNC_ITER) {
|
||||
SupportedFuncMapIt *supp_func_iter =
|
||||
reinterpret_cast<SupportedFuncMapIt *>((*handle)->func_id_iter);
|
||||
delete supp_func_iter;
|
||||
} else if ((*handle)->id_type == VARIANT_ITER) {
|
||||
VariantMapIt *var_iter =
|
||||
reinterpret_cast<VariantMapIt *>((*handle)->func_id_iter);
|
||||
delete var_iter;
|
||||
} else if ((*handle)->id_type == SUBVARIANT_ITER) {
|
||||
SubVariant *subvar_iter =
|
||||
reinterpret_cast<SubVariant *>((*handle)->func_id_iter);
|
||||
delete subvar_iter;
|
||||
} else {
|
||||
return RSMI_STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
delete *handle;
|
||||
|
||||
*handle = nullptr;
|
||||
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
|
||||
CATCH
|
||||
}
|
||||
|
||||
rsmi_status_t
|
||||
rsmi_func_iter_value_get(rsmi_func_id_iter_handle_t handle,
|
||||
rsmi_func_id_value_t *value) {
|
||||
TRY
|
||||
if (value == nullptr) {
|
||||
return RSMI_STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (handle->func_id_iter == 0) {
|
||||
return RSMI_STATUS_NO_DATA;
|
||||
}
|
||||
|
||||
SupportedFuncMapIt *func_itr = nullptr;
|
||||
VariantMapIt *variant_itr = nullptr;
|
||||
SubVariantIt *sub_var_itr = nullptr;
|
||||
|
||||
switch (handle->id_type) {
|
||||
case FUNC_ITER:
|
||||
func_itr = reinterpret_cast<SupportedFuncMapIt *>(handle->func_id_iter);
|
||||
value->name = (*func_itr)->first.c_str();
|
||||
break;
|
||||
|
||||
case VARIANT_ITER:
|
||||
variant_itr = reinterpret_cast<VariantMapIt *>(handle->func_id_iter);
|
||||
value->id = (*variant_itr)->first;
|
||||
break;
|
||||
|
||||
case SUBVARIANT_ITER:
|
||||
sub_var_itr = reinterpret_cast<SubVariantIt *>(handle->func_id_iter);
|
||||
value->id = *(*sub_var_itr);
|
||||
break;
|
||||
|
||||
default:
|
||||
return RSMI_STATUS_INVALID_ARGS;
|
||||
}
|
||||
CATCH
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
rsmi_status_t
|
||||
rsmi_func_iter_next(rsmi_func_id_iter_handle_t handle) {
|
||||
TRY
|
||||
if (handle->func_id_iter == 0) {
|
||||
return RSMI_STATUS_NO_DATA;
|
||||
}
|
||||
|
||||
SupportedFuncMapIt *func_iter;
|
||||
VariantMapIt *var_iter;
|
||||
SubVariantIt *sub_var_iter;
|
||||
|
||||
switch (handle->id_type) {
|
||||
case FUNC_ITER:
|
||||
func_iter = reinterpret_cast<SupportedFuncMapIt *>(handle->func_id_iter);
|
||||
(*func_iter)++;
|
||||
|
||||
if (*func_iter ==
|
||||
reinterpret_cast<SupportedFuncMap *>(handle->container_ptr)->end()) {
|
||||
handle->func_id_iter = 0;
|
||||
return RSMI_STATUS_NO_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case VARIANT_ITER:
|
||||
var_iter = reinterpret_cast<VariantMapIt *>(handle->func_id_iter);
|
||||
(*var_iter)++;
|
||||
if (*var_iter ==
|
||||
reinterpret_cast<VariantMap *>(handle->container_ptr)->end()) {
|
||||
handle->func_id_iter = 0;
|
||||
return RSMI_STATUS_NO_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case SUBVARIANT_ITER:
|
||||
sub_var_iter = reinterpret_cast<SubVariantIt *>(handle->func_id_iter);
|
||||
(*sub_var_iter)++;
|
||||
if (*sub_var_iter ==
|
||||
reinterpret_cast<SubVariant *>(handle->container_ptr)->end()) {
|
||||
handle->func_id_iter = 0;
|
||||
return RSMI_STATUS_NO_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return RSMI_STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
|
||||
CATCH
|
||||
}
|
||||
|
||||
+291
-14
@@ -55,6 +55,7 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "rocm_smi/rocm_smi_main.h"
|
||||
#include "rocm_smi/rocm_smi_device.h"
|
||||
@@ -70,7 +71,7 @@ extern "C" {
|
||||
namespace amd {
|
||||
namespace smi {
|
||||
|
||||
// Sysfs file names
|
||||
// Device sysfs file names
|
||||
static const char *kDevPerfLevelFName = "power_dpm_force_performance_level";
|
||||
static const char *kDevDevIDFName = "device";
|
||||
static const char *kDevVendorIDFName = "vendor";
|
||||
@@ -82,7 +83,7 @@ static const char *kDevGPUMClkFName = "pp_dpm_mclk";
|
||||
static const char *kDevDCEFClkFName = "pp_dpm_dcefclk";
|
||||
static const char *kDevFClkFName = "pp_dpm_fclk";
|
||||
static const char *kDevSOCClkFName = "pp_dpm_socclk";
|
||||
static const char *kDevGPUPCIEClkFname = "pp_dpm_pcie";
|
||||
static const char *kDevPCIEClkFName = "pp_dpm_pcie";
|
||||
static const char *kDevPowerProfileModeFName = "pp_power_profile_mode";
|
||||
static const char *kDevPowerODVoltageFName = "pp_od_clk_voltage";
|
||||
static const char *kDevUsageFName = "gpu_busy_percent";
|
||||
@@ -106,17 +107,6 @@ static const char *kDevMemBusyPercentFName = "mem_busy_percent";
|
||||
static const char *kDevXGMIErrorFName = "xgmi_error";
|
||||
static const char *kDevSerialNumberFName = "serial_number";
|
||||
|
||||
// Strings that are found within sysfs files
|
||||
static const char *kDevPerfLevelAutoStr = "auto";
|
||||
static const char *kDevPerfLevelLowStr = "low";
|
||||
static const char *kDevPerfLevelHighStr = "high";
|
||||
static const char *kDevPerfLevelManualStr = "manual";
|
||||
static const char *kDevPerfLevelStandardStr = "profile_standard";
|
||||
static const char *kDevPerfLevelMinMClkStr = "profile_min_mclk";
|
||||
static const char *kDevPerfLevelMinSClkStr = "profile_min_sclk";
|
||||
static const char *kDevPerfLevelPeakStr = "profile_peak";
|
||||
static const char *kDevPerfLevelUnknownStr = "unknown";
|
||||
|
||||
// Firmware version files
|
||||
static const char *kDevFwVersionAsdFName = "fw_version/asd_fw_version";
|
||||
static const char *kDevFwVersionCeFName = "fw_version/ce_fw_version";
|
||||
@@ -205,6 +195,18 @@ static const std::map<DevKFDNodePropTypes, const char *> kDevKFDPropNameMap = {
|
||||
{kDevKFDNodePropMaxEngClkCComp, kDevKFDNodePropMaxEngClkCCompSName},
|
||||
{kDevKFDNodePropDomain, kDevKFDNodePropDomainSName},
|
||||
};
|
||||
|
||||
// Strings that are found within sysfs files
|
||||
static const char *kDevPerfLevelAutoStr = "auto";
|
||||
static const char *kDevPerfLevelLowStr = "low";
|
||||
static const char *kDevPerfLevelHighStr = "high";
|
||||
static const char *kDevPerfLevelManualStr = "manual";
|
||||
static const char *kDevPerfLevelStandardStr = "profile_standard";
|
||||
static const char *kDevPerfLevelMinMClkStr = "profile_min_mclk";
|
||||
static const char *kDevPerfLevelMinSClkStr = "profile_min_sclk";
|
||||
static const char *kDevPerfLevelPeakStr = "profile_peak";
|
||||
static const char *kDevPerfLevelUnknownStr = "unknown";
|
||||
|
||||
static const std::map<DevInfoTypes, const char *> kDevAttribNameMap = {
|
||||
{kDevPerfLevel, kDevPerfLevelFName},
|
||||
{kDevOverDriveLevel, kDevOverDriveLevelFName},
|
||||
@@ -217,7 +219,7 @@ static const std::map<DevInfoTypes, const char *> kDevAttribNameMap = {
|
||||
{kDevDCEFClk, kDevDCEFClkFName},
|
||||
{kDevFClk, kDevFClkFName},
|
||||
{kDevSOCClk, kDevSOCClkFName},
|
||||
{kDevPCIEClk, kDevGPUPCIEClkFname},
|
||||
{kDevPCIEClk, kDevPCIEClkFName},
|
||||
{kDevPowerProfileMode, kDevPowerProfileModeFName},
|
||||
{kDevUsage, kDevUsageFName},
|
||||
{kDevPowerODVoltage, kDevPowerODVoltageFName},
|
||||
@@ -276,6 +278,178 @@ static const std::map<rsmi_dev_perf_level, const char *> kDevPerfLvlMap = {
|
||||
{RSMI_DEV_PERF_LEVEL_UNKNOWN, kDevPerfLevelUnknownStr},
|
||||
};
|
||||
|
||||
static std::map<DevInfoTypes, uint8_t> kDevInfoVarTypeToRSMIVariant = {
|
||||
// rsmi_memory_type_t
|
||||
{kDevMemTotGTT, RSMI_MEM_TYPE_GTT},
|
||||
{kDevMemTotVisVRAM, RSMI_MEM_TYPE_VIS_VRAM},
|
||||
{kDevMemTotVRAM, RSMI_MEM_TYPE_VRAM},
|
||||
{kDevMemUsedGTT, RSMI_MEM_TYPE_GTT},
|
||||
{kDevMemUsedVisVRAM, RSMI_MEM_TYPE_VIS_VRAM},
|
||||
{kDevMemUsedVRAM, RSMI_MEM_TYPE_VRAM},
|
||||
|
||||
// rsmi_clk_type_t
|
||||
{kDevGPUSClk, RSMI_CLK_TYPE_SYS},
|
||||
{kDevGPUMClk, RSMI_CLK_TYPE_MEM},
|
||||
{kDevFClk, RSMI_CLK_TYPE_DF},
|
||||
{kDevDCEFClk, RSMI_CLK_TYPE_DCEF},
|
||||
{kDevSOCClk, RSMI_CLK_TYPE_SOC},
|
||||
|
||||
// rsmi_fw_block_t
|
||||
{kDevFwVersionAsd, RSMI_FW_BLOCK_ASD},
|
||||
{kDevFwVersionCe, RSMI_FW_BLOCK_CE},
|
||||
{kDevFwVersionDmcu, RSMI_FW_BLOCK_DMCU},
|
||||
{kDevFwVersionMc, RSMI_FW_BLOCK_MC},
|
||||
{kDevFwVersionMe, RSMI_FW_BLOCK_ME},
|
||||
{kDevFwVersionMec, RSMI_FW_BLOCK_MEC},
|
||||
{kDevFwVersionMec2, RSMI_FW_BLOCK_MEC2},
|
||||
{kDevFwVersionPfp, RSMI_FW_BLOCK_PFP},
|
||||
{kDevFwVersionRlc, RSMI_FW_BLOCK_RLC},
|
||||
{kDevFwVersionRlcSrlc, RSMI_FW_BLOCK_RLC_SRLC},
|
||||
{kDevFwVersionRlcSrlg, RSMI_FW_BLOCK_RLC_SRLG},
|
||||
{kDevFwVersionRlcSrls, RSMI_FW_BLOCK_RLC_SRLS},
|
||||
{kDevFwVersionSdma, RSMI_FW_BLOCK_SDMA},
|
||||
{kDevFwVersionSdma2, RSMI_FW_BLOCK_SDMA2},
|
||||
{kDevFwVersionSmc, RSMI_FW_BLOCK_SMC},
|
||||
{kDevFwVersionSos, RSMI_FW_BLOCK_SOS},
|
||||
{kDevFwVersionTaRas, RSMI_FW_BLOCK_TA_RAS},
|
||||
{kDevFwVersionTaXgmi, RSMI_FW_BLOCK_TA_XGMI},
|
||||
{kDevFwVersionUvd, RSMI_FW_BLOCK_UVD},
|
||||
{kDevFwVersionVce, RSMI_FW_BLOCK_VCE},
|
||||
{kDevFwVersionVcn, RSMI_FW_BLOCK_VCN},
|
||||
|
||||
// rsmi_gpu_block_t
|
||||
{kDevErrCntUMC, RSMI_GPU_BLOCK_UMC},
|
||||
{kDevErrCntSDMA, RSMI_GPU_BLOCK_SDMA},
|
||||
{kDevErrCntGFX, RSMI_GPU_BLOCK_GFX},
|
||||
|
||||
// rsmi_event_group_t
|
||||
{kDevDFCountersAvailable, RSMI_EVNT_GRP_XGMI}
|
||||
};
|
||||
|
||||
static const std::map<const char *, dev_depends_t> kDevFuncDependsMap = {
|
||||
// Functions with only mandatory dependencies
|
||||
{"rsmi_dev_id_get", {{kDevDevIDFName}, {}}},
|
||||
{"rsmi_dev_vendor_id_get", {{kDevVendorIDFName}, {}}},
|
||||
|
||||
{"rsmi_dev_name_get", {{kDevVendorIDFName,
|
||||
kDevDevIDFName}, {}}},
|
||||
{"rsmi_dev_brand_get", {{kDevVendorIDFName}, {}}},
|
||||
{"rsmi_dev_vendor_name_get", {{kDevVendorIDFName}, {}}},
|
||||
{"rsmi_dev_serial_number_get", {{kDevSerialNumberFName}, {}}},
|
||||
{"rsmi_dev_subsystem_id_get", {{kDevSubSysDevIDFName}, {}}},
|
||||
{"rsmi_dev_subsystem_name_get", {{kDevSubSysVendorIDFName,
|
||||
kDevVendorIDFName,
|
||||
kDevDevIDFName}, {}}},
|
||||
{"rsmi_dev_drm_render_minor_get", {{}, {}}},
|
||||
{"rsmi_dev_subsystem_vendor_id_get", {{kDevSubSysVendorIDFName}, {}}},
|
||||
{"rsmi_dev_unique_id_get", {{kDevUniqueIdFName}, {}}},
|
||||
{"rsmi_dev_pci_bandwidth_get", {{kDevPCIEClkFName}, {}}},
|
||||
{"rsmi_dev_pci_id_get", {{}, {}}},
|
||||
{"rsmi_dev_pci_throughput_get", {{kDevPCIEThruPutFName}, {}}},
|
||||
{"rsmi_dev_pci_replay_counter_get", {{kDevPCIEReplayCountFName}, {}}},
|
||||
{"rsmi_dev_pci_bandwidth_set", {{kDevPerfLevelFName,
|
||||
kDevPCIEClkFName}, {}}},
|
||||
{"rsmi_dev_power_profile_set", {{kDevPerfLevelFName,
|
||||
kDevPowerProfileModeFName}, {}}},
|
||||
{"rsmi_dev_memory_busy_percent_get", {{kDevMemBusyPercentFName}, {}}},
|
||||
{"rsmi_dev_busy_percent_get", {{kDevUsageFName}, {}}},
|
||||
{"rsmi_dev_memory_reserved_pages_get", {{kDevMemPageBadFName}, {}}},
|
||||
{"rsmi_dev_overdrive_level_get", {{kDevOverDriveLevelFName}, {}}},
|
||||
{"rsmi_dev_power_profile_presets_get", {{kDevPowerProfileModeFName}, {}}},
|
||||
{"rsmi_dev_perf_level_set", {{kDevPerfLevelFName}, {}}},
|
||||
{"rsmi_dev_perf_level_get", {{kDevPerfLevelFName}, {}}},
|
||||
{"rsmi_dev_overdrive_level_set", {{kDevOverDriveLevelFName}, {}}},
|
||||
{"rsmi_dev_vbios_version_get", {{kDevVBiosVerFName}, {}}},
|
||||
{"rsmi_dev_od_volt_info_get", {{kDevPowerODVoltageFName}, {}}},
|
||||
{"rsmi_dev_od_volt_curve_regions_get", {{kDevPowerODVoltageFName}, {}}},
|
||||
{"rsmi_dev_ecc_enabled_get", {{kDevErrCntFeaturesFName}, {}}},
|
||||
{"rsmi_dev_ecc_status_get", {{kDevErrCntFeaturesFName}, {}}},
|
||||
{"rsmi_dev_counter_group_supported", {{}, {}}},
|
||||
{"rsmi_dev_counter_create", {{}, {}}},
|
||||
{"rsmi_dev_xgmi_error_status", {{kDevXGMIErrorFName}, {}}},
|
||||
{"rsmi_dev_xgmi_error_reset", {{kDevXGMIErrorFName}, {}}},
|
||||
{"rsmi_dev_memory_reserved_pages_get", {{kDevMemPageBadFName}, {}}},
|
||||
|
||||
// These functions with variants, but no sensors/units. (May or may not
|
||||
// have mandatory dependencies.)
|
||||
{"rsmi_dev_memory_total_get", { .mandatory_depends = {},
|
||||
.variants = {
|
||||
kDevMemTotGTT, kDevMemTotVisVRAM,
|
||||
kDevMemTotVRAM,
|
||||
}
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_memory_usage_get", { .mandatory_depends = {},
|
||||
.variants = {
|
||||
kDevMemUsedGTT,
|
||||
kDevMemUsedVisVRAM,
|
||||
kDevMemUsedVRAM,
|
||||
}
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_gpu_clk_freq_get", { .mandatory_depends = {},
|
||||
.variants = {
|
||||
kDevGPUSClk,
|
||||
kDevGPUMClk,
|
||||
kDevFClk,
|
||||
kDevDCEFClk,
|
||||
kDevSOCClk,
|
||||
}
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_gpu_clk_freq_set", { .mandatory_depends =
|
||||
{kDevPerfLevelFName},
|
||||
.variants = {
|
||||
kDevGPUSClk,
|
||||
kDevGPUMClk,
|
||||
kDevFClk,
|
||||
kDevDCEFClk,
|
||||
kDevSOCClk,
|
||||
}
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_firmware_version_get", { .mandatory_depends = {},
|
||||
.variants = {
|
||||
kDevFwVersionAsd,
|
||||
kDevFwVersionCe,
|
||||
kDevFwVersionDmcu,
|
||||
kDevFwVersionMc,
|
||||
kDevFwVersionMe,
|
||||
kDevFwVersionMec,
|
||||
kDevFwVersionMec2,
|
||||
kDevFwVersionPfp,
|
||||
kDevFwVersionRlc,
|
||||
kDevFwVersionRlcSrlc,
|
||||
kDevFwVersionRlcSrlg,
|
||||
kDevFwVersionRlcSrls,
|
||||
kDevFwVersionSdma,
|
||||
kDevFwVersionSdma2,
|
||||
kDevFwVersionSmc,
|
||||
kDevFwVersionSos,
|
||||
kDevFwVersionTaRas,
|
||||
kDevFwVersionTaXgmi,
|
||||
kDevFwVersionUvd,
|
||||
kDevFwVersionVce,
|
||||
kDevFwVersionVcn,
|
||||
}
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_ecc_count_get", { .mandatory_depends = {},
|
||||
.variants = {
|
||||
kDevErrCntUMC,
|
||||
kDevErrCntSDMA,
|
||||
kDevErrCntGFX,
|
||||
}
|
||||
}
|
||||
},
|
||||
{"rsmi_counter_available_counters_get", { .mandatory_depends = {},
|
||||
.variants = {
|
||||
kDevDFCountersAvailable,
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
#define RET_IF_NONZERO(X) { \
|
||||
if (X) return X; \
|
||||
}
|
||||
@@ -632,6 +806,109 @@ int Device::getKFDNodeProperty(DevKFDNodePropTypes prop, uint64_t *val) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Device::DumpSupportedFunctions(void) {
|
||||
SupportedFuncMapIt func_iter = supported_funcs_.begin();
|
||||
|
||||
std::cout << "*** Supported Functions ***" << std::endl;
|
||||
|
||||
while (func_iter != supported_funcs_.end()) {
|
||||
std::cout << func_iter->first << std::endl;
|
||||
|
||||
std::cout << "\tSupported Variants(Monitors): ";
|
||||
if (func_iter->second) {
|
||||
VariantMapIt var_iter = func_iter->second->begin();
|
||||
|
||||
// We should have at least 1 supported variant or the function should
|
||||
// not be listed as supported.
|
||||
assert(var_iter != func_iter->second->end());
|
||||
|
||||
while (var_iter != func_iter->second->end()) {
|
||||
std::cout << static_cast<uint32_t>(var_iter->first);
|
||||
|
||||
if (var_iter->second) {
|
||||
std::cout << "(";
|
||||
|
||||
SubVariantIt mon_iter = var_iter->second->begin();
|
||||
|
||||
// We should have at least 1 supported monitor or the function should
|
||||
// not be listed as supported.
|
||||
assert(mon_iter != var_iter->second->end());
|
||||
while (mon_iter != var_iter->second->end()) {
|
||||
std::cout << static_cast<uint32_t>(*mon_iter) << ", ";
|
||||
mon_iter++;
|
||||
}
|
||||
std::cout << ")";
|
||||
}
|
||||
std::cout << ", ";
|
||||
var_iter++;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
} else {
|
||||
std::cout << "Not Applicable" << std::endl;
|
||||
}
|
||||
func_iter++;
|
||||
}
|
||||
}
|
||||
|
||||
void Device::fillSupportedFuncs(void) {
|
||||
if (supported_funcs_.size() != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<const char *, dev_depends_t>::const_iterator it =
|
||||
kDevFuncDependsMap.begin();
|
||||
std::string dev_rt = path_ + "/device";
|
||||
bool mand_depends_met;
|
||||
std::shared_ptr<VariantMap> supported_variants;
|
||||
|
||||
while (it != kDevFuncDependsMap.end()) {
|
||||
// First, see if all the mandatory dependencies are there
|
||||
std::vector<const char *>::const_iterator dep =
|
||||
it->second.mandatory_depends.begin();
|
||||
|
||||
mand_depends_met = true;
|
||||
for (; dep != it->second.mandatory_depends.end(); dep++) {
|
||||
std::string dep_path = dev_rt + "/" + *dep;
|
||||
if (!FileExists(dep_path.c_str())) {
|
||||
mand_depends_met = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mand_depends_met) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
// Then, see if the variants are supported.
|
||||
std::vector<DevInfoTypes>::const_iterator var =
|
||||
it->second.variants.begin();
|
||||
|
||||
if (it->second.variants.size() == 0) {
|
||||
supported_funcs_[it->first] = nullptr;
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
supported_variants = std::make_shared<VariantMap>();
|
||||
|
||||
for (; var != it->second.variants.end(); var++) {
|
||||
std::string variant_path = dev_rt + "/" + kDevAttribNameMap.at(*var);
|
||||
if (!FileExists(variant_path.c_str())) {
|
||||
continue;
|
||||
}
|
||||
// At this point we assume no monitors, so map to nullptr
|
||||
(*supported_variants)[kDevInfoVarTypeToRSMIVariant.at(*var)] = nullptr;
|
||||
}
|
||||
|
||||
if ((*supported_variants).size() > 0) {
|
||||
supported_funcs_[it->first] = supported_variants;
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
monitor()->fillSupportedFuncs(&supported_funcs_);
|
||||
// DumpSupportedFunctions();
|
||||
}
|
||||
|
||||
#undef RET_IF_NONZERO
|
||||
} // namespace smi
|
||||
} // namespace amd
|
||||
|
||||
+235
-1
@@ -42,6 +42,7 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
@@ -49,6 +50,8 @@
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <regex> // NOLINT
|
||||
#include <vector>
|
||||
|
||||
#include "rocm_smi/rocm_smi_main.h"
|
||||
#include "rocm_smi/rocm_smi_monitor.h"
|
||||
@@ -126,7 +129,100 @@ static const std::map<MonitorTypes, const char *> kMonitorNameMap = {
|
||||
{kMonTempLabel, kMonTempLabelName},
|
||||
};
|
||||
|
||||
Monitor::Monitor(std::string path, RocmSMI_env_vars const *e) :
|
||||
static std::map<MonitorTypes, uint64_t> kMonInfoVarTypeToRSMIVariant = {
|
||||
// rsmi_temperature_metric_t
|
||||
{kMonTemp, RSMI_TEMP_CURRENT},
|
||||
{kMonTempMax, RSMI_TEMP_MAX},
|
||||
{kMonTempMin, RSMI_TEMP_MIN},
|
||||
{kMonTempMaxHyst, RSMI_TEMP_MAX_HYST},
|
||||
{kMonTempMinHyst, RSMI_TEMP_MIN_HYST},
|
||||
{kMonTempCritical, RSMI_TEMP_CRITICAL},
|
||||
{kMonTempCriticalHyst, RSMI_TEMP_CRITICAL_HYST},
|
||||
{kMonTempEmergency, RSMI_TEMP_EMERGENCY},
|
||||
{kMonTempEmergencyHyst, RSMI_TEMP_EMERGENCY_HYST},
|
||||
{kMonTempCritMin, RSMI_TEMP_CRIT_MIN},
|
||||
{kMonTempCritMinHyst, RSMI_TEMP_CRIT_MIN_HYST},
|
||||
{kMonTempOffset, RSMI_TEMP_OFFSET},
|
||||
{kMonTempLowest, RSMI_TEMP_LOWEST},
|
||||
{kMonTempHighest, RSMI_TEMP_HIGHEST},
|
||||
{kMonInvalid, RSMI_DEFAULT_VARIANT},
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
std::vector<const char *> mandatory_depends;
|
||||
std::vector<MonitorTypes> variants;
|
||||
} monitor_depends_t;
|
||||
|
||||
static const std::map<const char *, monitor_depends_t> kMonFuncDependsMap = {
|
||||
{"rsmi_dev_power_ave_get", { .mandatory_depends = {kMonPowerAveName},
|
||||
.variants = {kMonInvalid},
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_power_cap_get", { .mandatory_depends = {kMonPowerCapName},
|
||||
.variants = {kMonInvalid},
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_power_cap_range_get", { .mandatory_depends =
|
||||
{kMonPowerCapMaxName,
|
||||
kMonPowerCapMinName},
|
||||
.variants = {kMonInvalid},
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_power_cap_set", { .mandatory_depends =
|
||||
{kMonPowerCapMaxName,
|
||||
kMonPowerCapMinName,
|
||||
kMonPowerCapName},
|
||||
.variants = {kMonInvalid},
|
||||
}
|
||||
},
|
||||
|
||||
{"rsmi_dev_fan_rpms_get", { .mandatory_depends = {kMonFanRPMsName},
|
||||
.variants = {kMonInvalid},
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_fan_speed_get", { .mandatory_depends = {kMonFanSpeedFName},
|
||||
.variants = {kMonInvalid},
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_fan_speed_max_get", { .mandatory_depends =
|
||||
{kMonMaxFanSpeedFName},
|
||||
.variants = {kMonInvalid},
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_temp_metric_get", { .mandatory_depends =
|
||||
{kMonTempLabelName},
|
||||
.variants = {kMonTemp,
|
||||
kMonTempMax,
|
||||
kMonTempMin,
|
||||
kMonTempMaxHyst,
|
||||
kMonTempMinHyst,
|
||||
kMonTempCritical,
|
||||
kMonTempCriticalHyst,
|
||||
kMonTempEmergency,
|
||||
kMonTempEmergencyHyst,
|
||||
kMonTempCritMin,
|
||||
kMonTempCritMinHyst,
|
||||
kMonTempOffset,
|
||||
kMonTempLowest,
|
||||
kMonTempHighest,
|
||||
},
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_fan_reset", { .mandatory_depends =
|
||||
{kMonFanControlEnableName},
|
||||
.variants = {kMonInvalid},
|
||||
}
|
||||
},
|
||||
{"rsmi_dev_fan_speed_set", { .mandatory_depends =
|
||||
{kMonMaxFanSpeedFName,
|
||||
kMonFanControlEnableName,
|
||||
kMonFanSpeedFName},
|
||||
.variants = {kMonInvalid},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Monitor::Monitor(std::string path, RocmSMI_env_vars const *e) :
|
||||
path_(path), env_(e) {
|
||||
}
|
||||
Monitor::~Monitor(void) {
|
||||
@@ -193,11 +289,149 @@ Monitor::setSensorLabelMap(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_supported_sensors(std::string dir_path, std::string fn_reg_ex,
|
||||
std::vector<uint64_t> *sensors) {
|
||||
auto hwmon_dir = opendir(dir_path.c_str());
|
||||
assert(hwmon_dir != nullptr);
|
||||
assert(sensors != nullptr);
|
||||
|
||||
sensors->clear();
|
||||
|
||||
std::string::size_type pos = fn_reg_ex.find('#');
|
||||
|
||||
if (pos == std::string::npos) {
|
||||
return -1;
|
||||
}
|
||||
fn_reg_ex.erase(pos, 1);
|
||||
fn_reg_ex.insert(pos, "([0-9]+)");
|
||||
fn_reg_ex = "\\b" + fn_reg_ex + "\\b";
|
||||
|
||||
auto dentry = readdir(hwmon_dir);
|
||||
std::smatch match;
|
||||
int64_t mon_val;
|
||||
|
||||
char *endptr;
|
||||
std::regex re(fn_reg_ex);
|
||||
std::string fn;
|
||||
|
||||
while (dentry != nullptr) {
|
||||
fn = dentry->d_name;
|
||||
if (std::regex_search(fn, match, re)) {
|
||||
assert(match.size() == 2); // 1 for whole match + 1 for sub-match
|
||||
errno = 0;
|
||||
mon_val = strtol(match.str(1).c_str(), &endptr, 10);
|
||||
assert(errno == 0);
|
||||
assert(*endptr == '\0');
|
||||
if (errno) {
|
||||
return -2;
|
||||
}
|
||||
sensors->push_back(mon_val);
|
||||
}
|
||||
dentry = readdir(hwmon_dir);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Monitor::getSensorIndex(rsmi_temperature_type_t type) {
|
||||
return temp_type_index_map_.at(type);
|
||||
}
|
||||
|
||||
static std::vector<uint64_t> get_intersection(std::vector<uint64_t> *v1,
|
||||
std::vector<uint64_t> *v2) {
|
||||
assert(v1 != nullptr);
|
||||
assert(v2 != nullptr);
|
||||
std::vector<uint64_t> intersect;
|
||||
|
||||
std::sort(v1->begin(), v1->end());
|
||||
std::sort(v2->begin(), v2->end());
|
||||
|
||||
std::set_intersection(v1->begin(), v1->end(), v2->begin(), v2->end(),
|
||||
std::back_inserter(intersect));
|
||||
return intersect;
|
||||
}
|
||||
|
||||
void Monitor::fillSupportedFuncs(SupportedFuncMap *supported_funcs) {
|
||||
std::map<const char *, monitor_depends_t>::const_iterator it =
|
||||
kMonFuncDependsMap.begin();
|
||||
std::string mon_root = path_;
|
||||
bool mand_depends_met;
|
||||
std::shared_ptr<VariantMap> supported_variants;
|
||||
std::vector<uint64_t> sensors_i;
|
||||
std::vector<uint64_t> intersect;
|
||||
int ret;
|
||||
|
||||
assert(supported_funcs != nullptr);
|
||||
|
||||
while (it != kMonFuncDependsMap.end()) {
|
||||
// First, see if all the mandatory dependencies are there
|
||||
std::vector<const char *>::const_iterator dep =
|
||||
it->second.mandatory_depends.begin();
|
||||
|
||||
mand_depends_met = true;
|
||||
|
||||
// Initialize "intersect". A monitor is considered supported if all of its
|
||||
// dependency monitors with the same sensor index are present. So we
|
||||
// initialize "intersect" with the set of sensors that exist for the first
|
||||
// mandatory monitor, and take intersection of that with the subsequent
|
||||
// dependency monitors. The main assumption here is that
|
||||
// variant_<sensor_i>'s sensor-based dependencies have the same index i;
|
||||
// in other words, variant_i is not dependent on a sensor j, j != i
|
||||
do {
|
||||
ret = get_supported_sensors(mon_root + "/", *dep, &intersect);
|
||||
if (ret == -1) {
|
||||
// In this case, the dependency is not sensor-specific, so just
|
||||
// see if the file exists.
|
||||
std::string dep_path = mon_root + "/" + *dep;
|
||||
if (!FileExists(dep_path.c_str())) {
|
||||
mand_depends_met = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
dep++;
|
||||
} while (dep != it->second.mandatory_depends.end());
|
||||
|
||||
if (!mand_depends_met) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// "intersect" holds the set of sensors for the mandatory dependencies
|
||||
// that exist.
|
||||
|
||||
std::vector<MonitorTypes>::const_iterator var =
|
||||
it->second.variants.begin();
|
||||
supported_variants = std::make_shared<VariantMap>();
|
||||
|
||||
std::vector<uint64_t> supported_monitors;
|
||||
|
||||
for (; var != it->second.variants.end(); var++) {
|
||||
if (*var != kMonInvalid) {
|
||||
ret = get_supported_sensors(mon_root + "/",
|
||||
kMonitorNameMap.at(*var), &sensors_i);
|
||||
|
||||
if (ret == 0) {
|
||||
supported_monitors = get_intersection(&sensors_i, &intersect);
|
||||
}
|
||||
} else {
|
||||
supported_monitors = intersect;
|
||||
}
|
||||
if (supported_monitors.size() > 0) {
|
||||
(*supported_variants)[kMonInfoVarTypeToRSMIVariant.at(*var)] =
|
||||
std::make_shared<SubVariant>(supported_monitors);
|
||||
}
|
||||
}
|
||||
|
||||
if (it->second.variants.size() == 0) {
|
||||
(*supported_funcs)[it->first] = nullptr;
|
||||
supported_variants = nullptr; // Invoke destructor
|
||||
} else if ((*supported_variants).size() > 0) {
|
||||
(*supported_funcs)[it->first] = supported_variants;
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace smi
|
||||
} // namespace amd
|
||||
|
||||
Reference in New Issue
Block a user