Commit aba64735bb562f5148cd8bc7a4d158d294907f23

kanoi 2014-07-08T19:29:53

Merge pull request #625 from kanoi/master minion - 'reset' SPI when getting errors & mutex lock getaddrinfo

diff --git a/cgminer.c b/cgminer.c
index b0330b3..c783327 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -306,6 +306,7 @@ static pthread_mutex_t sshare_lock;
 pthread_rwlock_t netacc_lock;
 pthread_rwlock_t mining_thr_lock;
 pthread_rwlock_t devices_lock;
+pthread_mutex_t getaddr_lock;
 
 static pthread_mutex_t lp_lock;
 static pthread_cond_t lp_cond;
@@ -9261,6 +9262,7 @@ int main(int argc, char *argv[])
 	rwlock_init(&netacc_lock);
 	rwlock_init(&mining_thr_lock);
 	rwlock_init(&devices_lock);
+	mutex_init(&getaddr_lock);
 
 	mutex_init(&lp_lock);
 	if (unlikely(pthread_cond_init(&lp_cond, NULL)))
diff --git a/driver-minion.c b/driver-minion.c
index 876ab2c..2bb3831 100644
--- a/driver-minion.c
+++ b/driver-minion.c
@@ -67,8 +67,11 @@ static int minion_memory_addr = BCM2835_GPIO_BASE;
 #define MINION_SPI_BUS 0
 #define MINION_SPI_CHIP 0
 
-//#define MINION_SPI_SPEED 2000000
+#if MINION_ROCKCHIP == 0
 #define MINION_SPI_SPEED 8000000
