Browse Source

Semi-Merge commit '1802302' into update_avalon_20130524 (sync with cgminer rebase)

Conflicts:
	configure.ac
	driver-avalon.c
	driver-avalon.h
	fpgautils.c
	fpgautils.h
	miner.c
	miner.h
Luke Dashjr 12 years ago
parent
commit
d371272609
5 changed files with 64 additions and 105 deletions
  1. 50 98
      driver-avalon.c
  2. 3 0
      driver-avalon.h
  3. 4 1
      fpgautils.c
  4. 1 3
      miner.c
  5. 6 3
      miner.h

+ 50 - 98
driver-avalon.c

@@ -636,7 +636,6 @@ static void avalon_init(struct cgpu_info *avalon)
 		return;
 	}
 
-	avalon->status = LIFE_INIT;
 	avalon->device_fd = fd;
 	__avalon_init(avalon);
 }
@@ -644,35 +643,37 @@ static void avalon_init(struct cgpu_info *avalon)
 static bool avalon_prepare(struct thr_info *thr)
 {
 	struct cgpu_info *avalon = thr->cgpu;
+	struct avalon_info *info = avalon_info[avalon->device_id];
 	struct timeval now;
 
-	if (avalon->device_fd == -1)
-		avalon_init(avalon);
-	else
-		__avalon_init(avalon);
+	avalon->works = calloc(info->miner_count * sizeof(struct work *), 1);
+	if (!avalon->works)
+		quit(1, "Failed to calloc avalon works in avalon_prepare");
+	__avalon_init(avalon);
 
 	gettimeofday(&now, NULL);
 	get_datestamp(avalon->init, &now);
 	return true;
 }
 
-static void avalon_free_work(struct thr_info *thr, struct work **work)
+static void avalon_free_work(struct thr_info *thr, struct work **works)
 {
 	struct cgpu_info *avalon;
 	struct avalon_info *info;
 	int i;
 
-	if (unlikely(!work))
+	if (unlikely(!works))
 		return;
 
 	avalon = thr->cgpu;
 	info = avalon_info[avalon->device_id];
 
-	for (i = 0; i < info->miner_count; i++)
-		if (likely(work[i])) {
-			free_work(work[i]);
-			work[i] = NULL;
+	for (i = 0; i < info->miner_count; i++) {
+		if (likely(works[i])) {
+			work_completed(avalon, works[i]);
+			works[i] = NULL;
 		}
+	}
 }
 
 static void do_avalon_close(struct thr_info *thr)
@@ -756,11 +757,24 @@ static inline void adjust_fan(struct avalon_info *info)
 	}
 }
 
-static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
-			       __maybe_unused int64_t max_nonce)
+static bool avalon_fill(struct cgpu_info *avalon)
+{
+	struct work *work = get_queued(avalon);
+
+	if (unlikely(!work))
+		return false;
+	avalon->queued++;
+	if (avalon->queued == avalon_info[avalon->device_id]->miner_count)
+		return true;
+	return false;
+}
+
+static int64_t avalon_scanhash(struct thr_info *thr)
 {
 	struct cgpu_info *avalon;
+	struct work **works;
 	int fd, ret, full;
+	int64_t scanret = 0;
 
 	struct avalon_info *info;
 	struct avalon_task at;
@@ -775,17 +789,20 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 	int result_count, result_wrong;
 
 	avalon = thr->cgpu;
+	works = avalon->works;
 	info = avalon_info[avalon->device_id];
 	avalon_get_work_count = info->miner_count;
 
-	if (unlikely(avalon->device_fd == -1))
+	if (unlikely(avalon->device_fd == -1)) {
 		if (!avalon_prepare(thr)) {
 			applog(LOG_ERR, "AVA%i: Comms error(open)",
 			       avalon->device_id);
 			dev_error(avalon, REASON_DEV_COMMS_ERROR);
 			/* fail the device if the reopen attempt fails */
-			return -1;
+			scanret = -1;
+			goto out;
 		}
+	}
 	fd = avalon->device_fd;
 #ifndef WIN32
 	tcflush(fd, TCOFLUSH);
@@ -795,7 +812,7 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 		info->bulk0[i] = info->bulk1[i];
 		info->bulk1[i] = info->bulk2[i];
 		info->bulk2[i] = info->bulk3[i];
-		info->bulk3[i] = work[i];
+		info->bulk3[i] = works[i];
 		applog(LOG_DEBUG, "Avalon: bulk0/1/2 buffer [%d]: %p, %p, %p, %p",
 		       i, info->bulk0[i], info->bulk1[i], info->bulk2[i], info->bulk3[i]);
 	}
