Browse Source

titan: Change 'scanhash' minerloop to 'queue'

Vitalii Demianets 11 years ago
parent
commit
627352e614
3 changed files with 174 additions and 16 deletions
  1. 161 7
      driver-titan.c
  2. 12 8
      titan-asic.c
  3. 1 1
      titan-asic.h

+ 161 - 7
driver-titan.c

@@ -24,6 +24,8 @@
 
 
 #define KNC_TITAN_HWERR_DISABLE_SECS	10
 #define KNC_TITAN_HWERR_DISABLE_SECS	10
 
 
+#define	KNC_POLL_INTERVAL_US		10000
+
 #define	KNC_TITAN_SPI_SPEED		3000000
 #define	KNC_TITAN_SPI_SPEED		3000000
 #define	KNC_TITAN_SPI_DELAY		0
 #define	KNC_TITAN_SPI_DELAY		0
 #define	KNC_TITAN_SPI_MODE		(SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
 #define	KNC_TITAN_SPI_MODE		(SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
@@ -40,6 +42,8 @@ struct knc_titan_core {
 	struct knc_titan_die *die;
 	struct knc_titan_die *die;
 	struct cgpu_info *proc;
 	struct cgpu_info *proc;
 
 
+	int next_slot;
+
 	int hwerr_in_row;
 	int hwerr_in_row;
 	int hwerr_disable_time;
 	int hwerr_disable_time;
 	struct timeval enable_at;
 	struct timeval enable_at;
@@ -60,6 +64,14 @@ struct knc_titan_info {
 	struct cgpu_info *cgpu;
 	struct cgpu_info *cgpu;
 	int cores;
 	int cores;
 	struct knc_titan_die dies[KNC_TITAN_MAX_ASICS][KNC_TITAN_DIES_PER_ASIC];
 	struct knc_titan_die dies[KNC_TITAN_MAX_ASICS][KNC_TITAN_DIES_PER_ASIC];
+
+	bool need_flush;
+	struct work *workqueue;
+	int workqueue_size;
+	int workqueue_max;
+	int next_id;
+
+	struct work *devicework;
 };
 };
 
 
 static bool knc_titan_spi_open(const char *repr, struct spi_port * const spi)
 static bool knc_titan_spi_open(const char *repr, struct spi_port * const spi)
@@ -126,6 +138,7 @@ static bool knc_titan_detect_one(const char *devpath)
 
 
 		knc->spi = spi;
 		knc->spi = spi;
 		knc->cgpu = cgpu;
 		knc->cgpu = cgpu;
+		knc->workqueue_max = 1;
 	} else {
 	} else {
 		knc = prev_cgpu->device_data;
 		knc = prev_cgpu->device_data;
 		spi = knc->spi;
 		spi = knc->spi;
@@ -240,6 +253,7 @@ static bool knc_titan_init(struct thr_info * const thr)
 				.asicno = asic,
 				.asicno = asic,
 				.dieno = die,
 				.dieno = die,
 				.coreno = i - core_base,
 				.coreno = i - core_base,
+				.next_slot = 1,
 				.die = &(knc->dies[asic][die]),
 				.die = &(knc->dies[asic][die]),
 				.proc = proc,
 				.proc = proc,
 				.hwerr_in_row = 0,
 				.hwerr_in_row = 0,
@@ -292,12 +306,152 @@ static bool knc_titan_init(struct thr_info * const thr)
 		knc_titan_setup_core(proc->device->dev_repr, knc->spi, &setup_params, knccore->dieno, knccore->coreno);
 		knc_titan_setup_core(proc->device->dev_repr, knc->spi, &setup_params, knccore->dieno, knccore->coreno);
 	}
 	}
 
 
+	timer_set_now(&thr->tv_poll);
+
 	return true;
 	return true;
 }
 }
 
 
