Browse Source

Merge branch 'master' of https://github.com/ckolivas/cgminer

ckolivas 13 years ago
parent
commit
6a45cbbdfb
10 changed files with 127 additions and 49 deletions
  1. 15 7
      NEWS
  2. 7 0
      README
  3. 59 15
      api.c
  4. 20 13
      cgminer.c
  5. 4 2
      driver-bitforce.c
  6. 3 1
      driver-icarus.c
  7. 3 1
      driver-modminer.c
  8. 9 4
      fpgautils.c
  9. 4 4
      fpgautils.h
  10. 3 2
      miner.h

+ 15 - 7
NEWS

@@ -1,13 +1,20 @@
 Version 2.4.3 - June 14, 2012
 
-- can_roll and should_roll should have no bearing on the cycle period within the miner_thread so remove it.
+- can_roll and should_roll should have no bearing on the cycle period within the
+miner_thread so remove it.
 - Check for strategy being changed to load balance when enabling LPs.
-- Check that all threads on the device that called get_work are waiting on getwork before considering the pool lagging.
-- Iterate over each thread belonging to each device in the hashmeter instead of searching for them now that they're a list.
-- When using rotate pool strategy, ensure we only select from alive enabled pools.
+- Check that all threads on the device that called get_work are waiting on
+getwork before considering the pool lagging.
+- Iterate over each thread belonging to each device in the hashmeter instead of
+searching for them now that they're a list.
+- When using rotate pool strategy, ensure we only select from alive enabled
+pools.
 - Start longpoll from every pool when load balance strategy is in use.
-- Add mandatory and block fields to the work struct. Flag any shares that are detected as blocks as mandatory to submit, along with longpoll work from a previously rejecting pool.
-- Consider the fan optimal if fanspeed is dropping but within the optimal speed window.
+- Add mandatory and block fields to the work struct. Flag any shares that are
+detected as blocks as mandatory to submit, along with longpoll work from a
+previously rejecting pool.
+- Consider the fan optimal if fanspeed is dropping but within the optimal speed
+window.
 - Fix typo in some API messages (succeess/success)
 - api.c MMQ stat bugs
 - Bugfix: Fix warnings when built without libudev support
@@ -17,7 +24,8 @@ Version 2.4.3 - June 14, 2012
 - Bugfix: Honour forceauto parameter in serial_detect functions
 - modminer: Temperature sensor improvements
 - modminer: Make log messages more consistent in format
-- Only adjust GPU speed up if the fanspeed is within the normal fanrange and hasn't been turned to maximum speed under overheat conditions.
+- Only adjust GPU speed up if the fanspeed is within the normal fanrange and
+hasn't been turned to maximum speed under overheat conditions.
 - ModMiner use valid .name
 - New driver: BTCFPGA ModMiner
 - Abstract generally useful FPGA code into fpgautils.c

+ 7 - 0
README

@@ -199,6 +199,8 @@ FPGA mining boards(BitForce, Icarus, ModMiner, Ztex) only options:
 
 --scan-serial|-S <arg> Serial port to probe for FPGA mining device
 
+     This option is only for BitForce, Icarus, and/or ModMiner FPGAs
+
      By default, cgminer will scan for autodetected FPGAs unless at least one
      -S is specified for that driver. If you specify -S and still want cgminer
      to scan, you must also use "-S auto". If you want to prevent cgminer from
@@ -210,6 +212,11 @@ FPGA mining boards(BitForce, Icarus, ModMiner, Ztex) only options:
      On windows <arg> is usually of the format \\.\COMn
        (where n = the correct device number for the FPGA device)
 
+     The official supplied binaries are compiled with support for all FPGAs.
+     To force the code to only attempt detection with a specific driver,
+     prepend the argument with the driver name followed by a colon.
+     For example, "icarus:/dev/ttyUSB0" or "bitforce:\\.\COM5"
+
 For other FPGA details see the FPGA-README
 
 

+ 59 - 15
api.c

