Reduced number of syscalls

This commit is contained in:
2025-02-01 08:04:41 -08:00
parent afdddabc0c
commit 34bbcf7883
5 changed files with 82 additions and 99 deletions
+50 -78
View File
@@ -9,32 +9,42 @@
#include "icx3.h"
/* Check an I2C device file for an ICX3 controller, returns the product id, or ICX3_PRODUCT_NONE on bad read. */
enum icx3_product_id check_for_icx3(char *i2c_dev_path)
int icx3_init(struct card_info *card)
{
char data[I2C_SMBUS_BLOCK_MAX] = {};
int fd, read_result;
int read_result;
struct icx3_info *temp_info;
fd = open_i2c_dev(i2c_dev_path);
int fd = open(card->i2c_dev_path, O_RDONLY);
if (fd == -1)
return ICX3_PRODUCT_NONE;
return -1;
if (ioctl(fd, I2C_SLAVE, ICX3_I2C_ADDR) < 0) {
close(fd);
return -1;
}
read_result = i2c_smbus_read_i2c_block_data(fd, ICX3_REG_READINFORMATION, ICX3_READINFORMATION_SIZE, data);
close(fd);
if (read_result == ICX3_READINFORMATION_SIZE) {
temp_info = (struct icx3_info*)&data;
if (temp_info->slave_address == ICX3_I2C_ADDR)
return temp_info->product_id;
if (temp_info->slave_address == ICX3_I2C_ADDR) {
card->product_id = temp_info->product_id;
card->i2c_fd = fd;
return fd;
} else {
close(fd);
return -1;
}
}
return ICX3_PRODUCT_NONE;
return -1;
}
void print_icx3_fans(char *i2c_dev_path)
void print_icx3_fans(struct card_info *card)
{
struct icx3_fan_control fans[ICX3_MAX_FANS];
get_fan_status(fans, i2c_dev_path);
get_fan_status(fans, card);
for (int i=0; i < ICX3_MAX_FANS; i++) {
printf("%s: %d RPM (%d/%d%%, %s)\n",
@@ -47,10 +57,10 @@ void print_icx3_fans(char *i2c_dev_path)
}
}
void print_icx3_fans_oneline(char *i2c_dev_path)
void print_icx3_fans_oneline(struct card_info *card)
{
struct icx3_fan_control fans[ICX3_MAX_FANS];
get_fan_status(fans, i2c_dev_path);
get_fan_status(fans, card);
printf("FAN");
for (int i=0; i < ICX3_MAX_FANS; i++) {
@@ -59,11 +69,11 @@ void print_icx3_fans_oneline(char *i2c_dev_path)
printf("%%");
}
void print_icx3_temps(char *i2c_dev_path)
void print_icx3_temps(struct card_info *card)
{
float temps[ICX3_NUM_TEMP_SENSORS];
get_temp_sensors(temps, i2c_dev_path);
get_temp_sensors(temps, card);
for (int i=0; i<ICX3_NUM_TEMP_SENSORS; i++) {
printf("%s: %+.1f°C\n",
@@ -72,11 +82,11 @@ void print_icx3_temps(char *i2c_dev_path)
}
}
void print_icx3_temps_oneline(char *i2c_dev_path)
void print_icx3_temps_oneline(struct card_info *card)
{
float temps[ICX3_NUM_TEMP_SENSORS];
get_temp_sensors(temps, i2c_dev_path);
get_temp_sensors(temps, card);
for (int i=0; i<ICX3_NUM_TEMP_SENSORS; i++) {
if (i == 0 || strncmp(icx3_temp_sensor_names[i], icx3_temp_sensor_names[i-1], 3))
@@ -86,9 +96,9 @@ void print_icx3_temps_oneline(char *i2c_dev_path)
printf("°C");
}
void get_available_fans(char *i2c_dev_path, char *fans_avail)
void get_available_fans(char *fans_avail, struct card_info *card)
{
int product_id = check_for_icx3(i2c_dev_path);
int product_id = card->product_id;
/* From ICX3TotalFanCtrl.cs */
switch(product_id) {
@@ -142,47 +152,34 @@ void get_available_fans(char *i2c_dev_path, char *fans_avail)
}
}
void get_fan_status(struct icx3_fan_control *fans, char *i2c_dev_path)
void get_fan_status(struct icx3_fan_control *fans, struct card_info *card)
{
char data[I2C_SMBUS_BLOCK_MAX] = {};
int fd, read_result;
int read_result;
/* First thing is to check for the product ID to figure out how many fans we have */
char fans_avail[ICX3_MAX_FANS] = {0};
get_available_fans(i2c_dev_path, fans_avail);
fd = open_i2c_dev(i2c_dev_path);
if (fd == -1)
return;
get_available_fans(fans_avail, card);
for (int i=0; i < ICX3_MAX_FANS; i++) {
if (!fans_avail[i]) {
continue;
}
read_result = i2c_smbus_read_i2c_block_data(fd, ICX3_REG_FANCONTROL + i, ICX3_FANCONTROL_SIZE, data);
read_result = i2c_smbus_read_i2c_block_data(card->i2c_fd, ICX3_REG_FANCONTROL + i, ICX3_FANCONTROL_SIZE, data);
if (read_result != ICX3_FANCONTROL_SIZE) {
close(fd);
return;
}
memcpy(&fans[i], &data, sizeof(struct icx3_fan_control));
}
close(fd);
}
void get_temp_sensors(float *temps, char *i2c_dev_path)
void get_temp_sensors(float *temps, struct card_info *card)
{
char data[I2C_SMBUS_BLOCK_MAX] = {};
int fd, read_result;
int read_result;
struct icx3_temp_sensors *temp_sensors;
fd = open_i2c_dev(i2c_dev_path);
if (fd == -1)
return;
read_result = i2c_smbus_read_i2c_block_data(fd, ICX3_REG_TEMPSENSOR, ICX3_TEMPSENSOR_SIZE, data);
close(fd);
read_result = i2c_smbus_read_i2c_block_data(card->i2c_fd, ICX3_REG_TEMPSENSOR, ICX3_TEMPSENSOR_SIZE, data);
if (read_result != ICX3_TEMPSENSOR_SIZE)
return;
temp_sensors = (struct icx3_temp_sensors*) &data;
@@ -198,54 +195,34 @@ void get_temp_sensors(float *temps, char *i2c_dev_path)
}
}
int open_i2c_dev(char *i2c_dev_path)
{
int fd = open(i2c_dev_path, O_RDONLY);
/* Error silently here because we should have already checked we can read the i2c in check_for_icx3() */
if (fd == -1)
return -1;
if (ioctl(fd, I2C_SLAVE, ICX3_I2C_ADDR) < 0) {
close(fd);
return -1;
}
return fd;
}
void enable_write(int enable, char *i2c_dev_path)
{
int fd = open_i2c_dev(i2c_dev_path);
if (fd == -1)
return;
void enable_write(int enable, struct card_info *card)
{
unsigned char *data;
if (enable)
data = icx3_write_enable;
else
data = icx3_write_disable;
/* Enable or disable write */
i2c_smbus_write_i2c_block_data(fd, ICX3_REG_ENABLEWRITE, ICX3_ENABLEWRITE_SIZE, data);
i2c_smbus_write_i2c_block_data(card->i2c_fd, ICX3_REG_ENABLEWRITE, ICX3_ENABLEWRITE_SIZE, data);
/* Read back the result to verify */
unsigned char read_result[ICX3_ENABLEWRITE_SIZE];
int write_ok = 0;
i2c_smbus_read_i2c_block_data(fd, ICX3_REG_ENABLEWRITE, ICX3_ENABLEWRITE_SIZE, read_result);
i2c_smbus_read_i2c_block_data(card->i2c_fd, ICX3_REG_ENABLEWRITE, ICX3_ENABLEWRITE_SIZE, read_result);
if (enable)
write_ok = (read_result[1] == 0xFC);
else
write_ok = (read_result[1] == 0xFE);
if (!write_ok)
printf("Unable to enable/disable write on %s\n", i2c_dev_path);
printf("Unable to enable/disable write on %s\n", card->i2c_dev_path);
}
/* Sets a given fan on the GPU according to a string setting
'auto' resets the fan to default (fans 1-2 go to GPU control, 3-4 to +0 RPM offset from GPU control)
A number without a sign (e.g. 50) manually sets the fan to a given % duty cycle
A number with a sign (e.g. +500) sets the fan to run at an RPM offset from GPU control */
void set_fan(int fan, char *setting, char *i2c_dev_path)
void set_fan(int fan, char *setting, struct card_info *card)
{
char fans_avail[ICX3_MAX_FANS] = {0};
@@ -256,15 +233,11 @@ void set_fan(int fan, char *setting, char *i2c_dev_path)
int write_result;
/* Check to make sure we're setting a valid fan */
get_available_fans(i2c_dev_path, fans_avail);
get_available_fans(fans_avail, card);
if (fans_avail[fan] == 0) {
printf("Fan %d does not exist on this card \n", fan);
return;
}
int fp = open_i2c_dev(i2c_dev_path);
if (fp == -1)
return;
fan_control.length = ICX3_FANCONTROL_SIZE - 1;
if (strcmp(setting, "auto") == 0) {
@@ -283,16 +256,15 @@ void set_fan(int fan, char *setting, char *i2c_dev_path)
fan_control.duty = atoi(setting);
}
enable_write(1, i2c_dev_path);
enable_write(1, card);
i2c_smbus_write_i2c_block_data(fp, reg, ICX3_FANCONTROL_SIZE, (char *)&fan_control);
i2c_smbus_write_i2c_block_data(card->i2c_fd, reg, ICX3_FANCONTROL_SIZE, (char *)&fan_control);
/* Read back data and verify we set the fan properly */
i2c_smbus_read_i2c_block_data(fp, reg, ICX3_FANCONTROL_SIZE, (char *)&fan_readback);
i2c_smbus_read_i2c_block_data(card->i2c_fd, reg, ICX3_FANCONTROL_SIZE, (char *)&fan_readback);
if (fan_readback.fanmode != fan_control.fanmode ||
fan_readback.rpm_offset != fan_control.rpm_offset ||
fan_readback.duty != fan_control.duty)
printf("Error setting fan %d on %s\n", fan, i2c_dev_path);
close(fp);
printf("Error setting fan %d on %s\n", fan, card->i2c_fd);
}