Issue a shutdown prior to a reset command for hfa devices and lock access to reads awaiting the response if the device is already running.
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
diff --git a/driver-hashfast.c b/driver-hashfast.c
index 90667c2..f4d0fa0 100644
--- a/driver-hashfast.c
+++ b/driver-hashfast.c
@@ -457,13 +457,18 @@ tryagain:
return true;
}
-static void hfa_send_shutdown(struct cgpu_info *hashfast)
+static bool hfa_send_shutdown(struct cgpu_info *hashfast)
{
+ bool ret = false;
+
if (hashfast->usbinfo.nodev)
- return;
- hfa_send_frame(hashfast, HF_USB_CMD(OP_USB_SHUTDOWN), 0, NULL, 0);
- /* Wait to allow device to properly shut down. */
- cgsleep_ms(1000);
+ return ret;
+ if (hfa_send_frame(hashfast, HF_USB_CMD(OP_USB_SHUTDOWN), 0, NULL, 0)) {
+ /* Wait to allow device to properly shut down. */
+ cgsleep_ms(1000);
+ ret = true;
+ }
+ return ret;
}
static void hfa_clear_readbuf(struct cgpu_info *hashfast)
@@ -638,6 +643,8 @@ out:
return ret;
}
+static bool hfa_running_reset(struct cgpu_info *hashfast, struct hashfast_info *info);
+
static void hfa_parse_gwq_status(struct cgpu_info *hashfast, struct hashfast_info *info,
struct hf_header *h)
{
@@ -652,8 +659,7 @@ static void hfa_parse_gwq_status(struct cgpu_info *hashfast, struct hashfast_inf
if (unlikely(h->core_address & 0x80)) {
applog(LOG_ERR, "%s %d Thermal overload tripped! Resetting device",
hashfast->drv->name, hashfast->device_id);
- hfa_send_shutdown(hashfast);
- if (hfa_reset(hashfast, info)) {
+ if (hfa_running_reset(hashfast, info)) {
applog(LOG_NOTICE, "%s %d: Succesfully reset, continuing operation",
hashfast->drv->name, hashfast->device_id);
return;
@@ -913,7 +919,11 @@ static void *hfa_read(void *arg)
while (likely(!hashfast->shutdown)) {
char buf[512];
struct hf_header *h = (struct hf_header *)buf;
- bool ret = hfa_get_packet(hashfast, h);
+ bool ret;
+
+ mutex_lock(&info->rlock);
+ ret = hfa_get_packet(hashfast, h);
+ mutex_unlock(&info->rlock);
if (unlikely(hashfast->usbinfo.nodev))
break;
@@ -976,6 +986,7 @@ static bool hfa_prepare(struct thr_info *thr)
struct timeval now;
mutex_init(&info->lock);
+ mutex_init(&info->rlock);
if (pthread_create(&info->read_thr, NULL, hfa_read, (void *)thr))
quit(1, "Failed to pthread_create read thr in hfa_prepare");
@@ -1227,6 +1238,26 @@ dies_only:
}
}
+static bool hfa_running_reset(struct cgpu_info *hashfast, struct hashfast_info *info)
+{
+ bool ret;
+
+ ret = hfa_send_shutdown(hashfast);
+ if (!ret)
+ goto out;
+
+ /* hfa_reset is the only other place we read from the device so we must
+ * inhibit the read thread from reading our response to the
+ * OP_USB_INIT */
+ mutex_lock(&info->rlock);
+ hfa_clear_readbuf(hashfast);
+ ret = hfa_reset(hashfast, info);
+ mutex_unlock(&info->rlock);
+
+out:
+ return ret;
+}
+
static int64_t hfa_scanwork(struct thr_info *thr)
{
struct cgpu_info *hashfast = thr->cgpu;
@@ -1250,7 +1281,7 @@ static int64_t hfa_scanwork(struct thr_info *thr)
applog(LOG_WARNING, "%s %d: Decreasing clock speed to %d with reset",
hashfast->drv->name, hashfast->device_id, info->hash_clock_rate);
}
- ret = hfa_reset(hashfast, info);
+ ret = hfa_running_reset(hashfast, info);
if (!ret) {
applog(LOG_ERR, "%s %d: Failed to reset after hash failure, disabling",
hashfast->drv->name, hashfast->device_id);
@@ -1266,7 +1297,7 @@ restart:
thr->work_restart = false;
ret = hfa_send_frame(hashfast, HF_USB_CMD(OP_WORK_RESTART), 0, (uint8_t *)NULL, 0);
if (unlikely(!ret)) {
- ret = hfa_reset(hashfast, info);
+ ret = hfa_running_reset(hashfast, info);
if (unlikely(!ret)) {
applog(LOG_ERR, "%s %d: Failed to reset after write failure, disabling",
hashfast->drv->name, hashfast->device_id);
@@ -1327,7 +1358,7 @@ restart:
sequence = 0;
ret = hfa_send_frame(hashfast, OP_HASH, sequence, (uint8_t *)&op_hash_data, sizeof(op_hash_data));
if (unlikely(!ret)) {
- ret = hfa_reset(hashfast, info);
+ ret = hfa_running_reset(hashfast, info);
if (unlikely(!ret)) {
applog(LOG_ERR, "%s %d: Failed to reset after write failure, disabling",
hashfast->drv->name, hashfast->device_id);
diff --git a/driver-hashfast.h b/driver-hashfast.h
index e19a990..7e160b6 100644
--- a/driver-hashfast.h
+++ b/driver-hashfast.h
@@ -112,6 +112,7 @@ struct hashfast_info {
int core_ntime_roll; // Total core ntime roll amount
pthread_mutex_t lock;
+ pthread_mutex_t rlock;
struct work **works;
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