Browse Source

Merge pull request #441 from kanoi/master

USB locking
nfactor-troky
Con Kolivas 12 years ago
parent
commit
3f105a23c8
  1. 44
      driver-avalon.c
  2. 45
      driver-bflsc.c
  3. 40
      driver-bitforce.c
  4. 26
      driver-icarus.c
  5. 67
      driver-modminer.c
  6. 151
      usbutils.c
  7. 17
      usbutils.h

44
driver-avalon.c

@ -574,39 +574,27 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found
int this_option_offset = ++option_offset; int this_option_offset = ++option_offset;
struct avalon_info *info; struct avalon_info *info;
struct cgpu_info *avalon; struct cgpu_info *avalon;
char devpath[20];
bool configured; bool configured;
int ret; int ret;
avalon = calloc(1, sizeof(struct cgpu_info)); avalon = usb_alloc_cgpu(&avalon_drv, AVALON_MINER_THREADS);
if (unlikely(!avalon))
quit(1, "Failed to calloc avalon in avalon_detect_one");;
avalon->drv = &avalon_drv;
avalon->threads = AVALON_MINER_THREADS;
configured = get_options(this_option_offset, &baud, &miner_count, configured = get_options(this_option_offset, &baud, &miner_count,
&asic_count, &timeout, &frequency); &asic_count, &timeout, &frequency);
if (!usb_init(avalon, dev, found)) if (!usb_init(avalon, dev, found))
return false; goto shin;
/* Even though this is an FTDI type chip, we want to do the parsing /* Even though this is an FTDI type chip, we want to do the parsing
* all ourselves so set it to std usb type */ * all ourselves so set it to std usb type */
avalon->usbdev->usb_type = USB_TYPE_STD; avalon->usbdev->usb_type = USB_TYPE_STD;
/* We have a real Avalon! */ /* We have a real Avalon! */
sprintf(devpath, "%d:%d",
(int)(avalon->usbinfo.bus_number),
(int)(avalon->usbinfo.device_address));
avalon_initialise(avalon); avalon_initialise(avalon);
avalon->device_path = strdup(devpath);
add_cgpu(avalon);
avalon->device_data = calloc(sizeof(struct avalon_info), 1); avalon->device_data = calloc(sizeof(struct avalon_info), 1);
if (unlikely(!(avalon->device_data))) if (unlikely(!(avalon->device_data)))
quit(1, "Failed to malloc avalon_info data"); quit(1, "Failed to calloc avalon_info data");
info = avalon->device_data; info = avalon->device_data;
if (configured) { if (configured) {
@ -635,19 +623,35 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found
info->temp_old = 0; info->temp_old = 0;
ret = avalon_reset(avalon, true); ret = avalon_reset(avalon, true);
if (ret && !configured) { if (ret && !configured)
usb_uninit(avalon); goto unshin;
return false;
} if (!add_cgpu(avalon))
goto unshin;
update_usb_stats(avalon);
avalon_idle(avalon, info); avalon_idle(avalon, info);
applog(LOG_DEBUG, "Avalon Detected: %s " applog(LOG_DEBUG, "Avalon Detected: %s "
"(miner_count=%d asic_count=%d timeout=%d frequency=%d)", "(miner_count=%d asic_count=%d timeout=%d frequency=%d)",
devpath, info->miner_count, info->asic_count, info->timeout, avalon->device_path, info->miner_count, info->asic_count, info->timeout,
info->frequency); info->frequency);
return true; return true;
unshin:
usb_uninit(avalon);
shin:
free(avalon->device_data);
avalon->device_data = NULL;
avalon = usb_free_cgpu(avalon);
return false;
} }
static void avalon_detect(void) static void avalon_detect(void)

45
driver-bflsc.c

