add AMD power nodes

This commit is contained in:
Jussi Kuokkanen 2023-10-24 22:26:52 +03:00
parent 38e43f7db4
commit 78b826f81d

View File

@ -256,6 +256,82 @@ std::vector<TreeNode<DeviceNode>> getFanSpeedRead(AMDGPUData data) {
return {};
}
std::vector<TreeNode<DeviceNode>> getPowerLimit(AMDGPUData data) {
// Get delta of min and max fan RPMs
char path[96];
snprintf(path, 96, "%s/power1_cap_min", data.hwmonPath.c_str());
auto contents = fileContents(path);
if (!contents.has_value())
return {};
// uW -> W
double minLimit = static_cast<double>(std::stoi(*contents)) / 1000000;
snprintf(path, 96, "%s/power1_cap_max", data.hwmonPath.c_str());
contents = fileContents(path);
if (!contents.has_value())
return {};
double maxLimit = static_cast<double>(std::stoi(*contents)) / 1000000;
Range<double> range{minLimit, maxLimit};
snprintf(path, 96, "%s/power1_cap", data.hwmonPath.c_str());
auto getFunc = [=]() -> std::optional<AssignmentArgument> {
auto string = fileContents(path);
if (!string.has_value())
return std::nullopt;
int cur_uW = std::stoi(*string);
return static_cast<double>(cur_uW) / 1000000;
};
auto setFunc = [=](AssignmentArgument a) -> std::optional<AssignmentError> {
if (!std::holds_alternative<double>(a))
return AssignmentError::InvalidType;
auto value = std::get<double>(a);
if (value < range.min || value > range.max)
return AssignmentError::OutOfRange;
// W -> uW
auto target = std::round(value * 1000000);
if (std::ofstream{path} << target)
return std::nullopt;
return AssignmentError::UnknownError;
};
Assignable a{setFunc, range, getFunc, _("W")};
return {DeviceNode{
.name = _("Power Limit"),
.interface = a,
.hash = md5(data.pciId + "Power Limit"),
}};
}
std::vector<TreeNode<DeviceNode>> getPowerUsage(AMDGPUData data) {
auto func = [=]() -> ReadResult {
uint power;
// TODO: is this microwatts too?
if (amdgpu_query_sensor_info(data.devHandle, AMDGPU_INFO_SENSOR_GPU_AVG_POWER,
sizeof(power), &power) == 0)
return static_cast<double>(power) / 1000000;
return ReadError::UnknownError;
};
DynamicReadable dr{func, _("W")};
if (hasReadableValue(func())) {
return {DeviceNode{
.name = _("Power Usage"),
.interface = dr,
.hash = md5(data.pciId + "Power Usage"),
}};
}
return {};
}
std::vector<TreeNode<DeviceNode>> getFanRoot(AMDGPUData data) {
return {DeviceNode{
.name = _("Fans"),
@ -264,6 +340,15 @@ std::vector<TreeNode<DeviceNode>> getFanRoot(AMDGPUData data) {
}};
}
std::vector<TreeNode<DeviceNode>> getPowerRoot(AMDGPUData data) {
// Root for power usage and power limit
return {DeviceNode{
.name = _("Power"),
.interface = std::nullopt,
.hash = md5(data.pciId + "Power"),
}};
}
std::vector<TreeNode<DeviceNode>> getGPUName(AMDGPUData data) {
auto name = amdgpu_get_marketing_name(data.devHandle);
if (name) {
@ -284,6 +369,10 @@ auto gpuTree = TreeConstructor<AMDGPUData, DeviceNode>{
{getFanMode, {}},
{getFanSpeedWrite, {}},
{getFanSpeedRead, {}}
}},
{getPowerRoot, {
{getPowerLimit, {}},
{getPowerUsage, {}}
}}
}
};