Browse Source

icarus: Processor detail support

Luke Dashjr 11 years ago
parent
commit
6596f2d3bd
1 changed files with 43 additions and 11 deletions
  1. 43 11
      driver-icarus.c

+ 43 - 11
driver-icarus.c

@@ -313,9 +313,8 @@ static const char *timing_mode_str(enum timing_mode timing_mode)
 }
 
 static
-const char *icarus_set_timing(struct cgpu_info * const proc, const char * const optname, const char * const buf, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+const char *_icarus_set_timing(struct ICARUS_INFO * const info, const char * const repr, const struct device_drv * const drv, const char * const buf)
 {
-	struct ICARUS_INFO * const info = proc->device_data;
 	double Hs;
 	char *eq;
 
@@ -388,7 +387,7 @@ const char *icarus_set_timing(struct cgpu_info * const proc, const char * const
 		int def_read_count = ICARUS_READ_COUNT_TIMING;
 
 		if (info->timing_mode == MODE_DEFAULT) {
-			if (proc->drv == &icarus_drv) {
+			if (drv == &icarus_drv) {
 				info->do_default_detection = 0x10;
 			} else {
 				def_read_count = (int)(info->fullnonce * TIME_FACTOR) - 1;
@@ -405,13 +404,20 @@ const char *icarus_set_timing(struct cgpu_info * const proc, const char * const
 	info->min_data_count = MIN_DATA_COUNT;
 
 	applog(LOG_DEBUG, "%"PRIpreprv": Init: mode=%s read_count=%d limit=%dms Hs=%e",
-		proc->proc_repr,
+		repr,
 		timing_mode_str(info->timing_mode),
 		info->read_count, info->read_count_limit, info->Hs);
 	
 	return NULL;
 }
 
+static
+const char *icarus_set_timing(struct cgpu_info * const proc, const char * const optname, const char * const buf, char * const replybuf, enum bfg_set_device_replytype * const out_success)
+{
+	struct ICARUS_INFO * const info = proc->device_data;
+	return _icarus_set_timing(info, proc->proc_repr, proc->drv, buf);
+}
+
 static uint32_t mask(int work_division)
 {
 	return 0xffffffff / work_division;
@@ -594,6 +600,7 @@ bool icarus_detect_custom(const char *devpath, struct device_drv *api, struct IC
 	if (serial_claim_v(devpath, api))
 		return false;
 
+	_icarus_set_timing(info, api->dname, api, "");
 	if (!info->fpga_count)
 	{
 		if (!info->work_division)
@@ -614,6 +621,7 @@ bool icarus_detect_custom(const char *devpath, struct device_drv *api, struct IC
 	icarus->device_path = strdup(devpath);
 	icarus->device_fd = -1;
 	icarus->threads = 1;
+	icarus->procs = info->fpga_count;
 	icarus->set_device_funcs = icarus_set_device_funcs_live;
 	add_cgpu(icarus);
 
@@ -628,7 +636,6 @@ bool icarus_detect_custom(const char *devpath, struct device_drv *api, struct IC
 	icarus->device_data = info;
 
 	timersub(&tv_finish, &tv_start, &(info->golden_tv));
-	icarus_set_timing(icarus, NULL, "", NULL, NULL);
 
 	return true;
 }
@@ -712,6 +719,18 @@ bool icarus_init(struct thr_info *thr)
 	return true;
 }
 
+static
+struct thr_info *icarus_thread_for_nonce(const struct cgpu_info * const icarus, const uint32_t nonce)
+{
+	struct ICARUS_INFO * const info = icarus->device_data;
+	unsigned proc_id = 0;
+	for (int i = info->work_division, j = 0; i /= 2; ++j)
+		if (nonce & (1 << (31 - j)))
+			proc_id |= (1 << j);
+	const struct cgpu_info * const proc = device_proc_by_id(icarus, proc_id) ?: icarus;
+	return proc->thr[0];
+}
+
 static bool icarus_reopen(struct cgpu_info *icarus, struct icarus_state *state, int *fdp)
 {
 	struct ICARUS_INFO *info = icarus->device_data;
@@ -835,7 +854,7 @@ void handle_identify(struct thr_info * const thr, int ret, const bool was_first_
 			{
 				memcpy(&nonce, nonce_bin, sizeof(nonce));
 				nonce = icarus_nonce32toh(info, nonce);
-				submit_nonce(thr, state->last_work, nonce);
+				submit_nonce(icarus_thread_for_nonce(icarus, nonce), state->last_work, nonce);
 			}
 		}
 	}
@@ -980,7 +999,7 @@ keepwaiting:
 			if (nonce_work == state->last2_work)
 			{
 				// nonce was for the last job; submit and keep processing the current one
-				submit_nonce(thr, nonce_work, nonce);
+				submit_nonce(icarus_thread_for_nonce(icarus, nonce), nonce_work, nonce);
 				goto keepwaiting;
 			}
 			if (info->continue_search)
@@ -988,7 +1007,7 @@ keepwaiting:
 				read_count = info->read_count - ((timer_elapsed_us(&state->tv_workstart, NULL) / (1000000 / TIME_FACTOR)) + 1);
 				if (read_count)
 				{
-					submit_nonce(thr, nonce_work, nonce);
+					submit_nonce(icarus_thread_for_nonce(icarus, nonce), nonce_work, nonce);
 					goto keepwaiting;
 				}
 			}
@@ -1042,7 +1061,7 @@ keepwaiting:
 
 	if (ret == ICA_GETS_OK && !was_hw_error)
 	{
-		submit_nonce(thr, nonce_work, nonce);
+		submit_nonce(icarus_thread_for_nonce(icarus, nonce), nonce_work, nonce);
 		
 		icarus_transition_work(state, work);
 		
@@ -1063,7 +1082,8 @@ keepwaiting:
 		
 		if (ret == ICA_GETS_OK)
 		{
-			inc_hw_errors(thr, state->last_work, nonce);
+			// We can't be sure which processor got the error, but at least this is a decent guess
+			inc_hw_errors(icarus_thread_for_nonce(icarus, nonce), state->last_work, nonce);
 			estimate_hashes -= ICARUS_READ_TIME(info->baud, info->read_size);
 		}
 		
@@ -1233,6 +1253,18 @@ out:
 	if (unlikely(state->identify))
 		handle_identify(thr, ret, was_first_run);
 	
+	int hash_count_per_proc = hash_count / icarus->procs;
+	if (hash_count_per_proc > 0)
+	{
+		for_each_managed_proc(proc, icarus)
+		{
+			struct thr_info * const proc_thr = proc->thr[0];
+			
+			hashes_done2(proc_thr, hash_count_per_proc, NULL);
+			hash_count -= hash_count_per_proc;
+		}
+	}
+	
 	return hash_count;
 }
 
@@ -1314,7 +1346,7 @@ const char *icarus_set_fpga_count(struct cgpu_info * const proc, const char * co
 {
 	struct ICARUS_INFO * const info = proc->device_data;
 	const int fpga_count = atoi(newvalue);
-	if (fpga_count < 1 || fpga_count > info->work_division)
+	if (fpga_count < 1 || (fpga_count > info->work_division && info->work_division))
 		return "Invalid fpga_count: must be >0 and <=work_division";
 	info->fpga_count = fpga_count;
 	return NULL;