Add a simple PID-like controller to bi*fury devices to dynamically alter the clock setting to maintain a nominal target temperature set to 82 degrees.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
diff --git a/driver-bitfury.c b/driver-bitfury.c
index 77c7069..9806048 100644
--- a/driver-bitfury.c
+++ b/driver-bitfury.c
@@ -369,6 +369,16 @@ static void parse_bxf_submit(struct cgpu_info *bitfury, struct bitfury_info *inf
free_work(work);
}
+static bool bxf_send_clock(struct cgpu_info *bitfury, struct bitfury_info *info,
+ uint8_t clockspeed)
+{
+ char buf[64];
+
+ info->clocks = clockspeed;
+ sprintf(buf, "clock %d %d\n", clockspeed, clockspeed);
+ return bxf_send_msg(bitfury, buf, C_BXF_CLOCK);
+}
+
static void parse_bxf_temp(struct cgpu_info *bitfury, struct bitfury_info *info, char *buf)
{
int decitemp;
@@ -387,6 +397,52 @@ static void parse_bxf_temp(struct cgpu_info *bitfury, struct bitfury_info *info,
bitfury->device_id, decitemp);
}
mutex_unlock(&info->lock);
+
+ if (decitemp > BXF_TEMP_TARGET + BXF_TEMP_HYSTERESIS) {
+ if (info->clocks <= BXF_CLOCK_MIN)
+ goto out;
+ applog(LOG_WARNING, "%s %d: Hit overheat temperature of %d, throttling!",
+ bitfury->drv->name, bitfury->device_id, decitemp);
+ bxf_send_clock(bitfury, info, BXF_CLOCK_MIN);
+ goto out;
+ }
+ if (decitemp > BXF_TEMP_TARGET) {
+ if (info->clocks <= BXF_CLOCK_MIN)
+ goto out;
+ if (decitemp < info->last_decitemp)
+ goto out;
+ applog(LOG_INFO, "%s %d: Temp %d over target and not falling, decreasing clock",
+ bitfury->drv->name, bitfury->device_id, decitemp);
+ bxf_send_clock(bitfury, info, info->clocks - 1);
+ goto out;
+ }
+ if (decitemp <= BXF_TEMP_TARGET && decitemp >= BXF_TEMP_TARGET - BXF_TEMP_HYSTERESIS) {
+ if (decitemp == info->last_decitemp)
+ goto out;
+ if (decitemp > info->last_decitemp) {
+ if (info->clocks <= BXF_CLOCK_MIN)
+ goto out;
+ applog(LOG_DEBUG, "%s %d: Temp %d in target and rising, decreasing clock",
+ bitfury->drv->name, bitfury->device_id, decitemp);
+ bxf_send_clock(bitfury, info, info->clocks - 1);
+ goto out;
+ }
+ /* implies: decitemp < info->last_decitemp */
+ if (info->clocks >= BXF_CLOCK_DEFAULT)
+ goto out;
+ applog(LOG_DEBUG, "%s %d: Temp %d in target and falling, increasing clock",
+ bitfury->drv->name, bitfury->device_id, decitemp);
+ bxf_send_clock(bitfury, info, info->clocks + 1);
+ goto out;
+ }
+ /* implies: decitemp < BXF_TEMP_TARGET - BXF_TEMP_HYSTERESIS */
+ if (info->clocks >= BXF_CLOCK_DEFAULT)
+ goto out;
+ applog(LOG_DEBUG, "%s %d: Temp %d below target, increasing clock",
+ bitfury->drv->name, bitfury->device_id, decitemp);
+ bxf_send_clock(bitfury, info, info->clocks + 1);
+out:
+ info->last_decitemp = decitemp;
}
static void bxf_update_work(struct cgpu_info *bitfury, struct bitfury_info *info);
@@ -497,14 +553,10 @@ out:
static bool bxf_prepare(struct cgpu_info *bitfury, struct bitfury_info *info)
{
- char buf[64];
-
mutex_init(&info->lock);
if (pthread_create(&info->read_thr, NULL, bxf_get_results, (void *)bitfury))
quit(1, "Failed to create bxf read_thr");
- info->clocks = BXF_DEFAULT_CLOCK;
- sprintf(buf, "clock %d %d\n", info->clocks, info->clocks);
- return bxf_send_msg(bitfury, buf, C_BXF_CLOCK);
+ return bxf_send_clock(bitfury, info, BXF_CLOCK_DEFAULT);
}
static bool bitfury_prepare(struct thr_info *thr)
@@ -831,6 +883,7 @@ static struct api_data *bxf_api_stats(struct bitfury_info *info)
root = api_add_int(root, "NoMatchingWork", &info->no_matching_work, false);
root = api_add_double(root, "Temperature", &info->temperature, false);
root = api_add_int(root, "Max DeciTemp", &info->max_decitemp, false);
+ root = api_add_uint8(root, "Clock", &info->clocks, false);
root = api_add_int(root, "Core0 hwerror", &info->filtered_hw[0], false);
root = api_add_int(root, "Core1 hwerror", &info->filtered_hw[1], false);
root = api_add_int(root, "Core0 jobs", &info->job[0], false);
diff --git a/driver-bitfury.h b/driver-bitfury.h
index 9fa7436..9ebf575 100644
--- a/driver-bitfury.h
+++ b/driver-bitfury.h
@@ -13,9 +13,14 @@
#include "miner.h"
#include "usbutils.h"
-#define BXF_DEFAULT_CLOCK 54
-#define BXF_MIN_CLOCK 0
-#define BXF_MAX_CLOCK 63
+#define BXF_CLOCK_DEFAULT 54
+#define BXF_CLOCK_OFF 0
+#define BXF_CLOCK_MIN 32
+#define BXF_CLOCK_MAX 63 // Not really used since we only get hw errors above default
+
+/* In tenths of a degree */
+#define BXF_TEMP_TARGET 820
+#define BXF_TEMP_HYSTERESIS 30
struct bitfury_info {
struct cgpu_info *base_cgpu;
@@ -37,6 +42,7 @@ struct bitfury_info {
pthread_mutex_t lock;
pthread_t read_thr;
double temperature;
+ int last_decitemp;
int max_decitemp;
int work_id; // Current work->subid
int no_matching_work;