@@ -805,7 +822,7 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 		avalon_init_task(&at, 0, 0, info->fan_pwm,
 				 info->timeout, info->asic_count,
 				 info->miner_count, 1, 0, info->frequency);
-		avalon_create_task(&at, work[i]);
+		avalon_create_task(&at, works[i]);
 		ret = avalon_send_task(fd, &at, avalon);
 		if (unlikely(ret == AVA_SEND_ERROR ||
 			     (ret == AVA_SEND_BUFFER_EMPTY &&
@@ -822,14 +839,15 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 			first_try = 0;
 			nmsleep(1000);
 			avalon_init(avalon);
-			return 0;	/* This should never happen */
+			goto out;	/* This should never happen */
 		}
 		if (ret == AVA_SEND_BUFFER_EMPTY && (i + 1 == avalon_get_work_count)) {
 			first_try = 1;
-			return 0xffffffff;
+			ret = 0xffffffff;
+			goto out;
 		}
 
-		work[i]->blk.nonce = 0xffffffff;
+		works[i]->blk.nonce = 0xffffffff;
 
 		if (ret == AVA_SEND_BUFFER_FULL)
 			break;
@@ -864,7 +882,7 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 			applog(LOG_ERR,
 			       "AVA%i: Comms error(read)", avalon->device_id);
 			dev_error(avalon, REASON_DEV_COMMS_ERROR);
-			return 0;
+			goto out;
 		}
 		if (unlikely(ret == AVA_GETS_TIMEOUT)) {
 			timersub(&tv_finish, &tv_start, &elapsed);
@@ -931,7 +949,7 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 		do_avalon_close(thr);
 		nmsleep(1000);
 		avalon_init(avalon);
-		return 0;
+		goto out;
 	}
 
 	avalon_free_work(thr, info->bulk0);
@@ -961,81 +979,14 @@ static int64_t avalon_scanhash(struct thr_info *thr, struct work **work,
 	 *
 	 * Any patch will be great.
 	 */
-	return (hash_count * 2);
-}
-
-// minerloop_scanhash hacked to handle Avalon's many processors
-static
-void minerloop_avalon(struct thr_info *mythr)
-{
-	const int thr_id = mythr->id;
-	struct cgpu_info *cgpu = mythr->cgpu;
-	struct device_drv *api = cgpu->drv;
-	struct timeval tv_start, tv_end;
-	struct timeval tv_hashes;
-	uint32_t max_nonce = api->can_limit_work ? api->can_limit_work(mythr) : 0xffffffff;
-	int64_t hashes;
-	struct avalon_info *info = avalon_info[cgpu->device_id];
-	int i;
-	int avalon_get_work_count = info->miner_count;
-	struct work **work = calloc(1,
-				    avalon_get_work_count * sizeof(struct work *));
-	if (!work)
-		quit(1, "Faile on Avalon calloc");
-	const bool primary = (!mythr->device_thread) || mythr->primary_thread;
-	
-	while (1) {
-		mythr->work_restart = false;
-		for (i = 0; i < avalon_get_work_count; i++)
-			request_work(mythr);
-		for (i = 0; i < avalon_get_work_count; i++) {
-			work[i] = get_work(mythr);
-			work[i]->blk.nonce = 0;
-		}
-		for (i = 0; i < avalon_get_work_count; i++) {
-			if (api->prepare_work && !api->prepare_work(mythr, work[i])) {
-				applog(LOG_ERR, "work prepare failed, exiting "
-					"mining thread %d", thr_id);
-				break;
-			}
-			gettimeofday(&(work[i]->tv_work_start), NULL);
-		}
-		
-		do {
-			thread_reportin(mythr);
-			gettimeofday(&tv_start, NULL);
-			hashes = api->scanhash_queue(mythr, work, max_nonce);
-			gettimeofday(&tv_end, NULL);
-			thread_reportin(mythr);
-			
-			timersub(&tv_end, &tv_start, &tv_hashes);
-			if (!hashes_done(mythr, hashes, &tv_hashes, api->can_limit_work ? &max_nonce : NULL))
-				goto disabled;
-			
-			if (unlikely(mythr->work_restart)) {
-				/* Apart from device_thread 0, we stagger the
-				 * starting of every next thread to try and get
-				 * all devices busy before worrying about
-				 * getting work for their extra threads */
-				if (!primary) {
-					struct timespec rgtp;
-
-					rgtp.tv_sec = 0;
-					rgtp.tv_nsec = 250 * mythr->device_thread * 1000000;
-					nanosleep(&rgtp, NULL);
-				}
-				break;
-			}
-			
-			if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED))
-disabled:
-				mt_disable(mythr);
-		} while (false);
-	}
-	free(work);
+	scanret = hash_count * 2;
+out:
+	avalon_free_work(thr, avalon->works);
+	avalon->queued = 0;
+	return scanret;
 }
 
