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

51
usbutils.c

@ -1339,6 +1339,10 @@ void usb_uninit(struct cgpu_info *cgpu) @@ -1339,6 +1339,10 @@ void usb_uninit(struct cgpu_info *cgpu)
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)
{
struct cg_usb_device *cgusb = cgpu->usbdev;
@ -1399,6 +1403,8 @@ struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig) @@ -1399,6 +1403,8 @@ struct cgpu_info *usb_copy_cgpu(struct cgpu_info *orig)
copy->usbinfo.nodev = (copy->usbdev != NULL);
copy->usbinfo.devlock = orig->usbinfo.devlock;
return copy;
}
@ -1415,16 +1421,25 @@ struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int threads) @@ -1415,16 +1421,25 @@ struct cgpu_info *usb_alloc_cgpu(struct device_drv *drv, int 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(struct cgpu_info *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;
@ -1446,6 +1461,8 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u @@ -1446,6 +1461,8 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
int err, i, j, k;
int bad = USB_INIT_FAIL;
wr_lock(cgpu->usbinfo.devlock);
cgpu->usbinfo.bus_number = libusb_get_bus_number(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 @@ -1684,6 +1701,8 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u
cgpu->drv->name = (char *)(found->name);
}
wr_unlock(cgpu->usbinfo.devlock);
return USB_INIT_OK;
cldame:
@ -1697,6 +1716,8 @@ dame: @@ -1697,6 +1716,8 @@ dame:
cgusb = free_cgusb(cgusb);
wr_unlock(cgpu->usbinfo.devlock);
return bad;
}
@ -2145,11 +2166,15 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro @@ -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;
size_t usbbufread;
wr_lock(cgpu->usbinfo.devlock);
if (cgpu->usbinfo.nodev) {
*buf = '\0';
*processed = 0;
USB_REJECT(cgpu, MODE_BULK_READ);
wr_unlock(cgpu->usbinfo.devlock);
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 @@ -2252,6 +2277,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
if (NODEV(err))
release_cgpu(cgpu);
wr_unlock(cgpu->usbinfo.devlock);
return err;
}
@ -2367,6 +2394,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro @@ -2367,6 +2394,8 @@ int _usb_read(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pro
if (NODEV(err))
release_cgpu(cgpu);
wr_unlock(cgpu->usbinfo.devlock);
return err;
}
@ -2382,6 +2411,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr @@ -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;
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));
*processed = 0;
@ -2389,6 +2420,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr @@ -2389,6 +2420,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
if (cgpu->usbinfo.nodev) {
USB_REJECT(cgpu, MODE_BULK_WRITE);
wr_unlock(cgpu->usbinfo.devlock);
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 @@ -2441,6 +2474,8 @@ int _usb_write(struct cgpu_info *cgpu, int ep, char *buf, size_t bufsiz, int *pr
if (NODEV(err))
release_cgpu(cgpu);
wr_unlock(cgpu->usbinfo.devlock);
return err;
}
@ -2453,11 +2488,15 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest @@ -2453,11 +2488,15 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest
uint32_t *buf = NULL;
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));
if (cgpu->usbinfo.nodev) {
USB_REJECT(cgpu, MODE_CTRL_WRITE);
wr_unlock(cgpu->usbinfo.devlock);
return LIBUSB_ERROR_NO_DEVICE;
}
usbdev = cgpu->usbdev;
@ -2494,6 +2533,8 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest @@ -2494,6 +2533,8 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest
if (NODEV(err))
release_cgpu(cgpu);
wr_unlock(cgpu->usbinfo.devlock);
return err;
}
@ -2505,11 +2546,15 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe @@ -2505,11 +2546,15 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe
#endif
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));
if (cgpu->usbinfo.nodev) {
USB_REJECT(cgpu, MODE_CTRL_READ);
wr_unlock(cgpu->usbinfo.devlock);
return LIBUSB_ERROR_NO_DEVICE;
}
usbdev = cgpu->usbdev;
@ -2534,6 +2579,8 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe @@ -2534,6 +2579,8 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe
} else if (NODEV(err))
release_cgpu(cgpu);
wr_unlock(cgpu->usbinfo.devlock);
return err;
}
@ -2647,7 +2694,9 @@ void usb_cleanup() @@ -2647,7 +2694,9 @@ void usb_cleanup()
case DRIVER_MODMINER:
case DRIVER_ICARUS:
case DRIVER_AVALON:
wr_lock(cgpu->usbinfo.devlock);
release_cgpu(cgpu);
wr_unlock(cgpu->usbinfo.devlock);
count++;
break;
default:

14
usbutils.h

@ -188,6 +188,17 @@ struct cg_usb_info { @@ -188,6 +188,17 @@ struct cg_usb_info {
struct timeval last_nodev;
uint32_t 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 {
@ -262,7 +273,8 @@ const char *usb_cmdname(enum usb_cmds cmd); @@ -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);
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(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);
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 *));

Loading…
Cancel
Save