@ -802,7 +802,6 @@ static bool bflsc_detect_one(struct libusb_device *dev, struct usb_find_devices
{ {
struct bflsc_info *sc_info = NULL; struct bflsc_info *sc_info = NULL;
char buf[BFLSC_BUFSIZ+1]; char buf[BFLSC_BUFSIZ+1];
char devpath[20];
int i, err, amount; int i, err, amount;
struct timeval init_start, init_now; struct timeval init_start, init_now;
int init_sleep, init_count; int init_sleep, init_count;
@ -810,13 +809,7 @@ static bool bflsc_detect_one(struct libusb_device *dev, struct usb_find_devices
char *newname; char *newname;
uint16_t latency; uint16_t latency;
struct cgpu_info *bflsc = calloc(1, sizeof(*bflsc)); struct cgpu_info *bflsc = usb_alloc_cgpu(&bflsc_drv, 1);
if (unlikely(!bflsc))
quit(1, "Failed to calloc bflsc in bflsc_detect_one");
bflsc->drv = &bflsc_drv;
bflsc->deven = DEV_ENABLED;
bflsc->threads = 1;
sc_info = calloc(1, sizeof(*sc_info)); sc_info = calloc(1, sizeof(*sc_info));
if (unlikely(!sc_info)) if (unlikely(!sc_info))
@ -827,11 +820,6 @@ static bool bflsc_detect_one(struct libusb_device *dev, struct usb_find_devices
if (!usb_init(bflsc, dev, found)) if (!usb_init(bflsc, dev, found))
goto shin; goto shin;
sprintf(devpath, "%d:%d",
(int)(bflsc->usbinfo.bus_number),
(int)(bflsc->usbinfo.device_address));
// Allow 2 complete attempts if the 1st time returns an unrecognised reply // Allow 2 complete attempts if the 1st time returns an unrecognised reply
ident_first = true; ident_first = true;
retry: retry:
@ -843,7 +831,7 @@ reinit:
err = write_to_dev(bflsc, 0, BFLSC_IDENTIFY, BFLSC_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY); err = write_to_dev(bflsc, 0, BFLSC_IDENTIFY, BFLSC_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY);
if (err < 0 || amount != BFLSC_IDENTIFY_LEN) { if (err < 0 || amount != BFLSC_IDENTIFY_LEN) {
applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)", applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)",
bflsc->drv->dname, devpath, amount, err); bflsc->drv->dname, bflsc->device_path, amount, err);
goto unshin; goto unshin;
} }
@ -854,7 +842,7 @@ reinit:
if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) { if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) {
if (init_count == 2) { if (init_count == 2) {
applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying", applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying",
bflsc->drv->dname, devpath, amount, err); bflsc->drv->dname, bflsc->device_path, amount, err);
} }
nmsleep(init_sleep); nmsleep(init_sleep);
if ((init_sleep * 2) <= REINIT_TIME_MAX_MS) if ((init_sleep * 2) <= REINIT_TIME_MAX_MS)
@ -864,14 +852,14 @@ reinit:
if (init_count > 0) if (init_count > 0)
applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs", applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs",
bflsc->drv->dname, devpath, init_count, tdiff(&init_now, &init_start)); bflsc->drv->dname, bflsc->device_path, init_count, tdiff(&init_now, &init_start));
if (err < 0) { if (err < 0) {
applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)",
bflsc->drv->dname, devpath, amount, err); bflsc->drv->dname, bflsc->device_path, amount, err);
} else { } else {
applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)",
bflsc->drv->dname, devpath, amount); bflsc->drv->dname, bflsc->device_path, amount);
} }
goto unshin; goto unshin;
@ -880,24 +868,22 @@ reinit:
if (unlikely(!strstr(buf, BFLSC_BFLSC))) { if (unlikely(!strstr(buf, BFLSC_BFLSC))) {
applog(LOG_DEBUG, "%s detect (%s) found an FPGA '%s' ignoring", applog(LOG_DEBUG, "%s detect (%s) found an FPGA '%s' ignoring",
bflsc->drv->dname, devpath, buf); bflsc->drv->dname, bflsc->device_path, buf);
goto unshin; goto unshin;
} }
if (unlikely(strstr(buf, BFLSC_IDENTITY))) { if (unlikely(strstr(buf, BFLSC_IDENTITY))) {
if (ident_first) { if (ident_first) {
applog(LOG_DEBUG, "%s detect (%s) didn't recognise '%s' trying again ...", applog(LOG_DEBUG, "%s detect (%s) didn't recognise '%s' trying again ...",
bflsc->drv->dname, devpath, buf); bflsc->drv->dname, bflsc->device_path, buf);
ident_first = false; ident_first = false;
goto retry; goto retry;
} }
applog(LOG_DEBUG, "%s detect (%s) didn't recognise '%s' on 2nd attempt", applog(LOG_DEBUG, "%s detect (%s) didn't recognise '%s' on 2nd attempt",
bflsc->drv->dname, devpath, buf); bflsc->drv->dname, bflsc->device_path, buf);
goto unshin; goto unshin;
} }
bflsc->device_path = strdup(devpath);
if (!getinfo(bflsc, 0)) if (!getinfo(bflsc, 0))
goto unshin; goto unshin;
@ -951,7 +937,7 @@ reinit:
// We have a real BFLSC! // We have a real BFLSC!
applog(LOG_DEBUG, "%s (%s) identified as: '%s'", applog(LOG_DEBUG, "%s (%s) identified as: '%s'",
bflsc->drv->dname, devpath, bflsc->drv->name); bflsc->drv->dname, bflsc->device_path, bflsc->drv->name);
if (!add_cgpu(bflsc)) if (!add_cgpu(bflsc))
goto unshin; goto unshin;
@ -971,16 +957,15 @@ unshin:
shin: shin:
free(bflsc->device_path);
free(bflsc->device_data); free(bflsc->device_data);
bflsc->device_data = NULL;
if (bflsc->name != blank) if (bflsc->name != blank) {
free(bflsc->name); free(bflsc->name);
bflsc->name = NULL;
}
if (bflsc->drv->copy) bflsc = usb_free_cgpu(bflsc);
free(bflsc->drv);
free(bflsc);
return false; return false;
} }

40
driver-bitforce.c