-static int64_t knc_titan_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce)
+static void knc_titan_set_queue_full(struct knc_titan_info * const knc)
+{
+	const bool full = (knc->workqueue_size >= knc->workqueue_max);
+	struct cgpu_info *proc;
+
+	for (proc = knc->cgpu; proc; proc = proc->next_proc) {
+		struct thr_info * const thr = proc->thr[0];
+		thr->queue_full = full;
+	}
+}
+
+static void knc_titan_remove_local_queue(struct knc_titan_info * const knc, struct work * const work)
+{
+	DL_DELETE(knc->workqueue, work);
+	free_work(work);
+	--knc->workqueue_size;
+}
+
+static void knc_titan_prune_local_queue(struct thr_info *thr)
 {
 {
-	return 0;
+	struct cgpu_info * const cgpu = thr->cgpu;
+	struct knc_titan_info * const knc = cgpu->device_data;
+	struct work *work, *tmp;
+
+	DL_FOREACH_SAFE(knc->workqueue, work, tmp) {
+		if (stale_work(work, false))
+			knc_titan_remove_local_queue(knc, work);
+	}
+	knc_titan_set_queue_full(knc);
+}
+
+static bool knc_titan_queue_append(struct thr_info * const thr, struct work * const work)
+{
+	struct cgpu_info * const cgpu = thr->cgpu;
+	struct knc_titan_info * const knc = cgpu->device_data;
+
+	if (knc->workqueue_size >= knc->workqueue_max) {
+		knc_titan_prune_local_queue(thr);
+		if (thr->queue_full)
+			return false;
+	}
+
+	DL_APPEND(knc->workqueue, work);
+	++knc->workqueue_size;
+
+	knc_titan_set_queue_full(knc);
+	if (thr->queue_full)
+		knc_titan_prune_local_queue(thr);
+
+	return true;
+}
+
+#define HASH_LAST_ADDED(head, out)  \
+	(out = (head) ? (ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail)) : NULL)
+
+static void knc_titan_queue_flush(struct thr_info * const thr)
+{
+	struct cgpu_info * const cgpu = thr->cgpu;
+	struct knc_titan_info * const knc = cgpu->device_data;
+	struct work *work, *tmp;
+
+	if (knc->cgpu != cgpu)
+		return;
+
+	DL_FOREACH_SAFE(knc->workqueue, work, tmp){
+		knc_titan_remove_local_queue(knc, work);
+	}
+	knc_titan_set_queue_full(knc);
+
+	HASH_LAST_ADDED(knc->devicework, work);
+	if (work && stale_work(work, true)) {
+		knc->need_flush = true;
+		timer_set_now(&thr->tv_poll);
+	}
+}
+
+static void knc_titan_poll(struct thr_info * const thr)
+{
+	struct cgpu_info * const cgpu = thr->cgpu;
+	struct knc_titan_info * const knc = cgpu->device_data;
+	struct spi_port * const spi = knc->spi;
+	struct knc_titan_core *knccore;
+	struct work *work, *tmp;
+	int workaccept = 0;
+	unsigned long delay_usecs = KNC_POLL_INTERVAL_US;
+	struct titan_report report;
+	bool urgent = false;
+
+	knc_titan_prune_local_queue(thr);
+
+	spi_clear_buf(spi);
+	if (knc->need_flush) {
+		applog(LOG_NOTICE, "%s: Flushing stale works", knc_titan_drv.dname);
+		urgent = true;
+	}
+	knccore = cgpu->thr[0]->cgpu_data;
+	DL_FOREACH(knc->workqueue, work) {
+		bool work_accepted;
+		if (!knc_titan_set_work(cgpu->dev_repr, knc->spi, &report, 0, 0xFFFF, knccore->next_slot, work, urgent, &work_accepted))
+			work_accepted = false;
+		if (!work_accepted)
+			break;
+		if (++(knccore->next_slot) >= 16)
+			knccore->next_slot = 1;
+		urgent = false;
+		++workaccept;
+	}
+
+	applog(LOG_DEBUG, "%s: %d jobs accepted to queue (max=%d)", knc_titan_drv.dname, workaccept, knc->workqueue_max);
+
+	while (true) {
+		/* TODO: collect reports from processors */
+	}
+
+	if (knc->need_flush) {
+		knc->need_flush = false;
+		HASH_ITER(hh, knc->devicework, work, tmp)
+		{
+			HASH_DEL(knc->devicework, work);
+			free_work(work);
+		}
+		delay_usecs = 0;
+	}
+
+	if (workaccept) {
+		if (workaccept >= knc->workqueue_max) {
+			knc->workqueue_max = workaccept;
+			delay_usecs = 0;
+		}
+		DL_FOREACH_SAFE(knc->workqueue, work, tmp) {
+			--knc->workqueue_size;
+			DL_DELETE(knc->workqueue, work);
+			work->device_id = knc->next_id++;
+			HASH_ADD(hh, knc->devicework, device_id, sizeof(work->device_id), work);
+			if (!--workaccept)
+				break;
+		}
+		knc_titan_set_queue_full(knc);
+	}
+
+	timer_set_delay_from_now(&thr->tv_poll, delay_usecs);
 }
 }
 
 
 /*
 /*
@@ -367,11 +521,11 @@ struct device_drv knc_titan_drv =
 
 
 	.thread_init = knc_titan_init,
 	.thread_init = knc_titan_init,
 
 
-	/* specify mining type - scanhash */
-	.minerloop = minerloop_scanhash,
-
-	/* scanhash mining hooks */
-	.scanhash = knc_titan_scanhash,
+	/* specify mining type - queue */
+	.minerloop = minerloop_queue,
+	.queue_append = knc_titan_queue_append,
+	.queue_flush = knc_titan_queue_flush,
+	.poll = knc_titan_poll,
 
 
 	/* TUI support - e.g. setting clock via UI */
 	/* TUI support - e.g. setting clock via UI */
 #ifdef HAVE_CURSES
 #ifdef HAVE_CURSES

