Browse Source

lowlevel: Collapse multiple lowlevel drivers on the same devid to a secondary linked list, and only spawn one thread to probe all lowlevels on a given devid

Luke Dashjr 12 years ago
parent
commit
1a39ff42b1
3 changed files with 54 additions and 26 deletions
  1. 17 1
      lowlevel.c
  2. 1 0
      lowlevel.h
  3. 36 25
      miner.c

+ 17 - 1
lowlevel.c

@@ -59,11 +59,16 @@ void lowlevel_scan_free()
 		return;
 	
 	struct lowlevel_device_info *info, *tmp;
+	struct lowlevel_device_info *info2, *tmp2;
 	
 	LL_FOREACH_SAFE(devinfo_list, info, tmp)
 	{
 		LL_DELETE(devinfo_list, info);
-		lowlevel_devinfo_free(info);
+		LL_FOREACH_SAFE2(info, info2, tmp2, same_devid_next)
+		{
+			LL_DELETE(info, info2);
+			lowlevel_devinfo_free(info2);
+		}
 	}
 }
 
@@ -98,8 +103,19 @@ struct lowlevel_device_info *lowlevel_scan()
 	LL_CONCAT(devinfo_list, devinfo_mid_list);
 #endif
 	
+	struct lowlevel_device_info *devinfo_same_prev_ht = NULL, *devinfo_same_list;
 	LL_FOREACH(devinfo_list, devinfo_mid_list)
 	{
+		// Check for devid overlapping, and build a secondary linked list for them, only including the devid in the main list once (high level to low level)
+		HASH_FIND_STR(devinfo_same_prev_ht, devinfo_mid_list->devid, devinfo_same_list);
+		if (devinfo_same_list)
+		{
+			HASH_DEL(devinfo_same_prev_ht, devinfo_same_list);
+			LL_DELETE(devinfo_list, devinfo_same_list);
+		}
+		LL_PREPEND2(devinfo_same_list, devinfo_mid_list, same_devid_next);
+		HASH_ADD_KEYPTR(hh, devinfo_same_prev_ht, devinfo_mid_list->devid, strlen(devinfo_mid_list->devid), devinfo_same_list);
+		
 		applog(LOG_DEBUG, "%s: Found %s device at %s (path=%s, vid=%04x, pid=%04x, manuf=%s, prod=%s, serial=%s)",
 		       __func__,
 		       devinfo_mid_list->lowl->dname,

+ 1 - 0
lowlevel.h

@@ -30,6 +30,7 @@ struct lowlevel_device_info {
 	void *lowl_data;
 	
 	struct lowlevel_device_info *next;
+	struct lowlevel_device_info *same_devid_next;
 	UT_hash_handle hh;
 	pthread_t probe_pth;
 	int ref;

+ 36 - 25
miner.c

@@ -10384,11 +10384,12 @@ bool _probe_device_internal(struct lowlevel_device_info * const info, const char
 static
 void *probe_device_thread(void *p)
 {
-	struct lowlevel_device_info * const info = p;
+	struct lowlevel_device_info * const infolist = p;
+	struct lowlevel_device_info *info = infolist;
 	
 	{
 		char threadname[5 + strlen(info->devid) + 1];
-		sprintf(threadname, "probe%s", info->devid);
+		sprintf(threadname, "probe_%s", info->devid);
 		RenameThread(threadname);
 	}
 	
@@ -10407,11 +10408,14 @@ void *probe_device_thread(void *p)
 		if (!colon)
 			continue;
 		const char * const ser = &colon[1];
-		if (!_probe_device_match(info, ser))
-			continue;
-		const size_t dnamelen = (colon - dname);
-		if (_probe_device_internal(info, dname, dnamelen))
-			return NULL;
+		LL_FOREACH2(infolist, info, same_devid_next)
+		{
+			if (!_probe_device_match(info, ser))
+				continue;
+			const size_t dnamelen = (colon - dname);
+			if (_probe_device_internal(info, dname, dnamelen))
+				return NULL;
+		}
 	}
 	
 	// probe driver(s) with auto enabled and matching VID/PID/Product/etc of device
@@ -10438,41 +10442,48 @@ void *probe_device_thread(void *p)
 				break;
 		}
 		
-		if (doauto)
+		if (doauto && drv->lowl_match)
 		{
-			if (!(drv->lowl_match && drv->lowl_match(info)))
-				continue;
-			if (drv->lowl_probe(info))
-				return NULL;
+			LL_FOREACH2(infolist, info, same_devid_next)
+			{
+				if (!drv->lowl_match(info))
+					continue;
+				if (drv->lowl_probe(info))
+					return NULL;
+			}
 		}
 	}
 	
 	// probe driver(s) with 'all' enabled
-	bool allall = false;
 	DL_FOREACH_SAFE(scan_devices, sd_iter, sd_tmp)
 	{
 		const char * const dname = sd_iter->string;
 		const char * const colon = strchr(dname, ':');
 		if (!colon)
 		{
-			if ((!strcasecmp(dname, "all")) || _probe_device_match(info, dname))
-				allall = true;
+			LL_FOREACH2(infolist, info, same_devid_next)
+			{
+				if ((!strcasecmp(dname, "all")) || _probe_device_match(info, dname))
+				{
+					BFG_FOREACH_DRIVER_BY_PRIORITY(dreg, dreg_tmp)
+					{
+						const struct device_drv * const drv = dreg->drv;
+						if (!drv->lowl_probe)
+							continue;
+						if (drv->lowl_probe(info))
+							return NULL;
+					}
+					break;
+				}
+			}
 			continue;
 		}
 		if (strcasecmp(&colon[1], "all"))
 			continue;
 		const size_t dnamelen = (colon - dname);
-		if (_probe_device_internal(info, dname, dnamelen))
-			return NULL;
-	}
-	if (allall)
-	{
-		BFG_FOREACH_DRIVER_BY_PRIORITY(dreg, dreg_tmp)
+		LL_FOREACH2(infolist, info, same_devid_next)
 		{
-			const struct device_drv * const drv = dreg->drv;
-			if (!drv->lowl_probe)
-				continue;
-			if (drv->lowl_probe(info))
+			if (_probe_device_internal(info, dname, dnamelen))
 				return NULL;
 		}
 	}