Commit 8f18d4c8b0f92da9bd2ae218860d8f49e2e473a7

Kano 2013-06-19T00:52:13

bflsc driver support for v2 firmware

diff --git a/driver-bflsc.c b/driver-bflsc.c
index 3dc3172..4c53ae3 100644
--- a/driver-bflsc.c
+++ b/driver-bflsc.c
@@ -31,12 +31,36 @@
 #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 from the last LP
+ * The next LP will restart all chips approximately together again
+ */
+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 +73,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 +98,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 +129,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 +144,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 +180,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 +335,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 +365,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)) {
+		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 +817,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 +842,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 +960,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 +1376,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 +1385,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 +1423,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 +1689,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 +1744,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 +1753,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 +1836,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 +1852,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