Commit 5598e4016fe55072537fb51723f5d0a2201afba4

kanoi 2014-06-25T17:21:30

minion - allow resetting a chip via the API

diff --git a/API-README b/API-README
index d4db726..62d3c47 100644
--- a/API-README
+++ b/API-README
@@ -442,6 +442,7 @@ The list of requests - a (*) means it requires privileged access - and replies:
                               The current options are:
                                AVA+BTB opt=freq val=256 to 1024 - chip frequency
                                BTB opt=millivolts val=1000 to 1400 - corevoltage
+                               MBA opt=reset val=0 to chipcount - reset a chip
 
  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/driver-minion.c b/driver-minion.c
index afabc4e..e87fbd0 100644
--- a/driver-minion.c
+++ b/driver-minion.c
@@ -742,6 +742,7 @@ struct minion_info {
 	uint64_t nonces_recovered[MINION_CHIPS];
 	struct timeval last_reset[MINION_CHIPS];
 	double do_reset[MINION_CHIPS];
+	bool flag_reset[MINION_CHIPS];
 
 	// Work items
 	K_LIST *wfree_list;
@@ -2167,6 +2168,44 @@ unalloc:
 	free(minioncgpu);
 }
 
+static char *minion_set(struct cgpu_info *minioncgpu, char *option, char *setting, char *replybuf)
+{
+	struct minion_info *minioninfo = (struct minion_info *)(minioncgpu->device_data);
+	int chip;
+
+	if (strcasecmp(option, "help") == 0) {
+		sprintf(replybuf, "reset: chip 0-%d",
+				  minioninfo->chips - 1);
+		return replybuf;
+	}
+
+	if (strcasecmp(option, "reset") == 0) {
+		if (!setting || !*setting) {
+			sprintf(replybuf, "missing chip to reset");
+			return replybuf;
+		}
+
+		chip = atoi(setting);
+		if (chip < 0 || chip >= minioninfo->chips) {
+			sprintf(replybuf, "invalid reset: chip '%s' valid range 0-%d",
+					  setting,
+					  minioninfo->chips);
+			return replybuf;
+		}
+
+		if (!minioninfo->has_chip[chip]) {
+			sprintf(replybuf, "unable to reset chip %d - chip disabled",
+					  chip);
+			return replybuf;
+		}
+		minioninfo->flag_reset[chip] = true;
+		return NULL;
+	}
+
+	sprintf(replybuf, "Unknown option: %s", option);
+	return replybuf;
+}
+
 static void minion_identify(__maybe_unused struct cgpu_info *minioncgpu)
 {
 	// flash a led
@@ -3787,11 +3826,25 @@ static void chip_report(struct cgpu_info *minioncgpu)
 					minioninfo->do_reset[chip] = 0.0;
 					memcpy(&(minioninfo->last_reset[chip]), &now, sizeof(now));
 					init_chip(minioncgpu, minioninfo, chip);
+					minioninfo->flag_reset[chip] = false;
 				}
 			}
 		}
 		memcpy(&(minioninfo->chip_chk), &now, sizeof(now));
 	}
+
+	for (chip = 0; chip < (int)MINION_CHIPS; chip++) {
+		if (minioninfo->has_chip[chip]) {
+			if (minioninfo->flag_reset[chip]) {
+				applog(LOG_WARNING, "%s%d: Chip %d flagged - resetting ...",
+						    minioncgpu->drv->name, minioncgpu->device_id,
+						    chip);
+				memcpy(&(minioninfo->last_reset[chip]), &now, sizeof(now));
+				init_chip(minioncgpu, minioninfo, chip);
+				minioninfo->flag_reset[chip] = false;
+			}
+		}
+	}
 }
 
 static int64_t minion_scanwork(__maybe_unused struct thr_info *thr)
@@ -4178,6 +4231,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,
 	.identify_device = minion_identify,
 	.thread_prepare = minion_thread_prepare,
 	.hash_work = hash_queued_work,