-static struct api_data *avalon_drv_stats(struct cgpu_info *cgpu)
+static struct api_data *avalon_api_stats(struct cgpu_info *cgpu)
 {
 	struct api_data *root = NULL;
 	struct avalon_info *info = avalon_info[cgpu->device_id];
@@ -1095,9 +1046,10 @@ struct device_drv avalon_drv = {
 	.name = "AVA",
 	.drv_detect = avalon_detect,
 	.thread_prepare = avalon_prepare,
-	.minerloop = minerloop_avalon,
-	.scanhash_queue = avalon_scanhash,
-	.get_api_stats = avalon_drv_stats,
+	.minerloop = hash_queued_work,
+	.queue_full = avalon_fill,
+	.scanwork = avalon_scanhash,
+	.get_api_stats = avalon_api_stats,
 	.reinit_device = avalon_init,
 	.thread_shutdown = avalon_shutdown,
 };

+ 3 - 0
driver-avalon.h

@@ -10,6 +10,8 @@
 #ifndef AVALON_H
 #define AVALON_H
 
+#ifdef USE_AVALON
+
 #define AVALON_TIME_FACTOR 10
 #define AVALON_RESET_FAULT_DECISECONDS 1
 #define AVALON_MINER_THREADS 1
@@ -130,4 +132,5 @@ ASSERT1(sizeof(uint32_t) == 4);
 
 extern struct avalon_info **avalon_info;
 
+#endif /* USE_AVALON */
 #endif	/* AVALON_H */

+ 4 - 1
fpgautils.c

@@ -1,5 +1,6 @@
 /*
  * Copyright 2012-2013 Luke Dashjr
+ * Copyright 2013 Con Kolivas
  * Copyright 2012 Andrew Smith
  * Copyright 2013 Xiangfu
  *
@@ -27,8 +28,8 @@
 #ifndef WIN32
 #include <errno.h>
 #include <termios.h>
-#include <sys/stat.h>
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
 #ifndef O_CLOEXEC
@@ -57,10 +58,12 @@ enum {
 
 #ifdef HAVE_LIBUDEV
 #include <libudev.h>
+#include <sys/ioctl.h>
 #endif
 
 #include "elist.h"
 #include "logging.h"
+#include "miner.h"
 #include "fpgautils.h"
 
 #define SEARCH_NEEDLES_BEGIN()  {  \

+ 1 - 3
miner.c

@@ -59,9 +59,7 @@
 #include "driver-opencl.h"
 #include "bench_block.h"
 #include "scrypt.h"
-#ifdef USE_AVALON
-  #include "driver-avalon.h"
-#endif
+#include "driver-avalon.h"
 
 #ifdef USE_X6500
 #include "ft232r.h"

+ 6 - 3
miner.h

@@ -289,9 +289,6 @@ struct device_drv {
 	uint64_t (*can_limit_work)(struct thr_info *);
 	bool (*thread_init)(struct thr_info *);
 	bool (*prepare_work)(struct thr_info *, struct work *);
-#ifdef USE_AVALON
-	int64_t (*scanhash_queue)(struct thr_info *, struct work **, int64_t);
-#endif
 	int64_t (*scanhash)(struct thr_info *, struct work *, int64_t);
 	int64_t (*scanwork)(struct thr_info *);
 
@@ -434,6 +431,10 @@ struct cgpu_info {
 		int device_fd;
 #ifdef USE_X6500
 		struct ft232r_device_handle *device_ft232r;
+#endif
+#ifdef USE_AVALON
+	struct work **works;
+	int queued;
 #endif
 	};
 #ifdef USE_BITFORCE
@@ -839,7 +840,9 @@ extern bool opt_restart;
 extern char *opt_icarus_options;
 extern char *opt_icarus_timing;
 extern bool opt_worktime;
+#ifdef USE_AVALON
 extern char *opt_avalon_options;
+#endif
 #ifdef USE_BITFORCE
 extern bool opt_bfl_noncerange;
 #endif