Browse Source

gridseed: Switch from the Queued miner loop to the Scanhash miner loop
Improves performance on Raspberry Pi
Fixes inaccurate hashrate estimates
Fixes bug overwriting work inadvertently

Nate Woolls 11 years ago
parent
commit
b036aa43b4
3 changed files with 39 additions and 203 deletions
  1. 38 193
      driver-gridseed.c
  2. 0 9
      gc3355.c
  3. 1 1
      gc3355.h

+ 38 - 193
driver-gridseed.c

@@ -20,6 +20,7 @@
 
 #define GRIDSEED_DEFAULT_FREQUENCY  600
 #define GRIDSEED_MAX_QUEUED          10
+#define GRIDSEED_HASH_SPEED			0.0851128926	// in ms
 
 BFG_REGISTER_DRIVER(gridseed_drv)
 
@@ -38,7 +39,6 @@ struct cgpu_info *gridseed_alloc_device(const char *path, struct device_drv *dri
 	device->device_path = strdup(path);
 	device->device_fd = -1;
 	device->threads = 1;
-	device->procs = GC3355_ORB_DEFAULT_CHIPS;
 	device->device_data = info;
 	
 	return device;
@@ -140,22 +140,6 @@ bool gridseed_thread_prepare(struct thr_info *thr)
 	return true;
 }
 
-static
-bool gridseed_set_queue_full(const struct cgpu_info * const device, int needwork);
-
-static
-bool gridseed_thread_init(struct thr_info *master_thr)
-{
-	struct cgpu_info * const device = master_thr->cgpu;
-	gridseed_set_queue_full(device, 0);
-	timer_set_now(&master_thr->tv_poll);
-	
-	// kick off queue minerloop
-	gridseed_set_queue_full(device, device->procs * 2);
-	
-	return true;
-}
-
 static
 void gridseed_thread_shutdown(struct thr_info *thr)
 {
@@ -165,45 +149,25 @@ void gridseed_thread_shutdown(struct thr_info *thr)
 	free(thr->cgpu_data);
 }
 
-static
-void gridseed_reinit_device(struct cgpu_info * const proc)
-{
-	timer_set_now(&proc->thr[0]->tv_poll);
-}
-
 /*
- * queued mining loop
+ * scanhash mining loop
  */
 
+// send work to the device
 static
-bool gridseed_set_queue_full(const struct cgpu_info * const device, int needwork)
+bool gridseed_prepare_work(struct thr_info __maybe_unused *thr, struct work *work)
 {
-	struct gc3355_orb_info * const info = device->device_data;
-	struct thr_info * const master_thr = device->thr[0];
-	
-	if (needwork != -1)
-		info->needwork = needwork;
-	
-	const bool full = (device->device_fd == -1 || !info->needwork);
-	
-	if (full == master_thr->queue_full)
-		return full;
-	
-	for (const struct cgpu_info *proc = device; proc; proc = proc->next_proc)
-	{
-		struct thr_info * const thr = proc->thr[0];
-		thr->queue_full = full;
-	}
-	
-	return full;
-}
+	struct cgpu_info *device = thr->cgpu;
+	struct gc3355_orb_info *info = device->device_data;
 