@ -166,26 +166,17 @@ failed:
static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found) static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{ {
char buf[BITFORCE_BUFSIZ+1]; char buf[BITFORCE_BUFSIZ+1];
char devpath[20];
int err, amount; int err, amount;
char *s; char *s;
struct timeval init_start, init_now; struct timeval init_start, init_now;
int init_sleep, init_count; int init_sleep, init_count;
bool ident_first; bool ident_first;
struct cgpu_info *bitforce = NULL; struct cgpu_info *bitforce = usb_alloc_cgpu(&bitforce_drv, 1);
bitforce = calloc(1, sizeof(*bitforce));
bitforce->drv = &bitforce_drv;
bitforce->deven = DEV_ENABLED;
bitforce->threads = 1;
if (!usb_init(bitforce, dev, found)) if (!usb_init(bitforce, dev, found))
goto shin; goto shin;
sprintf(devpath, "%d:%d",
(int)(bitforce->usbinfo.bus_number),
(int)(bitforce->usbinfo.device_address));
// Allow 2 complete attempts if the 1st time returns an unrecognised reply // Allow 2 complete attempts if the 1st time returns an unrecognised reply
ident_first = true; ident_first = true;
retry: retry:
@ -196,7 +187,7 @@ reinit:
bitforce_initialise(bitforce, false); bitforce_initialise(bitforce, false);
if ((err = usb_write(bitforce, BITFORCE_IDENTIFY, BITFORCE_IDENTIFY_LEN, &amount, C_REQUESTIDENTIFY)) < 0 || amount != BITFORCE_IDENTIFY_LEN) { 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)", applog(LOG_ERR, "%s detect (%s) send identify request failed (%d:%d)",
bitforce->drv->dname, devpath, amount, err); bitforce->drv->dname, bitforce->device_path, amount, err);
goto unshin; goto unshin;
} }
@ -206,7 +197,7 @@ reinit:
if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) { if (us_tdiff(&init_now, &init_start) <= REINIT_TIME_MAX) {
if (init_count == 2) { if (init_count == 2) {
applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying", applog(LOG_WARNING, "%s detect (%s) 2nd init failed (%d:%d) - retrying",
bitforce->drv->dname, devpath, amount, err); bitforce->drv->dname, bitforce->device_path, amount, err);
} }
nmsleep(init_sleep); nmsleep(init_sleep);
if ((init_sleep * 2) <= REINIT_TIME_MAX_MS) if ((init_sleep * 2) <= REINIT_TIME_MAX_MS)
@ -216,14 +207,14 @@ reinit:
if (init_count > 0) if (init_count > 0)
applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs", applog(LOG_WARNING, "%s detect (%s) init failed %d times %.2fs",
bitforce->drv->dname, devpath, init_count, tdiff(&init_now, &init_start)); bitforce->drv->dname, bitforce->device_path, init_count, tdiff(&init_now, &init_start));
if (err < 0) { if (err < 0) {
applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)", applog(LOG_ERR, "%s detect (%s) error identify reply (%d:%d)",
bitforce->drv->dname, devpath, amount, err); bitforce->drv->dname, bitforce->device_path, amount, err);
} else { } else {
applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)", applog(LOG_ERR, "%s detect (%s) empty identify reply (%d)",
bitforce->drv->dname, devpath, amount); bitforce->drv->dname, bitforce->device_path, amount);
} }
goto unshin; goto unshin;
@ -233,12 +224,12 @@ reinit:
if (unlikely(!strstr(buf, "SHA256"))) { if (unlikely(!strstr(buf, "SHA256"))) {
if (ident_first) { if (ident_first) {
applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...", applog(LOG_WARNING, "%s detect (%s) didn't recognise '%s' trying again ...",
bitforce->drv->dname, devpath, buf); bitforce->drv->dname, bitforce->device_path, buf);
ident_first = false; ident_first = false;
goto retry; goto retry;
} }
applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt", applog(LOG_ERR, "%s detect (%s) didn't recognise '%s' on 2nd attempt",
bitforce->drv->dname, devpath, buf); bitforce->drv->dname, bitforce->device_path, buf);
goto unshin; goto unshin;
} }
@ -260,7 +251,7 @@ reinit:
// We have a real BitForce! // We have a real BitForce!
applog(LOG_DEBUG, "%s (%s) identified as: '%s'", applog(LOG_DEBUG, "%s (%s) identified as: '%s'",
bitforce->drv->dname, devpath, bitforce->name); bitforce->drv->dname, bitforce->device_path, bitforce->name);
/* Initially enable support for nonce range and disable it later if it /* Initially enable support for nonce range and disable it later if it
* fails */ * fails */
@ -273,8 +264,6 @@ reinit:
bitforce->kname = KNAME_WORK; bitforce->kname = KNAME_WORK;
} }
bitforce->device_path = strdup(devpath);
if (!add_cgpu(bitforce)) if (!add_cgpu(bitforce))
goto unshin; goto unshin;
@ -290,15 +279,12 @@ unshin:
shin: shin:
free(bitforce->device_path); if (bitforce->name != blank) {
if (bitforce->name != blank)
free(bitforce->name); free(bitforce->name);
bitforce->name = NULL;
}
if (bitforce->drv->copy) bitforce = usb_free_cgpu(bitforce);
free(bitforce->drv);
free(bitforce);
return false; return false;
} }

26
driver-icarus.c

