Merge pull request #452 from kanoi/master bflsc driver support for v2 firmware
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
diff --git a/driver-bflsc.c b/driver-bflsc.c
index 3dc3172..767d367 100644
--- a/driver-bflsc.c
+++ b/driver-bflsc.c
@@ -31,12 +31,35 @@
#define LFSTR "<LF>"
/*
+ * Firmware
+ * DRV_V2 expects (beyond V1) the GetInfo to return the chip count
+ * The queues are 40 instead of 20 and are *usually* consumed and filled
+ * in bursts due to e.g. a 16 chip device doing 16 items at a time and
+ * returning 16 results at a time
+ * If the device has varying chip speeds, it will gradually break up the
+ * burst of results as we progress
+ */
+enum driver_version {
+ BFLSC_DRVUNDEF = 0,
+ BFLSC_DRV1,
+ BFLSC_DRV2
+};
+
+/*
* With Firmware 1.0.0 and a result queue of 20 the Max is:
* inprocess = 12
* max count = 9
* 64+1+24+1+1+(1+8)*8+1 per line = 164 * 20
* OK = 3
* Total: 3304
+ *
+ * With Firmware 1.2.* and a result queue of 40 but a limit of 15 replies:
+ * inprocess = 12
+ * max count = 9
+ * 64+1+24+1+1+1+1+(1+8)*8+1 per line = 166 * 15
+ * OK = 3
+ * Total: 2514
+ *
*/
#define BFLSC_BUFSIZ (0x1000)
@@ -49,6 +72,7 @@
#define BFLSC_DI_XLINKPRESENT "XLINK PRESENT"
#define BFLSC_DI_DEVICESINCHAIN "DEVICES IN CHAIN"
#define BFLSC_DI_CHAINPRESENCE "CHAIN PRESENCE MASK"
+#define BFLSC_DI_CHIPS "CHIP PARALLELIZATION"
#define FULLNONCE 0x100000000ULL
@@ -73,6 +97,7 @@ struct bflsc_dev {
int engines; // each engine represents a 'thread' in a chip
char *xlink_mode;
char *xlink_present;
+ char *chips;
// Status
bool dead; // TODO: handle seperate x-link devices failing?
@@ -103,6 +128,7 @@ struct bflsc_dev {
};
struct bflsc_info {
+ enum driver_version driver_version;
pthread_rwlock_t stat_lock;
struct thr_info results_thr;
uint64_t hashes_sent;
@@ -117,6 +143,12 @@ struct bflsc_info {
bool flash_led;
bool not_first_work; // allow ignoring the first nonce error
bool fanauto;
+ int que_size;
+ int que_full_enough;
+ int que_watermark;
+ int que_noncecount;
+ int que_fld_min;
+ int que_fld_max;
};
#define BFLSC_XLINKHDR '@'
@@ -147,9 +179,15 @@ struct QueueJobStructure {
#define QUE_RES_LINES_MIN 3
#define QUE_MIDSTATE 0
#define QUE_BLOCKDATA 1
-#define QUE_NONCECOUNT 2
-#define QUE_FLD_MIN 3
-#define QUE_FLD_MAX 11
+
+#define QUE_NONCECOUNT_V1 2
+#define QUE_FLD_MIN_V1 3
+#define QUE_FLD_MAX_V1 11
+
+#define QUE_CHIP_V2 2
+#define QUE_NONCECOUNT_V2 3
+#define QUE_FLD_MIN_V2 4
+#define QUE_FLD_MAX_V2 12
#define BFLSC_SIGNATURE 0xc1
#define BFLSC_EOW 0xfe
@@ -296,12 +334,20 @@ struct SaveString {
#define BAJ_LATENCY LATENCY_STD
#define BAL_LATENCY LATENCY_STD
#define BAS_LATENCY LATENCY_STD
+// For now a BAM doesn't really exist - it's currently 8 independent BASs
#define BAM_LATENCY 2
#define BFLSC_TEMP_SLEEPMS 5
-#define BFLSC_QUE_SIZE 20
-#define BFLSC_QUE_FULL_ENOUGH 13
-#define BFLSC_QUE_WATERMARK 6
+
+#define BFLSC_QUE_SIZE_V1 20
+#define BFLSC_QUE_FULL_ENOUGH_V1 13
+#define BFLSC_QUE_WATERMARK_V1 6
+
+// TODO: use 5 batch jobs
+// TODO: base these numbers on the chip count?
+#define BFLSC_QUE_SIZE_V2 40
+#define BFLSC_QUE_FULL_ENOUGH_V2 35
+#define BFLSC_QUE_WATERMARK_V2 20
// Must drop this far below cutoff before resuming work
#define BFLSC_TEMP_RECOVER 5
@@ -318,6 +364,29 @@ static const char *blank = "";
struct device_drv bflsc_drv;
+static enum driver_version drv_ver(struct cgpu_info *bflsc, const char *ver)
+{
+ char *tmp;
+
+ if (strcmp(ver, "1.0.0") == 0)
+ return BFLSC_DRV1;
+
+ if (strncmp(ver, "1.0", 3) == 0 || strncmp(ver, "1.1", 3) == 0) {
+ applog(LOG_WARNING, "%s detect (%s) Warning assuming firmware '%s' is Ver1",
+ bflsc->drv->dname, bflsc->device_path, ver);
+ return BFLSC_DRV1;
+ }
+
+ if (strncmp(ver, "1.2", 3) == 0)
+ return BFLSC_DRV2;
+
+ tmp = str_text((char *)ver);
+ applog(LOG_WARNING, "%s detect (%s) Warning unknown firmware '%s' using Ver2",
+ bflsc->drv->dname, bflsc->device_path, tmp);
+ free(tmp);
+ return BFLSC_DRV2;
+}
+
static void xlinkstr(char *xlink, int dev, struct bflsc_info *sc_info)
{
if (dev > 0)
@@ -747,12 +816,7 @@ static bool getinfo(struct cgpu_info *bflsc, int dev)
}
if (strcmp(firstname, BFLSC_DI_FIRMWARE) == 0) {
sc_dev.firmware = strdup(fields[0]);
- if (strcmp(sc_dev.firmware, "1.0.0")) {
- tmp = str_text(items[i]);
- applog(LOG_WARNING, "%s detect (%s) Warning unknown firmware '%s'",
- bflsc->drv->dname, bflsc->device_path, tmp);
- free(tmp);
- }
+ sc_info->driver_version = drv_ver(bflsc, sc_dev.firmware);
}
else if (strcmp(firstname, BFLSC_DI_ENGINES) == 0) {
sc_dev.engines = atoi(fields[0]);
@@ -777,10 +841,18 @@ static bool getinfo(struct cgpu_info *bflsc, int dev)
free(tmp);
goto mata;
}
+ else if (strcmp(firstname, BFLSC_DI_CHIPS) == 0)
+ sc_dev.chips = strdup(fields[0]);
}
freebreakdown(&count, &firstname, &fields);
}
+ if (sc_info->driver_version == BFLSC_DRVUNDEF) {
+ applog(LOG_WARNING, "%s detect (%s) missing %s",
+ bflsc->drv->dname, bflsc->device_path, BFLSC_DI_FIRMWARE);
+ goto ne;
+ }
+
sc_info->sc_devs = calloc(sc_info->sc_count, sizeof(struct bflsc_dev));
if (unlikely(!sc_info->sc_devs))
quit(1, "Failed to calloc in getinfo");
@@ -887,6 +959,29 @@ reinit:
if (!getinfo(bflsc, 0))
goto unshin;
+ switch (sc_info->driver_version) {
+ case BFLSC_DRV1:
+ sc_info->que_size = BFLSC_QUE_SIZE_V1;
+ sc_info->que_full_enough = BFLSC_QUE_FULL_ENOUGH_V1;
+ sc_info->que_watermark = BFLSC_QUE_WATERMARK_V1;
+ sc_info->que_noncecount = QUE_NONCECOUNT_V1;
+ sc_info->que_fld_min = QUE_FLD_MIN_V1;
+ sc_info->que_fld_max = QUE_FLD_MAX_V1;
+ break;
+ case BFLSC_DRV2:
+ case BFLSC_DRVUNDEF:
+ default:
+ sc_info->driver_version = BFLSC_DRV2;
+
+ sc_info->que_size = BFLSC_QUE_SIZE_V2;
+ sc_info->que_full_enough = BFLSC_QUE_FULL_ENOUGH_V2;
+ sc_info->que_watermark = BFLSC_QUE_WATERMARK_V2;
+ sc_info->que_noncecount = QUE_NONCECOUNT_V2;
+ sc_info->que_fld_min = QUE_FLD_MIN_V2;
+ sc_info->que_fld_max = QUE_FLD_MAX_V2;
+ break;
+ }
+
sc_info->scan_sleep_time = BAS_SCAN_TIME;
sc_info->results_sleep_time = BAS_RES_TIME;
sc_info->default_ms_work = BAS_WORK_TIME;
@@ -1280,7 +1375,7 @@ static void process_nonces(struct cgpu_info *bflsc, int dev, char *xlink, char *
bool res;
char *tmp;
- if (count < QUE_FLD_MIN) {
+ if (count < sc_info->que_fld_min) {
tmp = str_text(data);
applog(LOG_ERR, "%s%i:%s work returned too small (%d,%s)",
bflsc->drv->name, bflsc->device_id, xlink, count, tmp);
@@ -1289,18 +1384,18 @@ static void process_nonces(struct cgpu_info *bflsc, int dev, char *xlink, char *
return;
}
- if (count > QUE_FLD_MAX) {
+ if (count > sc_info->que_fld_max) {
applog(LOG_ERR, "%s%i:%s work returned too large (%d) processing %d anyway",
- bflsc->drv->name, bflsc->device_id, xlink, count, QUE_FLD_MAX);
- count = QUE_FLD_MAX;
+ bflsc->drv->name, bflsc->device_id, xlink, count, sc_info->que_fld_max);
+ count = sc_info->que_fld_max;
inc_hw_errors(bflsc->thr[0]);
}
- num = atoi(fields[QUE_NONCECOUNT]);
- if (num != count - QUE_FLD_MIN) {
+ num = atoi(fields[sc_info->que_noncecount]);
+ if (num != count - sc_info->que_fld_min) {
tmp = str_text(data);
applog(LOG_ERR, "%s%i:%s incorrect data count (%d) will use %d instead from (%s)",
- bflsc->drv->name, bflsc->device_id, xlink, num, count - QUE_FLD_MAX, tmp);
+ bflsc->drv->name, bflsc->device_id, xlink, num, count - sc_info->que_fld_max, tmp);
free(tmp);
inc_hw_errors(bflsc->thr[0]);
}
@@ -1327,7 +1422,7 @@ static void process_nonces(struct cgpu_info *bflsc, int dev, char *xlink, char *
}
res = false;
- for (i = QUE_FLD_MIN; i < count; i++) {
+ for (i = sc_info->que_fld_min; i < count; i++) {
if (strlen(fields[i]) != 8) {
tmp = str_text(data);
applog(LOG_ERR, "%s%i:%s invalid nonce (%s) will try to process anyway",
@@ -1593,7 +1688,7 @@ re_send:
}
if (!getokerr(bflsc, C_QUEJOBSTATUS, &err, &amount, buf, sizeof(buf))) {
- // TODO: check for QUEUE FULL and set work_queued to BFLSC_QUE_SIZE
+ // TODO: check for QUEUE FULL and set work_queued to sc_info->que_size
// and report a code bug LOG_ERR - coz it should never happen
// Try twice
@@ -1648,7 +1743,7 @@ static bool bflsc_queue_full(struct cgpu_info *bflsc)
}
if (dev == -1) {
- que = BFLSC_QUE_SIZE * 10; // 10x is certainly above the MAX it could be
+ que = sc_info->que_size * 10; // 10x is certainly above the MAX it could be
// The first device with the smallest amount queued
for (i = 0; i < sc_info->sc_count; i++) {
if (i != tried && sc_info->sc_devs[i].work_queued < que &&
@@ -1657,7 +1752,7 @@ static bool bflsc_queue_full(struct cgpu_info *bflsc)
que = sc_info->sc_devs[i].work_queued;
}
}
- if (que > BFLSC_QUE_FULL_ENOUGH)
+ if (que > sc_info->que_full_enough)
dev = -1;
}
rd_unlock(&(sc_info->stat_lock));
@@ -1740,10 +1835,10 @@ static int64_t bflsc_scanwork(struct thr_info *thr)
waited = restart_wait(sc_info->scan_sleep_time);
if (waited == ETIMEDOUT) {
unsigned int old_sleep_time, new_sleep_time = 0;
- int min_queued = BFLSC_QUE_SIZE;
+ int min_queued = sc_info->que_size;
/* Only adjust the scan_sleep_time if we did not receive a
* restart message while waiting. Try to adjust sleep time
- * so we drop to BFLSC_QUE_WATERMARK before getting more work.
+ * so we drop to sc_info->que_watermark before getting more work.
*/
rd_lock(&sc_info->stat_lock);
@@ -1756,9 +1851,9 @@ static int64_t bflsc_scanwork(struct thr_info *thr)
new_sleep_time = old_sleep_time;
/* Increase slowly but decrease quickly */
- if (min_queued > BFLSC_QUE_WATERMARK && old_sleep_time < BFLSC_MAX_SLEEP)
+ if (min_queued > sc_info->que_watermark && old_sleep_time < BFLSC_MAX_SLEEP)
new_sleep_time = old_sleep_time * 21 / 20;
- else if (min_queued < BFLSC_QUE_WATERMARK)
+ else if (min_queued < sc_info->que_watermark)
new_sleep_time = old_sleep_time * 2 / 3;
/* Do not sleep more than BFLSC_MAX_SLEEP so we can always
@@ -1870,6 +1965,7 @@ static struct api_data *bflsc_api_stats(struct cgpu_info *bflsc)
{
struct bflsc_info *sc_info = (struct bflsc_info *)(bflsc->device_data);
struct api_data *root = NULL;
+ int i;
//if no x-link ... etc
rd_lock(&(sc_info->stat_lock));
@@ -1882,7 +1978,24 @@ static struct api_data *bflsc_api_stats(struct cgpu_info *bflsc)
root = api_add_temp(root, "Temp2 Max", &(sc_info->sc_devs[0].temp2_max), true);
root = api_add_time(root, "Temp1 Max Time", &(sc_info->sc_devs[0].temp1_max_time), true);
root = api_add_time(root, "Temp2 Max Time", &(sc_info->sc_devs[0].temp2_max_time), true);
+ root = api_add_int(root, "Work Queued", &(sc_info->sc_devs[0].work_queued), true);
+ root = api_add_int(root, "Work Complete", &(sc_info->sc_devs[0].work_complete), true);
+ root = api_add_bool(root, "Overheat", &(sc_info->sc_devs[0].overheat), true);
+ root = api_add_uint64(root, "Flush ID", &(sc_info->sc_devs[0].flush_id), true);
+ root = api_add_uint64(root, "Result ID", &(sc_info->sc_devs[0].result_id), true);
+ root = api_add_bool(root, "Flushed", &(sc_info->sc_devs[0].flushed), true);
+ root = api_add_uint(root, "Scan Sleep", &(sc_info->scan_sleep_time), true);
+ root = api_add_uint(root, "Results Sleep", &(sc_info->results_sleep_time), true);
+ root = api_add_uint(root, "Work ms", &(sc_info->default_ms_work), true);
rd_unlock(&(sc_info->stat_lock));
+
+ i = (int)(sc_info->driver_version);
+ root = api_add_int(root, "Driver", &i, true);
+ root = api_add_string(root, "Firmware", sc_info->sc_devs[0].firmware, false);
+ root = api_add_string(root, "Chips", sc_info->sc_devs[0].chips, false);
+ root = api_add_int(root, "Que Size", &(sc_info->que_size), false);
+ root = api_add_int(root, "Que Full", &(sc_info->que_full_enough), false);
+ root = api_add_int(root, "Que Watermark", &(sc_info->que_watermark), false);
root = api_add_escape(root, "GetInfo", sc_info->sc_devs[0].getinfo, false);
/*