From cbf6c71648d2edc56fae7ec60b217e5475f9cfca Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 08:54:02 +1100 Subject: [PATCH 01/87] BFL libusb driver --- driver-bitforce.c | 602 ++++++++++++++++++++++------------------------ usbutils.c | 133 ++++++++-- usbutils.h | 55 ++++- 3 files changed, 450 insertions(+), 340 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index b8a83430..62c40636 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -1,4 +1,5 @@ /* + * Copyright 2012 Andrew Smith * Copyright 2012 Luke Dashjr * Copyright 2012 Con Kolivas * @@ -19,34 +20,25 @@ #include "config.h" #ifdef WIN32 - #include - -#define dlsym (void*)GetProcAddress -#define dlclose FreeLibrary - -typedef unsigned long FT_STATUS; -typedef PVOID FT_HANDLE; -__stdcall FT_STATUS (*FT_ListDevices)(PVOID pArg1, PVOID pArg2, DWORD Flags); -__stdcall FT_STATUS (*FT_Open)(int idx, FT_HANDLE*); -__stdcall FT_STATUS (*FT_GetComPortNumber)(FT_HANDLE, LPLONG lplComPortNumber); -__stdcall FT_STATUS (*FT_Close)(FT_HANDLE); -const uint32_t FT_OPEN_BY_DESCRIPTION = 2; -const uint32_t FT_LIST_ALL = 0x20000000; -const uint32_t FT_LIST_NUMBER_ONLY = 0x80000000; -enum { - FT_OK, -}; - -// Code must deal with a timeout. Make it 1 second on windows, 0.1 on linux. -#define BFopen(devpath) serial_open(devpath, 0, 10, true) -#else /* WIN32 */ -#define BFopen(devpath) serial_open(devpath, 0, 1, true) #endif /* WIN32 */ #include "compat.h" #include "miner.h" -#include "fpgautils.h" +#include "usbutils.h" + +#define BITFORCE_IDENTIFY "ZGX" +#define BITFORCE_IDENTIFY_LEN (sizeof(BITFORCE_IDENTIFY)-1) +#define BITFORCE_FLASH "ZMX" +#define BITFORCE_FLASH_LEN (sizeof(BITFORCE_FLASH)-1) +#define BITFORCE_TEMPERATURE "ZLX" +#define BITFORCE_TEMPERATURE_LEN (sizeof(BITFORCE_TEMPERATURE)-1) +#define BITFORCE_SENDRANGE "ZPX" +#define BITFORCE_SENDRANGE_LEN (sizeof(BITFORCE_SENDRANGE)-1) +#define BITFORCE_SENDWORK "ZDX" +#define BITFORCE_SENDWORK_LEN (sizeof(BITFORCE_SENDWORK)-1) +#define BITFORCE_WORKSTATUS "ZFX" +#define BITFORCE_WORKSTATUS_LEN (sizeof(BITFORCE_WORKSTATUS)-1) #define BITFORCE_SLEEP_MS 500 #define BITFORCE_TIMEOUT_S 7 @@ -62,62 +54,143 @@ enum { #define KNAME_WORK "full work" #define KNAME_RANGE "nonce range" +#define BITFORCE_BUFSIZ (0x200) + +// If initialisation fails the first time, +// sleep this amount (ms) and try again +#define REINIT_TIME_MS 6000 + +static const char *blank = ""; + struct device_api bitforce_api; -static void BFgets(char *buf, size_t bufLen, int fd) +static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) { - do { - buf[0] = '\0'; - --bufLen; - } while (likely(bufLen && read(fd, buf, 1) == 1 && (buf++)[0] != '\n')); + int err; - buf[0] = '\0'; -} + if (lock) + mutex_lock(&bitforce->device_mutex); -static ssize_t BFwrite(int fd, const void *buf, ssize_t bufLen) -{ - if ((bufLen) != write(fd, buf, bufLen)) - return 0; - else - return bufLen; + // Reset + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, + FTDI_VALUE_RESET, bitforce->usbdev->found->interface, C_RESET); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: reset got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Set data control + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, + FTDI_VALUE_DATA, bitforce->usbdev->found->interface, C_SETDATA); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: setdata got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Set the baud + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD, + (FTDI_INDEX_BAUD & 0xff00) | bitforce->usbdev->found->interface, + C_SETBAUD); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: setbaud got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Set Flow Control + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, + FTDI_VALUE_FLOW, bitforce->usbdev->found->interface, C_SETFLOW); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Set Modem Control + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM, + FTDI_VALUE_MODEM, bitforce->usbdev->found->interface, C_SETMODEM); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", + bitforce->api->name, bitforce->device_id, err); + + // Clear any sent data +// err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, +// FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); +// if (opt_debug) +// applog(LOG_DEBUG, "%s%i: purgetx got err %d", +// bitforce->api->name, bitforce->device_id, err); + + // Clear any received data +// err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, +// FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); +// if (opt_debug) +// applog(LOG_DEBUG, "%s%i: purgerx got err %d", +// bitforce->api->name, bitforce->device_id, err); + + if (lock) + mutex_unlock(&bitforce->device_mutex); } -#define BFclose(fd) close(fd) - -static bool bitforce_detect_one(const char *devpath) +static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found) { - int fdDev = BFopen(devpath); - struct cgpu_info *bitforce; - char pdevbuf[0x100]; + char buf[BITFORCE_BUFSIZ+1]; + char devpath[20]; + int err, amount; char *s; - applog(LOG_DEBUG, "BFL: Attempting to open %s", devpath); + struct cgpu_info *bitforce = NULL; + bitforce = calloc(1, sizeof(*bitforce)); + bitforce->api = &bitforce_api; + bitforce->deven = DEV_ENABLED; + bitforce->threads = 1; - if (unlikely(fdDev == -1)) { - applog(LOG_ERR, "BFL: Failed to open %s", devpath); - return false; + if (!usb_init(bitforce, dev, found)) { + applog(LOG_ERR, "%s detect: failed to initialise (incorrect device?)", bitforce->api->dname); + goto shin; } - BFwrite(fdDev, "ZGX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - if (unlikely(!pdevbuf[0])) { - applog(LOG_ERR, "BFL: Error reading/timeout (ZGX)"); - return 0; + int init_counter = 0; +reinit: + + bitforce_initialise(bitforce, false); + + if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { + applog(LOG_ERR, "%s detect: send identify request failed (%d:%d)", + bitforce->api->dname, amount, err); + goto unshin; } - BFclose(fdDev); - if (unlikely(!strstr(pdevbuf, "SHA256"))) { - applog(LOG_ERR, "BFL: Didn't recognise BitForce on %s", devpath); - return false; + if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { + // Maybe it was still processing previous work? + if (init_counter++ < 1) { + applog(LOG_WARNING, "%s detect: 1st init failed - retrying in %dms (%d:%d)", + bitforce->api->dname, REINIT_TIME_MS, amount, err); + nmsleep(REINIT_TIME_MS); + goto reinit; + } + + if (err < 0) { + applog(LOG_ERR, "%s detect: error identify reply (%d:%d)", + bitforce->api->dname, amount, err); + } else { + applog(LOG_ERR, "%s detect: empty identify reply (%d)", + bitforce->api->dname, amount); + } + + goto unshin; + } + buf[amount] = '\0'; + + if (unlikely(!strstr(buf, "SHA256"))) { + applog(LOG_ERR, "%s detect: didn't recognise %s", + bitforce->api->dname, buf); + goto unshin; + } + + if (likely((!memcmp(buf, ">>>ID: ", 7)) && (s = strstr(buf + 3, ">>>")))) { + s[0] = '\0'; + bitforce->name = strdup(buf + 7); + } else { + bitforce->name = (char *)blank; } // We have a real BitForce! - bitforce = calloc(1, sizeof(*bitforce)); - bitforce->api = &bitforce_api; - bitforce->device_path = strdup(devpath); - bitforce->deven = DEV_ENABLED; - bitforce->threads = 1; + applog(LOG_DEBUG, "%s identified as: '%s'", bitforce->api->dname, bitforce->name); + /* Initially enable support for nonce range and disable it later if it * fails */ if (opt_bfl_noncerange) { @@ -129,108 +202,38 @@ static bool bitforce_detect_one(const char *devpath) bitforce->kname = KNAME_WORK; } - if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>")))) { - s[0] = '\0'; - bitforce->name = strdup(pdevbuf + 7); - } + sprintf(devpath, "%d:%d", + (int)(bitforce->usbdev->bus_number), + (int)(bitforce->usbdev->device_address)); + + bitforce->device_path = strdup(devpath); + + if (!add_cgpu(bitforce)) + goto unshin; mutex_init(&bitforce->device_mutex); - return add_cgpu(bitforce); -} + return true; -#define LOAD_SYM(sym) do { \ - if (!(sym = dlsym(dll, #sym))) { \ - applog(LOG_DEBUG, "Failed to load " #sym ", not using FTDI bitforce autodetect"); \ - goto out; \ - } \ -} while(0) +unshin: -#ifdef WIN32 -static int bitforce_autodetect_ftdi(void) -{ - char devpath[] = "\\\\.\\COMnnnnn"; - char *devpathnum = &devpath[7]; - char **bufptrs; - char *buf; - int found = 0; - DWORD i; - - FT_STATUS ftStatus; - DWORD numDevs; - HMODULE dll = LoadLibrary("FTD2XX.DLL"); - if (!dll) { - applog(LOG_DEBUG, "FTD2XX.DLL failed to load, not using FTDI bitforce autodetect"); - return 0; - } - LOAD_SYM(FT_ListDevices); - LOAD_SYM(FT_Open); - LOAD_SYM(FT_GetComPortNumber); - LOAD_SYM(FT_Close); - - ftStatus = FT_ListDevices(&numDevs, NULL, FT_LIST_NUMBER_ONLY); - if (ftStatus != FT_OK) { - applog(LOG_DEBUG, "FTDI device count failed, not using FTDI bitforce autodetect"); - goto out; - } - applog(LOG_DEBUG, "FTDI reports %u devices", (unsigned)numDevs); - - buf = alloca(65 * numDevs); - bufptrs = alloca(sizeof(*bufptrs) * (numDevs + 1)); - - for (i = 0; i < numDevs; ++i) - bufptrs[i] = &buf[i * 65]; - bufptrs[numDevs] = NULL; - ftStatus = FT_ListDevices(bufptrs, &numDevs, FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); - if (ftStatus != FT_OK) { - applog(LOG_DEBUG, "FTDI device list failed, not using FTDI bitforce autodetect"); - goto out; - } - - for (i = numDevs; i > 0; ) { - --i; - bufptrs[i][64] = '\0'; - - if (!(strstr(bufptrs[i], "BitFORCE") && strstr(bufptrs[i], "SHA256"))) - continue; - - FT_HANDLE ftHandle; - if (FT_OK != FT_Open(i, &ftHandle)) - continue; - LONG lComPortNumber; - ftStatus = FT_GetComPortNumber(ftHandle, &lComPortNumber); - FT_Close(ftHandle); - if (FT_OK != ftStatus || lComPortNumber < 0) - continue; - - sprintf(devpathnum, "%d", (int)lComPortNumber); - - if (bitforce_detect_one(devpath)) - ++found; - } + usb_uninit(bitforce); -out: - dlclose(dll); - return found; -} -#else -static int bitforce_autodetect_ftdi(void) -{ - return 0; -} -#endif +shin: -static int bitforce_detect_auto(void) -{ - return (serial_autodetect_udev (bitforce_detect_one, "BitFORCE*SHA256") ?: - serial_autodetect_devserial(bitforce_detect_one, "BitFORCE_SHA256") ?: - bitforce_autodetect_ftdi() ?: - 0); + free(bitforce->device_path); + + if (bitforce->name != blank) + free(bitforce->name); + + free(bitforce); + + return false; } static void bitforce_detect(void) { - serial_detect_auto(&bitforce_api, bitforce_detect_one, bitforce_detect_auto); + usb_detect(&bitforce_api, bitforce_detect_one); } static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce) @@ -247,105 +250,17 @@ static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce) static bool bitforce_thread_prepare(struct thr_info *thr) { struct cgpu_info *bitforce = thr->cgpu; - int fdDev = BFopen(bitforce->device_path); struct timeval now; - if (unlikely(fdDev == -1)) { - applog(LOG_ERR, "BFL%i: Failed to open %s", bitforce->device_id, bitforce->device_path); - return false; - } - - bitforce->device_fd = fdDev; - - applog(LOG_INFO, "BFL%i: Opened %s", bitforce->device_id, bitforce->device_path); gettimeofday(&now, NULL); get_datestamp(bitforce->init, &now); return true; } -static void bitforce_clear_buffer(struct cgpu_info *bitforce) -{ - int fdDev = bitforce->device_fd; - char pdevbuf[0x100]; - int count = 0; - - if (!fdDev) - return; - - applog(LOG_DEBUG, "BFL%i: Clearing read buffer", bitforce->device_id); - - mutex_lock(&bitforce->device_mutex); - do { - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - } while (pdevbuf[0] && (++count < 10)); - mutex_unlock(&bitforce->device_mutex); -} - -void bitforce_init(struct cgpu_info *bitforce) -{ - char *devpath = bitforce->device_path; - int fdDev = bitforce->device_fd, retries = 0; - char pdevbuf[0x100]; - char *s; - - applog(LOG_WARNING, "BFL%i: Re-initialising", bitforce->device_id); - - bitforce_clear_buffer(bitforce); - - mutex_lock(&bitforce->device_mutex); - if (fdDev) { - BFclose(fdDev); - sleep(5); - } - bitforce->device_fd = 0; - - fdDev = BFopen(devpath); - if (unlikely(fdDev == -1)) { - mutex_unlock(&bitforce->device_mutex); - applog(LOG_ERR, "BFL%i: Failed to open %s", bitforce->device_id, devpath); - return; - } - - do { - BFwrite(fdDev, "ZGX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - - if (unlikely(!pdevbuf[0])) { - mutex_unlock(&bitforce->device_mutex); - applog(LOG_ERR, "BFL%i: Error reading/timeout (ZGX)", bitforce->device_id); - return; - } - - if (retries++) - nmsleep(10); - } while (!strstr(pdevbuf, "BUSY") && (retries * 10 < BITFORCE_TIMEOUT_MS)); - - if (unlikely(!strstr(pdevbuf, "SHA256"))) { - mutex_unlock(&bitforce->device_mutex); - applog(LOG_ERR, "BFL%i: Didn't recognise BitForce on %s returned: %s", bitforce->device_id, devpath, pdevbuf); - return; - } - - if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>")))) { - s[0] = '\0'; - bitforce->name = strdup(pdevbuf + 7); - } - - bitforce->device_fd = fdDev; - bitforce->sleep_ms = BITFORCE_SLEEP_MS; - - mutex_unlock(&bitforce->device_mutex); -} - static void bitforce_flash_led(struct cgpu_info *bitforce) { - int fdDev = bitforce->device_fd; - - if (!fdDev) - return; + int err, amount; /* Do not try to flash the led if we're polling for a result to * minimise the chance of interleaved results */ @@ -353,19 +268,22 @@ static void bitforce_flash_led(struct cgpu_info *bitforce) return; /* It is not critical flashing the led so don't get stuck if we - * can't grab the mutex here */ + * can't grab the mutex now */ if (mutex_trylock(&bitforce->device_mutex)) return; - BFwrite(fdDev, "ZMX", 3); + if ((err = usb_write(bitforce, BITFORCE_FLASH, BITFORCE_FLASH_LEN, &amount, C_REQUESTFLASH)) < 0 || amount != BITFORCE_FLASH_LEN) { + applog(LOG_ERR, "%s%i: flash request failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + } else { + /* However, this stops anything else getting a reply + * So best to delay any other access to the BFL */ + sleep(4); + } /* Once we've tried - don't do it until told to again */ bitforce->flash_led = false; - /* However, this stops anything else getting a reply - * So best to delay any other access to the BFL */ - sleep(4); - mutex_unlock(&bitforce->device_mutex); return; // nothing is returned by the BFL @@ -373,13 +291,10 @@ static void bitforce_flash_led(struct cgpu_info *bitforce) static bool bitforce_get_temp(struct cgpu_info *bitforce) { - int fdDev = bitforce->device_fd; - char pdevbuf[0x100]; + char buf[BITFORCE_BUFSIZ+1]; + int err, amount; char *s; - if (!fdDev) - return false; - /* Do not try to get the temperature if we're polling for a result to * minimise the chance of interleaved results */ if (bitforce->polling) @@ -396,18 +311,30 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) if (mutex_trylock(&bitforce->device_mutex)) return false; - BFwrite(fdDev, "ZLX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - mutex_unlock(&bitforce->device_mutex); - - if (unlikely(!pdevbuf[0])) { - applog(LOG_ERR, "BFL%i: Error: Get temp returned empty string/timed out", bitforce->device_id); + if ((err = usb_write(bitforce, BITFORCE_TEMPERATURE, BITFORCE_TEMPERATURE_LEN, &amount, C_REQUESTTEMPERATURE)) < 0 || amount != BITFORCE_TEMPERATURE_LEN) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%i: Error: Request temp invalid/timed out (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + bitforce->hw_errors++; + return false; + } + + if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETTEMPERATURE)) < 0 || amount < 1) { + mutex_unlock(&bitforce->device_mutex); + if (err < 0) { + applog(LOG_ERR, "%s%i: Error: Get temp return invalid/timed out (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + } else { + applog(LOG_ERR, "%s%i: Error: Get temp returned nothing (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + } bitforce->hw_errors++; return false; } - if ((!strncasecmp(pdevbuf, "TEMP", 4)) && (s = strchr(pdevbuf + 4, ':'))) { + mutex_unlock(&bitforce->device_mutex); + + if ((!strncasecmp(buf, "TEMP", 4)) && (s = strchr(buf + 4, ':'))) { float temp = strtof(s + 1, NULL); /* Cope with older software that breaks and reads nonsense @@ -418,7 +345,8 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) if (temp > 0) { bitforce->temp = temp; if (unlikely(bitforce->cutofftemp > 0 && temp > bitforce->cutofftemp)) { - applog(LOG_WARNING, "BFL%i: Hit thermal cutoff limit, disabling!", bitforce->device_id); + applog(LOG_WARNING, "%s%i: Hit thermal cutoff limit, disabling!", + bitforce->api->name, bitforce->device_id); bitforce->deven = DEV_RECOVER; dev_error(bitforce, REASON_DEV_THERMAL_CUTOFF); } @@ -427,11 +355,12 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) /* Use the temperature monitor as a kind of watchdog for when * our responses are out of sync and flush the buffer to * hopefully recover */ - applog(LOG_WARNING, "BFL%i: Garbled response probably throttling, clearing buffer", bitforce->device_id); + applog(LOG_WARNING, "%s%i: Garbled response probably throttling, clearing buffer", + bitforce->api->name, bitforce->device_id); dev_error(bitforce, REASON_DEV_THROTTLE); /* Count throttling episodes as hardware errors */ bitforce->hw_errors++; - bitforce_clear_buffer(bitforce); + bitforce_initialise(bitforce, true); return false; } @@ -441,35 +370,53 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) static bool bitforce_send_work(struct thr_info *thr, struct work *work) { struct cgpu_info *bitforce = thr->cgpu; - int fdDev = bitforce->device_fd; unsigned char ob[70]; - char pdevbuf[0x100]; + char buf[BITFORCE_BUFSIZ+1]; + int err, amount; char *s; + char *cmd; + int len; - if (!fdDev) - return false; re_send: + if (bitforce->nonce_range) { + cmd = BITFORCE_SENDRANGE; + len = BITFORCE_SENDRANGE_LEN; + } else { + cmd = BITFORCE_SENDWORK; + len = BITFORCE_SENDWORK_LEN; + } + mutex_lock(&bitforce->device_mutex); - if (bitforce->nonce_range) - BFwrite(fdDev, "ZPX", 3); - else - BFwrite(fdDev, "ZDX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); - if (!pdevbuf[0] || !strncasecmp(pdevbuf, "B", 1)) { + if ((err = usb_write(bitforce, cmd, len, &amount, C_REQUESTSENDWORK)) < 0 || amount != len) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%i: request send work failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + return false; + } + + if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_REQUESTSENDWORKSTATUS)) < 0) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%d: read request send work status failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + return false; + } + + if (amount == 0 || !buf[0] || !strncasecmp(buf, "B", 1)) { mutex_unlock(&bitforce->device_mutex); nmsleep(WORK_CHECK_INTERVAL_MS); goto re_send; - } else if (unlikely(strncasecmp(pdevbuf, "OK", 2))) { + } else if (unlikely(strncasecmp(buf, "OK", 2))) { mutex_unlock(&bitforce->device_mutex); if (bitforce->nonce_range) { - applog(LOG_WARNING, "BFL%i: Does not support nonce range, disabling", bitforce->device_id); + applog(LOG_WARNING, "%s%i: Does not support nonce range, disabling", + bitforce->api->name, bitforce->device_id); bitforce->nonce_range = false; bitforce->sleep_ms *= 5; bitforce->kname = KNAME_WORK; goto re_send; } - applog(LOG_ERR, "BFL%i: Error: Send work reports: %s", bitforce->device_id, pdevbuf); + applog(LOG_ERR, "%s%i: Error: Send work reports: %s", + bitforce->api->name, bitforce->device_id, buf); return false; } @@ -479,7 +426,7 @@ re_send: if (!bitforce->nonce_range) { sprintf((char *)ob + 8 + 32 + 12, ">>>>>>>>"); work->blk.nonce = bitforce->nonces = 0xffffffff; - BFwrite(fdDev, ob, 60); + len = 60; } else { uint32_t *nonce; @@ -491,26 +438,41 @@ re_send: *nonce = htobe32(work->blk.nonce + bitforce->nonces); work->blk.nonce += bitforce->nonces + 1; sprintf((char *)ob + 8 + 32 + 12 + 8, ">>>>>>>>"); - BFwrite(fdDev, ob, 68); + len = 68; + } + + if ((err = usb_write(bitforce, (char *)ob, len, &amount, C_SENDWORK)) < 0 || amount != len) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%i: send work failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + return false; + } + + if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_SENDWORKSTATUS)) < 0) { + mutex_unlock(&bitforce->device_mutex); + applog(LOG_ERR, "%s%d: read send work status failed (%d:%d)", + bitforce->api->name, bitforce->device_id, amount, err); + return false; } - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); mutex_unlock(&bitforce->device_mutex); if (opt_debug) { s = bin2hex(ob + 8, 44); - applog(LOG_DEBUG, "BFL%i: block data: %s", bitforce->device_id, s); + applog(LOG_DEBUG, "%s%i: block data: %s", + bitforce->api->name, bitforce->device_id, s); free(s); } - if (unlikely(!pdevbuf[0])) { - applog(LOG_ERR, "BFL%i: Error: Send block data returned empty string/timed out", bitforce->device_id); + if (amount == 0 || !buf[0]) { + applog(LOG_ERR, "%s%i: Error: Send block data returned empty string/timed out", + bitforce->api->name, bitforce->device_id); return false; } - if (unlikely(strncasecmp(pdevbuf, "OK", 2))) { - applog(LOG_ERR, "BFL%i: Error: Send block data reports: %s", bitforce->device_id, pdevbuf); + if (unlikely(strncasecmp(buf, "OK", 2))) { + applog(LOG_ERR, "%s%i: Error: Send block data reports: %s", + bitforce->api->name, bitforce->device_id, buf); return false; } @@ -521,53 +483,52 @@ re_send: static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) { struct cgpu_info *bitforce = thr->cgpu; - int fdDev = bitforce->device_fd; unsigned int delay_time_ms; struct timeval elapsed; struct timeval now; - char pdevbuf[0x100]; + char buf[BITFORCE_BUFSIZ+1]; + int amount; char *pnoncebuf; uint32_t nonce; - if (!fdDev) - return -1; - while (1) { if (unlikely(thr->work_restart)) return 0; mutex_lock(&bitforce->device_mutex); - BFwrite(fdDev, "ZFX", 3); - pdevbuf[0] = '\0'; - BFgets(pdevbuf, sizeof(pdevbuf), fdDev); + usb_write(bitforce, BITFORCE_WORKSTATUS, BITFORCE_WORKSTATUS_LEN, &amount, C_REQUESTWORKSTATUS); + usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETWORKSTATUS); mutex_unlock(&bitforce->device_mutex); gettimeofday(&now, NULL); timersub(&now, &bitforce->work_start_tv, &elapsed); if (elapsed.tv_sec >= BITFORCE_LONG_TIMEOUT_S) { - applog(LOG_ERR, "BFL%i: took %dms - longer than %dms", bitforce->device_id, + applog(LOG_ERR, "%s%i: took %dms - longer than %dms", + bitforce->api->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_LONG_TIMEOUT_MS); return 0; } - if (pdevbuf[0] && strncasecmp(pdevbuf, "B", 1)) /* BFL does not respond during throttling */ + if (amount > 0 && buf[0] && strncasecmp(buf, "B", 1)) /* BFL does not respond during throttling */ break; /* if BFL is throttling, no point checking so quickly */ - delay_time_ms = (pdevbuf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2 * WORK_CHECK_INTERVAL_MS); + delay_time_ms = (buf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2 * WORK_CHECK_INTERVAL_MS); nmsleep(delay_time_ms); bitforce->wait_ms += delay_time_ms; } if (elapsed.tv_sec > BITFORCE_TIMEOUT_S) { - applog(LOG_ERR, "BFL%i: took %dms - longer than %dms", bitforce->device_id, + applog(LOG_ERR, "%s%i: took %dms - longer than %dms", + bitforce->api->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_TIMEOUT_MS); dev_error(bitforce, REASON_DEV_OVER_HEAT); - if (!pdevbuf[0]) /* Only return if we got nothing after timeout - there still may be results */ + /* Only return if we got nothing after timeout - there still may be results */ + if (amount == 0) return 0; - } else if (!strncasecmp(pdevbuf, "N", 1)) {/* Hashing complete (NONCE-FOUND or NO-NONCE) */ + } else if (!strncasecmp(buf, "N", 1)) {/* Hashing complete (NONCE-FOUND or NO-NONCE) */ /* Simple timing adjustment. Allow a few polls to cope with * OS timer delays being variably reliable. wait_ms will * always equal sleep_ms when we've waited greater than or @@ -584,26 +545,31 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) } if (delay_time_ms != bitforce->sleep_ms) - applog(LOG_DEBUG, "BFL%i: Wait time changed to: %d, waited %u", bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms); + applog(LOG_DEBUG, "%s%i: Wait time changed to: %d, waited %u", + bitforce->api->name, bitforce->device_id, + bitforce->sleep_ms, bitforce->wait_ms); /* Work out the average time taken. Float for calculation, uint for display */ bitforce->avg_wait_f += (tv_to_ms(elapsed) - bitforce->avg_wait_f) / TIME_AVG_CONSTANT; bitforce->avg_wait_d = (unsigned int) (bitforce->avg_wait_f + 0.5); } - applog(LOG_DEBUG, "BFL%i: waited %dms until %s", bitforce->device_id, bitforce->wait_ms, pdevbuf); - if (!strncasecmp(&pdevbuf[2], "-", 1)) + applog(LOG_DEBUG, "%s%i: waited %dms until %s", + bitforce->api->name, bitforce->device_id, + bitforce->wait_ms, buf); + if (!strncasecmp(&buf[2], "-", 1)) return bitforce->nonces; /* No valid nonce found */ - else if (!strncasecmp(pdevbuf, "I", 1)) + else if (!strncasecmp(buf, "I", 1)) return 0; /* Device idle */ - else if (strncasecmp(pdevbuf, "NONCE-FOUND", 11)) { + else if (strncasecmp(buf, "NONCE-FOUND", 11)) { bitforce->hw_errors++; - applog(LOG_WARNING, "BFL%i: Error: Get result reports: %s", bitforce->device_id, pdevbuf); - bitforce_clear_buffer(bitforce); + applog(LOG_WARNING, "%s%i: Error: Get result reports: %s", + bitforce->api->name, bitforce->device_id, buf); + bitforce_initialise(bitforce, true); return 0; } - pnoncebuf = &pdevbuf[12]; + pnoncebuf = &buf[12]; while (1) { hex2bin((void*)&nonce, pnoncebuf, 4); @@ -612,7 +578,8 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) #endif if (unlikely(bitforce->nonce_range && (nonce >= work->blk.nonce || (work->blk.nonce > 0 && nonce < work->blk.nonce - bitforce->nonces - 1)))) { - applog(LOG_WARNING, "BFL%i: Disabling broken nonce range support", bitforce->device_id); + applog(LOG_WARNING, "%s%i: Disabling broken nonce range support", + bitforce->api->name, bitforce->device_id); bitforce->nonce_range = false; work->blk.nonce = 0xffffffff; bitforce->sleep_ms *= 5; @@ -628,19 +595,16 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) return bitforce->nonces; } -static void bitforce_shutdown(struct thr_info *thr) +static void bitforce_shutdown(__maybe_unused struct thr_info *thr) { - struct cgpu_info *bitforce = thr->cgpu; - - BFclose(bitforce->device_fd); - bitforce->device_fd = 0; +// struct cgpu_info *bitforce = thr->cgpu; } static void biforce_thread_enable(struct thr_info *thr) { struct cgpu_info *bitforce = thr->cgpu; - bitforce_init(bitforce); + bitforce_initialise(bitforce, true); } static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce) @@ -665,11 +629,11 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_ if (ret == -1) { ret = 0; - applog(LOG_ERR, "BFL%i: Comms error", bitforce->device_id); + applog(LOG_ERR, "%s%i: Comms error", bitforce->api->name, bitforce->device_id); dev_error(bitforce, REASON_DEV_COMMS_ERROR); bitforce->hw_errors++; /* empty read buffer */ - bitforce_clear_buffer(bitforce); + bitforce_initialise(bitforce, true); } return ret; } @@ -692,7 +656,8 @@ static bool bitforce_thread_init(struct thr_info *thr) /* Pause each new thread at least 100ms between initialising * so the devices aren't making calls all at the same time. */ wait = thr->id * MAX_START_DELAY_MS; - applog(LOG_DEBUG, "BFL%i: Delaying start by %dms", bitforce->device_id, wait / 1000); + applog(LOG_DEBUG, "%s%d: Delaying start by %dms", + bitforce->api->name, bitforce->device_id, wait / 1000); nmsleep(wait); return true; @@ -717,7 +682,6 @@ struct device_api bitforce_api = { .name = "BFL", .api_detect = bitforce_detect, .get_api_stats = bitforce_api_stats, - .reinit_device = bitforce_init, .get_statline_before = get_bitforce_statline_before, .get_stats = bitforce_get_stats, .identify_device = bitforce_identify, diff --git a/usbutils.c b/usbutils.c index ad3ff270..d2298dfa 100644 --- a/usbutils.c +++ b/usbutils.c @@ -36,11 +36,20 @@ #define EPO(x) (LIBUSB_ENDPOINT_OUT | (unsigned char)(x)) #ifdef WIN32 +#define BITFORCE_TIMEOUT_MS 200 #define MODMINER_TIMEOUT_MS 200 #else +#define BITFORCE_TIMEOUT_MS 100 #define MODMINER_TIMEOUT_MS 100 #endif +#ifdef USE_BITFORCE +static struct usb_endpoints bfl_eps[] = { + { LIBUSB_TRANSFER_TYPE_BULK, 512, EPI(1), 0 }, + { LIBUSB_TRANSFER_TYPE_BULK, 512, EPO(2), 0 } +}; +#endif + #ifdef USE_MODMINER static struct usb_endpoints mmq_eps[] = { { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(3), 0 }, @@ -48,7 +57,7 @@ static struct usb_endpoints mmq_eps[] = { }; #endif -// TODO: Add support for (at least) Interrupt endpoints +// TODO: Add support for (at least) Isochronous endpoints static struct usb_find_devices find_dev[] = { /* #ifdef USE_ICARUS @@ -56,10 +65,19 @@ static struct usb_find_devices find_dev[] = { { DRV_ICARUS, "LOT", 0x0403, 0x6001, false, EPI(0), EPO(0), 1 }, { DRV_ICARUS, "CM1", 0x067b, 0x0230, false, EPI(0), EPO(0), 1 }, #endif +*/ #ifdef USE_BITFORCE - { DRV_BITFORCE, "BFL", 0x0403, 0x6014, true, EPI(1), EPO(2), 1 }, + { + .drv = DRV_BITFORCE, + .name = "BFL", + .idVendor = 0x0403, + .idProduct = 0x6014, + .config = 1, + .interface = 0, + .timeout = BITFORCE_TIMEOUT_MS, + .epcount = ARRAY_SIZE(bfl_eps), + .eps = bfl_eps }, #endif -*/ #ifdef USE_MODMINER { .drv = DRV_MODMINER, @@ -160,6 +178,18 @@ static const char *C_SENDWORK_S = "SendWork"; static const char *C_SENDWORKSTATUS_S = "SendWorkStatus"; static const char *C_REQUESTWORKSTATUS_S = "RequestWorkStatus"; static const char *C_GETWORKSTATUS_S = "GetWorkStatus"; +static const char *C_REQUESTIDENTIFY_S = "RequestIdentify"; +static const char *C_GETIDENTIFY_S = "GetIdentify"; +static const char *C_REQUESTFLASH_S = "RequestFlash"; +static const char *C_REQUESTSENDWORK_S = "RequestSendWork"; +static const char *C_REQUESTSENDWORKSTATUS_S = "RequestSendWorkStatus"; +static const char *C_RESET_S = "Reset"; +static const char *C_SETBAUD_S = "SetBaud"; +static const char *C_SETDATA_S = "SetDataCtrl"; +static const char *C_SETFLOW_S = "SetFlowCtrl"; +static const char *C_SETMODEM_S = "SetModemCtrl"; +static const char *C_PURGERX_S = "PurgeRx"; +static const char *C_PURGETX_S = "PurgeTx"; #ifdef EOL #undef EOL @@ -505,6 +535,7 @@ static void cgusb_check_init() list_lock = calloc(1, sizeof(*list_lock)); mutex_init(list_lock); + // N.B. environment LIBUSB_DEBUG also sets libusb_set_debug() if (opt_usbdump >= 0) { libusb_set_debug(NULL, opt_usbdump); usb_all(); @@ -537,6 +568,18 @@ static void cgusb_check_init() usb_commands[C_SENDWORKSTATUS] = C_SENDWORKSTATUS_S; usb_commands[C_REQUESTWORKSTATUS] = C_REQUESTWORKSTATUS_S; usb_commands[C_GETWORKSTATUS] = C_GETWORKSTATUS_S; + usb_commands[C_REQUESTIDENTIFY] = C_REQUESTIDENTIFY_S; + usb_commands[C_GETIDENTIFY] = C_GETIDENTIFY_S; + usb_commands[C_REQUESTFLASH] = C_REQUESTFLASH_S; + usb_commands[C_REQUESTSENDWORK] = C_REQUESTSENDWORK_S; + usb_commands[C_REQUESTSENDWORKSTATUS] = C_REQUESTSENDWORKSTATUS_S; + usb_commands[C_RESET] = C_RESET_S; + usb_commands[C_SETBAUD] = C_SETBAUD_S; + usb_commands[C_SETDATA] = C_SETDATA_S; + usb_commands[C_SETFLOW] = C_SETFLOW_S; + usb_commands[C_SETMODEM] = C_SETMODEM_S; + usb_commands[C_PURGERX] = C_PURGERX_S; + usb_commands[C_PURGETX] = C_PURGETX_S; } mutex_unlock(&cgusb_lock); @@ -745,9 +788,9 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find } if (libusb_kernel_driver_active(cgusb->handle, 0) == 1) { - applog(LOG_WARNING, "USB init, kernel attached ..."); + applog(LOG_DEBUG, "USB init, kernel attached ..."); if (libusb_detach_kernel_driver(cgusb->handle, 0) == 0) - applog(LOG_WARNING, "USB init, kernel detached successfully"); + applog(LOG_DEBUG, "USB init, kernel detached successfully"); else applog(LOG_WARNING, "USB init, kernel detach failed :("); } @@ -773,7 +816,7 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find goto cldame; } - if ((int)(config->bNumInterfaces) < found->interface) + if ((int)(config->bNumInterfaces) <= found->interface) goto cldame; for (i = 0; i < found->epcount; i++) @@ -1118,26 +1161,42 @@ static void stats(struct cgpu_info *cgpu, struct timeval *tv_start, struct timev } #endif -int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds cmd) +int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds cmd, bool ftdi) { struct cg_usb_device *usbdev = cgpu->usbdev; #if DO_USB_STATS - struct timeval tv_start, tv_finish; + struct timeval tv_start; #endif - int err, got, tot; + struct timeval read_start, tv_finish; + unsigned int initial_timeout; + double max, done; + int err, got, tot, i; bool first = true; + if (timeout == DEVTIMEOUT) + timeout = usbdev->found->timeout; + if (eol == -1) { got = 0; STATS_TIMEVAL(&tv_start); err = libusb_bulk_transfer(usbdev->handle, usbdev->found->eps[ep].ep, (unsigned char *)buf, - bufsiz, &got, - timeout == DEVTIMEOUT ? usbdev->found->timeout : timeout); + bufsiz, &got, timeout); STATS_TIMEVAL(&tv_finish); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); + if (ftdi) { + // first 2 bytes returned are an FTDI status + if (got > 2) { + got -= 2; + memmove(buf, buf+2, got+1); + } else { + got = 0; + *buf = '\0'; + } + } + *processed = got; return err; @@ -1145,31 +1204,55 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro tot = 0; err = LIBUSB_SUCCESS; + initial_timeout = timeout; + max = ((double)timeout) / 1000.0; + gettimeofday(&read_start, NULL); while (bufsiz) { got = 0; STATS_TIMEVAL(&tv_start); err = libusb_bulk_transfer(usbdev->handle, usbdev->found->eps[ep].ep, (unsigned char *)buf, - 1, &got, - timeout == DEVTIMEOUT ? usbdev->found->timeout : timeout); - STATS_TIMEVAL(&tv_finish); + bufsiz, &got, timeout); + gettimeofday(&tv_finish, NULL); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, first ? SEQ0 : SEQ1); + if (ftdi) { + // first 2 bytes returned are an FTDI status + if (got > 2) { + got -= 2; + memmove(buf, buf+2, got+1); + } else { + got = 0; + *buf = '\0'; + } + } + tot += got; if (err) break; - if (eol == buf[0]) - break; + // WARNING - this will return data past EOL ('if' there is extra data) + for (i = 0; i < got; i++) + if (buf[i] == eol) + goto goteol; buf += got; bufsiz -= got; first = false; + + 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); } +goteol: + *processed = tot; return err; @@ -1198,6 +1281,24 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr return err; } +int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout, enum usb_cmds cmd) +{ + struct cg_usb_device *usbdev = cgpu->usbdev; +#if DO_USB_STATS + struct timeval tv_start, tv_finish; +#endif + int err; + + STATS_TIMEVAL(&tv_start); + err = libusb_control_transfer(usbdev->handle, request_type, + bRequest, wValue, wIndex, NULL, 0, + timeout == DEVTIMEOUT ? usbdev->found->timeout : timeout); + STATS_TIMEVAL(&tv_finish); + USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); + + return err; +} + void usb_cleanup() { // TODO: diff --git a/usbutils.h b/usbutils.h index 71fd9699..156e2a2d 100644 --- a/usbutils.h +++ b/usbutils.h @@ -12,6 +12,29 @@ #include +// for 0x0403/0x6014 FT232H (and possibly others?) +#define FTDI_TYPE_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT) + +#define FTDI_REQUEST_RESET ((uint8_t)0) +#define FTDI_REQUEST_MODEM ((uint8_t)1) +#define FTDI_REQUEST_FLOW ((uint8_t)2) +#define FTDI_REQUEST_BAUD ((uint8_t)3) +#define FTDI_REQUEST_DATA ((uint8_t)4) + +#define FTDI_VALUE_RESET 0 +#define FTDI_VALUE_PURGE_RX 1 +#define FTDI_VALUE_PURGE_TX 2 + +// baud with a 0 divisor is 120,000,000/10 +//#define FTDI_VALUE_BAUD (0) +//#define FTDI_INDEX_BAUD (0) +#define FTDI_VALUE_BAUD 0xc068 +#define FTDI_INDEX_BAUD 0x0200 + +#define FTDI_VALUE_DATA 0 +#define FTDI_VALUE_FLOW 0 +#define FTDI_VALUE_MODEM 0x0303 + // Use the device defined timeout #define DEVTIMEOUT 0 @@ -78,6 +101,18 @@ enum usb_cmds { C_SENDWORKSTATUS, C_REQUESTWORKSTATUS, C_GETWORKSTATUS, + C_REQUESTIDENTIFY, + C_GETIDENTIFY, + C_REQUESTFLASH, + C_REQUESTSENDWORK, + C_REQUESTSENDWORKSTATUS, + C_RESET, + C_SETBAUD, + C_SETDATA, + C_SETFLOW, + C_SETMODEM, + C_PURGERX, + C_PURGETX, C_MAX }; @@ -89,21 +124,25 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find void usb_detect(struct device_api *api, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); struct api_data *api_usb_stats(int *count); void update_usb_stats(struct cgpu_info *cgpu); -int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds); +int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds, bool ftdi); int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, enum usb_cmds); +int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout, enum usb_cmds cmd); void usb_cleanup(); #define usb_read(cgpu, buf, bufsiz, read, cmd) \ - _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd) + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, -1, cmd, false) + +#define usb_read_nl(cgpu, buf, bufsiz, read, cmd) \ + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, '\n', cmd, false) #define usb_read_ep(cgpu, ep, buf, bufsiz, read, cmd) \ - _usb_read(cgpu, ep, buf, bufsiz, read, DEVTIMEOUT, -1, cmd) + _usb_read(cgpu, ep, buf, bufsiz, read, DEVTIMEOUT, -1, cmd, false) #define usb_read_timeout(cgpu, buf, bufsiz, read, timeout, cmd) \ - _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, timeout, -1, cmd) + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, timeout, -1, cmd, false) #define usb_read_ep_timeout(cgpu, ep, buf, bufsiz, read, timeout, cmd) \ - _usb_read(cgpu, ep, buf, bufsiz, read, timeout, -1, cmd) + _usb_read(cgpu, ep, buf, bufsiz, read, timeout, -1, cmd, false) #define usb_write(cgpu, buf, bufsiz, wrote, cmd) \ _usb_write(cgpu, DEFAULT_EP_OUT, buf, bufsiz, wrote, DEVTIMEOUT, cmd) @@ -117,4 +156,10 @@ void usb_cleanup(); #define usb_write_ep_timeout(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) \ _usb_write(cgpu, ep, buf, bufsiz, wrote, timeout, cmd) +#define usb_ftdi_read_nl(cgpu, buf, bufsiz, read, cmd) \ + _usb_read(cgpu, DEFAULT_EP_IN, buf, bufsiz, read, DEVTIMEOUT, '\n', cmd, true) + +#define usb_transfer(cgpu, typ, req, val, idx, cmd) \ + _usb_transfer(cgpu, typ, req, val, idx, DEVTIMEOUT, cmd) + #endif From 040ec589fa4dfdecfb1ae04b94e88e1b4588ff9f Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 09:09:43 +1100 Subject: [PATCH 02/87] BFL USB build changes --- Makefile.am | 6 +++++- configure.ac | 7 ++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 5f846289..b7f90637 100644 --- a/Makefile.am +++ b/Makefile.am @@ -82,6 +82,10 @@ if NEED_FPGAUTILS cgminer_SOURCES += fpgautils.c fpgautils.h endif +if NEED_USBUTILS_C +cgminer_SOURCES += usbutils.c +endif + if HAS_BITFORCE cgminer_SOURCES += driver-bitforce.c endif @@ -91,7 +95,7 @@ cgminer_SOURCES += driver-icarus.c endif if HAS_MODMINER -cgminer_SOURCES += driver-modminer.c usbutils.c +cgminer_SOURCES += driver-modminer.c bitstreamsdir = $(bindir)/bitstreams dist_bitstreams_DATA = bitstreams/* endif diff --git a/configure.ac b/configure.ac index 3b51f73a..67a70bee 100644 --- a/configure.ac +++ b/configure.ac @@ -273,6 +273,7 @@ fi AM_CONDITIONAL([NEED_FPGAUTILS], [test x$icarus$bitforce$modminer$ztex != xnononono]) +AM_CONDITIONAL([NEED_USBUTILS_C], [test x$bitforce$modminer != xnono]) AM_CONDITIONAL([HAVE_CURSES], [test x$curses = xyes]) AM_CONDITIONAL([WANT_JANSSON], [test x$request_jansson = xtrue]) AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = xtrue]) @@ -321,7 +322,7 @@ fi AM_CONDITIONAL([HAS_YASM], [test x$has_yasm = xtrue]) -if test "x$bitforce" != xno; then +if test "x$icarus" != xno; then AC_ARG_WITH([libudev], [AC_HELP_STRING([--without-libudev], [Autodetect FPGAs using libudev (default enabled)])], [libudev=$withval], [libudev=auto] @@ -343,7 +344,7 @@ AM_CONDITIONAL([HAVE_LIBUDEV], [test x$libudev != xno]) PKG_PROG_PKG_CONFIG() -if test "x$ztex$modminer" != xnono; then +if test "x$ztex$modminer$bitforce" != xnonono; then case $target in *-*-freebsd*) LIBUSB_LIBS="-lusb" @@ -508,7 +509,7 @@ else echo " Ztex.FPGAs...........: Disabled" fi -if test "x$bitforce" != xno; then +if test "x$icarus" != xno; then echo " libudev.detection....: $libudev" fi From b0996152461abe61522b4cc173f9f51bc22dfa99 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 13:04:53 +1100 Subject: [PATCH 03/87] BFL report USB device numbers for init errors and allow faster 'reinit' --- driver-bitforce.c | 70 +++++++++++++++++++++++++++-------------------- usbutils.c | 5 ++++ 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index 62c40636..57d2115c 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -58,7 +58,9 @@ // If initialisation fails the first time, // sleep this amount (ms) and try again -#define REINIT_TIME_MS 6000 +#define REINIT_TIME_MS 1000 +// But try this many times +#define REINIT_COUNT 6 static const char *blank = ""; @@ -108,18 +110,18 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) bitforce->api->name, bitforce->device_id, err); // Clear any sent data -// err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, -// FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); -// if (opt_debug) -// applog(LOG_DEBUG, "%s%i: purgetx got err %d", -// bitforce->api->name, bitforce->device_id, err); + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, + FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: purgetx got err %d", + bitforce->api->name, bitforce->device_id, err); // Clear any received data -// err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, -// FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); -// if (opt_debug) -// applog(LOG_DEBUG, "%s%i: purgerx got err %d", -// bitforce->api->name, bitforce->device_id, err); + err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, + FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); + if (opt_debug) + applog(LOG_DEBUG, "%s%i: purgerx got err %d", + bitforce->api->name, bitforce->device_id, err); if (lock) mutex_unlock(&bitforce->device_mutex); @@ -139,36 +141,49 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic bitforce->threads = 1; if (!usb_init(bitforce, dev, found)) { - applog(LOG_ERR, "%s detect: failed to initialise (incorrect device?)", bitforce->api->dname); + applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", + bitforce->api->dname, + (int)libusb_get_bus_number(dev), + (int)libusb_get_device_address(dev)); goto shin; } - int init_counter = 0; + sprintf(devpath, "%d:%d", + (int)(bitforce->usbdev->bus_number), + (int)(bitforce->usbdev->device_address)); + + int init_count = 0; reinit: bitforce_initialise(bitforce, false); if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { - applog(LOG_ERR, "%s detect: send identify request failed (%d:%d)", - bitforce->api->dname, amount, err); + applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", + bitforce->api->dname, devpath, amount, err); goto unshin; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { // Maybe it was still processing previous work? - if (init_counter++ < 1) { - applog(LOG_WARNING, "%s detect: 1st init failed - retrying in %dms (%d:%d)", - bitforce->api->dname, REINIT_TIME_MS, amount, err); + if (++init_count <= REINIT_COUNT) { + if (init_count < 2) { + applog(LOG_WARNING, "%s detect (%s) 1st init failed - retrying (%d:%d)", + bitforce->api->dname, devpath, amount, err); + } nmsleep(REINIT_TIME_MS); goto reinit; } + if (init_count > 0) + applog(LOG_WARNING, "%s detect (%s) init failed %d times", + bitforce->api->dname, devpath, init_count); + if (err < 0) { - applog(LOG_ERR, "%s detect: error identify reply (%d:%d)", - bitforce->api->dname, amount, err); + applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", + bitforce->api->dname, devpath, amount, err); } else { - applog(LOG_ERR, "%s detect: empty identify reply (%d)", - bitforce->api->dname, amount); + applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", + bitforce->api->dname, devpath, amount); } goto unshin; @@ -176,8 +191,8 @@ reinit: buf[amount] = '\0'; if (unlikely(!strstr(buf, "SHA256"))) { - applog(LOG_ERR, "%s detect: didn't recognise %s", - bitforce->api->dname, buf); + applog(LOG_ERR, "%s detect (%s) didn't recognise '%s'", + bitforce->api->dname, devpath, buf); goto unshin; } @@ -189,7 +204,8 @@ reinit: } // We have a real BitForce! - applog(LOG_DEBUG, "%s identified as: '%s'", bitforce->api->dname, bitforce->name); + applog(LOG_DEBUG, "%s (%s) identified as: '%s'", + bitforce->api->dname, devpath, bitforce->name); /* Initially enable support for nonce range and disable it later if it * fails */ @@ -202,10 +218,6 @@ reinit: bitforce->kname = KNAME_WORK; } - sprintf(devpath, "%d:%d", - (int)(bitforce->usbdev->bus_number), - (int)(bitforce->usbdev->device_address)); - bitforce->device_path = strdup(devpath); if (!add_cgpu(bitforce)) diff --git a/usbutils.c b/usbutils.c index d2298dfa..4b126177 100644 --- a/usbutils.c +++ b/usbutils.c @@ -45,8 +45,13 @@ #ifdef USE_BITFORCE static struct usb_endpoints bfl_eps[] = { +#ifdef WIN32 + { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 }, + { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 } +#else { LIBUSB_TRANSFER_TYPE_BULK, 512, EPI(1), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 512, EPO(2), 0 } +#endif }; #endif From 70b47a770d5181330826fd84b1640714da2a5793 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 13:25:19 +1100 Subject: [PATCH 04/87] BFL USB - README and FPGA-README --- FPGA-README | 25 ++++++++++++++----------- README | 18 ++++++++++-------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/FPGA-README b/FPGA-README index a970df72..5a1e6a34 100644 --- a/FPGA-README +++ b/FPGA-README @@ -2,15 +2,8 @@ This README contains extended details about FPGA mining with cgminer -ModMinerQuad (MMQ) ------------------- - -The mining bitstream does not survive a power cycle, so cgminer will upload -it, if it needs to, before it starts mining (approx 7min 40sec) - -The red LED also flashes while it is uploading the bitstream - -- +For ModMinerQuad (MMQ) and BitForce (BFL) +----------------------------------------- When mining on windows, the driver being used will determine if mining will work. @@ -39,7 +32,17 @@ problems: --usb-dump 0 -It will only help if you have a working MMQ device attached to the computer +It will only help if you have a working MMQ or BFL device attached to the +computer + + +ModMinerQuad (MMQ) +------------------ + +The mining bitstream does not survive a power cycle, so cgminer will upload +it, if it needs to, before it starts mining (approx 7min 40sec) + +The red LED also flashes while it is uploading the bitstream - @@ -130,7 +133,7 @@ modem-manager software TODO: check that all MMQ's have the same product ID -Bitforce (BFL) +BitForce (BFL) -------------- --bfl-range Use nonce range on bitforce devices if supported diff --git a/README b/README index 8865529c..fd310154 100644 --- a/README +++ b/README @@ -220,15 +220,16 @@ SCRYPT only options: See SCRYPT-README for more information regarding litecoin mining. -FPGA mining boards(BitForce, Icarus, ModMiner, Ztex) only options: +FPGA mining boards (BitForce, Icarus, ModMiner, Ztex) only options: -cgminer will automatically find your ModMiner or Ztex FPGAs +cgminer will automatically find your ModMiner, BitForce or Ztex FPGAs +independent of the --scan-serial options specified below ---scan-serial|-S Serial port to probe for FPGA mining device +--scan-serial|-S Serial port to probe for Icarus mining device -This option is only for BitForce and/or Icarus FPGAs +This option is only for Icarus bitstream FPGAs -By default, cgminer will scan for autodetected FPGAs unless at least one +By default, cgminer will scan for autodetected Icarus unless at least one -S is specified for that driver. If you specify -S and still want cgminer to scan, you must also use "-S auto". If you want to prevent cgminer from scanning without specifying a device, you can use "-S noauto". Note that @@ -237,13 +238,14 @@ device depending on the version of udev being used. On linux is usually of the format /dev/ttyUSBn On windows is usually of the format \\.\COMn -(where n = the correct device number for the FPGA device) +(where n = the correct device number for the Icarus device) The official supplied binaries are compiled with support for all FPGAs. To force the code to only attempt detection with a specific driver, prepend the argument with the driver name followed by a colon. -For example, "icarus:/dev/ttyUSB0" or "bitforce:\\.\COM5" -or using the short name: "ica:/dev/ttyUSB0" or "bfl:\\.\COM5" +For example, "icarus:/dev/ttyUSB0" or using the short name: "ica:/dev/ttyUSB0" +This option not longer matters since Icarus is the only serial-USB +device that uses it For other FPGA details see the FPGA-README From 03c2cabab2cca31731c4a2e1940a331d8fd7b7d7 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 31 Dec 2012 23:46:03 +1100 Subject: [PATCH 05/87] BFL include all USB requirements --- miner.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/miner.h b/miner.h index f777a30d..5a6e89a1 100644 --- a/miner.h +++ b/miner.h @@ -114,7 +114,7 @@ static inline int fsync (int fd) #include "libztex.h" #endif -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) #include "usbutils.h" #endif @@ -374,13 +374,17 @@ struct cgpu_info { #ifdef USE_ZTEX struct libztex_device *device_ztex; #endif -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) struct cg_usb_device *usbdev; #endif +#ifdef USE_ICARUS int device_fd; +#endif }; -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) int usbstat; +#endif +#ifdef USE_MODMINER char fpgaid; unsigned char clock; pthread_mutex_t *modminer_mutex; From 07db1ed6874d96c08910275e6bc53ef745ab5933 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 1 Jan 2013 00:29:17 +1100 Subject: [PATCH 06/87] BFL USB api.c usbstats --- api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api.c b/api.c index 659d934a..1d29dbb9 100644 --- a/api.c +++ b/api.c @@ -3120,7 +3120,7 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may { struct api_data *root = NULL; -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) char buf[TMPBUFSIZ]; bool io_open = false; int count = 0; @@ -3133,7 +3133,7 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may return; } -#ifdef USE_MODMINER +#if defined(USE_MODMINER) || defined(USE_BITFORCE) message(io_data, MSG_USBSTA, 0, NULL, isjson); From 211b0f4ea15dcd88012232cb31e537cc8b61f490 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 21:18:08 +1100 Subject: [PATCH 07/87] BFL USB longer timeout --- usbutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/usbutils.c b/usbutils.c index 4b126177..0d9e79aa 100644 --- a/usbutils.c +++ b/usbutils.c @@ -36,10 +36,10 @@ #define EPO(x) (LIBUSB_ENDPOINT_OUT | (unsigned char)(x)) #ifdef WIN32 -#define BITFORCE_TIMEOUT_MS 200 +#define BITFORCE_TIMEOUT_MS 500 #define MODMINER_TIMEOUT_MS 200 #else -#define BITFORCE_TIMEOUT_MS 100 +#define BITFORCE_TIMEOUT_MS 200 #define MODMINER_TIMEOUT_MS 100 #endif From 03f626e68d1a90fde0441cf39d932238bf0edab6 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 21:51:09 +1100 Subject: [PATCH 08/87] Remember best share per pool and return in API pools --- API-README | 9 ++++++++- api.c | 1 + cgminer.c | 2 ++ miner.h | 1 + 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/API-README b/API-README index b205c90b..a71b694f 100644 --- a/API-README +++ b/API-README @@ -400,7 +400,14 @@ miner.php - an example web page to access the API Feature Changelog for external applications using the API: -API V1.23 +API V1.24 + +Modified API commands: + 'pools' - add 'Best Share' + +---------- + +API V1.23 (cgminer v2.10.2) Added API commands: 'pgaset' - with: MMQ opt=clock val=160 to 230 (and a multiple of 2) diff --git a/api.c b/api.c index 659d934a..94b1d5ce 100644 --- a/api.c +++ b/api.c @@ -1993,6 +1993,7 @@ static void poolstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m else root = api_add_const(root, "Stratum URL", BLANK, false); root = api_add_bool(root, "Has GBT", &(pool->has_gbt), false); + root = api_add_uint64(root, "Best Share", &(pool->best_diff), true); root = print_data(root, buf, isjson, isjson && (i > 0)); io_add(io_data, buf); diff --git a/cgminer.c b/cgminer.c index 876abeda..b33bb7fa 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2349,6 +2349,8 @@ static uint64_t share_diff(const struct work *work) best_diff = ret; suffix_string(best_diff, best_share, 0); } + if (ret > work->pool->best_diff) + work->pool->best_diff = ret; mutex_unlock(&control_lock); return ret; } diff --git a/miner.h b/miner.h index df2888e9..79a4cf27 100644 --- a/miner.h +++ b/miner.h @@ -920,6 +920,7 @@ struct pool { time_t last_share_time; double last_share_diff; + uint64_t best_diff; struct cgminer_stats cgminer_stats; struct cgminer_pool_stats cgminer_pool_stats; From abaaf93c8dc8714594d9d29490a195d8ed9df377 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 21:52:38 +1100 Subject: [PATCH 09/87] Correct API version to match docs --- api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.c b/api.c index 94b1d5ce..207dfd71 100644 --- a/api.c +++ b/api.c @@ -133,7 +133,7 @@ static const char SEPARATOR = '|'; #define SEPSTR "|" static const char GPUSEP = ','; -static const char *APIVERSION = "1.23"; +static const char *APIVERSION = "1.24"; static const char *DEAD = "Dead"; #if defined(HAVE_OPENCL) || defined(HAVE_AN_FPGA) static const char *SICK = "Sick"; From 4c2f26e28062143b2a9e8793bb57903080b8fbb1 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 22:34:05 +1100 Subject: [PATCH 10/87] zero (most) API stats --- cgminer.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/cgminer.c b/cgminer.c index b33bb7fa..0c2d8c2c 100644 --- a/cgminer.c +++ b/cgminer.c @@ -3935,6 +3935,10 @@ void zero_stats(void) total_diff1 = 0; memset(best_share, 0, 8); suffix_string(best_diff, best_share, 0); + found_blocks = 0; + total_diff_accepted = 0; + total_diff_rejected = 0; + total_diff_stale = 0; for (i = 0; i < total_pools; i++) { struct pool *pool = pools[i]; @@ -3946,6 +3950,13 @@ void zero_stats(void) pool->discarded_work = 0; pool->getfail_occasions = 0; pool->remotefail_occasions = 0; + pool->last_share_time = 0; + pool->diff1 = 0; + pool->diff_accepted = 0; + pool->diff_rejected = 0; + pool->diff_stale = 0; + pool->last_share_diff = 0; + pool->best_diff = 0; } mutex_lock(&hash_lock); @@ -3957,6 +3968,11 @@ void zero_stats(void) cgpu->rejected = 0; cgpu->hw_errors = 0; cgpu->utility = 0.0; + cgpu->last_share_pool_time = 0; + cgpu->diff1 = 0; + cgpu->diff_accepted = 0; + cgpu->diff_rejected = 0; + cgpu->last_share_diff = 0; } mutex_unlock(&hash_lock); } From 44ec75528219686b68ec9e50b8de8236f90f8439 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 2 Jan 2013 22:43:48 +1100 Subject: [PATCH 11/87] BFL USB correct usb stats id --- driver-bitforce.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/driver-bitforce.c b/driver-bitforce.c index 57d2115c..4a06b597 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -223,6 +223,8 @@ reinit: if (!add_cgpu(bitforce)) goto unshin; + update_usb_stats(bitforce); + mutex_init(&bitforce->device_mutex); return true; From 1b2654e1ff02de4d92724b695c4c758d3c2aa9f4 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 4 Jan 2013 16:07:10 +1100 Subject: [PATCH 12/87] miner.php optional user/pass login restrictions --- API-README | 32 +++++++ miner.php | 246 +++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 233 insertions(+), 45 deletions(-) diff --git a/API-README b/API-README index a71b694f..14f8b53c 100644 --- a/API-README +++ b/API-README @@ -937,6 +937,38 @@ true --------- +Default: + $userlist = null; + +Define password checking and default access + null means there is no password checking + +$userlist is an array of 3 arrays e.g. +$userlist = array('sys' => array('boss' => 'bpass'), + 'usr' => array('user' => 'upass', 'pleb' => 'ppass'), + 'def' => array('Pools')); + +'sys' is an array of system users and passwords (full access) +'usr' is an array of user level users and passwords (readonly access) +'def' is an array of custompages that anyone not logged in can view + +Any of the 3 can be null, meaning there are none of that item + +All validated 'usr' users are given $readonly = true; access +All validated 'sys' users are given the $readonly access you defined + +If 'def' has one or more values, and allowcustompages is true, then +anyone without a password can see the list of custompage buttons given +in 'def' and will see the first one when they go to the web page, with +a login button at the top right + +From the login page, if you login with no username or password, it will +show the first 'def' custompage (if there are any) + +If you are logged in, it will show a logout button at the top right + +--------- + Default: $notify = true; diff --git a/miner.php b/miner.php index 8c393ac8..b0e80030 100644 --- a/miner.php +++ b/miner.php @@ -8,7 +8,7 @@ global $checklastshare, $poolinputs, $hidefields; global $ignorerefresh, $changerefresh, $autorefresh; global $allowcustompages, $customsummarypages; global $miner_font_family, $miner_font_size; -global $colouroverride, $placebuttons; +global $colouroverride, $placebuttons, $userlist; # # See API-README for more details of these variables and how # to configure miner.php @@ -20,6 +20,9 @@ $title = 'Mine'; # Set $readonly to false then it will check cgminer 'privileged' $readonly = false; # +# Set $userlist to null to allow anyone access or read API-README +$userlist = null; +# # Set $notify to false to NOT attempt to display the notify command # Set $notify to true to attempt to display the notify command $notify = true; @@ -212,6 +215,10 @@ $rigerror = array(); global $rownum; $rownum = 0; # +// Login +global $ses; +$ses = 'rutroh'; +# function getcss($cssname, $dom = false) { global $colourtable, $colouroverride; @@ -239,7 +246,7 @@ function getdom($domname) return getcss($domname, true); } # -function htmlhead($checkapi, $rig, $pg = null) +function htmlhead($checkapi, $rig, $pg = null, $noscript = false) { global $title, $miner_font_family, $miner_font_size; global $error, $readonly, $poolinputs, $here; @@ -285,8 +292,10 @@ td.lst { $miner_font ".getcss('td.lst')."} td.hi { $miner_font ".getcss('td.hi')."} td.lo { $miner_font ".getcss('td.lo')."} - -\n"; +} ?> -
@@ -1507,7 +1517,6 @@ function doforeach($cmd, $des, $sum, $head, $datetime) # function refreshbuttons() { - global $readonly; global $ignorerefresh, $changerefresh, $autorefresh; if ($ignorerefresh == false && $changerefresh == true) @@ -1521,7 +1530,7 @@ function refreshbuttons() # function pagebuttons($rig, $pg) { - global $readonly, $rigs; + global $readonly, $rigs, $userlist, $ses; global $allowcustompages, $customsummarypages; if ($rig === null) @@ -1557,18 +1566,33 @@ function pagebuttons($rig, $pg) } echo '"; } # @@ -2410,13 +2440,126 @@ function showcustompage($pagename) pagebuttons(null, $pagename); } # +function onlylogin() +{ + global $here; + + htmlhead(false, null, null, true); + +?> + + +No rigs defined"); + return; + } if ($ignorerefresh == false) { @@ -2425,52 +2568,65 @@ function display() $autorefresh = intval($ref); } - $rig = trim(getparam('rig', true)); - - $arg = trim(getparam('arg', true)); - $preprocess = null; - if ($arg != null and $arg != '') + if ($pagesonly !== true) { - $num = null; - if ($rig != null and $rig != '') - { - if ($rig >= 0 and $rig < count($rigs)) - $num = $rig; - } - else - if (count($rigs) == 0) - $num = 0; + $rig = trim(getparam('rig', true)); - if ($num != null) + $arg = trim(getparam('arg', true)); + $preprocess = null; + if ($arg != null and $arg != '') { - $parts = explode(':', $rigs[$num], 3); - if (count($parts) >= 2) + if ($rig != null and $rig != '' and $rig >= 0 and $rig < count($rigs)) { - $miner = $parts[0]; - $port = $parts[1]; + $parts = explode(':', $rigs[$rig], 3); + if (count($parts) >= 2) + { + $miner = $parts[0]; + $port = $parts[1]; - if ($readonly !== true) - $preprocess = $arg; + if ($readonly !== true) + $preprocess = $arg; + } } } } - if ($rigs == null or count($rigs) == 0) - { - otherrow(""); - return; - } - if ($allowcustompages === true) { $pg = trim(getparam('pg', true)); - if ($pg != null && $pg != '') + if ($pagesonly === true) + { + if ($pg !== null && $pg !== '') + { + if ($userlist !== null && isset($userlist['def']) + && !in_array($pg, $userlist['def'])) + $pg = null; + } + else + { + if ($userlist !== null && isset($userlist['def'])) + foreach ($userlist['def'] as $pglook) + if (isset($customsummarypages[$pglook])) + { + $pg = $pglook; + break; + } + } + } + + if ($pg !== null && $pg !== '') { showcustompage($pg); return; } } + if ($pagesonly === true) + { + onlylogin(); + return; + } + if (count($rigs) == 1) { $parts = explode(':', $rigs[0], 3); From f6bde14c3113ec85f4743584a9900b3c81b387f7 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 4 Jan 2013 17:45:54 +1100 Subject: [PATCH 13/87] miner.php user/pass fix 'usr' is readonly --- miner.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner.php b/miner.php index b0e80030..9215a21e 100644 --- a/miner.php +++ b/miner.php @@ -2476,7 +2476,7 @@ function onlylogin() function checklogin() { global $allowcustompages, $customsummarypages; - global $userlist, $ses; + global $readonly, $userlist, $ses; $out = trim(getparam('logout', true)); if ($out !== null && $out !== '' && isset($_SESSION[$ses])) From 7724989d9bd59f458b0c873c09c0fff9e291f152 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 5 Jan 2013 10:40:32 +1100 Subject: [PATCH 14/87] diffexactone pool diff1 used for share value calculation is ffffffff... not 100000000... :P --- cgminer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index 0c2d8c2c..19ffcb98 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2576,7 +2576,7 @@ static inline struct pool *select_pool(bool lagging) return pool; } -static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249216.0; +static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249215.0; /* * Calculate the work share difficulty From a344deb6ac8605a57c96eb03cb7ec9b17c4575b7 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 5 Jan 2013 23:47:26 +1100 Subject: [PATCH 15/87] rename device_api -> device_drv and all related api -> drv and add a device_drv->drv enum for identifying which driver each is --- api.c | 64 ++++++++++--------------- cgminer.c | 119 +++++++++++++++++++++++----------------------- driver-bitforce.c | 87 ++++++++++++++++----------------- driver-cpu.c | 6 +-- driver-cpu.h | 2 +- driver-icarus.c | 11 +++-- driver-modminer.c | 93 ++++++++++++++++++------------------ driver-opencl.c | 38 +++++---------- driver-opencl.h | 2 +- driver-ztex.c | 10 ++-- findnonce.c | 2 +- fpgautils.c | 10 ++-- fpgautils.h | 14 +++--- miner.h | 19 ++++++-- usbutils.c | 38 +++++++-------- usbutils.h | 4 +- 16 files changed, 253 insertions(+), 266 deletions(-) diff --git a/api.c b/api.c index 3561c7ab..2e013ff4 100644 --- a/api.c +++ b/api.c @@ -599,22 +599,6 @@ struct APIGROUPS { static struct IP4ACCESS *ipaccess = NULL; static int ips = 0; -#ifdef USE_BITFORCE -extern struct device_api bitforce_api; -#endif - -#ifdef USE_ICARUS -extern struct device_api icarus_api; -#endif - -#ifdef USE_ZTEX -extern struct device_api ztex_api; -#endif - -#ifdef USE_MODMINER -extern struct device_api modminer_api; -#endif - struct io_data { size_t siz; char *ptr; @@ -1153,19 +1137,19 @@ static int numpgas() for (i = 0; i < total_devices; i++) { #ifdef USE_BITFORCE - if (devices[i]->api == &bitforce_api) + if (devices[i]->drv->drv == DRIVER_BITFORCE) count++; #endif #ifdef USE_ICARUS - if (devices[i]->api == &icarus_api) + if (devices[i]->drv->drv == DRIVER_ICARUS) count++; #endif #ifdef USE_ZTEX - if (devices[i]->api == &ztex_api) + if (devices[i]->drv->drv == DRIVER_ZTEX) count++; #endif #ifdef USE_MODMINER - if (devices[i]->api == &modminer_api) + if (devices[i]->drv->drv == DRIVER_MODMINER) count++; #endif } @@ -1179,19 +1163,19 @@ static int pgadevice(int pgaid) for (i = 0; i < total_devices; i++) { #ifdef USE_BITFORCE - if (devices[i]->api == &bitforce_api) + if (devices[i]->drv->drv == DRIVER_BITFORCE) count++; #endif #ifdef USE_ICARUS - if (devices[i]->api == &icarus_api) + if (devices[i]->drv->drv == DRIVER_ICARUS) count++; #endif #ifdef USE_ZTEX - if (devices[i]->api == &ztex_api) + if (devices[i]->drv->drv == DRIVER_ZTEX) count++; #endif #ifdef USE_MODMINER - if (devices[i]->api == &modminer_api) + if (devices[i]->drv->drv == DRIVER_MODMINER) count++; #endif if (count == (pgaid + 1)) @@ -1535,11 +1519,11 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom float temp = cgpu->temp; #ifdef USE_ZTEX - if (cgpu->api == &ztex_api && cgpu->device_ztex) + if (cgpu->drv->drv == DRIVER_ZTEX && cgpu->device_ztex) frequency = cgpu->device_ztex->freqM1 * (cgpu->device_ztex->freqM + 1); #endif #ifdef USE_MODMINER - if (cgpu->api == &modminer_api) + if (cgpu->drv->drv == DRIVER_MODMINER) frequency = cgpu->clock; #endif @@ -1553,7 +1537,7 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom status = (char *)status2str(cgpu->status); root = api_add_int(root, "PGA", &pga, false); - root = api_add_string(root, "Name", cgpu->api->name, false); + root = api_add_string(root, "Name", cgpu->drv->name, false); root = api_add_int(root, "ID", &(cgpu->device_id), false); root = api_add_string(root, "Enabled", enabled, false); root = api_add_string(root, "Status", status, false); @@ -1868,12 +1852,12 @@ static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, ch } struct cgpu_info *cgpu = devices[dev]; - struct device_api *api = cgpu->api; + struct device_drv *drv = cgpu->drv; - if (!api->identify_device) + if (!drv->identify_device) message(io_data, MSG_PGANOID, id, NULL, isjson); else { - api->identify_device(cgpu); + drv->identify_device(cgpu); message(io_data, MSG_PGAIDENT, id, NULL, isjson); } } @@ -2753,7 +2737,7 @@ void notifystatus(struct io_data *io_data, int device, struct cgpu_info *cgpu, b // ALL counters (and only counters) must start the name with a '*' // Simplifies future external support for identifying new counters root = api_add_int(root, "NOTIFY", &device, false); - root = api_add_string(root, "Name", cgpu->api->name, false); + root = api_add_string(root, "Name", cgpu->drv->name, false); root = api_add_int(root, "ID", &(cgpu->device_id), false); root = api_add_time(root, "Last Well", &(cgpu->device_last_well), false); root = api_add_time(root, "Last Not Well", &(cgpu->device_last_not_well), false); @@ -2817,9 +2801,9 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m cgpu = devices[i]; root = api_add_int(root, "DEVDETAILS", &i, false); - root = api_add_string(root, "Name", cgpu->api->name, false); + root = api_add_string(root, "Name", cgpu->drv->name, false); root = api_add_int(root, "ID", &(cgpu->device_id), false); - root = api_add_string(root, "Driver", cgpu->api->dname, false); + root = api_add_string(root, "Driver", cgpu->drv->dname, false); root = api_add_const(root, "Kernel", cgpu->kname ? : BLANK, false); root = api_add_const(root, "Model", cgpu->name ? : BLANK, false); root = api_add_const(root, "Device Path", cgpu->device_path ? : BLANK, false); @@ -2923,13 +2907,13 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m for (j = 0; j < total_devices; j++) { struct cgpu_info *cgpu = devices[j]; - if (cgpu && cgpu->api) { - if (cgpu->api->get_api_stats) - extra = cgpu->api->get_api_stats(cgpu); + if (cgpu && cgpu->drv) { + if (cgpu->drv->get_api_stats) + extra = cgpu->drv->get_api_stats(cgpu); else extra = NULL; - sprintf(id, "%s%d", cgpu->api->name, cgpu->device_id); + sprintf(id, "%s%d", cgpu->drv->name, cgpu->device_id); i = itemstats(io_data, i, id, &(cgpu->cgminer_stats), NULL, extra, isjson); } } @@ -3195,16 +3179,16 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe } struct cgpu_info *cgpu = devices[dev]; - struct device_api *api = cgpu->api; + struct device_drv *drv = cgpu->drv; char *set = strchr(opt, ','); if (set) *(set++) = '\0'; - if (!api->set_device) + if (!drv->set_device) message(io_data, MSG_PGANOSET, id, NULL, isjson); else { - char *ret = api->set_device(cgpu, opt, set, buf); + char *ret = drv->set_device(cgpu, opt, set, buf); if (ret) { if (strcasecmp(opt, "help") == 0) message(io_data, MSG_PGAHELP, id, ret, isjson); diff --git a/cgminer.c b/cgminer.c index 19ffcb98..adf7db45 100644 --- a/cgminer.c +++ b/cgminer.c @@ -385,7 +385,7 @@ static void sharelog(const char*disposition, const struct work*work) data = bin2hex(work->data, sizeof(work->data)); // timestamp,disposition,target,pool,dev,thr,sharehash,sharedata - rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s%u,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->api->name, cgpu->device_id, thr_id, hash, data); + rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s%u,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->drv->name, cgpu->device_id, thr_id, hash, data); free(target); free(hash); free(data); @@ -1875,9 +1875,9 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) suffix_string(dh64, displayed_hashes, 4); suffix_string(dr64, displayed_rolling, 4); - sprintf(buf, "%s%d ", cgpu->api->name, cgpu->device_id); - if (cgpu->api->get_statline_before) - cgpu->api->get_statline_before(buf, cgpu); + sprintf(buf, "%s%d ", cgpu->drv->name, cgpu->device_id); + if (cgpu->drv->get_statline_before) + cgpu->drv->get_statline_before(buf, cgpu); else tailsprintf(buf, " | "); tailsprintf(buf, "(%ds):%s (avg):%sh/s | A:%d R:%d HW:%d U:%.1f/m", @@ -1888,8 +1888,8 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) cgpu->rejected, cgpu->hw_errors, cgpu->utility); - if (cgpu->api->get_statline) - cgpu->api->get_statline(buf, cgpu); + if (cgpu->drv->get_statline) + cgpu->drv->get_statline(buf, cgpu); } static void text_print_status(int thr_id) @@ -1971,10 +1971,10 @@ static void curses_print_devstatus(int thr_id) cgpu->utility = cgpu->accepted / total_secs * 60; wmove(statuswin,devcursor + cgpu->cgminer_id, 0); - wprintw(statuswin, " %s %*d: ", cgpu->api->name, dev_width, cgpu->device_id); - if (cgpu->api->get_statline_before) { + wprintw(statuswin, " %s %*d: ", cgpu->drv->name, dev_width, cgpu->device_id); + if (cgpu->drv->get_statline_before) { logline[0] = '\0'; - cgpu->api->get_statline_before(logline, cgpu); + cgpu->drv->get_statline_before(logline, cgpu); wprintw(statuswin, "%s", logline); } else @@ -2007,9 +2007,9 @@ static void curses_print_devstatus(int thr_id) hwwidth, cgpu->hw_errors, uwidth + 3, cgpu->utility); - if (cgpu->api->get_statline) { + if (cgpu->drv->get_statline) { logline[0] = '\0'; - cgpu->api->get_statline(logline, cgpu); + cgpu->drv->get_statline(logline, cgpu); wprintw(statuswin, "%s", logline); } @@ -2234,10 +2234,10 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, if (!QUIET) { if (total_pools > 1) applog(LOG_NOTICE, "Accepted %s %s %d pool %d %s%s", - hashshow, cgpu->api->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime); + hashshow, cgpu->drv->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime); else applog(LOG_NOTICE, "Accepted %s %s %d %s%s", - hashshow, cgpu->api->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime); + hashshow, cgpu->drv->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime); } sharelog("accept", work); if (opt_shares && total_accepted >= opt_shares) { @@ -2302,7 +2302,7 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, } applog(LOG_NOTICE, "Rejected %s %s %d %s%s %s%s", - hashshow, cgpu->api->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime); + hashshow, cgpu->drv->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime); sharelog(disposition, work); } @@ -5238,15 +5238,15 @@ static bool hashtest(struct thr_info *thr, struct work *work) if (hash2_32[7] != 0) { applog(LOG_WARNING, "%s%d: invalid nonce - HW error", - thr->cgpu->api->name, thr->cgpu->device_id); + thr->cgpu->drv->name, thr->cgpu->device_id); mutex_lock(&stats_lock); hw_errors++; thr->cgpu->hw_errors++; mutex_unlock(&stats_lock); - if (thr->cgpu->api->hw_error) - thr->cgpu->api->hw_error(thr); + if (thr->cgpu->drv->hw_error) + thr->cgpu->drv->hw_error(thr); goto out; } @@ -5294,7 +5294,7 @@ static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64 } static void mt_disable(struct thr_info *mythr, const int thr_id, - struct device_api *api) + struct device_drv *drv) { applog(LOG_WARNING, "Thread %d being disabled", thr_id); mythr->rolling = mythr->cgpu->rolling = 0; @@ -5305,8 +5305,8 @@ static void mt_disable(struct thr_info *mythr, const int thr_id, } while (mythr->pause); thread_reportin(mythr); applog(LOG_WARNING, "Thread %d being re-enabled", thr_id); - if (api->thread_enable) - api->thread_enable(mythr); + if (drv->thread_enable) + drv->thread_enable(mythr); } void *miner_thread(void *userdata) @@ -5314,7 +5314,7 @@ void *miner_thread(void *userdata) struct thr_info *mythr = userdata; const int thr_id = mythr->id; struct cgpu_info *cgpu = mythr->cgpu; - struct device_api *api = cgpu->api; + struct device_drv *drv = cgpu->drv; struct cgminer_stats *dev_stats = &(cgpu->cgminer_stats); struct cgminer_stats *pool_stats; struct timeval getwork_start; @@ -5323,7 +5323,7 @@ void *miner_thread(void *userdata) const long cycle = opt_log_interval / 5 ? : 1; struct timeval tv_start, tv_end, tv_workstart, tv_lastupdate; struct timeval diff, sdiff, wdiff = {0, 0}; - uint32_t max_nonce = api->can_limit_work ? api->can_limit_work(mythr) : 0xffffffff; + uint32_t max_nonce = drv->can_limit_work ? drv->can_limit_work(mythr) : 0xffffffff; int64_t hashes_done = 0; int64_t hashes; struct work *work; @@ -5337,7 +5337,7 @@ void *miner_thread(void *userdata) gettimeofday(&getwork_start, NULL); - if (api->thread_init && !api->thread_init(mythr)) { + if (drv->thread_init && !drv->thread_init(mythr)) { dev_error(cgpu, REASON_THREAD_FAIL_INIT); goto out; } @@ -5357,7 +5357,7 @@ void *miner_thread(void *userdata) gettimeofday(&tv_workstart, NULL); work->blk.nonce = 0; cgpu->max_hashes = 0; - if (api->prepare_work && !api->prepare_work(mythr, work)) { + if (drv->prepare_work && !drv->prepare_work(mythr, work)) { applog(LOG_ERR, "work prepare failed, exiting " "mining thread %d", thr_id); break; @@ -5399,16 +5399,16 @@ void *miner_thread(void *userdata) gettimeofday(&(work->tv_work_start), NULL); thread_reportin(mythr); - hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce); + hashes = drv->scanhash(mythr, work, work->blk.nonce + max_nonce); thread_reportin(mythr); gettimeofday(&getwork_start, NULL); if (unlikely(hashes == -1)) { - applog(LOG_ERR, "%s %d failure, disabling!", api->name, cgpu->device_id); + applog(LOG_ERR, "%s %d failure, disabling!", drv->name, cgpu->device_id); cgpu->deven = DEV_DISABLED; dev_error(cgpu, REASON_THREAD_ZERO_HASH); - mt_disable(mythr, thr_id, api); + mt_disable(mythr, thr_id, drv); } hashes_done += hashes; @@ -5429,7 +5429,7 @@ void *miner_thread(void *userdata) if (unlikely((long)sdiff.tv_sec < cycle)) { int mult; - if (likely(!api->can_limit_work || max_nonce == 0xffffffff)) + if (likely(!drv->can_limit_work || max_nonce == 0xffffffff)) continue; mult = 1000000 / ((sdiff.tv_usec + 0x400) / 0x400) + 0x10; @@ -5438,9 +5438,9 @@ void *miner_thread(void *userdata) max_nonce = 0xffffffff; else max_nonce = (max_nonce * mult) / 0x400; - } else if (unlikely(sdiff.tv_sec > cycle) && api->can_limit_work) + } else if (unlikely(sdiff.tv_sec > cycle) && drv->can_limit_work) max_nonce = max_nonce * cycle / sdiff.tv_sec; - else if (unlikely(sdiff.tv_usec > 100000) && api->can_limit_work) + else if (unlikely(sdiff.tv_usec > 100000) && drv->can_limit_work) max_nonce = max_nonce * 0x400 / (((cycle * 1000000) + sdiff.tv_usec) / (cycle * 1000000 / 0x400)); timersub(&tv_end, &tv_lastupdate, &diff); @@ -5466,7 +5466,7 @@ void *miner_thread(void *userdata) } if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED)) - mt_disable(mythr, thr_id, api); + mt_disable(mythr, thr_id, drv); sdiff.tv_sec = sdiff.tv_usec = 0; } while (!abandon_work(work, &wdiff, cgpu->max_hashes)); @@ -5474,8 +5474,8 @@ void *miner_thread(void *userdata) } out: - if (api->thread_shutdown) - api->thread_shutdown(mythr); + if (drv->thread_shutdown) + drv->thread_shutdown(mythr); thread_reportin(mythr); applog(LOG_ERR, "Thread %d failure, exiting", thr_id); @@ -5703,8 +5703,8 @@ out: void reinit_device(struct cgpu_info *cgpu) { - if (cgpu->api->reinit_device) - cgpu->api->reinit_device(cgpu); + if (cgpu->drv->reinit_device) + cgpu->drv->reinit_device(cgpu); } static struct timeval rotate_tv; @@ -5879,12 +5879,12 @@ static void *watchdog_thread(void __maybe_unused *userdata) char dev_str[8]; int gpu; - if (cgpu->api->get_stats) - cgpu->api->get_stats(cgpu); + if (cgpu->drv->get_stats) + cgpu->drv->get_stats(cgpu); gpu = cgpu->device_id; denable = &cgpu->deven; - sprintf(dev_str, "%s%d", cgpu->api->name, gpu); + sprintf(dev_str, "%s%d", cgpu->drv->name, gpu); #ifdef HAVE_ADL if (adl_active && cgpu->has_adl) @@ -5904,7 +5904,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) continue; #ifdef WANT_CPUMINE - if (!strcmp(cgpu->api->dname, "cpu")) + if (cgpu->drv->drv != DRIVER_CPU) continue; #endif if (cgpu->status != LIFE_WELL && (now.tv_sec - thr->last.tv_sec < WATCHDOG_SICK_TIME)) { @@ -6294,26 +6294,27 @@ void enable_curses(void) { /* TODO: fix need a dummy CPU device_api even if no support for CPU mining */ #ifndef WANT_CPUMINE -struct device_api cpu_api; -struct device_api cpu_api = { +struct device_drv cpu_drv; +struct device_drv cpu_drv = { + .drv = DRIVER_CPU, .name = "CPU", }; #endif #ifdef USE_BITFORCE -extern struct device_api bitforce_api; +extern struct device_drv bitforce_drv; #endif #ifdef USE_ICARUS -extern struct device_api icarus_api; +extern struct device_drv icarus_drv; #endif #ifdef USE_MODMINER -extern struct device_api modminer_api; +extern struct device_drv modminer_drv; #endif #ifdef USE_ZTEX -extern struct device_api ztex_api; +extern struct device_drv ztex_drv; #endif @@ -6328,7 +6329,7 @@ void enable_device(struct cgpu_info *cgpu) adj_width(mining_threads, &dev_width); #endif #ifdef HAVE_OPENCL - if (cgpu->api == &opencl_api) { + if (cgpu->drv->drv == DRIVER_OPENCL) { gpu_threads += cgpu->threads; } #endif @@ -6345,12 +6346,12 @@ bool add_cgpu(struct cgpu_info*cgpu) static struct _cgpu_devid_counter *devids = NULL; struct _cgpu_devid_counter *d; - HASH_FIND_STR(devids, cgpu->api->name, d); + HASH_FIND_STR(devids, cgpu->drv->name, d); if (d) cgpu->device_id = ++d->lastid; else { d = malloc(sizeof(*d)); - memcpy(d->name, cgpu->api->name, sizeof(d->name)); + memcpy(d->name, cgpu->drv->name, sizeof(d->name)); cgpu->device_id = d->lastid = 0; HASH_ADD_STR(devids, name, d); } @@ -6568,32 +6569,32 @@ int main(int argc, char *argv[]) #ifdef HAVE_OPENCL if (!opt_nogpu) - opencl_api.api_detect(); + opencl_drv.drv_detect(); gpu_threads = 0; #endif #ifdef USE_ICARUS if (!opt_scrypt) - icarus_api.api_detect(); + icarus_drv.drv_detect(); #endif #ifdef USE_BITFORCE if (!opt_scrypt) - bitforce_api.api_detect(); + bitforce_drv.drv_detect(); #endif #ifdef USE_MODMINER if (!opt_scrypt) - modminer_api.api_detect(); + modminer_drv.drv_detect(); #endif #ifdef USE_ZTEX if (!opt_scrypt) - ztex_api.api_detect(); + ztex_drv.drv_detect(); #endif #ifdef WANT_CPUMINE - cpu_api.api_detect(); + cpu_drv.drv_detect(); #endif if (devices_enabled == -1) { @@ -6601,9 +6602,9 @@ int main(int argc, char *argv[]) for (i = 0; i < total_devices; ++i) { struct cgpu_info *cgpu = devices[i]; if (cgpu->name) - applog(LOG_ERR, " %2d. %s %d: %s (driver: %s)", i, cgpu->api->name, cgpu->device_id, cgpu->name, cgpu->api->dname); + applog(LOG_ERR, " %2d. %s %d: %s (driver: %s)", i, cgpu->drv->name, cgpu->device_id, cgpu->name, cgpu->drv->dname); else - applog(LOG_ERR, " %2d. %s %d (driver: %s)", i, cgpu->api->name, cgpu->device_id, cgpu->api->dname); + applog(LOG_ERR, " %2d. %s %d (driver: %s)", i, cgpu->drv->name, cgpu->device_id, cgpu->drv->dname); } quit(0, "%d devices listed", total_devices); } @@ -6617,7 +6618,7 @@ int main(int argc, char *argv[]) enable_device(devices[i]); } else if (i < total_devices) { if (opt_removedisabled) { - if (devices[i]->api == &cpu_api) + if (devices[i]->drv->drv == DRIVER_CPU) --opt_n_threads; } else { enable_device(devices[i]); @@ -6789,7 +6790,7 @@ begin_bench: thr->q = tq_new(); if (!thr->q) - quit(1, "tq_new failed in starting %s%d mining thread (#%d)", cgpu->api->name, cgpu->device_id, i); + quit(1, "tq_new failed in starting %s%d mining thread (#%d)", cgpu->drv->name, cgpu->device_id, i); /* Enable threads for devices set not to mine but disable * their queue in case we wish to enable them later */ @@ -6799,7 +6800,7 @@ begin_bench: tq_push(thr->q, &ping); } - if (cgpu->api->thread_prepare && !cgpu->api->thread_prepare(thr)) + if (cgpu->drv->thread_prepare && !cgpu->drv->thread_prepare(thr)) continue; thread_reportout(thr); diff --git a/driver-bitforce.c b/driver-bitforce.c index 4a06b597..f1196322 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -64,7 +64,7 @@ static const char *blank = ""; -struct device_api bitforce_api; +struct device_drv bitforce_drv; static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) { @@ -78,14 +78,14 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) FTDI_VALUE_RESET, bitforce->usbdev->found->interface, C_RESET); if (opt_debug) applog(LOG_DEBUG, "%s%i: reset got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Set data control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, FTDI_VALUE_DATA, bitforce->usbdev->found->interface, C_SETDATA); if (opt_debug) applog(LOG_DEBUG, "%s%i: setdata got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Set the baud err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD, @@ -93,35 +93,35 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) C_SETBAUD); if (opt_debug) applog(LOG_DEBUG, "%s%i: setbaud got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Set Flow Control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, FTDI_VALUE_FLOW, bitforce->usbdev->found->interface, C_SETFLOW); if (opt_debug) applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Set Modem Control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM, FTDI_VALUE_MODEM, bitforce->usbdev->found->interface, C_SETMODEM); if (opt_debug) applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Clear any sent data err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); if (opt_debug) applog(LOG_DEBUG, "%s%i: purgetx got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); // Clear any received data err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); if (opt_debug) applog(LOG_DEBUG, "%s%i: purgerx got err %d", - bitforce->api->name, bitforce->device_id, err); + bitforce->drv->name, bitforce->device_id, err); if (lock) mutex_unlock(&bitforce->device_mutex); @@ -136,13 +136,13 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic struct cgpu_info *bitforce = NULL; bitforce = calloc(1, sizeof(*bitforce)); - bitforce->api = &bitforce_api; + bitforce->drv = &bitforce_drv; bitforce->deven = DEV_ENABLED; bitforce->threads = 1; if (!usb_init(bitforce, dev, found)) { applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", - bitforce->api->dname, + bitforce->drv->dname, (int)libusb_get_bus_number(dev), (int)libusb_get_device_address(dev)); goto shin; @@ -159,7 +159,7 @@ reinit: if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", - bitforce->api->dname, devpath, amount, err); + bitforce->drv->dname, devpath, amount, err); goto unshin; } @@ -168,7 +168,7 @@ reinit: if (++init_count <= REINIT_COUNT) { if (init_count < 2) { applog(LOG_WARNING, "%s detect (%s) 1st init failed - retrying (%d:%d)", - bitforce->api->dname, devpath, amount, err); + bitforce->drv->dname, devpath, amount, err); } nmsleep(REINIT_TIME_MS); goto reinit; @@ -176,14 +176,14 @@ reinit: if (init_count > 0) applog(LOG_WARNING, "%s detect (%s) init failed %d times", - bitforce->api->dname, devpath, init_count); + bitforce->drv->dname, devpath, init_count); if (err < 0) { applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", - bitforce->api->dname, devpath, amount, err); + bitforce->drv->dname, devpath, amount, err); } else { applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", - bitforce->api->dname, devpath, amount); + bitforce->drv->dname, devpath, amount); } goto unshin; @@ -192,7 +192,7 @@ reinit: if (unlikely(!strstr(buf, "SHA256"))) { applog(LOG_ERR, "%s detect (%s) didn't recognise '%s'", - bitforce->api->dname, devpath, buf); + bitforce->drv->dname, devpath, buf); goto unshin; } @@ -205,7 +205,7 @@ reinit: // We have a real BitForce! applog(LOG_DEBUG, "%s (%s) identified as: '%s'", - bitforce->api->dname, devpath, bitforce->name); + bitforce->drv->dname, devpath, bitforce->name); /* Initially enable support for nonce range and disable it later if it * fails */ @@ -247,7 +247,7 @@ shin: static void bitforce_detect(void) { - usb_detect(&bitforce_api, bitforce_detect_one); + usb_detect(&bitforce_drv, bitforce_detect_one); } static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce) @@ -288,7 +288,7 @@ static void bitforce_flash_led(struct cgpu_info *bitforce) if ((err = usb_write(bitforce, BITFORCE_FLASH, BITFORCE_FLASH_LEN, &amount, C_REQUESTFLASH)) < 0 || amount != BITFORCE_FLASH_LEN) { applog(LOG_ERR, "%s%i: flash request failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); } else { /* However, this stops anything else getting a reply * So best to delay any other access to the BFL */ @@ -328,7 +328,7 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) if ((err = usb_write(bitforce, BITFORCE_TEMPERATURE, BITFORCE_TEMPERATURE_LEN, &amount, C_REQUESTTEMPERATURE)) < 0 || amount != BITFORCE_TEMPERATURE_LEN) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%i: Error: Request temp invalid/timed out (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); bitforce->hw_errors++; return false; } @@ -337,10 +337,10 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) mutex_unlock(&bitforce->device_mutex); if (err < 0) { applog(LOG_ERR, "%s%i: Error: Get temp return invalid/timed out (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); } else { applog(LOG_ERR, "%s%i: Error: Get temp returned nothing (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); } bitforce->hw_errors++; return false; @@ -360,7 +360,7 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) bitforce->temp = temp; if (unlikely(bitforce->cutofftemp > 0 && temp > bitforce->cutofftemp)) { applog(LOG_WARNING, "%s%i: Hit thermal cutoff limit, disabling!", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); bitforce->deven = DEV_RECOVER; dev_error(bitforce, REASON_DEV_THERMAL_CUTOFF); } @@ -370,7 +370,7 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) * our responses are out of sync and flush the buffer to * hopefully recover */ applog(LOG_WARNING, "%s%i: Garbled response probably throttling, clearing buffer", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); dev_error(bitforce, REASON_DEV_THROTTLE); /* Count throttling episodes as hardware errors */ bitforce->hw_errors++; @@ -404,14 +404,14 @@ re_send: if ((err = usb_write(bitforce, cmd, len, &amount, C_REQUESTSENDWORK)) < 0 || amount != len) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%i: request send work failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); return false; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_REQUESTSENDWORKSTATUS)) < 0) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%d: read request send work status failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); return false; } @@ -423,14 +423,14 @@ re_send: mutex_unlock(&bitforce->device_mutex); if (bitforce->nonce_range) { applog(LOG_WARNING, "%s%i: Does not support nonce range, disabling", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); bitforce->nonce_range = false; bitforce->sleep_ms *= 5; bitforce->kname = KNAME_WORK; goto re_send; } applog(LOG_ERR, "%s%i: Error: Send work reports: %s", - bitforce->api->name, bitforce->device_id, buf); + bitforce->drv->name, bitforce->device_id, buf); return false; } @@ -458,14 +458,14 @@ re_send: if ((err = usb_write(bitforce, (char *)ob, len, &amount, C_SENDWORK)) < 0 || amount != len) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%i: send work failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); return false; } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_SENDWORKSTATUS)) < 0) { mutex_unlock(&bitforce->device_mutex); applog(LOG_ERR, "%s%d: read send work status failed (%d:%d)", - bitforce->api->name, bitforce->device_id, amount, err); + bitforce->drv->name, bitforce->device_id, amount, err); return false; } @@ -474,19 +474,19 @@ re_send: if (opt_debug) { s = bin2hex(ob + 8, 44); applog(LOG_DEBUG, "%s%i: block data: %s", - bitforce->api->name, bitforce->device_id, s); + bitforce->drv->name, bitforce->device_id, s); free(s); } if (amount == 0 || !buf[0]) { applog(LOG_ERR, "%s%i: Error: Send block data returned empty string/timed out", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); return false; } if (unlikely(strncasecmp(buf, "OK", 2))) { applog(LOG_ERR, "%s%i: Error: Send block data reports: %s", - bitforce->api->name, bitforce->device_id, buf); + bitforce->drv->name, bitforce->device_id, buf); return false; } @@ -519,7 +519,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) if (elapsed.tv_sec >= BITFORCE_LONG_TIMEOUT_S) { applog(LOG_ERR, "%s%i: took %dms - longer than %dms", - bitforce->api->name, bitforce->device_id, + bitforce->drv->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_LONG_TIMEOUT_MS); return 0; } @@ -535,7 +535,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) if (elapsed.tv_sec > BITFORCE_TIMEOUT_S) { applog(LOG_ERR, "%s%i: took %dms - longer than %dms", - bitforce->api->name, bitforce->device_id, + bitforce->drv->name, bitforce->device_id, tv_to_ms(elapsed), BITFORCE_TIMEOUT_MS); dev_error(bitforce, REASON_DEV_OVER_HEAT); @@ -560,7 +560,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) if (delay_time_ms != bitforce->sleep_ms) applog(LOG_DEBUG, "%s%i: Wait time changed to: %d, waited %u", - bitforce->api->name, bitforce->device_id, + bitforce->drv->name, bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms); /* Work out the average time taken. Float for calculation, uint for display */ @@ -569,7 +569,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) } applog(LOG_DEBUG, "%s%i: waited %dms until %s", - bitforce->api->name, bitforce->device_id, + bitforce->drv->name, bitforce->device_id, bitforce->wait_ms, buf); if (!strncasecmp(&buf[2], "-", 1)) return bitforce->nonces; /* No valid nonce found */ @@ -578,7 +578,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) else if (strncasecmp(buf, "NONCE-FOUND", 11)) { bitforce->hw_errors++; applog(LOG_WARNING, "%s%i: Error: Get result reports: %s", - bitforce->api->name, bitforce->device_id, buf); + bitforce->drv->name, bitforce->device_id, buf); bitforce_initialise(bitforce, true); return 0; } @@ -593,7 +593,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) if (unlikely(bitforce->nonce_range && (nonce >= work->blk.nonce || (work->blk.nonce > 0 && nonce < work->blk.nonce - bitforce->nonces - 1)))) { applog(LOG_WARNING, "%s%i: Disabling broken nonce range support", - bitforce->api->name, bitforce->device_id); + bitforce->drv->name, bitforce->device_id); bitforce->nonce_range = false; work->blk.nonce = 0xffffffff; bitforce->sleep_ms *= 5; @@ -643,7 +643,7 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_ if (ret == -1) { ret = 0; - applog(LOG_ERR, "%s%i: Comms error", bitforce->api->name, bitforce->device_id); + applog(LOG_ERR, "%s%i: Comms error", bitforce->drv->name, bitforce->device_id); dev_error(bitforce, REASON_DEV_COMMS_ERROR); bitforce->hw_errors++; /* empty read buffer */ @@ -671,7 +671,7 @@ static bool bitforce_thread_init(struct thr_info *thr) * so the devices aren't making calls all at the same time. */ wait = thr->id * MAX_START_DELAY_MS; applog(LOG_DEBUG, "%s%d: Delaying start by %dms", - bitforce->api->name, bitforce->device_id, wait / 1000); + bitforce->drv->name, bitforce->device_id, wait / 1000); nmsleep(wait); return true; @@ -691,10 +691,11 @@ static struct api_data *bitforce_api_stats(struct cgpu_info *cgpu) return root; } -struct device_api bitforce_api = { +struct device_drv bitforce_drv = { + .drv = DRIVER_BITFORCE, .dname = "bitforce", .name = "BFL", - .api_detect = bitforce_detect, + .drv_detect = bitforce_detect, .get_api_stats = bitforce_api_stats, .get_statline_before = get_bitforce_statline_before, .get_stats = bitforce_get_stats, diff --git a/driver-cpu.c b/driver-cpu.c index 75d9a5a4..99c5a3fa 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -758,7 +758,7 @@ static void cpu_detect() struct cgpu_info *cgpu; cgpu = &cpus[i]; - cgpu->api = &cpu_api; + cgpu->drv = &cpu_drv; cgpu->deven = DEV_ENABLED; cgpu->threads = 1; cgpu->kname = algo_names[opt_algo]; @@ -843,10 +843,10 @@ CPUSearch: return last_nonce - first_nonce + 1; } -struct device_api cpu_api = { +struct device_drv cpu_drv = { .dname = "cpu", .name = "CPU", - .api_detect = cpu_detect, + .drv_detect = cpu_detect, .reinit_device = reinit_cpu_device, .thread_prepare = cpu_thread_prepare, .can_limit_work = cpu_can_limit_work, diff --git a/driver-cpu.h b/driver-cpu.h index e4b44527..361ae5d8 100644 --- a/driver-cpu.h +++ b/driver-cpu.h @@ -53,7 +53,7 @@ enum sha256_algos { extern const char *algo_names[]; extern bool opt_usecpu; -extern struct device_api cpu_api; +extern struct device_drv cpu_drv; extern char *set_algo(const char *arg, enum sha256_algos *algo); extern void show_algo(char buf[OPT_SHOW_LEN], const enum sha256_algos *algo); diff --git a/driver-icarus.c b/driver-icarus.c index c979a681..f42e7214 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -208,7 +208,7 @@ static struct ICARUS_INFO **icarus_info; // static int option_offset = -1; -struct device_api icarus_api; +struct device_drv icarus_drv; static void rev(unsigned char *s, size_t l) { @@ -571,7 +571,7 @@ static bool icarus_detect_one(const char *devpath) /* We have a real Icarus! */ struct cgpu_info *icarus; icarus = calloc(1, sizeof(struct cgpu_info)); - icarus->api = &icarus_api; + icarus->drv = &icarus_drv; icarus->device_path = strdup(devpath); icarus->device_fd = -1; icarus->threads = 1; @@ -609,7 +609,7 @@ static bool icarus_detect_one(const char *devpath) static void icarus_detect() { - serial_detect(&icarus_api, icarus_detect_one); + serial_detect(&icarus_drv, icarus_detect_one); } static bool icarus_prepare(struct thr_info *thr) @@ -900,10 +900,11 @@ static void icarus_shutdown(struct thr_info *thr) do_icarus_close(thr); } -struct device_api icarus_api = { +struct device_drv icarus_drv = { + .drv = DRIVER_ICARUS, .dname = "icarus", .name = "ICA", - .api_detect = icarus_detect, + .drv_detect = icarus_detect, .get_api_stats = icarus_api_stats, .thread_prepare = icarus_prepare, .scanhash = icarus_scanhash, diff --git a/driver-modminer.c b/driver-modminer.c index c48a51bc..0868e85e 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -87,7 +87,7 @@ // Limit when reducing shares_to_good #define MODMINER_MIN_BACK 12 -struct device_api modminer_api; +struct device_drv modminer_drv; // 45 noops sent when detecting, in case the device was left in "start job" reading static const char NOOP[] = MODMINER_PING "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; @@ -100,15 +100,15 @@ static void do_ping(struct cgpu_info *modminer) // Don't care if it fails err = usb_write(modminer, (char *)NOOP, sizeof(NOOP)-1, &amount, C_PING); applog(LOG_DEBUG, "%s%u: flush noop got %d err %d", - modminer->api->name, modminer->fpgaid, amount, err); + modminer->drv->name, modminer->fpgaid, amount, err); // Clear any outstanding data while ((err = usb_read(modminer, buf, sizeof(buf)-1, &amount, C_CLEAR)) == 0 && amount > 0) applog(LOG_DEBUG, "%s%u: clear got %d", - modminer->api->name, modminer->fpgaid, amount); + modminer->drv->name, modminer->fpgaid, amount); applog(LOG_DEBUG, "%s%u: final clear got %d err %d", - modminer->api->name, modminer->fpgaid, amount, err); + modminer->drv->name, modminer->fpgaid, amount, err); } static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devices *found) @@ -121,7 +121,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic struct cgpu_info *modminer = NULL; modminer = calloc(1, sizeof(*modminer)); - modminer->api = &modminer_api; + modminer->drv = &modminer_drv; modminer->modminer_mutex = calloc(1, sizeof(*(modminer->modminer_mutex))); mutex_init(modminer->modminer_mutex); modminer->fpgaid = (char)0; @@ -182,7 +182,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic for (i = 0; i < buf[0]; i++) { struct cgpu_info *tmp = calloc(1, sizeof(*tmp)); - tmp->api = modminer->api; + tmp->drv = modminer->drv; tmp->name = devname; sprintf(devpath, "%d:%d:%d", @@ -233,7 +233,7 @@ shin: static void modminer_detect() { - usb_detect(&modminer_api, modminer_detect_one); + usb_detect(&modminer_drv, modminer_detect_one); } static bool get_expect(struct cgpu_info *modminer, FILE *f, char c) @@ -242,13 +242,13 @@ static bool get_expect(struct cgpu_info *modminer, FILE *f, char c) if (fread(&buf, 1, 1, f) != 1) { applog(LOG_ERR, "%s%u: Error (%d) reading bitstream (%c)", - modminer->api->name, modminer->device_id, errno, c); + modminer->drv->name, modminer->device_id, errno, c); return false; } if (buf != c) { applog(LOG_ERR, "%s%u: firmware code mismatch (%c)", - modminer->api->name, modminer->device_id, c); + modminer->drv->name, modminer->device_id, c); return false; } @@ -262,7 +262,7 @@ static bool get_info(struct cgpu_info *modminer, FILE *f, char *buf, int bufsiz, if (fread(siz, 2, 1, f) != 1) { applog(LOG_ERR, "%s%u: Error (%d) reading bitstream '%s' len", - modminer->api->name, modminer->device_id, errno, name); + modminer->drv->name, modminer->device_id, errno, name); return false; } @@ -270,13 +270,13 @@ static bool get_info(struct cgpu_info *modminer, FILE *f, char *buf, int bufsiz, if (len >= bufsiz) { applog(LOG_ERR, "%s%u: Bitstream '%s' len too large (%d)", - modminer->api->name, modminer->device_id, name, len); + modminer->drv->name, modminer->device_id, name, len); return false; } if (fread(buf, len, 1, f) != 1) { applog(LOG_ERR, "%s%u: Error (%d) reading bitstream '%s'", errno, - modminer->api->name, modminer->device_id, errno, name); + modminer->drv->name, modminer->device_id, errno, name); return false; } @@ -302,7 +302,7 @@ static bool get_status_timeout(struct cgpu_info *modminer, char *msg, unsigned i mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d:%d) getting %s reply", - modminer->api->name, modminer->device_id, amount, err, msg); + modminer->drv->name, modminer->device_id, amount, err, msg); return false; } @@ -311,7 +311,7 @@ static bool get_status_timeout(struct cgpu_info *modminer, char *msg, unsigned i mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error, invalid %s reply (was %d should be 1)", - modminer->api->name, modminer->device_id, msg, buf[0]); + modminer->drv->name, modminer->device_id, msg, buf[0]); return false; } @@ -343,7 +343,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d) opening bitstream file %s", - modminer->api->name, modminer->device_id, errno, bsfile); + modminer->drv->name, modminer->device_id, errno, bsfile); return false; } @@ -352,7 +352,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d) reading bitstream magic", - modminer->api->name, modminer->device_id, errno); + modminer->drv->name, modminer->device_id, errno); goto dame; } @@ -361,7 +361,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: bitstream has incorrect magic (%u,%u) instead of (%u,%u)", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, buf[0], buf[1], BITSTREAM_MAGIC_0, BITSTREAM_MAGIC_1); @@ -372,7 +372,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d) bitstream seek failed", - modminer->api->name, modminer->device_id, errno); + modminer->drv->name, modminer->device_id, errno); goto dame; } @@ -384,7 +384,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) goto undame; applog(LOG_DEBUG, "%s%u: bitstream file '%s' info:", - modminer->api->name, modminer->device_id, bsfile); + modminer->drv->name, modminer->device_id, bsfile); applog(LOG_DEBUG, " Design name: '%s'", buf); @@ -399,7 +399,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Bad usercode in bitstream file", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); goto dame; } @@ -408,7 +408,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: bitstream doesn't support user code", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); goto dame; } @@ -446,7 +446,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error (%d) reading bitstream data len", - modminer->api->name, modminer->device_id, errno); + modminer->drv->name, modminer->device_id, errno); goto dame; } @@ -460,7 +460,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) *ptr = '\0'; applog(LOG_WARNING, "%s%u: Programming all FPGA on %s ... Mining will not start until complete", - modminer->api->name, modminer->device_id, devmsg); + modminer->drv->name, modminer->device_id, devmsg); buf[0] = MODMINER_PROGRAM; buf[1] = fpgaid; @@ -473,7 +473,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Program init failed (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); goto dame; } @@ -492,7 +492,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: bitstream file read error %d (%d bytes left)", - modminer->api->name, modminer->device_id, errno, len); + modminer->drv->name, modminer->device_id, errno, len); goto dame; } @@ -507,7 +507,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) if (opt_debug) applog(LOG_DEBUG, "%s%u: Program timeout (%d:%d) sent %d tries %d", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, amount, err, remaining, tries); if (!get_status(modminer, "write status", C_PROGRAMSTATUS2)) @@ -517,7 +517,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Program failed (%d:%d) sent %d", - modminer->api->name, modminer->device_id, amount, err, remaining); + modminer->drv->name, modminer->device_id, amount, err, remaining); goto dame; } @@ -532,7 +532,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) if (upto >= nextmsg) { applog(LOG_WARNING, "%s%u: Programming %.1f%% (%d out of %d)", - modminer->api->name, modminer->device_id, upto*100, (totlen - len), totlen); + modminer->drv->name, modminer->device_id, upto*100, (totlen - len), totlen); nextmsg += 0.1; } @@ -542,7 +542,7 @@ static bool modminer_fpga_upload_bitstream(struct cgpu_info *modminer) goto undame; applog(LOG_WARNING, "%s%u: Programming completed for all FPGA on %s", - modminer->api->name, modminer->device_id, devmsg); + modminer->drv->name, modminer->device_id, devmsg); // Give it a 2/3s delay after programming nmsleep(666); @@ -653,7 +653,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error writing set clock speed (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return clocksetfail; } @@ -662,7 +662,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error reading set clock speed (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return clockreplyfail; } @@ -670,7 +670,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te mutex_unlock(modminer->modminer_mutex); applog(LOG_WARNING, "%s%u: Set clock speed %sto %u", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, (delta < 0) ? "down " : (delta > 0 ? "up " : ""), modminer->clock); @@ -691,7 +691,7 @@ static bool modminer_fpga_init(struct thr_info *thr) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error requesting USER code (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return false; } @@ -700,14 +700,14 @@ static bool modminer_fpga_init(struct thr_info *thr) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Error reading USER code (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return false; } if (memcmp(buf, BISTREAM_USER_ID, 4)) { applog(LOG_ERR, "%s%u: FPGA not programmed", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); if (!modminer_fpga_upload_bitstream(modminer)) return false; @@ -717,7 +717,7 @@ static bool modminer_fpga_init(struct thr_info *thr) mutex_unlock(modminer->modminer_mutex); applog(LOG_DEBUG, "%s%u: FPGA is already programmed :)", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); } modminer->clock = MODMINER_DEF_CLOCK; @@ -773,7 +773,7 @@ static bool modminer_start_work(struct thr_info *thr) mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Start work failed (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return false; } @@ -827,14 +827,14 @@ static void check_temperature(struct thr_info *thr) if (modminer->temp < MODMINER_RECOVER_TEMP) { state->overheated = false; applog(LOG_WARNING, "%s%u: Recovered, temp less than (%.1f) now %.3f", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, MODMINER_RECOVER_TEMP, modminer->temp); } } else if (modminer->temp >= MODMINER_OVERHEAT_TEMP) { if (modminer->temp >= MODMINER_CUTOFF_TEMP) { applog(LOG_WARNING, "%s%u: Hit thermal cutoff limit! (%.1f) at %.3f", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, MODMINER_CUTOFF_TEMP, modminer->temp); modminer_delta_clock(thr, MODMINER_CLOCK_CUTOFF, true, false); @@ -842,7 +842,7 @@ static void check_temperature(struct thr_info *thr) dev_error(modminer, REASON_DEV_THERMAL_CUTOFF); } else { applog(LOG_WARNING, "%s%u: Overheat limit (%.1f) reached %.3f", - modminer->api->name, modminer->device_id, + modminer->drv->name, modminer->device_id, MODMINER_OVERHEAT_TEMP, modminer->temp); // If it's defined to be 0 then don't call modminer_delta_clock() @@ -909,7 +909,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) } applog(LOG_ERR, "%s%u: Error sending (get nonce) (%d:%d)", - modminer->api->name, modminer->device_id, amount, err); + modminer->drv->name, modminer->device_id, amount, err); return -1; } @@ -936,7 +936,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) } applog(LOG_ERR, "%s%u: Error reading (get nonce) (%d:%d)", - modminer->api->name, modminer->device_id, amount+amount2, err); + modminer->drv->name, modminer->device_id, amount+amount2, err); } if (memcmp(&nonce, "\xff\xff\xff\xff", 4)) { @@ -975,7 +975,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) if (state->death_stage_one) { modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false, true); applog(LOG_ERR, "%s%u: DEATH clock down", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); // reset the death info and DISABLE it state->last_nonce.tv_sec = 0; @@ -985,7 +985,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) } else { modminer_delta_clock(thr, MODMINER_CLOCK_DEAD, false, true); applog(LOG_ERR, "%s%u: death clock down", - modminer->api->name, modminer->device_id); + modminer->drv->name, modminer->device_id); state->death_stage_one = true; } @@ -1141,10 +1141,11 @@ static char *modminer_set_device(struct cgpu_info *modminer, char *option, char return replybuf; } -struct device_api modminer_api = { +struct device_drv modminer_drv = { + .drv = DRIVER_MODMINER, .dname = "modminer", .name = "MMQ", - .api_detect = modminer_detect, + .drv_detect = modminer_detect, .get_statline_before = get_modminer_statline_before, .set_device = modminer_set_device, .thread_prepare = modminer_fpga_prepare, diff --git a/driver-opencl.c b/driver-opencl.c index 01e70198..966d8cd0 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -50,24 +50,24 @@ extern int gpur_thr_id; extern bool opt_noadl; extern bool have_opencl; - - extern void *miner_thread(void *userdata); extern int dev_from_id(int thr_id); extern void tailsprintf(char *f, const char *fmt, ...); extern void wlog(const char *f, ...); extern void decay_time(double *f, double fadd); - /**********************************************/ +#ifdef HAVE_OPENCL +struct device_drv opencl_drv; +#endif + #ifdef HAVE_ADL extern float gpu_temp(int gpu); extern int gpu_fanspeed(int gpu); extern int gpu_fanpercent(int gpu); #endif - #ifdef HAVE_OPENCL char *set_vector(char *arg) { @@ -591,28 +591,20 @@ char *set_intensity(char *arg) return NULL; } -#endif - - -#ifdef HAVE_OPENCL -struct device_api opencl_api; char *print_ndevs_and_exit(int *ndevs) { opt_log_output = true; - opencl_api.api_detect(); + opencl_drv.drv_detect(); clear_adl(*ndevs); applog(LOG_INFO, "%i GPU devices max detected", *ndevs); exit(*ndevs); } #endif - struct cgpu_info gpus[MAX_GPUDEVICES]; /* Maximum number apparently possible */ struct cgpu_info *cpus; - - #ifdef HAVE_OPENCL /* In dynamic mode, only the first thread of each device will be in use. @@ -637,9 +629,6 @@ void pause_dynamic_threads(int gpu) } } - -struct device_api opencl_api; - #endif /* HAVE_OPENCL */ #if defined(HAVE_OPENCL) && defined(HAVE_CURSES) @@ -773,7 +762,7 @@ retry: for (i = 0; i < mining_threads; ++i) { thr = &thr_info[i]; cgpu = thr->cgpu; - if (cgpu->api != &opencl_api) + if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(i) != selected) continue; @@ -1160,7 +1149,7 @@ select_cgpu: for (thr_id = 0; thr_id < mining_threads; ++thr_id) { thr = &thr_info[thr_id]; cgpu = thr->cgpu; - if (cgpu->api != &opencl_api) + if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; @@ -1185,7 +1174,7 @@ select_cgpu: thr = &thr_info[thr_id]; cgpu = thr->cgpu; - if (cgpu->api != &opencl_api) + if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; @@ -1222,7 +1211,7 @@ select_cgpu: for (thr_id = 0; thr_id < mining_threads; ++thr_id) { thr = &thr_info[thr_id]; cgpu = thr->cgpu; - if (cgpu->api != &opencl_api) + if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; @@ -1243,8 +1232,6 @@ void *reinit_gpu(__maybe_unused void *userdata) #ifdef HAVE_OPENCL -struct device_api opencl_api; - static void opencl_detect() { int i; @@ -1263,7 +1250,7 @@ static void opencl_detect() cgpu = &gpus[i]; cgpu->deven = DEV_ENABLED; - cgpu->api = &opencl_api; + cgpu->drv = &opencl_drv; cgpu->device_id = i; cgpu->threads = opt_g_threads; cgpu->virtual_gpu = i; @@ -1570,10 +1557,11 @@ static void opencl_thread_shutdown(struct thr_info *thr) clReleaseContext(clState->context); } -struct device_api opencl_api = { +struct device_drv opencl_drv = { + .drv = DRIVER_OPENCL, .dname = "opencl", .name = "GPU", - .api_detect = opencl_detect, + .drv_detect = opencl_detect, .reinit_device = reinit_opencl_device, #ifdef HAVE_ADL .get_statline_before = get_opencl_statline_before, diff --git a/driver-opencl.h b/driver-opencl.h index c1d61822..22bd9ec2 100644 --- a/driver-opencl.h +++ b/driver-opencl.h @@ -30,6 +30,6 @@ extern void pause_dynamic_threads(int gpu); extern bool have_opencl; extern int opt_platform_id; -extern struct device_api opencl_api; +extern struct device_drv opencl_drv; #endif /* __DEVICE_GPU_H__ */ diff --git a/driver-ztex.c b/driver-ztex.c index 23aa97e4..4a61a5c5 100644 --- a/driver-ztex.c +++ b/driver-ztex.c @@ -30,7 +30,7 @@ #define GOLDEN_BACKLOG 5 -struct device_api ztex_api; +struct device_drv ztex_drv; // Forward declarations static void ztex_disable(struct thr_info* thr); @@ -68,7 +68,7 @@ static void ztex_detect(void) for (i = 0; i < cnt; i++) { ztex = calloc(1, sizeof(struct cgpu_info)); - ztex->api = &ztex_api; + ztex->drv = &ztex_drv; ztex->device_ztex = ztex_devices[i]->dev; ztex->threads = 1; ztex->device_ztex->fpgaNum = 0; @@ -82,7 +82,7 @@ static void ztex_detect(void) for (j = 1; j < fpgacount; j++) { ztex = calloc(1, sizeof(struct cgpu_info)); - ztex->api = &ztex_api; + ztex->drv = &ztex_drv; ztex_slave = calloc(1, sizeof(struct libztex_device)); memcpy(ztex_slave, ztex_devices[i]->dev, sizeof(struct libztex_device)); ztex->device_ztex = ztex_slave; @@ -394,10 +394,10 @@ static void ztex_disable(struct thr_info *thr) ztex_shutdown(thr); } -struct device_api ztex_api = { +struct device_drv ztex_drv = { .dname = "ztex", .name = "ZTX", - .api_detect = ztex_detect, + .drv_detect = ztex_detect, .get_statline_before = ztex_statline_before, .thread_prepare = ztex_prepare, .scanhash = ztex_scanhash, diff --git a/findnonce.c b/findnonce.c index bf39a122..fcf75f23 100644 --- a/findnonce.c +++ b/findnonce.c @@ -204,7 +204,7 @@ static void *postcalc_hash(void *userdata) * end of the res[] array */ if (unlikely(pcd->res[FOUND] & ~FOUND)) { applog(LOG_WARNING, "%s%d: invalid nonce count - HW error", - thr->cgpu->api->name, thr->cgpu->device_id); + thr->cgpu->drv->name, thr->cgpu->device_id); hw_errors++; thr->cgpu->hw_errors++; pcd->res[FOUND] &= FOUND; diff --git a/fpgautils.c b/fpgautils.c index 487395cc..307bec49 100644 --- a/fpgautils.c +++ b/fpgautils.c @@ -104,14 +104,14 @@ int serial_autodetect_devserial(__maybe_unused detectone_func_t detectone, __may #endif } -int _serial_detect(struct device_api *api, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto) +int _serial_detect(struct device_drv *drv, detectone_func_t detectone, autoscan_func_t autoscan, bool forceauto) { struct string_elist *iter, *tmp; const char *dev, *colon; bool inhibitauto = false; char found = 0; - size_t namel = strlen(api->name); - size_t dnamel = strlen(api->dname); + size_t namel = strlen(drv->name); + size_t dnamel = strlen(drv->dname); list_for_each_entry_safe(iter, tmp, &scan_devices, list) { dev = iter->string; @@ -119,8 +119,8 @@ int _serial_detect(struct device_api *api, detectone_func_t detectone, autoscan_ size_t idlen = colon - dev; // allow either name:device or dname:device - if ((idlen != namel || strncasecmp(dev, api->name, idlen)) - && (idlen != dnamel || strncasecmp(dev, api->dname, idlen))) + if ((idlen != namel || strncasecmp(dev, drv->name, idlen)) + && (idlen != dnamel || strncasecmp(dev, drv->dname, idlen))) continue; dev = colon + 1; diff --git a/fpgautils.h b/fpgautils.h index 18025488..b979b6c6 100644 --- a/fpgautils.h +++ b/fpgautils.h @@ -16,13 +16,13 @@ typedef bool(*detectone_func_t)(const char*); typedef int(*autoscan_func_t)(); -extern int _serial_detect(struct device_api *api, detectone_func_t, autoscan_func_t, bool force_autoscan); -#define serial_detect_fauto(api, detectone, autoscan) \ - _serial_detect(api, detectone, autoscan, true) -#define serial_detect_auto(api, detectone, autoscan) \ - _serial_detect(api, detectone, autoscan, false) -#define serial_detect(api, detectone) \ - _serial_detect(api, detectone, NULL, false) +extern int _serial_detect(struct device_drv *drv, detectone_func_t, autoscan_func_t, bool force_autoscan); +#define serial_detect_fauto(drv, detectone, autoscan) \ + _serial_detect(drv, detectone, autoscan, true) +#define serial_detect_auto(drv, detectone, autoscan) \ + _serial_detect(drv, detectone, autoscan, false) +#define serial_detect(drv, detectone) \ + _serial_detect(drv, detectone, NULL, false) extern int serial_autodetect_devserial(detectone_func_t, const char *prodname); extern int serial_autodetect_udev(detectone_func_t, const char *prodname); diff --git a/miner.h b/miner.h index d892ed03..4e888f32 100644 --- a/miner.h +++ b/miner.h @@ -196,6 +196,15 @@ static inline int fsync (int fd) #endif #endif +enum drv_driver { + DRIVER_OPENCL, + DRIVER_ICARUS, + DRIVER_BITFORCE, + DRIVER_MODMINER, + DRIVER_ZTEX, + DRIVER_CPU, +}; + enum alive { LIFE_WELL, LIFE_SICK, @@ -263,12 +272,14 @@ struct api_data; struct thr_info; struct work; -struct device_api { +struct device_drv { + enum drv_driver drv; + char *dname; char *name; - // API-global functions - void (*api_detect)(); + // DRV-global functions + void (*drv_detect)(); // Device-specific functions void (*reinit_device)(struct cgpu_info *); @@ -365,7 +376,7 @@ struct cgminer_pool_stats { struct cgpu_info { int cgminer_id; - struct device_api *api; + struct device_drv *drv; int device_id; char *name; char *device_path; diff --git a/usbutils.c b/usbutils.c index 0d9e79aa..bebd722d 100644 --- a/usbutils.c +++ b/usbutils.c @@ -99,15 +99,15 @@ static struct usb_find_devices find_dev[] = { }; #ifdef USE_BITFORCE -extern struct device_api bitforce_api; +extern struct device_drv bitforce_drv; #endif #ifdef USE_ICARUS -extern struct device_api icarus_api; +extern struct device_drv icarus_drv; #endif #ifdef USE_MODMINER -extern struct device_api modminer_api; +extern struct device_drv modminer_drv; #endif /* @@ -907,7 +907,7 @@ dame: return false; } -static bool usb_check_device(struct device_api *api, struct libusb_device *dev, struct usb_find_devices *look) +static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev, struct usb_find_devices *look) { struct libusb_device_descriptor desc; int err; @@ -920,25 +920,25 @@ static bool usb_check_device(struct device_api *api, struct libusb_device *dev, if (desc.idVendor != look->idVendor || desc.idProduct != look->idProduct) { applog(LOG_DEBUG, "%s looking for %04x:%04x but found %04x:%04x instead", - api->name, look->idVendor, look->idProduct, desc.idVendor, desc.idProduct); + drv->name, look->idVendor, look->idProduct, desc.idVendor, desc.idProduct); return false; } applog(LOG_DEBUG, "%s looking for and found %04x:%04x", - api->name, look->idVendor, look->idProduct); + drv->name, look->idVendor, look->idProduct); return true; } -static struct usb_find_devices *usb_check_each(int drv, struct device_api *api, struct libusb_device *dev) +static struct usb_find_devices *usb_check_each(int drvnum, struct device_drv *drv, struct libusb_device *dev) { struct usb_find_devices *found; int i; for (i = 0; find_dev[i].drv != DRV_LAST; i++) - if (find_dev[i].drv == drv) { - if (usb_check_device(api, dev, &(find_dev[i]))) { + if (find_dev[i].drv == drvnum) { + if (usb_check_device(drv, dev, &(find_dev[i]))) { found = malloc(sizeof(*found)); memcpy(found, &(find_dev[i]), sizeof(*found)); return found; @@ -948,27 +948,27 @@ static struct usb_find_devices *usb_check_each(int drv, struct device_api *api, return NULL; } -static struct usb_find_devices *usb_check(__maybe_unused struct device_api *api, __maybe_unused struct libusb_device *dev) +static struct usb_find_devices *usb_check(__maybe_unused struct device_drv *drv, __maybe_unused struct libusb_device *dev) { #ifdef USE_BITFORCE - if (api == &bitforce_api) - return usb_check_each(DRV_BITFORCE, api, dev); + if (drv->drv == DRIVER_BITFORCE) + return usb_check_each(DRV_BITFORCE, drv, dev); #endif #ifdef USE_ICARUS - if (api == &icarus_api) - return usb_check_each(DRV_ICARUS, api, dev); + if (drv->drv == DRIVER_ICARUS) + return usb_check_each(DRV_ICARUS, drv, dev); #endif #ifdef USE_MODMINER - if (api == &modminer_api) - return usb_check_each(DRV_MODMINER, api, dev); + if (drv->drv == DRIVER_MODMINER) + return usb_check_each(DRV_MODMINER, drv, dev); #endif return NULL; } -void usb_detect(struct device_api *api, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)) +void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)) { libusb_device **list; ssize_t count, i; @@ -995,7 +995,7 @@ void usb_detect(struct device_api *api, bool (*device_detect)(struct libusb_devi mutex_unlock(list_lock); - found = usb_check(api, list[i]); + found = usb_check(drv, list[i]); if (!found) release_dev(list[i], true); else @@ -1106,7 +1106,7 @@ static void newstats(struct cgpu_info *cgpu) cgpu->usbstat = ++next_stat; usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat); - usb_stats[next_stat-1].name = cgpu->api->name; + usb_stats[next_stat-1].name = cgpu->drv->name; usb_stats[next_stat-1].device_id = -1; usb_stats[next_stat-1].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2); for (i = 1; i < C_MAX * 2; i += 2) diff --git a/usbutils.h b/usbutils.h index 156e2a2d..2ee86150 100644 --- a/usbutils.h +++ b/usbutils.h @@ -116,12 +116,12 @@ enum usb_cmds { C_MAX }; -struct device_api; +struct device_drv; struct cgpu_info; void usb_uninit(struct cgpu_info *cgpu); bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found); -void usb_detect(struct device_api *api, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); +void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); struct api_data *api_usb_stats(int *count); void update_usb_stats(struct cgpu_info *cgpu); int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds, bool ftdi); From a4e95cfa424084b26a900d3e31f5ec6e5152b70c Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 6 Jan 2013 01:00:18 +1100 Subject: [PATCH 16/87] device_drv missing drv for cpu and incorrect test --- cgminer.c | 2 +- driver-cpu.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index adf7db45..177f61c4 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5904,7 +5904,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) continue; #ifdef WANT_CPUMINE - if (cgpu->drv->drv != DRIVER_CPU) + if (cgpu->drv->drv == DRIVER_CPU) continue; #endif if (cgpu->status != LIFE_WELL && (now.tv_sec - thr->last.tv_sec < WATCHDOG_SICK_TIME)) { diff --git a/driver-cpu.c b/driver-cpu.c index 99c5a3fa..eb46f3d8 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -844,6 +844,7 @@ CPUSearch: } struct device_drv cpu_drv = { + .drv = DRIVER_CPU, .dname = "cpu", .name = "CPU", .drv_detect = cpu_detect, From f9e04a3c5b311e2a1f54ca5729d974825b5f09ea Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 6 Jan 2013 21:00:38 +1100 Subject: [PATCH 17/87] device_drv - allow .name to be changed before add_cgpu() --- cgminer.c | 15 +++++++++++++++ driver-bitforce.c | 3 +++ driver-modminer.c | 10 +++++++++- miner.h | 5 +++++ usbutils.c | 16 ++++++++++++---- 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/cgminer.c b/cgminer.c index 177f61c4..befe57e7 100644 --- a/cgminer.c +++ b/cgminer.c @@ -6360,6 +6360,21 @@ bool add_cgpu(struct cgpu_info*cgpu) return true; } +struct device_drv *copy_drv(struct device_drv *drv) +{ + struct device_drv *copy; + char buf[100]; + + if (unlikely(!(copy = malloc(sizeof(*copy))))) { + sprintf(buf, "Failed to allocate device_drv copy of %s (%s)", + drv->name, drv->copy ? "copy" : "original"); + quit(1, buf); + } + memcpy(copy, drv, sizeof(*copy)); + copy->copy = true; + return copy; +} + int main(int argc, char *argv[]) { bool pools_active = false; diff --git a/driver-bitforce.c b/driver-bitforce.c index f1196322..0181b170 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -240,6 +240,9 @@ shin: if (bitforce->name != blank) free(bitforce->name); + if (bitforce->drv->copy) + free(bitforce->drv); + free(bitforce); return false; diff --git a/driver-modminer.c b/driver-modminer.c index 0868e85e..246947b4 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -182,7 +182,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic for (i = 0; i < buf[0]; i++) { struct cgpu_info *tmp = calloc(1, sizeof(*tmp)); - tmp->drv = modminer->drv; + tmp->drv = copy_drv(modminer->drv); tmp->name = devname; sprintf(devpath, "%d:%d:%d", @@ -202,6 +202,8 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic if (!add_cgpu(tmp)) { free(tmp->device_path); + if (tmp->drv->copy) + free(tmp->drv); free(tmp); goto unshin; } @@ -211,6 +213,9 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic added = true; } + if (modminer->drv->copy) + free(modminer->drv); + free(modminer); return true; @@ -223,6 +228,9 @@ shin: if (!added) free(modminer->modminer_mutex); + if (modminer->drv->copy) + free(modminer->drv); + free(modminer); if (added) diff --git a/miner.h b/miner.h index 4e888f32..b89d072e 100644 --- a/miner.h +++ b/miner.h @@ -299,8 +299,13 @@ struct device_drv { void (*hw_error)(struct thr_info *); void (*thread_shutdown)(struct thr_info *); void (*thread_enable)(struct thr_info *); + + // Does it need to be free()d? + bool copy; }; +extern struct device_drv *copy_drv(struct device_drv*); + enum dev_enable { DEV_ENABLED, DEV_DISABLED, diff --git a/usbutils.c b/usbutils.c index bebd722d..ebfcc0b2 100644 --- a/usbutils.c +++ b/usbutils.c @@ -891,6 +891,14 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find libusb_free_config_descriptor(config); + // Allow a name change based on the idVendor+idProduct + // N.B. must be done before calling add_cgpu() + if (strcmp(cgpu->drv->name, found->name)) { + if (!cgpu->drv->copy) + cgpu->drv = copy_drv(cgpu->drv); + cgpu->drv->name = (char *)(found->name); + } + return true; cldame: @@ -919,14 +927,14 @@ static bool usb_check_device(struct device_drv *drv, struct libusb_device *dev, } if (desc.idVendor != look->idVendor || desc.idProduct != look->idProduct) { - applog(LOG_DEBUG, "%s looking for %04x:%04x but found %04x:%04x instead", - drv->name, look->idVendor, look->idProduct, desc.idVendor, desc.idProduct); + applog(LOG_DEBUG, "%s looking for %s %04x:%04x but found %04x:%04x instead", + drv->name, look->name, look->idVendor, look->idProduct, desc.idVendor, desc.idProduct); return false; } - applog(LOG_DEBUG, "%s looking for and found %04x:%04x", - drv->name, look->idVendor, look->idProduct); + applog(LOG_DEBUG, "%s looking for and found %s %04x:%04x", + drv->name, look->name, look->idVendor, look->idProduct); return true; } From bad942e59a209bc35c370bb7d34c75578bd2502e Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 8 Jan 2013 14:06:16 +1100 Subject: [PATCH 18/87] increase device status string length --- cgminer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cgminer.c b/cgminer.c index befe57e7..1bc57e96 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1986,11 +1986,11 @@ static void curses_print_devstatus(int thr_id) suffix_string(dr64, displayed_rolling, 4); if (cgpu->status == LIFE_DEAD) - wprintw(statuswin, "DEAD "); + wprintw(statuswin, "DEAD "); else if (cgpu->status == LIFE_SICK) - wprintw(statuswin, "SICK "); + wprintw(statuswin, "SICK "); else if (cgpu->deven == DEV_DISABLED) - wprintw(statuswin, "OFF "); + wprintw(statuswin, "OFF "); else if (cgpu->deven == DEV_RECOVER) wprintw(statuswin, "REST "); else From bd5f20ebf57103eefb52c4e1fe0be7823623ed9a Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 8 Jan 2013 16:30:51 +1100 Subject: [PATCH 19/87] api.c pgaenable not re-enabling the device - plus related debug --- api.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/api.c b/api.c index 2e013ff4..bfd83708 100644 --- a/api.c +++ b/api.c @@ -1761,6 +1761,9 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char struct cgpu_info *cgpu = devices[dev]; + applog(LOG_DEBUG, "API: request to pgaenable pgaid %d device %d %s%u", + id, dev, cgpu->drv->name, cgpu->device_id); + if (cgpu->deven != DEV_DISABLED) { message(io_data, MSG_PGALRENA, id, NULL, isjson); return; @@ -1774,10 +1777,11 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char #endif for (i = 0; i < mining_threads; i++) { - pga = thr_info[i].cgpu->device_id; + pga = thr_info[i].cgpu->cgminer_id; if (pga == dev) { thr = &thr_info[i]; cgpu->deven = DEV_ENABLED; + applog(LOG_DEBUG, "API: pushing ping (%d) to thread %d", ping, thr->id); tq_push(thr->q, &ping); } } @@ -1814,6 +1818,9 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha struct cgpu_info *cgpu = devices[dev]; + applog(LOG_DEBUG, "API: request to pgadisable pgaid %d device %d %s%u", + id, dev, cgpu->drv->name, cgpu->device_id); + if (cgpu->deven == DEV_DISABLED) { message(io_data, MSG_PGALRDIS, id, NULL, isjson); return; @@ -2066,6 +2073,9 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char return; } + applog(LOG_DEBUG, "API: request to gpuenable gpuid %d %s%u", + id, gpus[id].drv->name, gpus[id].device_id); + if (gpus[id].deven != DEV_DISABLED) { message(io_data, MSG_ALRENA, id, NULL, isjson); return; @@ -2079,10 +2089,9 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char message(io_data, MSG_GPUMRE, id, NULL, isjson); return; } - gpus[id].deven = DEV_ENABLED; + applog(LOG_DEBUG, "API: pushing ping (%d) to thread %d", ping, thr->id); tq_push(thr->q, &ping); - } } @@ -2109,6 +2118,9 @@ static void gpudisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha return; } + applog(LOG_DEBUG, "API: request to gpudisable gpuid %d %s%u", + id, gpus[id].drv->name, gpus[id].device_id); + if (gpus[id].deven == DEV_DISABLED) { message(io_data, MSG_ALRDIS, id, NULL, isjson); return; From 0b3d8c89c24cefc67626e703aece84a7f59d446e Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 10 Jan 2013 11:08:12 +1100 Subject: [PATCH 20/87] API zero - zero statistics - all or bestshare - with optional on screen summary --- API-README | 15 ++++++++++++++ api.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cgminer.c | 24 +++++++++++++++------- miner.h | 3 +++ 4 files changed, 93 insertions(+), 7 deletions(-) diff --git a/API-README b/API-README index 14f8b53c..d8a5dec5 100644 --- a/API-README +++ b/API-README @@ -347,6 +347,18 @@ The list of requests - a (*) means it requires privileged access - and replies a The current options are: MMQ opt=clock val=160 to 230 (and a multiple of 2) + zero|Which,true/false (*) + none There is no reply section just the STATUS section + stating that the zero, and optional summary, was done + If Which='all', all normal cgminer and API statistics + will be zeroed other than the numbers displayed by the + usbstats and stats commands + If Which='bestshare', only the 'Best Share' values + are zeroed for each pool and the global 'Best Share' + The true/false option determines if a full summary is + shown on the cgminer display like is normally displayed + on exit. + When you enable, disable or restart a GPU or PGA, you will also get Thread messages in the cgminer status window @@ -402,6 +414,9 @@ Feature Changelog for external applications using the API: API V1.24 +Added API commands: + 'zero' + Modified API commands: 'pools' - add 'Best Share' diff --git a/api.c b/api.c index bfd83708..faad39ae 100644 --- a/api.c +++ b/api.c @@ -387,6 +387,11 @@ static const char *JSON_PARAMETER = "parameter"; #define MSG_PGASETERR 93 #endif +#define MSG_ZERMIS 94 +#define MSG_ZERINV 95 +#define MSG_ZERSUM 96 +#define MSG_ZERNOSUM 97 + enum code_severity { SEVERITY_ERR, SEVERITY_WARN, @@ -559,6 +564,10 @@ struct CODES { { SEVERITY_SUCC, MSG_PGASETOK, PARAM_BOTH, "PGA %d set OK" }, { SEVERITY_ERR, MSG_PGASETERR, PARAM_BOTH, "PGA %d set failed: %s" }, #endif + { SEVERITY_ERR, MSG_ZERMIS, PARAM_NONE, "Missing zero parameters" }, + { SEVERITY_ERR, MSG_ZERINV, PARAM_STR, "Invalid zero parameter '%s'" }, + { SEVERITY_SUCC, MSG_ZERSUM, PARAM_STR, "Zeroed %s stats with summary" }, + { SEVERITY_SUCC, MSG_ZERNOSUM, PARAM_STR, "Zeroed %s stats without summary" }, { SEVERITY_FAIL, 0, 0, NULL } }; @@ -3212,6 +3221,54 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe } #endif +static void dozero(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) +{ + if (param == NULL || *param == '\0') { + message(io_data, MSG_ZERMIS, 0, NULL, isjson); + return; + } + + char *sum = strchr(param, ','); + if (sum) + *(sum++) = '\0'; + if (!sum || !*sum) { + message(io_data, MSG_MISBOOL, 0, NULL, isjson); + return; + } + + bool all = false; + bool bs = false; + if (strcasecmp(param, "all") == 0) + all = true; + else if (strcasecmp(param, "bestshare") == 0) + bs = true; + + if (all == false && bs == false) { + message(io_data, MSG_ZERINV, 0, param, isjson); + return; + } + + *sum = tolower(*sum); + if (*sum != 't' && *sum != 'f') { + message(io_data, MSG_INVBOOL, 0, NULL, isjson); + return; + } + + bool dosum = (*sum == 't'); + if (dosum) + print_summary(); + + if (all) + zero_stats(); + if (bs) + zero_bestshare(); + + if (dosum) + message(io_data, MSG_ZERSUM, 0, all ? "All" : "BestShare", isjson); + else + message(io_data, MSG_ZERNOSUM, 0, all ? "All" : "BestShare", isjson); +} + static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, char group); struct CMDS { @@ -3271,6 +3328,7 @@ struct CMDS { #ifdef HAVE_AN_FPGA { "pgaset", pgaset, true }, #endif + { "zero", dozero, true }, { NULL, NULL, false } }; diff --git a/cgminer.c b/cgminer.c index 1bc57e96..c42703fb 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2732,8 +2732,6 @@ static void disable_curses(void) } #endif -static void print_summary(void); - static void __kill_work(void) { struct thr_info *thr; @@ -3915,6 +3913,20 @@ void write_config(FILE *fcfg) json_escape_free(); } +void zero_bestshare(void) +{ + int i; + + best_diff = 0; + memset(best_share, 0, 8); + suffix_string(best_diff, best_share, 0); + + for (i = 0; i < total_pools; i++) { + struct pool *pool = pools[i]; + pool->best_diff = 0; + } +} + void zero_stats(void) { int i; @@ -3931,10 +3943,7 @@ void zero_stats(void) total_go = 0; total_ro = 0; total_secs = 1.0; - best_diff = 0; total_diff1 = 0; - memset(best_share, 0, 8); - suffix_string(best_diff, best_share, 0); found_blocks = 0; total_diff_accepted = 0; total_diff_rejected = 0; @@ -3956,9 +3965,10 @@ void zero_stats(void) pool->diff_rejected = 0; pool->diff_stale = 0; pool->last_share_diff = 0; - pool->best_diff = 0; } + zero_bestshare(); + mutex_lock(&hash_lock); for (i = 0; i < total_devices; ++i) { struct cgpu_info *cgpu = devices[i]; @@ -5961,7 +5971,7 @@ static void log_print_status(struct cgpu_info *cgpu) applog(LOG_WARNING, "%s", logline); } -static void print_summary(void) +void print_summary(void) { struct timeval diff; int hours, mins, secs, i; diff --git a/miner.h b/miner.h index b89d072e..1992bd50 100644 --- a/miner.h +++ b/miner.h @@ -759,6 +759,7 @@ extern void api(int thr_id); extern struct pool *current_pool(void); extern int enabled_pools; extern bool detect_stratum(struct pool *pool, char *url); +extern void print_summary(void); extern struct pool *add_pool(void); extern void add_pool_details(struct pool *pool, bool live, char *url, char *user, char *pass); @@ -1077,6 +1078,8 @@ extern void kill_work(void); extern void switch_pools(struct pool *selected); extern void remove_pool(struct pool *pool); extern void write_config(FILE *fcfg); +extern void zero_bestshare(void); +extern void zero_stats(void); extern void default_save_file(char *filename); extern bool log_curses_only(int prio, const char *f, va_list ap); extern void clear_logwin(void); From f53549a861a65957ab748f09dca0a753e3e00ea7 Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 10 Jan 2013 11:27:51 +1100 Subject: [PATCH 21/87] BFL minimise first initialisation failure delay since it is common --- driver-bitforce.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index 0181b170..75e8b160 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -58,9 +58,11 @@ // If initialisation fails the first time, // sleep this amount (ms) and try again -#define REINIT_TIME_MS 1000 -// But try this many times -#define REINIT_COUNT 6 +#define REINIT_TIME_FIRST_MS 100 +// Max ms per sleep +#define REINIT_TIME_MAX_MS 800 +// Keep trying up to this many us +#define REINIT_TIME_MAX 3000000 static const char *blank = ""; @@ -133,6 +135,8 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic char devpath[20]; int err, amount; char *s; + struct timeval init_start, init_now; + int init_sleep, init_count; struct cgpu_info *bitforce = NULL; bitforce = calloc(1, sizeof(*bitforce)); @@ -152,7 +156,10 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic (int)(bitforce->usbdev->bus_number), (int)(bitforce->usbdev->device_address)); - int init_count = 0; + + init_count = 0; + init_sleep = REINIT_TIME_FIRST_MS; + gettimeofday(&init_start, NULL); reinit: bitforce_initialise(bitforce, false); @@ -164,19 +171,22 @@ reinit: } if ((err = usb_ftdi_read_nl(bitforce, buf, sizeof(buf)-1, &amount, C_GETIDENTIFY)) < 0 || amount < 1) { - // Maybe it was still processing previous work? - if (++init_count <= REINIT_COUNT) { - if (init_count < 2) { - applog(LOG_WARNING, "%s detect (%s) 1st init failed - retrying (%d:%d)", + init_count++; + gettimeofday(&init_now, NULL); + if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) { + if (init_count == 2) { + applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying", bitforce->drv->dname, devpath, amount, err); } - nmsleep(REINIT_TIME_MS); + nmsleep(init_sleep); + if ((init_sleep * 2) <= REINIT_TIME_MAX_MS) + init_sleep *= 2; goto reinit; } if (init_count > 0) - applog(LOG_WARNING, "%s detect (%s) init failed %d times", - bitforce->drv->dname, devpath, init_count); + applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs", + bitforce->drv->dname, devpath, init_count, tdiff(&init_now, &init_start)); if (err < 0) { applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", From 4f460ca72d5573b98970364c048560a52e898b18 Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 13 Jan 2013 10:28:19 +1100 Subject: [PATCH 22/87] Best Share readme --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index fd310154..21f12962 100644 --- a/README +++ b/README @@ -457,7 +457,7 @@ The block display shows: Block: 0074c5e482e34a506d2a051a... Started: [17:17:22] Best share: 2.71K This shows a short stretch of the current block, when the new block started, -and the all time best difficulty share you've submitted since starting cgminer +and the all time best difficulty share you've found since starting cgminer this time. From 34bcc1c66de4e03baf5aadb2a4c2369fa920379a Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 11:30:11 +1100 Subject: [PATCH 23/87] USB automatically handle losing the device and report nodev in the API --- API-README | 1 + api.c | 14 +++++++ driver-bitforce.c | 30 ++++++++++++- driver-modminer.c | 29 +++++++++---- miner.h | 1 + usbutils.c | 104 +++++++++++++++++++++++++++++++++++++++++----- usbutils.h | 6 ++- 7 files changed, 165 insertions(+), 20 deletions(-) diff --git a/API-README b/API-README index d8a5dec5..5fd2dda4 100644 --- a/API-README +++ b/API-README @@ -419,6 +419,7 @@ Added API commands: Modified API commands: 'pools' - add 'Best Share' + 'devs' and 'pga' - add 'No Device' for PGAs if MMQ or BFL compiled ---------- diff --git a/api.c b/api.c index faad39ae..c3158758 100644 --- a/api.c +++ b/api.c @@ -391,6 +391,7 @@ static const char *JSON_PARAMETER = "parameter"; #define MSG_ZERINV 95 #define MSG_ZERSUM 96 #define MSG_ZERNOSUM 97 +#define MSG_USBNODEV 98 enum code_severity { SEVERITY_ERR, @@ -568,6 +569,9 @@ struct CODES { { SEVERITY_ERR, MSG_ZERINV, PARAM_STR, "Invalid zero parameter '%s'" }, { SEVERITY_SUCC, MSG_ZERSUM, PARAM_STR, "Zeroed %s stats with summary" }, { SEVERITY_SUCC, MSG_ZERNOSUM, PARAM_STR, "Zeroed %s stats without summary" }, +#if defined(USE_MODMINER) || defined(USE_BITFORCE) + { SEVERITY_ERR, MSG_USBNODEV, PARAM_PGA, "PGA%d has no device" }, +#endif { SEVERITY_FAIL, 0, 0, NULL } }; @@ -1570,6 +1574,9 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom root = api_add_diff(root, "Difficulty Accepted", &(cgpu->diff_accepted), false); root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false); +#if defined(USE_MODMINER) || defined(USE_BITFORCE) + root = api_add_bool(root, "No Device", &(cgpu->nodev), false); +#endif root = print_data(root, buf, isjson, precom); io_add(io_data, buf); @@ -1785,6 +1792,13 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char } #endif +#if defined(USE_MODMINER) || defined(USE_BITFORCE) + if (cgpu->nodev) { + message(io_data, MSG_USBNODEV, id, NULL, isjson); + return; + } +#endif + for (i = 0; i < mining_threads; i++) { pga = thr_info[i].cgpu->cgminer_id; if (pga == dev) { diff --git a/driver-bitforce.c b/driver-bitforce.c index 75e8b160..a529042b 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 Andrew Smith + * Copyright 2012-2013 Andrew Smith * Copyright 2012 Luke Dashjr * Copyright 2012 Con Kolivas * @@ -82,6 +82,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: reset got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Set data control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_DATA, FTDI_VALUE_DATA, bitforce->usbdev->found->interface, C_SETDATA); @@ -89,6 +92,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setdata got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Set the baud err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_BAUD, FTDI_VALUE_BAUD, (FTDI_INDEX_BAUD & 0xff00) | bitforce->usbdev->found->interface, @@ -97,6 +103,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setbaud got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Set Flow Control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_FLOW, FTDI_VALUE_FLOW, bitforce->usbdev->found->interface, C_SETFLOW); @@ -104,6 +113,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Set Modem Control err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_MODEM, FTDI_VALUE_MODEM, bitforce->usbdev->found->interface, C_SETMODEM); @@ -111,6 +123,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Clear any sent data err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_TX, bitforce->usbdev->found->interface, C_PURGETX); @@ -118,6 +133,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: purgetx got err %d", bitforce->drv->name, bitforce->device_id, err); + if (bitforce->nodev) + goto failed; + // Clear any received data err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_PURGE_RX, bitforce->usbdev->found->interface, C_PURGERX); @@ -125,6 +143,8 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: purgerx got err %d", bitforce->drv->name, bitforce->device_id, err); +failed: + if (lock) mutex_unlock(&bitforce->device_mutex); } @@ -322,6 +342,10 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) int err, amount; char *s; + // Device is gone + if (bitforce->nodev) + return false; + /* Do not try to get the temperature if we're polling for a result to * minimise the chance of interleaved results */ if (bitforce->polling) @@ -640,6 +664,10 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_ bool send_ret; int64_t ret; + // Device is gone + if (bitforce->nodev) + return -1; + send_ret = bitforce_send_work(thr, work); if (!restart_wait(bitforce->sleep_ms)) diff --git a/driver-modminer.c b/driver-modminer.c index 246947b4..5c165760 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 Andrew Smith + * Copyright 2012-2013 Andrew Smith * Copyright 2012 Luke Dashjr * * This program is free software; you can redistribute it and/or modify it @@ -607,6 +607,7 @@ static bool modminer_fpga_prepare(struct thr_info *thr) * * N.B. clock must always be a multiple of 2 */ +static const char *clocknodev = "clock failed - no device"; static const char *clockoldwork = "clock already changed for this work"; static const char *clocktoolow = "clock too low"; static const char *clocktoohi = "clock too high"; @@ -620,6 +621,10 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te unsigned char cmd[6], buf[1]; int err, amount; + // Device is gone + if (modminer->nodev) + return clocknodev; + // Only do once if multiple shares per work or multiple reasons if (!state->new_work && !force) return clockoldwork; @@ -775,9 +780,6 @@ static bool modminer_start_work(struct thr_info *thr) mutex_lock(modminer->modminer_mutex); if ((err = usb_write(modminer, (char *)(state->next_work_cmd), 46, &amount, C_SENDWORK)) < 0 || amount != 46) { -// TODO: err = LIBUSB_ERROR_NO_DEVICE means the MMQ disappeared -// - need to delete it and rescan for it? (after a delay?) -// but check all (4) disappeared mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Start work failed (%d:%d)", @@ -807,6 +809,10 @@ static void check_temperature(struct thr_info *thr) int tbytes, tamount; int amount; + // Device is gone + if (modminer->nodev) + return; + if (state->one_byte_temp) { cmd[0] = MODMINER_TEMP1; tbytes = 1; @@ -891,6 +897,10 @@ static uint64_t modminer_process_results(struct thr_info *thr) double timeout; int temploop; + // Device is gone + if (modminer->nodev) + return -1; + // If we are overheated it will just keep checking for results // since we can't stop the work // The next work will not start until the temp drops @@ -904,9 +914,6 @@ static uint64_t modminer_process_results(struct thr_info *thr) while (1) { mutex_lock(modminer->modminer_mutex); if ((err = usb_write(modminer, cmd, 2, &amount, C_REQUESTWORKSTATUS)) < 0 || amount != 2) { -// TODO: err = LIBUSB_ERROR_NO_DEVICE means the MMQ disappeared -// - need to delete it and rescan for it? (after a delay?) -// but check all (4) disappeared mutex_unlock(modminer->modminer_mutex); // timeoutloop never resets so the timeouts can't @@ -1053,6 +1060,10 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ bool startwork; struct timeval tv1, tv2; + // Device is gone + if (thr->cgpu->nodev) + return -1; + // Don't start new work if overheated if (state->overheated == true) { gettimeofday(&tv1, NULL); @@ -1062,6 +1073,10 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ while (state->overheated == true) { check_temperature(thr); + // Device is gone + if (thr->cgpu->nodev) + return -1; + if (state->overheated == true) { gettimeofday(&tv2, NULL); diff --git a/miner.h b/miner.h index 1992bd50..a7b6fa15 100644 --- a/miner.h +++ b/miner.h @@ -399,6 +399,7 @@ struct cgpu_info { }; #if defined(USE_MODMINER) || defined(USE_BITFORCE) int usbstat; + bool nodev; #endif #ifdef USE_MODMINER char fpgaid; diff --git a/usbutils.c b/usbutils.c index ebfcc0b2..273d8528 100644 --- a/usbutils.c +++ b/usbutils.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 Andrew Smith + * Copyright 2012-2013 Andrew Smith * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -16,6 +16,10 @@ #include "miner.h" #include "usbutils.h" +#define NODEV(err) ((err) == LIBUSB_ERROR_NO_DEVICE || \ + (err) == LIBUSB_ERROR_PIPE || \ + (err) == LIBUSB_ERROR_OTHER) + #ifdef USE_ICARUS #define DRV_ICARUS 1 #endif @@ -161,6 +165,7 @@ static int next_stat = 0; static const char **usb_commands; +static const char *C_REJECTED_S = "RejectedNoDevice"; static const char *C_PING_S = "Ping"; static const char *C_CLEAR_S = "Clear"; static const char *C_REQUESTVERSION_S = "RequestVersion"; @@ -551,6 +556,7 @@ static void cgusb_check_init() // use constants so the stat generation is very quick // and the association between number and name can't // be missalined easily + usb_commands[C_REJECTED] = C_REJECTED_S; usb_commands[C_PING] = C_PING_S; usb_commands[C_CLEAR] = C_CLEAR_S; usb_commands[C_REQUESTVERSION] = C_REQUESTVERSION_S; @@ -673,8 +679,7 @@ static void release(uint8_t bus_number, uint8_t device_address, bool lock) if (lock) mutex_lock(list_lock); - usb_tmp = usb_head; - if (usb_tmp) + if ((usb_tmp = usb_head)) do { if (bus_number == usb_tmp->bus_number && device_address == usb_tmp->device_address) { @@ -698,6 +703,8 @@ static void release(uint8_t bus_number, uint8_t device_address, bool lock) if (usb_tmp->next == usb_tmp) { usb_head = NULL; } else { + if (usb_head == usb_tmp) + usb_head = usb_tmp->next; usb_tmp->next->prev = usb_tmp->prev; usb_tmp->prev->next = usb_tmp->next; } @@ -719,13 +726,6 @@ static void release_dev(libusb_device *dev, bool lock) release(bus_number, device_address, lock); } -#if 0 -static void release_cgusb(struct cg_usb_device *cgusb, bool lock) -{ - release(cgusb->bus_number, cgusb->device_address, lock); -} -#endif - static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb) { if (cgusb->serial_string && cgusb->serial_string != BLANK) @@ -739,6 +739,8 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb) free(cgusb->descriptor); + free(cgusb->found); + free(cgusb); return NULL; @@ -751,6 +753,31 @@ void usb_uninit(struct cgpu_info *cgpu) cgpu->usbdev = free_cgusb(cgpu->usbdev); } +void release_cgpu(struct cgpu_info *cgpu) +{ + struct cg_usb_device *cgusb = cgpu->usbdev; + uint8_t bus_number; + uint8_t device_address; + int i; + + cgpu->nodev = true; + + // Any devices sharing the same USB device should be marked also + // Currently only MMQ shares a USB device + for (i = 0; i < total_devices; i++) + if (devices[i] != cgpu && devices[i]->usbdev == cgusb) { + devices[i]->nodev = true; + devices[i]->usbdev = NULL; + } + + bus_number = cgusb->bus_number; + device_address = cgusb->device_address; + + usb_uninit(cgpu); + + release(bus_number, device_address, true); +} + bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found) { struct cg_usb_device *cgusb = NULL; @@ -1172,6 +1199,19 @@ static void stats(struct cgpu_info *cgpu, struct timeval *tv_start, struct timev memcpy(&(details->item[item].last), tv_start, sizeof(tv_start)); details->item[item].count++; } + +static void rejected_inc(struct cgpu_info *cgpu) +{ + struct cg_usb_stats_details *details; + int item = CMD_ERROR; + + if (cgpu->usbstat < 1) + newstats(cgpu); + + details = &(usb_stats[cgpu->usbstat - 1].details[C_REJECTED * 2 + 0]); + + details->item[item].count++; +} #endif int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *processed, unsigned int timeout, int eol, enum usb_cmds cmd, bool ftdi) @@ -1186,6 +1226,15 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro int err, got, tot, i; bool first = true; + if (cgpu->nodev) { + *buf = '\0'; + *processed = 0; +#if DO_USB_STATS + rejected_inc(cgpu); +#endif + return LIBUSB_ERROR_NO_DEVICE; + } + if (timeout == DEVTIMEOUT) timeout = usbdev->found->timeout; @@ -1212,6 +1261,11 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro *processed = got; + if (NODEV(err)) { + cgpu->nodev = true; + release_cgpu(cgpu); + } + return err; } @@ -1268,6 +1322,11 @@ goteol: *processed = tot; + if (NODEV(err)) { + cgpu->nodev = true; + release_cgpu(cgpu); + } + return err; } @@ -1279,6 +1338,14 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr #endif int err, sent; + if (cgpu->nodev) { + *processed = 0; +#if DO_USB_STATS + rejected_inc(cgpu); +#endif + return LIBUSB_ERROR_NO_DEVICE; + } + sent = 0; STATS_TIMEVAL(&tv_start); err = libusb_bulk_transfer(usbdev->handle, @@ -1291,6 +1358,11 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr *processed = sent; + if (NODEV(err)) { + cgpu->nodev = true; + release_cgpu(cgpu); + } + return err; } @@ -1302,6 +1374,13 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest #endif int err; + if (cgpu->nodev) { +#if DO_USB_STATS + rejected_inc(cgpu); +#endif + return LIBUSB_ERROR_NO_DEVICE; + } + STATS_TIMEVAL(&tv_start); err = libusb_control_transfer(usbdev->handle, request_type, bRequest, wValue, wIndex, NULL, 0, @@ -1309,6 +1388,11 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest STATS_TIMEVAL(&tv_finish); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); + if (NODEV(err)) { + cgpu->nodev = true; + release_cgpu(cgpu); + } + return err; } diff --git a/usbutils.h b/usbutils.h index 2ee86150..7912be52 100644 --- a/usbutils.h +++ b/usbutils.h @@ -1,5 +1,5 @@ /* - * Copyright 2012 Andrew Smith + * Copyright 2012-2013 Andrew Smith * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -79,7 +79,8 @@ struct cg_usb_device { }; enum usb_cmds { - C_PING = 0, + C_REJECTED = 0, + C_PING, C_CLEAR, C_REQUESTVERSION, C_GETVERSION, @@ -120,6 +121,7 @@ struct device_drv; struct cgpu_info; void usb_uninit(struct cgpu_info *cgpu); +void release_cgpu(struct cgpu_info *cgpu); bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found); void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); struct api_data *api_usb_stats(int *count); From 24525edbefffd944d07d289beaf1f0534cbfc10d Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 11:40:02 +1100 Subject: [PATCH 24/87] api.c update copyright year --- api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.c b/api.c index c3158758..ce598683 100644 --- a/api.c +++ b/api.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 Andrew Smith + * Copyright 2011-2013 Andrew Smith * Copyright 2011-2012 Con Kolivas * * This program is free software; you can redistribute it and/or modify it From ea807cf0c7ee5c8bd9b315f395847d0176d741fc Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 11:44:31 +1100 Subject: [PATCH 25/87] USB BFL transfer is only 64 bytes in a USB1.1 socket --- usbutils.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/usbutils.c b/usbutils.c index 273d8528..d9427067 100644 --- a/usbutils.c +++ b/usbutils.c @@ -48,14 +48,10 @@ #endif #ifdef USE_BITFORCE +// N.B. transfer size is 512 with USB2.0, but only 64 with USB1.1 static struct usb_endpoints bfl_eps[] = { -#ifdef WIN32 { LIBUSB_TRANSFER_TYPE_BULK, 64, EPI(1), 0 }, { LIBUSB_TRANSFER_TYPE_BULK, 64, EPO(2), 0 } -#else - { LIBUSB_TRANSFER_TYPE_BULK, 512, EPI(1), 0 }, - { LIBUSB_TRANSFER_TYPE_BULK, 512, EPO(2), 0 } -#endif }; #endif From a52522af3727cad95c5818c1d137c80e403dc121 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 21:01:25 +1100 Subject: [PATCH 26/87] MMQ it's a bitstream --- driver-modminer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver-modminer.c b/driver-modminer.c index 5c165760..abb2d7fc 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -255,7 +255,7 @@ static bool get_expect(struct cgpu_info *modminer, FILE *f, char c) } if (buf != c) { - applog(LOG_ERR, "%s%u: firmware code mismatch (%c)", + applog(LOG_ERR, "%s%u: bitstream code mismatch (%c)", modminer->drv->name, modminer->device_id, c); return false; } From 92abe36f1207533e29d42d1eba6306663ce9b6b1 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 14 Jan 2013 21:12:50 +1100 Subject: [PATCH 27/87] MMQ include USB devpath in detection error messages --- driver-modminer.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/driver-modminer.c b/driver-modminer.c index abb2d7fc..24a952a4 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -126,37 +126,52 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic mutex_init(modminer->modminer_mutex); modminer->fpgaid = (char)0; - if (!usb_init(modminer, dev, found)) + if (!usb_init(modminer, dev, found)) { + applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", + modminer->drv->dname, + (int)libusb_get_bus_number(dev), + (int)libusb_get_device_address(dev)); goto shin; + } + + sprintf(devpath, "%d:%d", + (int)(modminer->usbdev->bus_number), + (int)(modminer->usbdev->device_address)); do_ping(modminer); if ((err = usb_write(modminer, MODMINER_GET_VERSION, 1, &amount, C_REQUESTVERSION)) < 0 || amount != 1) { - applog(LOG_ERR, "ModMiner detect: send version request failed (%d:%d)", amount, err); + applog(LOG_ERR, "%s detect (%s) send version request failed (%d:%d)", + modminer->drv->dname, devpath, amount, err); goto unshin; } if ((err = usb_read(modminer, buf, sizeof(buf)-1, &amount, C_GETVERSION)) < 0 || amount < 1) { if (err < 0) - applog(LOG_ERR, "ModMiner detect: no version reply (%d)", err); + applog(LOG_ERR, "%s detect (%s) no version reply (%d)", + modminer->drv->dname, devpath, err); else - applog(LOG_ERR, "ModMiner detect: empty version reply (%d)", amount); + applog(LOG_ERR, "%s detect (%s) empty version reply (%d)", + modminer->drv->dname, devpath, amount); - applog(LOG_DEBUG, "ModMiner detect: check the firmware"); + applog(LOG_DEBUG, "%s detect (%s) check the firmware", + modminer->drv->dname, devpath); goto unshin; } buf[amount] = '\0'; devname = strdup(buf); - applog(LOG_DEBUG, "ModMiner identified as: %s", devname); + applog(LOG_DEBUG, "%s (%s) identified as: %s", modminer->drv->dname, devpath, devname); if ((err = usb_write(modminer, MODMINER_FPGA_COUNT, 1, &amount, C_REQUESTFPGACOUNT) < 0 || amount != 1)) { - applog(LOG_ERR, "ModMiner detect: FPGA count request failed (%d:%d)", amount, err); + applog(LOG_ERR, "%s detect (%s) FPGA count request failed (%d:%d)", + modminer->drv->dname, devpath, amount, err); goto unshin; } if ((err = usb_read(modminer, buf, 1, &amount, C_GETFPGACOUNT)) < 0 || amount != 1) { - applog(LOG_ERR, "ModMiner detect: no FPGA count reply (%d:%d)", amount, err); + applog(LOG_ERR, "%s detect (%s) no FPGA count reply (%d:%d)", + modminer->drv->dname, devpath, amount, err); goto unshin; } @@ -164,16 +179,19 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic // can detect with modminer->cgusb->serial ? if (buf[0] == 0) { - applog(LOG_ERR, "ModMiner detect: zero FPGA count from %s", devname); + applog(LOG_ERR, "%s detect (%s) zero FPGA count from %s", + modminer->drv->dname, devpath, devname); goto unshin; } if (buf[0] < 1 || buf[0] > 4) { - applog(LOG_ERR, "ModMiner detect: invalid FPGA count (%u) from %s", buf[0], devname); + applog(LOG_ERR, "%s detect (%s) invalid FPGA count (%u) from %s", + modminer->drv->dname, devpath, buf[0], devname); goto unshin; } - applog(LOG_DEBUG, "ModMiner %s has %u FPGAs", devname, buf[0]); + applog(LOG_DEBUG, "%s (%s) %s has %u FPGAs", + modminer->drv->dname, devpath, devname, buf[0]); modminer->name = devname; From c1eae36f7bf2299fb49b1eeeba49345e5dc7a46a Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 15 Jan 2013 01:13:00 +1100 Subject: [PATCH 28/87] API stats - include pool network bytes + in miner.php --- api.c | 2 ++ miner.h | 2 ++ miner.php | 16 +++++++++++----- util.c | 35 +++++++++++++++++++++++++++++++---- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/api.c b/api.c index ce598683..fe593a76 100644 --- a/api.c +++ b/api.c @@ -2915,6 +2915,8 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st root = api_add_uint64(root, "Bytes Sent", &(pool_stats->bytes_sent), false); root = api_add_uint64(root, "Times Recv", &(pool_stats->times_received), false); root = api_add_uint64(root, "Bytes Recv", &(pool_stats->bytes_received), false); + root = api_add_uint64(root, "Net Bytes Sent", &(pool_stats->net_bytes_sent), false); + root = api_add_uint64(root, "Net Bytes Recv", &(pool_stats->net_bytes_received), false); } if (extra) diff --git a/miner.h b/miner.h index a7b6fa15..f9e616d0 100644 --- a/miner.h +++ b/miner.h @@ -375,8 +375,10 @@ struct cgminer_pool_stats { uint32_t max_diff_count; uint64_t times_sent; uint64_t bytes_sent; + uint64_t net_bytes_sent; uint64_t times_received; uint64_t bytes_received; + uint64_t net_bytes_received; }; struct cgpu_info { diff --git a/miner.php b/miner.php index 9215a21e..717e26aa 100644 --- a/miner.php +++ b/miner.php @@ -116,16 +116,17 @@ $poolspage = array( 'POOL.Difficulty Rejected=Diff Rej', 'POOL.Has Stratum=Stratum', 'POOL.Stratum Active=StrAct', 'POOL.Has GBT=GBT', 'STATS.Times Sent=TSent', - 'STATS.Bytes Sent=BSent', 'STATS.Times Recv=TRecv', - 'STATS.Bytes Recv=BRecv')); + 'STATS.Bytes Sent=BSent', 'STATS.Net Bytes Sent=NSent', + 'STATS.Times Recv=TRecv', 'STATS.Bytes Recv=BRecv', + 'STATS.Net Bytes Recv=NRecv')); # $poolssum = array( 'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted', 'Rejected', 'Utility', 'Hardware Errors', 'Work Utility'), 'POOL+STATS' => array('POOL.Difficulty Accepted', 'POOL.Difficulty Rejected', - 'STATS.Times Sent', 'STATS.Bytes Sent', - 'STATS.Times Recv', 'STATS.Bytes Recv')); + 'STATS.Times Sent', 'STATS.Bytes Sent', 'STATS.Net Bytes Sent', + 'STATS.Times Recv', 'STATS.Bytes Recv', 'STATS.Net Bytes Recv')); # $poolsext = array( 'POOL+STATS' => array( @@ -133,7 +134,8 @@ $poolsext = array( 'group' => array('POOL.URL', 'POOL.Has Stratum', 'POOL.Stratum Active', 'POOL.Has GBT'), 'calc' => array('POOL.Difficulty Accepted' => 'sum', 'POOL.Difficulty Rejected' => 'sum', 'STATS.Times Sent' => 'sum', 'STATS.Bytes Sent' => 'sum', - 'STATS.Times Recv' => 'sum', 'STATS.Bytes Recv' => 'sum'), + 'STATS.Net Bytes Sent' => 'sum', 'STATS.Times Recv' => 'sum', + 'STATS.Bytes Recv' => 'sum', 'STATS.Net Bytes Recv' => 'sum'), 'having' => array(array('STATS.Bytes Recv', '>', 0))) ); @@ -850,12 +852,16 @@ function fmt($section, $name, $value, $when, $alldata) case 'total.Diff1 Work': case 'STATS.Times Sent': case 'STATS.Bytes Sent': + case 'STATS.Net Bytes Sent': case 'STATS.Times Recv': case 'STATS.Bytes Recv': + case 'STATS.Net Bytes Recv': case 'total.Times Sent': case 'total.Bytes Sent': + case 'total.Net Bytes Sent': case 'total.Times Recv': case 'total.Bytes Recv': + case 'total.Net Bytes Recv': $parts = explode('.', $value, 2); if (count($parts) == 1) $dec = ''; diff --git a/util.c b/util.c index e628af45..9283955c 100644 --- a/util.c +++ b/util.c @@ -261,6 +261,30 @@ static void set_nettime(void) wr_unlock(&netacc_lock); } +static int curl_debug_cb(__maybe_unused CURL *handle, curl_infotype type, + __maybe_unused unsigned char *data, size_t size, + void *userdata) +{ + struct pool *pool = (struct pool *)userdata; + + switch(type) { + case CURLINFO_HEADER_IN: + case CURLINFO_DATA_IN: + case CURLINFO_SSL_DATA_IN: + pool->cgminer_pool_stats.net_bytes_received += size; + break; + case CURLINFO_HEADER_OUT: + case CURLINFO_DATA_OUT: + case CURLINFO_SSL_DATA_OUT: + pool->cgminer_pool_stats.net_bytes_sent += size; + break; + case CURLINFO_TEXT: + default: + break; + } + return 0; +} + json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass, const char *rpc_req, bool probe, bool longpoll, int *rolltime, @@ -287,10 +311,11 @@ json_t *json_rpc_call(CURL *curl, const char *url, probing = !pool->probed; curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); -#if 0 /* Disable curl debugging since it spews to stderr */ - if (opt_protocol) - curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); -#endif + // CURLOPT_VERBOSE won't write to stderr if we use CURLOPT_DEBUGFUNCTION + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_debug_cb); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *)pool); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_ENCODING, ""); @@ -912,6 +937,7 @@ static bool __stratum_send(struct pool *pool, char *s, ssize_t len) pool->cgminer_pool_stats.times_sent++; pool->cgminer_pool_stats.bytes_sent += ssent; + pool->cgminer_pool_stats.net_bytes_sent += ssent; return true; } @@ -1041,6 +1067,7 @@ char *recv_line(struct pool *pool) pool->cgminer_pool_stats.times_received++; pool->cgminer_pool_stats.bytes_received += len; + pool->cgminer_pool_stats.net_bytes_received += len; out: if (!sret) clear_sock(pool); From baf3aca88c5196029caa200aa504c96adfba2690 Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 17 Jan 2013 19:21:40 +1100 Subject: [PATCH 29/87] usbutils.c release_cgpu() sets nodev --- usbutils.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/usbutils.c b/usbutils.c index d9427067..30be2884 100644 --- a/usbutils.c +++ b/usbutils.c @@ -1257,10 +1257,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro *processed = got; - if (NODEV(err)) { - cgpu->nodev = true; + if (NODEV(err)) release_cgpu(cgpu); - } return err; } @@ -1318,10 +1316,8 @@ goteol: *processed = tot; - if (NODEV(err)) { - cgpu->nodev = true; + if (NODEV(err)) release_cgpu(cgpu); - } return err; } @@ -1354,10 +1350,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr *processed = sent; - if (NODEV(err)) { - cgpu->nodev = true; + if (NODEV(err)) release_cgpu(cgpu); - } return err; } @@ -1384,10 +1378,8 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest STATS_TIMEVAL(&tv_finish); USB_STATS(cgpu, &tv_start, &tv_finish, err, cmd, SEQ0); - if (NODEV(err)) { - cgpu->nodev = true; + if (NODEV(err)) release_cgpu(cgpu); - } return err; } From 9447610091feb5a679d72ae7bae89a776917186e Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 17 Jan 2013 19:55:08 +1100 Subject: [PATCH 30/87] ICA use drv->name --- driver-icarus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/driver-icarus.c b/driver-icarus.c index f42e7214..1faab2b6 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -668,7 +668,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, icarus = thr->cgpu; if (icarus->device_fd == -1) if (!icarus_prepare(thr)) { - applog(LOG_ERR, "ICA%i: Comms error", icarus->device_id); + applog(LOG_ERR, "%s%i: Comms error", icarus->drv->name, icarus->device_id); dev_error(icarus, REASON_DEV_COMMS_ERROR); // fail the device if the reopen attempt fails @@ -688,7 +688,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, ret = icarus_write(fd, ob_bin, sizeof(ob_bin)); if (ret) { do_icarus_close(thr); - applog(LOG_ERR, "ICA%i: Comms error", icarus->device_id); + applog(LOG_ERR, "%s%i: Comms error", icarus->drv->name, icarus->device_id); dev_error(icarus, REASON_DEV_COMMS_ERROR); return 0; /* This should never happen */ } @@ -708,7 +708,7 @@ static int64_t icarus_scanhash(struct thr_info *thr, struct work *work, ret = icarus_gets(nonce_bin, fd, &tv_finish, thr, info->read_count); if (ret == ICA_GETS_ERROR) { do_icarus_close(thr); - applog(LOG_ERR, "ICA%i: Comms error", icarus->device_id); + applog(LOG_ERR, "%s%i: Comms error", icarus->drv->name, icarus->device_id); dev_error(icarus, REASON_DEV_COMMS_ERROR); return 0; } From 383a21bebf871e22a7152129313aa52cbf307d79 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 18 Jan 2013 20:33:23 +1100 Subject: [PATCH 31/87] miner.php trim trailing zeros on some of the STATS numbers --- miner.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/miner.php b/miner.php index 717e26aa..396121b6 100644 --- a/miner.php +++ b/miner.php @@ -590,6 +590,14 @@ function classlastshare($when, $alldata, $warnclass, $errorclass) return ''; } # +function endzero($num) +{ + $rep = preg_replace('/0*$/', '', $num); + if ($rep === '') + $rep = '0'; + return $rep; +} +# function fmt($section, $name, $value, $when, $alldata) { global $dfmt, $rownum; @@ -869,6 +877,23 @@ function fmt($section, $name, $value, $when, $alldata) $dec = '.'.$parts[1]; $ret = number_format((float)$parts[0]).$dec; break; + case 'STATS.Hs': + case 'STATS.W': + case 'STATS.history_time': + case 'STATS.Pool Wait': + case 'STATS.Pool Max': + case 'STATS.Pool Min': + case 'STATS.Pool Av': + case 'STATS.Min Diff': + case 'STATS.Max Diff': + case 'STATS.Work Diff': + $parts = explode('.', $value, 2); + if (count($parts) == 1) + $dec = ''; + else + $dec = '.'.endzero($parts[1]); + $ret = number_format((float)$parts[0]).$dec; + break; case 'GPU.Status': case 'PGA.Status': case 'DEVS.Status': From 3f4d9fc5d61784e6a7df3d1d11f1511fe36c3ce3 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 19 Jan 2013 00:24:26 +1100 Subject: [PATCH 32/87] BFL use #defined strings for work replies --- driver-bitforce.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index a529042b..fbc98723 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -40,6 +40,16 @@ #define BITFORCE_WORKSTATUS "ZFX" #define BITFORCE_WORKSTATUS_LEN (sizeof(BITFORCE_WORKSTATUS)-1) +// Either of Nonce or No-nonce start with: +#define BITFORCE_EITHER "N" +#define BITFORCE_EITHER_LEN 1 +#define BITFORCE_NONCE "NONCE-FOUND" +#define BITFORCE_NONCE_LEN (sizeof(BITFORCE_NONCE)-1) +#define BITFORCE_NO_NONCE "NO-NONCE" +#define BITFORCE_NO_NONCE_MATCH 3 +#define BITFORCE_IDLE "IDLE" +#define BITFORCE_IDLE_MATCH 1 + #define BITFORCE_SLEEP_MS 500 #define BITFORCE_TIMEOUT_S 7 #define BITFORCE_TIMEOUT_MS (BITFORCE_TIMEOUT_S * 1000) @@ -579,7 +589,7 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) /* Only return if we got nothing after timeout - there still may be results */ if (amount == 0) return 0; - } else if (!strncasecmp(buf, "N", 1)) {/* Hashing complete (NONCE-FOUND or NO-NONCE) */ + } else if (!strncasecmp(buf, BITFORCE_EITHER, BITFORCE_EITHER_LEN)) { /* Simple timing adjustment. Allow a few polls to cope with * OS timer delays being variably reliable. wait_ms will * always equal sleep_ms when we've waited greater than or @@ -608,11 +618,11 @@ static int64_t bitforce_get_result(struct thr_info *thr, struct work *work) applog(LOG_DEBUG, "%s%i: waited %dms until %s", bitforce->drv->name, bitforce->device_id, bitforce->wait_ms, buf); - if (!strncasecmp(&buf[2], "-", 1)) + if (!strncasecmp(buf, BITFORCE_NO_NONCE, BITFORCE_NO_NONCE_MATCH)) return bitforce->nonces; /* No valid nonce found */ - else if (!strncasecmp(buf, "I", 1)) + else if (!strncasecmp(buf, BITFORCE_IDLE, BITFORCE_IDLE_MATCH)) return 0; /* Device idle */ - else if (strncasecmp(buf, "NONCE-FOUND", 11)) { + else if (strncasecmp(buf, BITFORCE_NONCE, BITFORCE_NONCE_LEN)) { bitforce->hw_errors++; applog(LOG_WARNING, "%s%i: Error: Get result reports: %s", bitforce->drv->name, bitforce->device_id, buf); From 8f4340bfeb1348f1369fdd1962f9267383052e31 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 21 Jan 2013 21:30:21 +1100 Subject: [PATCH 33/87] BFL allow a 2nd init attempt if the 1st reply is unknown --- driver-bitforce.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index fbc98723..f97bcda5 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -167,6 +167,7 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic char *s; struct timeval init_start, init_now; int init_sleep, init_count; + bool ident_first; struct cgpu_info *bitforce = NULL; bitforce = calloc(1, sizeof(*bitforce)); @@ -187,13 +188,14 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic (int)(bitforce->usbdev->device_address)); + // Allow 2 complete attempts if the 1st time returns an unrecognised reply + ident_first = true; +retry: init_count = 0; init_sleep = REINIT_TIME_FIRST_MS; gettimeofday(&init_start, NULL); reinit: - bitforce_initialise(bitforce, false); - if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", bitforce->drv->dname, devpath, amount, err); @@ -231,7 +233,13 @@ reinit: buf[amount] = '\0'; if (unlikely(!strstr(buf, "SHA256"))) { - applog(LOG_ERR, "%s detect (%s) didn't recognise '%s'", + if (ident_first) { + applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...", + bitforce->drv->dname, devpath, buf); + ident_first = false; + goto retry; + } + applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt", bitforce->drv->dname, devpath, buf); goto unshin; } From 7fbc3770b471b956d40cb78e8b7e365b54de9cf1 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 22 Jan 2013 21:46:21 +1100 Subject: [PATCH 34/87] USB move usbdev info that needs to stay around into usbinfo --- api.c | 4 ++-- driver-bitforce.c | 24 +++++++++++----------- driver-modminer.c | 24 +++++++++++----------- miner.h | 3 +-- usbutils.c | 51 ++++++++++++++++++++++++----------------------- usbutils.h | 11 ++++++++-- 6 files changed, 62 insertions(+), 55 deletions(-) diff --git a/api.c b/api.c index fe593a76..a2470b0d 100644 --- a/api.c +++ b/api.c @@ -1575,7 +1575,7 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom root = api_add_diff(root, "Difficulty Rejected", &(cgpu->diff_rejected), false); root = api_add_diff(root, "Last Share Difficulty", &(cgpu->last_share_diff), false); #if defined(USE_MODMINER) || defined(USE_BITFORCE) - root = api_add_bool(root, "No Device", &(cgpu->nodev), false); + root = api_add_bool(root, "No Device", &(cgpu->usbinfo.nodev), false); #endif root = print_data(root, buf, isjson, precom); @@ -1793,7 +1793,7 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char #endif #if defined(USE_MODMINER) || defined(USE_BITFORCE) - if (cgpu->nodev) { + if (cgpu->usbinfo.nodev) { message(io_data, MSG_USBNODEV, id, NULL, isjson); return; } diff --git a/driver-bitforce.c b/driver-bitforce.c index f97bcda5..be22c7b6 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -92,7 +92,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: reset got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Set data control @@ -102,7 +102,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setdata got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Set the baud @@ -113,7 +113,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setbaud got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Set Flow Control @@ -123,7 +123,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setflowctrl got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Set Modem Control @@ -133,7 +133,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: setmodemctrl got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Clear any sent data @@ -143,7 +143,7 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) applog(LOG_DEBUG, "%s%i: purgetx got err %d", bitforce->drv->name, bitforce->device_id, err); - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) goto failed; // Clear any received data @@ -178,14 +178,14 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic if (!usb_init(bitforce, dev, found)) { applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", bitforce->drv->dname, - (int)libusb_get_bus_number(dev), - (int)libusb_get_device_address(dev)); + (int)(bitforce->usbinfo.bus_number), + (int)(bitforce->usbinfo.device_address)); goto shin; } sprintf(devpath, "%d:%d", - (int)(bitforce->usbdev->bus_number), - (int)(bitforce->usbdev->device_address)); + (int)(bitforce->usbinfo.bus_number), + (int)(bitforce->usbinfo.device_address)); // Allow 2 complete attempts if the 1st time returns an unrecognised reply @@ -361,7 +361,7 @@ static bool bitforce_get_temp(struct cgpu_info *bitforce) char *s; // Device is gone - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) return false; /* Do not try to get the temperature if we're polling for a result to @@ -683,7 +683,7 @@ static int64_t bitforce_scanhash(struct thr_info *thr, struct work *work, int64_ int64_t ret; // Device is gone - if (bitforce->nodev) + if (bitforce->usbinfo.nodev) return -1; send_ret = bitforce_send_work(thr, work); diff --git a/driver-modminer.c b/driver-modminer.c index 24a952a4..eb54d914 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -129,14 +129,14 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic if (!usb_init(modminer, dev, found)) { applog(LOG_ERR, "%s detect (%d:%d) failed to initialise (incorrect device?)", modminer->drv->dname, - (int)libusb_get_bus_number(dev), - (int)libusb_get_device_address(dev)); + (int)(modminer->usbinfo.bus_number), + (int)(modminer->usbinfo.device_address)); goto shin; } sprintf(devpath, "%d:%d", - (int)(modminer->usbdev->bus_number), - (int)(modminer->usbdev->device_address)); + (int)(modminer->usbinfo.bus_number), + (int)(modminer->usbinfo.device_address)); do_ping(modminer); @@ -204,15 +204,15 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic tmp->name = devname; sprintf(devpath, "%d:%d:%d", - (int)(modminer->usbdev->bus_number), - (int)(modminer->usbdev->device_address), + (int)(modminer->usbinfo.bus_number), + (int)(modminer->usbinfo.device_address), i); tmp->device_path = strdup(devpath); tmp->usbdev = modminer->usbdev; // Only the first copy gets the already used stats if (!added) - tmp->usbstat = modminer->usbstat; + tmp->usbinfo.usbstat = modminer->usbinfo.usbstat; tmp->fpgaid = (char)i; tmp->modminer_mutex = modminer->modminer_mutex; tmp->deven = DEV_ENABLED; @@ -640,7 +640,7 @@ static const char *modminer_delta_clock(struct thr_info *thr, int delta, bool te int err, amount; // Device is gone - if (modminer->nodev) + if (modminer->usbinfo.nodev) return clocknodev; // Only do once if multiple shares per work or multiple reasons @@ -828,7 +828,7 @@ static void check_temperature(struct thr_info *thr) int amount; // Device is gone - if (modminer->nodev) + if (modminer->usbinfo.nodev) return; if (state->one_byte_temp) { @@ -916,7 +916,7 @@ static uint64_t modminer_process_results(struct thr_info *thr) int temploop; // Device is gone - if (modminer->nodev) + if (modminer->usbinfo.nodev) return -1; // If we are overheated it will just keep checking for results @@ -1079,7 +1079,7 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ struct timeval tv1, tv2; // Device is gone - if (thr->cgpu->nodev) + if (thr->cgpu->usbinfo.nodev) return -1; // Don't start new work if overheated @@ -1092,7 +1092,7 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ check_temperature(thr); // Device is gone - if (thr->cgpu->nodev) + if (thr->cgpu->usbinfo.nodev) return -1; if (state->overheated == true) { diff --git a/miner.h b/miner.h index f9e616d0..2a74bdc0 100644 --- a/miner.h +++ b/miner.h @@ -400,8 +400,7 @@ struct cgpu_info { #endif }; #if defined(USE_MODMINER) || defined(USE_BITFORCE) - int usbstat; - bool nodev; + struct cg_usb_info usbinfo; #endif #ifdef USE_MODMINER char fpgaid; diff --git a/usbutils.c b/usbutils.c index 30be2884..9c55ca49 100644 --- a/usbutils.c +++ b/usbutils.c @@ -641,7 +641,7 @@ static void add_used(libusb_device *dev, bool lock) mutex_unlock(list_lock); sprintf(buf, "add_used() duplicate bus_number %d device_address %d", - bus_number, device_address); + (int)bus_number, (int)device_address); quit(1, buf); } @@ -692,7 +692,7 @@ static void release(uint8_t bus_number, uint8_t device_address, bool lock) mutex_unlock(list_lock); sprintf(buf, "release() unknown: bus_number %d device_address %d", - bus_number, device_address); + (int)bus_number, (int)device_address); quit(1, buf); } @@ -752,26 +752,26 @@ void usb_uninit(struct cgpu_info *cgpu) void release_cgpu(struct cgpu_info *cgpu) { struct cg_usb_device *cgusb = cgpu->usbdev; - uint8_t bus_number; - uint8_t device_address; int i; - cgpu->nodev = true; + cgpu->usbinfo.nodev = true; + cgpu->usbinfo.nodev_count++; + gettimeofday(&(cgpu->usbinfo.last_nodev), NULL); // Any devices sharing the same USB device should be marked also // Currently only MMQ shares a USB device for (i = 0; i < total_devices; i++) if (devices[i] != cgpu && devices[i]->usbdev == cgusb) { - devices[i]->nodev = true; + devices[i]->usbinfo.nodev = true; + devices[i]->usbinfo.nodev_count++; + memcpy(&(devices[i]->usbinfo.last_nodev), + &(cgpu->usbinfo.last_nodev), sizeof(struct timeval)); devices[i]->usbdev = NULL; } - bus_number = cgusb->bus_number; - device_address = cgusb->device_address; - usb_uninit(cgpu); - release(bus_number, device_address, true); + release(cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address, true); } bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found) @@ -783,12 +783,12 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find unsigned char strbuf[STRBUFLEN+1]; int err, i, j, k; + cgpu->usbinfo.bus_number = libusb_get_bus_number(dev); + cgpu->usbinfo.device_address = libusb_get_device_address(dev); + cgusb = calloc(1, sizeof(*cgusb)); cgusb->found = found; - cgusb->bus_number = libusb_get_bus_number(dev); - cgusb->device_address = libusb_get_device_address(dev); - cgusb->descriptor = calloc(1, sizeof(*(cgusb->descriptor))); err = libusb_get_device_descriptor(dev, cgusb->descriptor); @@ -828,7 +828,8 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find switch(err) { case LIBUSB_ERROR_BUSY: applog(LOG_WARNING, "USB init, %s device %d:%d in use", - found->name, cgusb->bus_number, cgusb->device_address); + found->name, (int)(cgpu->usbinfo.bus_number), + (int)(cgpu->usbinfo.device_address)); break; default: applog(LOG_DEBUG, "USB init, failed to set config to %d, err %d", @@ -908,7 +909,7 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find // cgusb->fwVersion <- for temp1/temp2 decision? or serial? (driver-modminer.c) // cgusb->interfaceVersion - applog(LOG_DEBUG, "USB init device bus_number=%d device_address=%d usbver=%04x prod='%s' manuf='%s' serial='%s'", (int)(cgusb->bus_number), (int)(cgusb->device_address), cgusb->usbver, cgusb->prod_string, cgusb->manuf_string, cgusb->serial_string); + applog(LOG_DEBUG, "USB init device bus_number=%d device_address=%d usbver=%04x prod='%s' manuf='%s' serial='%s'", (int)(cgpu->usbinfo.bus_number), (int)(cgpu->usbinfo.device_address), cgusb->usbver, cgusb->prod_string, cgusb->manuf_string, cgusb->serial_string); cgpu->usbdev = cgusb; @@ -1134,7 +1135,7 @@ static void newstats(struct cgpu_info *cgpu) { int i; - cgpu->usbstat = ++next_stat; + cgpu->usbinfo.usbstat = ++next_stat; usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat); usb_stats[next_stat-1].name = cgpu->drv->name; @@ -1148,11 +1149,11 @@ static void newstats(struct cgpu_info *cgpu) void update_usb_stats(__maybe_unused struct cgpu_info *cgpu) { #if DO_USB_STATS - if (cgpu->usbstat < 1) + if (cgpu->usbinfo.usbstat < 1) newstats(cgpu); // we don't know the device_id until after add_cgpu() - usb_stats[cgpu->usbstat - 1].device_id = cgpu->device_id; + usb_stats[cgpu->usbinfo.usbstat - 1].device_id = cgpu->device_id; #endif } @@ -1163,10 +1164,10 @@ static void stats(struct cgpu_info *cgpu, struct timeval *tv_start, struct timev double diff; int item; - if (cgpu->usbstat < 1) + if (cgpu->usbinfo.usbstat < 1) newstats(cgpu); - details = &(usb_stats[cgpu->usbstat - 1].details[cmd * 2 + seq]); + details = &(usb_stats[cgpu->usbinfo.usbstat - 1].details[cmd * 2 + seq]); diff = tdiff(tv_finish, tv_start); @@ -1201,10 +1202,10 @@ static void rejected_inc(struct cgpu_info *cgpu) struct cg_usb_stats_details *details; int item = CMD_ERROR; - if (cgpu->usbstat < 1) + if (cgpu->usbinfo.usbstat < 1) newstats(cgpu); - details = &(usb_stats[cgpu->usbstat - 1].details[C_REJECTED * 2 + 0]); + details = &(usb_stats[cgpu->usbinfo.usbstat - 1].details[C_REJECTED * 2 + 0]); details->item[item].count++; } @@ -1222,7 +1223,7 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro int err, got, tot, i; bool first = true; - if (cgpu->nodev) { + if (cgpu->usbinfo.nodev) { *buf = '\0'; *processed = 0; #if DO_USB_STATS @@ -1330,7 +1331,7 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr #endif int err, sent; - if (cgpu->nodev) { + if (cgpu->usbinfo.nodev) { *processed = 0; #if DO_USB_STATS rejected_inc(cgpu); @@ -1364,7 +1365,7 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest #endif int err; - if (cgpu->nodev) { + if (cgpu->usbinfo.nodev) { #if DO_USB_STATS rejected_inc(cgpu); #endif diff --git a/usbutils.h b/usbutils.h index 7912be52..d63122f8 100644 --- a/usbutils.h +++ b/usbutils.h @@ -67,8 +67,6 @@ struct cg_usb_device { libusb_device_handle *handle; pthread_mutex_t *mutex; struct libusb_device_descriptor *descriptor; - uint8_t bus_number; - uint8_t device_address; uint16_t usbver; int speed; char *prod_string; @@ -78,6 +76,15 @@ struct cg_usb_device { unsigned char interfaceVersion; // ?? }; +struct cg_usb_info { + uint8_t bus_number; + uint8_t device_address; + int usbstat; + bool nodev; + int nodev_count; + struct timeval last_nodev; +}; + enum usb_cmds { C_REJECTED = 0, C_PING, From d05779191541b4502aaba0ada5ca7bfa24f5733f Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 22 Jan 2013 21:58:33 +1100 Subject: [PATCH 35/87] Capitalise driver long names used in applog messages --- driver-bitforce.c | 2 +- driver-icarus.c | 2 +- driver-modminer.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver-bitforce.c b/driver-bitforce.c index be22c7b6..69da9a5e 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -752,7 +752,7 @@ static struct api_data *bitforce_api_stats(struct cgpu_info *cgpu) struct device_drv bitforce_drv = { .drv = DRIVER_BITFORCE, - .dname = "bitforce", + .dname = "BitForce", .name = "BFL", .drv_detect = bitforce_detect, .get_api_stats = bitforce_api_stats, diff --git a/driver-icarus.c b/driver-icarus.c index 1faab2b6..49300319 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -902,7 +902,7 @@ static void icarus_shutdown(struct thr_info *thr) struct device_drv icarus_drv = { .drv = DRIVER_ICARUS, - .dname = "icarus", + .dname = "Icarus", .name = "ICA", .drv_detect = icarus_detect, .get_api_stats = icarus_api_stats, diff --git a/driver-modminer.c b/driver-modminer.c index eb54d914..2c850b84 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -1184,7 +1184,7 @@ static char *modminer_set_device(struct cgpu_info *modminer, char *option, char struct device_drv modminer_drv = { .drv = DRIVER_MODMINER, - .dname = "modminer", + .dname = "ModMiner", .name = "MMQ", .drv_detect = modminer_detect, .get_statline_before = get_modminer_statline_before, From a59b0c0355912bfce47ae5cff1500e342b810133 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 12:42:33 +1100 Subject: [PATCH 36/87] usbutils.c use correct config from found (not 0) --- usbutils.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/usbutils.c b/usbutils.c index 9c55ca49..422962f4 100644 --- a/usbutils.c +++ b/usbutils.c @@ -815,19 +815,26 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find goto dame; } - if (libusb_kernel_driver_active(cgusb->handle, 0) == 1) { + if (libusb_kernel_driver_active(cgusb->handle, found->config) == 1) { applog(LOG_DEBUG, "USB init, kernel attached ..."); - if (libusb_detach_kernel_driver(cgusb->handle, 0) == 0) + err = libusb_detach_kernel_driver(cgusb->handle, found->config); + if (err == 0) applog(LOG_DEBUG, "USB init, kernel detached successfully"); - else - applog(LOG_WARNING, "USB init, kernel detach failed :("); + else { + applog(LOG_WARNING, + "USB init, kernel detach failed, err %s - %s device %d:%d in use?", + err, found->name, + (int)(cgpu->usbinfo.bus_number), + (int)(cgpu->usbinfo.device_address)); + goto cldame; + } } err = libusb_set_configuration(cgusb->handle, found->config); if (err) { switch(err) { case LIBUSB_ERROR_BUSY: - applog(LOG_WARNING, "USB init, %s device %d:%d in use", + applog(LOG_WARNING, "USB init, set config - %s device %d:%d in use", found->name, (int)(cgpu->usbinfo.bus_number), (int)(cgpu->usbinfo.device_address)); break; From 59c73ae59a61ac5034dabce460429e568aff0e39 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 15:56:42 +1100 Subject: [PATCH 37/87] USB usb_init() consistent err/warning/debug messages --- usbutils.c | 72 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/usbutils.c b/usbutils.c index 422962f4..31489a08 100644 --- a/usbutils.c +++ b/usbutils.c @@ -781,11 +781,15 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find const struct libusb_interface_descriptor *idesc; const struct libusb_endpoint_descriptor *epdesc; unsigned char strbuf[STRBUFLEN+1]; + char devstr[STRBUFLEN+1]; int err, i, j, k; cgpu->usbinfo.bus_number = libusb_get_bus_number(dev); cgpu->usbinfo.device_address = libusb_get_device_address(dev); + sprintf(devstr, "- %s device %d:%d", found->name, + cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); + cgusb = calloc(1, sizeof(*cgusb)); cgusb->found = found; @@ -793,7 +797,9 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find err = libusb_get_device_descriptor(dev, cgusb->descriptor); if (err) { - applog(LOG_ERR, "USB init failed to get descriptor, err %d", err); + applog(LOG_DEBUG, + "USB init failed to get descriptor, err %d %s", + err, devstr); goto dame; } @@ -801,31 +807,39 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find if (err) { switch (err) { case LIBUSB_ERROR_ACCESS: - applog(LOG_ERR, "USB init open device failed, err %d, you dont have priviledge to access the device", err); + applog(LOG_ERR, + "USB init open device failed, err %d, " + "you dont have priviledge to access %s", + err, devstr); break; #ifdef WIN32 // Windows specific message case LIBUSB_ERROR_NOT_SUPPORTED: - applog(LOG_ERR, "USB init, open device failed, err %d, you need to install a Windows USB driver for the device", err); + applog(LOG_ERR, + "USB init, open device failed, err %d, " + "you need to install a Windows USB driver for %s", + err, devstr); break; #endif default: - applog(LOG_ERR, "USB init, open device failed, err %d", err); + applog(LOG_DEBUG, + "USB init, open failed, err %d %s", + err, devstr); } goto dame; } if (libusb_kernel_driver_active(cgusb->handle, found->config) == 1) { - applog(LOG_DEBUG, "USB init, kernel attached ..."); + applog(LOG_DEBUG, "USB init, kernel attached ... %s", devstr); err = libusb_detach_kernel_driver(cgusb->handle, found->config); - if (err == 0) - applog(LOG_DEBUG, "USB init, kernel detached successfully"); - else { + if (err == 0) { + applog(LOG_DEBUG, + "USB init, kernel detached successfully %s", + devstr); + } else { applog(LOG_WARNING, - "USB init, kernel detach failed, err %s - %s device %d:%d in use?", - err, found->name, - (int)(cgpu->usbinfo.bus_number), - (int)(cgpu->usbinfo.device_address)); + "USB init, kernel detach failed, err %d in use? %s", + err, devstr); goto cldame; } } @@ -834,21 +848,23 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find if (err) { switch(err) { case LIBUSB_ERROR_BUSY: - applog(LOG_WARNING, "USB init, set config - %s device %d:%d in use", - found->name, (int)(cgpu->usbinfo.bus_number), - (int)(cgpu->usbinfo.device_address)); + applog(LOG_WARNING, + "USB init, set config %d in use %s", + found->config, devstr); break; default: - applog(LOG_DEBUG, "USB init, failed to set config to %d, err %d", - found->config, err); + applog(LOG_DEBUG, + "USB init, failed to set config to %d, err %d %s", + found->config, err, devstr); } goto cldame; } err = libusb_get_active_config_descriptor(dev, &config); if (err) { - applog(LOG_DEBUG, "USB init, failed to get config descriptor %d, err %d", - found->config, err); + applog(LOG_DEBUG, + "USB init, failed to get config descriptor %d, err %d %s", + found->config, err, devstr); goto cldame; } @@ -881,8 +897,17 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find err = libusb_claim_interface(cgusb->handle, found->interface); if (err) { - applog(LOG_DEBUG, "USB init, claim interface %d failed, err %d", - found->interface, err); + switch(err) { + case LIBUSB_ERROR_BUSY: + applog(LOG_WARNING, + "USB init, claim interface %d in use %s", + found->interface, devstr); + break; + default: + applog(LOG_DEBUG, + "USB init, claim interface %d failed, err %d %s", + found->interface, err, devstr); + } goto cldame; } @@ -916,7 +941,10 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find // cgusb->fwVersion <- for temp1/temp2 decision? or serial? (driver-modminer.c) // cgusb->interfaceVersion - applog(LOG_DEBUG, "USB init device bus_number=%d device_address=%d usbver=%04x prod='%s' manuf='%s' serial='%s'", (int)(cgpu->usbinfo.bus_number), (int)(cgpu->usbinfo.device_address), cgusb->usbver, cgusb->prod_string, cgusb->manuf_string, cgusb->serial_string); + applog(LOG_DEBUG, + "USB init %s usbver=%04x prod='%s' manuf='%s' serial='%s'", + devstr, cgusb->usbver, cgusb->prod_string, + cgusb->manuf_string, cgusb->serial_string); cgpu->usbdev = cgusb; From cb3e3ebfac5edd8ff696eaa31913ea5812bd4b05 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 20:37:28 +1100 Subject: [PATCH 38/87] USB system wide device locking on linux --- usbutils.c | 286 +++++++++++++++++++++++++++-------------------------- 1 file changed, 144 insertions(+), 142 deletions(-) diff --git a/usbutils.c b/usbutils.c index 31489a08..2e758a07 100644 --- a/usbutils.c +++ b/usbutils.c @@ -110,24 +110,10 @@ extern struct device_drv icarus_drv; extern struct device_drv modminer_drv; #endif -/* - * Our own internal list of used USB devices - * So two drivers or a single driver searching - * can't touch the same device during detection - */ -struct usb_list { - uint8_t bus_number; - uint8_t device_address; - uint8_t filler[2]; - struct usb_list *prev; - struct usb_list *next; -}; - #define STRBUFLEN 256 static const char *BLANK = ""; -static pthread_mutex_t *list_lock = NULL; -static struct usb_list *usb_head = NULL; +static bool stats_initialised = false; struct cg_usb_stats_item { uint64_t count; @@ -537,10 +523,7 @@ static void cgusb_check_init() { mutex_lock(&cgusb_lock); - if (list_lock == NULL) { - list_lock = calloc(1, sizeof(*list_lock)); - mutex_init(list_lock); - + if (stats_initialised == false) { // N.B. environment LIBUSB_DEBUG also sets libusb_set_debug() if (opt_usbdump >= 0) { libusb_set_debug(NULL, opt_usbdump); @@ -592,134 +575,163 @@ static void cgusb_check_init() mutex_unlock(&cgusb_lock); } -static bool in_use(libusb_device *dev, bool lock) -{ - struct usb_list *usb_tmp; - bool used = false; - uint8_t bus_number; - uint8_t device_address; - - bus_number = libusb_get_bus_number(dev); - device_address = libusb_get_device_address(dev); - - if (lock) - mutex_lock(list_lock); - - if ((usb_tmp = usb_head)) - do { - if (bus_number == usb_tmp->bus_number - && device_address == usb_tmp->device_address) { - used = true; - break; - } - - usb_tmp = usb_tmp->next; - - } while (usb_tmp != usb_head); - - if (lock) - mutex_unlock(list_lock); - - return used; -} +#ifdef WIN32 +#else +#include +#include +#include +#include +#include +#include +#include +#include + +union semun { + int sem; + struct semid_ds *seminfo; + ushort *all; +}; +#endif -static void add_used(libusb_device *dev, bool lock) +// Any errors should always be printed since they will rarely if ever occur +// and thus it is best to always display them +static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { - struct usb_list *usb_tmp; - char buf[128]; - uint8_t bus_number; - uint8_t device_address; - - bus_number = libusb_get_bus_number(dev); - device_address = libusb_get_device_address(dev); - - if (lock) - mutex_lock(list_lock); +#ifdef WIN32 +#else + struct semid_ds seminfo; + union semun opt; + char name[64]; + key_t key; + int fd, sem, count; + + sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address); + fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (fd == -1) { + applog(LOG_ERR, + "SEM: %s USB open failed '%s' err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return false; + } + close(fd); + key = ftok(name, 'K'); + sem = semget(key, 1, IPC_CREAT | IPC_EXCL | 438); + if (sem < 0) { + if (errno != EEXIST) { + applog(LOG_ERR, + "SEM: %s USB failed to get '%s' err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return false; + } - if (in_use(dev, false)) { - if (lock) - mutex_unlock(list_lock); + sem = semget(key, 1, 0); + if (sem < 0) { + applog(LOG_ERR, + "SEM: %s USB failed to access '%s' err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return false; + } - sprintf(buf, "add_used() duplicate bus_number %d device_address %d", - (int)bus_number, (int)device_address); - quit(1, buf); + opt.seminfo = &seminfo; + count = 0; + while (++count) { + // Should NEVER take 100ms + if (count > 99) { + applog(LOG_ERR, + "SEM: %s USB timeout waiting for (%d) '%s'", + drv->dname, sem, name); + return false; + } + if (semctl(sem, 0, IPC_STAT, opt) == -1) { + applog(LOG_ERR, + "SEM: %s USB failed to wait for (%d) '%s' count %d err (%d) %s", + drv->dname, sem, name, count, errno, strerror(errno)); + return false; + } + if (opt.seminfo->sem_otime != 0) + break; + nmsleep(1); + } } - usb_tmp = malloc(sizeof(*usb_tmp)); - - usb_tmp->bus_number = bus_number; - usb_tmp->device_address = device_address; - - if (usb_head) { - // add to end - usb_tmp->prev = usb_head->prev; - usb_tmp->next = usb_head; - usb_head->prev = usb_tmp; - usb_tmp->prev->next = usb_tmp; - } else { - usb_tmp->prev = usb_tmp; - usb_tmp->next = usb_tmp; - usb_head = usb_tmp; + struct sembuf sops[] = { + { 0, 0, IPC_NOWAIT | SEM_UNDO }, + { 0, 1, IPC_NOWAIT | SEM_UNDO } + }; + + if (semop(sem, sops, 2)) { + if (errno == EAGAIN) { + applog(LOG_WARNING, + "SEM: %s USB failed to get (%d) '%s' - device in use", + drv->dname, sem, name); + } else { + applog(LOG_DEBUG, + "SEM: %s USB failed to get (%d) '%s' err(%d) %s", + drv->dname, sem, name, errno, strerror(errno)); + } + return false; } - if (lock) - mutex_unlock(list_lock); + return true; +#endif } -static void release(uint8_t bus_number, uint8_t device_address, bool lock) +static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev) { - struct usb_list *usb_tmp; - bool found = false; - char buf[128]; - - if (lock) - mutex_lock(list_lock); - - if ((usb_tmp = usb_head)) - do { - if (bus_number == usb_tmp->bus_number - && device_address == usb_tmp->device_address) { - found = true; - break; - } - - usb_tmp = usb_tmp->next; + return cgminer_usb_lock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev)); +} - } while (usb_tmp != usb_head); +// Any errors should always be printed since they will rarely if ever occur +// and thus it is best to always display them +static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) +{ +#ifdef WIN32 +#else + char name[64]; + key_t key; + int fd, sem; + + sprintf(name, "/tmp/cgminer-usb-%d-%d", (int)bus_number, (int)device_address); + fd = open(name, O_CREAT|O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (fd == -1) { + applog(LOG_ERR, + "SEM: %s USB open failed '%s' for release err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return; + } + close(fd); + key = ftok(name, 'K'); + + sem = semget(key, 1, 0); + if (sem < 0) { + applog(LOG_ERR, + "SEM: %s USB failed to get '%s' for release err (%d) %s", + drv->dname, name, errno, strerror(errno)); + return; + } - if (!found) { - if (lock) - mutex_unlock(list_lock); + struct sembuf sops[] = { + { 0, -1, SEM_UNDO } + }; - sprintf(buf, "release() unknown: bus_number %d device_address %d", - (int)bus_number, (int)device_address); - quit(1, buf); - } + // Allow a 10ms timeout + // exceeding this timeout means it would probably never succeed anyway + struct timespec timeout = { 0, 10000000 }; - if (usb_tmp->next == usb_tmp) { - usb_head = NULL; - } else { - if (usb_head == usb_tmp) - usb_head = usb_tmp->next; - usb_tmp->next->prev = usb_tmp->prev; - usb_tmp->prev->next = usb_tmp->next; + // Wait forever since we shoud be the one who has it + if (semtimedop(sem, sops, 1, &timeout)) { + applog(LOG_ERR, + "SEM: %d USB failed to release '%s' err (%d) %s", + drv->dname, name, errno, strerror(errno)); } - if (lock) - mutex_unlock(list_lock); - - free(usb_tmp); + return; +#endif } -static void release_dev(libusb_device *dev, bool lock) +static void cgminer_usb_unlock(struct device_drv *drv, libusb_device *dev) { - uint8_t bus_number; - uint8_t device_address; - - bus_number = libusb_get_bus_number(dev); - device_address = libusb_get_device_address(dev); - - release(bus_number, device_address, lock); + cgminer_usb_unlock_bd(drv, libusb_get_bus_number(dev), libusb_get_device_address(dev)); } static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb) @@ -771,7 +783,7 @@ void release_cgpu(struct cgpu_info *cgpu) usb_uninit(cgpu); - release(cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address, true); + cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); } bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found) @@ -1053,21 +1065,11 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi applog(LOG_DEBUG, "USB scan devices: found no devices"); for (i = 0; i < count; i++) { - mutex_lock(list_lock); - - if (in_use(list[i], false)) - mutex_unlock(list_lock); - else { - add_used(list[i], false); - - mutex_unlock(list_lock); - - found = usb_check(drv, list[i]); - if (!found) - release_dev(list[i], true); - else + found = usb_check(drv, list[i]); + if (found) { + if (cgminer_usb_lock(drv, list[i]) == true) if (!device_detect(list[i], found)) - release_dev(list[i], true); + cgminer_usb_unlock(drv, list[i]); } } From 829730408920371bdd18892ca5e208b72403b76e Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 20:41:29 +1100 Subject: [PATCH 39/87] USB device locking NOOP for windows (for now) --- usbutils.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/usbutils.c b/usbutils.c index 2e758a07..035e5621 100644 --- a/usbutils.c +++ b/usbutils.c @@ -598,6 +598,10 @@ union semun { static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { #ifdef WIN32 + // NOOP for now + drv = 0; + bus_number = device_address = 0; + return true; #else struct semid_ds seminfo; union semun opt; @@ -686,6 +690,9 @@ static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev) static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { #ifdef WIN32 + // NOOP for now + drv = 0; + bus_number = device_address = 0; #else char name[64]; key_t key; From 028da16bf804d5bdebaffa8a6e47ae94b6fa3d85 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 22:13:42 +1100 Subject: [PATCH 40/87] usbutils free found if not used --- usbutils.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/usbutils.c b/usbutils.c index 035e5621..9eab1e1f 100644 --- a/usbutils.c +++ b/usbutils.c @@ -1073,10 +1073,13 @@ void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_devi for (i = 0; i < count; i++) { found = usb_check(drv, list[i]); - if (found) { - if (cgminer_usb_lock(drv, list[i]) == true) + if (found != NULL) { + if (cgminer_usb_lock(drv, list[i]) == false) + free(found); + else { if (!device_detect(list[i], found)) cgminer_usb_unlock(drv, list[i]); + } } } From 16fa090013c4ba1fb5eac4b9cfbe2dda4dc0691c Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 23 Jan 2013 22:39:26 +1100 Subject: [PATCH 41/87] usbutils stats_initialised not set --- usbutils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usbutils.c b/usbutils.c index 9eab1e1f..3c03510a 100644 --- a/usbutils.c +++ b/usbutils.c @@ -570,6 +570,8 @@ static void cgusb_check_init() usb_commands[C_SETMODEM] = C_SETMODEM_S; usb_commands[C_PURGERX] = C_PURGERX_S; usb_commands[C_PURGETX] = C_PURGETX_S; + + stats_initialised = true; } mutex_unlock(&cgusb_lock); From 128e3270fbb3f82f811e5de0679eb08793f63ced Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 24 Jan 2013 02:39:37 +1100 Subject: [PATCH 42/87] USB system wide device locking on windows --- usbutils.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 7 deletions(-) diff --git a/usbutils.c b/usbutils.c index 3c03510a..42b23d38 100644 --- a/usbutils.c +++ b/usbutils.c @@ -600,10 +600,67 @@ union semun { static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { #ifdef WIN32 - // NOOP for now - drv = 0; - bus_number = device_address = 0; + struct cgpu_info *cgpu; + HANDLE usbMutex; + char name[64]; + DWORD res; + int i; + + sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address); + + usbMutex = CreateMutex(NULL, FALSE, name); + if (usbMutex == NULL) { + applog(LOG_ERR, + "MTX: %s USB failed to get '%s' err (%d)", + drv->dname, name, GetLastError()); + return false; + } + + res = WaitForSingleObject(usbMutex, 0); + switch(res) { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + // Am I using it already? + for (i = 0; i < total_devices; i++) { + cgpu = devices[i]; + if (cgpu->usbinfo.bus_number == bus_number && + cgpu->usbinfo.device_address == device_address && + cgpu->usbinfo.nodev == false) { + if (ReleaseMutex(usbMutex)) { + applog(LOG_WARNING, + "MTX: %s USB can't get '%s' - device in use", + drv->dname, name); + goto fail; + } + applog(LOG_ERR, + "MTX: %s USB can't get '%s' - device in use - failure (%d)", + drv->dname, name, GetLastError()); + goto fail; + } + } + return true; + case WAIT_TIMEOUT: + applog(LOG_WARNING, + "MTX: %s USB failed to get '%s' - device in use", + drv->dname, name); + goto fail; + case WAIT_FAILED: + applog(LOG_ERR, + "MTX: %s USB failed to get '%s' err (%d)", + drv->dname, name, GetLastError()); + goto fail; + default: + applog(LOG_ERR, + "MTX: %s USB failed to get '%s' unknown reply (%d)", + drv->dname, name, res); + goto fail; + } + + CloseHandle(usbMutex); return true; +fail: + CloseHandle(usbMutex); + return false; #else struct semid_ds seminfo; union semun opt; @@ -672,7 +729,7 @@ static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint drv->dname, sem, name); } else { applog(LOG_DEBUG, - "SEM: %s USB failed to get (%d) '%s' err(%d) %s", + "SEM: %s USB failed to get (%d) '%s' err (%d) %s", drv->dname, sem, name, errno, strerror(errno)); } return false; @@ -692,9 +749,26 @@ static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev) static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address) { #ifdef WIN32 - // NOOP for now - drv = 0; - bus_number = device_address = 0; + HANDLE usbMutex; + char name[64]; + + sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address); + + usbMutex = CreateMutex(NULL, FALSE, name); + if (usbMutex == NULL) { + applog(LOG_ERR, + "MTX: %s USB failed to get '%s' for release err (%d)", + drv->dname, name, GetLastError()); + return; + } + + if (!ReleaseMutex(usbMutex)) + applog(LOG_ERR, + "MTX: %s USB failed to release '%s' err (%d)", + drv->dname, name, GetLastError()); + + CloseHandle(usbMutex); + return; #else char name[64]; key_t key; From 05157e0802972ee25b187ee7e0ba18d5a9e097a5 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 26 Jan 2013 21:49:20 +1100 Subject: [PATCH 43/87] USB in linux use the expected kernel config to check and detach - and set the configuration in linux also --- usbutils.c | 14 +++++++++----- usbutils.h | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/usbutils.c b/usbutils.c index 42b23d38..a34028e3 100644 --- a/usbutils.c +++ b/usbutils.c @@ -77,6 +77,7 @@ static struct usb_find_devices find_dev[] = { .name = "BFL", .idVendor = 0x0403, .idProduct = 0x6014, + .kernel = 0, .config = 1, .interface = 0, .timeout = BITFORCE_TIMEOUT_MS, @@ -89,13 +90,14 @@ static struct usb_find_devices find_dev[] = { .name = "MMQ", .idVendor = 0x1fc9, .idProduct = 0x0003, + .kernel = 0, .config = 1, .interface = 1, .timeout = MODMINER_TIMEOUT_MS, .epcount = ARRAY_SIZE(mmq_eps), .eps = mmq_eps }, #endif - { DRV_LAST, NULL, 0, 0, 0, 0, 0, 0, NULL } + { DRV_LAST, NULL, 0, 0, 0, 0, 0, 0, 0, NULL } }; #ifdef USE_BITFORCE @@ -924,9 +926,10 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find goto dame; } - if (libusb_kernel_driver_active(cgusb->handle, found->config) == 1) { +#ifndef WIN32 + if (libusb_kernel_driver_active(cgusb->handle, found->kernel) == 1) { applog(LOG_DEBUG, "USB init, kernel attached ... %s", devstr); - err = libusb_detach_kernel_driver(cgusb->handle, found->config); + err = libusb_detach_kernel_driver(cgusb->handle, found->kernel); if (err == 0) { applog(LOG_DEBUG, "USB init, kernel detached successfully %s", @@ -938,6 +941,7 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find goto cldame; } } +#endif err = libusb_set_configuration(cgusb->handle, found->config); if (err) { @@ -958,8 +962,8 @@ bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find err = libusb_get_active_config_descriptor(dev, &config); if (err) { applog(LOG_DEBUG, - "USB init, failed to get config descriptor %d, err %d %s", - found->config, err, devstr); + "USB init, failed to get config descriptor, err %d %s", + err, devstr); goto cldame; } diff --git a/usbutils.h b/usbutils.h index d63122f8..ac6ce0cd 100644 --- a/usbutils.h +++ b/usbutils.h @@ -55,6 +55,7 @@ struct usb_find_devices { const char *name; uint16_t idVendor; uint16_t idProduct; + int kernel; int config; int interface; unsigned int timeout; From 7388942bbd9471049a86ca3bbd2b92dc408cb512 Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 26 Jan 2013 21:57:09 +1100 Subject: [PATCH 44/87] Stratum disconnect shares - count total against stale --- cgminer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index c42703fb..af1e668b 100644 --- a/cgminer.c +++ b/cgminer.c @@ -4601,8 +4601,8 @@ static void clear_stratum_shares(struct pool *pool) if (cleared) { applog(LOG_WARNING, "Lost %d shares due to stratum disconnect on pool %d", cleared, pool->pool_no); - pool->stale_shares++; - total_stale++; + pool->stale_shares += cleared; + total_stale += cleared; } } From 8fbc4dade6205e101b1bbc0ac4c169b8c886c188 Mon Sep 17 00:00:00 2001 From: Kano Date: Mon, 28 Jan 2013 13:54:23 +1100 Subject: [PATCH 45/87] MMQ must copy USB bus:device due to usbinfo change --- driver-modminer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/driver-modminer.c b/driver-modminer.c index 2c850b84..02ad85dc 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -210,6 +210,8 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic tmp->device_path = strdup(devpath); tmp->usbdev = modminer->usbdev; + tmp->usbinfo.bus_number = modminer->usbinfo.bus_number; + tmp->usbinfo.device_address = modminer->usbinfo.device_address; // Only the first copy gets the already used stats if (!added) tmp->usbinfo.usbstat = modminer->usbinfo.usbstat; From 212f32e5e03ac8b351fce8b2bc9a2f7317664419 Mon Sep 17 00:00:00 2001 From: Kano Date: Tue, 29 Jan 2013 23:44:09 +1100 Subject: [PATCH 46/87] Split thr_info array into control_thr and mining_thr pointers so more mining threads can be added later --- api.c | 8 ++--- cgminer.c | 94 ++++++++++++++++++++++++++++--------------------- driver-cpu.c | 2 +- driver-opencl.c | 16 ++++----- miner.h | 3 +- 5 files changed, 69 insertions(+), 54 deletions(-) diff --git a/api.c b/api.c index a2470b0d..00d1f3ba 100644 --- a/api.c +++ b/api.c @@ -1800,9 +1800,9 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char #endif for (i = 0; i < mining_threads; i++) { - pga = thr_info[i].cgpu->cgminer_id; + thr = mining_thr[i]; + pga = thr->cgpu->cgminer_id; if (pga == dev) { - thr = &thr_info[i]; cgpu->deven = DEV_ENABLED; applog(LOG_DEBUG, "API: pushing ping (%d) to thread %d", ping, thr->id); tq_push(thr->q, &ping); @@ -2105,9 +2105,9 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char } for (i = 0; i < gpu_threads; i++) { - gpu = thr_info[i].cgpu->device_id; + thr = mining_thr[i]; + gpu = thr->cgpu->device_id; if (gpu == id) { - thr = &thr_info[i]; if (thr->cgpu->status != LIFE_WELL) { message(io_data, MSG_GPUMRE, id, NULL, isjson); return; diff --git a/cgminer.c b/cgminer.c index af1e668b..3b4d77dc 100644 --- a/cgminer.c +++ b/cgminer.c @@ -146,7 +146,8 @@ bool opt_bfl_noncerange; #endif #define QUIET (opt_quiet || opt_realquiet) -struct thr_info *thr_info; +struct thr_info *control_thr; +struct thr_info **mining_thr; static int gwsched_thr_id; static int stage_thr_id; static int watchpool_thr_id; @@ -156,7 +157,7 @@ static int input_thr_id; #endif int gpur_thr_id; static int api_thr_id; -static int total_threads; +static int total_control_threads; #ifdef HAVE_LIBUSB pthread_mutex_t cgusb_lock; @@ -377,7 +378,7 @@ static void sharelog(const char*disposition, const struct work*work) return; thr_id = work->thr_id; - cgpu = thr_info[thr_id].cgpu; + cgpu = mining_thr[thr_id]->cgpu; pool = work->pool; t = (unsigned long int)(work->tv_work_found.tv_sec); target = bin2hex(work->target, sizeof(work->target)); @@ -1722,7 +1723,7 @@ out: int dev_from_id(int thr_id) { - return thr_info[thr_id].cgpu->device_id; + return mining_thr[thr_id]->cgpu->device_id; } /* Make the change in the recent value adjust dynamically when the difference @@ -1894,7 +1895,7 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) static void text_print_status(int thr_id) { - struct cgpu_info *cgpu = thr_info[thr_id].cgpu; + struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; char logline[256]; if (cgpu) { @@ -1960,7 +1961,7 @@ static int dev_width; static void curses_print_devstatus(int thr_id) { static int awidth = 1, rwidth = 1, hwwidth = 1, uwidth = 1; - struct cgpu_info *cgpu = thr_info[thr_id].cgpu; + struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; char logline[256]; char displayed_hashes[16], displayed_rolling[16]; uint64_t dh64, dr64; @@ -2212,7 +2213,7 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, char *hashshow, bool resubmit, char *worktime) { struct pool *pool = work->pool; - struct cgpu_info *cgpu = thr_info[work->thr_id].cgpu; + struct cgpu_info *cgpu = mining_thr[work->thr_id]->cgpu; if (json_is_true(res) || (work->gbt && json_is_null(res))) { mutex_lock(&stats_lock); @@ -2362,7 +2363,7 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) char *s; bool rc = false; int thr_id = work->thr_id; - struct cgpu_info *cgpu = thr_info[thr_id].cgpu; + struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; struct pool *pool = work->pool; int rolltime; struct timeval tv_submit, tv_submit_reply; @@ -2744,18 +2745,18 @@ static void __kill_work(void) applog(LOG_DEBUG, "Killing off watchpool thread"); /* Kill the watchpool thread */ - thr = &thr_info[watchpool_thr_id]; + thr = &control_thr[watchpool_thr_id]; thr_info_cancel(thr); applog(LOG_DEBUG, "Killing off watchdog thread"); /* Kill the watchdog thread */ - thr = &thr_info[watchdog_thr_id]; + thr = &control_thr[watchdog_thr_id]; thr_info_cancel(thr); applog(LOG_DEBUG, "Stopping mining threads"); /* Stop the mining threads*/ for (i = 0; i < mining_threads; i++) { - thr = &thr_info[i]; + thr = mining_thr[i]; thr_info_freeze(thr); thr->pause = true; } @@ -2765,17 +2766,17 @@ static void __kill_work(void) applog(LOG_DEBUG, "Killing off mining threads"); /* Kill the mining threads*/ for (i = 0; i < mining_threads; i++) { - thr = &thr_info[i]; + thr = mining_thr[i]; thr_info_cancel(thr); } applog(LOG_DEBUG, "Killing off stage thread"); /* Stop the others */ - thr = &thr_info[stage_thr_id]; + thr = &control_thr[stage_thr_id]; thr_info_cancel(thr); applog(LOG_DEBUG, "Killing off API thread"); - thr = &thr_info[api_thr_id]; + thr = &control_thr[api_thr_id]; thr_info_cancel(thr); } @@ -3369,7 +3370,7 @@ static void restart_threads(void) discard_stale(); for (i = 0; i < mining_threads; i++) - thr_info[i].work_restart = true; + mining_thr[i]->work_restart = true; mutex_lock(&restart_lock); pthread_cond_broadcast(&restart_cond); @@ -4409,16 +4410,16 @@ static void hashmeter(int thr_id, struct timeval *diff, local_mhashes = (double)hashes_done / 1000000.0; /* Update the last time this thread reported in */ if (thr_id >= 0) { - gettimeofday(&thr_info[thr_id].last, NULL); - thr_info[thr_id].cgpu->device_last_well = time(NULL); + gettimeofday(&(mining_thr[thr_id]->last), NULL); + mining_thr[thr_id]->cgpu->device_last_well = time(NULL); } secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0); /* So we can call hashmeter from a non worker thread */ if (thr_id >= 0) { - struct thr_info *thr = &thr_info[thr_id]; - struct cgpu_info *cgpu = thr_info[thr_id].cgpu; + struct thr_info *thr = mining_thr[thr_id]; + struct cgpu_info *cgpu = thr->cgpu; double thread_rolling = 0.0; int i; @@ -4908,7 +4909,7 @@ retry_stratum: calc_diff(work, 0); applog(LOG_DEBUG, "Pushing pooltest work to base pool"); - tq_push(thr_info[stage_thr_id].q, work); + tq_push(control_thr[stage_thr_id].q, work); total_getworks++; pool->getwork_requested++; ret = true; @@ -5858,7 +5859,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) sched_paused = true; for (i = 0; i < mining_threads; i++) { struct thr_info *thr; - thr = &thr_info[i]; + thr = mining_thr[i]; thr->pause = true; } @@ -5872,7 +5873,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) for (i = 0; i < mining_threads; i++) { struct thr_info *thr; - thr = &thr_info[i]; + thr = mining_thr[i]; /* Don't touch disabled devices */ if (thr->cgpu->deven == DEV_DISABLED) @@ -6709,14 +6710,23 @@ int main(int argc, char *argv[]) fork_monitor(); #endif // defined(unix) - total_threads = mining_threads + 7; - thr_info = calloc(total_threads, sizeof(*thr)); - if (!thr_info) - quit(1, "Failed to calloc thr_info"); + mining_thr = calloc(mining_threads, sizeof(thr)); + if (!mining_thr) + quit(1, "Failed to calloc mining_thr"); + for (i = 0; i < mining_threads; i++) { + mining_thr[i] = calloc(1, sizeof(*thr)); + if (!mining_thr[i]) + quit(1, "Failed to calloc mining_thr[%d]", i); + } - gwsched_thr_id = mining_threads; - stage_thr_id = mining_threads + 1; - thr = &thr_info[stage_thr_id]; + total_control_threads = 7; + control_thr = calloc(total_control_threads, sizeof(*thr)); + if (!control_thr) + quit(1, "Failed to calloc control_thr"); + + gwsched_thr_id = 0; + stage_thr_id = 1; + thr = &control_thr[stage_thr_id]; thr->q = tq_new(); if (!thr->q) quit(1, "Failed to tq_new"); @@ -6808,7 +6818,7 @@ begin_bench: cgpu->status = LIFE_INIT; for (j = 0; j < cgpu->threads; ++j, ++k) { - thr = &thr_info[k]; + thr = mining_thr[k]; thr->id = k; thr->cgpu = cgpu; thr->device_thread = j; @@ -6853,15 +6863,15 @@ begin_bench: gettimeofday(&total_tv_start, NULL); gettimeofday(&total_tv_end, NULL); - watchpool_thr_id = mining_threads + 2; - thr = &thr_info[watchpool_thr_id]; + watchpool_thr_id = 2; + thr = &control_thr[watchpool_thr_id]; /* start watchpool thread */ if (thr_info_create(thr, NULL, watchpool_thread, NULL)) quit(1, "watchpool thread create failed"); pthread_detach(thr->pth); - watchdog_thr_id = mining_threads + 3; - thr = &thr_info[watchdog_thr_id]; + watchdog_thr_id = 3; + thr = &control_thr[watchdog_thr_id]; /* start watchdog thread */ if (thr_info_create(thr, NULL, watchdog_thread, NULL)) quit(1, "watchdog thread create failed"); @@ -6869,8 +6879,8 @@ begin_bench: #ifdef HAVE_OPENCL /* Create reinit gpu thread */ - gpur_thr_id = mining_threads + 4; - thr = &thr_info[gpur_thr_id]; + gpur_thr_id = 4; + thr = &control_thr[gpur_thr_id]; thr->q = tq_new(); if (!thr->q) quit(1, "tq_new failed for gpur_thr_id"); @@ -6879,8 +6889,8 @@ begin_bench: #endif /* Create API socket thread */ - api_thr_id = mining_threads + 5; - thr = &thr_info[api_thr_id]; + api_thr_id = 5; + thr = &control_thr[api_thr_id]; if (thr_info_create(thr, NULL, api_thread, thr)) quit(1, "API thread create failed"); @@ -6888,13 +6898,17 @@ begin_bench: /* Create curses input thread for keyboard input. Create this last so * that we know all threads are created since this can call kill_work * to try and shut down ll previous threads. */ - input_thr_id = mining_threads + 6; - thr = &thr_info[input_thr_id]; + input_thr_id = 6; + thr = &control_thr[input_thr_id]; if (thr_info_create(thr, NULL, input_thread, thr)) quit(1, "input thread create failed"); pthread_detach(thr->pth); #endif + /* Just to be sure */ + if (total_control_threads != 7) + quit(1, "incorrect total_control_threads (%d) should be 7", total_control_threads); + /* Once everything is set up, main() becomes the getwork scheduler */ while (42) { int ts, max_staged = opt_queue; diff --git a/driver-cpu.c b/driver-cpu.c index eb46f3d8..4b0c0865 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -768,7 +768,7 @@ static void cpu_detect() static void reinit_cpu_device(struct cgpu_info *cpu) { - tq_push(thr_info[cpur_thr_id].q, cpu); + tq_push(control_thr[cpur_thr_id].q, cpu); } static bool cpu_thread_prepare(struct thr_info *thr) diff --git a/driver-opencl.c b/driver-opencl.c index 966d8cd0..eacb0f76 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -616,7 +616,7 @@ void pause_dynamic_threads(int gpu) int i; for (i = 1; i < cgpu->threads; i++) { - struct thr_info *thr = &thr_info[i]; + struct thr_info *thr = mining_thr[i]; if (!thr->pause && cgpu->dynamic) { applog(LOG_WARNING, "Disabling extra threads due to dynamic mode."); @@ -705,7 +705,7 @@ retry: else wlog("%d\n", gpus[gpu].intensity); for (i = 0; i < mining_threads; i++) { - thr = &thr_info[i]; + thr = mining_thr[i]; if (thr->cgpu != cgpu) continue; get_datestamp(checkin, &thr->last); @@ -760,7 +760,7 @@ retry: } gpus[selected].deven = DEV_ENABLED; for (i = 0; i < mining_threads; ++i) { - thr = &thr_info[i]; + thr = mining_thr[i]; cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1147,14 +1147,14 @@ select_cgpu: gpu = cgpu->device_id; for (thr_id = 0; thr_id < mining_threads; ++thr_id) { - thr = &thr_info[thr_id]; + thr = mining_thr[thr_id]; cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; - thr = &thr_info[thr_id]; + thr = mining_thr[thr_id]; if (!thr) { applog(LOG_WARNING, "No reference to thread %d exists", thr_id); continue; @@ -1172,7 +1172,7 @@ select_cgpu: for (thr_id = 0; thr_id < mining_threads; ++thr_id) { int virtual_gpu; - thr = &thr_info[thr_id]; + thr = mining_thr[thr_id]; cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1209,7 +1209,7 @@ select_cgpu: get_datestamp(cgpu->init, &now); for (thr_id = 0; thr_id < mining_threads; ++thr_id) { - thr = &thr_info[thr_id]; + thr = mining_thr[thr_id]; cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1263,7 +1263,7 @@ static void opencl_detect() static void reinit_opencl_device(struct cgpu_info *gpu) { - tq_push(thr_info[gpur_thr_id].q, gpu); + tq_push(control_thr[gpur_thr_id].q, gpu); } #ifdef HAVE_ADL diff --git a/miner.h b/miner.h index 2a74bdc0..e6d18c00 100644 --- a/miner.h +++ b/miner.h @@ -784,7 +784,8 @@ extern int num_processors; extern int hw_errors; extern bool use_syslog; extern bool opt_quiet; -extern struct thr_info *thr_info; +extern struct thr_info *control_thr; +extern struct thr_info **mining_thr; extern struct cgpu_info gpus[MAX_GPUDEVICES]; extern int gpu_threads; #ifdef USE_SCRYPT From 61ec1fe91f2a2da3511243848f04ddad9d0874de Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 30 Jan 2013 15:02:25 +1100 Subject: [PATCH 47/87] mutex all access to mining_thr --- api.c | 4 +++ cgminer.c | 66 ++++++++++++++++++++++++++++++++++++++----------- driver-opencl.c | 18 +++++++++++++- miner.h | 1 + 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/api.c b/api.c index 00d1f3ba..4998d97b 100644 --- a/api.c +++ b/api.c @@ -1800,7 +1800,9 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char #endif for (i = 0; i < mining_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); pga = thr->cgpu->cgminer_id; if (pga == dev) { cgpu->deven = DEV_ENABLED; @@ -2105,7 +2107,9 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char } for (i = 0; i < gpu_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); gpu = thr->cgpu->device_id; if (gpu == id) { if (thr->cgpu->status != LIFE_WELL) { diff --git a/cgminer.c b/cgminer.c index 3b4d77dc..1a43e77b 100644 --- a/cgminer.c +++ b/cgminer.c @@ -172,6 +172,7 @@ static pthread_rwlock_t blk_lock; static pthread_mutex_t sshare_lock; pthread_rwlock_t netacc_lock; +pthread_mutex_t mining_thr_lock; static pthread_mutex_t lp_lock; static pthread_cond_t lp_cond; @@ -378,7 +379,9 @@ static void sharelog(const char*disposition, const struct work*work) return; thr_id = work->thr_id; + mutex_lock(&mining_thr_lock); cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); pool = work->pool; t = (unsigned long int)(work->tv_work_found.tv_sec); target = bin2hex(work->target, sizeof(work->target)); @@ -1723,7 +1726,13 @@ out: int dev_from_id(int thr_id) { - return mining_thr[thr_id]->cgpu->device_id; + struct cgpu_info *cgpu; + + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); + + return cgpu->device_id; } /* Make the change in the recent value adjust dynamically when the difference @@ -1895,9 +1904,13 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) static void text_print_status(int thr_id) { - struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; + struct cgpu_info *cgpu; char logline[256]; + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); + if (cgpu) { get_statline(logline, cgpu); printf("%s\n", logline); @@ -1961,11 +1974,15 @@ static int dev_width; static void curses_print_devstatus(int thr_id) { static int awidth = 1, rwidth = 1, hwwidth = 1, uwidth = 1; - struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; + struct cgpu_info *cgpu; char logline[256]; char displayed_hashes[16], displayed_rolling[16]; uint64_t dh64, dr64; + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); + if (devcursor + cgpu->cgminer_id > LINES - 2 || opt_compact) return; @@ -2213,7 +2230,11 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, char *hashshow, bool resubmit, char *worktime) { struct pool *pool = work->pool; - struct cgpu_info *cgpu = mining_thr[work->thr_id]->cgpu; + struct cgpu_info *cgpu; + + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[work->thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); if (json_is_true(res) || (work->gbt && json_is_null(res))) { mutex_lock(&stats_lock); @@ -2363,13 +2384,17 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) char *s; bool rc = false; int thr_id = work->thr_id; - struct cgpu_info *cgpu = mining_thr[thr_id]->cgpu; + struct cgpu_info *cgpu; struct pool *pool = work->pool; int rolltime; struct timeval tv_submit, tv_submit_reply; char hashshow[64 + 4] = ""; char worktime[200] = ""; + mutex_lock(&mining_thr_lock); + cgpu = mining_thr[thr_id]->cgpu; + mutex_unlock(&mining_thr_lock); + #ifdef __BIG_ENDIAN__ int swapcounter = 0; for (swapcounter = 0; swapcounter < 32; swapcounter++) @@ -2756,7 +2781,9 @@ static void __kill_work(void) applog(LOG_DEBUG, "Stopping mining threads"); /* Stop the mining threads*/ for (i = 0; i < mining_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); thr_info_freeze(thr); thr->pause = true; } @@ -2766,7 +2793,9 @@ static void __kill_work(void) applog(LOG_DEBUG, "Killing off mining threads"); /* Kill the mining threads*/ for (i = 0; i < mining_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); thr_info_cancel(thr); } @@ -3369,8 +3398,10 @@ static void restart_threads(void) /* Discard staged work that is now stale */ discard_stale(); + mutex_lock(&mining_thr_lock); for (i = 0; i < mining_threads; i++) mining_thr[i]->work_restart = true; + mutex_unlock(&mining_thr_lock); mutex_lock(&restart_lock); pthread_cond_broadcast(&restart_cond); @@ -4406,19 +4437,22 @@ static void hashmeter(int thr_id, struct timeval *diff, bool showlog = false; char displayed_hashes[16], displayed_rolling[16]; uint64_t dh64, dr64; + struct thr_info *thr; local_mhashes = (double)hashes_done / 1000000.0; /* Update the last time this thread reported in */ if (thr_id >= 0) { - gettimeofday(&(mining_thr[thr_id]->last), NULL); - mining_thr[thr_id]->cgpu->device_last_well = time(NULL); + mutex_lock(&mining_thr_lock); + thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); + gettimeofday(&(thr->last), NULL); + thr->cgpu->device_last_well = time(NULL); } secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0); /* So we can call hashmeter from a non worker thread */ if (thr_id >= 0) { - struct thr_info *thr = mining_thr[thr_id]; struct cgpu_info *cgpu = thr->cgpu; double thread_rolling = 0.0; int i; @@ -5857,12 +5891,10 @@ static void *watchdog_thread(void __maybe_unused *userdata) applog(LOG_WARNING, "Will restart execution as scheduled at %02d:%02d", schedstart.tm.tm_hour, schedstart.tm.tm_min); sched_paused = true; - for (i = 0; i < mining_threads; i++) { - struct thr_info *thr; - thr = mining_thr[i]; - - thr->pause = true; - } + mutex_lock(&mining_thr_lock); + for (i = 0; i < mining_threads; i++) + mining_thr[i]->pause = true; + mutex_unlock(&mining_thr_lock); } else if (sched_paused && should_run()) { applog(LOG_WARNING, "Restarting execution as per start time %02d:%02d scheduled", schedstart.tm.tm_hour, schedstart.tm.tm_min); @@ -5873,7 +5905,10 @@ static void *watchdog_thread(void __maybe_unused *userdata) for (i = 0; i < mining_threads; i++) { struct thr_info *thr; + + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); /* Don't touch disabled devices */ if (thr->cgpu->deven == DEV_DISABLED) @@ -6426,6 +6461,7 @@ int main(int argc, char *argv[]) mutex_init(&sshare_lock); rwlock_init(&blk_lock); rwlock_init(&netacc_lock); + mutex_init(&mining_thr_lock); mutex_init(&lp_lock); if (unlikely(pthread_cond_init(&lp_cond, NULL))) @@ -6818,7 +6854,9 @@ begin_bench: cgpu->status = LIFE_INIT; for (j = 0; j < cgpu->threads; ++j, ++k) { + mutex_lock(&mining_thr_lock); thr = mining_thr[k]; + mutex_unlock(&mining_thr_lock); thr->id = k; thr->cgpu = cgpu; thr->device_thread = j; diff --git a/driver-opencl.c b/driver-opencl.c index eacb0f76..299d8c40 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -616,7 +616,11 @@ void pause_dynamic_threads(int gpu) int i; for (i = 1; i < cgpu->threads; i++) { - struct thr_info *thr = mining_thr[i]; + struct thr_info *thr; + + mutex_lock(&mining_thr_lock); + thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); if (!thr->pause && cgpu->dynamic) { applog(LOG_WARNING, "Disabling extra threads due to dynamic mode."); @@ -705,7 +709,9 @@ retry: else wlog("%d\n", gpus[gpu].intensity); for (i = 0; i < mining_threads; i++) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); if (thr->cgpu != cgpu) continue; get_datestamp(checkin, &thr->last); @@ -760,7 +766,9 @@ retry: } gpus[selected].deven = DEV_ENABLED; for (i = 0; i < mining_threads; ++i) { + mutex_lock(&mining_thr_lock); thr = mining_thr[i]; + mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1147,14 +1155,18 @@ select_cgpu: gpu = cgpu->device_id; for (thr_id = 0; thr_id < mining_threads; ++thr_id) { + mutex_lock(&mining_thr_lock); thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; + mutex_lock(&mining_thr_lock); thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); if (!thr) { applog(LOG_WARNING, "No reference to thread %d exists", thr_id); continue; @@ -1172,7 +1184,9 @@ select_cgpu: for (thr_id = 0; thr_id < mining_threads; ++thr_id) { int virtual_gpu; + mutex_lock(&mining_thr_lock); thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; @@ -1209,7 +1223,9 @@ select_cgpu: get_datestamp(cgpu->init, &now); for (thr_id = 0; thr_id < mining_threads; ++thr_id) { + mutex_lock(&mining_thr_lock); thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; if (cgpu->drv->drv != DRIVER_OPENCL) continue; diff --git a/miner.h b/miner.h index e6d18c00..f25b6263 100644 --- a/miner.h +++ b/miner.h @@ -737,6 +737,7 @@ extern pthread_mutex_t cgusb_lock; extern pthread_mutex_t hash_lock; extern pthread_mutex_t console_lock; extern pthread_mutex_t ch_lock; +extern pthread_mutex_t mining_thr_lock; extern pthread_mutex_t restart_lock; extern pthread_cond_t restart_cond; From 7abf30b2c035b833f507200ce90d0651b0518be1 Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 3 Feb 2013 22:51:05 +1100 Subject: [PATCH 48/87] distinguish between drv and it's id enum now called drv_id --- api.c | 20 ++++++++++---------- cgminer.c | 8 ++++---- driver-bitforce.c | 2 +- driver-cpu.c | 2 +- driver-icarus.c | 2 +- driver-modminer.c | 2 +- driver-opencl.c | 10 +++++----- miner.h | 2 +- usbutils.c | 6 +++--- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/api.c b/api.c index 4998d97b..1a2f312e 100644 --- a/api.c +++ b/api.c @@ -1150,19 +1150,19 @@ static int numpgas() for (i = 0; i < total_devices; i++) { #ifdef USE_BITFORCE - if (devices[i]->drv->drv == DRIVER_BITFORCE) + if (devices[i]->drv->drv_id == DRIVER_BITFORCE) count++; #endif #ifdef USE_ICARUS - if (devices[i]->drv->drv == DRIVER_ICARUS) + if (devices[i]->drv->drv_id == DRIVER_ICARUS) count++; #endif #ifdef USE_ZTEX - if (devices[i]->drv->drv == DRIVER_ZTEX) + if (devices[i]->drv->drv_id == DRIVER_ZTEX) count++; #endif #ifdef USE_MODMINER - if (devices[i]->drv->drv == DRIVER_MODMINER) + if (devices[i]->drv->drv_id == DRIVER_MODMINER) count++; #endif } @@ -1176,19 +1176,19 @@ static int pgadevice(int pgaid) for (i = 0; i < total_devices; i++) { #ifdef USE_BITFORCE - if (devices[i]->drv->drv == DRIVER_BITFORCE) + if (devices[i]->drv->drv_id == DRIVER_BITFORCE) count++; #endif #ifdef USE_ICARUS - if (devices[i]->drv->drv == DRIVER_ICARUS) + if (devices[i]->drv->drv_id == DRIVER_ICARUS) count++; #endif #ifdef USE_ZTEX - if (devices[i]->drv->drv == DRIVER_ZTEX) + if (devices[i]->drv->drv_id == DRIVER_ZTEX) count++; #endif #ifdef USE_MODMINER - if (devices[i]->drv->drv == DRIVER_MODMINER) + if (devices[i]->drv->drv_id == DRIVER_MODMINER) count++; #endif if (count == (pgaid + 1)) @@ -1532,11 +1532,11 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom float temp = cgpu->temp; #ifdef USE_ZTEX - if (cgpu->drv->drv == DRIVER_ZTEX && cgpu->device_ztex) + if (cgpu->drv->drv_id == DRIVER_ZTEX && cgpu->device_ztex) frequency = cgpu->device_ztex->freqM1 * (cgpu->device_ztex->freqM + 1); #endif #ifdef USE_MODMINER - if (cgpu->drv->drv == DRIVER_MODMINER) + if (cgpu->drv->drv_id == DRIVER_MODMINER) frequency = cgpu->clock; #endif diff --git a/cgminer.c b/cgminer.c index 1a43e77b..7a95d1fc 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5950,7 +5950,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) continue; #ifdef WANT_CPUMINE - if (cgpu->drv->drv == DRIVER_CPU) + if (cgpu->drv->drv_id == DRIVER_CPU) continue; #endif if (cgpu->status != LIFE_WELL && (now.tv_sec - thr->last.tv_sec < WATCHDOG_SICK_TIME)) { @@ -6342,7 +6342,7 @@ void enable_curses(void) { #ifndef WANT_CPUMINE struct device_drv cpu_drv; struct device_drv cpu_drv = { - .drv = DRIVER_CPU, + .drv_id = DRIVER_CPU, .name = "CPU", }; #endif @@ -6375,7 +6375,7 @@ void enable_device(struct cgpu_info *cgpu) adj_width(mining_threads, &dev_width); #endif #ifdef HAVE_OPENCL - if (cgpu->drv->drv == DRIVER_OPENCL) { + if (cgpu->drv->drv_id == DRIVER_OPENCL) { gpu_threads += cgpu->threads; } #endif @@ -6680,7 +6680,7 @@ int main(int argc, char *argv[]) enable_device(devices[i]); } else if (i < total_devices) { if (opt_removedisabled) { - if (devices[i]->drv->drv == DRIVER_CPU) + if (devices[i]->drv->drv_id == DRIVER_CPU) --opt_n_threads; } else { enable_device(devices[i]); diff --git a/driver-bitforce.c b/driver-bitforce.c index 69da9a5e..de1a8e6d 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -751,7 +751,7 @@ static struct api_data *bitforce_api_stats(struct cgpu_info *cgpu) } struct device_drv bitforce_drv = { - .drv = DRIVER_BITFORCE, + .drv_id = DRIVER_BITFORCE, .dname = "BitForce", .name = "BFL", .drv_detect = bitforce_detect, diff --git a/driver-cpu.c b/driver-cpu.c index 4b0c0865..a8b7a56a 100644 --- a/driver-cpu.c +++ b/driver-cpu.c @@ -844,7 +844,7 @@ CPUSearch: } struct device_drv cpu_drv = { - .drv = DRIVER_CPU, + .drv_id = DRIVER_CPU, .dname = "cpu", .name = "CPU", .drv_detect = cpu_detect, diff --git a/driver-icarus.c b/driver-icarus.c index 49300319..9a99e866 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -901,7 +901,7 @@ static void icarus_shutdown(struct thr_info *thr) } struct device_drv icarus_drv = { - .drv = DRIVER_ICARUS, + .drv_id = DRIVER_ICARUS, .dname = "Icarus", .name = "ICA", .drv_detect = icarus_detect, diff --git a/driver-modminer.c b/driver-modminer.c index 02ad85dc..22812aa5 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -1185,7 +1185,7 @@ static char *modminer_set_device(struct cgpu_info *modminer, char *option, char } struct device_drv modminer_drv = { - .drv = DRIVER_MODMINER, + .drv_id = DRIVER_MODMINER, .dname = "ModMiner", .name = "MMQ", .drv_detect = modminer_detect, diff --git a/driver-opencl.c b/driver-opencl.c index 299d8c40..0521ac1e 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -770,7 +770,7 @@ retry: thr = mining_thr[i]; mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; - if (cgpu->drv->drv != DRIVER_OPENCL) + if (cgpu->drv->drv_id != DRIVER_OPENCL) continue; if (dev_from_id(i) != selected) continue; @@ -1159,7 +1159,7 @@ select_cgpu: thr = mining_thr[thr_id]; mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; - if (cgpu->drv->drv != DRIVER_OPENCL) + if (cgpu->drv->drv_id != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; @@ -1188,7 +1188,7 @@ select_cgpu: thr = mining_thr[thr_id]; mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; - if (cgpu->drv->drv != DRIVER_OPENCL) + if (cgpu->drv->drv_id != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; @@ -1227,7 +1227,7 @@ select_cgpu: thr = mining_thr[thr_id]; mutex_unlock(&mining_thr_lock); cgpu = thr->cgpu; - if (cgpu->drv->drv != DRIVER_OPENCL) + if (cgpu->drv->drv_id != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; @@ -1574,7 +1574,7 @@ static void opencl_thread_shutdown(struct thr_info *thr) } struct device_drv opencl_drv = { - .drv = DRIVER_OPENCL, + .drv_id = DRIVER_OPENCL, .dname = "opencl", .name = "GPU", .drv_detect = opencl_detect, diff --git a/miner.h b/miner.h index f25b6263..87d58fe6 100644 --- a/miner.h +++ b/miner.h @@ -273,7 +273,7 @@ struct thr_info; struct work; struct device_drv { - enum drv_driver drv; + enum drv_driver drv_id; char *dname; char *name; diff --git a/usbutils.c b/usbutils.c index a34028e3..ba4db390 100644 --- a/usbutils.c +++ b/usbutils.c @@ -1117,17 +1117,17 @@ static struct usb_find_devices *usb_check_each(int drvnum, struct device_drv *dr static struct usb_find_devices *usb_check(__maybe_unused struct device_drv *drv, __maybe_unused struct libusb_device *dev) { #ifdef USE_BITFORCE - if (drv->drv == DRIVER_BITFORCE) + if (drv->drv_id == DRIVER_BITFORCE) return usb_check_each(DRV_BITFORCE, drv, dev); #endif #ifdef USE_ICARUS - if (drv->drv == DRIVER_ICARUS) + if (drv->drv_id == DRIVER_ICARUS) return usb_check_each(DRV_ICARUS, drv, dev); #endif #ifdef USE_MODMINER - if (drv->drv == DRIVER_MODMINER) + if (drv->drv_id == DRIVER_MODMINER) return usb_check_each(DRV_MODMINER, drv, dev); #endif From 5d122cad93f0d6e57e5ad36b0f9b00ff39d9ff18 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sun, 3 Feb 2013 23:41:41 +1100 Subject: [PATCH 49/87] Provide wrappers for grabbing of thr value under the mining_thr_lock. --- api.c | 8 ++----- cgminer.c | 64 ++++++++++++++++++++++--------------------------- driver-opencl.c | 29 ++++++---------------- miner.h | 1 + 4 files changed, 38 insertions(+), 64 deletions(-) diff --git a/api.c b/api.c index 1a2f312e..84a947c6 100644 --- a/api.c +++ b/api.c @@ -1800,9 +1800,7 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char #endif for (i = 0; i < mining_threads; i++) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[i]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(i); pga = thr->cgpu->cgminer_id; if (pga == dev) { cgpu->deven = DEV_ENABLED; @@ -2107,9 +2105,7 @@ static void gpuenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char } for (i = 0; i < gpu_threads; i++) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[i]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(i); gpu = thr->cgpu->device_id; if (gpu == id) { if (thr->cgpu->status != LIFE_WELL) { diff --git a/cgminer.c b/cgminer.c index cfc2cfaa..f8efa624 100644 --- a/cgminer.c +++ b/cgminer.c @@ -365,6 +365,23 @@ static void applog_and_exit(const char *fmt, ...) static pthread_mutex_t sharelog_lock; static FILE *sharelog_file = NULL; +struct thr_info *get_thread(int thr_id) +{ + struct thr_info *thr; + + mutex_lock(&mining_thr_lock); + thr = mining_thr[thr_id]; + mutex_unlock(&mining_thr_lock); + return thr; +} + +static struct cgpu_info *get_thr_cgpu(int thr_id) +{ + struct thr_info *thr = get_thread(thr_id); + + return thr->cgpu; +} + static void sharelog(const char*disposition, const struct work*work) { char *target, *hash, *data; @@ -379,9 +396,7 @@ static void sharelog(const char*disposition, const struct work*work) return; thr_id = work->thr_id; - mutex_lock(&mining_thr_lock); - cgpu = mining_thr[thr_id]->cgpu; - mutex_unlock(&mining_thr_lock); + cgpu = get_thr_cgpu(thr_id); pool = work->pool; t = (unsigned long int)(work->tv_work_found.tv_sec); target = bin2hex(work->target, sizeof(work->target)); @@ -1726,11 +1741,7 @@ out: int dev_from_id(int thr_id) { - struct cgpu_info *cgpu; - - mutex_lock(&mining_thr_lock); - cgpu = mining_thr[thr_id]->cgpu; - mutex_unlock(&mining_thr_lock); + struct cgpu_info *cgpu = get_thr_cgpu(thr_id); return cgpu->device_id; } @@ -1907,10 +1918,7 @@ static void text_print_status(int thr_id) struct cgpu_info *cgpu; char logline[256]; - mutex_lock(&mining_thr_lock); - cgpu = mining_thr[thr_id]->cgpu; - mutex_unlock(&mining_thr_lock); - + cgpu = get_thr_cgpu(thr_id); if (cgpu) { get_statline(logline, cgpu); printf("%s\n", logline); @@ -1979,9 +1987,7 @@ static void curses_print_devstatus(int thr_id) char displayed_hashes[16], displayed_rolling[16]; uint64_t dh64, dr64; - mutex_lock(&mining_thr_lock); - cgpu = mining_thr[thr_id]->cgpu; - mutex_unlock(&mining_thr_lock); + cgpu = get_thr_cgpu(thr_id); if (devcursor + cgpu->cgminer_id > LINES - 2 || opt_compact) return; @@ -2232,9 +2238,7 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, struct pool *pool = work->pool; struct cgpu_info *cgpu; - mutex_lock(&mining_thr_lock); - cgpu = mining_thr[work->thr_id]->cgpu; - mutex_unlock(&mining_thr_lock); + cgpu = get_thr_cgpu(work->thr_id); if (json_is_true(res) || (work->gbt && json_is_null(res))) { mutex_lock(&stats_lock); @@ -2391,9 +2395,7 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) char hashshow[64 + 4] = ""; char worktime[200] = ""; - mutex_lock(&mining_thr_lock); - cgpu = mining_thr[thr_id]->cgpu; - mutex_unlock(&mining_thr_lock); + cgpu = get_thr_cgpu(thr_id); #ifdef __BIG_ENDIAN__ int swapcounter = 0; @@ -2781,9 +2783,7 @@ static void __kill_work(void) applog(LOG_DEBUG, "Stopping mining threads"); /* Stop the mining threads*/ for (i = 0; i < mining_threads; i++) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[i]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(i); thr_info_freeze(thr); thr->pause = true; } @@ -2793,9 +2793,7 @@ static void __kill_work(void) applog(LOG_DEBUG, "Killing off mining threads"); /* Kill the mining threads*/ for (i = 0; i < mining_threads; i++) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[i]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(i); thr_info_cancel(thr); } @@ -4443,9 +4441,7 @@ static void hashmeter(int thr_id, struct timeval *diff, local_mhashes = (double)hashes_done / 1000000.0; /* Update the last time this thread reported in */ if (thr_id >= 0) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[thr_id]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(thr_id); gettimeofday(&(thr->last), NULL); thr->cgpu->device_last_well = time(NULL); } @@ -5907,9 +5903,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) for (i = 0; i < mining_threads; i++) { struct thr_info *thr; - mutex_lock(&mining_thr_lock); - thr = mining_thr[i]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(i); /* Don't touch disabled devices */ if (thr->cgpu->deven == DEV_DISABLED) @@ -6855,9 +6849,7 @@ begin_bench: cgpu->status = LIFE_INIT; for (j = 0; j < cgpu->threads; ++j, ++k) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[k]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(k); thr->id = k; thr->cgpu = cgpu; thr->device_thread = j; diff --git a/driver-opencl.c b/driver-opencl.c index 0521ac1e..9e9e4015 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -618,10 +618,7 @@ void pause_dynamic_threads(int gpu) for (i = 1; i < cgpu->threads; i++) { struct thr_info *thr; - mutex_lock(&mining_thr_lock); - thr = mining_thr[i]; - mutex_unlock(&mining_thr_lock); - + thr = get_thread(i); if (!thr->pause && cgpu->dynamic) { applog(LOG_WARNING, "Disabling extra threads due to dynamic mode."); applog(LOG_WARNING, "Tune dynamic intensity with --gpu-dyninterval"); @@ -709,9 +706,7 @@ retry: else wlog("%d\n", gpus[gpu].intensity); for (i = 0; i < mining_threads; i++) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[i]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(i); if (thr->cgpu != cgpu) continue; get_datestamp(checkin, &thr->last); @@ -766,9 +761,7 @@ retry: } gpus[selected].deven = DEV_ENABLED; for (i = 0; i < mining_threads; ++i) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[i]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(i); cgpu = thr->cgpu; if (cgpu->drv->drv_id != DRIVER_OPENCL) continue; @@ -1155,18 +1148,14 @@ select_cgpu: gpu = cgpu->device_id; for (thr_id = 0; thr_id < mining_threads; ++thr_id) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[thr_id]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(thr_id); cgpu = thr->cgpu; if (cgpu->drv->drv_id != DRIVER_OPENCL) continue; if (dev_from_id(thr_id) != gpu) continue; - mutex_lock(&mining_thr_lock); - thr = mining_thr[thr_id]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(thr_id); if (!thr) { applog(LOG_WARNING, "No reference to thread %d exists", thr_id); continue; @@ -1184,9 +1173,7 @@ select_cgpu: for (thr_id = 0; thr_id < mining_threads; ++thr_id) { int virtual_gpu; - mutex_lock(&mining_thr_lock); - thr = mining_thr[thr_id]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(thr_id); cgpu = thr->cgpu; if (cgpu->drv->drv_id != DRIVER_OPENCL) continue; @@ -1223,9 +1210,7 @@ select_cgpu: get_datestamp(cgpu->init, &now); for (thr_id = 0; thr_id < mining_threads; ++thr_id) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[thr_id]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(thr_id); cgpu = thr->cgpu; if (cgpu->drv->drv_id != DRIVER_OPENCL) continue; diff --git a/miner.h b/miner.h index 87d58fe6..a862af6c 100644 --- a/miner.h +++ b/miner.h @@ -1101,6 +1101,7 @@ extern void clean_work(struct work *work); extern void free_work(struct work *work); extern void __copy_work(struct work *work, struct work *base_work); extern struct work *copy_work(struct work *base_work); +extern struct thr_info *get_thread(int thr_id); enum api_data_type { API_ESCAPE, From 296eab26b4cf064f76f64511f8adf1794d7737b0 Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 31 Jan 2013 23:18:12 +1100 Subject: [PATCH 50/87] Report USB nodev as ZOMBIE on the screen --- cgminer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cgminer.c b/cgminer.c index dfa22abc..8abdcaf1 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2012,6 +2012,11 @@ static void curses_print_devstatus(int thr_id) suffix_string(dh64, displayed_hashes, 4); suffix_string(dr64, displayed_rolling, 4); +#if defined(USE_MODMINER) || defined(USE_BITFORCE) + if (cgpu->usbinfo.nodev) + wprintw(statuswin, "ZOMBIE"); + else +#endif if (cgpu->status == LIFE_DEAD) wprintw(statuswin, "DEAD "); else if (cgpu->status == LIFE_SICK) From 983fe2b0c0e0c0365dc457cc1d40ef7025bbb53f Mon Sep 17 00:00:00 2001 From: Kano Date: Sat, 2 Feb 2013 09:51:47 +1100 Subject: [PATCH 51/87] usbutils hotplug v0.1 --- api.c | 59 ++++++++++++--- cgminer.c | 201 +++++++++++++++++++++++++++++++++++++++++++++----- driver-ztex.c | 2 + miner.h | 2 + usbutils.c | 33 ++++++--- 5 files changed, 255 insertions(+), 42 deletions(-) diff --git a/api.c b/api.c index 84a947c6..7432637a 100644 --- a/api.c +++ b/api.c @@ -1148,6 +1148,7 @@ static int numpgas() int count = 0; int i; + mutex_lock(&devices_lock); for (i = 0; i < total_devices; i++) { #ifdef USE_BITFORCE if (devices[i]->drv->drv_id == DRIVER_BITFORCE) @@ -1166,6 +1167,7 @@ static int numpgas() count++; #endif } + mutex_unlock(&devices_lock); return count; } @@ -1174,6 +1176,7 @@ static int pgadevice(int pgaid) int count = 0; int i; + mutex_lock(&devices_lock); for (i = 0; i < total_devices; i++) { #ifdef USE_BITFORCE if (devices[i]->drv->drv_id == DRIVER_BITFORCE) @@ -1191,9 +1194,12 @@ static int pgadevice(int pgaid) if (devices[i]->drv->drv_id == DRIVER_MODMINER) count++; #endif - if (count == (pgaid + 1)) + if (count == (pgaid + 1)) { + mutex_unlock(&devices_lock); return i; + } } + mutex_unlock(&devices_lock); return -1; } #endif @@ -1527,9 +1533,14 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom if (dev < 0) // Should never happen return; - struct cgpu_info *cgpu = devices[dev]; + struct cgpu_info *cgpu; double frequency = 0; - float temp = cgpu->temp; + float temp; + + mutex_lock(&devices_lock); + cgpu = devices[dev]; + mutex_unlock(&devices_lock); + temp = cgpu->temp; #ifdef USE_ZTEX if (cgpu->drv->drv_id == DRIVER_ZTEX && cgpu->device_ztex) @@ -1747,6 +1758,7 @@ static void pgadev(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *p static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) { + struct cgpu_info *cgpu; int numpga = numpgas(); struct thr_info *thr; int pga; @@ -1775,7 +1787,9 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char return; } - struct cgpu_info *cgpu = devices[dev]; + mutex_lock(&devices_lock); + cgpu = devices[dev]; + mutex_unlock(&devices_lock); applog(LOG_DEBUG, "API: request to pgaenable pgaid %d device %d %s%u", id, dev, cgpu->drv->name, cgpu->device_id); @@ -1814,6 +1828,7 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) { + struct cgpu_info *cgpu; int numpga = numpgas(); int id; @@ -1839,7 +1854,9 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha return; } - struct cgpu_info *cgpu = devices[dev]; + mutex_lock(&devices_lock); + cgpu = devices[dev]; + mutex_unlock(&devices_lock); applog(LOG_DEBUG, "API: request to pgadisable pgaid %d device %d %s%u", id, dev, cgpu->drv->name, cgpu->device_id); @@ -1856,6 +1873,8 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) { + struct cgpu_info *cgpu; + struct device_drv *drv; int numpga = numpgas(); int id; @@ -1881,8 +1900,10 @@ static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, ch return; } - struct cgpu_info *cgpu = devices[dev]; - struct device_drv *drv = cgpu->drv; + mutex_lock(&devices_lock); + cgpu = devices[dev]; + mutex_unlock(&devices_lock); + drv = cgpu->drv; if (!drv->identify_device) message(io_data, MSG_PGANOID, id, NULL, isjson); @@ -2794,6 +2815,7 @@ void notifystatus(struct io_data *io_data, int device, struct cgpu_info *cgpu, b static void notify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, char group) { + struct cgpu_info *cgpu; bool io_open = false; int i; @@ -2807,8 +2829,12 @@ static void notify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe if (isjson) io_open = io_add(io_data, COMSTR JSON_NOTIFY); - for (i = 0; i < total_devices; i++) - notifystatus(io_data, i, devices[i], isjson, group); + for (i = 0; i < total_devices; i++) { + mutex_lock(&devices_lock); + cgpu = devices[i]; + mutex_unlock(&devices_lock); + notifystatus(io_data, i, cgpu, isjson, group); + } if (isjson && io_open) io_close(io_data); @@ -2833,7 +2859,9 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m io_open = io_add(io_data, COMSTR JSON_DEVDETAILS); for (i = 0; i < total_devices; i++) { + mutex_lock(&devices_lock); cgpu = devices[i]; + mutex_unlock(&devices_lock); root = api_add_int(root, "DEVDETAILS", &i, false); root = api_add_string(root, "Name", cgpu->drv->name, false); @@ -2930,6 +2958,7 @@ static int itemstats(struct io_data *io_data, int i, char *id, struct cgminer_st static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group) { + struct cgpu_info *cgpu; bool io_open = false; struct api_data *extra; char id[20]; @@ -2942,7 +2971,9 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m i = 0; for (j = 0; j < total_devices; j++) { - struct cgpu_info *cgpu = devices[j]; + mutex_lock(&devices_lock); + cgpu = devices[j]; + mutex_unlock(&devices_lock); if (cgpu && cgpu->drv) { if (cgpu->drv->get_api_stats) @@ -3182,6 +3213,8 @@ static void usbstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may #ifdef HAVE_AN_FPGA static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group) { + struct cgpu_info *cgpu; + struct device_drv *drv; char buf[TMPBUFSIZ]; int numpga = numpgas(); @@ -3215,8 +3248,10 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe return; } - struct cgpu_info *cgpu = devices[dev]; - struct device_drv *drv = cgpu->drv; + mutex_lock(&devices_lock); + cgpu = devices[dev]; + mutex_unlock(&devices_lock); + drv = cgpu->drv; char *set = strchr(opt, ','); if (set) diff --git a/cgminer.c b/cgminer.c index 8abdcaf1..5981b7c5 100644 --- a/cgminer.c +++ b/cgminer.c @@ -157,7 +157,14 @@ static int input_thr_id; #endif int gpur_thr_id; static int api_thr_id; +#if defined(USE_MODMINER) || defined(USE_BITFORCE) +static int hotplug_thr_id; +#endif static int total_control_threads; +bool hotplug_mode; +static int new_devices; +static int new_threads; +static int start_devices; #ifdef HAVE_LIBUSB pthread_mutex_t cgusb_lock; @@ -173,6 +180,7 @@ static pthread_mutex_t sshare_lock; pthread_rwlock_t netacc_lock; pthread_mutex_t mining_thr_lock; +pthread_mutex_t devices_lock; static pthread_mutex_t lp_lock; static pthread_cond_t lp_cond; @@ -742,18 +750,24 @@ static void load_temp_cutoffs() if (val < 0 || val > 200) quit(1, "Invalid value passed to set temp cutoff"); + mutex_lock(&devices_lock); devices[device]->cutofftemp = val; + mutex_unlock(&devices_lock); } } else { + mutex_lock(&devices_lock); for (i = device; i < total_devices; ++i) { if (!devices[i]->cutofftemp) devices[i]->cutofftemp = opt_cutofftemp; } + mutex_unlock(&devices_lock); return; } if (device <= 1) { + mutex_lock(&devices_lock); for (i = device; i < total_devices; ++i) devices[i]->cutofftemp = val; + mutex_unlock(&devices_lock); } } @@ -1990,9 +2004,12 @@ static void curses_print_devstatus(int thr_id) char displayed_hashes[16], displayed_rolling[16]; uint64_t dh64, dr64; + if (opt_compact) + return; + cgpu = get_thr_cgpu(thr_id); - if (devcursor + cgpu->cgminer_id > LINES - 2 || opt_compact) + if (cgpu->cgminer_id >= start_devices || devcursor + cgpu->cgminer_id > LINES - 2) return; cgpu->utility = cgpu->accepted / total_secs * 60; @@ -2782,6 +2799,16 @@ static void __kill_work(void) applog(LOG_INFO, "Received kill message"); +#if defined(USE_MODMINER) || defined(USE_BITFORCE) + /* Best to get rid of it first so it doesn't + * try to create any new devices */ + if (!opt_scrypt) { + applog(LOG_DEBUG, "Killing off HotPlug thread"); + thr = &control_thr[hotplug_thr_id]; + thr_info_cancel(thr); + } +#endif + applog(LOG_DEBUG, "Killing off watchpool thread"); /* Kill the watchpool thread */ thr = &control_thr[watchpool_thr_id]; @@ -4015,10 +4042,14 @@ void zero_stats(void) zero_bestshare(); - mutex_lock(&hash_lock); for (i = 0; i < total_devices; ++i) { - struct cgpu_info *cgpu = devices[i]; + struct cgpu_info *cgpu; + + mutex_lock(&devices_lock); + cgpu = devices[i]; + mutex_unlock(&devices_lock); + mutex_lock(&hash_lock); cgpu->total_mhashes = 0; cgpu->accepted = 0; cgpu->rejected = 0; @@ -4029,8 +4060,8 @@ void zero_stats(void) cgpu->diff_accepted = 0; cgpu->diff_rejected = 0; cgpu->last_share_diff = 0; + mutex_unlock(&hash_lock); } - mutex_unlock(&hash_lock); } #ifdef HAVE_CURSES @@ -5936,12 +5967,17 @@ static void *watchdog_thread(void __maybe_unused *userdata) } for (i = 0; i < total_devices; ++i) { - struct cgpu_info *cgpu = devices[i]; - struct thr_info *thr = cgpu->thr[0]; + struct cgpu_info *cgpu; + struct thr_info *thr; enum dev_enable *denable; char dev_str[8]; int gpu; + mutex_lock(&devices_lock); + cgpu = devices[i]; + mutex_unlock(&devices_lock); + thr = cgpu->thr[0]; + if (cgpu->drv->get_stats) cgpu->drv->get_stats(cgpu); @@ -6104,8 +6140,13 @@ void print_summary(void) } applog(LOG_WARNING, "Summary of per device statistics:\n"); - for (i = 0; i < total_devices; ++i) - log_print_status(devices[i]); + for (i = 0; i < total_devices; ++i) { + struct cgpu_info *cgpu; + mutex_lock(&devices_lock); + cgpu = devices[i]; + mutex_unlock(&devices_lock); + log_print_status(cgpu); + } if (opt_shares) applog(LOG_WARNING, "Mined %d accepted shares of %d requested\n", total_accepted, opt_shares); @@ -6355,7 +6396,7 @@ void enable_curses(void) { } #endif -/* TODO: fix need a dummy CPU device_api even if no support for CPU mining */ +/* TODO: fix need a dummy CPU device_drv even if no support for CPU mining */ #ifndef WANT_CPUMINE struct device_drv cpu_drv; struct device_drv cpu_drv = { @@ -6386,11 +6427,18 @@ static int cgminer_id_count = 0; void enable_device(struct cgpu_info *cgpu) { cgpu->deven = DEV_ENABLED; + mutex_lock(&devices_lock); devices[cgpu->cgminer_id = cgminer_id_count++] = cgpu; - mining_threads += cgpu->threads; + mutex_unlock(&devices_lock); + if (hotplug_mode) { + new_threads += cgpu->threads; + adj_width(mining_threads + new_threads, &dev_width); + } else { + mining_threads += cgpu->threads; #ifdef HAVE_CURSES - adj_width(mining_threads, &dev_width); + adj_width(mining_threads, &dev_width); #endif + } #ifdef HAVE_OPENCL if (cgpu->drv->drv_id == DRIVER_OPENCL) { gpu_threads += cgpu->threads; @@ -6418,8 +6466,13 @@ bool add_cgpu(struct cgpu_info*cgpu) cgpu->device_id = d->lastid = 0; HASH_ADD_STR(devids, name, d); } - devices = realloc(devices, sizeof(struct cgpu_info *) * (total_devices + 2)); - devices[total_devices++] = cgpu; + mutex_lock(&devices_lock); + devices = realloc(devices, sizeof(struct cgpu_info *) * (total_devices + new_devices + 2)); + mutex_unlock(&devices_lock); + if (hotplug_mode) + devices[total_devices + new_devices++] = cgpu; + else + devices[total_devices++] = cgpu; return true; } @@ -6438,6 +6491,105 @@ struct device_drv *copy_drv(struct device_drv *drv) return copy; } +#if defined(USE_MODMINER) || defined(USE_BITFORCE) +static void hotplug_process() +{ + struct thr_info *thr; + int i, j; + + for (i = 0; i < new_devices; i++) { + struct cgpu_info *cgpu = devices[total_devices + i]; + enable_device(cgpu); + cgpu->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET; + cgpu->rolling = cgpu->total_mhashes = 0; + } + + mutex_lock(&mining_thr_lock); + mining_thr = realloc(mining_thr, sizeof(thr) * (mining_threads + new_threads + 1)); + mutex_unlock(&mining_thr_lock); + if (!mining_thr) + quit(1, "Failed to hotplug realloc mining_thr"); + for (i = 0; i < new_threads; i++) { + mining_thr[mining_threads + i] = calloc(1, sizeof(*thr)); + if (!mining_thr[mining_threads + i]) + quit(1, "Failed to hotplug calloc mining_thr[%d]", i); + } + + // Start threads + for (i = 0; i < new_devices; ++i) { + struct cgpu_info *cgpu = devices[total_devices]; + cgpu->thr = malloc(sizeof(*cgpu->thr) * (cgpu->threads+1)); + cgpu->thr[cgpu->threads] = NULL; + cgpu->status = LIFE_INIT; + + for (j = 0; j < cgpu->threads; ++j) { + mutex_lock(&mining_thr_lock); + thr = mining_thr[mining_threads]; + mutex_unlock(&mining_thr_lock); + thr->id = mining_threads; + thr->cgpu = cgpu; + thr->device_thread = j; + + thr->q = tq_new(); + if (!thr->q) + quit(1, "tq_new hotplug failed in starting %s%d mining thread (#%d)", cgpu->drv->name, cgpu->device_id, total_devices); + + /* Enable threads for devices set not to mine but disable + * their queue in case we wish to enable them later */ + if (cgpu->deven != DEV_DISABLED) { + applog(LOG_DEBUG, "Pushing hotplug ping to thread %d", thr->id); + tq_push(thr->q, &ping); + } + + if (cgpu->drv->thread_prepare && !cgpu->drv->thread_prepare(thr)) + continue; + + thread_reportout(thr); + + if (unlikely(thr_info_create(thr, NULL, miner_thread, thr))) + quit(1, "hotplug thread %d create failed", thr->id); + + cgpu->thr[j] = thr; + + mining_threads++; + } + total_devices++; + applog(LOG_WARNING, "Hotplug: %s added %s %i", cgpu->drv->dname, cgpu->drv->name, cgpu->device_id); + } +} + +static void *hotplug_thread(void __maybe_unused *userdata) +{ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + RenameThread("hotplug"); + + hotplug_mode = true; + + while (0x2a) { + sleep(5); + +// Version 0.1 just add the devices on - worry about using nodev later + + new_devices = 0; + new_threads = 0; + +#ifdef USE_BITFORCE + bitforce_drv.drv_detect(); +#endif + +#ifdef USE_MODMINER + modminer_drv.drv_detect(); +#endif + + if (new_devices) + hotplug_process(); + } + + return NULL; +} +#endif + int main(int argc, char *argv[]) { bool pools_active = false; @@ -6479,6 +6631,7 @@ int main(int argc, char *argv[]) rwlock_init(&blk_lock); rwlock_init(&netacc_lock); mutex_init(&mining_thr_lock); + mutex_init(&devices_lock); mutex_init(&lp_lock); if (unlikely(pthread_cond_init(&lp_cond, NULL))) @@ -6714,6 +6867,8 @@ int main(int argc, char *argv[]) if (!total_devices) quit(1, "All devices disabled, cannot mine!"); + start_devices = total_devices; + load_temp_cutoffs(); for (i = 0; i < total_devices; ++i) @@ -6772,7 +6927,7 @@ int main(int argc, char *argv[]) quit(1, "Failed to calloc mining_thr[%d]", i); } - total_control_threads = 7; + total_control_threads = 8; control_thr = calloc(total_control_threads, sizeof(*thr)); if (!control_thr) quit(1, "Failed to calloc control_thr"); @@ -6947,11 +7102,21 @@ begin_bench: if (thr_info_create(thr, NULL, api_thread, thr)) quit(1, "API thread create failed"); +#if defined(USE_MODMINER) || defined(USE_BITFORCE) + if (!opt_scrypt) { + hotplug_thr_id = 6; + thr = &control_thr[hotplug_thr_id]; + if (thr_info_create(thr, NULL, hotplug_thread, thr)) + quit(1, "hotplug thread create failed"); + pthread_detach(thr->pth); + } +#endif + #ifdef HAVE_CURSES /* Create curses input thread for keyboard input. Create this last so * that we know all threads are created since this can call kill_work - * to try and shut down ll previous threads. */ - input_thr_id = 6; + * to try and shut down all previous threads. */ + input_thr_id = 7; thr = &control_thr[input_thr_id]; if (thr_info_create(thr, NULL, input_thread, thr)) quit(1, "input thread create failed"); @@ -6959,8 +7124,8 @@ begin_bench: #endif /* Just to be sure */ - if (total_control_threads != 7) - quit(1, "incorrect total_control_threads (%d) should be 7", total_control_threads); + if (total_control_threads != 8) + quit(1, "incorrect total_control_threads (%d) should be 8", total_control_threads); /* Once everything is set up, main() becomes the getwork scheduler */ while (42) { diff --git a/driver-ztex.c b/driver-ztex.c index 4a61a5c5..add381b9 100644 --- a/driver-ztex.c +++ b/driver-ztex.c @@ -390,7 +390,9 @@ static void ztex_shutdown(struct thr_info *thr) static void ztex_disable(struct thr_info *thr) { applog(LOG_ERR, "%s: Disabling!", thr->cgpu->device_ztex->repr); + mutex_lock(&devices_lock); devices[thr->cgpu->device_id]->deven = DEV_DISABLED; + mutex_unlock(&devices_lock); ztex_shutdown(thr); } diff --git a/miner.h b/miner.h index 0902228a..5b5af431 100644 --- a/miner.h +++ b/miner.h @@ -738,6 +738,7 @@ extern pthread_mutex_t hash_lock; extern pthread_mutex_t console_lock; extern pthread_mutex_t ch_lock; extern pthread_mutex_t mining_thr_lock; +extern pthread_mutex_t devices_lock; extern pthread_mutex_t restart_lock; extern pthread_cond_t restart_cond; @@ -778,6 +779,7 @@ extern void add_pool_details(struct pool *pool, bool live, char *url, char *user #define _MAX_INTENSITY_STR "14" #endif +extern bool hotplug_mode; extern struct list_head scan_devices; extern int nDevs; extern int opt_n_threads; diff --git a/usbutils.c b/usbutils.c index ba4db390..6498a56b 100644 --- a/usbutils.c +++ b/usbutils.c @@ -624,7 +624,9 @@ static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint case WAIT_ABANDONED: // Am I using it already? for (i = 0; i < total_devices; i++) { + mutex_lock(&devices_lock); cgpu = devices[i]; + mutex_unlock(&devices_lock); if (cgpu->usbinfo.bus_number == bus_number && cgpu->usbinfo.device_address == device_address && cgpu->usbinfo.nodev == false) { @@ -642,9 +644,10 @@ static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint } return true; case WAIT_TIMEOUT: - applog(LOG_WARNING, - "MTX: %s USB failed to get '%s' - device in use", - drv->dname, name); + if (!hotplug_mode) + applog(LOG_WARNING, + "MTX: %s USB failed to get '%s' - device in use", + drv->dname, name); goto fail; case WAIT_FAILED: applog(LOG_ERR, @@ -726,9 +729,10 @@ fail: if (semop(sem, sops, 2)) { if (errno == EAGAIN) { - applog(LOG_WARNING, - "SEM: %s USB failed to get (%d) '%s' - device in use", - drv->dname, sem, name); + if (!hotplug_mode) + applog(LOG_WARNING, + "SEM: %s USB failed to get (%d) '%s' - device in use", + drv->dname, sem, name); } else { applog(LOG_DEBUG, "SEM: %s USB failed to get (%d) '%s' err (%d) %s", @@ -849,6 +853,7 @@ void usb_uninit(struct cgpu_info *cgpu) void release_cgpu(struct cgpu_info *cgpu) { struct cg_usb_device *cgusb = cgpu->usbdev; + struct cgpu_info *lookcgpu; int i; cgpu->usbinfo.nodev = true; @@ -857,14 +862,18 @@ void release_cgpu(struct cgpu_info *cgpu) // Any devices sharing the same USB device should be marked also // Currently only MMQ shares a USB device - for (i = 0; i < total_devices; i++) - if (devices[i] != cgpu && devices[i]->usbdev == cgusb) { - devices[i]->usbinfo.nodev = true; - devices[i]->usbinfo.nodev_count++; - memcpy(&(devices[i]->usbinfo.last_nodev), + for (i = 0; i < total_devices; i++) { + mutex_lock(&devices_lock); + lookcgpu = devices[i]; + mutex_unlock(&devices_lock); + if (lookcgpu != cgpu && lookcgpu->usbdev == cgusb) { + lookcgpu->usbinfo.nodev = true; + lookcgpu->usbinfo.nodev_count++; + memcpy(&(lookcgpu->usbinfo.last_nodev), &(cgpu->usbinfo.last_nodev), sizeof(struct timeval)); - devices[i]->usbdev = NULL; + lookcgpu->usbdev = NULL; } + } usb_uninit(cgpu); From 1c69417def7df49b587559c674f5375ffb6460cc Mon Sep 17 00:00:00 2001 From: Kano Date: Sun, 3 Feb 2013 14:02:31 +1100 Subject: [PATCH 52/87] usbutils - avoid free cgusb twice --- usbutils.c | 6 +++++- usbutils.h | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/usbutils.c b/usbutils.c index 6498a56b..8d4a0957 100644 --- a/usbutils.c +++ b/usbutils.c @@ -845,12 +845,16 @@ static struct cg_usb_device *free_cgusb(struct cg_usb_device *cgusb) void usb_uninit(struct cgpu_info *cgpu) { + // May have happened already during a failed initialisation + // if release_cgpu() was called due to a USB NODEV(err) + if (!cgpu->usbdev) + return; libusb_release_interface(cgpu->usbdev->handle, cgpu->usbdev->found->interface); libusb_close(cgpu->usbdev->handle); cgpu->usbdev = free_cgusb(cgpu->usbdev); } -void release_cgpu(struct cgpu_info *cgpu) +static void release_cgpu(struct cgpu_info *cgpu) { struct cg_usb_device *cgusb = cgpu->usbdev; struct cgpu_info *lookcgpu; diff --git a/usbutils.h b/usbutils.h index ac6ce0cd..1ec19360 100644 --- a/usbutils.h +++ b/usbutils.h @@ -129,7 +129,6 @@ struct device_drv; struct cgpu_info; void usb_uninit(struct cgpu_info *cgpu); -void release_cgpu(struct cgpu_info *cgpu); bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found); void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *)); struct api_data *api_usb_stats(int *count); From bc5755233c1b1ecd22f9b7237dbd528462382f56 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 8 Feb 2013 02:12:09 +1100 Subject: [PATCH 53/87] call a separate get_devices() with locking, as required --- api.c | 49 +++++++++++++++++-------------------------------- cgminer.c | 31 +++++++++++++++---------------- driver-ztex.c | 7 ++++--- miner.h | 1 + usbutils.c | 8 ++------ 5 files changed, 39 insertions(+), 57 deletions(-) diff --git a/api.c b/api.c index 7432637a..776e735d 100644 --- a/api.c +++ b/api.c @@ -1194,13 +1194,17 @@ static int pgadevice(int pgaid) if (devices[i]->drv->drv_id == DRIVER_MODMINER) count++; #endif - if (count == (pgaid + 1)) { - mutex_unlock(&devices_lock); - return i; - } + if (count == (pgaid + 1)) + goto foundit; } + mutex_unlock(&devices_lock); return -1; + +foundit: + + mutex_unlock(&devices_lock); + return i; } #endif @@ -1533,14 +1537,9 @@ static void pgastatus(struct io_data *io_data, int pga, bool isjson, bool precom if (dev < 0) // Should never happen return; - struct cgpu_info *cgpu; + struct cgpu_info *cgpu = get_devices(dev); double frequency = 0; - float temp; - - mutex_lock(&devices_lock); - cgpu = devices[dev]; - mutex_unlock(&devices_lock); - temp = cgpu->temp; + float temp = cgpu->temp; #ifdef USE_ZTEX if (cgpu->drv->drv_id == DRIVER_ZTEX && cgpu->device_ztex) @@ -1787,9 +1786,7 @@ static void pgaenable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char return; } - mutex_lock(&devices_lock); - cgpu = devices[dev]; - mutex_unlock(&devices_lock); + cgpu = get_devices(dev); applog(LOG_DEBUG, "API: request to pgaenable pgaid %d device %d %s%u", id, dev, cgpu->drv->name, cgpu->device_id); @@ -1854,9 +1851,7 @@ static void pgadisable(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha return; } - mutex_lock(&devices_lock); - cgpu = devices[dev]; - mutex_unlock(&devices_lock); + cgpu = get_devices(dev); applog(LOG_DEBUG, "API: request to pgadisable pgaid %d device %d %s%u", id, dev, cgpu->drv->name, cgpu->device_id); @@ -1900,9 +1895,7 @@ static void pgaidentify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, ch return; } - mutex_lock(&devices_lock); - cgpu = devices[dev]; - mutex_unlock(&devices_lock); + cgpu = get_devices(dev); drv = cgpu->drv; if (!drv->identify_device) @@ -2830,9 +2823,7 @@ static void notify(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe io_open = io_add(io_data, COMSTR JSON_NOTIFY); for (i = 0; i < total_devices; i++) { - mutex_lock(&devices_lock); - cgpu = devices[i]; - mutex_unlock(&devices_lock); + cgpu = get_devices(i); notifystatus(io_data, i, cgpu, isjson, group); } @@ -2859,9 +2850,7 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m io_open = io_add(io_data, COMSTR JSON_DEVDETAILS); for (i = 0; i < total_devices; i++) { - mutex_lock(&devices_lock); - cgpu = devices[i]; - mutex_unlock(&devices_lock); + cgpu = get_devices(i); root = api_add_int(root, "DEVDETAILS", &i, false); root = api_add_string(root, "Name", cgpu->drv->name, false); @@ -2971,9 +2960,7 @@ static void minerstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m i = 0; for (j = 0; j < total_devices; j++) { - mutex_lock(&devices_lock); - cgpu = devices[j]; - mutex_unlock(&devices_lock); + cgpu = get_devices(j); if (cgpu && cgpu->drv) { if (cgpu->drv->get_api_stats) @@ -3248,9 +3235,7 @@ static void pgaset(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe return; } - mutex_lock(&devices_lock); - cgpu = devices[dev]; - mutex_unlock(&devices_lock); + cgpu = get_devices(dev); drv = cgpu->drv; char *set = strchr(opt, ','); diff --git a/cgminer.c b/cgminer.c index 5981b7c5..33d4341d 100644 --- a/cgminer.c +++ b/cgminer.c @@ -390,6 +390,16 @@ static struct cgpu_info *get_thr_cgpu(int thr_id) return thr->cgpu; } +struct cgpu_info *get_devices(int id) +{ + struct cgpu_info *cgpu; + + mutex_lock(&devices_lock); + cgpu = devices[id]; + mutex_unlock(&devices_lock); + return cgpu; +} + static void sharelog(const char*disposition, const struct work*work) { char *target, *hash, *data; @@ -4043,11 +4053,7 @@ void zero_stats(void) zero_bestshare(); for (i = 0; i < total_devices; ++i) { - struct cgpu_info *cgpu; - - mutex_lock(&devices_lock); - cgpu = devices[i]; - mutex_unlock(&devices_lock); + struct cgpu_info *cgpu = get_devices(i); mutex_lock(&hash_lock); cgpu->total_mhashes = 0; @@ -5967,17 +5973,12 @@ static void *watchdog_thread(void __maybe_unused *userdata) } for (i = 0; i < total_devices; ++i) { - struct cgpu_info *cgpu; - struct thr_info *thr; + struct cgpu_info *cgpu = get_devices(i); + struct thr_info *thr = cgpu->thr[0]; enum dev_enable *denable; char dev_str[8]; int gpu; - mutex_lock(&devices_lock); - cgpu = devices[i]; - mutex_unlock(&devices_lock); - thr = cgpu->thr[0]; - if (cgpu->drv->get_stats) cgpu->drv->get_stats(cgpu); @@ -6141,10 +6142,8 @@ void print_summary(void) applog(LOG_WARNING, "Summary of per device statistics:\n"); for (i = 0; i < total_devices; ++i) { - struct cgpu_info *cgpu; - mutex_lock(&devices_lock); - cgpu = devices[i]; - mutex_unlock(&devices_lock); + struct cgpu_info *cgpu = get_devices(i); + log_print_status(cgpu); } diff --git a/driver-ztex.c b/driver-ztex.c index add381b9..27b8c26b 100644 --- a/driver-ztex.c +++ b/driver-ztex.c @@ -389,10 +389,11 @@ static void ztex_shutdown(struct thr_info *thr) static void ztex_disable(struct thr_info *thr) { + struct cgpu_info *cgpu; + applog(LOG_ERR, "%s: Disabling!", thr->cgpu->device_ztex->repr); - mutex_lock(&devices_lock); - devices[thr->cgpu->device_id]->deven = DEV_DISABLED; - mutex_unlock(&devices_lock); + cgpu = get_devices(thr->cgpu->device_id); + cgpu->deven = DEV_DISABLED; ztex_shutdown(thr); } diff --git a/miner.h b/miner.h index 5b5af431..3c4f89f5 100644 --- a/miner.h +++ b/miner.h @@ -1110,6 +1110,7 @@ extern void free_work(struct work *work); extern void __copy_work(struct work *work, struct work *base_work); extern struct work *copy_work(struct work *base_work); extern struct thr_info *get_thread(int thr_id); +extern struct cgpu_info *get_devices(int id); enum api_data_type { API_ESCAPE, diff --git a/usbutils.c b/usbutils.c index 8d4a0957..88edb937 100644 --- a/usbutils.c +++ b/usbutils.c @@ -624,9 +624,7 @@ static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint case WAIT_ABANDONED: // Am I using it already? for (i = 0; i < total_devices; i++) { - mutex_lock(&devices_lock); - cgpu = devices[i]; - mutex_unlock(&devices_lock); + cgpu = get_devices(i); if (cgpu->usbinfo.bus_number == bus_number && cgpu->usbinfo.device_address == device_address && cgpu->usbinfo.nodev == false) { @@ -867,9 +865,7 @@ static void release_cgpu(struct cgpu_info *cgpu) // Any devices sharing the same USB device should be marked also // Currently only MMQ shares a USB device for (i = 0; i < total_devices; i++) { - mutex_lock(&devices_lock); - lookcgpu = devices[i]; - mutex_unlock(&devices_lock); + lookcgpu = get_devices(i); if (lookcgpu != cgpu && lookcgpu->usbdev == cgusb) { lookcgpu->usbinfo.nodev = true; lookcgpu->usbinfo.nodev_count++; From b9c19a9353d054f0c037e1f3ee963af92cec4f96 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 8 Feb 2013 02:17:28 +1100 Subject: [PATCH 54/87] remove empty #ifdef --- usbutils.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/usbutils.c b/usbutils.c index 88edb937..f0dd7c77 100644 --- a/usbutils.c +++ b/usbutils.c @@ -579,8 +579,7 @@ static void cgusb_check_init() mutex_unlock(&cgusb_lock); } -#ifdef WIN32 -#else +#ifndef WIN32 #include #include #include From 6fb32f7b5df7df2269d308b74d51629b899e1ec8 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 8 Feb 2013 02:32:27 +1100 Subject: [PATCH 55/87] convert sleep(const) to nmsleep() --- adl.c | 2 +- api.c | 4 ++-- cgminer.c | 22 +++++++++++----------- driver-bitforce.c | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/adl.c b/adl.c index d5e83a90..3ff7e02a 100644 --- a/adl.c +++ b/adl.c @@ -1392,7 +1392,7 @@ updated: clear_logwin(); return; } - sleep(1); + nmsleep(1000); goto updated; } #endif diff --git a/api.c b/api.c index 776e735d..6d77c600 100644 --- a/api.c +++ b/api.c @@ -3792,7 +3792,7 @@ void api(int api_thr_id) /* This should be done before curl in needed * to ensure curl has already called WSAStartup() in windows */ - sleep(opt_log_interval); + nmsleep(opt_log_interval*1000); sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == INVSOCK) { @@ -3838,7 +3838,7 @@ void api(int api_thr_id) break; else { applog(LOG_WARNING, "API bind to port %d failed - trying again in 30sec", port); - sleep(30); + nmsleep(30000); } } else bound = 1; diff --git a/cgminer.c b/cgminer.c index 33d4341d..7b17950c 100644 --- a/cgminer.c +++ b/cgminer.c @@ -2502,7 +2502,7 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) pool->remotefail_occasions++; applog(LOG_WARNING, "Pool %d communication failure, caching submissions", pool->pool_no); } - sleep(5); + nmsleep(5000); goto out; } else if (pool_tclear(pool, &pool->submit_fail)) applog(LOG_WARNING, "Pool %d communication resumed, submitting work", pool->pool_no); @@ -2837,7 +2837,7 @@ static void __kill_work(void) thr->pause = true; } - sleep(1); + nmsleep(1000); applog(LOG_DEBUG, "Killing off mining threads"); /* Kill the mining threads*/ @@ -4780,7 +4780,7 @@ static void *stratum_thread(void *userdata) while (!initiate_stratum(pool) || !auth_stratum(pool)) { if (pool->removed) goto out; - sleep(30); + nmsleep(30000); } } } @@ -4818,7 +4818,7 @@ static void *stratum_thread(void *userdata) while (!initiate_stratum(pool) || !auth_stratum(pool)) { if (pool->removed) goto out; - sleep(30); + nmsleep(30000); } stratum_resumed(pool); continue; @@ -5703,7 +5703,7 @@ retry_pool: if (!pool) { applog(LOG_WARNING, "No suitable long-poll found for %s", cp->rpc_url); while (!pool) { - sleep(60); + nmsleep(60000); pool = select_longpoll_pool(cp); } } @@ -5778,7 +5778,7 @@ retry_pool: continue; if (failures == 1) applog(LOG_WARNING, "longpoll failed for %s, retrying every 30s", lp_url); - sleep(30); + nmsleep(30000); } if (pool != cp) { @@ -5883,7 +5883,7 @@ static void *watchpool_thread(void __maybe_unused *userdata) switch_pools(NULL); } - sleep(30); + nmsleep(30000); } return NULL; @@ -6566,7 +6566,7 @@ static void *hotplug_thread(void __maybe_unused *userdata) hotplug_mode = true; while (0x2a) { - sleep(5); + nmsleep(5000); // Version 0.1 just add the devices on - worry about using nodev later @@ -7170,7 +7170,7 @@ retry: while (!pool->stratum_active || !pool->stratum_notify) { struct pool *altpool = select_pool(true); - sleep(5); + nmsleep(5000); if (altpool != pool) { pool = altpool; goto retry; @@ -7186,7 +7186,7 @@ retry: while (pool->idle) { struct pool *altpool = select_pool(true); - sleep(5); + nmsleep(5000); if (altpool != pool) { pool = altpool; goto retry; @@ -7220,7 +7220,7 @@ retry: * requests but is up as we'll keep hammering it */ if (++pool->seq_getfails > mining_threads + opt_queue) pool_died(pool); - sleep(5); + nmsleep(5000); push_curl_entry(ce, pool); pool = select_pool(!opt_fail_only); goto retry; diff --git a/driver-bitforce.c b/driver-bitforce.c index de1a8e6d..b7f238b9 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -343,7 +343,7 @@ static void bitforce_flash_led(struct cgpu_info *bitforce) } else { /* However, this stops anything else getting a reply * So best to delay any other access to the BFL */ - sleep(4); + nmsleep(4000); } /* Once we've tried - don't do it until told to again */ From 530e3b017273868925368a0bcec51aecfa64f379 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 8 Feb 2013 02:38:37 +1100 Subject: [PATCH 56/87] hotplug use get_thread() where appropriate --- cgminer.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cgminer.c b/cgminer.c index 7b17950c..ad0071e5 100644 --- a/cgminer.c +++ b/cgminer.c @@ -6522,9 +6522,7 @@ static void hotplug_process() cgpu->status = LIFE_INIT; for (j = 0; j < cgpu->threads; ++j) { - mutex_lock(&mining_thr_lock); - thr = mining_thr[mining_threads]; - mutex_unlock(&mining_thr_lock); + thr = get_thread(mining_threads); thr->id = mining_threads; thr->cgpu = cgpu; thr->device_thread = j; From 5d986852b2a6a11d3d37cb7f7ef09432d9443c25 Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 8 Feb 2013 10:01:22 +1100 Subject: [PATCH 57/87] add 'count' to cumstomsummarypage 'calc' --- API-README | 5 ++++- miner.php | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/API-README b/API-README index 5fd2dda4..c1c4ca44 100644 --- a/API-README +++ b/API-README @@ -1357,9 +1357,12 @@ You can only see fields listed in 'group' and 'calc' A 'calc' is formatted as: 'Field' => 'function' The current list of operations available for 'calc' are: -'sum', 'avg', 'min', 'max', 'lo', 'hi', 'any' +'sum', 'avg', 'min', 'max', 'lo', 'hi', 'coount', 'any' The first 4 are as expected - the numerical sum, average, minimum or maximum 'lo' is the first string of the list, sorted ignoring case 'hi' is the last string of the list, sorted ignoring case +'count' is the number of rows in the section specified in the calc e.g. + ('DEVS.Name' => 'count') would be the number of DEVS selected in the 'where' + of course any valid 'DEVS.Xyz' would give the same 'count' value 'any' is effectively random: the field value in the first row of the grouped data An unrecognised 'function' uses 'any' diff --git a/miner.php b/miner.php index 396121b6..dd9ff399 100644 --- a/miner.php +++ b/miner.php @@ -2076,6 +2076,8 @@ function docalc($func, $data) if (strcasecmp($val, $ans) > 0) $ans = $val; return $ans; + case 'count': + return count($data); case 'any': default: return $data[0]; From f2380eab4c29b4e1438fc6ac877df355269f4e52 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 15:10:10 +1100 Subject: [PATCH 58/87] Fill drivers missing reinit_device with a noop version. --- cgminer.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index dfa22abc..17e3df82 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5762,8 +5762,7 @@ out: void reinit_device(struct cgpu_info *cgpu) { - if (cgpu->drv->reinit_device) - cgpu->drv->reinit_device(cgpu); + cgpu->drv->reinit_device(cgpu); } static struct timeval rotate_tv; @@ -6378,6 +6377,19 @@ extern struct device_drv ztex_drv; static int cgminer_id_count = 0; +void noop_reinit_device(struct cgpu_info __maybe_unused *cgpu) +{ +} + +/* Fill missing driver api functions with noops */ +void fill_device_api(struct cgpu_info *cgpu) +{ + struct device_drv *drv = cgpu->drv; + + if (!drv->reinit_device) + drv->reinit_device = &noop_reinit_device; +} + void enable_device(struct cgpu_info *cgpu) { cgpu->deven = DEV_ENABLED; From b3d9477eb7b78fac4c91d30f887e1eebf1181a45 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 18:18:52 +1100 Subject: [PATCH 59/87] Provide a blank get_statline_before function for drivers that don't have one. --- cgminer.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/cgminer.c b/cgminer.c index 17e3df82..a325a64a 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1900,10 +1900,7 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) suffix_string(dr64, displayed_rolling, 4); sprintf(buf, "%s%d ", cgpu->drv->name, cgpu->device_id); - if (cgpu->drv->get_statline_before) - cgpu->drv->get_statline_before(buf, cgpu); - else - tailsprintf(buf, " | "); + cgpu->drv->get_statline_before(buf, cgpu); tailsprintf(buf, "(%ds):%s (avg):%sh/s | A:%d R:%d HW:%d U:%.1f/m", opt_log_interval, displayed_rolling, @@ -1999,13 +1996,9 @@ static void curses_print_devstatus(int thr_id) wmove(statuswin,devcursor + cgpu->cgminer_id, 0); wprintw(statuswin, " %s %*d: ", cgpu->drv->name, dev_width, cgpu->device_id); - if (cgpu->drv->get_statline_before) { - logline[0] = '\0'; - cgpu->drv->get_statline_before(logline, cgpu); - wprintw(statuswin, "%s", logline); - } - else - wprintw(statuswin, " | "); + logline[0] = '\0'; + cgpu->drv->get_statline_before(logline, cgpu); + wprintw(statuswin, "%s", logline); dh64 = (double)cgpu->total_mhashes / total_secs * 1000000ull; dr64 = (double)cgpu->rolling * 1000000ull; @@ -6381,6 +6374,11 @@ void noop_reinit_device(struct cgpu_info __maybe_unused *cgpu) { } +void blank_get_statline_before(char *buf, struct cgpu_info __maybe_unused *cgpu) +{ + tailsprintf(buf, " | "); +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6388,6 +6386,8 @@ void fill_device_api(struct cgpu_info *cgpu) if (!drv->reinit_device) drv->reinit_device = &noop_reinit_device; + if (!drv->get_statline_before) + drv->get_statline_before = &blank_get_statline_before; } void enable_device(struct cgpu_info *cgpu) @@ -6403,6 +6403,7 @@ void enable_device(struct cgpu_info *cgpu) gpu_threads += cgpu->threads; } #endif + fill_device_api(cgpu); } struct _cgpu_devid_counter { From de48ccca0e9b8a1adad53d53bd0ba063b57a5734 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:22:13 +1100 Subject: [PATCH 60/87] Provide a blank get_statline for drivers that don't support it. --- cgminer.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/cgminer.c b/cgminer.c index a325a64a..bfc4397f 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1909,8 +1909,7 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) cgpu->rejected, cgpu->hw_errors, cgpu->utility); - if (cgpu->drv->get_statline) - cgpu->drv->get_statline(buf, cgpu); + cgpu->drv->get_statline(buf, cgpu); } static void text_print_status(int thr_id) @@ -2027,11 +2026,9 @@ static void curses_print_devstatus(int thr_id) hwwidth, cgpu->hw_errors, uwidth + 3, cgpu->utility); - if (cgpu->drv->get_statline) { - logline[0] = '\0'; - cgpu->drv->get_statline(logline, cgpu); - wprintw(statuswin, "%s", logline); - } + logline[0] = '\0'; + cgpu->drv->get_statline(logline, cgpu); + wprintw(statuswin, "%s", logline); wclrtoeol(statuswin); } @@ -6370,15 +6367,19 @@ extern struct device_drv ztex_drv; static int cgminer_id_count = 0; -void noop_reinit_device(struct cgpu_info __maybe_unused *cgpu) +static void noop_reinit_device(struct cgpu_info __maybe_unused *cgpu) { } -void blank_get_statline_before(char *buf, struct cgpu_info __maybe_unused *cgpu) +static void blank_get_statline_before(char *buf, struct cgpu_info __maybe_unused *cgpu) { tailsprintf(buf, " | "); } +static void noop_get_statline(char __maybe_unused *buf, struct cgpu_info __maybe_unused *cgpu) +{ +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6388,6 +6389,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->reinit_device = &noop_reinit_device; if (!drv->get_statline_before) drv->get_statline_before = &blank_get_statline_before; + if (!drv->get_statline) + drv->get_statline = &noop_get_statline; } void enable_device(struct cgpu_info *cgpu) From 2c3c9e5b55e130ed374ddc914068457aa07997d9 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:25:24 +1100 Subject: [PATCH 61/87] Provide a noop get_stats function for drivers that don't support it. --- cgminer.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index bfc4397f..ef7efa6c 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5926,8 +5926,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) char dev_str[8]; int gpu; - if (cgpu->drv->get_stats) - cgpu->drv->get_stats(cgpu); + cgpu->drv->get_stats(cgpu); gpu = cgpu->device_id; denable = &cgpu->deven; @@ -6380,6 +6379,11 @@ static void noop_get_statline(char __maybe_unused *buf, struct cgpu_info __maybe { } +static bool noop_get_stats(struct cgpu_info __maybe_unused *cgpu) +{ + return true; +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6391,6 +6395,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->get_statline_before = &blank_get_statline_before; if (!drv->get_statline) drv->get_statline = &noop_get_statline; + if (!drv->get_stats) + drv->get_stats = &noop_get_stats; } void enable_device(struct cgpu_info *cgpu) From 5d581cb5d7234328eafd6eb52ad98f98f18d9e78 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:27:57 +1100 Subject: [PATCH 62/87] Use blank_get_statline_before for GPU devices that don't support adl monitoring. --- cgminer.c | 2 +- driver-opencl.c | 3 ++- miner.h | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index ef7efa6c..acf3880c 100644 --- a/cgminer.c +++ b/cgminer.c @@ -6370,7 +6370,7 @@ static void noop_reinit_device(struct cgpu_info __maybe_unused *cgpu) { } -static void blank_get_statline_before(char *buf, struct cgpu_info __maybe_unused *cgpu) +void blank_get_statline_before(char *buf, struct cgpu_info __maybe_unused *cgpu) { tailsprintf(buf, " | "); } diff --git a/driver-opencl.c b/driver-opencl.c index 9e9e4015..8580b221 100644 --- a/driver-opencl.c +++ b/driver-opencl.c @@ -1287,7 +1287,8 @@ static void get_opencl_statline_before(char *buf, struct cgpu_info *gpu) else tailsprintf(buf, " "); tailsprintf(buf, "| "); - } + } else + gpu->drv->get_statline_before = &blank_get_statline_before; } #endif diff --git a/miner.h b/miner.h index 0902228a..58d125fd 100644 --- a/miner.h +++ b/miner.h @@ -268,6 +268,8 @@ struct gpu_adl { }; #endif +extern void blank_get_statline_before(char *buf, struct cgpu_info __maybe_unused *cgpu); + struct api_data; struct thr_info; struct work; From 5b22f092d9358cf4c4cac48957af7be0fff2b7de Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:36:38 +1100 Subject: [PATCH 63/87] Provide a noop thread_prepare function for drivers that don't use thread_prepare. --- cgminer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index acf3880c..4b33a435 100644 --- a/cgminer.c +++ b/cgminer.c @@ -6384,6 +6384,11 @@ static bool noop_get_stats(struct cgpu_info __maybe_unused *cgpu) return true; } +static bool noop_thread_prepare(struct thr_info __maybe_unused *thr) +{ + return true; +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6397,6 +6402,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->get_statline = &noop_get_statline; if (!drv->get_stats) drv->get_stats = &noop_get_stats; + if (!drv->thread_prepare) + drv->thread_prepare = &noop_thread_prepare; } void enable_device(struct cgpu_info *cgpu) @@ -6905,7 +6912,7 @@ begin_bench: tq_push(thr->q, &ping); } - if (cgpu->drv->thread_prepare && !cgpu->drv->thread_prepare(thr)) + if (!cgpu->drv->thread_prepare(thr)) continue; thread_reportout(thr); From 8e12a05b477237092fc4119682df247eb7550d0d Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:48:11 +1100 Subject: [PATCH 64/87] Provide a noop can_limit_work for devices that don't support it. --- cgminer.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/cgminer.c b/cgminer.c index 4b33a435..64434279 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5372,7 +5372,7 @@ void *miner_thread(void *userdata) const long cycle = opt_log_interval / 5 ? : 1; struct timeval tv_start, tv_end, tv_workstart, tv_lastupdate; struct timeval diff, sdiff, wdiff = {0, 0}; - uint32_t max_nonce = drv->can_limit_work ? drv->can_limit_work(mythr) : 0xffffffff; + uint32_t max_nonce = drv->can_limit_work(mythr); int64_t hashes_done = 0; int64_t hashes; struct work *work; @@ -5478,7 +5478,7 @@ void *miner_thread(void *userdata) if (unlikely((long)sdiff.tv_sec < cycle)) { int mult; - if (likely(!drv->can_limit_work || max_nonce == 0xffffffff)) + if (likely(max_nonce == 0xffffffff)) continue; mult = 1000000 / ((sdiff.tv_usec + 0x400) / 0x400) + 0x10; @@ -5487,9 +5487,9 @@ void *miner_thread(void *userdata) max_nonce = 0xffffffff; else max_nonce = (max_nonce * mult) / 0x400; - } else if (unlikely(sdiff.tv_sec > cycle) && drv->can_limit_work) + } else if (unlikely(sdiff.tv_sec > cycle)) max_nonce = max_nonce * cycle / sdiff.tv_sec; - else if (unlikely(sdiff.tv_usec > 100000) && drv->can_limit_work) + else if (unlikely(sdiff.tv_usec > 100000)) max_nonce = max_nonce * 0x400 / (((cycle * 1000000) + sdiff.tv_usec) / (cycle * 1000000 / 0x400)); timersub(&tv_end, &tv_lastupdate, &diff); @@ -6389,6 +6389,11 @@ static bool noop_thread_prepare(struct thr_info __maybe_unused *thr) return true; } +static uint64_t noop_can_limit_work(struct thr_info __maybe_unused *thr) +{ + return 0xffffffff; +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6404,6 +6409,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->get_stats = &noop_get_stats; if (!drv->thread_prepare) drv->thread_prepare = &noop_thread_prepare; + if (!drv->can_limit_work) + drv->can_limit_work = &noop_can_limit_work; } void enable_device(struct cgpu_info *cgpu) From b9f5b48c08bd692182056741cfe3df55a77ac4b8 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:50:07 +1100 Subject: [PATCH 65/87] Provide a noop thread_init for drivers that don't support it. --- cgminer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index 64434279..41bbcab3 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5386,7 +5386,7 @@ void *miner_thread(void *userdata) gettimeofday(&getwork_start, NULL); - if (drv->thread_init && !drv->thread_init(mythr)) { + if (!drv->thread_init(mythr)) { dev_error(cgpu, REASON_THREAD_FAIL_INIT); goto out; } @@ -6394,6 +6394,11 @@ static uint64_t noop_can_limit_work(struct thr_info __maybe_unused *thr) return 0xffffffff; } +static bool noop_thread_init(struct thr_info __maybe_unused *thr) +{ + return true; +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6411,6 +6416,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->thread_prepare = &noop_thread_prepare; if (!drv->can_limit_work) drv->can_limit_work = &noop_can_limit_work; + if (!drv->thread_init) + drv->thread_init = &noop_thread_init; } void enable_device(struct cgpu_info *cgpu) From 210537198c56a372064638b1200d4a2be0cfebbc Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:52:00 +1100 Subject: [PATCH 66/87] Provide a noop prepare_work for drivers that don't support it. --- cgminer.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index 41bbcab3..8d997d01 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5406,7 +5406,7 @@ void *miner_thread(void *userdata) gettimeofday(&tv_workstart, NULL); work->blk.nonce = 0; cgpu->max_hashes = 0; - if (drv->prepare_work && !drv->prepare_work(mythr, work)) { + if (!drv->prepare_work(mythr, work)) { applog(LOG_ERR, "work prepare failed, exiting " "mining thread %d", thr_id); break; @@ -6399,6 +6399,11 @@ static bool noop_thread_init(struct thr_info __maybe_unused *thr) return true; } +static bool noop_prepare_work(struct thr_info __maybe_unused *thr, struct work __maybe_unused *work) +{ + return true; +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6418,6 +6423,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->can_limit_work = &noop_can_limit_work; if (!drv->thread_init) drv->thread_init = &noop_thread_init; + if (!drv->prepare_work) + drv->prepare_work = &noop_prepare_work; } void enable_device(struct cgpu_info *cgpu) From 2c28eefc45c301a7a6103a90842c3105f37230e9 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:54:54 +1100 Subject: [PATCH 67/87] Provide a noop hw_error function for drivers that don't support it. --- cgminer.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index 8d997d01..e289f3b7 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5294,8 +5294,7 @@ static bool hashtest(struct thr_info *thr, struct work *work) thr->cgpu->hw_errors++; mutex_unlock(&stats_lock); - if (thr->cgpu->drv->hw_error) - thr->cgpu->drv->hw_error(thr); + thr->cgpu->drv->hw_error(thr); goto out; } @@ -6404,6 +6403,10 @@ static bool noop_prepare_work(struct thr_info __maybe_unused *thr, struct work _ return true; } +static void noop_hw_error(struct thr_info __maybe_unused *thr) +{ +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6425,6 +6428,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->thread_init = &noop_thread_init; if (!drv->prepare_work) drv->prepare_work = &noop_prepare_work; + if (!drv->hw_error) + drv->hw_error = &noop_hw_error; } void enable_device(struct cgpu_info *cgpu) From b884d11a2370bf24bc1ecf4056f3cccd505c86d5 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:56:45 +1100 Subject: [PATCH 68/87] Provide a noop thread_shutdown function for drivers that don't support it. --- cgminer.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index e289f3b7..e33dfa93 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5522,8 +5522,7 @@ void *miner_thread(void *userdata) } out: - if (drv->thread_shutdown) - drv->thread_shutdown(mythr); + drv->thread_shutdown(mythr); thread_reportin(mythr); applog(LOG_ERR, "Thread %d failure, exiting", thr_id); @@ -6407,6 +6406,10 @@ static void noop_hw_error(struct thr_info __maybe_unused *thr) { } +static void noop_thread_shutdown(struct thr_info __maybe_unused *thr) +{ +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6430,6 +6433,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->prepare_work = &noop_prepare_work; if (!drv->hw_error) drv->hw_error = &noop_hw_error; + if (!drv->thread_shutdown) + drv->thread_shutdown = &noop_thread_shutdown; } void enable_device(struct cgpu_info *cgpu) From 81b84d4f7bafc53899033501e64726d3b0cc11ef Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 19:59:36 +1100 Subject: [PATCH 69/87] Provide a noop thread_enable function for drivers that don't support it. --- cgminer.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cgminer.c b/cgminer.c index e33dfa93..2d453233 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5353,8 +5353,7 @@ static void mt_disable(struct thr_info *mythr, const int thr_id, } while (mythr->pause); thread_reportin(mythr); applog(LOG_WARNING, "Thread %d being re-enabled", thr_id); - if (drv->thread_enable) - drv->thread_enable(mythr); + drv->thread_enable(mythr); } void *miner_thread(void *userdata) @@ -6361,9 +6360,10 @@ extern struct device_drv modminer_drv; extern struct device_drv ztex_drv; #endif - static int cgminer_id_count = 0; +/* Various noop functions for drivers that don't support or need their + * variants. */ static void noop_reinit_device(struct cgpu_info __maybe_unused *cgpu) { } @@ -6410,6 +6410,10 @@ static void noop_thread_shutdown(struct thr_info __maybe_unused *thr) { } +static void noop_thread_enable(struct thr_info __maybe_unused *thr) +{ +} + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6435,6 +6439,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->hw_error = &noop_hw_error; if (!drv->thread_shutdown) drv->thread_shutdown = &noop_thread_shutdown; + if (!drv->thread_enable) + drv->thread_enable = &noop_thread_enable; } void enable_device(struct cgpu_info *cgpu) From dafc2f775a0c455714cbdae7f78b819d1b083ac4 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 9 Feb 2013 21:12:03 +1100 Subject: [PATCH 70/87] Abstract out the main hashing loop to allow us to use a separate loop for devices that are fast enough to require queued work. --- cgminer.c | 60 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/cgminer.c b/cgminer.c index 2d453233..5714639c 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5356,49 +5356,33 @@ static void mt_disable(struct thr_info *mythr, const int thr_id, drv->thread_enable(mythr); } -void *miner_thread(void *userdata) +/* The main hashing loop for devices that are slow enough to work on one work + * item at a time, without a queue, aborting work before the entire nonce + * range has been hashed if needed. */ +void hash_sole_work(struct thr_info *mythr) { - struct thr_info *mythr = userdata; const int thr_id = mythr->id; struct cgpu_info *cgpu = mythr->cgpu; struct device_drv *drv = cgpu->drv; + struct timeval getwork_start, tv_start, tv_end, tv_workstart, tv_lastupdate; struct cgminer_stats *dev_stats = &(cgpu->cgminer_stats); struct cgminer_stats *pool_stats; - struct timeval getwork_start; - /* Try to cycle approximately 5 times before each log update */ const long cycle = opt_log_interval / 5 ? : 1; - struct timeval tv_start, tv_end, tv_workstart, tv_lastupdate; + const bool primary = (!mythr->device_thread) || mythr->primary_thread; struct timeval diff, sdiff, wdiff = {0, 0}; uint32_t max_nonce = drv->can_limit_work(mythr); int64_t hashes_done = 0; - int64_t hashes; - struct work *work; - const bool primary = (!mythr->device_thread) || mythr->primary_thread; - - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - - char threadname[20]; - snprintf(threadname,20,"miner %d",thr_id); - RenameThread(threadname); gettimeofday(&getwork_start, NULL); - - if (!drv->thread_init(mythr)) { - dev_error(cgpu, REASON_THREAD_FAIL_INIT); - goto out; - } - - thread_reportout(mythr); - applog(LOG_DEBUG, "Popping ping in miner thread"); - tq_pop(mythr->q, NULL); /* Wait for a ping to start */ - sdiff.tv_sec = sdiff.tv_usec = 0; gettimeofday(&tv_lastupdate, NULL); - while (1) { + while (42) { + struct work *work = get_work(mythr, thr_id); + int64_t hashes; + mythr->work_restart = false; - work = get_work(mythr, thr_id); cgpu->new_work = true; gettimeofday(&tv_workstart, NULL); @@ -5519,7 +5503,31 @@ void *miner_thread(void *userdata) } while (!abandon_work(work, &wdiff, cgpu->max_hashes)); free_work(work); } +} + +void *miner_thread(void *userdata) +{ + struct thr_info *mythr = userdata; + const int thr_id = mythr->id; + struct cgpu_info *cgpu = mythr->cgpu; + struct device_drv *drv = cgpu->drv; + char threadname[20]; + + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + snprintf(threadname,20,"miner %d",thr_id); + RenameThread(threadname); + + if (!drv->thread_init(mythr)) { + dev_error(cgpu, REASON_THREAD_FAIL_INIT); + goto out; + } + + thread_reportout(mythr); + applog(LOG_DEBUG, "Popping ping in miner thread"); + tq_pop(mythr->q, NULL); /* Wait for a ping to start */ + hash_sole_work(mythr); out: drv->thread_shutdown(mythr); From 20b5ebbc95912a6d18ec2955a518050773c23b6f Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 11 Feb 2013 15:28:41 +1100 Subject: [PATCH 71/87] hash_sole_work can be static --- cgminer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index eff364a4..ba7bfd3e 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5406,7 +5406,7 @@ static void mt_disable(struct thr_info *mythr, const int thr_id, /* The main hashing loop for devices that are slow enough to work on one work * item at a time, without a queue, aborting work before the entire nonce * range has been hashed if needed. */ -void hash_sole_work(struct thr_info *mythr) +static void hash_sole_work(struct thr_info *mythr) { const int thr_id = mythr->id; struct cgpu_info *cgpu = mythr->cgpu; From b9968156bae95f14a30b8befb3e74d8d620f1920 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 13 Feb 2013 11:13:30 +1100 Subject: [PATCH 72/87] MMQ rewrite the last of the old scanhash loop and drastically reduce CPU --- driver-modminer.c | 78 +++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/driver-modminer.c b/driver-modminer.c index 22812aa5..10d42a3b 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -595,8 +595,6 @@ static bool modminer_fpga_prepare(struct thr_info *thr) struct modminer_fpga_state *state; state = thr->cgpu_data = calloc(1, sizeof(struct modminer_fpga_state)); - state->next_work_cmd[0] = MODMINER_SEND_WORK; - state->next_work_cmd[1] = modminer->fpgaid; state->shares_to_good = MODMINER_EARLY_UP; state->overheated = false; @@ -773,24 +771,19 @@ static void get_modminer_statline_before(char *buf, struct cgpu_info *modminer) strcat(buf, info); } -static bool modminer_prepare_next_work(struct modminer_fpga_state *state, struct work *work) -{ - char *midstate = state->next_work_cmd + 2; - char *taildata = midstate + 32; - if (!(memcmp(midstate, work->midstate, 32) || memcmp(taildata, work->data + 64, 12))) - return false; - memcpy(midstate, work->midstate, 32); - memcpy(taildata, work->data + 64, 12); - return true; -} - -static bool modminer_start_work(struct thr_info *thr) +static bool modminer_start_work(struct thr_info *thr, struct work *work) { struct cgpu_info *modminer = thr->cgpu; struct modminer_fpga_state *state = thr->cgpu_data; int err, amount; + char cmd[48]; bool sta; + cmd[0] = MODMINER_SEND_WORK; + cmd[1] = modminer->fpgaid; + memcpy(&cmd[2], work->midstate, 32); + memcpy(&cmd[34], work->data + 64, 12); + if (state->first_work.tv_sec == 0) gettimeofday(&state->first_work, NULL); @@ -799,7 +792,7 @@ static bool modminer_start_work(struct thr_info *thr) mutex_lock(modminer->modminer_mutex); - if ((err = usb_write(modminer, (char *)(state->next_work_cmd), 46, &amount, C_SENDWORK)) < 0 || amount != 46) { + if ((err = usb_write(modminer, cmd, 46, &amount, C_SENDWORK)) < 0 || amount != 46) { mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Start work failed (%d:%d)", @@ -809,7 +802,6 @@ static bool modminer_start_work(struct thr_info *thr) } gettimeofday(&state->tv_workstart, NULL); - state->hashes = 0; sta = get_status(modminer, "start work", C_SENDWORKSTATUS); @@ -903,11 +895,10 @@ static const double processtime = 17.0; // 160Mhz is 26.84 - when overheated ensure we don't throw away shares static const double overheattime = 26.9; -static uint64_t modminer_process_results(struct thr_info *thr) +static uint64_t modminer_process_results(struct thr_info *thr, struct work *work) { struct cgpu_info *modminer = thr->cgpu; struct modminer_fpga_state *state = thr->cgpu_data; - struct work *work = &state->running_work; struct timeval now; char cmd[2]; uint32_t nonce; @@ -931,14 +922,14 @@ static uint64_t modminer_process_results(struct thr_info *thr) timeoutloop = 0; temploop = 0; - while (1) { + while (0x80085) { mutex_lock(modminer->modminer_mutex); if ((err = usb_write(modminer, cmd, 2, &amount, C_REQUESTWORKSTATUS)) < 0 || amount != 2) { mutex_unlock(modminer->modminer_mutex); // timeoutloop never resets so the timeouts can't // accumulate much during a single item of work - if (err == LIBUSB_ERROR_TIMEOUT && ++timeoutloop < 10) { + if (err == LIBUSB_ERROR_TIMEOUT && ++timeoutloop < 5) { state->timeout_fail++; goto tryagain; } @@ -1033,8 +1024,8 @@ tryagain: break; if (state->overheated == true) { - // don't check every time - if (++temploop > 30) { + // don't check every time (every ~1/2 sec) + if (++temploop > 4) { check_temperature(thr); temploop = 0; } @@ -1050,7 +1041,8 @@ tryagain: if (tdiff(&now, &state->tv_workstart) > timeout) break; - nmsleep(10); + // 1/10th sec to lower CPU usage + nmsleep(100); if (work_restart(thr)) break; } @@ -1064,21 +1056,17 @@ tryagain: // Overheat will complete the nonce range if (hashes > 0xffffffff) hashes = 0xffffffff; - else - if (hashes <= state->hashes) - hashes = 1; - else - hashes -= state->hashes; - state->hashes += hashes; + + work->blk.nonce = 0xffffffff; + return hashes; } static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce) { struct modminer_fpga_state *state = thr->cgpu_data; - int64_t hashes = 0; - bool startwork; struct timeval tv1, tv2; + int64_t hashes; // Device is gone if (thr->cgpu->usbinfo.nodev) @@ -1087,8 +1075,6 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ // Don't start new work if overheated if (state->overheated == true) { gettimeofday(&tv1, NULL); - if (state->work_running) - state->work_running = false; while (state->overheated == true) { check_temperature(thr); @@ -1100,7 +1086,7 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ if (state->overheated == true) { gettimeofday(&tv2, NULL); - // give up on this work item + // give up on this work item after 30s if (work_restart(thr) || tdiff(&tv2, &tv1) > 30) return 0; @@ -1110,27 +1096,13 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ } } - startwork = modminer_prepare_next_work(state, work); - if (state->work_running) { - hashes = modminer_process_results(thr); - if (hashes == -1) - return hashes; - - if (work_restart(thr)) { - state->work_running = false; - return 0; - } - } else - state->work_running = true; + if (!modminer_start_work(thr, work)) + return -1; - if (startwork) { - if (!modminer_start_work(thr)) - return -1; - __copy_work(&state->running_work, work); - } + hashes = modminer_process_results(thr, work); + if (hashes == -1) + return hashes; - // This is intentionally early - work->blk.nonce += hashes; return hashes; } From c432c655f7712babf43e887bd3d17528cc96e5f7 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 13 Feb 2013 14:50:55 +1100 Subject: [PATCH 73/87] debug_cb buffer type warning --- util.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/util.c b/util.c index 555e7093..cbb8b634 100644 --- a/util.c +++ b/util.c @@ -262,8 +262,7 @@ static void set_nettime(void) } static int curl_debug_cb(__maybe_unused CURL *handle, curl_infotype type, - __maybe_unused unsigned char *data, size_t size, - void *userdata) + __maybe_unused char *data, size_t size, void *userdata) { struct pool *pool = (struct pool *)userdata; From 00be617ce145eee6f9aa7c08eb23ac7bde0da04c Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 15 Feb 2013 01:36:50 +1100 Subject: [PATCH 74/87] API.java allow partial reads --- API.class | Bin 3635 -> 3431 bytes API.java | 13 +++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/API.class b/API.class index 026ab141c692de8f3bae7b867d29c2214bbd9d04..d506b93dc8265210b46db47f80ba3fd27f3365a2 100644 GIT binary patch delta 1719 zcmZXUTUb<86vuyuxtueHGwL@&Iv_S$hREP}g&f5jQIVLYnId>W7-$3s8t|Tusim2k zb~5vpw`?jc18Pt)Q?oL=zV_IYPxaiBwl)xv&G(%(d$0B1Yp?bH@4Y*Q-OWnexp(Cn zFrHsMlu%_7V41;klNGE~rdpX*1~mq?Y8Wx8qh9AllXRlWtX8JMLnCVpVg^knBWX5x z$sn#mEe5RyYYo=vtT*u!b-?}m1{(}ECQLT5+2CcJEo$$rI^qhjO(l6nZMa>T9csE$ znOAjQQ-ED2dF)o^b(M3EDb>HBvscxz&m=^HayJ<4H+WM8515pyf;Vwc=Pd)<;BAxK zbPk!k!(p9w4UQ<_QG;U!#|=*Cyr&!|bxzsYT5Nz>x}hf0+!}3)wdkC-liEnHhTa@+ zs)@9;Xawy*n&19Q8*FE!mD(%PN)u%~V{wLZjkGH1@T|rAoU{0Vq{WAPq@e}nE4KKU z^EwwSKH*c1A*-v`Rfig@WA&kht?_8Ae)igEV{IgEv50bui+pC$MpCEUqJz&RL#2ju zS)h2j#TP7)`DhIUIF^(I0)c?UT`C@sSf0j1|KFglE)usVJ4U!WEiRF?s~kg%7I9f) za5pyE6q+xUv`RgZ>NOTu=u*{OwfIu?a*eMnu5-iUCgt{d$M88{b4vlfvG|tnRL!?7 z<|rci@|Df&W7Fb$)rK)E*0MelFV2-Jb1j}@fyEtuuydV7=@Gw`NfVpCpi}K zynV_!%CU$S?Ay+KzpJLPsU@N@=)u-H@?Aw*W=6L=7HJKYiJ4Vf8yCeoR=U$Q_wdn` zC1qvy@2-q=MZ#1KMHGKaumAT8Q4X-I4$3>6yALKd^uu*DTb@@!(wEf znPNZ+Ul)OjU`{6^I?%cpS<#M`;*m}s4eNeg)+R=!cq~P(Ur#Z*i@YAdm`?J;hTrhJ z9KP%n!9sVY+j$0el5D?IoSE(v1&jSI@zzc{djGd14p}lbNoH7YXPinlUN%?0Hor5) z1m*54d!kgRAYR|3R03~Lp<|S1a+?r0lM8Z~LNZb`*U1$}i1i4m1BFx{3k9)QBw0cw z71Xm-o`Whj%M-GTmF%OM1FYg0HJqbX?qI#-i%G_)+^7bw3i>*0xIr_wi6^*AD}S)| zKibKW>s9=g2%$>>jnYeD@DfE~XOg_Is4(sy6{bihLcZ4*R(%OGQ+qmUE4ak8Lf3=v z>4GZggD3jo$K?B+nXVKw+GKO596>LSGm$AwqqvuiLh-={iEfqnPMK{JR<<*N9fI5~ z*!_au!*uov5Br3N1Jd)se$9D=yCuENoy0XjQo#z}%yQqXxxU%$G@?qE&$v3aoU~M!P|W!72|atTtFb+elKcyV)P++G*pH|=*on1;`w}*80 zD6rQf0Y9s=Pr2UjA&Zqd2b7j&aM0j6#XsbsM1>jTu+H-aM+}atpkDCsA}{GA9W!`Y z3BF=*+~8G%6FRRc!bzRitu(DAIl8jLU*A;WUs2^>(j3t6l&-B0tmtTLZE4r(w2o_I z+@d0`b>6TpXp;mxrSql)W?j=tUE)^fm{n{m&3lOHCT~%uVOzM-7iHWeUsCKG)7uo&XLnh7Eopq=8VY)bm^Qm>EoQp*J(Hwr4&su`H(q+kJCU2 zo)>ybN{X1nHkLVJ#P$OoUf3-iSCD4&m*;?Ne=umDx)`*Lc8(VW` zw>7qORCcrl{L4)~;Zw!GVDgy?`ExFse8HC{Ur}bAvL|~laajp`ZSoD@n#>ULZ}x<| z?^K+z5tGgSmWCX$*VxjaB)``%id)*(1lo$yC7^VZ*~~HdfgdfeqaZ5GPdY!F{K6Hh z%8_TEN42%fk!D{&oz?5ejEk!)|F2am)0G%yt1FSL>ziBK1HFGb3bfu*ms`8V9%yUR z(8tx4%$PC0+G^KN1dC-fz(yhuQi{g32u1+QBR7q%mlco;WD3e#eIFm_? z@I^*31|L~M(r)r1x;Hs-{rGUpQYyV0|6!Wx=tI4VCR|0oigQ?o(yW2HX;s28B<9Or z-#KTY!=CT#A*PS0+AyX!F+_BxJl;_PvOpoIy zBb84LGp5kxbBXdDA?^&3=5vJ@+ei8Ue_WXHg}P7oIqY6vh>Uz^MwrY_;tO3pWGmST zVp`F<`^c#kv3O^gyA(I3FE|+8-4cfqjrL9yFc3|KBII^U6AReFcDZ#1S~rt8NphC- zel~9A3b$GsSR<$TJVGt?)X6oqkWGSZAt0KMvV$cY5Y8c%a+n5A(kRQ-MDUW_v8vCb zu=R`NV4rnrq=)lm40UQp3@f+n#Ne3zA$`|HwOMk@%R0k7g^o@sh06Ly(F-IQsdcpX zUI8kdNdu{MXP==k-`PoUxcp=h%l<$4j7*;+-Wj5(Tbw&&Z=%U3mq|?KzQMBO3k_O@ zyGr;Q1Y1K4>*Ra0UL=DeyIrI=%XV$W&o(K@4w|aj8A*REj(*W_3>`<6{K9K$(rc#c zERvHpq!Mna?&85poR+~;`?%OUrQCaeh4%sLh*=RVuFcHK4l}jp-?g0}-vih!Yr03; zw^!P?PZoGTsj_Fe9HdYhR4xswgX>FMdh`KeBn)pe!*-k`3HYzY(M}2 diff --git a/API.java b/API.java index 36c1578a..54dcda99 100644 --- a/API.java +++ b/API.java @@ -76,6 +76,7 @@ class API public void process(String cmd, InetAddress ip, int port) throws Exception { + StringBuffer sb = new StringBuffer(); char buf[] = new char[MAXRECEIVESIZE]; int len = 0; @@ -89,7 +90,15 @@ System.out.println("Attempting to send '"+cmd+"' to "+ip.getHostAddress()+":"+po ps.flush(); InputStreamReader isr = new InputStreamReader(socket.getInputStream()); - len = isr.read(buf, 0, MAXRECEIVESIZE); + while (0x80085 > 0) + { + len = isr.read(buf, 0, MAXRECEIVESIZE); + if (len < 1) + break; + sb.append(buf, 0, len); + if (buf[len-1] == '\0') + break; + } closeAll(); } @@ -100,7 +109,7 @@ System.out.println("Attempting to send '"+cmd+"' to "+ip.getHostAddress()+":"+po return; } - String result = new String(buf, 0, len); + String result = sb.toString(); System.out.println("Answer='"+result+"'"); From e414cd055cc5e9609f94f815102cec63c16a828b Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 16 Feb 2013 09:07:33 +1100 Subject: [PATCH 75/87] Fix tv_lastupdate being made into tv_end and update the hashmeter on cycle, not opt_log_interval. --- cgminer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index ff7b3eba..2e427dad 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5565,10 +5565,10 @@ static void hash_sole_work(struct thr_info *mythr) max_nonce = max_nonce * 0x400 / (((cycle * 1000000) + sdiff.tv_usec) / (cycle * 1000000 / 0x400)); timersub(&tv_end, &tv_lastupdate, &diff); - if (diff.tv_sec >= opt_log_interval) { + if (diff.tv_sec >= cycle) { hashmeter(thr_id, &diff, hashes_done); hashes_done = 0; - tv_lastupdate = tv_end; + memcpy(&tv_lastupdate, &tv_end, sizeof(struct timeval)); } if (unlikely(mythr->work_restart)) { From 649f2939f7c836afaa513952e7790601229f511c Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 16 Feb 2013 09:09:44 +1100 Subject: [PATCH 76/87] Update copyright year. --- cgminer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index 2e427dad..931e16a7 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 Con Kolivas + * Copyright 2011-2013 Con Kolivas * Copyright 2011-2012 Luke Dashjr * Copyright 2010 Jeff Garzik * From 5e3253a7cf1fd1a0736c252c2fc6ce2933fe475e Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 16 Feb 2013 11:54:05 +1100 Subject: [PATCH 77/87] Create the hash queued work variant for use with devices that are fast enough to require a queue. --- cgminer.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ miner.h | 1 + 2 files changed, 48 insertions(+) diff --git a/cgminer.c b/cgminer.c index 931e16a7..6c28a4d0 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5595,6 +5595,53 @@ static void hash_sole_work(struct thr_info *mythr) } } +/* This version of hash work is for devices that are fast enough to always + * perform a full nonce range and need a queue to maintain the device busy. + * Work creation and destruction is not done from within this function + * directly. */ +static void hash_queued_work(struct thr_info *mythr) +{ + const long cycle = opt_log_interval / 5 ? : 1; + struct timeval tv_start = {0, 0}, tv_end; + struct cgpu_info *cgpu = mythr->cgpu; + struct device_drv *drv = cgpu->drv; + const int thr_id = mythr->id; + int64_t hashes_done = 0; + + while (42) { + struct timeval diff; + int64_t hashes; + + mythr->work_restart = false; + + //fill_queue(mythr, cgpu, drv, thr_id); + + thread_reportin(mythr); + hashes = drv->scanwork(mythr); + if (unlikely(hashes == -1 )) { + applog(LOG_ERR, "%s %d failure, disabling!", drv->name, cgpu->device_id); + cgpu->deven = DEV_DISABLED; + dev_error(cgpu, REASON_THREAD_ZERO_HASH); + mt_disable(mythr, thr_id, drv); + } + + hashes_done += hashes; + gettimeofday(&tv_end, NULL); + timersub(&tv_end, &tv_start, &diff); + if (diff.tv_sec >= cycle) { + hashmeter(thr_id, &diff, hashes_done); + hashes_done = 0; + memcpy(&tv_start, &tv_end, sizeof(struct timeval)); + } + + //if (unlikely(mythr->work_restart)) + // flush_queue(mythr, cgpu); + + if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED)) + mt_disable(mythr, thr_id, drv); + } +} + void *miner_thread(void *userdata) { struct thr_info *mythr = userdata; diff --git a/miner.h b/miner.h index 70a379fe..f68707a8 100644 --- a/miner.h +++ b/miner.h @@ -298,6 +298,7 @@ struct device_drv { bool (*thread_init)(struct thr_info *); bool (*prepare_work)(struct thr_info *, struct work *); int64_t (*scanhash)(struct thr_info *, struct work *, int64_t); + int64_t (*scanwork)(struct thr_info *); void (*hw_error)(struct thr_info *); void (*thread_shutdown)(struct thr_info *); void (*thread_enable)(struct thr_info *); From 95b2020263b28396cbd96f3581d575d201f7c19f Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 16 Feb 2013 12:14:13 +1100 Subject: [PATCH 78/87] Create a fill_queue function that creates hashtables of as many work items as is required by the device driver till it flags the queue full. --- cgminer.c | 26 +++++++++++++++++++++++++- miner.h | 5 +++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/cgminer.c b/cgminer.c index 6c28a4d0..c9f02e72 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5595,6 +5595,25 @@ static void hash_sole_work(struct thr_info *mythr) } } +/* Create a hashtable of work items for devices with a queue. The device + * driver must have a custom queue_full function or it will default to true + * and put only one work item in the queue. Work items should not be removed + * from this hashtable until they are no longer in use anywhere. Once a work + * item is physically queued on the device itself, the work->queued flag + * should be set under cgpu->qlock write lock to prevent it being dereferenced + * while still in use. */ +static void fill_queue(struct thr_info *mythr, struct cgpu_info *cgpu, struct device_drv *drv, const int thr_id) +{ + thread_reportout(mythr); + do { + struct work *work = get_work(mythr, thr_id); + + wr_lock(&cgpu->qlock); + HASH_ADD_INT(cgpu->queued_work, id, work); + wr_unlock(&cgpu->qlock); + } while (!drv->queue_full(cgpu)); +} + /* This version of hash work is for devices that are fast enough to always * perform a full nonce range and need a queue to maintain the device busy. * Work creation and destruction is not done from within this function @@ -5614,7 +5633,7 @@ static void hash_queued_work(struct thr_info *mythr) mythr->work_restart = false; - //fill_queue(mythr, cgpu, drv, thr_id); + fill_queue(mythr, cgpu, drv, thr_id); thread_reportin(mythr); hashes = drv->scanwork(mythr); @@ -6589,6 +6608,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->thread_shutdown = &noop_thread_shutdown; if (!drv->thread_enable) drv->thread_enable = &noop_thread_enable; + if (!drv->queue_full) + drv->queue_full = &noop_get_stats; } void enable_device(struct cgpu_info *cgpu) @@ -6612,6 +6633,9 @@ void enable_device(struct cgpu_info *cgpu) } #endif fill_device_api(cgpu); + + rwlock_init(&cgpu->qlock); + cgpu->queued_work = NULL; } struct _cgpu_devid_counter { diff --git a/miner.h b/miner.h index f68707a8..14d53384 100644 --- a/miner.h +++ b/miner.h @@ -299,6 +299,8 @@ struct device_drv { bool (*prepare_work)(struct thr_info *, struct work *); int64_t (*scanhash)(struct thr_info *, struct work *, int64_t); int64_t (*scanwork)(struct thr_info *); + bool (*queue_full)(struct cgpu_info *); + void (*hw_error)(struct thr_info *); void (*thread_shutdown)(struct thr_info *); void (*thread_enable)(struct thr_info *); @@ -500,6 +502,9 @@ struct cgpu_info { int dev_throttle_count; struct cgminer_stats cgminer_stats; + + pthread_rwlock_t qlock; + struct work *queued_work; }; extern bool add_cgpu(struct cgpu_info*); From e8e88beff10641a9f6e578f41ff1620f2bb3a5d3 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 16 Feb 2013 12:28:50 +1100 Subject: [PATCH 79/87] Create a central point for removal of work items completed by queued device drivers. --- cgminer.c | 10 ++++++++++ miner.h | 1 + 2 files changed, 11 insertions(+) diff --git a/cgminer.c b/cgminer.c index c9f02e72..a562b3f4 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5614,6 +5614,16 @@ static void fill_queue(struct thr_info *mythr, struct cgpu_info *cgpu, struct de } while (!drv->queue_full(cgpu)); } +/* This function should be used by queued device drivers when they're sure + * the work struct is no longer in use. */ +void work_completed(struct cgpu_info *cgpu, struct work *work) +{ + wr_lock(&cgpu->qlock); + HASH_DEL(cgpu->queued_work, work); + wr_unlock(&cgpu->qlock); + free_work(work); +} + /* This version of hash work is for devices that are fast enough to always * perform a full nonce range and need a queue to maintain the device busy. * Work creation and destruction is not done from within this function diff --git a/miner.h b/miner.h index 14d53384..9f7d3b54 100644 --- a/miner.h +++ b/miner.h @@ -1093,6 +1093,7 @@ struct modminer_fpga_state { extern void get_datestamp(char *, struct timeval *); extern void submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce); +extern void work_completed(struct cgpu_info *cgpu, struct work *work); extern void tailsprintf(char *f, const char *fmt, ...); extern void wlogprint(const char *f, ...); extern int curses_int(const char *query); From 294cda2eb28ac886fc630c9f45ddf013f493cb3c Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 16 Feb 2013 12:35:16 +1100 Subject: [PATCH 80/87] Flush queued work on a restart from the hash database and discard the work structs. --- cgminer.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index a562b3f4..f01e9a34 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5624,6 +5624,27 @@ void work_completed(struct cgpu_info *cgpu, struct work *work) free_work(work); } +static void flush_queue(struct cgpu_info *cgpu) +{ + struct work *work, *tmp; + int discarded = 0; + + wr_lock(&cgpu->qlock); + HASH_ITER(hh, cgpu->queued_work, work, tmp) { + /* Can only discard the work items if they're not physically + * queued on the device. */ + if (!work->queued) { + HASH_DEL(cgpu->queued_work, work); + discard_work(work); + discarded++; + } + } + wr_unlock(&cgpu->qlock); + + if (discarded) + applog(LOG_DEBUG, "Discarded %d queued work items", discarded); +} + /* This version of hash work is for devices that are fast enough to always * perform a full nonce range and need a queue to maintain the device busy. * Work creation and destruction is not done from within this function @@ -5663,8 +5684,8 @@ static void hash_queued_work(struct thr_info *mythr) memcpy(&tv_start, &tv_end, sizeof(struct timeval)); } - //if (unlikely(mythr->work_restart)) - // flush_queue(mythr, cgpu); + if (unlikely(mythr->work_restart)) + flush_queue(cgpu); if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED)) mt_disable(mythr, thr_id, drv); From c80c65eac051b7f5da00221cfda557bafe89c8bb Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 16 Feb 2013 12:38:53 +1100 Subject: [PATCH 81/87] Add a driver specific flush_work for queued devices that may have work items already queued to abort working on them on the device and discard them. --- cgminer.c | 11 +++++++++-- miner.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index f01e9a34..48164f51 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5684,8 +5684,10 @@ static void hash_queued_work(struct thr_info *mythr) memcpy(&tv_start, &tv_end, sizeof(struct timeval)); } - if (unlikely(mythr->work_restart)) + if (unlikely(mythr->work_restart)) { flush_queue(cgpu); + drv->flush_work(cgpu); + } if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED)) mt_disable(mythr, thr_id, drv); @@ -6612,6 +6614,9 @@ static void noop_thread_enable(struct thr_info __maybe_unused *thr) { } +#define noop_flush_work noop_reinit_device +#define noop_queue_full noop_get_stats + /* Fill missing driver api functions with noops */ void fill_device_api(struct cgpu_info *cgpu) { @@ -6639,8 +6644,10 @@ void fill_device_api(struct cgpu_info *cgpu) drv->thread_shutdown = &noop_thread_shutdown; if (!drv->thread_enable) drv->thread_enable = &noop_thread_enable; + if (!drv->flush_work) + drv->flush_work = &noop_flush_work; if (!drv->queue_full) - drv->queue_full = &noop_get_stats; + drv->queue_full = &noop_queue_full; } void enable_device(struct cgpu_info *cgpu) diff --git a/miner.h b/miner.h index 9f7d3b54..da44dc9b 100644 --- a/miner.h +++ b/miner.h @@ -300,6 +300,7 @@ struct device_drv { int64_t (*scanhash)(struct thr_info *, struct work *, int64_t); int64_t (*scanwork)(struct thr_info *); bool (*queue_full)(struct cgpu_info *); + void (*flush_work)(struct cgpu_info *); void (*hw_error)(struct thr_info *); void (*thread_shutdown)(struct thr_info *); From 254e25ac7fbbe53ad0c8488bfe9653e84cec62e5 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 16 Feb 2013 14:03:40 +1100 Subject: [PATCH 82/87] Add comments. --- cgminer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cgminer.c b/cgminer.c index 48164f51..764a9c64 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5611,6 +5611,9 @@ static void fill_queue(struct thr_info *mythr, struct cgpu_info *cgpu, struct de wr_lock(&cgpu->qlock); HASH_ADD_INT(cgpu->queued_work, id, work); wr_unlock(&cgpu->qlock); + /* The queue_full function should be used by the driver to + * actually place work items on the physical device if it + * does have a queue. */ } while (!drv->queue_full(cgpu)); } From fda6d46e95ecda20d2d012662c6cc25a996128a9 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Sat, 16 Feb 2013 14:09:44 +1100 Subject: [PATCH 83/87] Add the choice of hash loop to the device driver, defaulting to hash_sole_work if none is specified. --- cgminer.c | 6 ++++-- miner.h | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/cgminer.c b/cgminer.c index 764a9c64..81e2eb1d 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5652,7 +5652,7 @@ static void flush_queue(struct cgpu_info *cgpu) * perform a full nonce range and need a queue to maintain the device busy. * Work creation and destruction is not done from within this function * directly. */ -static void hash_queued_work(struct thr_info *mythr) +void hash_queued_work(struct thr_info *mythr) { const long cycle = opt_log_interval / 5 ? : 1; struct timeval tv_start = {0, 0}, tv_end; @@ -5719,7 +5719,7 @@ void *miner_thread(void *userdata) applog(LOG_DEBUG, "Popping ping in miner thread"); tq_pop(mythr->q, NULL); /* Wait for a ping to start */ - hash_sole_work(mythr); + drv->hash_work(mythr); out: drv->thread_shutdown(mythr); @@ -6647,6 +6647,8 @@ void fill_device_api(struct cgpu_info *cgpu) drv->thread_shutdown = &noop_thread_shutdown; if (!drv->thread_enable) drv->thread_enable = &noop_thread_enable; + if (!drv->hash_work) + drv->hash_work = &hash_sole_work; if (!drv->flush_work) drv->flush_work = &noop_flush_work; if (!drv->queue_full) diff --git a/miner.h b/miner.h index da44dc9b..897f01d8 100644 --- a/miner.h +++ b/miner.h @@ -297,8 +297,18 @@ struct device_drv { uint64_t (*can_limit_work)(struct thr_info *); bool (*thread_init)(struct thr_info *); bool (*prepare_work)(struct thr_info *, struct work *); + + /* Which hash work loop this driver uses. */ + void (*hash_work)(struct thr_info *); + /* Two variants depending on whether the device divides work up into + * small pieces or works with whole work items and may or may not have + * a queue of its own. */ int64_t (*scanhash)(struct thr_info *, struct work *, int64_t); int64_t (*scanwork)(struct thr_info *); + + /* Used to extract work from the hash table of queued work and tell + * the main loop that it should not add any further work to the table. + */ bool (*queue_full)(struct cgpu_info *); void (*flush_work)(struct cgpu_info *); @@ -1095,6 +1105,7 @@ struct modminer_fpga_state { extern void get_datestamp(char *, struct timeval *); extern void submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce); extern void work_completed(struct cgpu_info *cgpu, struct work *work); +extern void hash_queued_work(struct thr_info *mythr); extern void tailsprintf(char *f, const char *fmt, ...); extern void wlogprint(const char *f, ...); extern int curses_int(const char *query); From fce5434975d367477cc037c2bfdf52a817f39342 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 18 Feb 2013 14:14:10 +1100 Subject: [PATCH 84/87] Add a get_queued function for devices to use to retrieve work items from the queued hashtable. --- cgminer.c | 21 +++++++++++++++++++++ miner.h | 1 + 2 files changed, 22 insertions(+) diff --git a/cgminer.c b/cgminer.c index 8b062743..4fca0759 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5619,6 +5619,27 @@ static void fill_queue(struct thr_info *mythr, struct cgpu_info *cgpu, struct de } while (!drv->queue_full(cgpu)); } +/* This function is for retrieving one work item from the queued hashtable of + * available work items that are not yet physically on a device (which is + * flagged with the work->queued bool). Code using this function must be able + * to handle NULL as a return which implies there is no work available. */ +struct work *get_queued(struct cgpu_info *cgpu) +{ + struct work *work, *tmp, *ret = NULL; + + wr_lock(&cgpu->qlock); + HASH_ITER(hh, cgpu->queued_work, work, tmp) { + if (!work->queued) { + work->queued = true; + ret = work; + break; + } + } + wr_unlock(&cgpu->qlock); + + return ret; +} + /* This function should be used by queued device drivers when they're sure * the work struct is no longer in use. */ void work_completed(struct cgpu_info *cgpu, struct work *work) diff --git a/miner.h b/miner.h index 897f01d8..fa262414 100644 --- a/miner.h +++ b/miner.h @@ -1104,6 +1104,7 @@ struct modminer_fpga_state { extern void get_datestamp(char *, struct timeval *); extern void submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce); +extern struct work *get_queued(struct cgpu_info *cgpu); extern void work_completed(struct cgpu_info *cgpu, struct work *work); extern void hash_queued_work(struct thr_info *mythr); extern void tailsprintf(char *f, const char *fmt, ...); From 3515b6e2e6407f07d84d92aaef0d8511fb263ebb Mon Sep 17 00:00:00 2001 From: Kano Date: Thu, 21 Feb 2013 07:35:39 +1100 Subject: [PATCH 85/87] BFL stop 1st init command if no device --- driver-bitforce.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/driver-bitforce.c b/driver-bitforce.c index b7f238b9..228fa5e7 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -85,6 +85,9 @@ static void bitforce_initialise(struct cgpu_info *bitforce, bool lock) if (lock) mutex_lock(&bitforce->device_mutex); + if (bitforce->usbinfo.nodev) + goto failed; + // Reset err = usb_transfer(bitforce, FTDI_TYPE_OUT, FTDI_REQUEST_RESET, FTDI_VALUE_RESET, bitforce->usbdev->found->interface, C_RESET); From 42a01e7b37789c31933cc7a73e7ed4266bbd48ae Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 1 Mar 2013 16:49:08 +1100 Subject: [PATCH 86/87] Update diff stale: total and pools when stratum throws away shares --- cgminer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cgminer.c b/cgminer.c index 4fca0759..66af12eb 100644 --- a/cgminer.c +++ b/cgminer.c @@ -4698,12 +4698,14 @@ out: void clear_stratum_shares(struct pool *pool) { struct stratum_share *sshare, *tmpshare; + double diff_cleared = 0; int cleared = 0; mutex_lock(&sshare_lock); HASH_ITER(hh, stratum_shares, sshare, tmpshare) { if (sshare->work->pool == pool) { HASH_DEL(stratum_shares, sshare); + diff_cleared += sshare->work->work_difficulty; free_work(sshare->work); free(sshare); cleared++; @@ -4715,6 +4717,8 @@ void clear_stratum_shares(struct pool *pool) applog(LOG_WARNING, "Lost %d shares due to stratum disconnect on pool %d", cleared, pool->pool_no); pool->stale_shares += cleared; total_stale += cleared; + pool->diff_stale += diff_cleared; + total_diff_stale += diff_cleared; } } From f56a0fb71923ac931c6643cb29f407dbbe44330c Mon Sep 17 00:00:00 2001 From: Kano Date: Fri, 1 Mar 2013 16:57:22 +1100 Subject: [PATCH 87/87] API always report failed send() replies --- api.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/api.c b/api.c index 6d77c600..9140df64 100644 --- a/api.c +++ b/api.c @@ -3433,12 +3433,10 @@ static void send_result(struct io_data *io_data, SOCKETTYPE c, bool isjson) // ignore failure - it's closed immediately anyway n = send(c, buf, len+1, 0); - if (opt_debug) { - if (SOCKETFAIL(n)) - applog(LOG_DEBUG, "API: send failed: %s", SOCKERRMSG); - else - applog(LOG_DEBUG, "API: sent %d", n); - } + if (SOCKETFAIL(n)) + applog(LOG_WARNING, "API: send failed: %s", SOCKERRMSG); + else + applog(LOG_DEBUG, "API: sent %d", n); } static void tidyup(__maybe_unused void *arg)
'; - if ($prev !== null) - echo riginput($prev, 'Prev').' '; - echo " "; - if ($next !== null) - echo riginput($next, 'Next').' '; - echo ' '; - if (count($rigs) > 1) - echo " "; + if ($userlist === null || isset($_SESSION[$ses])) + { + if ($prev !== null) + echo riginput($prev, 'Prev').' '; + echo " "; + if ($next !== null) + echo riginput($next, 'Next').' '; + echo ' '; + if (count($rigs) > 1) + echo " "; + } if ($allowcustompages === true) - foreach ($customsummarypages as $pagename => $data) + { + if ($userlist === null || isset($_SESSION[$ses])) + $list = $customsummarypages; + else + { + if ($userlist !== null && isset($userlist['def'])) + $list = array_flip($userlist['def']); + else + $list = array(); + } + + foreach ($list as $pagename => $data) echo " "; + } echo ' '; if ($rig !== null && $readonly === false) @@ -1580,6 +1604,12 @@ function pagebuttons($rig, $pg) echo " "; } refreshbuttons(); + if (isset($_SESSION[$ses])) + echo " "; + else + if ($userlist !== null) + echo " "; + echo "
 
+
+ + +
+ + +
+ + + + + + + + +
 
+

LOGIN

Username:
+
Password:
+
+
+
No rigs defined