@ -445,7 +445,7 @@ static int icarus_get_nonce(struct cgpu_info *icarus, unsigned char *buf, struct
if (amt >= read_amount) if (amt >= read_amount)
return ICA_NONCE_OK; return ICA_NONCE_OK;
rc += SECTOMS(tdiff(&read_finish, &read_start)); rc = SECTOMS(tdiff(&read_finish, tv_start));
if (rc >= read_time) { if (rc >= read_time) {
if (amt > 0) if (amt > 0)
applog(LOG_DEBUG, "Icarus Read: Timeout reading for %d ms", rc); applog(LOG_DEBUG, "Icarus Read: Timeout reading for %d ms", rc);
@ -728,7 +728,6 @@ static void get_options(int this_option_offset, struct cgpu_info *icarus, int *b
static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices *found) static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{ {
int this_option_offset = ++option_offset; int this_option_offset = ++option_offset;
char devpath[20];
struct ICARUS_INFO *info; struct ICARUS_INFO *info;
struct timeval tv_start, tv_finish; struct timeval tv_start, tv_finish;
@ -751,24 +750,13 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
int ret, err, amount, tries; int ret, err, amount, tries;
bool ok; bool ok;
icarus = calloc(1, sizeof(struct cgpu_info)); icarus = usb_alloc_cgpu(&icarus_drv, 1);
if (unlikely(!icarus))
quit(1, "Failed to calloc icarus in icarus_detect_one");
icarus->drv = &icarus_drv;
icarus->deven = DEV_ENABLED;
icarus->threads = 1;
if (!usb_init(icarus, dev, found)) if (!usb_init(icarus, dev, found))
goto shin; goto shin;
get_options(this_option_offset, icarus, &baud, &work_division, &fpga_count); get_options(this_option_offset, icarus, &baud, &work_division, &fpga_count);
sprintf(devpath, "%d:%d",
(int)(icarus->usbinfo.bus_number),
(int)(icarus->usbinfo.device_address));
icarus->device_path = strdup(devpath);
hex2bin(ob_bin, golden_ob, sizeof(ob_bin)); hex2bin(ob_bin, golden_ob, sizeof(ob_bin));
tries = 2; tries = 2;
@ -794,7 +782,7 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
applog(LOG_ERR, applog(LOG_ERR,
"Icarus Detect: " "Icarus Detect: "
"Test failed at %s: get %s, should: %s", "Test failed at %s: get %s, should: %s",
devpath, nonce_hex, golden_nonce); icarus->device_path, nonce_hex, golden_nonce);
} }
} }
free(nonce_hex); free(nonce_hex);
@ -806,7 +794,7 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
applog(LOG_DEBUG, applog(LOG_DEBUG,
"Icarus Detect: " "Icarus Detect: "
"Test succeeded at %s: got %s", "Test succeeded at %s: got %s",
devpath, golden_nonce); icarus->device_path, golden_nonce);
/* We have a real Icarus! */ /* We have a real Icarus! */
if (!add_cgpu(icarus)) if (!add_cgpu(icarus))
@ -815,7 +803,7 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices
update_usb_stats(icarus); update_usb_stats(icarus);
applog(LOG_INFO, "%s%d: Found at %s", applog(LOG_INFO, "%s%d: Found at %s",
icarus->drv->name, icarus->device_id, devpath); icarus->drv->name, icarus->device_id, icarus->device_path);
applog(LOG_DEBUG, "%s%d: Init baud=%d work_division=%d fpga_count=%d", applog(LOG_DEBUG, "%s%d: Init baud=%d work_division=%d fpga_count=%d",
icarus->drv->name, icarus->device_id, baud, work_division, fpga_count); icarus->drv->name, icarus->device_id, baud, work_division, fpga_count);
@ -847,11 +835,9 @@ unshin:
usb_uninit(icarus); usb_uninit(icarus);
free(icarus->device_path);
shin: shin:
free(icarus); icarus = usb_free_cgpu(icarus);
return false; return false;
} }

67
driver-modminer.c

