added gpu
This commit is contained in:
123
src/gpu.c
Normal file
123
src/gpu.c
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "gpu.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "gpu_metrics.h"
|
||||
|
||||
#include "utils.h"
|
||||
#include "log.h"
|
||||
|
||||
constexpr char rel_metrics_path[] = "/../../gpu_metrics"; // gpu_metrics path relative to hwmon path
|
||||
constexpr uint16_t max_metrics_length = 512; // length of the metrics buffer
|
||||
|
||||
void gpu_detect(struct gpu_sensors_t *t, const char *pci) {
|
||||
snprintf(t->hwmon, sizeof(t->hwmon), "/sys/bus/pci/devices/%s/hwmon", pci);
|
||||
const int ret = get_hwmon_dir(t->hwmon);
|
||||
if (ret != 0) {
|
||||
t->hwmon[0] = '\0';
|
||||
applog(LOG_WRN, "Detected GPU hwmon");
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[128];
|
||||
char *nt = stpncpy(buf, t->hwmon, sizeof(buf));
|
||||
stpcpy(nt, rel_metrics_path); // write at the null terminator address
|
||||
if (file_exists(buf)) {
|
||||
char raw_metrics[max_metrics_length];
|
||||
if (!read_file(buf, raw_metrics, sizeof(raw_metrics)))
|
||||
return;
|
||||
const struct metrics_table_header* header = (struct metrics_table_header*)raw_metrics;
|
||||
applog(LOG_INF, "Found gpu_metrics_v%d_%d", header->format_revision, header->content_revision);
|
||||
t->has_gpu_metrics = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* some metrics are missing in gpu_metrics, we always fill them from fs, unused metrics are commented out */
|
||||
void fill_missing_metrics(struct gpu_sensors_t *g) {
|
||||
char buf[32];
|
||||
fast_read_num_f(g->hwmon, "/in0_input", buf, &g->vcore, 1000);
|
||||
// g->fan_pwm = std::stoi(readFile(g->hwmon + "/pwm1", 4)) * 100 / 256;
|
||||
fast_read_num_u16(g->hwmon, "/fan1_input", buf, &g->fan_speed, 1);
|
||||
fast_read_num_u16(g->hwmon, "/power1_cap", buf, &g->power_cap, 1000000);
|
||||
// utils::fastReadNum(g->hwmon + "/power1_cap_max", g->power_cap_max) / 1000000;
|
||||
fast_read_num_u64(g->hwmon, "/../../mem_info_vram_used", buf, &g->vram_used, 1);
|
||||
// utils::fastReadNum(g->hwmon + "/../../mem_info_vram_total", g->vram_total);
|
||||
}
|
||||
|
||||
/* get sensors for pre-vega cards (rx480/580) */
|
||||
void update_from_fs(struct gpu_sensors_t *g) {
|
||||
char buf[32];
|
||||
fast_read_num_u16(g->hwmon, "/freq1_input", buf, &g->clock_core, 1000000);
|
||||
fast_read_num_u16(g->hwmon, "/freq2_input", buf, &g->clock_mem, 1000000);
|
||||
fast_read_num_u16(g->hwmon, "/power1_input", buf, &g->power_avg, 1000000);
|
||||
fast_read_num_u8(g->hwmon, "/temp1_input", buf, &g->temp_edge, 1000);
|
||||
fast_read_num_u8(g->hwmon, "/../../gpu_busy_percent", buf, &g->usage_core, 1);
|
||||
}
|
||||
|
||||
void update_from_metrics(struct gpu_sensors_t *g) {
|
||||
char buf[128];
|
||||
char raw_metrics[max_metrics_length];
|
||||
char *nt = stpncpy(buf, g->hwmon, sizeof(buf));
|
||||
stpcpy(nt, rel_metrics_path); // write at the null terminator address
|
||||
|
||||
if (!read_file(buf, raw_metrics, sizeof(raw_metrics)))
|
||||
return;
|
||||
|
||||
const struct metrics_table_header *header = (struct metrics_table_header *)raw_metrics;
|
||||
|
||||
switch (header->format_revision * 10 + header->content_revision) {
|
||||
|
||||
/* rx5700xt, rx7800xtx rx9070xt */
|
||||
case 13: {
|
||||
const struct gpu_metrics_v1_3* metrics = (struct gpu_metrics_v1_3*)raw_metrics;
|
||||
g->usage_core = metrics->average_gfx_activity;
|
||||
g->usage_umc = metrics->average_umc_activity;
|
||||
g->usage_media = metrics->average_mm_activity;
|
||||
|
||||
g->temp_edge = metrics->temperature_edge;
|
||||
g->temp_hotspot = metrics->temperature_hotspot;
|
||||
g->temp_mem = metrics->temperature_mem;
|
||||
|
||||
g->temp_vrm_gfx = metrics->temperature_vrgfx;
|
||||
g->temp_vrm_soc = metrics->temperature_vrsoc;
|
||||
g->temp_vrm_mem = metrics->temperature_vrmem;
|
||||
g->power_avg = metrics->average_socket_power;
|
||||
g->fan_speed = metrics->current_fan_speed;
|
||||
|
||||
g->clock_core = metrics->average_gfxclk_frequency;
|
||||
g->clock_mem = metrics->average_uclk_frequency; // mem controller clock, needs to be 2x on 5700xt for some reason
|
||||
|
||||
// hacks for rx7800xt
|
||||
// g->clock_core = metrics->average_vclk1_frequency; // why not gfxclock?
|
||||
// g->clock_mem = metrics->average_gfxclk_frequency; // why gfxclock? min mem clock seems to be 96mhz, this is probably including time sleeping
|
||||
break;
|
||||
}
|
||||
|
||||
/* ryzen 5 5600g */
|
||||
case 22: {
|
||||
const struct gpu_metrics_v2_2* metrics = (struct gpu_metrics_v2_2*)raw_metrics;
|
||||
g->temp_edge = metrics->temperature_gfx / 100;
|
||||
break;
|
||||
}
|
||||
|
||||
/* werid hardware i probably dont like, maybe fallback to reading from fs? */
|
||||
default: {
|
||||
applog(LOG_WRN, "Unsupported gpu_metrics_v%d_%d", header->format_revision, header->content_revision);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* reads values from system and updates the target gpu_sensors_t struct */
|
||||
void gpu_update(struct gpu_sensors_t *g) {
|
||||
const bool hwmon_valid = g->hwmon[0] != '\0';
|
||||
|
||||
if (hwmon_valid)
|
||||
fill_missing_metrics(g);
|
||||
if (g->has_gpu_metrics)
|
||||
update_from_metrics(g);
|
||||
else if (hwmon_valid)
|
||||
update_from_fs(g);
|
||||
if (g->fan_speed > 9999)
|
||||
g->fan_speed = 9999; // sanity check fan speed
|
||||
}
|
||||
Reference in New Issue
Block a user