Commit 6a45cbbdfbb83491a0a228c9093f4d766be15dd3

ckolivas 2012-06-23T23:45:08

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

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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
diff --git a/NEWS b/NEWS
index 40d5255..c9a9d3a 100644
--- a/NEWS
+++ b/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
diff --git a/README b/README
index fac8e6f..862ec54 100644
--- a/README
+++ b/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
 
 
diff --git a/api.c b/api.c
index d8ddde3..7eb684d 100644
--- a/api.c
+++ b/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 },
diff --git a/cgminer.c b/cgminer.c
index 3f315d8..7b6b436 100644
--- a/cgminer.c
+++ b/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 ? "," : "",
@@ -2768,9 +2771,9 @@ void write_config(FILE *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;
diff --git a/driver-bitforce.c b/driver-bitforce.c
index aa22dee..08595a7 100644
--- a/driver-bitforce.c
+++ b/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)
diff --git a/driver-icarus.c b/driver-icarus.c
index ee9800c..a463c28 100644
--- a/driver-icarus.c
+++ b/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)
diff --git a/driver-modminer.c b/driver-modminer.c
index 0afce2d..2f8ee11 100644
--- a/driver-modminer.c
+++ b/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;
 }
 
diff --git a/fpgautils.c b/fpgautils.c
index 783015a..70387c6 100644
--- a/fpgautils.c
+++ b/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
diff --git a/fpgautils.h b/fpgautils.h
index 91ccb30..c45183b 100644
--- a/fpgautils.h
+++ b/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);
 
diff --git a/miner.h b/miner.h
index 8675195..b1840e9 100644
--- a/miner.h
+++ b/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;