@ -115,13 +115,12 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
{ {
char buf[0x100+1]; char buf[0x100+1];
char *devname = NULL; char *devname = NULL;
char devpath[20]; char devpath[32];
int err, i, amount; int err, i, amount;
bool added = false; bool added = false;
struct cgpu_info *modminer = NULL; struct cgpu_info *modminer = usb_alloc_cgpu(&modminer_drv, 1);
modminer = calloc(1, sizeof(*modminer));
modminer->drv = &modminer_drv;
modminer->modminer_mutex = calloc(1, sizeof(*(modminer->modminer_mutex))); modminer->modminer_mutex = calloc(1, sizeof(*(modminer->modminer_mutex)));
mutex_init(modminer->modminer_mutex); mutex_init(modminer->modminer_mutex);
modminer->fpgaid = (char)0; modminer->fpgaid = (char)0;
@ -129,44 +128,40 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
if (!usb_init(modminer, dev, found)) if (!usb_init(modminer, dev, found))
goto shin; goto shin;
sprintf(devpath, "%d:%d",
(int)(modminer->usbinfo.bus_number),
(int)(modminer->usbinfo.device_address));
do_ping(modminer); do_ping(modminer);
if ((err = usb_write(modminer, MODMINER_GET_VERSION, 1, &amount, C_REQUESTVERSION)) < 0 || amount != 1) { if ((err = usb_write(modminer, MODMINER_GET_VERSION, 1, &amount, C_REQUESTVERSION)) < 0 || amount != 1) {
applog(LOG_ERR, "%s detect (%s) send version request failed (%d:%d)", applog(LOG_ERR, "%s detect (%s) send version request failed (%d:%d)",
modminer->drv->dname, devpath, amount, err); modminer->drv->dname, modminer->device_path, amount, err);
goto unshin; goto unshin;
} }
if ((err = usb_read_once(modminer, buf, sizeof(buf)-1, &amount, C_GETVERSION)) < 0 || amount < 1) { if ((err = usb_read_once(modminer, buf, sizeof(buf)-1, &amount, C_GETVERSION)) < 0 || amount < 1) {
if (err < 0) if (err < 0)
applog(LOG_ERR, "%s detect (%s) no version reply (%d)", applog(LOG_ERR, "%s detect (%s) no version reply (%d)",
modminer->drv->dname, devpath, err); modminer->drv->dname, modminer->device_path, err);
else else
applog(LOG_ERR, "%s detect (%s) empty version reply (%d)", applog(LOG_ERR, "%s detect (%s) empty version reply (%d)",
modminer->drv->dname, devpath, amount); modminer->drv->dname, modminer->device_path, amount);
applog(LOG_DEBUG, "%s detect (%s) check the firmware", applog(LOG_DEBUG, "%s detect (%s) check the firmware",
modminer->drv->dname, devpath); modminer->drv->dname, modminer->device_path);
goto unshin; goto unshin;
} }
buf[amount] = '\0'; buf[amount] = '\0';
devname = strdup(buf); devname = strdup(buf);
applog(LOG_DEBUG, "%s (%s) identified as: %s", modminer->drv->dname, devpath, devname); applog(LOG_DEBUG, "%s (%s) identified as: %s", modminer->drv->dname, modminer->device_path, devname);
if ((err = usb_write(modminer, MODMINER_FPGA_COUNT, 1, &amount, C_REQUESTFPGACOUNT) < 0 || amount != 1)) { if ((err = usb_write(modminer, MODMINER_FPGA_COUNT, 1, &amount, C_REQUESTFPGACOUNT) < 0 || amount != 1)) {
applog(LOG_ERR, "%s detect (%s) FPGA count request failed (%d:%d)", applog(LOG_ERR, "%s detect (%s) FPGA count request failed (%d:%d)",
modminer->drv->dname, devpath, amount, err); modminer->drv->dname, modminer->device_path, amount, err);
goto unshin; goto unshin;
} }
if ((err = usb_read(modminer, buf, 1, &amount, C_GETFPGACOUNT)) < 0 || amount != 1) { if ((err = usb_read(modminer, buf, 1, &amount, C_GETFPGACOUNT)) < 0 || amount != 1) {
applog(LOG_ERR, "%s detect (%s) no FPGA count reply (%d:%d)", applog(LOG_ERR, "%s detect (%s) no FPGA count reply (%d:%d)",
modminer->drv->dname, devpath, amount, err); modminer->drv->dname, modminer->device_path, amount, err);
goto unshin; goto unshin;
} }
@ -175,28 +170,25 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
if (buf[0] == 0) { if (buf[0] == 0) {
applog(LOG_ERR, "%s detect (%s) zero FPGA count from %s", applog(LOG_ERR, "%s detect (%s) zero FPGA count from %s",
modminer->drv->dname, devpath, devname); modminer->drv->dname, modminer->device_path, devname);
goto unshin; goto unshin;
} }
if (buf[0] < 1 || buf[0] > 4) { if (buf[0] < 1 || buf[0] > 4) {
applog(LOG_ERR, "%s detect (%s) invalid FPGA count (%u) from %s", applog(LOG_ERR, "%s detect (%s) invalid FPGA count (%u) from %s",
modminer->drv->dname, devpath, buf[0], devname); modminer->drv->dname, modminer->device_path, buf[0], devname);
goto unshin; goto unshin;
} }
applog(LOG_DEBUG, "%s (%s) %s has %u FPGAs", applog(LOG_DEBUG, "%s (%s) %s has %u FPGAs",
modminer->drv->dname, devpath, devname, buf[0]); modminer->drv->dname, modminer->device_path, devname, buf[0]);
modminer->name = devname; modminer->name = devname;
// TODO: test with 1 board missing in the middle and each end // TODO: test with 1 board missing in the middle and each end
// to see how that affects the sequence numbers // to see how that affects the sequence numbers
for (i = 0; i < buf[0]; i++) { for (i = 0; i < buf[0]; i++) {
struct cgpu_info *tmp = calloc(1, sizeof(*tmp)); struct cgpu_info *tmp = usb_copy_cgpu(modminer);
tmp->drv = copy_drv(modminer->drv);
tmp->name = devname;
sprintf(devpath, "%d:%d:%d", sprintf(devpath, "%d:%d:%d",
(int)(modminer->usbinfo.bus_number), (int)(modminer->usbinfo.bus_number),
@ -204,22 +196,16 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
i); i);
tmp->device_path = strdup(devpath); 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 // Only the first copy gets the already used stats
if (!added) if (added)
tmp->usbinfo.usbstat = modminer->usbinfo.usbstat; tmp->usbinfo.usbstat = USB_NOSTAT;
tmp->fpgaid = (char)i; tmp->fpgaid = (char)i;
tmp->modminer_mutex = modminer->modminer_mutex; tmp->modminer_mutex = modminer->modminer_mutex;
tmp->deven = DEV_ENABLED;
tmp->threads = 1;
if (!add_cgpu(tmp)) { if (!add_cgpu(tmp)) {
free(tmp->device_path); tmp = usb_free_cgpu_devlock(tmp, !added);
if (tmp->drv->copy)
free(tmp->drv);
free(tmp);
goto unshin; goto unshin;
} }
@ -228,10 +214,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
added = true; added = true;
} }
if (modminer->drv->copy) modminer = usb_free_cgpu_devlock(modminer, !added);
free(modminer->drv);
free(modminer);
return true; return true;
@ -240,13 +223,12 @@ unshin:
usb_uninit(modminer); usb_uninit(modminer);
shin: shin:
if (!added) if (!added) {
free(modminer->modminer_mutex); free(modminer->modminer_mutex);
modminer->modminer_mutex = NULL;
}
if (modminer->drv->copy) modminer = usb_free_cgpu_devlock(modminer, !added);
free(modminer->drv);
free(modminer);
if (added) if (added)
return true; return true;
@ -1111,6 +1093,7 @@ static void modminer_hw_error(struct thr_info *thr)
static void modminer_fpga_shutdown(struct thr_info *thr) static void modminer_fpga_shutdown(struct thr_info *thr)
{ {
free(thr->cgpu_data); free(thr->cgpu_data);
thr->cgpu_data = NULL;
} }
static char *modminer_set_device(struct cgpu_info *modminer, char *option, char *setting, char *replybuf) static char *modminer_set_device(struct cgpu_info *modminer, char *option, char *setting, char *replybuf)

151
usbutils.c

@ -451,7 +451,7 @@ struct cg_usb_stats {
#define SEQ1 1 #define SEQ1 1
static struct cg_usb_stats *usb_stats = NULL; static struct cg_usb_stats *usb_stats = NULL;
static int next_stat = 0; static int next_stat = USB_NOSTAT;
#define USB_STATS(sgpu, sta, fin, err, mode, cmd, seq) \ #define USB_STATS(sgpu, sta, fin, err, mode, cmd, seq) \
stats(cgpu, sta, fin, err, mode, cmd, seq) stats(cgpu, sta, fin, err, mode, cmd, seq)
@ -1339,6 +1339,10 @@ void usb_uninit(struct cgpu_info *cgpu)
cgpu->usbdev = free_cgusb(cgpu->usbdev); cgpu->usbdev = free_cgusb(cgpu->usbdev);
} }
/*
* N.B. this is always called inside
* DEVLOCK(cgpu);
*/
static void release_cgpu(struct cgpu_info *cgpu) static void release_cgpu(struct cgpu_info *cgpu)
{ {
struct cg_usb_device *cgusb = cgpu->usbdev; struct cg_usb_device *cgusb = cgpu->usbdev;
@ -1380,10 +1384,84 @@ static void release_cgpu(struct cgpu_info *cgpu)
cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address);
} }
// Currently only used by MMQ
struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig)
{
struct cgpu_info *copy = calloc(1, sizeof(*copy));
if (unlikely(!copy))
quit(1, "Failed to calloc cgpu for %s in usb_copy_cgpu", orig->drv->dname);
copy->name = orig->name;
copy->drv = copy_drv(orig->drv);
copy->deven = orig->deven;
copy->threads = orig->threads;
copy->usbdev = orig->usbdev;
memcpy(&(copy->usbinfo), &(orig->usbinfo), sizeof(copy->usbinfo));
copy->usbinfo.nodev = (copy->usbdev == NULL);
copy->usbinfo.devlock = orig->usbinfo.devlock;
return copy;
}
struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads)
{
struct cgpu_info *cgpu = calloc(1, sizeof(*cgpu));
if (unlikely(!cgpu))
quit(1, "Failed to calloc cgpu for %s in usb_alloc_cgpu", drv->dname);
cgpu->drv = drv;
cgpu->deven = DEV_ENABLED;
cgpu->threads = threads;
cgpu->usbinfo.nodev = true;
cgpu->usbinfo.devlock = calloc(1, sizeof(*(cgpu->usbinfo.devlock)));
if (unlikely(!cgpu->usbinfo.devlock))
quit(1, "Failed to calloc devlock for %s in usb_alloc_cgpu", drv->dname);
rwlock_init(cgpu->usbinfo.devlock);
return cgpu;
}
struct cgpu_info *usb_free_cgpu_devlock(struct cgpu_info *cgpu, bool free_devlock)
{
if (cgpu->drv->copy)
free(cgpu->drv);
free(cgpu->device_path);
if (free_devlock)
free(cgpu->usbinfo.devlock);
free(cgpu);
return NULL;
}
#define USB_INIT_FAIL 0 #define USB_INIT_FAIL 0
#define USB_INIT_OK 1 #define USB_INIT_OK 1
#define USB_INIT_IGNORE 2 #define USB_INIT_IGNORE 2
/*
* WARNING - these assume DEVLOCK(cgpu) is called first and
* DEVUNLOCK(cgpu) in called in the same function inside the same brace level
* You must call DEVUNLOCK(cgpu) before exiting the function or it will leave
* the thread Cancelability unrestored
*/
#define DEVLOCK(cgpu) int _pth_state; \
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &_pth_state); \
wr_lock(cgpu->usbinfo.devlock);
#define DEVUNLOCK(cgpu) wr_unlock(cgpu->usbinfo.devlock); \
pthread_setcanceltype(_pth_state, NULL);
static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found) static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found)
{ {
struct cg_usb_device *cgusb = NULL; struct cg_usb_device *cgusb = NULL;
@ -1391,15 +1469,23 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
const struct libusb_interface_descriptor *idesc; const struct libusb_interface_descriptor *idesc;
const struct libusb_endpoint_descriptor *epdesc; const struct libusb_endpoint_descriptor *epdesc;
unsigned char strbuf[STRBUFLEN+1]; unsigned char strbuf[STRBUFLEN+1];
char devpath[32];
char devstr[STRBUFLEN+1]; char devstr[STRBUFLEN+1];
int err, i, j, k; int err, i, j, k;
int bad = USB_INIT_FAIL; int bad = USB_INIT_FAIL;
DEVLOCK(cgpu);
cgpu->usbinfo.bus_number = libusb_get_bus_number(dev); cgpu->usbinfo.bus_number = libusb_get_bus_number(dev);
cgpu->usbinfo.device_address = libusb_get_device_address(dev); cgpu->usbinfo.device_address = libusb_get_device_address(dev);
sprintf(devstr, "- %s device %d:%d", found->name, sprintf(devpath, "%d:%d",
cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address); (int)(cgpu->usbinfo.bus_number),
(int)(cgpu->usbinfo.device_address));
cgpu->device_path = strdup(devpath);
sprintf(devstr, "- %s device %s", found->name, devpath);
cgusb = calloc(1, sizeof(*cgusb)); cgusb = calloc(1, sizeof(*cgusb));
if (unlikely(!cgusb)) if (unlikely(!cgusb))
@ -1616,6 +1702,7 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
cgusb->manuf_string, cgusb->serial_string); cgusb->manuf_string, cgusb->serial_string);
cgpu->usbdev = cgusb; cgpu->usbdev = cgusb;
cgpu->usbinfo.nodev = false;
libusb_free_config_descriptor(config); libusb_free_config_descriptor(config);
@ -1627,6 +1714,8 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
cgpu->drv->name = (char *)(found->name); cgpu->drv->name = (char *)(found->name);
} }
DEVUNLOCK(cgpu);
return USB_INIT_OK; return USB_INIT_OK;
cldame: cldame:
@ -1640,6 +1729,8 @@ dame:
cgusb = free_cgusb(cgusb); cgusb = free_cgusb(cgusb);
DEVUNLOCK(cgpu);
return bad; return bad;
} }
@ -1876,7 +1967,7 @@ struct api_data *api_usb_stats(__maybe_unused int *count)
int cmdseq; int cmdseq;
char modes_s[32]; char modes_s[32];
if (next_stat == 0) if (next_stat == USB_NOSTAT)
return NULL; return NULL;
while (*count < next_stat * C_MAX * 2) { while (*count < next_stat * C_MAX * 2) {
@ -1949,21 +2040,25 @@ static void newstats(struct cgpu_info *cgpu)
int i; int i;
mutex_lock(&cgusb_lock); mutex_lock(&cgusb_lock);
cgpu->usbinfo.usbstat = ++next_stat;
mutex_unlock(&cgusb_lock);
usb_stats = realloc(usb_stats, sizeof(*usb_stats) * next_stat); cgpu->usbinfo.usbstat = next_stat + 1;
usb_stats = realloc(usb_stats, sizeof(*usb_stats) * (next_stat+1));
if (unlikely(!usb_stats)) if (unlikely(!usb_stats))
quit(1, "USB failed to realloc usb_stats %d", next_stat); quit(1, "USB failed to realloc usb_stats %d", next_stat+1);
usb_stats[next_stat-1].name = cgpu->drv->name; usb_stats[next_stat].name = cgpu->drv->name;
usb_stats[next_stat-1].device_id = -1; usb_stats[next_stat].device_id = -1;
usb_stats[next_stat-1].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2); usb_stats[next_stat].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2);
if (unlikely(!usb_stats[next_stat-1].details)) if (unlikely(!usb_stats[next_stat].details))
quit(1, "USB failed to calloc details for %d", next_stat); quit(1, "USB failed to calloc details for %d", next_stat+1);
for (i = 1; i < C_MAX * 2; i += 2) for (i = 1; i < C_MAX * 2; i += 2)
usb_stats[next_stat-1].details[i].seq = 1; usb_stats[next_stat].details[i].seq = 1;
next_stat++;
mutex_unlock(&cgusb_lock);
} }
#endif #endif
@ -2084,11 +2179,15 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
unsigned char usbbuf[USB_MAX_READ+4], *ptr; unsigned char usbbuf[USB_MAX_READ+4], *ptr;
size_t usbbufread; size_t usbbufread;
DEVLOCK(cgpu);
if (cgpu->usbinfo.nodev) { if (cgpu->usbinfo.nodev) {
*buf = '\0'; *buf = '\0';
*processed = 0; *processed = 0;
USB_REJECT(cgpu, MODE_BULK_READ); USB_REJECT(cgpu, MODE_BULK_READ);
DEVUNLOCK(cgpu);
return LIBUSB_ERROR_NO_DEVICE; return LIBUSB_ERROR_NO_DEVICE;
} }
@ -2191,6 +2290,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
if (NODEV(err)) if (NODEV(err))
release_cgpu(cgpu); release_cgpu(cgpu);
DEVUNLOCK(cgpu);
return err; return err;
} }
@ -2306,6 +2407,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
if (NODEV(err)) if (NODEV(err))
release_cgpu(cgpu); release_cgpu(cgpu);
DEVUNLOCK(cgpu);
return err; return err;
} }
@ -2321,6 +2424,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
__maybe_unused bool first = true; __maybe_unused bool first = true;
int err, sent, tot; int err, sent, tot;
DEVLOCK(cgpu);
USBDEBUG("USB debug: _usb_write(%s (nodev=%s),ep=%d,buf='%s',bufsiz=%zu,proc=%p,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), ep, (char *)str_text(buf), bufsiz, processed, timeout, usb_cmdname(cmd)); USBDEBUG("USB debug: _usb_write(%s (nodev=%s),ep=%d,buf='%s',bufsiz=%zu,proc=%p,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), ep, (char *)str_text(buf), bufsiz, processed, timeout, usb_cmdname(cmd));
*processed = 0; *processed = 0;
@ -2328,6 +2433,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
if (cgpu->usbinfo.nodev) { if (cgpu->usbinfo.nodev) {
USB_REJECT(cgpu, MODE_BULK_WRITE); USB_REJECT(cgpu, MODE_BULK_WRITE);
DEVUNLOCK(cgpu);
return LIBUSB_ERROR_NO_DEVICE; return LIBUSB_ERROR_NO_DEVICE;
} }
@ -2380,6 +2487,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
if (NODEV(err)) if (NODEV(err))
release_cgpu(cgpu); release_cgpu(cgpu);
DEVUNLOCK(cgpu);
return err; return err;
} }
@ -2392,11 +2501,15 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest
uint32_t *buf = NULL; uint32_t *buf = NULL;
int err, i, bufsiz; int err, i, bufsiz;
DEVLOCK(cgpu);
USBDEBUG("USB debug: _usb_transfer(%s (nodev=%s),type=%"PRIu8",req=%"PRIu8",value=%"PRIu16",index=%"PRIu16",siz=%d,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), request_type, bRequest, wValue, wIndex, siz, timeout, usb_cmdname(cmd)); USBDEBUG("USB debug: _usb_transfer(%s (nodev=%s),type=%"PRIu8",req=%"PRIu8",value=%"PRIu16",index=%"PRIu16",siz=%d,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), request_type, bRequest, wValue, wIndex, siz, timeout, usb_cmdname(cmd));
if (cgpu->usbinfo.nodev) { if (cgpu->usbinfo.nodev) {
USB_REJECT(cgpu, MODE_CTRL_WRITE); USB_REJECT(cgpu, MODE_CTRL_WRITE);
DEVUNLOCK(cgpu);
return LIBUSB_ERROR_NO_DEVICE; return LIBUSB_ERROR_NO_DEVICE;
} }
usbdev = cgpu->usbdev; usbdev = cgpu->usbdev;
@ -2433,6 +2546,8 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest
if (NODEV(err)) if (NODEV(err))
release_cgpu(cgpu); release_cgpu(cgpu);
DEVUNLOCK(cgpu);
return err; return err;
} }
@ -2444,11 +2559,15 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe
#endif #endif
int err; int err;
DEVLOCK(cgpu);
USBDEBUG("USB debug: _usb_transfer_read(%s (nodev=%s),type=%"PRIu8",req=%"PRIu8",value=%"PRIu16",index=%"PRIu16",bufsiz=%d,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), request_type, bRequest, wValue, wIndex, bufsiz, timeout, usb_cmdname(cmd)); USBDEBUG("USB debug: _usb_transfer_read(%s (nodev=%s),type=%"PRIu8",req=%"PRIu8",value=%"PRIu16",index=%"PRIu16",bufsiz=%d,timeout=%u,cmd=%s)", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), request_type, bRequest, wValue, wIndex, bufsiz, timeout, usb_cmdname(cmd));
if (cgpu->usbinfo.nodev) { if (cgpu->usbinfo.nodev) {
USB_REJECT(cgpu, MODE_CTRL_READ); USB_REJECT(cgpu, MODE_CTRL_READ);
DEVUNLOCK(cgpu);
return LIBUSB_ERROR_NO_DEVICE; return LIBUSB_ERROR_NO_DEVICE;
} }
usbdev = cgpu->usbdev; usbdev = cgpu->usbdev;
@ -2473,6 +2592,8 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe
} else if (NODEV(err)) } else if (NODEV(err))
release_cgpu(cgpu); release_cgpu(cgpu);
DEVUNLOCK(cgpu);
return err; return err;
} }
@ -2586,7 +2707,9 @@ void usb_cleanup()
case DRIVER_MODMINER: case DRIVER_MODMINER:
case DRIVER_ICARUS: case DRIVER_ICARUS:
case DRIVER_AVALON: case DRIVER_AVALON:
wr_lock(cgpu->usbinfo.devlock);
release_cgpu(cgpu); release_cgpu(cgpu);
wr_unlock(cgpu->usbinfo.devlock);
count++; count++;
break; break;
default: default:

