Browse Source

Add --set-device option to allow setting default procset commands

Luke Dashjr 12 years ago
parent
commit
f34678f301
5 changed files with 173 additions and 5 deletions
  1. 1 0
      README
  2. 3 0
      deviceapi.c
  3. 1 1
      driver-nanofury.c
  4. 164 4
      miner.c
  5. 4 0
      miner.h

+ 1 - 0
README

@@ -247,6 +247,7 @@ Options for both config file and command line:
 --sched-start <arg> Set a time of day in HH:MM to start mining (a once off without a stop time)
 --sched-stop <arg>  Set a time of day in HH:MM to stop mining (will quit without a start time)
 --scrypt            Use the scrypt algorithm for mining (non-bitcoin)
+--set-device <arg>  Set default parameters on devices; eg, NFY:osc6_bits=50
 --setuid <arg>      Username of an unprivileged user to run as
 --sharelog <arg>    Append share log to file
 --shares <arg>      Quit after mining N shares (default: unlimited)

+ 3 - 0
deviceapi.c

@@ -603,6 +603,9 @@ void *miner_thread(void *userdata)
 	if (cgpu->deven != DEV_ENABLED)
 		mt_disable_start(mythr);
 	
+	if (drv_ready(cgpu))
+		cgpu_set_defaults(cgpu);
+	
 	thread_reportout(mythr);
 	applog(LOG_DEBUG, "Popping ping in miner thread");
 	notifier_read(mythr->notifier);  // Wait for a notification to start

+ 1 - 1
driver-nanofury.c

@@ -273,7 +273,7 @@ bool nanofury_init(struct thr_info * const thr)
 	bitfury_init_chip(cgpu);
 	
 	timer_set_now(&thr->tv_poll);
-	
+	cgpu->status = LIFE_INIT2;
 	return true;
 }
 

+ 164 - 4
miner.c

@@ -173,6 +173,7 @@ int stratumsrv_port = -1;
 #endif
 
 struct string_elist *scan_devices;
+static struct string_elist *opt_set_device_list;
 bool opt_force_dev_init;
 static bool devices_enabled[MAX_DEVICES];
 static int opt_devs_enabled;
@@ -493,6 +494,83 @@ static void applog_and_exit(const char *fmt, ...)
 	exit(1);
 }
 
+static
+bool cgpu_match(const char * const pattern, const struct cgpu_info * const cgpu)
+{
+	// all - matches anything
+	// d0 - matches all processors of device 0
+	// d0a - matches first processor of device 0
+	// 0 - matches processor 0
+	// ___ - matches all processors on all devices using driver/name ___
+	// ___0 - matches all processors of 0th device using driver/name ___
+	// ___0a - matches first processor of 0th device using driver/name ___
+	if (!strcasecmp(pattern, "all"))
+		return true;
+	
+	const char *p = pattern, *p2;
+	size_t L;
+	int n, i, c = -1;
+	struct cgpu_info *device;
+	
+	while (p[0] && !isdigit(p[0]))
+		++p;
+	
+	L = p - pattern;
+	while (L && isspace(pattern[L-1]))
+		--L;
+	n = strtol(p, (void*)&p2, 0);
+	if (L == 0)
+	{
+		if (!p[0])
+			return true;
+		if (p2 && p2[0])
+			goto invsyntax;
+		if (n >= total_devices)
+			return false;
+		return (cgpu == devices[n]);
+	}
+	
+	if (L > 1 || tolower(pattern[0]) != 'd' || !p[0])
+	{
+		const struct device_drv * const drv = cgpu->drv;
+		if ((L == 3 && !strncasecmp(pattern, drv->name, 3)) ||
+			(L == strlen(drv->dname) && !strncasecmp(pattern, drv->dname, L)))
+			{}  // Matched name or dname
+		else
+			return false;
+		if (p[0] && n != cgpu->device_id)
+			return false;
+		if (p2[0] && strcasecmp(p2, &cgpu->proc_repr[5]))
+			return false;
+		return true;
+	}
+	
+	// d#
+	
+	c = -1;
+	for (i = 0; ; ++i)
+	{
+		if (i == total_devices)
+			return false;
+		if (devices[i]->device != devices[i])
+			continue;
+		if (++c == n)
+			break;
+	}
+	for (device = devices[i]; device; device = device->next_proc)
+	{
+		if (p2 && p2[0] && strcasecmp(p2, &cgpu->proc_repr[5]))
+			continue;
+		if (device == cgpu)
+			return true;
+	}
+	return false;
+
+invsyntax:
+	applog(LOG_WARNING, "%s: Invalid syntax: %s", __func__, pattern);
+	return false;
+}
+
 static pthread_mutex_t sharelog_lock;
 static FILE *sharelog_file = NULL;
 
@@ -862,6 +940,13 @@ static char *add_serial(const char *arg)
 	return NULL;
 }
 
