Commit 581afcf9ab7471b891af005bc8392c10e48c08d3

Con Kolivas 2013-06-21T11:18:00

Use only one cgsem in avalon signalling when the write thread should commit work by reading the status bytes off during an avalon_read, minimising the number of usb calls and resetting from only one place.

diff --git a/driver-avalon.c b/driver-avalon.c
index fb877af..1e71bbc 100644
--- a/driver-avalon.c
+++ b/driver-avalon.c
@@ -233,9 +233,17 @@ static void wait_avalon_ready(struct cgpu_info *avalon)
 	}
 }
 
+#define AVALON_CTS    (1 << 4)
+
+static inline bool avalon_cts(char c)
+{
+	return (c & AVALON_CTS);
+}
+
 static int avalon_read(struct cgpu_info *avalon, unsigned char *buf,
 		       size_t bufsize, int timeout, int ep)
 {
+	struct avalon_info *info = avalon->device_data;
 	size_t total = 0, readsize = bufsize + 2;
 	char readbuf[AVALON_READBUF_SIZE];
 	int err, amount, ofs = 2, cp;
@@ -244,6 +252,15 @@ static int avalon_read(struct cgpu_info *avalon, unsigned char *buf,
 	applog(LOG_DEBUG, "%s%i: Get avalon read got err %d",
 	       avalon->drv->name, avalon->device_id, err);
 
+	if (amount < 2)
+		goto out;
+
+	/* Use the fact that we're reading the status with the buffer to tell
+	 * the write thread it should send more work without needing to call
+	 * avalon_buffer_full directly. */
+	if (avalon_cts(buf[0]))
+		cgsem_post(&info->write_sem);
+
 	/* The first 2 of every 64 bytes are status on FTDIRL */
 	while (amount > 2) {
 		cp = amount - 2;
@@ -254,6 +271,7 @@ static int avalon_read(struct cgpu_info *avalon, unsigned char *buf,
 		amount -= cp + 2;
 		ofs += 64;
 	}
+out:
 	return total;
 }
 
@@ -762,10 +780,7 @@ static void *avalon_get_results(void *userdata)
 		}
 
 		if (unlikely(info->reset)) {
-			/* Tell the write thread it can start the reset */
-			cgsem_post(&info->write_sem);
-			cgsem_wait(&info->read_sem);
-
+			avalon_running_reset(avalon, info);
 			/* Discard anything in the buffer */
 			offset = 0;
 		}
@@ -823,15 +838,8 @@ static void *avalon_send_tasks(void *userdata)
 		struct avalon_task at;
 		int idled = 0;
 
-		wait_avalon_ready(avalon);
-
-		if (unlikely(info->reset)) {
-			/* Wait till read thread tells us it's received the
-			 * reset message */
+		while (avalon_buffer_full(avalon))
 			cgsem_wait(&info->write_sem);
-			avalon_running_reset(avalon, info);
-			cgsem_post(&info->read_sem);
-		}
 
 		mutex_lock(&info->qlock);
 		start_count = avalon->work_array * avalon_get_work_count;
@@ -898,7 +906,6 @@ static bool avalon_prepare(struct thr_info *thr)
 	mutex_init(&info->qlock);
 	if (unlikely(pthread_cond_init(&info->qcond, NULL)))
 		quit(1, "Failed to pthread_cond_init avalon qcond");
-	cgsem_init(&info->read_sem);
 	cgsem_init(&info->write_sem);
 
 	if (pthread_create(&info->read_thr, NULL, avalon_get_results, (void *)avalon))
@@ -925,7 +932,6 @@ static void do_avalon_close(struct thr_info *thr)
 
 	info->no_matching_work = 0;
 
-	cgsem_destroy(&info->read_sem);
 	cgsem_destroy(&info->write_sem);
 }
 
diff --git a/driver-avalon.h b/driver-avalon.h
index b77a330..44a1ce8 100644
--- a/driver-avalon.h
+++ b/driver-avalon.h
@@ -111,7 +111,6 @@ struct avalon_info {
 	pthread_mutex_t lock;
 	pthread_mutex_t qlock;
 	pthread_cond_t qcond;
-	cgsem_t read_sem;
 	cgsem_t write_sem;
 	int nonces;