-static
-bool gridseed_send_work(const struct cgpu_info * const device, struct work *work)
-{
 	int work_size = opt_scrypt ? 156 : 52;
 	unsigned char cmd[work_size];
 	
+	cgtime(&info->scanhash_time);
+
+	//from GC3355 docs if we are using FIFO
+	work->id = 12345678;
+
 	if (opt_scrypt)
 	{
 		gc3355_scrypt_reset(device->device_fd);
@@ -218,149 +182,42 @@ bool gridseed_send_work(const struct cgpu_info * const device, struct work *work
 		applog(LOG_ERR, "%s: Failed to send work", device->dev_repr);
 		return false;
 	}
-	
-	return true;
-}
 
-static
-void gridseed_prune_queue(const struct cgpu_info * const device, struct work *work)
-{
-	struct thr_info * const master_thr = device->thr[0];
-	
-	// prune queue
-	int prunequeue = HASH_COUNT(master_thr->work_list) - GRIDSEED_MAX_QUEUED;
-	if (prunequeue > 0)
-	{
-		struct work *tmp;
-		applog(LOG_DEBUG, "%s: Pruning %d old work item%s",
-		       device->dev_repr, prunequeue, prunequeue == 1 ? "" : "s");
-		HASH_ITER(hh, master_thr->work_list, work, tmp)
-		{
-			HASH_DEL(master_thr->work_list, work);
-			free_work(work);
-			if (--prunequeue < 1)
-				break;
-		}
-	}
-}
-
-// send work to the device & queue work
-static
-bool gridseed_queue_append(struct thr_info * const thr, struct work *work)
-{
-	const struct cgpu_info * const device = thr->cgpu->device;
-	struct gc3355_orb_info * const info = device->device_data;
-	struct thr_info * const master_thr = device->thr[0];
-	
-	// if queue is full (-1 is a check flag) do not append new work
-	if (gridseed_set_queue_full(device, -1))
-		return false;
-	
-	// send work
-	if (!gridseed_send_work(device, work))
-		return false;
-	
-	// store work in queue
-	HASH_ADD(hh, master_thr->work_list, id, sizeof(work->id), work);
-	
-	// prune queue
-	gridseed_prune_queue(device, work);
-	
-	// sets info->needwork equal to 2nd arg and updates "full" flags
-	gridseed_set_queue_full(device, info->needwork - 1);
-	
 	return true;
 }
 
 static
-void gridseed_queue_flush(struct thr_info * const thr)
+void gridseed_submit_nonce(struct thr_info * const thr, const unsigned char buf[GC3355_READ_SIZE], struct work * const work)
 {
-	const struct cgpu_info *device = thr->cgpu;
-	if (device != device->device)
-		return;
-	
-	gridseed_set_queue_full(device, device->procs);
+	uint32_t nonce = *(uint32_t *)(buf + 4);
+	nonce = le32toh(nonce);
+	submit_nonce(thr, work, nonce);
 }
 
 static
-const struct cgpu_info *gridseed_proc_by_id(const struct cgpu_info * const dev, int procid)
+int64_t gridseed_estimate_hashes(struct thr_info *thr)
 {
-	const struct cgpu_info *proc = dev;
-	for (int i = 0; i < procid; ++i)
-	{
-		proc = proc->next_proc;
-		if (unlikely(!proc))
-			return NULL;
-	}
-	return proc;
-}
-
-static
-void gridseed_submit_nonce(struct thr_info * const master_thr, const unsigned char buf[GC3355_READ_SIZE])
-{
-	struct work *work;
-	uint32_t nonce;
-	int workid;
-	struct cgpu_info * const device = master_thr->cgpu;
-	struct gc3355_orb_info * const info = device->device_data;
-	
-	// extract workid from buffer
-	memcpy(&workid, buf + 8, 4);
-	// extract nonce from buffer
-	memcpy(&nonce, buf + 4, 4);
-	// extract chip # from nonce
-	const int chip = nonce / ((uint32_t)0xffffffff / GC3355_ORB_DEFAULT_CHIPS);
-	// find processor by device & chip
-	const struct cgpu_info *proc = gridseed_proc_by_id(device, chip);
-	// default process to device
-	if (unlikely(!proc))
-		proc = device;
-	// the thread specific to the ASIC chip:
-	struct thr_info * thr = proc->thr[0];
-	
-	nonce = htole32(nonce);
-	
-	// find the queued work for this nonce, by workid
-	HASH_FIND(hh, master_thr->work_list, &workid, sizeof(workid), work);
-	if (work)
-	{
-		submit_nonce(thr, work, nonce);
-		
-		HASH_DEL(master_thr->work_list, work);
-		
-		gridseed_set_queue_full(device, info->needwork + 2);
-	}
-}
+	struct cgpu_info *device = thr->cgpu;
+	struct gc3355_orb_info *info = device->device_data;
+	struct timeval old_scanhash_time = info->scanhash_time;
+	cgtime(&info->scanhash_time);
+	int elapsed_ms = ms_tdiff(&info->scanhash_time, &old_scanhash_time);
 
-static
-void gridseed_estimate_hashes(const struct cgpu_info * const device)
-{
-	const struct cgpu_info *proc = device;
-	const struct gc3355_orb_info *info = device->device_data;
-	
-	while (true)
-	{
-		hashes_done2(proc->thr[0], info->freq * 0xA4, NULL);
-		proc = proc->next_proc;
-		if (unlikely(!proc))
-			return;
-	}
+	return GRIDSEED_HASH_SPEED * (double)elapsed_ms * (double)(info->freq * GC3355_ORB_DEFAULT_CHIPS);
 }
 
-#define GRIDSEED_SHORT_WORK_DELAY_MS  20
-#define GRIDSEED_LONG_WORK_DELAY_MS   30
-
 // read from device for nonce or command
 static
-void gridseed_poll(struct thr_info * const master_thr)
+int64_t gridseed_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce)
 {
-	struct cgpu_info * const device = master_thr->cgpu;
+	struct cgpu_info *device = thr->cgpu;
+	struct gc3355_info *info = device->device_data;
+
 	unsigned char buf[GC3355_READ_SIZE];
 	int read = 0;
-	struct timeval tv_timeout;
-	timer_set_delay_from_now(&tv_timeout, GRIDSEED_LONG_WORK_DELAY_MS * 1000);  // X MS
-	
-	while (!master_thr->work_restart && (read = gc3355_read(device->device_fd, (char *)buf, GC3355_READ_SIZE)) > 0)
+	int fd = device->device_fd;
+
+	while (!thr->work_restart && (read = gc3355_read(fd, (char *)buf, GC3355_READ_SIZE)) > 0)
 	{
 		if (buf[0] == 0x55)
 		{
@@ -372,28 +229,19 @@ void gridseed_poll(struct thr_info * const master_thr)
 				case 0x10: // BTC result
 				case 0x20: // LTC result
 				{
-					gridseed_submit_nonce(master_thr, buf);
+					gridseed_submit_nonce(thr, buf, work);
 					break;
 				}
 			}
-		} else
-		{
-			applog(LOG_ERR, "%"PRIpreprv": Unrecognized response", device->proc_repr);
-			break;
 		}
-		
-		if (timer_passed(&tv_timeout, NULL))
+		else
 		{
-			// allow work to be sent to the device
-			applog(LOG_DEBUG, "%s poll: timeout met", device->dev_repr);
+			applog(LOG_ERR, "%"PRIpreprv": Unrecognized response", device->proc_repr);
 			break;
 		}
 	}
