Skip to content

Commit

Permalink
Update fan adjustment
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangfu committed Nov 10, 2014
1 parent 663ff36 commit 8a8f3d5
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 49 deletions.
8 changes: 6 additions & 2 deletions cgminer.c
Expand Up @@ -235,9 +235,10 @@ static char *opt_set_avalon2_fan;
static char *opt_set_avalon2_voltage;
#endif
#ifdef USE_AVALON4
static char *opt_set_avalon4_freq;
static char *opt_set_avalon4_temp;
static char *opt_set_avalon4_fan;
static char *opt_set_avalon4_voltage;
static char *opt_set_avalon4_freq;
#endif
#ifdef USE_BLOCKERUPTER
int opt_bet_clk = 0;
Expand Down Expand Up @@ -1184,7 +1185,10 @@ static struct opt_table opt_config_table[] = {
"Set Avalon4 core voltage, in millivolts, step: 125"),
OPT_WITH_CBARG("--avalon4-fan",
set_avalon4_fan, NULL, &opt_set_avalon4_fan,
"Set Avalon4 target fan speed"),
"Set Avalon4 target fan speed range"),
OPT_WITH_CBARG("--avalon4-temp",
set_avalon4_temp, NULL, &opt_set_avalon4_temp,
"Set Avalon4 target temp range"),
OPT_WITH_ARG("--avalon4-cutoff",
set_int_0_to_100, opt_show_intval, &opt_avalon4_overheat,
"Set Avalon4 overheat cut off temperature"),
Expand Down
95 changes: 70 additions & 25 deletions driver-avalon4.c
Expand Up @@ -21,8 +21,9 @@

#define get_fan_pwm(v) (AVA4_PWM_MAX - (v) * AVA4_PWM_MAX / 100)

static int avalon4_fan_min = get_fan_pwm(AVA4_DEFAULT_FAN_MIN);
static int avalon4_fan_max = get_fan_pwm(AVA4_DEFAULT_FAN_MAX);
int opt_avalon4_temp_min = AVA4_DEFAULT_TEMP_MIN;
int opt_avalon4_temp_max = AVA4_DEFAULT_TEMP_OVERHEAT;

int opt_avalon4_fan_min = AVA4_DEFAULT_FAN_MIN;
int opt_avalon4_fan_max = AVA4_DEFAULT_FAN_MAX;

Expand Down Expand Up @@ -73,6 +74,27 @@ static inline uint8_t rev8(uint8_t d)
return out;
}

char *set_avalon4_temp(char *arg)
{
int val1, val2, ret;

ret = sscanf(arg, "%d-%d", &val1, &val2);
if (ret < 1)
return "No values passed to avalon4-temp";
if (ret == 1)
val2 = val1;

if (val1 < AVA4_DEFAULT_TEMP_MIN || val1 > AVA4_DEFAULT_TEMP_OVERHEAT ||
val2 < AVA4_DEFAULT_TEMP_MIN || val2 > AVA4_DEFAULT_TEMP_OVERHEAT ||
val2 < val1)
return "Invalid value passed to avalon4-temp";

opt_avalon4_temp_min = val1;
opt_avalon4_temp_max = val2;

return NULL;
}

char *set_avalon4_fan(char *arg)
{
int val1, val2, ret;
Expand All @@ -88,8 +110,6 @@ char *set_avalon4_fan(char *arg)

opt_avalon4_fan_min = val1;
opt_avalon4_fan_max = val2;
avalon4_fan_min = get_fan_pwm(val1);
avalon4_fan_max = get_fan_pwm(val2);

return NULL;
}
Expand Down Expand Up @@ -231,19 +251,32 @@ static inline uint32_t decode_voltage(uint32_t v)
return (0x78 - (rev8(v >> 8) >> 1)) * 125;
}

static inline void adjust_fan(struct avalon4_info *info)
static inline uint32_t adjust_fan(struct avalon4_info *info, int id)
{
int t = get_current_temp_max(info);
uint32_t pwm;
int t = info->temp[id];

/* TODO: Add options for temperature range and fan adjust function 40 ~ 50 */
if (t < 40)
info->fan_pct = opt_avalon4_fan_min;
else if (t > 50)
info->fan_pct = opt_avalon4_fan_max;
else
info->fan_pct = (t - 40) * (opt_avalon4_fan_max - opt_avalon4_fan_min) / 10 + opt_avalon4_fan_min;
if (t < opt_avalon4_temp_min)
info->fan_pct[id] = opt_avalon4_fan_min;
else if (t > opt_avalon4_temp_max)
info->fan_pct[id] = opt_avalon4_fan_max;
else {
if (t >= ((opt_avalon4_temp_max + opt_avalon4_temp_min) / 2))
info->fan_pct[id] += 2;
else
info->fan_pct[id] -= 2;
}

if (info->fan_pct[id] < opt_avalon4_fan_min)
info->fan_pct[id] = opt_avalon4_fan_min;
if (info->fan_pct[id] > opt_avalon4_fan_max)
info->fan_pct[id] = opt_avalon4_fan_max;

info->fan_pwm = get_fan_pwm(info->fan_pct);
pwm = get_fan_pwm(info->fan_pct[id]);
applog(LOG_NOTICE, "[%d], Adjust_fan: %dC-%d%%(%03x)", id, t, info->fan_pct[id], pwm);

return pwm;
}

