Browse Source

New threaded device probe framework

Luke Dashjr 12 years ago
parent
commit
4db5edb054
5 changed files with 122 additions and 3 deletions
  1. 6 0
      deviceapi.h
  2. 3 1
      lowlevel.c
  3. 3 1
      lowlevel.h
  4. 107 1
      miner.c
  5. 3 0
      miner.h

+ 6 - 0
deviceapi.h

@@ -5,6 +5,8 @@
 #include <stdint.h>
 #include <stdint.h>
 #include <sys/time.h>
 #include <sys/time.h>
 
 
+#include <uthash.h>
+
 #include "miner.h"
 #include "miner.h"
 
 
 struct driver_registration;
 struct driver_registration;
@@ -20,6 +22,10 @@ extern struct driver_registration *_bfg_drvreg1;
 extern struct driver_registration *_bfg_drvreg2;
 extern struct driver_registration *_bfg_drvreg2;
 extern void bfg_devapi_init();
 extern void bfg_devapi_init();
 
 
+#define BFG_FIND_DRV_BY_DNAME(reg, name, namelen)  \
+	HASH_FIND(hh , _bfg_drvreg1, name, namelen, reg)
+#define BFG_FIND_DRV_BY_NAME(reg, name, namelen)  \
+	HASH_FIND(hh2, _bfg_drvreg2, name, namelen, reg)
 #define BFG_FOREACH_DRIVER_BY_DNAME(reg, tmp)  \
 #define BFG_FOREACH_DRIVER_BY_DNAME(reg, tmp)  \
 	HASH_ITER(hh , _bfg_drvreg1, reg, tmp)
 	HASH_ITER(hh , _bfg_drvreg1, reg, tmp)
 #define BFG_FOREACH_DRIVER_BY_PRIORITY(reg, tmp)  \
 #define BFG_FOREACH_DRIVER_BY_PRIORITY(reg, tmp)  \

+ 3 - 1
lowlevel.c

@@ -58,7 +58,7 @@ void lowlevel_scan_free()
 	}
 	}
 }
 }
 
 
-void lowlevel_scan()
+struct lowlevel_device_info *lowlevel_scan()
 {
 {
 	struct lowlevel_device_info *devinfo_mid_list;
 	struct lowlevel_device_info *devinfo_mid_list;
 	
 	
@@ -99,6 +99,8 @@ void lowlevel_scan()
 		       (unsigned)devinfo_mid_list->vid, (unsigned)devinfo_mid_list->pid,
 		       (unsigned)devinfo_mid_list->vid, (unsigned)devinfo_mid_list->pid,
 		       devinfo_mid_list->manufacturer, devinfo_mid_list->product, devinfo_mid_list->serial);
 		       devinfo_mid_list->manufacturer, devinfo_mid_list->product, devinfo_mid_list->serial);
 	}
 	}
+	
+	return devinfo_list;
 }
 }
 
 
 #define DETECT_BEGIN  \
 #define DETECT_BEGIN  \

+ 3 - 1
lowlevel.h

@@ -3,6 +3,7 @@
 
 
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
+#include <pthread.h>
 
 
 #include <uthash.h>
 #include <uthash.h>
 
 
@@ -30,9 +31,10 @@ struct lowlevel_device_info {
 	
 	
 	struct lowlevel_device_info *next;
 	struct lowlevel_device_info *next;
 	UT_hash_handle hh;
 	UT_hash_handle hh;
+	pthread_t probe_pth;
 };
 };
 
 
-extern void lowlevel_scan();
+extern struct lowlevel_device_info *lowlevel_scan();
 extern int _lowlevel_detect(lowl_found_devinfo_func_t, const char *serial, const char **product_needles, void *);
 extern int _lowlevel_detect(lowl_found_devinfo_func_t, const char *serial, const char **product_needles, void *);
 #define lowlevel_detect(func, ...)  _lowlevel_detect(func, NULL, (const char *[]){__VA_ARGS__, NULL}, NULL)
 #define lowlevel_detect(func, ...)  _lowlevel_detect(func, NULL, (const char *[]){__VA_ARGS__, NULL}, NULL)
 #define lowlevel_detect_serial(func, serial)  _lowlevel_detect(func, serial, (const char *[]){NULL}, NULL)
 #define lowlevel_detect_serial(func, serial)  _lowlevel_detect(func, serial, (const char *[]){NULL}, NULL)

+ 107 - 1
miner.c

@@ -68,6 +68,7 @@
 #include "logging.h"
 #include "logging.h"
 #include "miner.h"
 #include "miner.h"
 #include "findnonce.h"
 #include "findnonce.h"
+#include "fpgautils.h"
 #include "adl.h"
 #include "adl.h"
 #include "driver-cpu.h"
 #include "driver-cpu.h"
 #include "driver-opencl.h"
 #include "driver-opencl.h"
