diff --git a/driver-avalon.c b/driver-avalon.c index ddb7be7d..610483b1 100644 --- a/driver-avalon.c +++ b/driver-avalon.c @@ -578,17 +578,13 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found bool configured; int ret; - avalon = calloc(1, sizeof(struct cgpu_info)); - if (unlikely(!avalon)) - quit(1, "Failed to calloc avalon in avalon_detect_one");; - avalon->drv = &avalon_drv; - avalon->threads = AVALON_MINER_THREADS; + avalon = usb_alloc_cgpu(&avalon_drv, AVALON_MINER_THREADS); configured = get_options(this_option_offset, &baud, &miner_count, &asic_count, &timeout, &frequency); if (!usb_init(avalon, dev, found)) - return false; + goto shin; /* Even though this is an FTDI type chip, we want to do the parsing * all ourselves so set it to std usb type */ @@ -602,11 +598,10 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found avalon_initialise(avalon); avalon->device_path = strdup(devpath); - add_cgpu(avalon); avalon->device_data = calloc(sizeof(struct avalon_info), 1); 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; if (configured) { @@ -635,10 +630,13 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found info->temp_old = 0; ret = avalon_reset(avalon, true); - if (ret && !configured) { - usb_uninit(avalon); - return false; - } + if (ret && !configured) + goto unshin; + + if (!add_cgpu(avalon)) + goto unshin; + + update_usb_stats(avalon); avalon_idle(avalon, info); @@ -648,6 +646,22 @@ static bool avalon_detect_one(libusb_device *dev, struct usb_find_devices *found info->frequency); return true; + +unshin: + + usb_uninit(avalon); + +shin: + + if (avalon->device_data) + free(avalon->device_data); + + if (avalon->device_path) + free(avalon->device_path); + + avalon = usb_free_cgpu(avalon); + + return false; } static void avalon_detect(void) diff --git a/driver-bflsc.c b/driver-bflsc.c index 2b13ede6..501fa56d 100644 --- a/driver-bflsc.c +++ b/driver-bflsc.c @@ -810,13 +810,7 @@ static bool bflsc_detect_one(struct libusb_device *dev, struct usb_find_devices char *newname; uint16_t latency; - struct cgpu_info *bflsc = calloc(1, sizeof(*bflsc)); - - if (unlikely(!bflsc)) - quit(1, "Failed to calloc bflsc in bflsc_detect_one"); - bflsc->drv = &bflsc_drv; - bflsc->deven = DEV_ENABLED; - bflsc->threads = 1; + struct cgpu_info *bflsc = usb_alloc_cgpu(&bflsc_drv, 1); sc_info = calloc(1, sizeof(*sc_info)); if (unlikely(!sc_info)) @@ -980,7 +974,7 @@ shin: if (bflsc->drv->copy) free(bflsc->drv); - free(bflsc); + bflsc = usb_free_cgpu(bflsc); return false; } diff --git a/driver-bitforce.c b/driver-bitforce.c index c845285e..7e2f1d1e 100644 --- a/driver-bitforce.c +++ b/driver-bitforce.c @@ -173,11 +173,7 @@ static bool bitforce_detect_one(struct libusb_device *dev, struct usb_find_devic int init_sleep, init_count; bool ident_first; - struct cgpu_info *bitforce = NULL; - bitforce = calloc(1, sizeof(*bitforce)); - bitforce->drv = &bitforce_drv; - bitforce->deven = DEV_ENABLED; - bitforce->threads = 1; + struct cgpu_info *bitforce = usb_alloc_cgpu(&bitforce_drv, 1); if (!usb_init(bitforce, dev, found)) goto shin; @@ -298,7 +294,7 @@ shin: if (bitforce->drv->copy) free(bitforce->drv); - free(bitforce); + bitforce = usb_free_cgpu(bitforce); return false; } diff --git a/driver-icarus.c b/driver-icarus.c index a6c6fb0e..d854101d 100644 --- a/driver-icarus.c +++ b/driver-icarus.c @@ -751,12 +751,7 @@ static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices int ret, err, amount, tries; bool ok; - icarus = calloc(1, sizeof(struct cgpu_info)); - if (unlikely(!icarus)) - quit(1, "Failed to calloc icarus in icarus_detect_one"); - icarus->drv = &icarus_drv; - icarus->deven = DEV_ENABLED; - icarus->threads = 1; + icarus = usb_alloc_cgpu(&icarus_drv, 1); if (!usb_init(icarus, dev, found)) goto shin; @@ -851,7 +846,7 @@ unshin: shin: - free(icarus); + icarus = usb_free_cgpu(icarus); return false; } diff --git a/driver-modminer.c b/driver-modminer.c index 8d609dfb..5df05603 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -119,9 +119,8 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic int err, i, amount; bool added = false; - struct cgpu_info *modminer = NULL; - modminer = calloc(1, sizeof(*modminer)); - modminer->drv = &modminer_drv; + struct cgpu_info *modminer = usb_alloc_cgpu(&modminer_drv, 1); + modminer->modminer_mutex = calloc(1, sizeof(*(modminer->modminer_mutex))); mutex_init(modminer->modminer_mutex); modminer->fpgaid = (char)0; @@ -193,10 +192,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic // TODO: test with 1 board missing in the middle and each end // to see how that affects the sequence numbers for (i = 0; i < buf[0]; i++) { - struct cgpu_info *tmp = calloc(1, sizeof(*tmp)); - - tmp->drv = copy_drv(modminer->drv); - tmp->name = devname; + struct cgpu_info *tmp = usb_copy_cgpu(modminer); sprintf(devpath, "%d:%d:%d", (int)(modminer->usbinfo.bus_number), @@ -204,22 +200,17 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic i); 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 - if (!added) - tmp->usbinfo.usbstat = modminer->usbinfo.usbstat; + if (added) + tmp->usbinfo.usbstat = USB_NOSTAT; + tmp->fpgaid = (char)i; tmp->modminer_mutex = modminer->modminer_mutex; - tmp->deven = DEV_ENABLED; - tmp->threads = 1; if (!add_cgpu(tmp)) { free(tmp->device_path); - if (tmp->drv->copy) - free(tmp->drv); - free(tmp); + tmp = usb_free_cgpu(tmp); goto unshin; } @@ -228,10 +219,7 @@ static bool modminer_detect_one(struct libusb_device *dev, struct usb_find_devic added = true; } - if (modminer->drv->copy) - free(modminer->drv); - - free(modminer); + modminer = usb_free_cgpu(modminer); return true; @@ -243,10 +231,7 @@ shin: if (!added) free(modminer->modminer_mutex); - if (modminer->drv->copy) - free(modminer->drv); - - free(modminer); + modminer = usb_free_cgpu(modminer); if (added) return true; diff --git a/usbutils.c b/usbutils.c index 53430fa7..1a0e1182 100644 --- a/usbutils.c +++ b/usbutils.c @@ -451,7 +451,7 @@ struct cg_usb_stats { #define SEQ1 1 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) \ stats(cgpu, sta, fin, err, mode, cmd, seq) @@ -1380,6 +1380,54 @@ static void release_cgpu(struct cgpu_info *cgpu) 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); + + 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; + + return cgpu; +} + +struct cgpu_info *usb_free_cgpu(struct cgpu_info *cgpu) +{ + if (cgpu->drv->copy) + free(cgpu->drv); + + free(cgpu); + + return NULL; +} + #define USB_INIT_FAIL 0 #define USB_INIT_OK 1 #define USB_INIT_IGNORE 2 @@ -1616,6 +1664,7 @@ static int _usb_init(struct cgpu_info *cgpu, struct libusb_device *dev, struct u cgusb->manuf_string, cgusb->serial_string); cgpu->usbdev = cgusb; + cgpu->usbinfo.nodev = false; libusb_free_config_descriptor(config); @@ -1876,7 +1925,7 @@ struct api_data *api_usb_stats(__maybe_unused int *count) int cmdseq; char modes_s[32]; - if (next_stat == 0) + if (next_stat == USB_NOSTAT) return NULL; while (*count < next_stat * C_MAX * 2) { @@ -1949,21 +1998,25 @@ static void newstats(struct cgpu_info *cgpu) int i; 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)) - 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-1].device_id = -1; - usb_stats[next_stat-1].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2); - if (unlikely(!usb_stats[next_stat-1].details)) - quit(1, "USB failed to calloc details for %d", next_stat); + usb_stats[next_stat].name = cgpu->drv->name; + usb_stats[next_stat].device_id = -1; + usb_stats[next_stat].details = calloc(1, sizeof(struct cg_usb_stats_details) * C_MAX * 2); + if (unlikely(!usb_stats[next_stat].details)) + quit(1, "USB failed to calloc details for %d", next_stat+1); 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 diff --git a/usbutils.h b/usbutils.h index 199cbb14..96f2b84b 100644 --- a/usbutils.h +++ b/usbutils.h @@ -177,6 +177,8 @@ struct cg_usb_device { uint32_t bufamt; }; +#define USB_NOSTAT 0 + struct cg_usb_info { uint8_t bus_number; uint8_t device_address; @@ -258,6 +260,9 @@ struct cgpu_info; void usb_all(int level); 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); 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 *));