Commit 0d72bd9ef6b0cb98a234b1395005fb07427a31c6

kanoi 2014-07-11T20:34:36

minion - make SPI reset more configurable

diff --git a/API-README b/API-README
index c510797..29ee2a5 100644
--- a/API-README
+++ b/API-README
@@ -446,7 +446,9 @@ The list of requests - a (*) means it requires privileged access - and replies:
                                MBA opt=freq val=0-chip:100-1400 - set chip freq
                                MBA opt=ledcount val=0-100 - chip count for led
                                MBA opt=ledlimit val=0-200 - led off below GHs
-                               MBA opt=spireset val=0-9999 - SPI reset sleep ms
+                               MBA opt=spidelay val=0-9999 - SPI per I/O delay
+                               MBA opt=spireset i|s0-9999 - SPI regular reset
+                               MBA opt=spisleep val=0-9999 - SPI reset sleep ms
 
  lcd           LCD            An all-in-one short status summary of the miner
                               e.g. Elapsed,GHS av,GHS 5m,GHS 5s,Temp,
diff --git a/ASIC-README b/ASIC-README
index 938ed74..af04ed9 100644
--- a/ASIC-README
+++ b/ASIC-README
@@ -248,7 +248,9 @@ ASIC SPECIFIC COMMANDS
 --minion-idlecount  Report when IdleCount is >0 or changes
 --minion-noautofreq Disable automatic frequency adjustment
 --minion-overheat   Enable directly halting any chip when the status exceeds 100C
---minion-spireset   Sleep time in milliseconds when doing an SPI reset (default: 200)
+--minion-spidelay   Add a delay in microseconds after each SPI I/O
+--minion-spireset   SPI regular reset: iNNN for I/O count or sNNN for seconds
+--minion-spisleep   Sleep time in milliseconds when doing an SPI reset
 --minion-temp <arg> Set minion chip temperature threshold, single value or comma list, range 120-160 (default: 135C)
 --nfu-bits <arg>    Set nanofury bits for overclocking, range 32-63 (default: 50)
 --rock-freq <arg>   Set RockMiner frequency in MHz, range 125-500 (default: 270)
diff --git a/README b/README
index 9b705a0..5eb776c 100644
--- a/README
+++ b/README
@@ -225,7 +225,9 @@ Options for both config file and command line:
 --minion-ledlimit   Turn off led when chips GHs are below this (default: 90)
 --minion-noautofreq Disable automatic frequency adjustment
 --minion-overheat   Enable directly halting any chip when the status exceeds 100C
---minion-spireset   Sleep time in milliseconds when doing an SPI reset (default: 200)
+--minion-spidelay   Add a delay in microseconds after each SPI I/O
+--minion-spireset   SPI regular reset: iNNN for I/O count or sNNN for seconds
+--minion-spisleep   Sleep time in milliseconds when doing an SPI reset
 --minion-temp <arg> Set minion chip temperature threshold, single value or comma list, range 120-160 (default: 135C)
 --monitor|-m <arg>  Use custom pipe cmd for output messages
 --nfu-bits <arg>    Set nanofury bits for overclocking, range 32-63 (default: 50)
diff --git a/cgminer.c b/cgminer.c
index 1238b95..857a82e 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -254,7 +254,10 @@ int opt_minion_ledcount;
 int opt_minion_ledlimit = 90;
 bool opt_minion_noautofreq;
 bool opt_minion_overheat;
-int opt_minion_spireset = 200;
+int opt_minion_spidelay;
+char *opt_minion_spireset;
+int opt_minion_spisleep = 200;
+int opt_minion_spiusec;
 char *opt_minion_temp;
 #endif
 
@@ -1352,12 +1355,12 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITH_ARG("--minion-chipreport",
 		     set_int_0_to_100, opt_show_intval, &opt_minion_chipreport,
 		     "Seconds to report chip 5min hashrate, range 0-100 (default: 0=disabled)"),
-	OPT_WITH_ARG("--minion-freq",
-		     opt_set_charp, NULL, &opt_minion_freq,
-		     "Set minion chip frequencies in MHz, single value or comma list, range 100-1400 (default: 1200)"),
 	OPT_WITH_ARG("--minion-cores",
 		     opt_set_charp, NULL, &opt_minion_cores,
 		     opt_hidden),
+	OPT_WITH_ARG("--minion-freq",
+		     opt_set_charp, NULL, &opt_minion_freq,
+		     "Set minion chip frequencies in MHz, single value or comma list, range 100-1400 (default: 1200)"),
 	OPT_WITHOUT_ARG("--minion-idlecount",
 		     opt_set_bool, &opt_minion_idlecount,
 		     "Report when IdleCount is >0 or changes"),
@@ -1373,9 +1376,18 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITHOUT_ARG("--minion-overheat",
 		     opt_set_bool, &opt_minion_overheat,
 		     "Enable directly halting any chip when the status exceeds 100C"),
