Browse Source

modminer: Split each FPGA into its own logical processor (in the same device still)

Luke Dashjr 13 years ago
parent
commit
66d2a3ab07
1 changed files with 87 additions and 101 deletions
  1. 87 101
      driver-modminer.c

+ 87 - 101
driver-modminer.c

@@ -81,8 +81,8 @@ _bailout(int fd, struct cgpu_info*modminer, int prio, const char *fmt, ...)
 	if (fd != -1)
 		serial_close(fd);
 	if (modminer) {
-		pthread_mutex_t *mutexp = &modminer->device_mutex;
-		modminer->device_fd = -1;
+		pthread_mutex_t *mutexp = &modminer->device->device_mutex;
+		modminer->device->device_fd = -1;
 		mutex_unlock(mutexp);
 	}
 
@@ -140,6 +140,7 @@ modminer_detect_one(const char *devpath)
 	modminer->device_path = strdup(devpath);
 	modminer->device_fd = -1;
 	modminer->deven = DEV_ENABLED;
+	modminer->procs = buf[0];
 	modminer->threads = buf[0];
 	modminer->name = devname;
 	modminer->cutofftemp = 85;
@@ -168,13 +169,13 @@ modminer_detect()
 static bool
 modminer_reopen(struct cgpu_info*modminer)
 {
-	close(modminer->device_fd);
+	close(modminer->device->device_fd);
 	int fd = serial_open(modminer->device_path, 0, 10, true);
 	if (unlikely(-1 == fd)) {
 		applog(LOG_ERR, "%s: Failed to reopen %s", modminer->dev_repr, modminer->device_path);
 		return false;
 	}
-	modminer->device_fd = fd;
+	modminer->device->device_fd = fd;
 	return true;
 }
 #define safebailout() do {  \
@@ -226,7 +227,7 @@ modminer_fpga_upload_bitstream(struct cgpu_info*modminer)
 		return false;
 
 	flen = len;
-	int fd = modminer->device_fd;
+	int fd = modminer->device->device_fd;
 
 	applog(LOG_WARNING, "%s: Programming %s... DO NOT EXIT UNTIL COMPLETE", modminer->dev_repr, modminer->device_path);
 	buf[0] = MODMINER_PROGRAM;
@@ -268,7 +269,7 @@ modminer_device_prepare(struct cgpu_info *modminer)
 	if (unlikely(-1 == fd))
 		bailout(LOG_ERR, "%s: Failed to open %s", modminer->dev_repr, modminer->device_path);
 
-	modminer->device_fd = fd;
+	modminer->device->device_fd = fd;
 	applog(LOG_INFO, "%s: Opened %s", modminer->dev_repr, modminer->device_path);
 
 	struct timeval now;
@@ -283,17 +284,18 @@ modminer_device_prepare(struct cgpu_info *modminer)
 static bool
 modminer_fpga_prepare(struct thr_info *thr)
 {
-	struct cgpu_info *modminer = thr->cgpu;
+	struct cgpu_info *proc = thr->cgpu;
+	struct cgpu_info *modminer = proc->device;
 
 	// Don't need to lock the mutex here, since prepare runs from the main thread before the miner threads start
-	if (modminer->device_fd == -1 && !modminer_device_prepare(modminer))
+	if (modminer->device->device_fd == -1 && !modminer_device_prepare(modminer))
 		return false;
 
 	struct modminer_fpga_state *state;
 	state = thr->cgpu_data = calloc(1, sizeof(struct modminer_fpga_state));
 	dclk_prepare(&state->dclk);
 	state->next_work_cmd[0] = MODMINER_SEND_WORK;
-	state->next_work_cmd[1] = thr->device_thread;  // FPGA id
+	state->next_work_cmd[1] = proc->proc_id;  // FPGA id
 
 	return true;
 }