17
usbutils.h

@ -177,6 +177,8 @@ struct cg_usb_device {
uint32_t bufamt; uint32_t bufamt;
}; };
#define USB_NOSTAT 0
struct cg_usb_info { struct cg_usb_info {
uint8_t bus_number; uint8_t bus_number;
uint8_t device_address; uint8_t device_address;
@ -186,6 +188,17 @@ struct cg_usb_info {
struct timeval last_nodev; struct timeval last_nodev;
uint32_t ioerr_count; uint32_t ioerr_count;
uint32_t continuous_ioerr_count; uint32_t continuous_ioerr_count;
/*
* for nodev and cgusb access (read and write)
* it's a pointer so MMQ can have it in multiple devices
*
* N.B. general mining code doesn't need to use the read
* lock for 'nodev' if it calls a usb_read/write/etc function
* that uses the lock - however, all usbutils code MUST use it
* to avoid devices disappearing while in use by multiple threads
*/
pthread_rwlock_t *devlock;
}; };
enum usb_cmds { enum usb_cmds {
@ -258,6 +271,10 @@ struct cgpu_info;
void usb_all(int level); void usb_all(int level);
const char *usb_cmdname(enum usb_cmds cmd); const char *usb_cmdname(enum usb_cmds cmd);
void usb_applog(struct cgpu_info *bflsc, enum usb_cmds cmd, char *msg, int amount, int err); void usb_applog(struct cgpu_info *bflsc, enum usb_cmds cmd, char *msg, int amount, int err);
struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig);
struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads);
struct cgpu_info *usb_free_cgpu_devlock(struct cgpu_info *cgpu, bool free_devlock);
#define usb_free_cgpu(cgpu) usb_free_cgpu_devlock(cgpu, true)
void usb_uninit(struct cgpu_info *cgpu); void usb_uninit(struct cgpu_info *cgpu);
bool usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct usb_find_devices *found); 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 *)); void usb_detect(struct device_drv *drv, bool (*device_detect)(struct libusb_device *, struct usb_find_devices *));

Loading…
Cancel
Save