Check for nothing but consecutive bad results on avalon and reset the FPGA if it happens.
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
diff --git a/driver-avalon.c b/driver-avalon.c
index c9ad8fa..0a63eb3 100644
--- a/driver-avalon.c
+++ b/driver-avalon.c
@@ -222,7 +222,7 @@ static int avalon_send_task(int fd, const struct avalon_task *at,
return ret;
}
-static void avalon_decode_nonce(struct thr_info *thr, struct cgpu_info *avalon,
+static bool avalon_decode_nonce(struct thr_info *thr, struct cgpu_info *avalon,
struct avalon_info *info, struct avalon_result *ar,
struct work *work)
{
@@ -232,7 +232,7 @@ static void avalon_decode_nonce(struct thr_info *thr, struct cgpu_info *avalon,
info->matching_work[work->subid]++;
nonce = htole32(ar->nonce);
applog(LOG_DEBUG, "Avalon: nonce = %0x08x", nonce);
- submit_nonce(thr, work, nonce);
+ return submit_nonce(thr, work, nonce);
}
static int avalon_read(int fd, char *buf, ssize_t len)
@@ -544,7 +544,8 @@ static struct work *avalon_valid_result(struct cgpu_info *avalon, struct avalon_
static void avalon_update_temps(struct cgpu_info *avalon, struct avalon_info *info,
struct avalon_result *ar);
-static void avalon_inc_nvw(struct avalon_info *info, struct thr_info *thr)
+static void avalon_inc_nvw(struct cgpu_info *avalon, struct avalon_info *info,
+ struct thr_info *thr)
{
if (unlikely(info->idle))
return;
@@ -555,6 +556,7 @@ static void avalon_inc_nvw(struct avalon_info *info, struct thr_info *thr)
inc_hw_errors(thr);
mutex_lock(&info->lock);
info->no_matching_work++;
+ avalon->results--;
mutex_unlock(&info->lock);
}
@@ -575,15 +577,22 @@ static void avalon_parse_results(struct cgpu_info *avalon, struct avalon_info *i
found = true;
- mutex_lock(&info->lock);
- if (!(++avalon->results % info->miner_count)) {
- gettemp = true;
- avalon->results = 0;
+ if (avalon_decode_nonce(thr, avalon, info, ar, work)) {
+ mutex_lock(&info->lock);
+ if (avalon->results < 0)
+ avalon->results = 0;
+ if (!(++avalon->results % info->miner_count)) {
+ gettemp = true;
+ avalon->results = 0;
+ }
+ info->nonces++;
+ mutex_unlock(&info->lock);
+ } else {
+ mutex_lock(&info->lock);
+ avalon->results--;
+ mutex_unlock(&info->lock);
}
- info->nonces++;
- mutex_unlock(&info->lock);
- avalon_decode_nonce(thr, avalon, info, ar, work);
if (gettemp)
avalon_update_temps(avalon, info, ar);
break;
@@ -596,12 +605,12 @@ static void avalon_parse_results(struct cgpu_info *avalon, struct avalon_info *i
* work result. */
if (spare < (int)AVALON_READ_SIZE)
return;
- avalon_inc_nvw(info, thr);
+ avalon_inc_nvw(avalon, info, thr);
} else {
spare = AVALON_READ_SIZE + i;
if (i) {
if (i >= (int)AVALON_READ_SIZE)
- avalon_inc_nvw(info, thr);
+ avalon_inc_nvw(avalon, info, thr);
else
applog(LOG_WARNING, "Avalon: Discarding %d bytes from buffer", i);
}
@@ -636,6 +645,15 @@ static void *avalon_get_results(void *userdata)
if (offset >= (int)AVALON_READ_SIZE)
avalon_parse_results(avalon, info, thr, readbuf, &offset);
+ /* Check for nothing but consecutive bad results and reset the
+ * FPGA if necessary */
+ if (unlikely(avalon->results < -info->miner_count)) {
+ applog(LOG_ERR, "AVA%d: %d invalid consecutive results, resetting",
+ avalon->device_id, -avalon->results);
+ avalon_reset(avalon, fd);
+ avalon->results = 0;
+ }
+
if (unlikely(offset + rsize >= AVALON_READBUF_SIZE)) {
/* This should never happen */
applog(LOG_ERR, "Avalon readbuf overflow, resetting buffer");