Commit 4613b3c7bfbafe24185aee5fe9f9eb15aecd7df8

kanoi 2013-06-16T05:41:12

Merge pull request #448 from kanoi/master record and report USB pipe errors via API stats

diff --git a/api.c b/api.c
index f6f0a43..6aebd93 100644
--- a/api.c
+++ b/api.c
@@ -2933,7 +2933,7 @@ void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, b
 	ptr = NULL;
 }
 
-static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_stats *stats, struct cgminer_pool_stats *pool_stats, struct api_data *extra, bool isjson)
+static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_stats *stats, struct cgminer_pool_stats *pool_stats, struct api_data *extra, struct cgpu_info *cgpu, bool isjson)
 {
 	struct api_data *root = NULL;
 	char buf[TMPBUFSIZ];
@@ -2973,6 +2973,25 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st
 	if (extra)
 		root = api_add_extra(root, extra);
 
+	if (cgpu) {
+#ifdef USE_USBUTILS
+		char pipe_details[128];
+
+		if (cgpu->usbinfo.pipe_count)
+			snprintf(pipe_details, sizeof(pipe_details),
+				 "%"PRIu64" %"PRIu64"/%"PRIu64"/%"PRIu64" %lu",
+				 cgpu->usbinfo.pipe_count,
+				 cgpu->usbinfo.clear_err_count,
+				 cgpu->usbinfo.retry_err_count,
+				 cgpu->usbinfo.clear_fail_count,
+				 (unsigned long)(cgpu->usbinfo.last_pipe));
+		else
+			strcpy(pipe_details, "0");
+
+		root = api_add_string(root, "USB Pipe", pipe_details, true);
+#endif
+	}
+
 	root = print_data(root, buf, isjson, isjson && (i > 0));
 	io_add(io_data, buf);
 
@@ -3003,7 +3022,7 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
 				extra = NULL;
 
 			sprintf(id, "%s%d", cgpu->drv->name, cgpu->device_id);
-			i = itemstats(io_data, i, id, &(cgpu->cgminer_stats), NULL, extra, isjson);
+			i = itemstats(io_data, i, id, &(cgpu->cgminer_stats), NULL, extra, cgpu, isjson);
 		}
 	}
 
@@ -3011,7 +3030,7 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
 		struct pool *pool = pools[j];
 
 		sprintf(id, "POOL%d", j);
-		i = itemstats(io_data, i, id, &(pool->cgminer_stats), &(pool->cgminer_pool_stats), NULL, isjson);
+		i = itemstats(io_data, i, id, &(pool->cgminer_stats), &(pool->cgminer_pool_stats), NULL, NULL, isjson);
 	}
 
 	if (isjson && io_open)
diff --git a/usbutils.c b/usbutils.c
index 62bd05e..052a55f 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -2191,21 +2191,31 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle,
 	cg_runlock(&cgusb_fd_lock);
 
 	if (err == LIBUSB_ERROR_PIPE) {
-		applog(LOG_INFO, "%s: libusb pipe error, trying to clear",
-		       cgpu->drv->name);
+		cgpu->usbinfo.last_pipe = time(NULL);
+		cgpu->usbinfo.pipe_count++;
+		applog(LOG_INFO, "%s%i: libusb pipe error, trying to clear",
+			cgpu->drv->name, cgpu->device_id);
 		do {
 			err = libusb_clear_halt(dev_handle, endpoint);
 			if (unlikely(err == LIBUSB_ERROR_NOT_FOUND ||
-				     err == LIBUSB_ERROR_NO_DEVICE))
+				     err == LIBUSB_ERROR_NO_DEVICE)) {
+					cgpu->usbinfo.clear_err_count++;
 					break;
+			}
 
 			cg_rlock(&cgusb_fd_lock);
 			err = libusb_bulk_transfer(dev_handle, endpoint, data,
 						   length, transferred, timeout);
 			cg_runlock(&cgusb_fd_lock);
+
+			if (err)
+				cgpu->usbinfo.retry_err_count++;
 		} while (err == LIBUSB_ERROR_PIPE && tries++ < USB_RETRY_MAX);
-		applog(LOG_DEBUG, "%s: libusb pipe error%scleared",
-		       cgpu->drv->name, err ? " not " : " ");
+		applog(LOG_DEBUG, "%s%i: libusb pipe error%scleared",
+			cgpu->drv->name, cgpu->device_id, err ? " not " : " ");
+
+		if (err)
+			cgpu->usbinfo.clear_fail_count++;
 	}
 
 	return err;
diff --git a/usbutils.h b/usbutils.h
index 5d3f263..03288d2 100644
--- a/usbutils.h
+++ b/usbutils.h
@@ -199,6 +199,12 @@ struct cg_usb_info {
 	 * to avoid devices disappearing while in use by multiple threads
 	 */
 	pthread_rwlock_t *devlock;
+
+	time_t last_pipe;
+	uint64_t pipe_count;
+	uint64_t clear_err_count;
+	uint64_t retry_err_count;
+	uint64_t clear_fail_count;
 };
 
 enum usb_cmds {