From f340c52c88b4e81b6dae16ae280bb757e1ece101 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 19 Oct 2013 18:19:23 +1100 Subject: [PATCH] Implement reading of a whole hashfast packet from the read thread and parsing it, implementing parsing of gwq status. --- driver-hashfast.c | 83 +++++++++++++++++++++++++++++++++++++++++++++-- driver-hashfast.h | 12 ++++--- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/driver-hashfast.c b/driver-hashfast.c index c6fe333f..1f6f9535 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 175800aa..5e055330 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; };