Browse Source

USB automatically handle losing the device and report nodev in the API

nfactor-troky
Kano 12 years ago
parent
commit
34bcc1c66d
  1. 1
      API-README
  2. 14
      api.c
  3. 30
      driver-bitforce.c
  4. 29
      driver-modminer.c
  5. 1
      miner.h
  6. 104
      usbutils.c
  7. 6
      usbutils.h

1
API-README

@ -419,6 +419,7 @@ Added API commands: @@ -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

@ -391,6 +391,7 @@ static const char *JSON_PARAMETER = "parameter"; @@ -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 { @@ -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 @@ -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 @@ -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) {

30
driver-bitforce.c

@ -1,5 +1,5 @@ @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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_ @@ -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))

29
driver-modminer.c

@ -1,5 +1,5 @@ @@ -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) @@ -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 @@ -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) @@ -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) @@ -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) @@ -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) @@ -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_ @@ -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_ @@ -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

@ -399,6 +399,7 @@ struct cgpu_info { @@ -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

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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; @@ -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() @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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 @@ -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 @@ -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 @@ -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: @@ -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 @@ -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 @@ -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 @@ -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 @@ -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;
}

6
usbutils.h

@ -1,5 +1,5 @@ @@ -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 { @@ -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; @@ -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…
Cancel
Save