Optimise inner scanhash loop for bf1.
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-bitfury.c b/driver-bitfury.c
index a39fd9a..58839ad 100644
--- a/driver-bitfury.c
+++ b/driver-bitfury.c
@@ -199,50 +199,60 @@ static int64_t bitfury_scanhash(struct thr_info *thr, struct work *work,
{
struct cgpu_info *bitfury = thr->cgpu;
struct bitfury_info *info = bitfury->device_data;
- char sendbuf[45], buf[512];
int64_t hashes = 0;
- int amount, i, tot;
+ char buf[45];
+ int amount, i;
+
+ buf[0] = 'W';
+ memcpy(buf + 1, work->midstate, 32);
+ memcpy(buf + 33, work->data + 64, 12);
+
+ /* New results may spill out from the latest work, making us drop out
+ * too early so read whatever we get for the first half nonce and then
+ * look for the results to prev work. */
+ usb_read_timeout(bitfury, info->buf, 512, &info->tot, 600, C_BFO_GETRES);
+
+ /* Now look for the bulk of the previous work results, they will come
+ * in a batch following the first data. */
+ usb_read_once_timeout(bitfury, info->buf + info->tot, 7, &amount, 1000, C_BFO_GETRES);
+ info->tot += amount;
+ while (amount) {
+ usb_read_once_timeout(bitfury, info->buf + info->tot, 512, &amount, 10, C_BFO_GETRES);
+ info->tot += amount;
+ };
- sendbuf[0] = 'W';
- memcpy(sendbuf + 1, work->midstate, 32);
- memcpy(sendbuf + 33, work->data + 64, 12);
- usb_write(bitfury, sendbuf, 45, &amount, C_BFO_REQWORK);
+ /* Send work */
+ usb_write(bitfury, buf, 45, &amount, C_BFO_REQWORK);
+ /* Get response acknowledging work */
usb_read(bitfury, buf, 7, &amount, C_BFO_GETWORK);
- if (unlikely(!info->prevwork1)) {
- info->prevwork1 = copy_work(work);
- info->prevwork2 = copy_work(work);
- return 0;
- }
-
- usb_read_once_timeout(bitfury, buf, 7, &amount, BF1WAIT, C_BFO_GETRES);
- tot = amount;
- while (amount) {
- usb_read_once_timeout(bitfury, buf + tot, 512, &amount, 10, C_BFO_GETRES);
- tot += amount;
- }
+ /* Only happens on startup */
+ if (unlikely(!info->prevwork2))
+ goto cascade;
- for (i = 0; i < tot; i += 7) {
+ /* Search for what work the nonce matches in order of likelihood. */
+ for (i = 0; i < info->tot; i += 7) {
uint32_t nonce;
/* Ignore state & switched data in results for now. */
- memcpy(&nonce, buf + i + 3, 4);
+ memcpy(&nonce, info->buf + i + 3, 4);
nonce = decnonce(nonce);
if (bitfury_checkresults(thr, info->prevwork1, nonce)) {
hashes += 0xffffffff;
continue;
}
- if (bitfury_checkresults(thr, work, nonce)) {
+ if (bitfury_checkresults(thr, info->prevwork2, nonce)) {
hashes += 0xffffffff;
continue;
}
- if (bitfury_checkresults(thr, info->prevwork2, nonce)) {
+ if (bitfury_checkresults(thr, work, nonce)) {
hashes += 0xffffffff;
continue;
}
}
free_work(info->prevwork2);
+cascade:
info->prevwork2 = info->prevwork1;
info->prevwork1 = copy_work(work);
work->blk.nonce = 0xffffffff;
diff --git a/driver-bitfury.h b/driver-bitfury.h
index 6baa94f..96ec889 100644
--- a/driver-bitfury.h
+++ b/driver-bitfury.h
@@ -19,7 +19,8 @@ struct bitfury_info {
uint32_t serial;
struct work *prevwork1;
struct work *prevwork2;
- char readbuf[512];
+ char buf[512];
+ int tot;
};
#endif /* BITFURY_H */