@@ -303,8 +305,8 @@ modminer_change_clock(struct thr_info*thr, bool needlock, signed char delta)
 {
 	struct cgpu_info*modminer = thr->cgpu;
 	struct modminer_fpga_state *state = thr->cgpu_data;
-	char fpgaid = thr->device_thread;
-	pthread_mutex_t *mutexp = &modminer->device_mutex;
+	char fpgaid = modminer->proc_id;
+	pthread_mutex_t *mutexp = &modminer->device->device_mutex;
 	int fd;
 	unsigned char cmd[6], buf[1];
 	unsigned char clk;
@@ -318,11 +320,11 @@ modminer_change_clock(struct thr_info*thr, bool needlock, signed char delta)
 
 	if (needlock)
 		mutex_lock(mutexp);
-	fd = modminer->device_fd;
+	fd = modminer->device->device_fd;
 	if (6 != write(fd, cmd, 6))
-		bailout2(LOG_ERR, "%s.%u: Error writing (set frequency)", modminer->dev_repr, fpgaid);
+		bailout2(LOG_ERR, "%s: Error writing (set frequency)", modminer->proc_repr);
 	if (serial_read(fd, &buf, 1) != 1)
-		bailout2(LOG_ERR, "%s.%u: Error reading (set frequency)", modminer->dev_repr, fpgaid);
+		bailout2(LOG_ERR, "%s: Error reading (set frequency)", modminer->proc_repr);
 	if (needlock)
 		mutex_unlock(mutexp);
 
@@ -337,16 +339,13 @@ modminer_change_clock(struct thr_info*thr, bool needlock, signed char delta)
 static bool modminer_dclk_change_clock(struct thr_info*thr, int multiplier)
 {
 	struct cgpu_info *modminer = thr->cgpu;
-	char fpgaid = thr->device_thread;
 	struct modminer_fpga_state *state = thr->cgpu_data;
 	uint8_t oldFreq = state->dclk.freqM;
 	signed char delta = (multiplier - oldFreq) * 2;
 	if (unlikely(!modminer_change_clock(thr, true, delta)))
 		return false;
 
-	char repr[0x10];
-	sprintf(repr, "%s.%u", modminer->dev_repr, fpgaid);
-	dclk_msg_freqchange(repr, oldFreq * 2, state->dclk.freqM * 2, NULL);
+	dclk_msg_freqchange(modminer->proc_repr, oldFreq * 2, state->dclk.freqM * 2, NULL);
 	return true;
 }
 
@@ -363,15 +362,15 @@ modminer_reduce_clock(struct thr_info*thr, bool needlock)
 
 static bool _modminer_get_nonce(struct cgpu_info*modminer, char fpgaid, uint32_t*nonce)
 {
-	int fd = modminer->device_fd;
+	int fd = modminer->device->device_fd;
 	char cmd[2] = {MODMINER_CHECK_WORK, fpgaid};
 	
 	if (write(fd, cmd, 2) != 2) {
-		applog(LOG_ERR, "%s: Error writing (get nonce %u)", modminer->dev_repr, fpgaid);
+		applog(LOG_ERR, "%s: Error writing (get nonce)", modminer->proc_repr);
 		return false;
 	}
 	if (4 != serial_read(fd, nonce, 4)) {
-		applog(LOG_ERR, "%s: Short read (get nonce %u)", modminer->dev_repr, fpgaid);
+		applog(LOG_ERR, "%s: Short read (get nonce)", modminer->proc_repr);
 		return false;
 	}
 	
@@ -384,14 +383,14 @@ modminer_fpga_init(struct thr_info *thr)
 	struct cgpu_info *modminer = thr->cgpu;
 	struct modminer_fpga_state *state = thr->cgpu_data;
 	int fd;
-	char fpgaid = thr->device_thread;
-	pthread_mutex_t *mutexp = &modminer->device_mutex;
+	char fpgaid = modminer->proc_id;
+	pthread_mutex_t *mutexp = &modminer->device->device_mutex;
 	uint32_t nonce;
 
 	unsigned char cmd[2], buf[4];
 
 	mutex_lock(mutexp);
-	fd = modminer->device_fd;
+	fd = modminer->device->device_fd;
 	if (fd == -1) {
 		// Died in another thread...
 		mutex_unlock(mutexp);
@@ -401,34 +400,34 @@ modminer_fpga_init(struct thr_info *thr)
 	cmd[0] = MODMINER_GET_USERCODE;
 	cmd[1] = fpgaid;
 	if (write(fd, cmd, 2) != 2)
-		bailout2(LOG_ERR, "%s.%u: Error writing (read USER code)", modminer->dev_repr, fpgaid);
+		bailout2(LOG_ERR, "%s: Error writing (read USER code)", modminer->proc_repr);
 	if (serial_read(fd, buf, 4) != 4)
-		bailout2(LOG_ERR, "%s.%u: Error reading (read USER code)", modminer->dev_repr, fpgaid);
+		bailout2(LOG_ERR, "%s: Error reading (read USER code)", modminer->proc_repr);
 
 	if (memcmp(buf, BISTREAM_USER_ID, 4)) {
-		applog(LOG_ERR, "%s.%u: FPGA not programmed", modminer->dev_repr, fpgaid);
+		applog(LOG_ERR, "%s: FPGA not programmed", modminer->proc_repr);
 		if (!modminer_fpga_upload_bitstream(modminer))
 			return false;
 	} else if (opt_force_dev_init && modminer->status == LIFE_INIT) {
-		applog(LOG_DEBUG, "%s.%u: FPGA is already programmed, but --force-dev-init is set",
-		       modminer->dev_repr, fpgaid);
+		applog(LOG_DEBUG, "%s: FPGA is already programmed, but --force-dev-init is set",
+		       modminer->proc_repr);
 		if (!modminer_fpga_upload_bitstream(modminer))
 			return false;
 	}
 	else
-		applog(LOG_DEBUG, "%s.%u: FPGA is already programmed :)", modminer->dev_repr, fpgaid);
+		applog(LOG_DEBUG, "%s: FPGA is already programmed :)", modminer->proc_repr);
 	state->pdone = 101;
 
 	state->dclk.freqM = MODMINER_MAX_CLOCK / 2 + 1;  // Will be reduced immediately
 	while (1) {
 		if (state->dclk.freqM <= MODMINER_MIN_CLOCK / 2)
-			bailout2(LOG_ERR, "%s.%u: Hit minimum trying to find acceptable frequencies", modminer->dev_repr, fpgaid);
+			bailout2(LOG_ERR, "%s: Hit minimum trying to find acceptable frequencies", modminer->proc_repr);
 		--state->dclk.freqM;
 		if (!modminer_change_clock(thr, false, 0))
 			// MCU rejected assignment
 			continue;
 		if (!_modminer_get_nonce(modminer, fpgaid, &nonce))
-			bailout2(LOG_ERR, "%s.%u: Error detecting acceptable frequencies", modminer->dev_repr, fpgaid);
+			bailout2(LOG_ERR, "%s: Error detecting acceptable frequencies", modminer->proc_repr);
 		if (!memcmp(&nonce, "\x00\xff\xff\xff", 4))
 			// MCU took assignment, but disabled FPGA
 			continue;
@@ -438,10 +437,10 @@ modminer_fpga_init(struct thr_info *thr)
 	state->dclk.freqMaxM = state->dclk.freqM;
 	if (MODMINER_DEF_CLOCK / 2 < state->dclk.freqM) {
 		if (!modminer_change_clock(thr, false, -(state->dclk.freqM * 2 - MODMINER_DEF_CLOCK)))
-			applog(LOG_WARNING, "%s.%u: Failed to set desired initial frequency of %u", modminer->dev_repr, fpgaid, MODMINER_DEF_CLOCK);
+			applog(LOG_WARNING, "%s: Failed to set desired initial frequency of %u", modminer->proc_repr, MODMINER_DEF_CLOCK);
 	}
 	state->dclk.freqMDefault = state->dclk.freqM;
-	applog(LOG_WARNING, "%s.%u: Frequency set to %u MHz (range: %u-%u)", modminer->dev_repr, fpgaid, state->dclk.freqM * 2, MODMINER_MIN_CLOCK, state->dclk.freqMaxM * 2);
+	applog(LOG_WARNING, "%s: Frequency set to %u MHz (range: %u-%u)", modminer->proc_repr, state->dclk.freqM * 2, MODMINER_MIN_CLOCK, state->dclk.freqMaxM * 2);
 
 	mutex_unlock(mutexp);
 
@@ -458,7 +457,7 @@ get_modminer_statline_before(char *buf, struct cgpu_info *modminer)
 	bool havetemp = false;
 	int i;
 
-	char pdone = ((struct modminer_fpga_state*)(modminer->thr[0]->cgpu_data))->pdone;
+	char pdone = ((struct modminer_fpga_state*)(modminer->device->thr[0]->cgpu_data))->pdone;
 	if (pdone != 101) {
 		sprintf(&info[1], "%3d%%", pdone);
 		info[5] = ' ';
@@ -501,8 +500,8 @@ static void modminer_get_temperature(struct cgpu_info *modminer, struct thr_info
 		return;
 #endif
 
-	int fd = modminer->device_fd;
-	int fpgaid = thr->device_thread;
+	int fd = modminer->device->device_fd;
+	int fpgaid = modminer->proc_id;
 	char cmd[2] = {MODMINER_TEMP1, fpgaid};
 	char temperature;
 
@@ -516,8 +515,8 @@ static void modminer_get_temperature(struct cgpu_info *modminer, struct thr_info
 					state->last_cutoff_reduced = now;
 					int oldFreq = state->dclk.freqM;
 					if (modminer_reduce_clock(thr, false))
-						applog(LOG_NOTICE, "%s.%u: Frequency %s from %u to %u MHz (temp: %d)",
-						       modminer->dev_repr, fpgaid,
+						applog(LOG_NOTICE, "%s: Frequency %s from %u to %u MHz (temp: %d)",
+						       modminer->proc_repr,
 						       (oldFreq > state->dclk.freqM ? "dropped" : "raised "),
 						       oldFreq * 2, state->dclk.freqM * 2,
 						       temperature
@@ -539,15 +538,19 @@ static void modminer_get_temperature(struct cgpu_info *modminer, struct thr_info
 
 static bool modminer_get_stats(struct cgpu_info *modminer)
 {
+	pthread_mutex_t *mutexp = &modminer->device->device_mutex;
 	int hottest = 0;
 	bool get_temp = (modminer->deven != DEV_ENABLED);
 	// Getting temperature more efficiently while enabled
-	// NOTE: Don't need to mess with mutex here, since the device is disabled
 	for (int i = modminer->threads; i--; ) {
 		struct thr_info*thr = modminer->thr[i];
 		struct modminer_fpga_state *state = thr->cgpu_data;
 		if (get_temp)
+		{
+			mutex_lock(mutexp);
 			modminer_get_temperature(modminer, thr);
+			mutex_unlock(mutexp);
+		}
 		int temp = state->temp;
 		if (temp > hottest)
 			hottest = temp;
@@ -562,25 +565,24 @@ static struct api_data*
 get_modminer_api_extra_device_status(struct cgpu_info*modminer)
 {
 	struct api_data*root = NULL;
-	static char *k[4] = {"Board0", "Board1", "Board2", "Board3"};
-	int i;
+	struct thr_info*thr = modminer->thr[0];
+	struct modminer_fpga_state *state = thr->cgpu_data;
+	float f;
+	double d;
 
-	for (i = modminer->threads - 1; i >= 0; --i) {
-		struct thr_info*thr = modminer->thr[i];
-		struct modminer_fpga_state *state = thr->cgpu_data;
-		json_t *o = json_object();
-
-		if (state->temp)
-			json_object_set_new(o, "Temperature", json_integer(state->temp));
-		json_object_set_new(o, "Frequency", json_real((double)state->dclk.freqM * 2 * 1000000.));
-		json_object_set_new(o, "Cool Max Frequency", json_real((double)state->dclk.freqMaxM * 2 * 1000000.));
-		json_object_set_new(o, "Max Frequency", json_real((double)state->freqMaxMaxM * 2 * 1000000.));
-		json_object_set_new(o, "Hardware Errors", json_integer(state->bad_share_counter));
-		json_object_set_new(o, "Valid Nonces", json_integer(state->good_share_counter));
-
-		root = api_add_json(root, k[i], o, false);
-		json_decref(o);
+	if (state->temp)
+	{
+		f = state->temp;
+		root = api_add_temp(root, "Temperature", &f, true);
 	}
+	d = (double)state->dclk.freqM * 2 * 1000000.;
+	root = api_add_freq(root, "Frequency", &d, true);
+	d = (double)state->dclk.freqMaxM * 2 * 1000000.;
+	root = api_add_freq(root, "Cool Max Frequency", &d, true);
+	d = (double)state->freqMaxMaxM * 2 * 1000000.;
+	root = api_add_freq(root, "Max Frequency", &d, true);
+	root = api_add_int(root, "Hardware Errors", &state->bad_share_counter, true);
+	root = api_add_int(root, "Valid Nonces", &state->good_share_counter, true);
 
 	return root;
 }
@@ -603,33 +605,32 @@ modminer_start_work(struct thr_info*thr)
 fd_set fds;
 	struct cgpu_info*modminer = thr->cgpu;
 	struct modminer_fpga_state *state = thr->cgpu_data;
-	char fpgaid = thr->device_thread;
-	pthread_mutex_t *mutexp = &modminer->device_mutex;
+	pthread_mutex_t *mutexp = &modminer->device->device_mutex;
 	int fd;
 
 	char buf[1];
 
 	mutex_lock(mutexp);
-	fd = modminer->device_fd;
+	fd = modminer->device->device_fd;
 
 	if (unlikely(fd == -1)) {
 		if (!modminer_reopen(modminer)) {
 			mutex_unlock(mutexp);
 			return false;
 		}
-		fd = modminer->device_fd;
+		fd = modminer->device->device_fd;
 	}
 
 	if (46 != write(fd, state->next_work_cmd, 46))
-		bailout2(LOG_ERR, "%s.%u: Error writing (start work)", modminer->dev_repr, fpgaid);
+		bailout2(LOG_ERR, "%s: Error writing (start work)", modminer->proc_repr);
 	gettimeofday(&state->tv_workstart, NULL);
 	state->hashes = 0;
 	status_read("start work");
 	mutex_unlock(mutexp);
 	if (opt_debug) {
 		char *xdata = bin2hex(state->running_work.data, 80);
-		applog(LOG_DEBUG, "%s.%u: Started work: %s",
-		       modminer->dev_repr, fpgaid, xdata);
+		applog(LOG_DEBUG, "%s: Started work: %s",
+		       modminer->proc_repr, xdata);
 		free(xdata);
 	}
 
@@ -649,8 +650,8 @@ modminer_process_results(struct thr_info*thr)
 {
 	struct cgpu_info*modminer = thr->cgpu;
 	struct modminer_fpga_state *state = thr->cgpu_data;
-	char fpgaid = thr->device_thread;
-	pthread_mutex_t *mutexp = &modminer->device_mutex;
+	char fpgaid = modminer->proc_id;
+	pthread_mutex_t *mutexp = &modminer->device->device_mutex;
 	struct work *work = &state->running_work;
 
 	uint32_t nonce;
@@ -671,14 +672,14 @@ modminer_process_results(struct thr_info*thr)
 			bad = !test_nonce(work, nonce, false);
 			++immediate_nonces;
 			if (!bad)
-				applog(LOG_DEBUG, "%s.%u: Nonce for current  work: %02x%02x%02x%02x",
-				       modminer->dev_repr, fpgaid,
+				applog(LOG_DEBUG, "%s: Nonce for current  work: %02x%02x%02x%02x",
+				       modminer->proc_repr,
 				       NONCE_CHARS(nonce));
 			else
 			if (test_nonce(&state->last_work, nonce, false))
 			{
-				applog(LOG_DEBUG, "%s.%u: Nonce for previous work: %02x%02x%02x%02x",
-				       modminer->dev_repr, fpgaid,
+				applog(LOG_DEBUG, "%s: Nonce for previous work: %02x%02x%02x%02x",
+				       modminer->proc_repr,
 				       NONCE_CHARS(nonce));
 				work = &state->last_work;
 				bad = false;
@@ -689,8 +690,8 @@ modminer_process_results(struct thr_info*thr)
 				submit_nonce(thr, work, nonce);
 			}
 			else {
-				applog(LOG_DEBUG, "%s.%u: Nonce with H not zero  : %02x%02x%02x%02x",
-				       modminer->dev_repr, fpgaid,
+				applog(LOG_DEBUG, "%s: Nonce with H not zero  : %02x%02x%02x%02x",
+				       modminer->proc_repr,
 				       NONCE_CHARS(nonce));
 				++hw_errors;
 				++modminer->hw_errors;
@@ -713,7 +714,7 @@ modminer_process_results(struct thr_info*thr)
 	uint64_t hashes = (uint64_t)state->dclk.freqM * 2 * (((uint64_t)elapsed.tv_sec * 1000000) + elapsed.tv_usec);
 	if (hashes > 0xffffffff)
 	{
-		applog(LOG_WARNING, "%s.%u: Finished work before new one sent", modminer->dev_repr, fpgaid);
+		applog(LOG_WARNING, "%s: Finished work before new one sent", modminer->proc_repr);
 		hashes = 0xffffffff;
 	}
 	if (hashes <= state->hashes)
@@ -784,20 +785,8 @@ static char *modminer_set_device(struct cgpu_info *modminer, char *option, char
 		return replybuf;
 	}
 
-	if (!strncasecmp(option, "clock", 5)) {
-		char repr[0x10];
-		int fpgaid, fpgaid_end, multiplier;
-
-		if (option[5])
-			fpgaid = fpgaid_end = abs(atoi(&option[5]));
-		else {
-			fpgaid = 0;
-			fpgaid_end = modminer->threads - 1;
-		}
-		if (fpgaid >= modminer->threads) {
-			sprintf(replybuf, "invalid fpga: '%s' valid range 0-%d", &option[5], modminer->threads - 1);
-			return replybuf;
-		}
+	if (strcasecmp(option, "clock") == 0) {
+		int multiplier;
 
 		if (!setting || !*setting) {
 			sprintf(replybuf, "missing clock setting");
@@ -812,22 +801,19 @@ static char *modminer_set_device(struct cgpu_info *modminer, char *option, char
 		}
 
 		multiplier = val / 2;
-		for ( ; fpgaid <= fpgaid_end; ++fpgaid) {
-			struct thr_info *thr = modminer->thr[fpgaid];
-			struct modminer_fpga_state *state = thr->cgpu_data;
-			uint8_t oldFreqM = state->dclk.freqM;
-			signed char delta = (multiplier - oldFreqM) * 2;
-			state->dclk.freqMDefault = multiplier;
-			if (unlikely(!modminer_change_clock(thr, true, delta))) {
-				sprintf(replybuf, "Set clock failed: %s.%u",
-				        modminer->dev_repr, fpgaid);
-				return replybuf;
-			}
-
-			sprintf(repr, "%s.%u", modminer->dev_repr, fpgaid);
-			dclk_msg_freqchange(repr, oldFreqM * 2, state->dclk.freqM * 2, " on user request");
+		struct thr_info *thr = modminer->thr[0];
+		struct modminer_fpga_state *state = thr->cgpu_data;
+		uint8_t oldFreqM = state->dclk.freqM;
+		signed char delta = (multiplier - oldFreqM) * 2;
+		state->dclk.freqMDefault = multiplier;
+		if (unlikely(!modminer_change_clock(thr, true, delta))) {
+			sprintf(replybuf, "Set clock failed: %s",
+			        modminer->proc_repr);
+			return replybuf;
 		}
 
+		dclk_msg_freqchange(modminer->proc_repr, oldFreqM * 2, state->dclk.freqM * 2, " on user request");
+
 		return NULL;
 	}