-	
-	gridseed_estimate_hashes(device);
-	
-	// allow work to be sent to the device
-	timer_set_delay_from_now(&master_thr->tv_poll, GRIDSEED_SHORT_WORK_DELAY_MS * 1000); // X MS
+
+	return gridseed_estimate_hashes(thr);
 }
 
 /*
@@ -433,16 +281,13 @@ struct device_drv gridseed_drv =
 	
 	// initialize device
 	.thread_prepare = gridseed_thread_prepare,
-	.thread_init = gridseed_thread_init,
-	.reinit_device = gridseed_reinit_device,
 	
 	// specify mining type - scanhash
-	.minerloop = minerloop_queue,
+	.minerloop = minerloop_scanhash,
 	
-	// queued mining hooks
-	.queue_append = gridseed_queue_append,
-	.queue_flush = gridseed_queue_flush,
-	.poll = gridseed_poll,
+	// scanhash mining hooks
+	.prepare_work = gridseed_prepare_work,
+	.scanhash = gridseed_scanhash,
 	
 	// teardown device
 	.thread_shutdown = gridseed_thread_shutdown,

+ 0 - 9
gc3355.c

@@ -44,12 +44,6 @@ const char *firmware_request_cmd[] =
 	NULL
 };
 
-static
-const char *no_fifo_cmd[] = {
-	"55AAC000D0D0D0D00000000001000000",
-	NULL
-};
-
 // SHA-2 commands
 
 static
@@ -645,9 +639,6 @@ void gc3355_init_device(int fd, int pll_freq, bool scrypt_only, bool detect_only
 		if (usbstick)
 			// set request to send (RTS) status
 			set_serial_rts(fd, BGV_HIGH);
-		else
-			// no fifo for orb
-			gc3355_send_cmds(fd, no_fifo_cmd);
 	}
 }
 

+ 1 - 1
gc3355.h

@@ -33,7 +33,7 @@ int opt_pll_freq;
 struct gc3355_orb_info
 {
 	uint16_t freq;
-	int needwork;
+	struct timeval scanhash_time;
 };
 
 #define gc3355_open(path)  serial_open(path, 115200, 1, true)