Commit 1c64f3b6218b864a69f5d926b777a05bd1992e61

Kano 2013-06-04T13:17:57

usb set FTDI latency higher to minimise status bytes

diff --git a/driver-bflsc.c b/driver-bflsc.c
index e77d1cc..1023232 100644
--- a/driver-bflsc.c
+++ b/driver-bflsc.c
@@ -289,6 +289,11 @@ struct SaveString {
 #define BAJ_RES_TIME 100
 #define BFLSC_MAX_SLEEP 2000
 
+#define BAJ_LATENCY LATENCY_STD
+#define BAL_LATENCY LATENCY_STD
+#define BAS_LATENCY LATENCY_STD
+#define BAM_LATENCY 2
+
 #define BFLSC_TEMP_SLEEPMS 5
 #define BFLSC_QUE_SIZE 20
 #define BFLSC_QUE_FULL_ENOUGH 13
@@ -559,6 +564,25 @@ static bool bflsc_qres(struct cgpu_info *bflsc, char *buf, size_t bufsiz, int de
 	return readok;
 }
 
+static void __set_latency(struct cgpu_info *bflsc)
+{
+	int err;
+
+	if (bflsc->usbinfo.nodev)
+		return;
+
+	// Latency
+	err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_LATENCY,
+				bflsc->usbdev->found->latency,
+				bflsc->usbdev->found->interface, C_LATENCY);
+
+	applog(LOG_DEBUG, "%s%i: latency got err %d",
+		bflsc->drv->name, bflsc->device_id, err);
+
+	if (bflsc->usbinfo.nodev)
+		return;
+}
+
 static void __bflsc_initialise(struct cgpu_info *bflsc)
 {
 	int err;
@@ -579,6 +603,11 @@ static void __bflsc_initialise(struct cgpu_info *bflsc)
 	if (bflsc->usbinfo.nodev)
 		return;
 
+	__set_latency(bflsc);
+
+	if (bflsc->usbinfo.nodev)
+		return;
+
 	// Set data control
 	err = usb_transfer(bflsc, FTDI_TYPE_OUT, FTDI_REQUEST_DATA,
 				FTDI_VALUE_DATA_BAS, bflsc->usbdev->found->interface, C_SETDATA);
@@ -785,6 +814,7 @@ static bool bflsc_detect_one(struct libusb_device *dev, struct usb_find_devices 
 	int init_sleep, init_count;
 	bool ident_first;
 	char *newname;
+	uint16_t latency;
 
 	struct cgpu_info *bflsc = calloc(1, sizeof(*bflsc));
 
@@ -880,6 +910,7 @@ reinit:
 	sc_info->scan_sleep_time = BAS_SCAN_TIME;
 	sc_info->results_sleep_time = BAS_RES_TIME;
 	sc_info->default_ms_work = BAS_WORK_TIME;
+	latency = BAS_LATENCY;
 
 	/* When getinfo() "FREQUENCY: [UNKNOWN]" is fixed -
 	 * use 'freq * engines' to estimate.
@@ -891,6 +922,7 @@ reinit:
 		sc_info->results_sleep_time = BAM_RES_TIME;
 		sc_info->default_ms_work = BAM_WORK_TIME;
 		bflsc->usbdev->ident = IDENT_BAM;
+		latency = BAM_LATENCY;
 	} else {
 		if (sc_info->sc_devs[0].engines < 34) { // 16 * 2 + 2
 			newname = BFLSC_JALAPENO;
@@ -898,15 +930,22 @@ reinit:
 			sc_info->results_sleep_time = BAJ_RES_TIME;
 			sc_info->default_ms_work = BAJ_WORK_TIME;
 			bflsc->usbdev->ident = IDENT_BAJ;
+			latency = BAJ_LATENCY;
 		} else if (sc_info->sc_devs[0].engines < 130)  { // 16 * 8 + 2
 			newname = BFLSC_LITTLESINGLE;
 			sc_info->scan_sleep_time = BAL_SCAN_TIME;
 			sc_info->results_sleep_time = BAL_RES_TIME;
 			sc_info->default_ms_work = BAL_WORK_TIME;
 			bflsc->usbdev->ident = IDENT_BAL;
+			latency = BAL_LATENCY;
 		}
 	}
 
+	if (latency != bflsc->usbdev->found->latency) {
+		bflsc->usbdev->found->latency = latency;
+		__set_latency(bflsc);
+	}
+
 	for (i = 0; i < sc_info->sc_count; i++)
 		sc_info->sc_devs[i].ms_work = sc_info->default_ms_work;
 
diff --git a/driver-icarus.c b/driver-icarus.c
index ccd762b..d782a71 100644
--- a/driver-icarus.c
+++ b/driver-icarus.c
@@ -256,12 +256,9 @@ static void icarus_initialise(struct cgpu_info *icarus, int baud)
 		case IDENT_LLT:
 		case IDENT_CMR1:
 		case IDENT_CMR2:
-			// Latency
-			transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_LATENCY, FTDI_VALUE_LATENCY,
-				 icarus->usbdev->found->interface, C_LATENCY);
-
-			if (icarus->usbinfo.nodev)
-				return;
+			if (icarus->usbdev->found->latency == LATENCY_UNUSED)
+				quit(1, "%s: cgid %d invalid latency (UNUSED)",
+					icarus->drv->name, icarus->cgminer_id);
 
 			// Reset
 			transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_RESET,
@@ -270,6 +267,14 @@ static void icarus_initialise(struct cgpu_info *icarus, int baud)
 			if (icarus->usbinfo.nodev)
 				return;
 
+			// Latency
+			transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_LATENCY,
+				 icarus->usbdev->found->latency,
+				 icarus->usbdev->found->interface, C_LATENCY);
+
+			if (icarus->usbinfo.nodev)
+				return;
+
 			// Set data control
 			transfer(icarus, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, FTDI_VALUE_DATA_BLT,
 				 icarus->usbdev->found->interface, C_SETDATA);
diff --git a/usbutils.c b/usbutils.c
index 257a2ca..f22cbbd 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -149,6 +149,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 0,
 		.timeout = BFLSC_TIMEOUT_MS,
+		.latency = LATENCY_STD,
 		.epcount = ARRAY_SIZE(bas_eps),
 		.eps = bas_eps },
 #endif
@@ -165,6 +166,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 0,
 		.timeout = BITFORCE_TIMEOUT_MS,
+		.latency = LATENCY_STD,
 		.epcount = ARRAY_SIZE(bfl_eps),
 		.eps = bfl_eps },
 #endif
@@ -179,6 +181,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 1,
 		.timeout = MODMINER_TIMEOUT_MS,
+		.latency = LATENCY_UNUSED,
 		.epcount = ARRAY_SIZE(mmq_eps),
 		.eps = mmq_eps },
 #endif
@@ -193,6 +196,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 0,
 		.timeout = AVALON_TIMEOUT_MS,
+		.latency = 10,
 		.epcount = ARRAY_SIZE(ava_eps),
 		.eps = ava_eps },
 #endif
@@ -207,6 +211,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 0,
 		.timeout = ICARUS_TIMEOUT_MS,
+		.latency = LATENCY_UNUSED,
 		.epcount = ARRAY_SIZE(ica_eps),
 		.eps = ica_eps },
 	{
@@ -219,6 +224,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 0,
 		.timeout = ICARUS_TIMEOUT_MS,
+		.latency = LATENCY_UNUSED,
 		.epcount = ARRAY_SIZE(amu_eps),
 		.eps = amu_eps },
 	{
@@ -232,6 +238,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 0,
 		.timeout = ICARUS_TIMEOUT_MS,
+		.latency = LATENCY_STD,
 		.epcount = ARRAY_SIZE(llt_eps),
 		.eps = llt_eps },
 	// For any that don't match the above "BLT"
@@ -245,6 +252,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 0,
 		.timeout = ICARUS_TIMEOUT_MS,
+		.latency = LATENCY_STD,
 		.epcount = ARRAY_SIZE(llt_eps),
 		.eps = llt_eps },
 	{
@@ -258,6 +266,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 0,
 		.timeout = ICARUS_TIMEOUT_MS,
+		.latency = LATENCY_STD,
 		.epcount = ARRAY_SIZE(cmr1_eps),
 		.eps = cmr1_eps },
 	{
@@ -271,6 +280,7 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 0,
 		.timeout = ICARUS_TIMEOUT_MS,
+		.latency = LATENCY_STD,
 		.epcount = ARRAY_SIZE(cmr2_eps),
 		.eps = cmr2_eps },
 #endif
@@ -287,10 +297,11 @@ static struct usb_find_devices find_dev[] = {
 		.config = 1,
 		.interface = 1,
 		.timeout = 100,
+		.latency = LATENCY_UNUSED,
 		.epcount = 0,
 		.eps = NULL },
 #endif
-	{ DRV_LAST, NULL, 0, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, NULL }
+	{ DRV_LAST, NULL, 0, 0, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL }
 };
 
 #ifdef USE_BFLSC
@@ -2023,7 +2034,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
 	struct timeval tv_start;
 #endif
 	struct timeval read_start, tv_finish;
-	unsigned int initial_timeout, sleep_time;
+	unsigned int initial_timeout;
 	double max, done;
 	int bufleft, err, got, tot;
 	__maybe_unused bool first = true;
@@ -2058,9 +2069,6 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
 		bufleft = bufsiz;
 		err = LIBUSB_SUCCESS;
 		initial_timeout = timeout;
-		sleep_time = initial_timeout / 2;
-		if (sleep_time > USB_READ_MINPOLL)
-			sleep_time = USB_READ_MINPOLL;
 		max = ((double)timeout) / 1000.0;
 		cgtime(&read_start);
 		while (bufleft > 0) {
@@ -2105,23 +2113,9 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
 
 			done = tdiff(&tv_finish, &read_start);
 			// N.B. this is: return LIBUSB_SUCCESS with whatever size has already been read
-			if (unlikely(done >= max))
-				break;
-
-			/* Controversial. Even though libusb gives the device
-			 * a timeout, many devices (eg ftdi) simply time out
-			 * after only 1ms making this function poll every ms
-			 * if we don't sleep here, but do it only if we're not
-			 * receiving any data. */
 			timeout = initial_timeout - (done * 1000);
-			if (!timeout)
+			if (timeout <= 0)
 				break;
-			if (!got && sleep_time) {
-				if (timeout <= sleep_time)
-					sleep_time = timeout - 1;
-				timeout -= sleep_time;
-				nmsleep(sleep_time);
-			}
 		}
 
 		*processed = tot;
@@ -2139,9 +2133,6 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
 	endlen = strlen(end);
 	err = LIBUSB_SUCCESS;
 	initial_timeout = timeout;
-	sleep_time = initial_timeout / 2;
-	if (sleep_time > USB_READ_MINPOLL)
-		sleep_time = USB_READ_MINPOLL;
 	max = ((double)timeout) / 1000.0;
 	cgtime(&read_start);
 	while (bufleft > 0) {
@@ -2204,18 +2195,9 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
 
 		done = tdiff(&tv_finish, &read_start);
 		// N.B. this is: return LIBUSB_SUCCESS with whatever size has already been read
-		if (unlikely(done >= max))
-			break;
-
 		timeout = initial_timeout - (done * 1000);
-		if (!timeout)
+		if (timeout <= 0)
 			break;
-		if (!got && sleep_time) {
-			if (timeout <= sleep_time)
-				sleep_time = timeout - 1;
-			timeout -= sleep_time;
-			nmsleep(sleep_time);
-		}
 	}
 
 	*processed = tot;
diff --git a/usbutils.h b/usbutils.h
index 77a202c..5ff90c2 100644
--- a/usbutils.h
+++ b/usbutils.h
@@ -140,10 +140,14 @@ struct usb_find_devices {
 	int config;
 	int interface;
 	unsigned int timeout;
+	uint16_t latency;
 	int epcount;
 	struct usb_endpoints *eps;
 };
 
+#define LATENCY_UNUSED 0
+#define LATENCY_STD 40
+
 enum usb_types {
 	USB_TYPE_STD = 0,
 	USB_TYPE_FTDI