+#else
+#define MINION_SPI_SPEED 500000
+#endif
 #define MINION_SPI_BUFSIZ 1024
 
 static struct minion_select_pins {
@@ -709,6 +712,7 @@ static double time_bands[] = { 0.1, 0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0 };
 #define TIME_BANDS ((int)(sizeof(time_bands)/sizeof(double)))
 
 struct minion_info {
+	struct thr_info *thr;
 	struct thr_info spiw_thr;
 	struct thr_info spir_thr;
 	struct thr_info res_thr;
@@ -1120,11 +1124,14 @@ static void init_pins(struct minion_info *minioninfo)
 
 #define EXTRA_LOG_IO 0
 
-static int __do_ioctl(struct minion_info *minioninfo, int pin, uint8_t *obuf,
-		      uint32_t osiz, uint8_t *rbuf, uint32_t rsiz,
-		      uint64_t *ioseq, MINION_FFL_ARGS)
+static bool minion_init_spi(struct cgpu_info *minioncgpu, struct minion_info *minioninfo, int bus, int chip, bool reset);
+
+static int __do_ioctl(struct cgpu_info *minioncgpu, struct minion_info *minioninfo,
+		      int pin, uint8_t *obuf, uint32_t osiz, uint8_t *rbuf,
+		      uint32_t rsiz, uint64_t *ioseq, MINION_FFL_ARGS)
 {
 	struct spi_ioc_transfer tran;
+	bool fail = false;
 	int ret;
 #if MINION_SHOW_IO
 	char dataw[DATA_ALL], datar[DATA_ALL];
@@ -1197,12 +1204,31 @@ static int __do_ioctl(struct minion_info *minioninfo, int pin, uint8_t *obuf,
 		// Pin back high after I/O
 		set_pin(minioninfo, pin, true);
 	}
+	if (ret >= 0 && rbuf[0] == 0xff && rbuf[ret-1] == 0xff &&
+	    obuf[1] == READ_ADDR(MINION_RES_DATA)) {
+		int i;
+		fail = true;
+		for (i = 1; i < ret-2; i++) {
+			if (rbuf[i] != 0xff) {
+				fail = false;
+				break;
+			}
+		}
+		if (fail)
+			minion_init_spi(minioncgpu, minioninfo, 0, 0, true);
+	}
 	mutex_unlock(&(minioninfo->spi_lock));
 	IO_STAT_NOW(&lfin);
 	IO_STAT_NOW(&tsd);
 
 	IO_STAT_STORE(&sta, &fin, &lsta, &lfin, &tsd, obuf, osiz, ret, 1);
 
+	if (fail) {
+		applog(LOG_ERR, "%s%d: ioctl %"PRIu64" returned all 0xff - resetting",
+				minioncgpu->drv->name, minioncgpu->device_id,
+				*ioseq);
+	}
+
 #if MINION_SHOW_IO
 	if (ret > 0) {
 		buf = bin2hex((unsigned char *)&(datar[DATA_OFF]), ret);
@@ -1254,7 +1280,7 @@ static int __do_ioctl(struct minion_info *minioninfo, int pin, uint8_t *obuf,
 
 #if 1
 #define do_ioctl(_pin, _obuf, _osiz, _rbuf, _rsiz, _ioseq) \
-		__do_ioctl(minioninfo, _pin, _obuf, _osiz, _rbuf, \
+		__do_ioctl(minioncgpu, minioninfo, _pin, _obuf, _osiz, _rbuf, \
 			   _rsiz, _ioseq, MINION_FFL_HERE)
 #else
 #define do_ioctl(_pin, _obuf, _osiz, _rbuf, _rsiz, _ioseq) \
@@ -1273,9 +1299,9 @@ static int _do_ioctl(struct minion_info *minioninfo, int pin, uint8_t *obuf, uin
 	head->reg = READ_ADDR(MINION_SYS_FIFO_STA);
 	SET_HEAD_SIZ(head, DATA_SIZ);
 	siz = HSIZE() + DATA_SIZ;
-	__do_ioctl(minioninfo, pin, buf1, siz, buf2, MINION_CORE_SIZ, ioseq, MINION_FFL_PASS);
+	__do_ioctl(minioncgpu, minioninfo, pin, buf1, siz, buf2, MINION_CORE_SIZ, ioseq, MINION_FFL_PASS);
 
-	return __do_ioctl(minioninfo, pin, obuf, osiz, rbuf, rsiz, ioseq, MINION_FFL_PASS);
+	return __do_ioctl(minioncgpu, minioninfo, pin, obuf, osiz, rbuf, rsiz, ioseq, MINION_FFL_PASS);
 }
 #endif
 
@@ -1713,33 +1739,42 @@ static struct {
 	{ -1, -1 }
 };
 
-static bool minion_init_spi(struct cgpu_info *minioncgpu, struct minion_info *minioninfo, int bus, int chip)
+static bool minion_init_spi(struct cgpu_info *minioncgpu, struct minion_info *minioninfo, int bus, int chip, bool reset)
 {
 	int i, err, data;
 	char buf[64];
 
-	for (i = 0; minion_modules[i]; i++) {
-		snprintf(buf, sizeof(buf), "modprobe %s", minion_modules[i]);
-		err = system(buf);
-		if (err) {
-			applog(LOG_ERR, "%s: failed to modprobe %s (%d) - you need to be root?",
+	if (reset) {
+		// TODO: maybe slow it down?
+		close(minioninfo->spifd);
+		cgsleep_ms(100);
+		minioninfo->spifd = open(minioncgpu->device_path, O_RDWR);
+		if (minioninfo->spifd < 0)
+			goto bad_out;
+	} else {
+		for (i = 0; minion_modules[i]; i++) {
+			snprintf(buf, sizeof(buf), "modprobe %s", minion_modules[i]);
+			err = system(buf);
+			if (err) {
+				applog(LOG_ERR, "%s: failed to modprobe %s (%d) - you need to be root?",
+						minioncgpu->drv->dname,
+						minion_modules[i], err);
+				goto bad_out;
+			}
+		}
+
+		snprintf(buf, sizeof(buf), "/dev/spidev%d.%d", bus, chip);
+		minioninfo->spifd = open(buf, O_RDWR);
+		if (minioninfo->spifd < 0) {
+			applog(LOG_ERR, "%s: failed to open spidev (%d)",
 					minioncgpu->drv->dname,
-					minion_modules[i], err);
+					errno);
 			goto bad_out;
 		}
-	}
 
-	snprintf(buf, sizeof(buf), "/dev/spidev%d.%d", bus, chip);
-	minioninfo->spifd = open(buf, O_RDWR);
-	if (minioninfo->spifd < 0) {
-		applog(LOG_ERR, "%s: failed to open spidev (%d)",
-				minioncgpu->drv->dname,
-				errno);
-		goto bad_out;
+		minioncgpu->device_path = strdup(buf);
 	}
 
-	minioncgpu->device_path = strdup(buf);
-
 	for (i = 0; minion_ioc[i].value != -1; i++) {
 		data = minion_ioc[i].value;
 		err = ioctl(minioninfo->spifd, minion_ioc[i].request, (void *)&data);
@@ -2150,7 +2185,7 @@ static void minion_detect(bool hotplug)
 		quithere(1, "Failed to calloc minioninfo");
 	minioncgpu->device_data = (void *)minioninfo;
 
-	if (!minion_init_spi(minioncgpu, minioninfo, MINION_SPI_BUS, MINION_SPI_CHIP))
+	if (!minion_init_spi(minioncgpu, minioninfo, MINION_SPI_BUS, MINION_SPI_CHIP, false))
 		goto unalloc;
 
 #if ENABLE_INT_NONO
@@ -3254,7 +3289,7 @@ static void *minion_results(void *userdata)
 {
 	struct cgpu_info *minioncgpu = (struct cgpu_info *)userdata;
 	struct minion_info *minioninfo = (struct minion_info *)(minioncgpu->device_data);
-	struct thr_info *thr = minioncgpu->thr[0];
+	struct thr_info *thr;
 	int chip, core;
 	uint32_t task_id;
 	uint32_t nonce;
@@ -3275,6 +3310,8 @@ static void *minion_results(void *userdata)
 		cgsleep_ms(3);
 	}
 
+	thr = minioninfo->thr;
+
 	while (minioncgpu->shutdown == false) {
 		if (!oldest_nonce(minioncgpu, &chip, &core, &task_id, &nonce,
 				  &no_nonce, &when, &another, &task_id2, &nonce2)) {
@@ -3785,6 +3822,7 @@ static bool minion_thread_prepare(struct thr_info *thr)
 	struct cgpu_info *minioncgpu = thr->cgpu;
 	struct minion_info *minioninfo = (struct minion_info *)(minioncgpu->device_data);
 
+	minioninfo->thr = thr;
 	/*
 	 * SPI/ioctl write thread
 	 */
diff --git a/miner.h b/miner.h
index f8899c8..58aba3c 100644
--- a/miner.h
+++ b/miner.h
@@ -1078,6 +1078,7 @@ extern pthread_mutex_t console_lock;
 extern cglock_t ch_lock;
 extern pthread_rwlock_t mining_thr_lock;
 extern pthread_rwlock_t devices_lock;
+extern pthread_mutex_t getaddr_lock;
 
 extern pthread_mutex_t restart_lock;
 extern pthread_cond_t restart_cond;
diff --git a/util.c b/util.c
index 4f3a3d4..634e23c 100644
--- a/util.c
+++ b/util.c
@@ -2240,7 +2240,7 @@ static bool socks4_negotiate(struct pool *pool, int sockd, bool socks4a)
 	unsigned short port;
 	in_addr_t inp;
 	char buf[515];
-	int i, len;
+	int i, len, ret;
 
 	buf[0] = 0x04;
 	buf[1] = 0x01;
@@ -2262,7 +2262,10 @@ static bool socks4_negotiate(struct pool *pool, int sockd, bool socks4a)
 		servinfo = &servinfobase;
 		memset(&hints, 0, sizeof(struct addrinfo));
 		hints.ai_family = AF_INET; /* IPV4 only */
-		if (!getaddrinfo(pool->sockaddr_url, NULL, &hints, &servinfo)) {
+		mutex_lock(&getaddr_lock);
+		ret = getaddrinfo(pool->sockaddr_url, NULL, &hints, &servinfo);
+		mutex_unlock(&getaddr_lock);
+		if (ret == 0) {
 			struct sockaddr_in *saddr_in = (struct sockaddr_in *)servinfo->ai_addr;
 
 			inp = ntohl(saddr_in->sin_addr.s_addr);
@@ -2348,7 +2351,7 @@ static bool setup_stratum_socket(struct pool *pool)
 {
 	struct addrinfo servinfobase, *servinfo, *hints, *p;
 	char *sockaddr_url, *sockaddr_port;
-	int sockd;
+	int sockd, ret;
 
 	mutex_lock(&pool->stratum_lock);
 	pool->stratum_active = false;
@@ -2376,7 +2379,10 @@ static bool setup_stratum_socket(struct pool *pool)
 		sockaddr_url = pool->sockaddr_url;
 		sockaddr_port = pool->stratum_port;
 	}
-	if (getaddrinfo(sockaddr_url, sockaddr_port, hints, &servinfo) != 0) {
+	mutex_lock(&getaddr_lock);
+	ret = getaddrinfo(sockaddr_url, sockaddr_port, hints, &servinfo);
+	mutex_unlock(&getaddr_lock);
+	if (ret != 0) {
 		if (!pool->probed) {
 			applog(LOG_WARNING, "Failed to resolve (?wrong URL) %s:%s",
 			       sockaddr_url, sockaddr_port);