mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-22 20:44:19 +00:00
USB automatically handle losing the device and report nodev in the API
This commit is contained in:
parent
4f460ca72d
commit
34bcc1c66d
@ -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
|
||||
|
||||
----------
|
||||
|
||||
|
14
api.c
14
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) {
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
||||
|
1
miner.h
1
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;
|
||||
|
104
usbutils.c
104
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user