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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
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;