Browse Source

ubsutils lock all access to nodev and cgusb

nfactor-troky
Kano 11 years ago
parent
commit
7d35c6921e
  1. 4
      driver-modminer.c
  2. 51
      usbutils.c
  3. 14
      usbutils.h

4
driver-modminer.c

@ -205,7 +205,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic
tmp->modminer_mutex = modminer->modminer_mutex; tmp->modminer_mutex = modminer->modminer_mutex;
if (!add_cgpu(tmp)) { if (!add_cgpu(tmp)) {
tmp = usb_free_cgpu(tmp); tmp = usb_free_cgpu_devlock(tmp, !added);
goto unshin; goto unshin;
} }
@ -228,7 +228,7 @@ shin:
modminer->modminer_mutex = NULL; modminer->modminer_mutex = NULL;
} }
modminer = usb_free_cgpu(modminer); modminer = usb_free_cgpu_devlock(modminer, !added);
if (added) if (added)
return true; return true;

51
usbutils.c

@ -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
* wr_lock(cgpu->usbinfo.devlock);
*/
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;
@ -1399,6 +1403,8 @@ struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig)
copy->usbinfo.nodev = (copy->usbdev != NULL); copy->usbinfo.nodev = (copy->usbdev != NULL);
copy->usbinfo.devlock = orig->usbinfo.devlock;
return copy; return copy;
} }
@ -1415,16 +1421,25 @@ struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads)
cgpu->usbinfo.nodev = true; 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; return cgpu;
} }
struct cgpu_info *usb_free_cgpu(struct cgpu_info *cgpu) struct cgpu_info *usb_free_cgpu_devlock(struct cgpu_info *cgpu, bool free_devlock)
{ {
if (cgpu->drv->copy) if (cgpu->drv->copy)
free(cgpu->drv); free(cgpu->drv);
free(cgpu->device_path); free(cgpu->device_path);
if (free_devlock)
free(cgpu->usbinfo.devlock);
free(cgpu); free(cgpu);
return NULL; return NULL;
@ -1446,6 +1461,8 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
int err, i, j, k; int err, i, j, k;
int bad = USB_INIT_FAIL; int bad = USB_INIT_FAIL;
wr_lock(cgpu->usbinfo.devlock);
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);
@ -1684,6 +1701,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);
} }
wr_unlock(cgpu->usbinfo.devlock);
return USB_INIT_OK; return USB_INIT_OK;
cldame: cldame:
@ -1697,6 +1716,8 @@ dame:
cgusb = free_cgusb(cgusb); cgusb = free_cgusb(cgusb);
wr_unlock(cgpu->usbinfo.devlock);
return bad; return bad;
} }
@ -2145,11 +2166,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;
wr_lock(cgpu->usbinfo.devlock);
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);
wr_unlock(cgpu->usbinfo.devlock);
return LIBUSB_ERROR_NO_DEVICE; return LIBUSB_ERROR_NO_DEVICE;
} }
@ -2252,6 +2277,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);
wr_unlock(cgpu->usbinfo.devlock);
return err; return err;
} }
@ -2367,6 +2394,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);
wr_unlock(cgpu->usbinfo.devlock);
return err; return err;
} }
@ -2382,6 +2411,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;
wr_lock(cgpu->usbinfo.devlock);
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;
@ -2389,6 +2420,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);
wr_unlock(cgpu->usbinfo.devlock);
return LIBUSB_ERROR_NO_DEVICE; return LIBUSB_ERROR_NO_DEVICE;
} }
@ -2441,6 +2474,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);
wr_unlock(cgpu->usbinfo.devlock);
return err; return err;
} }
@ -2453,11 +2488,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;
wr_lock(cgpu->usbinfo.devlock);
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);
wr_unlock(cgpu->usbinfo.devlock);
return LIBUSB_ERROR_NO_DEVICE; return LIBUSB_ERROR_NO_DEVICE;
} }
usbdev = cgpu->usbdev; usbdev = cgpu->usbdev;
@ -2494,6 +2533,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);
wr_unlock(cgpu->usbinfo.devlock);
return err; return err;
} }
@ -2505,11 +2546,15 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe
#endif #endif
int err; int err;
wr_lock(cgpu->usbinfo.devlock);
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);
wr_unlock(cgpu->usbinfo.devlock);
return LIBUSB_ERROR_NO_DEVICE; return LIBUSB_ERROR_NO_DEVICE;
} }
usbdev = cgpu->usbdev; usbdev = cgpu->usbdev;
@ -2534,6 +2579,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);
wr_unlock(cgpu->usbinfo.devlock);
return err; return err;
} }
@ -2647,7 +2694,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:

14
usbutils.h

@ -188,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 {
@ -262,7 +273,8 @@ 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_copy_cgpu(struct cgpu_info *orig);
struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads); struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads);
struct cgpu_info *usb_free_cgpu(struct cgpu_info *cgpu); 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