+static
+char *opt_string_elist_add(const char *arg, struct string_elist **elist)
+{
+	string_elist_add(arg, elist);
+	return NULL;
+}
+
 bool get_intrange(const char *arg, int *val1, int *val2)
 {
 	// NOTE: This could be done with sscanf, but its %n is broken in strange ways on Windows
@@ -1798,12 +1883,15 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITHOUT_ARG("--scrypt",
 			opt_set_bool, &opt_scrypt,
 			"Use the scrypt algorithm for mining (non-bitcoin)"),
-#ifdef HAVE_OPENCL
+#endif
+	OPT_WITH_ARG("--set-device",
+			opt_string_elist_add, NULL, &opt_set_device_list,
+			"Set default parameters on devices; eg, NFY:osc6_bits=50"),
+#if defined(USE_SCRYPT) && defined(HAVE_OPENCL)
 	OPT_WITH_ARG("--shaders",
 		     set_shaders, NULL, NULL,
 		     "GPU shaders per card for tuning scrypt, comma separated"),
 #endif
-#endif
 #ifdef HAVE_PWD_H
         OPT_WITH_ARG("--setuid",
                      opt_set_charp, NULL, &opt_setuid,
@@ -9042,6 +9130,73 @@ void proc_enable(struct cgpu_info *cgpu)
 
 #define device_recovered(cgpu)  proc_enable(cgpu)
 
+void cgpu_set_defaults(struct cgpu_info * const cgpu)
+{
+	const struct device_drv * const drv = cgpu->drv;
+	struct string_elist *setstr_elist;
+	const char *p, *p2;
+	char replybuf[0x2000];
+	size_t L;
+	DL_FOREACH(opt_set_device_list, setstr_elist)
+	{
+		const char * const setstr = setstr_elist->string;
+		p = strchr(setstr, ':');
+		if (!p)
+			continue;
+		{
+			L = p - setstr;
+			char pattern[L + 1];
+			if (L)
+				memcpy(pattern, setstr, L);
+			pattern[L] = '\0';
+			if (!cgpu_match(pattern, cgpu))
+				continue;
+		}
+		
+		applog(LOG_DEBUG, "%"PRIpreprv": %s: Matched with set default: %s",
+		       cgpu->proc_repr, __func__, setstr);
+		
+		if (!drv->set_device)
+		{
+			applog(LOG_WARNING, "%"PRIpreprv": set_device is not implemented (trying to apply rule: %s)",
+			       cgpu->proc_repr, setstr);
+			continue;
+		}
+		
+		++p;
+		p2 = strchr(p, '=');
+		if (!p2)
+		{
+			L = strlen(p);
+			p2 = "";
+		}
+		else
+		{
+			L = p2 - p;
+			++p2;
+		}
+		char opt[L + 1];
+		if (L)
+			memcpy(opt, p, L);
+		opt[L] = '\0';
+		
+		L = strlen(p2);
+		char setval[L + 1];
+		if (L)
+			memcpy(setval, p2, L);
+		setval[L] = '\0';
+		
+		p = drv->set_device(cgpu, opt, setval, replybuf);
+		if (p)
+			applog(LOG_WARNING, "%"PRIpreprv": Applying rule %s: %s",
+			       cgpu->proc_repr, setstr, p);
+		else
+			applog(LOG_DEBUG, "%"PRIpreprv": Applied rule %s",
+			       cgpu->proc_repr, setstr);
+	}
+	cgpu->already_set_defaults = true;
+}
+
 /* Makes sure the hashmeter keeps going even if mining threads stall, updates
  * the screen at regular intervals, and restarts threads if they appear to have
  * died. */
@@ -9150,8 +9305,13 @@ void bfg_watchdog(struct cgpu_info * const cgpu, struct timeval * const tvp_now)
 			char *dev_str = cgpu->proc_repr;
 			int gpu;
 
-			if (cgpu->drv->get_stats && likely(drv_ready(cgpu)))
-			  cgpu->drv->get_stats(cgpu);
+			if (likely(drv_ready(cgpu)))
+			{
+				if (unlikely(!cgpu->already_set_defaults))
+					cgpu_set_defaults(cgpu);
+				if (cgpu->drv->get_stats)
+					cgpu->drv->get_stats(cgpu);
+			}
 
 			gpu = cgpu->device_id;
 			denable = &cgpu->deven;

+ 4 - 0
miner.h

@@ -485,6 +485,7 @@ struct cgpu_info {
 	pthread_cond_t	device_cond;
 
 	enum dev_enable deven;
+	bool already_set_defaults;
 	int accepted;
 	int rejected;
 	int stale;
@@ -997,6 +998,8 @@ extern void mt_enable(struct thr_info *thr);
 extern void proc_enable(struct cgpu_info *);
 extern void reinit_device(struct cgpu_info *cgpu);
 
+extern void cgpu_set_defaults(struct cgpu_info *);
+
 #ifdef HAVE_ADL
 extern bool gpu_stats(int gpu, float *temp, int *engineclock, int *memclock, float *vddc, int *activity, int *fanspeed, int *fanpercent, int *powertune);
 extern int set_fanspeed(int gpu, int iFanSpeed);
@@ -1374,6 +1377,7 @@ extern void _wlog(const char *str);
 extern void _wlogprint(const char *str);
 extern int curses_int(const char *query);
 extern char *curses_input(const char *query);
+extern bool drv_ready(struct cgpu_info *);
 extern double stats_elapsed(struct cgminer_stats *);
 #define cgpu_runtime(cgpu)  stats_elapsed(&((cgpu)->cgminer_stats))
 extern double cgpu_utility(struct cgpu_info *);