Commit c7d5256b3657bd6d4f2f04f7288cd757bcbf77a5

Con Kolivas 2013-10-07T20:03:53

Check for the async variants of the libusb errors and retry up to retry max when trying to clear a pipe error/stall.

diff --git a/usbutils.c b/usbutils.c
index e977e2a..e6e2c98 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -20,7 +20,10 @@
 
 #define NODEV(err) ((err) == LIBUSB_ERROR_NO_DEVICE || \
 			(err) == LIBUSB_ERROR_PIPE || \
-			(err) == LIBUSB_ERROR_OTHER)
+			(err) == LIBUSB_ERROR_OTHER || \
+			(err) == LIBUSB_TRANSFER_NO_DEVICE || \
+			(err) == LIBUSB_TRANSFER_STALL || \
+			(err) == LIBUSB_TRANSFER_ERROR)
 
 #define NOCONTROLDEV(err) ((err) == LIBUSB_ERROR_NO_DEVICE || \
 			(err) == LIBUSB_ERROR_OTHER)
@@ -2264,10 +2267,10 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle, int intinfo,
 		  enum usb_cmds cmd, __maybe_unused int seq)
 {
 	struct usb_epinfo *usb_epinfo;
+	int err, errn, retries = 0;
 	struct usb_transfer ut;
 	unsigned char endpoint;
 	uint16_t MaxPacketSize;
-	int err, errn;
 #if DO_USB_STATS
 	struct timeval tv_start, tv_finish;
 #endif
@@ -2294,6 +2297,7 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle, int intinfo,
 	libusb_fill_bulk_transfer(ut.transfer, dev_handle, endpoint, buf, length,
 				  bulk_callback, &ut, timeout);
 
+retry:
 	STATS_TIMEVAL(&tv_start);
 	cg_rlock(&cgusb_fd_lock);
 	err = libusb_submit_transfer(ut.transfer);
@@ -2305,12 +2309,13 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle, int intinfo,
 	STATS_TIMEVAL(&tv_finish);
 	USB_STATS(cgpu, &tv_start, &tv_finish, err, mode, cmd, seq, timeout);
 
-	if (err < 0)
+	if (err < 0) {
 		applog(LOG_DEBUG, "%s%i: %s (amt=%d err=%d ern=%d)",
 				cgpu->drv->name, cgpu->device_id,
 				usb_cmdname(cmd), *transferred, err, errn);
+	}
 
-	if (err == LIBUSB_ERROR_PIPE || err == LIBUSB_TRANSFER_STALL) {
+	if ((err == LIBUSB_ERROR_PIPE || err == LIBUSB_TRANSFER_STALL) && ++retries < USB_RETRY_MAX) {
 		cgpu->usbinfo.last_pipe = time(NULL);
 		cgpu->usbinfo.pipe_count++;
 		applog(LOG_INFO, "%s%i: libusb pipe error, trying to clear",
@@ -2321,6 +2326,8 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle, int intinfo,
 
 		if (err)
 			cgpu->usbinfo.clear_fail_count++;
+		else
+			goto retry;
 	}
 	if ((endpoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
 		memcpy(data, buf, length);