Commit 9287ee90f6fd54927042eb5ea4a061e66eebbc05

Kano 2013-06-10T15:22:37

USB control creation and free of cgpu

diff --git a/driver-avalon.c b/driver-avalon.c
index ddb7be7..610483b 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 2b13ede..501fa56 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 c845285..7e2f1d1 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 a6c6fb0..d854101 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 8d609df..5df0560 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 53430fa..1a0e118 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 199cbb1..96f2b84 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 *));