diff --git a/src/extract_gpuinfo_amdgpu.c b/src/extract_gpuinfo_amdgpu.c index a548cda..ab29a7e 100644 --- a/src/extract_gpuinfo_amdgpu.c +++ b/src/extract_gpuinfo_amdgpu.c @@ -122,6 +122,7 @@ struct gpu_info_amdgpu { FILE *fanSpeedFILE; // FILE* for this device current fan speed FILE *PCIeBW; // FILE* for this device PCIe bandwidth over one second FILE *powerCap; // FILE* for this device power cap + FILE *powerCapDefault; nvtop_device *amdgpuDevice; // The AMDGPU driver device nvtop_device *hwmonDevice; // The AMDGPU driver hwmon device @@ -241,6 +242,8 @@ static void gpuinfo_amdgpu_shutdown(void) { fclose(gpu_info->PCIeBW); if (gpu_info->powerCap) fclose(gpu_info->powerCap); + if (gpu_info->powerCapDefault) + fclose(gpu_info->powerCapDefault); nvtop_device_unref(gpu_info->amdgpuDevice); nvtop_device_unref(gpu_info->hwmonDevice); _drmFreeVersion(gpu_info->drmVersion); @@ -363,8 +366,18 @@ static void initDeviceSysfsPaths(struct gpu_info_amdgpu *gpu_info) { // Open the power cap file for dynamic info gathering gpu_info->powerCap = NULL; int powerCapFD = openat(hwmonFD, "power1_cap", O_RDONLY); - if (powerCapFD) { - gpu_info->powerCap = fdopen(powerCapFD, "r"); + if (powerCapFD >= 0) { + gpu_info->powerCap = fdopen(powerCapFD, "r"); + if (!gpu_info->powerCap) + close(powerCapFD); + } + + gpu_info->powerCapDefault = NULL; + int powerCapDefaultFD = openat(hwmonFD, "power1_cap_default", O_RDONLY); + if (powerCapDefaultFD >= 0) { + gpu_info->powerCapDefault = fdopen(powerCapDefaultFD, "r"); + if (!gpu_info->powerCapDefault) + close(powerCapDefaultFD); } close(hwmonFD); } @@ -773,14 +786,28 @@ static void gpuinfo_amdgpu_refresh_dynamic_info(struct gpu_info *_gpu_info) { } } + unsigned powerCap = 0; + bool havePowerCap = false; + + /* First try the current enforced power cap */ if (gpu_info->powerCap) { - // The power cap in microwatts - unsigned powerCap; - int NreadPatterns = rewindAndReadPattern(gpu_info->powerCap, "%u", &powerCap); - if (NreadPatterns == 1) { - SET_GPUINFO_DYNAMIC(dynamic_info, power_draw_max, powerCap / 1000); + if (rewindAndReadPattern(gpu_info->powerCap, "%u", &powerCap) == 1 && + powerCap > 0) { + havePowerCap = true; + } + } + + /* If unavailable or reported as 0, fall back to the default cap */ + if (!havePowerCap && gpu_info->powerCapDefault) { + if (rewindAndReadPattern(gpu_info->powerCapDefault, "%u", &powerCap) == 1 && + powerCap > 0) { + havePowerCap = true; } } + + if (havePowerCap) { + SET_GPUINFO_DYNAMIC(dynamic_info, power_draw_max, powerCap / 1000); + } } static const char drm_amdgpu_pdev_old[] = "pdev"; diff --git a/src/interface.c b/src/interface.c index ae23199..e46fe4f 100644 --- a/src/interface.c +++ b/src/interface.c @@ -1706,14 +1706,20 @@ void save_current_data_to_ring(struct list_head *devices, struct nvtop_interface data_val = 100u; } break; - case plot_gpu_power_draw_rate: - if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, power_draw) && - GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, power_draw_max)) { - data_val = device->dynamic_info.power_draw * 100 / device->dynamic_info.power_draw_max; - if (data_val > 100) - data_val = 100u; - } - break; + case plot_gpu_power_draw_rate: + if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, power_draw) && + GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, power_draw_max) && + device->dynamic_info.power_draw_max > 0) { + + data_val = device->dynamic_info.power_draw * 100 / + device->dynamic_info.power_draw_max; + + if (data_val > 100) + data_val = 100u; + } else { + data_val = 0; + } + break; case plot_fan_speed: if (GPUINFO_DYNAMIC_FIELD_VALID(&device->dynamic_info, fan_speed)) { data_val = device->dynamic_info.fan_speed;