log USB timeouts in API stats
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
diff --git a/api.c b/api.c
index 8c29bf9..50bbbbf 100644
--- a/api.c
+++ b/api.c
@@ -3023,7 +3023,7 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st
if (cgpu) {
#ifdef USE_USBUTILS
- char details[128];
+ char details[256];
if (cgpu->usbinfo.pipe_count)
snprintf(details, sizeof(details),
@@ -3046,6 +3046,30 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st
cgpu->usbinfo.total_write_delay);
root = api_add_string(root, "USB Delay", details, true);
+
+ if (cgpu->usbinfo.usb_tmo[0].count == 0 &&
+ cgpu->usbinfo.usb_tmo[0].count == 0 &&
+ cgpu->usbinfo.usb_tmo[0].count == 0) {
+ snprintf(details, sizeof(details),
+ "%"PRIu64" 0", cgpu->usbinfo.tmo_count);
+ } else {
+ snprintf(details, sizeof(details),
+ "%"PRIu64" %d=%d/%"PRIu64"/%"PRIu64
+ " %d=%d/%"PRIu64"/%"PRIu64
+ " %d=%d/%"PRIu64"/%"PRIu64" ",
+ cgpu->usbinfo.tmo_count,
+ USB_TMO_0, cgpu->usbinfo.usb_tmo[0].count,
+ cgpu->usbinfo.usb_tmo[0].total_over,
+ cgpu->usbinfo.usb_tmo[0].total_tmo,
+ USB_TMO_1, cgpu->usbinfo.usb_tmo[1].count,
+ cgpu->usbinfo.usb_tmo[1].total_over,
+ cgpu->usbinfo.usb_tmo[1].total_tmo,
+ USB_TMO_2, cgpu->usbinfo.usb_tmo[2].count,
+ cgpu->usbinfo.usb_tmo[2].total_over,
+ cgpu->usbinfo.usb_tmo[2].total_tmo);
+ }
+
+ root = api_add_string(root, "USB tmo", details, true);
#endif
}
diff --git a/usbutils.c b/usbutils.c
index fecd2e5..3da8dc2 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -460,9 +460,6 @@ static int next_stat = USB_NOSTAT;
#define SECTOMS(s) ((int)((s) * 1000))
-// timeout checks are only done when stats are enabled
-#define TIMEOUT_OVER_MS 500
-
#define USB_STATS(sgpu_, sta_, fin_, err_, mode_, cmd_, seq_, tmo_) \
stats(sgpu_, sta_, fin_, err_, mode_, cmd_, seq_, tmo_)
#define STATS_TIMEVAL(tv_) cgtime(tv_)
@@ -2128,17 +2125,29 @@ static void stats(struct cgpu_info *cgpu, struct timeval *tv_start, struct timev
{
struct cg_usb_stats_details *details;
double diff;
- int item, elapsedms;
+ int item, extrams;
if (cgpu->usbinfo.usbstat < 1)
newstats(cgpu);
+ cgpu->usbinfo.tmo_count++;
+
// timeout checks are only done when stats are enabled
- elapsedms = SECTOMS(tdiff(tv_finish, tv_start));
- if (elapsedms > (timeout + TIMEOUT_OVER_MS)) {
- applog(LOG_ERR, "%s%i: TIMEOUT %s took %dms but was %dms",
- cgpu->drv->name, cgpu->device_id,
- usb_cmdname(cmd), elapsedms, timeout) ;
+ extrams = SECTOMS(tdiff(tv_finish, tv_start)) - timeout;
+ if (extrams >= USB_TMO_0) {
+ int offset = 0;
+
+ if (extrams >= USB_TMO_2) {
+ applog(LOG_ERR, "%s%i: TIMEOUT %s took %dms but was %dms",
+ cgpu->drv->name, cgpu->device_id,
+ usb_cmdname(cmd), extrams+timeout, timeout) ;
+ offset = 2;
+ } else if (extrams >= USB_TMO_1)
+ offset = 1;
+
+ cgpu->usbinfo.usb_tmo[offset].count++;
+ cgpu->usbinfo.usb_tmo[offset].total_over += extrams;
+ cgpu->usbinfo.usb_tmo[offset].total_tmo += timeout;
}
details = &(usb_stats[cgpu->usbinfo.usbstat - 1].details[cmd * 2 + seq]);
diff --git a/usbutils.h b/usbutils.h
index 75f1e51..abfcc57 100644
--- a/usbutils.h
+++ b/usbutils.h
@@ -186,6 +186,17 @@ struct cg_usb_device {
#define USB_MAX_READ 8192
+#define USB_TMO_0 50
+#define USB_TMO_1 100
+#define USB_TMO_2 500
+#define USB_TMOS 3
+
+struct cg_usb_tmo {
+ uint32_t count;
+ uint64_t total_over;
+ uint64_t total_tmo;
+};
+
struct cg_usb_info {
uint8_t bus_number;
uint8_t device_address;
@@ -224,6 +235,9 @@ struct cg_usb_info {
* multiple of these
*/
unsigned char bulkbuf[USB_MAX_READ+4];
+
+ uint64_t tmo_count;
+ struct cg_usb_tmo usb_tmo[USB_TMOS];
};
enum usb_cmds {