Commit 158e24f938fa716ff5c43804999b288220f57e3d

Adrian Port 2013-11-10T14:45:38

Framework for ntime rolling, keep looking for OP_USB_INIT replies when other packets received

diff --git a/driver-hashfast.c b/driver-hashfast.c
index 7549a83..61fc303 100644
--- a/driver-hashfast.c
+++ b/driver-hashfast.c
@@ -128,14 +128,17 @@ static bool hfa_send_frame(struct cgpu_info *hashfast, uint8_t opcode, uint16_t 
 	return true;
 }
 
-static bool hfa_send_header(struct cgpu_info *hashfast, struct hf_header *h, int cmd)
+/* Send an already assembled packet, consisting of an 8 byte header which may
+ * or may not be followed by a packet body. */
+
+static bool hfa_send_packet(struct cgpu_info *hashfast, struct hf_header *h, int cmd)
 {
 	int amount, ret, len;
 
-	len = sizeof(*h);
+	len = sizeof(*h) + h->data_length*4;
 	ret = usb_write(hashfast, (char *)h, len, &amount, hfa_cmds[cmd].usb_cmd);
 	if (ret < 0 || amount != len) {
-		applog(LOG_WARNING, "HFA%d: send_header: %s USB Send error, ret %d amount %d vs. length %d",
+		applog(LOG_WARNING, "HFA%d: send_packet: %s USB Send error, ret %d amount %d vs. length %d",
 		       hashfast->device_id, hfa_cmds[cmd].cmd_name, ret, amount, len);
 		return false;
 	}
@@ -187,33 +190,58 @@ static bool hfa_get_data(struct cgpu_info *hashfast, char *buf, int len4)
 	return true;
 }
 
+static const char *hf_usb_init_errors[] = {
+        "Success",
+        "Reset timeout",
+        "Address cycle timeout",
+        "Clockgate operation timeout",
+        "Configuration operation timeout",
+        "Excessive core failures",
+        "All cores failed diagnostics",
+        "Too many groups configured - increase ntime roll amount"
+        };
+
+
 static bool hfa_reset(struct cgpu_info *hashfast, struct hashfast_info *info)
 {
 	struct hf_usb_init_header usb_init, *hu = &usb_init;
 	struct hf_usb_init_base *db;
+        struct hf_usb_init_options *ho;
 	char buf[1024];
 	struct hf_header *h = (struct hf_header *)buf;
 	uint8_t hcrc;
 	bool ret;
 	int i;
 
+        // XXX Following items need to be defaults with command-line overrides
 	info->hash_clock_rate = 550;                        // Hash clock rate in Mhz
+        info->group_ntime_roll = 1;
+        info->core_ntime_roll = 1;
+
 	// Assemble the USB_INIT request
 	memset(hu, 0, sizeof(*hu));
 	hu->preamble = HF_PREAMBLE;
 	hu->operation_code = OP_USB_INIT;
 	hu->protocol = PROTOCOL_GLOBAL_WORK_QUEUE;          // Protocol to use
 	hu->hash_clock = info->hash_clock_rate;             // Hash clock rate in Mhz
+        if (info->group_ntime_roll > 1 && info->core_ntime_roll) {
+                ho = (struct hf_usb_init_options *)(hu+1);
+                memset(ho, 0, sizeof(*ho));
+                ho->group_ntime_roll = info->group_ntime_roll;
+                ho->core_ntime_roll = info->core_ntime_roll;
+                hu->data_length = sizeof(*ho)/4;
+        }
 	hu->crc8 = hfa_crc8((uint8_t *)hu);
 	applog(LOG_INFO, "HFA%d: Sending OP_USB_INIT with GWQ protocol specified",
 	       hashfast->device_id);
-
-	if (!hfa_send_header(hashfast, (struct hf_header *)hu, HF_USB_CMD(OP_USB_INIT)))
+        
+	if (!hfa_send_packet(hashfast, (struct hf_header *)hu, HF_USB_CMD(OP_USB_INIT)))
 		return false;
 
 	// Check for the correct response.
 	// We extend the normal timeout - a complete device initialization, including
 	// bringing power supplies up from standby, etc., can take over a second.
+tryagain:
 	for (i = 0; i < 30; i++) {
 		ret = hfa_get_header(hashfast, h, &hcrc);
 		if (ret)
@@ -228,9 +256,12 @@ static bool hfa_reset(struct cgpu_info *hashfast, struct hashfast_info *info)
 		return false;
 	}
 	if (h->operation_code != OP_USB_INIT) {
-		applog(LOG_WARNING, "HFA %d: OP_USB_INIT: Tossing packet, valid but unexpected type", hashfast->device_id);
+                // This can happen if valid packet(s) were in transit *before* the OP_USB_INIT arrived
+                // at the device, so we just toss the packets and keep looking for the response.
+		applog(LOG_WARNING, "HFA %d: OP_USB_INIT: Tossing packet, valid but unexpected type %d",
+                        hashfast->device_id, h->operation_code);
 		hfa_get_data(hashfast, buf, h->data_length);
-		return false;
+		goto tryagain;
 	}
 
 	applog(LOG_DEBUG, "HFA %d: Good reply to OP_USB_INIT", hashfast->device_id);
@@ -286,6 +317,15 @@ static bool hfa_reset(struct cgpu_info *hashfast, struct hashfast_info *info)
 		return false;
 	}
 
+        // See if the initialization suceeded
+        if (db->operation_status) {
+		applog(LOG_WARNING, "HFA %d: OP_USB_INIT failed! Operation status %d (%s)",
+                        hashfast->device_id, db->operation_status,
+                        (db->operation_status < sizeof(hf_usb_init_errors)/sizeof(hf_usb_init_errors[0])) ?
+                            hf_usb_init_errors[db->operation_status] : "Unknown error code");
+		return false;
+        }
+
 	return true;
 }
 
diff --git a/driver-hashfast.h b/driver-hashfast.h
index 6c8efb2..5c8acb0 100644
--- a/driver-hashfast.h
+++ b/driver-hashfast.h
@@ -79,6 +79,8 @@ struct hashfast_info {
 	struct hf_config_data config_data;          // Configuration data used from USB_INIT
 	int core_bitmap_size;                       // in bytes
 	uint32_t *core_bitmap;                      // Core OK bitmap test results, run with PLL Bypassed
+        int group_ntime_roll;                       // Total ntime roll amount per group
+        int core_ntime_roll;                        // Total core ntime roll amount
 
 	pthread_mutex_t lock;
 	struct work **works;