Implement primary scanwork loop submitting work and returning hashrate for hashfast.
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
diff --git a/driver-hashfast.c b/driver-hashfast.c
index 659665e..f6a3cd0 100644
--- a/driver-hashfast.c
+++ b/driver-hashfast.c
@@ -99,8 +99,7 @@ static const struct hf_cmd hf_cmds[] = {
* packet body. */
static bool hashfast_send_frame(struct cgpu_info *hashfast, uint8_t opcode,
- uint8_t chip, uint8_t core, uint16_t hdata,
- uint8_t *data, int len)
+ uint16_t hdata, uint8_t *data, int len)
{
int tx_length, ret, amount, id = hashfast->device_id;
uint8_t packet[256];
@@ -108,8 +107,8 @@ static bool hashfast_send_frame(struct cgpu_info *hashfast, uint8_t opcode,
p->preamble = HF_PREAMBLE;
p->operation_code = opcode;
- p->chip_address = chip;
- p->core_address = core;
+ p->chip_address = HF_GWQ_ADDRESS;
+ p->core_address = 0;
p->hdata = htole16(hdata);
p->data_length = len / 4;
p->crc8 = hf_crc8(packet);
@@ -118,8 +117,6 @@ static bool hashfast_send_frame(struct cgpu_info *hashfast, uint8_t opcode,
memcpy(&packet[sizeof(struct hf_header)], data, len);
tx_length = sizeof(struct hf_header) + len;
- tx_length = sizeof(struct hf_header);
-
ret = usb_write(hashfast, (char *)packet, tx_length, &amount,
hf_cmds[opcode].usb_cmd);
if (unlikely(ret < 0 || amount != tx_length)) {
@@ -389,24 +386,103 @@ static bool hashfast_prepare(struct thr_info *thr)
return true;
}
+/* Figure out how many jobs to send. */
+static int __hashfast_jobs(struct hashfast_info *info)
+{
+ return info->usb_init_base.inflight_target - GWQ_SEQUENCE_DISTANCE(info->hash_sequence, info->device_sequence_tail);
+}
+
+static int hashfast_jobs(struct hashfast_info *info)
+{
+ int ret;
+
+ mutex_lock(&info->lock);
+ ret = __hashfast_jobs(info);
+ mutex_unlock(&info->lock);
+
+ return ret;
+}
+
static int64_t hashfast_scanwork(struct thr_info *thr)
{
struct cgpu_info *hashfast = thr->cgpu;
struct hashfast_info *info = hashfast->device_data;
- bool ret;
+ int64_t hashes;
+ int jobs, ret;
if (unlikely(thr->work_restart)) {
- ret = hashfast_send_frame(hashfast, OP_WORK_RESTART, HF_GWQ_ADDRESS, 0, 0, (uint8_t *)NULL, 0);
- if (unlikely(!ret))
+restart:
+ ret = hashfast_send_frame(hashfast, OP_WORK_RESTART, 0, (uint8_t *)NULL, 0);
+ if (unlikely(!ret)) {
ret = hashfast_reset(hashfast, info);
+ if (unlikely(!ret)) {
+ applog(LOG_ERR, "HFA %d: Failed to reset after write failure, disabling",
+ hashfast->device_id);
+ return -1;
+ }
+ }
+ }
+
+ jobs = hashfast_jobs(info);
+
+ if (!jobs) {
+ ret = restart_wait(thr, 100);
+ if (unlikely(!ret))
+ goto restart;
+ jobs = hashfast_jobs(info);
+ }
+
+ while (jobs > 0) {
+ struct hf_hash_usb op_hash_data;
+ struct work *work;
+ uint64_t intdiff;
+ int i, sequence;
+ uint32_t *p;
+
+ /* This is a blocking function if there's no work */
+ work = get_work(thr, thr->id);
+
+ /* Assemble the data frame and send the OP_HASH packet */
+ memcpy(op_hash_data.midstate, work->midstate, sizeof(op_hash_data.midstate));
+ memcpy(op_hash_data.merkle_residual, work->data + 64, 4);
+ p = (uint32_t *)(work->data + 64 + 4);
+ op_hash_data.timestamp = *p++;
+ op_hash_data.bits = *p++;
+ op_hash_data.nonce_loops = 0;
+
+ /* Set the number of leading zeroes to look for based on diff.
+ * Diff 1 = 32, Diff 2 = 33, Diff 4 = 34 etc. */
+ intdiff = (uint64_t)work->device_diff;
+ for (i = 31; intdiff; i++, intdiff >>= 1);
+ op_hash_data.search_difficulty = i;
+ if ((sequence = info->hash_sequence + 1) >= HF_NUM_SEQUENCE)
+ sequence = 0;
+ ret = hashfast_send_frame(hashfast, OP_HASH, sequence, (uint8_t *)&op_hash_data, sizeof(op_hash_data));
if (unlikely(!ret)) {
- applog(LOG_ERR, "HFA %d: Failed to reset after write failure, disabling",
- hashfast->device_id);
- return -1;
+ ret = hashfast_reset(hashfast, info);
+ if (unlikely(!ret)) {
+ applog(LOG_ERR, "HFA %d: Failed to reset after write failure, disabling",
+ hashfast->device_id);
+ return -1;
+ }
}
+
+ mutex_lock(&info->lock);
+ info->hash_sequence = sequence;
+ *(info->works + info->hash_sequence) = work;
+ jobs = __hashfast_jobs(info);
+ mutex_unlock(&info->lock);
+
+ applog(LOG_DEBUG, "HFA %d: OP_HASH sequence %d search_difficulty %d work_difficulty %g",
+ hashfast->device_id, info->hash_sequence, op_hash_data.search_difficulty, work->work_difficulty);
}
- return 0;
+ mutex_lock(&info->lock);
+ hashes = info->hash_count;
+ info->hash_count = 0;
+ mutex_unlock(&info->lock);
+
+ return hashes;
}
static struct api_data *hashfast_api_stats(struct cgpu_info __maybe_unused *cgpu)
diff --git a/driver-hashfast.h b/driver-hashfast.h
index 47d108d..175800a 100644
--- a/driver-hashfast.h
+++ b/driver-hashfast.h
@@ -18,6 +18,7 @@
#define HASHFAST_MINER_THREADS 1
#define HF_NUM_SEQUENCE 256
+#define GWQ_SEQUENCE_DISTANCE(tx,rx) ((tx)>=(rx)?((tx)-(rx)):(HF_NUM_SEQUENCE+(tx)-(rx)))
// Matching fields for hf_statistics, but large #'s for local accumulation, per-die
struct hf_long_statistics {
@@ -49,6 +50,7 @@ struct hashfast_info {
uint16_t device_sequence_head; // The most recent sequence number the device dispatched
uint16_t device_sequence_tail; // The most recently completed job in the device
uint16_t hash_sequence_tail; // Follows device_sequence_tail around to free work
+ int64_t hash_count;
pthread_t read_thr;
};