Merge branch 'master' into nogpu
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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
diff --git a/README b/README
index 025e8e5..78c32cc 100644
--- a/README
+++ b/README
@@ -119,6 +119,7 @@ Basic *nix build instructions:
./autogen.sh # only needed if building from git repo
CFLAGS="-O2 -Wall -march=native" ./configure <options>
+ make
No installation is necessary. You may run cgminer from the build
directory directly, but you may do make install if you wish to install
diff --git a/cgminer.c b/cgminer.c
index b7a8361..4249fa2 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -6233,6 +6233,13 @@ static void fill_queue(struct thr_info *mythr, struct cgpu_info *cgpu, struct de
} while (!drv->queue_full(cgpu));
}
+/* Add a work item to a cgpu's queued hashlist */
+void __add_queued(struct cgpu_info *cgpu, struct work *work)
+{
+ cgpu->queued_count++;
+ HASH_ADD_INT(cgpu->queued_work, id, work);
+}
+
/* This function is for retrieving one work item from the unqueued pointer and
* adding it to the hashtable of queued work. Code using this function must be
* able to handle NULL as a return which implies there is no work available. */
@@ -6243,7 +6250,7 @@ struct work *get_queued(struct cgpu_info *cgpu)
wr_lock(&cgpu->qlock);
if (cgpu->unqueued_work) {
work = cgpu->unqueued_work;
- HASH_ADD_INT(cgpu->queued_work, id, work);
+ __add_queued(cgpu, work);
cgpu->unqueued_work = NULL;
}
wr_unlock(&cgpu->qlock);
@@ -6251,6 +6258,22 @@ struct work *get_queued(struct cgpu_info *cgpu)
return work;
}
+void add_queued(struct cgpu_info *cgpu, struct work *work)
+{
+ wr_lock(&cgpu->qlock);
+ __add_queued(cgpu, work);
+ wr_unlock(&cgpu->qlock);
+}
+
+/* Get fresh work and add it to cgpu's queued hashlist */
+struct work *get_queue_work(struct thr_info *thr, struct cgpu_info *cgpu, int thr_id)
+{
+ struct work *work = get_work(thr, thr_id);
+
+ add_queued(cgpu, work);
+ return work;
+}
+
/* This function is for finding an already queued work item in the
* given que hashtable. Code using this function must be able
* to handle NULL as a return which implies there is no matching work.
diff --git a/driver-bitfury.c b/driver-bitfury.c
index 69f3aca..b177626 100644
--- a/driver-bitfury.c
+++ b/driver-bitfury.c
@@ -210,7 +210,9 @@ static bool bitfury_checkresults(struct thr_info *thr, struct work *work, uint32
int i;
for (i = 0; i < BT_OFFSETS; i++) {
- if (test_nonce(work, nonce + bf_offsets[i])) {
+ uint32_t noffset = nonce + bf_offsets[i];
+
+ if (test_nonce(work, noffset)) {
submit_tested_work(thr, work);
return true;
}
@@ -222,18 +224,18 @@ static int64_t bitfury_scanwork(struct thr_info *thr)
{
struct cgpu_info *bitfury = thr->cgpu;
struct bitfury_info *info = bitfury->device_data;
+ struct work *work, *tmp;
+ int amount, i, aged = 0;
struct timeval tv_now;
- struct work *work;
double nonce_rate;
int64_t ret = 0;
- int amount, i;
char buf[45];
int ms_diff;
- work = get_work(thr, thr->id);
+ work = get_queue_work(thr, bitfury, thr->id);
if (unlikely(thr->work_restart)) {
- free_work(work);
- return 0;
+ work_completed(bitfury, work);
+ goto out;
}
buf[0] = 'W';
@@ -251,7 +253,7 @@ static int64_t bitfury_scanwork(struct thr_info *thr)
}
if (unlikely(thr->work_restart))
- goto cascade;
+ goto out;
/* Now look for the bulk of the previous work results, they will come
* in a batch following the first data. */
@@ -268,41 +270,60 @@ static int64_t bitfury_scanwork(struct thr_info *thr)
};
if (unlikely(thr->work_restart))
- goto cascade;
+ goto out;
/* Send work */
+ cgtime(&work->tv_work_start);
usb_write(bitfury, buf, 45, &amount, C_BF1_REQWORK);
cgtime(&info->tv_start);
+
/* Get response acknowledging work */
usb_read(bitfury, buf, BF1MSGSIZE, &amount, C_BF1_GETWORK);
- /* Only happens on startup */
- if (unlikely(!info->prevwork[BF1ARRAY_SIZE]))
- goto cascade;
-
/* Search for what work the nonce matches in order of likelihood. Last
* entry is end of result marker. */
for (i = 0; i < info->tot - BF1MSGSIZE; i += BF1MSGSIZE) {
+ bool found = false;
uint32_t nonce;
- int j;
/* Ignore state & switched data in results for now. */
memcpy(&nonce, info->buf + i + 3, 4);
nonce = decnonce(nonce);
- for (j = 0; j < BF1ARRAY_SIZE; j++) {
- if (bitfury_checkresults(thr, info->prevwork[j], nonce)) {
+
+ rd_lock(&bitfury->qlock);
+ HASH_ITER(hh, bitfury->queued_work, work, tmp) {
+ if (bitfury_checkresults(thr, work, nonce)) {
info->nonces++;
+ found = true;
break;
}
}
+ rd_unlock(&bitfury->qlock);
+
+ if (!found)
+ inc_hw_errors(thr);
}
info->tot = 0;
- free_work(info->prevwork[BF1ARRAY_SIZE]);
-cascade:
- for (i = BF1ARRAY_SIZE; i > 0; i--)
- info->prevwork[i] = info->prevwork[i - 1];
- info->prevwork[0] = work;
+out:
+ cgtime(&tv_now);
+
+ /* This iterates over the hashlist finding work started more than 6
+ * seconds ago which equates to leaving 5 past work items in the array
+ * to look for results. */
+ wr_lock(&bitfury->qlock);
+ HASH_ITER(hh, bitfury->queued_work, work, tmp) {
+ if (tdiff(&tv_now, &work->tv_work_start) > 6.0) {
+ __work_completed(bitfury, work);
+ aged++;
+ }
+ }
+ wr_unlock(&bitfury->qlock);
+
+ if (aged) {
+ applog(LOG_DEBUG, "%s %d: Aged %d work items", bitfury->drv->name,
+ bitfury->device_id, aged);
+ }
info->cycles++;
info->total_nonces += info->nonces;
diff --git a/driver-bitfury.h b/driver-bitfury.h
index 07e795f..2f09de1 100644
--- a/driver-bitfury.h
+++ b/driver-bitfury.h
@@ -13,14 +13,11 @@
#include "miner.h"
#include "usbutils.h"
-#define BF1ARRAY_SIZE 2
-
struct bitfury_info {
struct cgpu_info *base_cgpu;
uint8_t version;
char product[8];
uint32_t serial;
- struct work *prevwork[BF1ARRAY_SIZE + 1];
char buf[512];
int tot;
int nonces;
diff --git a/miner.h b/miner.h
index f5a012b..bbcff0c 100644
--- a/miner.h
+++ b/miner.h
@@ -1435,7 +1435,10 @@ extern bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce
extern bool submit_noffset_nonce(struct thr_info *thr, struct work *work, uint32_t nonce,
int noffset);
extern struct work *get_work(struct thr_info *thr, const int thr_id);
+extern void __add_queued(struct cgpu_info *cgpu, struct work *work);
extern struct work *get_queued(struct cgpu_info *cgpu);
+extern void add_queued(struct cgpu_info *cgpu, struct work *work);
+extern struct work *get_queue_work(struct thr_info *thr, struct cgpu_info *cgpu, int thr_id);
extern struct work *__find_work_bymidstate(struct work *que, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
extern struct work *find_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
extern struct work *clone_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);