static int decode_pkg(struct thr_info *thr, struct avalon4_ret *ar, int modular_id)
Expand Down Expand Up @@ -435,7 +468,7 @@ static int avalon4_iic_xfer(struct cgpu_info *avalon4,

cgsleep_ms(opt_avalon4_aucxdelay / 4800 + 1);

rlen += 4; /* Add 4 bytes IIC header */
rlen += 4; /* Add 4 bytes IIC header */
err = usb_read(avalon4, (char *)rbuf, rlen, read, C_AVA4_READ);
if (err || *read != rlen) {
applog(LOG_DEBUG, "Avalon4: AUC xfer %d, r(%d-%d)!", err, rlen - 4, *read);
Expand Down Expand Up @@ -756,12 +789,10 @@ static struct cgpu_info *avalon4_auc_detect(struct libusb_device *dev, struct us

info->polling_first = 1;

info->fan_pct = AVA4_DEFAULT_FAN_MIN;
info->fan_pwm = get_fan_pwm(AVA4_DEFAULT_FAN_MIN);
info->temp_max = 0;
for (i = 0; i < AVA4_DEFAULT_MODULARS; i++) {
info->enable[i] = 0;
info->dev_type[i] = AVA4_ID_AVAX;
info->fan_pct[i] = (opt_avalon4_fan_max - opt_avalon4_fan_min) / 2;
}

info->set_voltage = opt_avalon4_voltage_min;
Expand All @@ -780,16 +811,22 @@ static inline void avalon4_detect(bool __maybe_unused hotplug)

static bool avalon4_prepare(struct thr_info *thr)
{
int i;
struct cgpu_info *avalon4 = thr->cgpu;
struct avalon4_info *info = avalon4->device_data;

info->polling_first = 1;

cgtime(&(info->last_fan));

cglock_init(&info->update_lock);
cglock_init(&info->pool0.data_lock);
cglock_init(&info->pool1.data_lock);
cglock_init(&info->pool2.data_lock);

for (i = 0; i < AVA4_DEFAULT_MODULARS; i++)
info->fan_pct[i] = (opt_avalon4_fan_max - opt_avalon4_fan_min) / 2;

return true;
}

Expand Down Expand Up @@ -855,14 +892,15 @@ static int polling(struct thr_info *thr, struct cgpu_info *avalon4, struct avalo
int i, j, tmp, ret, decode_err, do_polling = 0;
struct timeval current_fan;
int do_adjust_fan = 0;
uint32_t fan_pwm;

if (info->polling_first) {
cgsleep_ms(300);
info->polling_first = 0;
}

cgtime(&current_fan);
if (tdiff(&current_fan, &(info->last_fan)) > 10.0) {
if (tdiff(&current_fan, &(info->last_fan)) > 5.0) {
cgtime(&info->last_fan);
do_adjust_fan = 1;
}
Expand All @@ -881,9 +919,9 @@ static int polling(struct thr_info *thr, struct cgpu_info *avalon4, struct avalo

/* Adjust fan every 10 seconds*/
if (do_adjust_fan) {
adjust_fan(info);
info->fan_pwm |= 0x80000000;
tmp = be32toh(info->fan_pwm);
fan_pwm = adjust_fan(info, i);
fan_pwm |= 0x80000000;
tmp = be32toh(fan_pwm);
memcpy(send_pkg.data + 4, &tmp, 4);
}

Expand Down Expand Up @@ -1375,16 +1413,23 @@ static void avalon4_statline_before(char *buf, size_t bufsiz, struct cgpu_info *
int temp = get_current_temp_max(info);
float volts = (float)info->set_voltage / 10000;
int i, count = 0;
int min = AVA4_DEFAULT_FAN_MAX, max = AVA4_DEFAULT_FAN_MIN;

for (i = 1; i < AVA4_DEFAULT_MODULARS; i++) {
if (info->enable[i])
count++;
if (!info->enable[i])
continue;

count++;
if (max <= info->fan_pct[i])
max = info->fan_pct[i];
if (min >= info->fan_pct[i])
min = info->fan_pct[i];
}

tailsprintf(buf, bufsiz, "%2dMMs %.3fV %4dMhz %2dC %3d%%",
tailsprintf(buf, bufsiz, "%2dMMs %.3fV %4dMhz %2dC %3d%%-%3d%%",
count, volts,
(info->set_frequency[0] * 4 + info->set_frequency[1] * 4 + info->set_frequency[2]) / 9,
temp, info->fan_pct);
temp, min, max);
}

struct device_drv avalon4_drv = {
Expand Down
43 changes: 21 additions & 22 deletions driver-avalon4.h
Expand Up @@ -15,25 +15,27 @@

#ifdef USE_AVALON4

#define AVA4_DEFAULT_MODULARS 64
#define AVA4_DEFAULT_ASIC_COUNT 4

#define AVA4_PWM_MAX 0x3FF
#define AVA4_DEFAULT_FAN_MIN 10 /* % */
#define AVA4_DEFAULT_FAN_MAX 100

#define AVA4_DEFAULT_TEMP_MIN 25
#define AVA4_DEFAULT_TEMP_OVERHEAT 65
#define AVA4_DEFAULT_POLLING_DELAY 20 /* ms */

#define AVA4_DEFAULT_VOLTAGE_MIN 4000
#define AVA4_DEFAULT_VOLTAGE_MAX 9000

#define AVA4_DEFAULT_FREQUENCY_MIN 100
#define AVA4_DEFAULT_FREQUENCY_MAX 1000

#define AVA4_DEFAULT_MODULARS 64
#define AVA4_DEFAULT_MINERS 10
#define AVA4_DEFAULT_ASIC_COUNT 4

#define AVA4_DEFAULT_VOLTAGE 6875
#define AVA4_DEFAULT_FREQUENCY 200
#define AVA4_DEFAULT_POLLING_DELAY 20 /* ms */

#define AVA4_PWM_MAX 0x3FF

#define AVA4_AUC_VER_LEN 12 /* Version length: 12 (AUC-YYYYMMDD) */
#define AVA4_AUC_SPEED 400000
Expand Down Expand Up @@ -110,39 +112,37 @@ struct avalon4_info {
cglock_t update_lock;

int polling_first;
uint8_t polling_err_cnt[AVA4_DEFAULT_MODULARS];
int polling_err_cnt[AVA4_DEFAULT_MODULARS];
int xfer_err_cnt;

struct timeval last_fan;
struct timeval last_stratum;
int pool_no;
struct pool pool0;
struct pool pool1;
struct pool pool2;
int pool_no;

struct timeval last_fan;
struct timeval last_stratum;

char auc_version[AVA4_AUC_VER_LEN + 1];
int auc_speed;
int auc_xdelay;
int auc_temp;

int set_voltage;
int set_frequency[3];

char mm_version[AVA4_DEFAULT_MODULARS][AVA4_MM_VER_LEN + 1];
uint8_t mm_dna[AVA4_DEFAULT_MODULARS][AVA4_MM_DNA_LEN + 1];
int dev_type[AVA4_DEFAULT_MODULARS];
bool enable[AVA4_DEFAULT_MODULARS];

int set_frequency[3];
int set_voltage;

char mm_version[AVA4_DEFAULT_MODULARS][AVA4_MM_VER_LEN + 1];
uint8_t mm_dna[AVA4_DEFAULT_MODULARS][AVA4_MM_DNA_LEN + 1];
int get_voltage[AVA4_DEFAULT_MODULARS];
int get_frequency[AVA4_DEFAULT_MODULARS];
int power_good[AVA4_DEFAULT_MODULARS];

int fan_pwm;
int fan_pct;
int temp_max;
int auc_temp;

int fan_pct[AVA4_DEFAULT_MODULARS];
int fan[AVA4_DEFAULT_MODULARS];
int temp[AVA4_DEFAULT_MODULARS];
int led_red[AVA4_DEFAULT_MODULARS];

int local_works[AVA4_DEFAULT_MODULARS];
int hw_works[AVA4_DEFAULT_MODULARS];
Expand All @@ -151,8 +151,6 @@ struct avalon4_info {
int hw_work[AVA4_DEFAULT_MODULARS];
int matching_work[AVA4_DEFAULT_MINERS][AVA4_DEFAULT_MODULARS];
int chipmatching_work[AVA4_DEFAULT_MINERS][AVA4_DEFAULT_MODULARS][4];

int led_red[AVA4_DEFAULT_MODULARS];
};

struct avalon4_iic_info {
Expand All @@ -170,6 +168,7 @@ struct avalon4_iic_info {
#define AVA4_SEND_ERROR -1

extern char *set_avalon4_fan(char *arg);
extern char *set_avalon4_temp(char *arg);
extern char *set_avalon4_freq(char *arg);
extern char *set_avalon4_voltage(char *arg);
extern int opt_avalon4_overheat;
Expand Down

0 comments on commit 8a8f3d5

Please sign in to comment.