#include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipmi.h" #include "lm.h" static constexpr size_t IPMI_RAW_MAX_ARGS = 65536*2; sig_atomic_t running = true; void sig_handler(int sig) { (void)sig; running = false; } std::vector gather_sensors(std::vector& ipmi_sensors, ipmi_monitoring_ctx_t ctx, std::vector& lm_chips) { std::vector out; struct ipmi_monitoring_ipmi_config ipmi_config = {}; ipmi_config.driver_type = IPMI_MONITORING_DRIVER_TYPE_OPENIPMI; bool grabids = false; for(Sensor& sensor : ipmi_sensors) { if(sensor.id <= 0) { grabids = true; break; } } if(grabids) { if(!ipmi_fill_sensor_ids(ipmi_sensors, ctx, &ipmi_config)) { std::cout<<"could not get ids for all the required sensors\n"; return out; } } else { ipmi_update_sensors(ipmi_sensors, ctx, &ipmi_config); } out.insert(out.end(), ipmi_sensors.begin(), ipmi_sensors.end()); std::vector lm_sensors = lm_get_temperatures(lm_chips); out.insert(out.end(), lm_sensors.begin(), lm_sensors.end()); return out; } double fan_curve(double temperature, double min_fan, double max_fan, double low_temperature, double high_temperature) { double slope = (max_fan-min_fan)/(high_temperature-low_temperature); return std::max(std::min(max_fan, min_fan+slope*(temperature-low_temperature)), min_fan); } double gpu_fan_zone(const std::vector& sensors) { const char mi50Chip[] = "amdgpu-pci-2300"; const char mi25Chip[] = "amdgpu-pci-4300"; const char monitored_sensor_name[] = "edge"; double max_temp = std::numeric_limits::min(); for(const Sensor& sensor : sensors) { if((sensor.chip == mi50Chip || sensor.chip == mi25Chip) && sensor.name == monitored_sensor_name) { if(max_temp < sensor.reading) max_temp = sensor.reading; } } return fan_curve(max_temp, 0.2, 1.0, 40, 75); } double system_fan_zone(const std::vector& sensors) { Sensor cpu("IPMI", "CPU Temp"); Sensor system("IPMI", "System Temp"); std::vector out; for(const Sensor& sensor : sensors) { if(cpu == sensor) cpu = sensor; else if(sensor == system) system = sensor; } double fanSystem = fan_curve(system.reading, 0.2, 1.0, 35, 45); double fanCpu = fan_curve(cpu.reading, 0.2, 1.0, 40, 70); return std::max(fanSystem, fanCpu); } std::vector get_fan_zones(const std::vector& sensors) { std::vector out; out.push_back(system_fan_zone(sensors)); out.push_back(gpu_fan_zone(sensors)); return out; } ipmi_ctx_t ipmi_open() { ipmi_ctx_t ctx = nullptr; ipmi_driver_type_t driver = IPMI_DEVICE_OPENIPMI; int ret = ipmi_ctx_find_inband(ctx, &driver, false, 0, 0, nullptr, 0, 0); if(ret < 0) { std::cerr<<"Could not create raw context "<(64), static_cast(speed*64)), static_cast(0)); char command[] = {0x70, 0x66, 0x01, static_cast(group), converted_speed}; char bytesrx[IPMI_RAW_MAX_ARGS] = {0}; int rxlen = ipmi_cmd_raw(raw_ctx, 0, 0x30, command, sizeof(command), bytesrx, IPMI_RAW_MAX_ARGS); if(rxlen < 0) { std::cerr<<"Raw write to ipmi failed with: "< lm_chips = lm_get_chips("amdgpu-*"); std::vector ipmi_sensors; ipmi_sensors.push_back(Sensor("IPMI", "CPU Temp")); ipmi_sensors.push_back(Sensor("IPMI", "System Temp")); ipmi_monitoring_ctx_t monitoring_ctx = init_ipmi_monitoring(); if(!monitoring_ctx) return 1; ipmi_ctx_t raw_ctx = ipmi_open(); if(!raw_ctx) return 1; while(running) { std::vector sensors = gather_sensors(ipmi_sensors, monitoring_ctx, lm_chips); std::vector fanzones = get_fan_zones(sensors); for(const double fanzone : fanzones) std::cout<