+ 12 - 8
titan-asic.c

@@ -40,7 +40,7 @@
 /* send_size - size of send_buf, without crc
 /* send_size - size of send_buf, without crc
  * transfer_size - total size of transfer
  * transfer_size - total size of transfer
  */
  */
-static uint8_t * spi_transfer(struct spi_port * const spi, uint8_t *send_buf, int send_size, int transfer_size, int rcv_crc_data_len, uint32_t *errors)
+static uint8_t * spi_transfer(struct spi_port * const spi, uint8_t *send_buf, int send_size, int transfer_size, int rcv_crc_data_len, uint32_t *errors, bool *work_accepted)
 {
 {
 	uint8_t *rxbuf, crcbuf[CRC32_SIZE];
 	uint8_t *rxbuf, crcbuf[CRC32_SIZE];
 	uint32_t crc;
 	uint32_t crc;
@@ -52,6 +52,7 @@ static uint8_t * spi_transfer(struct spi_port * const spi, uint8_t *send_buf, in
 	}
 	}
 
 
 	*errors = 0;
 	*errors = 0;
+	*work_accepted = false;
 	if (transfer_size < min_transfer_size) {
 	if (transfer_size < min_transfer_size) {
 exit_other_error:
 exit_other_error:
 		*errors |= ERR_OTHER_ERR;
 		*errors |= ERR_OTHER_ERR;
@@ -80,7 +81,7 @@ exit_other_error:
 		if (crc != be32toh(*((uint32_t *)crcbuf)))
 		if (crc != be32toh(*((uint32_t *)crcbuf)))
 			*errors |= ERR_RCV_CRC_FAIL;
 			*errors |= ERR_RCV_CRC_FAIL;
 	}
 	}
-
+	*work_accepted = ((0 == *errors) && (rcv_status & RCV_STATUS_ACCEPTED_WORK));
 #if 0
 #if 0
 	{
 	{
 		uint8_t *txbuf = spi_gettxbuf(spi);
 		uint8_t *txbuf = spi_gettxbuf(spi);
@@ -115,9 +116,10 @@ bool knc_titan_spi_get_info(const char *repr, struct spi_port * const spi, struc
 	uint16_t revision;
 	uint16_t revision;
 	int transfer_size = 24 + ((core_hint + 3) / 4);
 	int transfer_size = 24 + ((core_hint + 3) / 4);
 	int i, core;
 	int i, core;
+	bool unused;
 
 
 	for (i = 0; i < 3; ++i) {
 	for (i = 0; i < 3; ++i) {
-		rxbuf = spi_transfer(spi, get_info_cmd, sizeof(get_info_cmd), transfer_size, transfer_size - 4 - CRC32_SIZE - SPI_RESPONSE_TRAILER_SIZE, &errors);
+		rxbuf = spi_transfer(spi, get_info_cmd, sizeof(get_info_cmd), transfer_size, transfer_size - 4 - CRC32_SIZE - SPI_RESPONSE_TRAILER_SIZE, &errors, &unused);
 		if (NULL == rxbuf) {
 		if (NULL == rxbuf) {
 exit_unrec_error:	applog(LOG_ERR, "%s[%d] knc_titan_spi_get_info: Unrecognized error", repr, die);
 exit_unrec_error:	applog(LOG_ERR, "%s[%d] knc_titan_spi_get_info: Unrecognized error", repr, die);
 			return false;
 			return false;
@@ -147,7 +149,7 @@ exit_bad_revision:	applog(LOG_ERR, "%s[%d] knc_titan_spi_get_info: Bad revision
 			applog(LOG_NOTICE, "%s[%d] core hint %d might be wrong, new guess is %d", repr, die, core_hint, resp->cores);
 			applog(LOG_NOTICE, "%s[%d] core hint %d might be wrong, new guess is %d", repr, die, core_hint, resp->cores);
 			transfer_size = 24 + ((resp->cores + 3) / 4);
 			transfer_size = 24 + ((resp->cores + 3) / 4);
 			for (i = 0; i < 3; ++i) {
 			for (i = 0; i < 3; ++i) {
-				rxbuf = spi_transfer(spi, get_info_cmd, sizeof(get_info_cmd), transfer_size, transfer_size - 4 - CRC32_SIZE - SPI_RESPONSE_TRAILER_SIZE, &errors);
+				rxbuf = spi_transfer(spi, get_info_cmd, sizeof(get_info_cmd), transfer_size, transfer_size - 4 - CRC32_SIZE - SPI_RESPONSE_TRAILER_SIZE, &errors, &unused);
 				if (NULL == rxbuf)
 				if (NULL == rxbuf)
 					goto exit_unrec_error;
 					goto exit_unrec_error;
 				if (errors != ERR_SEND_CRC_FAIL)
 				if (errors != ERR_SEND_CRC_FAIL)
@@ -208,7 +210,7 @@ static void knc_titan_parse_get_report(uint8_t *data, struct titan_report *repor
 	}
 	}
 }
 }
 
 
-bool knc_titan_set_work(const char *repr, struct spi_port * const spi, struct titan_report *report, int die, int core, int slot, struct work *work, bool urgent)
+bool knc_titan_set_work(const char *repr, struct spi_port * const spi, struct titan_report *report, int die, int core, int slot, struct work *work, bool urgent, bool *work_accepted)
 {
 {
 #define	SETWORK_CMD_SIZE	(5 + BLOCK_HEADER_BYTES_WITHOUT_NONCE)
 #define	SETWORK_CMD_SIZE	(5 + BLOCK_HEADER_BYTES_WITHOUT_NONCE)
 	uint8_t set_work_cmd_aligned[3 + SETWORK_CMD_SIZE] = {
 	uint8_t set_work_cmd_aligned[3 + SETWORK_CMD_SIZE] = {
@@ -232,7 +234,7 @@ bool knc_titan_set_work(const char *repr, struct spi_port * const spi, struct ti
 	for (i = 0; i < (BLOCK_HEADER_BYTES_WITHOUT_NONCE / 4); ++i)
 	for (i = 0; i < (BLOCK_HEADER_BYTES_WITHOUT_NONCE / 4); ++i)
 		dst[i] = htobe32(src[i]);
 		dst[i] = htobe32(src[i]);
 
 
-	rxbuf = spi_transfer(spi, &set_work_cmd_aligned[3], send_size, transfer_size, 2 + KNC_TITAN_NONCES_PER_REPORT * 5, &errors);
+	rxbuf = spi_transfer(spi, &set_work_cmd_aligned[3], send_size, transfer_size, 2 + KNC_TITAN_NONCES_PER_REPORT * 5, &errors, work_accepted);
 	if (NULL == rxbuf) {
 	if (NULL == rxbuf) {
 		applog(LOG_ERR, "%s[%d:%d] knc_titan_set_work: Unrecognized error", repr, die, core);
 		applog(LOG_ERR, "%s[%d:%d] knc_titan_set_work: Unrecognized error", repr, die, core);
 		return false;
 		return false;
@@ -252,8 +254,9 @@ bool knc_titan_get_report(const char *repr, struct spi_port * const spi, struct
 	const int transfer_size = send_size + 2 + KNC_TITAN_NONCES_PER_REPORT * 5 + CRC32_SIZE + SPI_RESPONSE_TRAILER_SIZE;
 	const int transfer_size = send_size + 2 + KNC_TITAN_NONCES_PER_REPORT * 5 + CRC32_SIZE + SPI_RESPONSE_TRAILER_SIZE;
 	uint8_t *rxbuf;
 	uint8_t *rxbuf;
 	uint32_t errors;
 	uint32_t errors;
+	bool unused;
 
 
-	rxbuf = spi_transfer(spi, get_report_cmd, send_size, transfer_size, 2 + KNC_TITAN_NONCES_PER_REPORT * 5, &errors);
+	rxbuf = spi_transfer(spi, get_report_cmd, send_size, transfer_size, 2 + KNC_TITAN_NONCES_PER_REPORT * 5, &errors, &unused);
 	if (NULL == rxbuf) {
 	if (NULL == rxbuf) {
 		applog(LOG_ERR, "%s[%d:%d] knc_titan_get_report: Unrecognized error", repr, die, core);
 		applog(LOG_ERR, "%s[%d:%d] knc_titan_get_report: Unrecognized error", repr, die, core);
 		return false;
 		return false;
@@ -280,6 +283,7 @@ bool knc_titan_setup_core(const char *repr, struct spi_port * const spi, struct
 	const int transfer_size = send_size + CRC32_SIZE + SPI_RESPONSE_TRAILER_SIZE;
 	const int transfer_size = send_size + CRC32_SIZE + SPI_RESPONSE_TRAILER_SIZE;
 	uint8_t *rxbuf;
 	uint8_t *rxbuf;
 	uint32_t errors;
 	uint32_t errors;
+	bool unused;
 	uint32_t *src, *dst;
 	uint32_t *src, *dst;
 	int i;
 	int i;
 	struct titan_packed_core_params {
 	struct titan_packed_core_params {
@@ -482,7 +486,7 @@ bool knc_titan_setup_core(const char *repr, struct spi_port * const spi, struct
 	for (i = 0; i < (sizeof(packed_params) / 4); ++i)
 	for (i = 0; i < (sizeof(packed_params) / 4); ++i)
 		dst[i] = htobe32(src[i]);
 		dst[i] = htobe32(src[i]);
 
 
-	rxbuf = spi_transfer(spi, setup_core_cmd, send_size, transfer_size, 0, &errors);
+	rxbuf = spi_transfer(spi, setup_core_cmd, send_size, transfer_size, 0, &errors, &unused);
 	if (NULL == rxbuf) {
 	if (NULL == rxbuf) {
 		applog(LOG_ERR, "%s[%d:%d] knc_titan_setup_core: Unrecognized error", repr, die, core);
 		applog(LOG_ERR, "%s[%d:%d] knc_titan_setup_core: Unrecognized error", repr, die, core);
 		return false;
 		return false;

+ 1 - 1
titan-asic.h

@@ -45,7 +45,7 @@ struct titan_setup_core_params {
 
 
 bool knc_titan_spi_get_info(const char *repr, struct spi_port * const spi, struct titan_info_response *resp, int die, int core_hint);
 bool knc_titan_spi_get_info(const char *repr, struct spi_port * const spi, struct titan_info_response *resp, int die, int core_hint);
 bool knc_titan_get_report(const char *repr, struct spi_port * const spi, struct titan_report *report, int die, int core);
 bool knc_titan_get_report(const char *repr, struct spi_port * const spi, struct titan_report *report, int die, int core);
-bool knc_titan_set_work(const char *repr, struct spi_port * const spi, struct titan_report *report, int die, int core, int slot, struct work *work, bool urgent);
+bool knc_titan_set_work(const char *repr, struct spi_port * const spi, struct titan_report *report, int die, int core, int slot, struct work *work, bool urgent, bool *work_accepted);
 bool knc_titan_setup_core(const char *repr, struct spi_port * const spi, struct titan_setup_core_params *params, int die, int core);
 bool knc_titan_setup_core(const char *repr, struct spi_port * const spi, struct titan_setup_core_params *params, int die, int core);
 
 
 #endif /* __TITAN_ASIC_H */
 #endif /* __TITAN_ASIC_H */