@@ -399,21 +399,32 @@ struct CODES {
 	const enum code_parameters params;
 	const char *description;
 } codes[] = {
+#ifdef HAVE_OPENCL
  { SEVERITY_ERR,   MSG_INVGPU,	PARAM_GPUMAX,	"Invalid GPU id %d - range is 0 - %d" },
  { SEVERITY_INFO,  MSG_ALRENA,	PARAM_GPU,	"GPU %d already enabled" },
  { SEVERITY_INFO,  MSG_ALRDIS,	PARAM_GPU,	"GPU %d already disabled" },
  { SEVERITY_WARN,  MSG_GPUMRE,	PARAM_GPU,	"GPU %d must be restarted first" },
  { SEVERITY_INFO,  MSG_GPUREN,	PARAM_GPU,	"GPU %d sent enable message" },
+#endif
  { SEVERITY_ERR,   MSG_GPUNON,	PARAM_NONE,	"No GPUs" },
  { SEVERITY_SUCC,  MSG_POOL,	PARAM_PMAX,	"%d Pool(s)" },
  { SEVERITY_ERR,   MSG_NOPOOL,	PARAM_NONE,	"No pools" },
 
- { SEVERITY_SUCC,  MSG_DEVS,	PARAM_DMAX,	"%d GPU(s)"
+ { SEVERITY_SUCC,  MSG_DEVS,	PARAM_DMAX,
+#ifdef HAVE_OPENCL
+		 	 	 	 	"%d GPU(s)"
+#endif
+#if defined(HAVE_AN_FPGA) && defined(HAVE_OPENCL)
+						" - "
+#endif
 #ifdef HAVE_AN_FPGA
-						" - %d PGA(s)"
+						"%d PGA(s)"
+#endif
+#if defined(WANT_CPUMINE) && (defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA))
+						" - "
 #endif
 #ifdef WANT_CPUMINE
-						" - %d CPU(s)"
+						"%d CPU(s)"
 #endif
  },
 
@@ -427,11 +438,15 @@ struct CODES {
  },
 
  { SEVERITY_SUCC,  MSG_SUMM,	PARAM_NONE,	"Summary" },
+#ifdef HAVE_OPENCL
  { SEVERITY_INFO,  MSG_GPUDIS,	PARAM_GPU,	"GPU %d set disable flag" },
  { SEVERITY_INFO,  MSG_GPUREI,	PARAM_GPU,	"GPU %d restart attempted" },
+#endif
  { SEVERITY_ERR,   MSG_INVCMD,	PARAM_NONE,	"Invalid command" },
  { SEVERITY_ERR,   MSG_MISID,	PARAM_NONE,	"Missing device id parameter" },
+#ifdef HAVE_OPENCL
  { SEVERITY_SUCC,  MSG_GPUDEV,	PARAM_GPU,	"GPU%d" },
+#endif
 #ifdef HAVE_AN_FPGA
  { SEVERITY_ERR,   MSG_PGANON,	PARAM_NONE,	"No PGAs" },
  { SEVERITY_SUCC,  MSG_PGADEV,	PARAM_PGA,	"PGA%d" },
@@ -462,6 +477,7 @@ struct CODES {
  { SEVERITY_ERR,   MSG_INVINT,	PARAM_STR,	"Invalid intensity (%s) - must be '" _DYNAMIC  "' or range " _MIN_INTENSITY_STR " - " _MAX_INTENSITY_STR },
  { SEVERITY_INFO,  MSG_GPUINT,	PARAM_BOTH,	"GPU %d set new intensity to %s" },
  { SEVERITY_SUCC,  MSG_MINECON, PARAM_NONE,	"CGMiner config" },
+#ifdef HAVE_OPENCL
  { SEVERITY_ERR,   MSG_GPUMERR,	PARAM_BOTH,	"Setting GPU %d memoryclock to (%s) reported failure" },
  { SEVERITY_SUCC,  MSG_GPUMEM,	PARAM_BOTH,	"Setting GPU %d memoryclock to (%s) reported success" },
  { SEVERITY_ERR,   MSG_GPUEERR,	PARAM_BOTH,	"Setting GPU %d clock to (%s) reported failure" },
@@ -470,6 +486,7 @@ struct CODES {
  { SEVERITY_SUCC,  MSG_GPUVDDC,	PARAM_BOTH,	"Setting GPU %d vddc to (%s) reported success" },
  { SEVERITY_ERR,   MSG_GPUFERR,	PARAM_BOTH,	"Setting GPU %d fan to (%s) reported failure" },
  { SEVERITY_SUCC,  MSG_GPUFAN,	PARAM_BOTH,	"Setting GPU %d fan to (%s) reported success" },
+#endif
  { SEVERITY_ERR,   MSG_MISFN,	PARAM_NONE,	"Missing save filename parameter" },
  { SEVERITY_ERR,   MSG_BADFN,	PARAM_STR,	"Can't open or create save file '%s'" },
  { SEVERITY_SUCC,  MSG_SAVED,	PARAM_STR,	"Configuration saved to file '%s'" },
@@ -697,9 +714,11 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
 			case PARAM_POOL:
 				sprintf(ptr, codes[i].description, paramid, pools[paramid]->rpc_url);
 				break;
+#ifdef HAVE_OPENCL
 			case PARAM_GPUMAX:
 				sprintf(ptr, codes[i].description, paramid, nDevs - 1);
 				break;
+#endif
 #ifdef HAVE_AN_FPGA
 			case PARAM_PGAMAX:
 				pga = numpgas();
@@ -732,7 +751,10 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
 					cpu = 0;
 #endif
 
-				sprintf(ptr, codes[i].description, nDevs
+				sprintf(ptr, codes[i].description
+#ifdef HAVE_OPENCL
+					, nDevs
+#endif
 #ifdef HAVE_AN_FPGA
 					, pga
 #endif
@@ -786,6 +808,7 @@ static void apiversion(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
 static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
 {
 	char buf[TMPBUFSIZ];
+	int gpucount = 0;
 	int pgacount = 0;
 	int cpucount = 0;
 	char *adlinuse = (char *)NO;
@@ -803,6 +826,10 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
 	const char *adl = NO;
 #endif
 
+#ifdef HAVE_OPENCL
+	gpucount = nDevs;
+#endif
+
 #ifdef HAVE_AN_FPGA
 	pgacount = numpgas();
 #endif
@@ -817,12 +844,12 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
 		? "," JSON_MINECON "{\"GPU Count\":%d,\"PGA Count\":%d,\"CPU Count\":%d,\"Pool Count\":%d,\"ADL\":\"%s\",\"ADL in use\":\"%s\",\"Strategy\":\"%s\",\"Log Interval\":%d,\"Device Code\":\"%s\",\"OS\":\"%s\"}" JSON_CLOSE
 		: _MINECON ",GPU Count=%d,PGA Count=%d,CPU Count=%d,Pool Count=%d,ADL=%s,ADL in use=%s,Strategy=%s,Log Interval=%d,Device Code=%s,OS=%s" SEPSTR,
 
-		nDevs, pgacount, cpucount, total_pools, adl, adlinuse,
+		gpucount, pgacount, cpucount, total_pools, adl, adlinuse,
 		strategies[pool_strategy].s, opt_log_interval, DEVICECODE, OSINFO);
 
 	strcat(io_buffer, buf);
 }
-
+#ifdef HAVE_OPENCL
 static void gpustatus(int gpu, bool isjson)
 {
 	char intensity[20];
@@ -874,7 +901,7 @@ static void gpustatus(int gpu, bool isjson)
 		strcat(io_buffer, buf);
 	}
 }
-
+#endif
 #ifdef HAVE_AN_FPGA
 static void pgastatus(int pga, bool isjson)
 {
@@ -979,14 +1006,19 @@ static void cpustatus(int cpu, bool isjson)
 static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
 {
 	int devcount = 0;
+	int numgpu = 0;
 	int numpga = 0;
 	int i;
 
+#ifdef HAVE_OPENCL
+	numgpu = nDevs;
+#endif
+
 #ifdef HAVE_AN_FPGA
 	numpga = numpgas();
 #endif
 
-	if (nDevs == 0 && opt_n_threads == 0 && numpga == 0) {
+	if (numgpu == 0 && opt_n_threads == 0 && numpga == 0) {
 		strcpy(io_buffer, message(MSG_NODEVS, 0, NULL, isjson));
 		return;
 	}
@@ -998,6 +1030,7 @@ static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, b
 		strcat(io_buffer, JSON_DEVS);
 	}
 
+#ifdef HAVE_OPENCL
 	for (i = 0; i < nDevs; i++) {
 		if (isjson && devcount > 0)
 			strcat(io_buffer, COMMA);
@@ -1006,7 +1039,7 @@ static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, b
 
 		devcount++;
 	}
-
+#endif
 #ifdef HAVE_AN_FPGA
 	if (numpga > 0)
 		for (i = 0; i < numpga; i++) {
@@ -1035,6 +1068,7 @@ static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, b
 		strcat(io_buffer, JSON_CLOSE);
 }
 
+#ifdef HAVE_OPENCL
 static void gpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
 {
 	int id;
@@ -1067,7 +1101,7 @@ static void gpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
 	if (isjson)
 		strcat(io_buffer, JSON_CLOSE);
 }
-
+#endif
 #ifdef HAVE_AN_FPGA
 static void pgadev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
 {
@@ -1342,7 +1376,7 @@ static void summary(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo
 		total_go, local_work, total_ro, new_blocks, total_mhashes_done);
 #endif
 }
-
+#ifdef HAVE_OPENCL
 static void gpuenable(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
 {
 	struct thr_info *thr;
@@ -1443,21 +1477,27 @@ static void gpurestart(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
 
 	strcpy(io_buffer, message(MSG_GPUREI, id, NULL, isjson));
 }
-
+#endif
 static void gpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
 {
 	char buf[TMPBUFSIZ];
+	int numgpu = 0;
+
+#ifdef HAVE_OPENCL
+	numgpu = nDevs;
+#endif
 
 	strcpy(io_buffer, message(MSG_NUMGPU, 0, NULL, isjson));
 
 	sprintf(buf, isjson
 		? "," JSON_GPUS "{\"Count\":%d}" JSON_CLOSE
 		: _GPUS ",Count=%d" SEPSTR,
-		nDevs);
+		numgpu);
 
 	strcat(io_buffer, buf);
 }
 
+
 static void pgacount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
 {
 	char buf[TMPBUFSIZ];
@@ -1732,6 +1772,7 @@ static void removepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
 	rpc_url = NULL;
 }
 
+#ifdef HAVE_OPENCL
 static bool splitgpuvalue(char *param, int *gpu, char **value, bool isjson)
 {
 	int id;
@@ -1766,7 +1807,6 @@ static bool splitgpuvalue(char *param, int *gpu, char **value, bool isjson)
 
 	return true;
 }
-
 static void gpuintensity(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
 {
 	int id;
@@ -1879,7 +1919,7 @@ static void gpuvddc(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo
 	strcpy(io_buffer, message(MSG_NOADL, 0, NULL, isjson));
 #endif
 }
-
+#endif
 void doquit(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
 {
 	if (isjson)
@@ -2144,10 +2184,12 @@ struct CMDS {
 	{ "devs",		devstatus,	false },
 	{ "pools",		poolstatus,	false },
 	{ "summary",		summary,	false },
+#ifdef HAVE_OPENCL
 	{ "gpuenable",		gpuenable,	true },
 	{ "gpudisable",		gpudisable,	true },
 	{ "gpurestart",		gpurestart,	true },
 	{ "gpu",		gpudev,		false },
+#endif
 #ifdef HAVE_AN_FPGA
 	{ "pga",		pgadev,		false },
 	{ "pgaenable",		pgaenable,	true },
@@ -2164,11 +2206,13 @@ struct CMDS {
 	{ "enablepool",		enablepool,	true },
 	{ "disablepool",	disablepool,	true },
 	{ "removepool",		removepool,	true },
+#ifdef HAVE_OPENCL
 	{ "gpuintensity",	gpuintensity,	true },
 	{ "gpumem",		gpumem,		true },
 	{ "gpuengine",		gpuengine,	true },
 	{ "gpufan",		gpufan,		true },
 	{ "gpuvddc",		gpuvddc,	true },
+#endif
 	{ "save",		dosave,		true },
 	{ "quit",		doquit,		true },
 	{ "privileged",		privileged,	true },

+ 20 - 13
cgminer.c

@@ -84,8 +84,6 @@ struct strategies strategies[] = {
 
 static char packagename[255];
 
-int gpu_threads;
-
 bool opt_protocol;
 static bool opt_benchmark;
 static bool have_longpoll;
@@ -107,19 +105,19 @@ static const bool opt_time = true;
 
 #ifdef HAVE_OPENCL
 int opt_dynamic_interval = 7;
+int nDevs;
+int opt_g_threads = 2;
+int gpu_threads;
 #endif
 bool opt_restart = true;
 static bool opt_nogpu;
 
 struct list_head scan_devices;
-int nDevs;
-int opt_g_threads = 2;
 static signed int devices_enabled;
 static bool opt_removedisabled;
 int total_devices;
 struct cgpu_info *devices[MAX_DEVICES];
 bool have_opencl;
-int gpu_threads;
 int opt_n_threads = -1;
 int mining_threads;
 int num_processors;
@@ -1289,7 +1287,9 @@ static char statusline[256];
 static int devcursor, logstart, logcursor;
 /* statusy is where the status window goes up to in cases where it won't fit at startup */
 static int statusy;
+#ifdef HAVE_OPENCL
 struct cgpu_info gpus[MAX_GPUDEVICES]; /* Maximum number apparently possible */
+#endif
 struct cgpu_info *cpus;
 
 #ifdef HAVE_CURSES
@@ -2181,6 +2181,8 @@ static bool stale_work(struct work *work, bool share)
 
 static void check_solve(struct work *work)
 {
+#ifndef MIPSEB
+	/* This segfaults on openwrt */
 	work->block = regeneratehash(work);
 	if (unlikely(work->block)) {
 		work->pool->solved++;
@@ -2188,6 +2190,7 @@ static void check_solve(struct work *work)
 		work->mandatory = true;
 		applog(LOG_NOTICE, "Found block for pool %d!", work->pool);
 	}
+#endif
 }
 
 static void *submit_work_thread(void *userdata)
@@ -2705,12 +2708,12 @@ void write_config(FILE *fcfg)
 		}
 	fputs("\n]\n", fcfg);
 
+#ifdef HAVE_OPENCL
 	if (nDevs) {
 		/* Write GPU device values */
 		fputs(",\n\"intensity\" : \"", fcfg);
 		for(i = 0; i < nDevs; i++)
 			fprintf(fcfg, gpus[i].dynamic ? "%sd" : "%s%d", i > 0 ? "," : "", gpus[i].intensity);
-#ifdef HAVE_OPENCL
 		fputs("\",\n\"vectors\" : \"", fcfg);
 		for(i = 0; i < nDevs; i++)
 			fprintf(fcfg, "%s%d", i > 0 ? "," : "",
@@ -2767,10 +2770,10 @@ void write_config(FILE *fcfg)
 		fputs("\",\n\"temp-target\" : \"", fcfg);
 		for(i = 0; i < nDevs; i++)
 			fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].adl.targettemp);
-#endif
 #endif
 		fputs("\"", fcfg);
 	}
+#endif
 #ifdef HAVE_ADL
 	if (opt_reorder)
 		fprintf(fcfg, ",\n\"gpu-reorder\" : true");
@@ -2824,6 +2827,7 @@ void write_config(FILE *fcfg)
 		fprintf(fcfg, ",\n\"stop-time\" : \"%d:%d\"", schedstop.tm.tm_hour, schedstop.tm.tm_min);
 	if (opt_socks_proxy && *opt_socks_proxy)
 		fprintf(fcfg, ",\n\"socks-proxy\" : \"%s\"", opt_socks_proxy);
+#ifdef HAVE_OPENCL
 	for(i = 0; i < nDevs; i++)
 		if (gpus[i].deven == DEV_DISABLED)
 			break;
@@ -2831,6 +2835,7 @@ void write_config(FILE *fcfg)
 		for (i = 0; i < nDevs; i++)
 			if (gpus[i].deven != DEV_DISABLED)
 				fprintf(fcfg, ",\n\"device\" : \"%d\"", i);
+#endif
 	if (opt_api_allow)
 		fprintf(fcfg, ",\n\"api-allow\" : \"%s\"", opt_api_allow);
 	if (strcmp(opt_api_description, PACKAGE_STRING) != 0)
@@ -3826,6 +3831,8 @@ void *miner_thread(void *userdata)
 	const time_t request_interval = opt_scantime * 2 / 3 ? : 1;
 	unsigned const long request_nonce = MAXTHREADS / 3 * 2;
 	bool requested = false;
+	const bool primary = (!mythr->device_thread) || mythr->primary_thread;
+
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 
 	gettimeofday(&getwork_start, NULL);
@@ -3907,7 +3914,7 @@ void *miner_thread(void *userdata)
 				 * starting of every next thread to try and get
 				 * all devices busy before worrying about
 				 * getting work for their extra threads */
-				if (mythr->device_thread) {
+				if (!primary) {
 					struct timespec rgtp;
 
 					rgtp.tv_sec = 0;
@@ -4893,9 +4900,11 @@ int main(int argc, char *argv[])
 
 	INIT_LIST_HEAD(&scan_devices);
 
+#ifdef HAVE_OPENCL
 	memset(gpus, 0, sizeof(gpus));
 	for (i = 0; i < MAX_GPUDEVICES; i++)
 		gpus[i].dynamic = true;
+#endif
 
 	memset(devices, 0, sizeof(devices));
 
@@ -5002,6 +5011,7 @@ int main(int argc, char *argv[])
 #ifdef HAVE_OPENCL
 	if (!opt_nogpu)
 		opencl_api.api_detect();
+	gpu_threads = 0;
 #endif
 
 #ifdef USE_ICARUS
@@ -5037,7 +5047,6 @@ int main(int argc, char *argv[])
 	}
 
 	mining_threads = 0;
-	gpu_threads = 0;
 	if (devices_enabled) {
 		for (i = 0; i < (int)(sizeof(devices_enabled) * 8) - 1; ++i) {
 			if (devices_enabled & (1 << i)) {
@@ -5221,10 +5230,6 @@ begin_bench:
 	gettimeofday(&total_tv_end, NULL);
 	get_datestamp(datestamp, &total_tv_start);
 
-#ifndef HAVE_OPENCL
-	opt_g_threads = 0;
-#endif
-
 	// Start threads
 	k = 0;
 	for (i = 0; i < total_devices; ++i) {
@@ -5292,6 +5297,7 @@ begin_bench:
 		quit(1, "watchdog thread create failed");
 	pthread_detach(thr->pth);
 
+#ifdef HAVE_OPENCL
 	/* Create reinit gpu thread */
 	gpur_thr_id = mining_threads + 4;
 	thr = &thr_info[gpur_thr_id];
@@ -5300,6 +5306,7 @@ begin_bench:
 		quit(1, "tq_new failed for gpur_thr_id");
 	if (thr_info_create(thr, NULL, reinit_gpu, thr))
 		quit(1, "reinit_gpu thread create failed");
+#endif
 
 	/* Create API socket thread */
 	api_thr_id = mining_threads + 5;

+ 4 - 2
driver-bitforce.c

@@ -53,9 +53,11 @@ static bool bitforce_detect_one(const char *devpath)
 	char *s;
 	char pdevbuf[0x100];
 
+	applog(LOG_DEBUG, "BitForce Detect: Attempting to open %s", devpath);
+
 	int fdDev = BFopen(devpath);
 	if (unlikely(fdDev == -1)) {
-		applog(LOG_DEBUG, "BitForce Detect: Failed to open %s", devpath);
+		applog(LOG_ERR, "BitForce Detect: Failed to open %s", devpath);
 		return false;
 	}
 	BFwrite(fdDev, "ZGX", 3);
@@ -96,7 +98,7 @@ static char bitforce_detect_auto()
 
 static void bitforce_detect()
 {
-	serial_detect_auto("bitforce", bitforce_detect_one, bitforce_detect_auto);
+	serial_detect_auto(bitforce_api.dname, bitforce_detect_one, bitforce_detect_auto);
 }
 
 static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce)

+ 3 - 1
driver-icarus.c

@@ -379,6 +379,8 @@ static bool icarus_detect_one(const char *devpath)
 	unsigned char ob_bin[64], nonce_bin[ICARUS_READ_SIZE];
 	char *nonce_hex;
 
+	applog(LOG_DEBUG, "Icarus Detect: Attempting to open %s", devpath);
+
 	fd = icarus_open2(devpath, true);
 	if (unlikely(fd == -1)) {
 		applog(LOG_ERR, "Icarus Detect: Failed to open %s", devpath);
@@ -444,7 +446,7 @@ static bool icarus_detect_one(const char *devpath)
 
 static void icarus_detect()
 {
-	serial_detect("icarus", icarus_detect_one);
+	serial_detect(icarus_api.dname, icarus_detect_one);
 }
 
 static bool icarus_prepare(struct thr_info *thr)

+ 3 - 1
driver-modminer.c

@@ -103,7 +103,7 @@ modminer_detect_auto()
 static void
 modminer_detect()
 {
-	serial_detect_auto("modminer", modminer_detect_one, modminer_detect_auto);
+	serial_detect_auto(modminer_api.dname, modminer_detect_one, modminer_detect_auto);
 }
 
 #define bailout(...)  return _bailout(-1, modminer, __VA_ARGS__);
@@ -318,6 +318,8 @@ modminer_fpga_init(struct thr_info *thr)
 
 	mutex_unlock(&modminer->device_mutex);
 
+	thr->primary_thread = true;
+
 	return true;
 }
 

+ 9 - 4
fpgautils.c

@@ -119,20 +119,25 @@ serial_autodetect_devserial(detectone_func_t detectone, const char*prodname)
 }
 
 char
-_serial_detect(const char*dnamec, size_t dnamel, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto)
+_serial_detect(const char*dname, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto)
 {
 	if (total_devices == MAX_DEVICES)
 		return 0;
 
 	struct string_elist *iter, *tmp;
-	const char*s;
+	const char*s, *p;
 	bool inhibitauto = false;
 	char found = 0;
+	size_t dnamel = strlen(dname);
 
 	list_for_each_entry_safe(iter, tmp, &scan_devices, list) {
 		s = iter->string;
-		if (!strncmp(dnamec, iter->string, dnamel))
-			s += dnamel;
+		if ((p = strchr(s, ':')) && p[1] != '\0') {
+			size_t plen = p - s;
+			if (plen != dnamel || strncasecmp(s, dname, plen))
+				continue;
+			s = p + 1;
+		}
 		if (!strcmp(s, "auto"))
 			forceauto = true;
 		else

+ 4 - 4
fpgautils.h

@@ -16,13 +16,13 @@
 typedef bool(*detectone_func_t)(const char*);
 typedef char(*autoscan_func_t)();
 
-extern char _serial_detect(const char*dnamec, size_t dnamel, detectone_func_t, autoscan_func_t, bool force_autoscan);
+extern char _serial_detect(const char*dname, detectone_func_t, autoscan_func_t, bool force_autoscan);
 #define serial_detect_fauto(dname, detectone, autoscan)  \
-	_serial_detect(dname ":", sizeof(dname), detectone, autoscan, true)
+	_serial_detect(dname, detectone, autoscan, true)
 #define serial_detect_auto(dname, detectone, autoscan)  \
-	_serial_detect(dname ":", sizeof(dname), detectone, autoscan, false)
+	_serial_detect(dname, detectone, autoscan, false)
 #define serial_detect(dname, detectone)  \
-	_serial_detect(dname ":", sizeof(dname), detectone,     NULL, false)
+	_serial_detect(dname, detectone,     NULL, false)
 extern char serial_autodetect_devserial(detectone_func_t, const char*prodname);
 extern char serial_autodetect_udev     (detectone_func_t, const char*prodname);
 

+ 3 - 2
miner.h

@@ -331,13 +331,13 @@ struct cgpu_info {
 
 	unsigned int max_hashes;
 
+	const char *kname;
+#ifdef HAVE_OPENCL
 	bool mapped;
 	int virtual_gpu;
 	int virtual_adl;
 	int intensity;
 	bool dynamic;
-	const char *kname;
-#ifdef HAVE_OPENCL
 	cl_uint vwidth;
 	size_t work_size;
 	enum cl_kernels kernel;
@@ -391,6 +391,7 @@ struct thread_q {
 struct thr_info {
 	int		id;
 	int		device_thread;
+	bool		primary_thread;
 
 	pthread_t	pth;
 	struct thread_q	*q;