Implement reading of a whole hashfast packet from the read thread and parsing it, implementing parsing of gwq status.
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
diff --git a/driver-hashfast.c b/driver-hashfast.c
index c6fe333..1f6f953 100644
--- a/driver-hashfast.c
+++ b/driver-hashfast.c
@@ -267,6 +267,9 @@ static bool hashfast_reset(struct cgpu_info *hashfast, struct hashfast_info *inf
db->hash_clockrate);
applog(LOG_INFO, "HFA %d: inflight_target: %d", hashfast->device_id,
db->inflight_target);
+ applog(LOG_INFO, "HFA %d: sequence_modulus: %d", hashfast->device_id,
+ db->sequence_modulus);
+ info->num_sequence = db->sequence_modulus;
// Now a copy of the config data used
if (!hashfast_get_data(hashfast, (char *)&info->config_data, U32SIZE(info->config_data))) {
@@ -314,7 +317,7 @@ static bool hashfast_detect_common(struct cgpu_info *hashfast)
if (unlikely(!(info->die_statistics)))
quit(1, "Failed to calloc die_statistics");
- info->works = calloc(sizeof(struct work *), HF_NUM_SEQUENCE);
+ info->works = calloc(sizeof(struct work *), info->num_sequence);
if (!info->works)
quit(1, "Failed to calloc info works in hashfast_detect_common");
@@ -358,6 +361,62 @@ static void hashfast_detect(bool hotplug)
usb_detect(&hashfast_drv, hashfast_detect_one_usb);
}
+static bool hashfast_get_packet(struct cgpu_info *hashfast, struct hf_header *h)
+{
+ uint8_t hcrc;
+ bool ret;
+
+ ret = hashfast_get_header(hashfast, h, &hcrc);
+ if (unlikely(!ret))
+ goto out;
+ if (unlikely(h->crc8 != hcrc)) {
+ applog(LOG_WARNING, "HFA %d: Bad CRC %d vs %d, attempting to process anyway",
+ hashfast->device_id, h->crc8, hcrc);
+ }
+ if (h->data_length > 0)
+ ret = hashfast_get_data(hashfast, (char *)(h + 1), h->data_length);
+ if (unlikely(!ret)) {
+ applog(LOG_WARNING, "HFA %d: Failed to get data associated with header",
+ hashfast->device_id);
+ }
+
+out:
+ return ret;
+}
+
+static void hfa_parse_gwq_status(struct cgpu_info *hashfast, struct hashfast_info *info,
+ struct hf_header *h)
+{
+ struct hf_gwq_data *g = (struct hf_gwq_data *)(h + 1);
+ struct work *work;
+
+ applog(LOG_DEBUG, "HFA %d: OP_GWQ_STATUS, device_head %4d tail %4d my tail %4d shed %3d inflight %4d",
+ hashfast->device_id, g->sequence_head, g->sequence_tail, info->hash_sequence_tail,
+ g->shed_count, SEQUENCE_DISTANCE(info->hash_sequence_head,g->sequence_tail));
+
+ mutex_lock(&info->lock);
+ info->hash_count += g->hash_count;
+ info->device_sequence_head = g->sequence_head;
+ info->device_sequence_tail = g->sequence_tail;
+ info->shed_count = g->shed_count;
+ /* Free any work that is no longer required */
+ while (info->device_sequence_tail != info->hash_sequence_tail) {
+ if (++info->hash_sequence_tail >= info->num_sequence)
+ info->hash_sequence_tail = 0;
+ if (unlikely(!(work = info->works[info->hash_sequence_tail]))) {
+ applog(LOG_ERR, "HFA %d: Bad work sequence tail",
+ hashfast->device_id);
+ hashfast->shutdown = true;
+ break;
+ }
+ applog(LOG_DEBUG, "HFA %d: Completing work on hash_sequence_tail %d",
+ hashfast->device_id, info->hash_sequence_tail);
+ free_work(work);
+ info->works[info->hash_sequence_tail] = NULL;
+ }
+ mutex_unlock(&info->lock);
+}
+
static void *hfa_read(void *arg)
{
struct thr_info *thr = (struct thr_info *)arg;
@@ -369,6 +428,24 @@ static void *hfa_read(void *arg)
RenameThread(threadname);
while (likely(!hashfast->shutdown)) {
+ char buf[512];
+ struct hf_header *h = (struct hf_header *)buf;
+ bool ret = hashfast_get_packet(hashfast, h);
+
+ if (unlikely(!ret))
+ continue;
+
+ switch (h->operation_code) {
+ case OP_GWQ_STATUS:
+ hfa_parse_gwq_status(hashfast, info, h);
+ break;
+ case OP_DIE_STATUS:
+ case OP_NONCE:
+ case OP_STATISTICS:
+ case OP_USB_STATS1:
+ default:
+ break;
+ }
}
return NULL;
@@ -393,7 +470,7 @@ static bool hashfast_prepare(struct thr_info *thr)
/* 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);
+ return info->usb_init_base.inflight_target - HF_SEQUENCE_DISTANCE(info->hash_sequence, info->device_sequence_tail);
}
static int hashfast_jobs(struct hashfast_info *info)
@@ -459,7 +536,7 @@ restart:
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)
+ if ((sequence = info->hash_sequence + 1) >= info->num_sequence)
sequence = 0;
ret = hashfast_send_frame(hashfast, OP_HASH, sequence, (uint8_t *)&op_hash_data, sizeof(op_hash_data));
if (unlikely(!ret)) {
diff --git a/driver-hashfast.h b/driver-hashfast.h
index 175800a..5e05533 100644
--- a/driver-hashfast.h
+++ b/driver-hashfast.h
@@ -17,8 +17,7 @@
#include "hf_protocol.h"
#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)))
+#define HF_SEQUENCE_DISTANCE(tx,rx) ((tx)>=(rx)?((tx)-(rx)):(info->num_sequence+(tx)-(rx)))
// Matching fields for hf_statistics, but large #'s for local accumulation, per-die
struct hf_long_statistics {
@@ -35,6 +34,7 @@ struct hashfast_info {
int asic_count; // # of chips in the chain
int core_count; // # of cores per chip
int device_type; // What sort of device this is
+ int num_sequence; // A power of 2. What the sequence number range is.
int ref_frequency; // Reference clock rate
uint16_t hash_sequence; // The next hash sequence # to be sent
struct hf_g1_die_data *die_status; // Array of per-die voltage, current, temperature sensor data
@@ -47,10 +47,12 @@ struct hashfast_info {
pthread_mutex_t lock;
struct work **works;
- 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
+ uint16_t hash_sequence_head; // HOST: The next hash sequence # to be sent
+ uint16_t hash_sequence_tail; // HOST: Follows device_sequence_tail around to free work
+ uint16_t device_sequence_head; // DEVICE: The most recent sequence number the device dispatched
+ uint16_t device_sequence_tail; // DEVICE: The most recently completed job in the device
int64_t hash_count;
+ uint16_t shed_count; // Dynamic copy of #cores device has shed for thermal control
pthread_t read_thr;
};