@@ -10129,6 +10130,7 @@ extern struct sigaction pcwm_orig_term_handler;
 #endif
 #endif
 
 
 bool bfg_need_detect_rescan;
 bool bfg_need_detect_rescan;
+extern void probe_device(struct lowlevel_device_info *);
 
 
 static
 static
 void drv_detect_all()
 void drv_detect_all()
@@ -10137,7 +10139,12 @@ rescan:
 	bfg_need_detect_rescan = false;
 	bfg_need_detect_rescan = false;
 	
 	
 #ifdef HAVE_BFG_LOWLEVEL
 #ifdef HAVE_BFG_LOWLEVEL
-	lowlevel_scan();
+	struct lowlevel_device_info * const infolist = lowlevel_scan(), *info, *infotmp;
+	
+	LL_FOREACH_SAFE(infolist, info, infotmp)
+		probe_device(info);
+	LL_FOREACH_SAFE(infolist, info, infotmp)
+		pthread_join(info->probe_pth, NULL);
 #endif
 #endif
 	
 	
 	struct driver_registration *reg, *tmp;
 	struct driver_registration *reg, *tmp;
@@ -10270,6 +10277,105 @@ void _scan_serial(void *p)
 	}
 	}
 }
 }
 
 
+static
+bool _probe_device_internal(struct lowlevel_device_info * const info, const char * const dname, const size_t dnamelen)
+{
+	struct driver_registration *dreg;
+	
+	BFG_FIND_DRV_BY_DNAME(dreg, dname, dnamelen);
+	if (!dreg)
+	{
+		BFG_FIND_DRV_BY_NAME(dreg, dname, dnamelen);
+		if (!dreg)
+			return false;
+	}
+	
+	const struct device_drv * const drv = dreg->drv;
+	if (!drv->lowl_probe)
+		return false;
+	return drv->lowl_probe(info);
+}
+
+static
+void *probe_device_thread(void *p)
+{
+	struct lowlevel_device_info * const info = p;
+	
+	{
+		char threadname[5 + strlen(info->devid) + 1];
+		sprintf(threadname, "probe%s", info->devid);
+		RenameThread(threadname);
+	}
+	
+	// If already in use, ignore
+	if (bfg_claim_any(NULL, NULL, info->devid))
+		applogr(NULL, LOG_DEBUG, "%s: \"%s\" already in use",
+		        __func__, info->product);
+	
+	// if lowlevel device matches specific user assignment, probe requested driver(s)
+	struct string_elist *sd_iter, *sd_tmp;
+	struct driver_registration *dreg, *dreg_tmp;
+	DL_FOREACH_SAFE(scan_devices, sd_iter, sd_tmp)
+	{
+		const char * const dname = sd_iter->string;
+		const char * const colon = strchr(dname, ':');
+		if (!colon)
+			continue;
+		const char * const ser = &colon[1];
+		if (!(info->serial && !strcasecmp(ser, info->serial))
+		  || (info->path && !strcasecmp(ser, info->path)))
+			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
+	BFG_FOREACH_DRIVER_BY_PRIORITY(dreg, dreg_tmp)
+	{
+		const struct device_drv * const drv = dreg->drv;
+		if (!(drv->lowl_match && 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"))
+				allall = true;
+			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)
+		{
+			const struct device_drv * const drv = dreg->drv;
+			if (drv->lowl_probe(info))
+				return NULL;
+		}
+	}
+	
+	return NULL;
+}
+
+void probe_device(struct lowlevel_device_info * const info)
+{
+	pthread_create(&info->probe_pth, NULL, probe_device_thread, info);
+}
+
 int create_new_cgpus(void (*addfunc)(void*), void *arg)
 int create_new_cgpus(void (*addfunc)(void*), void *arg)
 {
 {
 	static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 	static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

+ 3 - 0
miner.h

@@ -288,6 +288,7 @@ typedef uint8_t supported_algos_t;
 struct api_data;
 struct api_data;
 struct thr_info;
 struct thr_info;
 struct work;
 struct work;
+struct lowlevel_device_info;
 
 
 struct device_drv {
 struct device_drv {
 	const char *dname;
 	const char *dname;
@@ -298,6 +299,8 @@ struct device_drv {
 	// DRV-global functions
 	// DRV-global functions
 	void (*drv_init)();
 	void (*drv_init)();
 	void (*drv_detect)();
 	void (*drv_detect)();
+	bool (*lowl_match)(const struct lowlevel_device_info *);
+	bool (*lowl_probe)(const struct lowlevel_device_info *);
 
 
 	// Processor-specific functions
 	// Processor-specific functions
 	void (*reinit_device)(struct cgpu_info *);
 	void (*reinit_device)(struct cgpu_info *);