+	OPT_WITH_ARG("--minion-spidelay",
+		     set_int_0_to_9999, opt_show_intval, &opt_minion_spidelay,
+		     "Add a delay in microseconds after each SPI I/O"),
 	OPT_WITH_ARG("--minion-spireset",
-		     set_int_0_to_9999, opt_show_intval, &opt_minion_spireset,
-		     "Sleep time in milliseconds when doing an SPI reset (default: 200)"),
+		     opt_set_charp, NULL, &opt_minion_spireset,
+		     "SPI regular reset: iNNN for I/O count or sNNN for seconds"),
+	OPT_WITH_ARG("--minion-spisleep",
+		     set_int_0_to_9999, opt_show_intval, &opt_minion_spisleep,
+		     "Sleep time in milliseconds when doing an SPI reset"),
+	OPT_WITH_ARG("--minion-spiusec",
+		     set_int_0_to_9999, NULL, &opt_minion_spiusec,
+		     opt_hidden),
 	OPT_WITH_ARG("--minion-temp",
 		     opt_set_charp, NULL, &opt_minion_temp,
 		     "Set minion chip temperature threshold, single value or comma list, range 120-160 (default: 135C)"),
diff --git a/driver-minion.c b/driver-minion.c
index 48f3d2d..29332a5 100644
--- a/driver-minion.c
+++ b/driver-minion.c
@@ -734,6 +734,11 @@ struct minion_info {
 	char gpiointvalue[64];
 	int gpiointfd;
 
+	// I/O or seconds
+	bool spi_reset_io;
+	int spi_reset_count;
+	time_t last_spi_reset;
+
 	// TODO: need to track disabled chips - done?
 	int chips;
 	bool has_chip[MINION_CHIPS];
@@ -1186,7 +1191,7 @@ static int __do_ioctl(struct cgpu_info *minioncgpu, struct minion_info *minionin
 	else
 		return MINION_OVERSIZE_TASK;
 
-	tran.delay_usecs = 0;
+	tran.delay_usecs = opt_minion_spiusec;
 	tran.speed_hz = MINION_SPI_SPEED;
 
 #if MINION_SHOW_IO
@@ -1226,7 +1231,24 @@ static int __do_ioctl(struct cgpu_info *minioncgpu, struct minion_info *minionin
 		}
 		if (fail)
 			minion_init_spi(minioncgpu, minioninfo, 0, 0, true);
+	} else if (minioninfo->spi_reset_count) {
+		if (minioninfo->spi_reset_io) {
+			if (*ioseq > 0 && (*ioseq % minioninfo->spi_reset_count) == 0)
+				minion_init_spi(minioncgpu, minioninfo, 0, 0, true);
+		} else {
+			if (minioninfo->last_spi_reset == 0L)
+				minioninfo->last_spi_reset = time(NULL);
+			else {
+				time_t now = time(NULL);
+				if ((now - minioninfo->last_spi_reset) >= minioninfo->spi_reset_count) {
+					minioninfo->last_spi_reset = now;
+					minion_init_spi(minioncgpu, minioninfo, 0, 0, true);
+				}
+			}
+		}
 	}
+	if (opt_minion_spidelay)
+		cgsleep_ms(opt_minion_spidelay);
 	mutex_unlock(&(minioninfo->spi_lock));
 	IO_STAT_NOW(&lfin);
 	IO_STAT_NOW(&tsd);
@@ -1757,7 +1779,8 @@ static bool minion_init_spi(struct cgpu_info *minioncgpu, struct minion_info *mi
 	if (reset) {
 		// TODO: maybe slow it down?
 		close(minioninfo->spifd);
-		cgsleep_ms(opt_minion_spireset);
+		if (opt_minion_spisleep)
+			cgsleep_ms(opt_minion_spisleep);
 		minioninfo->spifd = open(minioncgpu->device_path, O_RDWR);
 		if (minioninfo->spifd < 0)
 			goto bad_out;
@@ -2041,6 +2064,33 @@ static void minion_process_options(struct minion_info *minioninfo)
 	int i, core1, core2;
 	bool cleared;
 
+	if (opt_minion_spireset && *opt_minion_spireset) {
+		bool is_io = true;
+		int val;
+
+		switch (tolower(*opt_minion_spireset)) {
+			case 'i':
+				is_io = true;
+				break;
+			case 's':
+				is_io = false;
+				break;
+			default:
+				applog(LOG_WARNING, "ERR: Invalid SPI reset '%s'",
+						    opt_minion_spireset);
+				goto skip;
+		}
+		val = atoi(opt_minion_spireset+1);
+		if (val < 0 || val > 9999) {
+			applog(LOG_WARNING, "ERR: Invalid SPI reset '%s'",
+					    opt_minion_spireset);
+		} else {
+			minioninfo->spi_reset_io = is_io;
+			minioninfo->spi_reset_count = val;
+			minioninfo->last_spi_reset = time(NULL);
+		}
+	}
+skip:
 	last_freq = MINION_FREQ_DEF;
 	if (opt_minion_freq && *opt_minion_freq) {
 		buf = freq = strdup(opt_minion_freq);
@@ -2295,7 +2345,7 @@ unalloc:
 	free(minioncgpu);
 }
 
-static char *minion_set(struct cgpu_info *minioncgpu, char *option, char *setting, char *replybuf)
+static char *minion_api_set(struct cgpu_info *minioncgpu, char *option, char *setting, char *replybuf)
 {
 	struct minion_info *minioninfo = (struct minion_info *)(minioncgpu->device_data);
 	int chip, val;
@@ -2304,7 +2354,8 @@ static char *minion_set(struct cgpu_info *minioncgpu, char *option, char *settin
 	if (strcasecmp(option, "help") == 0) {
 		sprintf(replybuf, "reset: chip 0-%d freq: 0-%d:%d-%d "
 				  "ledcount: 0-100 ledlimit: 0-200 "
-				  "spireset: 0-9999",
+				  "spidelay: 0-9999 spireset i|s0-9999 "
+				  "spisleep: 0-9999",
 				  minioninfo->chips - 1,
 				  minioninfo->chips - 1,
 				  MINION_FREQ_MIN, MINION_FREQ_MAX);
@@ -2416,20 +2467,88 @@ static char *minion_set(struct cgpu_info *minioncgpu, char *option, char *settin
 		return NULL;
 	}
 
+	if (strcasecmp(option, "spidelay") == 0) {
+		if (!setting || !*setting) {
+			sprintf(replybuf, "missing spidelay value");
+			return replybuf;
+		}
+
+		val = atoi(setting);
+		if (val < 0 || val > 9999) {
+			sprintf(replybuf, "invalid spidelay: ms '%s' valid range 0-9999",
+					  setting);
+			return replybuf;
+		}
+
+		opt_minion_spidelay = val;
+		return NULL;
+	}
+
 	if (strcasecmp(option, "spireset") == 0) {
+		bool is_io = true;
+
 		if (!setting || !*setting) {
 			sprintf(replybuf, "missing spireset value");
 			return replybuf;
 		}
 
+		switch (tolower(*setting)) {
+			case 'i':
+				is_io = true;
+				break;
+			case 's':
+				is_io = false;
+				break;
+			default:
+				sprintf(replybuf, "invalid spireset: '%s' must start with i or s",
+						  setting);
+				return replybuf;
+		}
+		val = atoi(setting+1);
+		if (val < 0 || val > 9999) {
+			sprintf(replybuf, "invalid spireset: %c '%s' valid range 0-9999",
+					  *setting, setting+1);
+			return replybuf;
+		}
+
+		minioninfo->spi_reset_io = is_io;
+		minioninfo->spi_reset_count = val;
+		minioninfo->last_spi_reset = time(NULL);
+
+		return NULL;
+	}
+
+	if (strcasecmp(option, "spisleep") == 0) {
+		if (!setting || !*setting) {
+			sprintf(replybuf, "missing spisleep value");
+			return replybuf;
+		}
+
+		val = atoi(setting);
+		if (val < 0 || val > 9999) {
+			sprintf(replybuf, "invalid spisleep: ms '%s' valid range 0-9999",
+					  setting);
+			return replybuf;
+		}
+
+		opt_minion_spisleep = val;
+		return NULL;
+	}
+
+	if (strcasecmp(option, "spiusec") == 0) {
+		if (!setting || !*setting) {
+			sprintf(replybuf, "missing spiusec value");
+			return replybuf;
+		}
+
 		val = atoi(setting);
 		if (val < 0 || val > 9999) {
-			sprintf(replybuf, "invalid spireset: ms '%s' valid range 0-9999",
+			sprintf(replybuf, "invalid spiusec: '%s' valid range 0-9999",
 					  setting);
 			return replybuf;
 		}
 
-		opt_minion_spireset = val;
+		opt_minion_spiusec = val;
 		return NULL;
 	}
 
@@ -4719,7 +4838,7 @@ struct device_drv minion_drv = {
 #ifdef LINUX
 	.get_api_stats = minion_api_stats,
 	.get_statline_before = minion_get_statline_before,
-	.set_device = minion_set,
+	.set_device = minion_api_set,
 	.identify_device = minion_identify,
 	.thread_prepare = minion_thread_prepare,
 	.hash_work = hash_queued_work,
diff --git a/miner.h b/miner.h
index 3e6f08a..8e1c71b 100644
--- a/miner.h
+++ b/miner.h
@@ -1028,7 +1028,10 @@ extern int opt_minion_ledcount;
 extern int opt_minion_ledlimit;
 extern bool opt_minion_noautofreq;
 extern bool opt_minion_overheat;
-extern int opt_minion_spireset;
+extern int opt_minion_spidelay;
+extern char *opt_minion_spireset;
+extern int opt_minion_spisleep;
+extern int opt_minion_spiusec;
 extern char *opt_minion_temp;
 #endif
 #ifdef USE_USBUTILS