diff --git a/API-README b/API-README index c73bb2aa..6f5fbe12 100644 --- a/API-README +++ b/API-README @@ -80,7 +80,7 @@ The STATUS section is: This defaults to the cgminer version but is the value of --api-description if it was specified at runtime. -For API version 1.9: +For API version 1.10 and later: The list of requests - a (*) means it requires privileged access - and replies are: @@ -290,6 +290,8 @@ API V1.12 Modified API commands: 'stats' - more pool stats added +Support for the ModMinerQuad FPGA was added + ---------- API V1.11 (cgminer v2.4.2) diff --git a/Makefile.am b/Makefile.am index f4e58988..d17414df 100644 --- a/Makefile.am +++ b/Makefile.am @@ -69,7 +69,7 @@ endif # HAS_YASM endif # HAS_CPUMINE if NEED_FPGAUTILS -cgminer_SOURCES += fpgautils.c +cgminer_SOURCES += fpgautils.c fpgautils.h endif if HAS_BITFORCE diff --git a/NEWS b/NEWS index 90462891..40d5255b 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,34 @@ +Version 2.4.3 - June 14, 2012 + +- can_roll and should_roll should have no bearing on the cycle period within the miner_thread so remove it. +- Check for strategy being changed to load balance when enabling LPs. +- Check that all threads on the device that called get_work are waiting on getwork before considering the pool lagging. +- Iterate over each thread belonging to each device in the hashmeter instead of searching for them now that they're a list. +- When using rotate pool strategy, ensure we only select from alive enabled pools. +- Start longpoll from every pool when load balance strategy is in use. +- Add mandatory and block fields to the work struct. Flag any shares that are detected as blocks as mandatory to submit, along with longpoll work from a previously rejecting pool. +- Consider the fan optimal if fanspeed is dropping but within the optimal speed window. +- Fix typo in some API messages (succeess/success) +- api.c MMQ stat bugs +- Bugfix: Fix warnings when built without libudev support +- Bugfix: slay a variety of warnings +- Bugfix: modminer: Fix unsigned/signed comparison and similar warnings +- API add ModMinerQuad support +- Bugfix: Honour forceauto parameter in serial_detect functions +- modminer: Temperature sensor improvements +- modminer: Make log messages more consistent in format +- Only adjust GPU speed up if the fanspeed is within the normal fanrange and hasn't been turned to maximum speed under overheat conditions. +- ModMiner use valid .name +- New driver: BTCFPGA ModMiner +- Abstract generally useful FPGA code into fpgautils.c +- API add stats for pool getworks +- miner.php option to hide specific fields from the display +- miner.php add version numbers to the summary page +- Update debian configs to v2.4.2 +- Add API and FPGA READMEs into Makefile to be included in source distribution. +- Icarus - fix unit64_t printf warnings + + Version 2.4.2 - June 2, 2012 - API.class compiled with Java SE 6.0_03 - works with Win7x64 diff --git a/api.c b/api.c index f18f7f73..d8ddde3e 100644 --- a/api.c +++ b/api.c @@ -27,6 +27,10 @@ #include "miner.h" #include "driver-cpu.h" /* for algo_names[], TODO: re-factor dependency */ +#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) || defined(USE_MODMINER) +#define HAVE_AN_FPGA 1 +#endif + #if defined(unix) || defined(__APPLE__) #include #include @@ -188,6 +192,9 @@ static const char *DEVICECODE = "" #ifdef USE_ZTEX "ZTX " #endif +#ifdef USE_MODMINER + "MMQ " +#endif #ifdef WANT_CPUMINE "CPU " #endif @@ -220,7 +227,7 @@ static const char *OSINFO = #define _MINECON "CONFIG" #define _GPU "GPU" -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA #define _PGA "PGA" #endif @@ -253,7 +260,7 @@ static const char ISJSON = '{'; #define JSON_MINECON JSON1 _MINECON JSON2 #define JSON_GPU JSON1 _GPU JSON2 -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA #define JSON_PGA JSON1 _PGA JSON2 #endif @@ -335,7 +342,7 @@ static const char *JSON_PARAMETER = "parameter"; #define MSG_TOOMANYP 54 #define MSG_ADDPOOL 55 -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA #define MSG_PGANON 56 #define MSG_PGADEV 57 #define MSG_INVPGA 58 @@ -344,7 +351,7 @@ static const char *JSON_PARAMETER = "parameter"; #define MSG_NUMPGA 59 #define MSG_NOTIFY 60 -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA #define MSG_PGALRENA 61 #define MSG_PGALRDIS 62 #define MSG_PGAENA 63 @@ -402,7 +409,7 @@ struct CODES { { SEVERITY_ERR, MSG_NOPOOL, PARAM_NONE, "No pools" }, { SEVERITY_SUCC, MSG_DEVS, PARAM_DMAX, "%d GPU(s)" -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA " - %d PGA(s)" #endif #ifdef WANT_CPUMINE @@ -411,7 +418,7 @@ struct CODES { }, { SEVERITY_ERR, MSG_NODEVS, PARAM_NONE, "No GPUs" -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA "/PGAs" #endif #ifdef WANT_CPUMINE @@ -425,7 +432,7 @@ struct CODES { { SEVERITY_ERR, MSG_INVCMD, PARAM_NONE, "Invalid command" }, { SEVERITY_ERR, MSG_MISID, PARAM_NONE, "Missing device id parameter" }, { SEVERITY_SUCC, MSG_GPUDEV, PARAM_GPU, "GPU%d" }, -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA { SEVERITY_ERR, MSG_PGANON, PARAM_NONE, "No PGAs" }, { SEVERITY_SUCC, MSG_PGADEV, PARAM_PGA, "PGA%d" }, { SEVERITY_ERR, MSG_INVPGA, PARAM_PGAMAX, "Invalid PGA id %d - range is 0 - %d" }, @@ -519,6 +526,10 @@ extern struct device_api icarus_api; extern struct device_api ztex_api; #endif +#ifdef USE_MODMINER +extern struct device_api modminer_api; +#endif + // This is only called when expected to be needed (rarely) // i.e. strings outside of the codes control (input from the user) static char *escape_string(char *str, bool isjson) @@ -581,7 +592,7 @@ static char *escape_string(char *str, bool isjson) return buf; } -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA static int numpgas() { int count = 0; @@ -599,6 +610,10 @@ static int numpgas() #ifdef USE_ZTEX if (devices[i]->api == &ztex_api) count++; +#endif +#ifdef USE_MODMINER + if (devices[i]->api == &modminer_api) + count++; #endif } return count; @@ -621,6 +636,10 @@ static int pgadevice(int pgaid) #ifdef USE_ZTEX if (devices[i]->api == &ztex_api) count++; +#endif +#ifdef USE_MODMINER + if (devices[i]->api == &modminer_api) + count++; #endif if (count == (pgaid + 1)) return i; @@ -636,7 +655,7 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) { char severity; char *ptr; -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA int pga; #endif #ifdef WANT_CPUMINE @@ -681,7 +700,7 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) case PARAM_GPUMAX: sprintf(ptr, codes[i].description, paramid, nDevs - 1); break; -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA case PARAM_PGAMAX: pga = numpgas(); sprintf(ptr, codes[i].description, paramid, pga - 1); @@ -703,7 +722,7 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) sprintf(ptr, codes[i].description, paramid, total_pools - 1); break; case PARAM_DMAX: -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA pga = numpgas(); #endif #ifdef WANT_CPUMINE @@ -714,7 +733,7 @@ static char *message(int messageid, int paramid, char *param2, bool isjson) #endif sprintf(ptr, codes[i].description, nDevs -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA , pga #endif #ifdef WANT_CPUMINE @@ -784,7 +803,7 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, const char *adl = NO; #endif -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA pgacount = numpgas(); #endif @@ -856,7 +875,7 @@ static void gpustatus(int gpu, bool isjson) } } -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA static void pgastatus(int pga, bool isjson) { char buf[TMPBUFSIZ]; @@ -871,11 +890,35 @@ static void pgastatus(int pga, bool isjson) struct cgpu_info *cgpu = devices[dev]; double frequency = 0; + float temp = cgpu->temp; #ifdef USE_ZTEX if (cgpu->api == &ztex_api && cgpu->device_ztex) frequency = cgpu->device_ztex->freqM1 * (cgpu->device_ztex->freqM + 1); #endif +#ifdef USE_MODMINER +// TODO: a modminer has up to 4 devices but only 1 set of data for all ... +// except 4 sets of data for temp/clock +// So this should change in the future to just find the single temp/clock +// if the modminer code splits the device into seperate devices later +// For now, just display the highest temp and the average clock + if (cgpu->api == &modminer_api) { + int tc = cgpu->threads; + int i; + + temp = 0; + if (tc > 4) + tc = 4; + for (i = 0; i < tc; i++) { + struct thr_info *thr = cgpu->thr[i]; + struct modminer_fpga_state *state = thr->cgpu_data; + if (state->temp > temp) + temp = state->temp; + frequency += state->clock; + } + frequency /= (tc ? tc : 1); + } +#endif cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60; @@ -897,7 +940,7 @@ static void pgastatus(int pga, bool isjson) ? "{\"PGA\":%d,\"Name\":\"%s\",\"ID\":%d,\"Enabled\":\"%s\",\"Status\":\"%s\",\"Temperature\":%.2f,\"MHS av\":%.2f,\"MHS %ds\":%.2f,\"Accepted\":%d,\"Rejected\":%d,\"Hardware Errors\":%d,\"Utility\":%.2f,\"Last Share Pool\":%d,\"Last Share Time\":%lu,\"Total MH\":%.4f,\"Frequency\":%.2f}" : "PGA=%d,Name=%s,ID=%d,Enabled=%s,Status=%s,Temperature=%.2f,MHS av=%.2f,MHS %ds=%.2f,Accepted=%d,Rejected=%d,Hardware Errors=%d,Utility=%.2f,Last Share Pool=%d,Last Share Time=%lu,Total MH=%.4f,Frequency=%.2f" SEPSTR, pga, cgpu->api->name, cgpu->device_id, - enabled, status, cgpu->temp, + enabled, status, temp, cgpu->total_mhashes / total_secs, opt_log_interval, cgpu->rolling, cgpu->accepted, cgpu->rejected, cgpu->hw_errors, cgpu->utility, ((unsigned long)(cgpu->last_share_pool_time) > 0) ? cgpu->last_share_pool : -1, @@ -939,7 +982,7 @@ static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, b int numpga = 0; int i; -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA numpga = numpgas(); #endif @@ -964,7 +1007,7 @@ static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, b devcount++; } -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA if (numpga > 0) for (i = 0; i < numpga; i++) { if (isjson && devcount > 0) @@ -1025,7 +1068,7 @@ static void gpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson) strcat(io_buffer, JSON_CLOSE); } -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA static void pgadev(__maybe_unused SOCKETTYPE c, char *param, bool isjson) { int numpga = numpgas(); @@ -1420,7 +1463,7 @@ static void pgacount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo char buf[TMPBUFSIZ]; int count = 0; -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA count = numpgas(); #endif @@ -2105,7 +2148,7 @@ struct CMDS { { "gpudisable", gpudisable, true }, { "gpurestart", gpurestart, true }, { "gpu", gpudev, false }, -#if defined(USE_BITFORCE) || defined(USE_ICARUS) || defined(USE_ZTEX) +#ifdef HAVE_AN_FPGA { "pga", pgadev, false }, { "pgaenable", pgaenable, true }, { "pgadisable", pgadisable, true }, diff --git a/cgminer.c b/cgminer.c index 7ea9b4cc..cef4c8cc 100644 --- a/cgminer.c +++ b/cgminer.c @@ -3302,12 +3302,9 @@ static void hashmeter(int thr_id, struct timeval *diff, /* Rolling average for each thread and each device */ decay_time(&thr->rolling, local_mhashes / secs); - for (i = 0; i < mining_threads; i++) { - struct thr_info *th = &thr_info[i]; + for (i = 0; i < cgpu->threads; i++) + thread_rolling += cgpu->thr[i]->rolling; - if (th->cgpu == cgpu) - thread_rolling += th->rolling; - } mutex_lock(&hash_lock); decay_time(&cgpu->rolling, thread_rolling); cgpu->total_mhashes += local_mhashes; @@ -3635,11 +3632,26 @@ retry: goto out; } - if (requested && !newreq && !requests_staged() && requests_queued() >= mining_threads && - !pool_tset(pool, &pool->lagging)) { - applog(LOG_WARNING, "Pool %d not providing work fast enough", pool->pool_no); - pool->getfail_occasions++; - total_go++; + if (!pool->lagging && requested && !newreq && !requests_staged() && requests_queued() >= mining_threads) { + struct cgpu_info *cgpu = thr->cgpu; + bool stalled = true; + int i; + + /* Check to see if all the threads on the device that called + * get_work are waiting on work and only consider the pool + * lagging if true */ + for (i = 0; i < cgpu->threads; i++) { + if (!cgpu->thr[i]->getwork) { + stalled = false; + break; + } + } + + if (stalled && !pool_tset(pool, &pool->lagging)) { + applog(LOG_WARNING, "Pool %d not providing work fast enough", pool->pool_no); + pool->getfail_occasions++; + total_go++; + } } newreq = requested = false; @@ -3802,8 +3814,7 @@ void *miner_thread(void *userdata) struct timeval getwork_start; /* Try to cycle approximately 5 times before each log update */ - const unsigned long def_cycle = opt_log_interval / 5 ? : 1; - long cycle; + const long cycle = opt_log_interval / 5 ? : 1; struct timeval tv_start, tv_end, tv_workstart, tv_lastupdate; struct timeval diff, sdiff, wdiff; uint32_t max_nonce = api->can_limit_work ? api->can_limit_work(mythr) : 0xffffffff; @@ -3842,7 +3853,6 @@ void *miner_thread(void *userdata) break; } requested = false; - cycle = (can_roll(work) && should_roll(work)) ? 1 : def_cycle; gettimeofday(&tv_workstart, NULL); work->blk.nonce = 0; cgpu->max_hashes = 0; @@ -3947,7 +3957,7 @@ void *miner_thread(void *userdata) } } - if (unlikely(sdiff.tv_sec < cycle)) { + if (unlikely((long)sdiff.tv_sec < cycle)) { if (likely(!api->can_limit_work || max_nonce == 0xffffffff)) continue; @@ -4088,7 +4098,7 @@ static void wait_lpcurrent(struct pool *pool) if (pool->enabled == POOL_REJECTING || pool_strategy == POOL_LOADBALANCE) return; - while (pool != current_pool()) { + while (pool != current_pool() && pool_strategy != POOL_LOADBALANCE) { mutex_lock(&lp_lock); pthread_cond_wait(&lp_cond, &lp_lock); mutex_unlock(&lp_lock); diff --git a/configure.ac b/configure.ac index 5cfb9ff9..7169c0ac 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## m4_define([v_maj], [2]) m4_define([v_min], [4]) -m4_define([v_mic], [2]) +m4_define([v_mic], [3]) ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## m4_define([v_ver], [v_maj.v_min.v_mic]) m4_define([lt_rev], m4_eval(v_maj + v_min)) diff --git a/driver-modminer.c b/driver-modminer.c index d139091e..0afce2d1 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -232,22 +232,6 @@ modminer_device_prepare(struct cgpu_info *modminer) #undef bailout -struct modminer_fpga_state { - bool work_running; - struct work running_work; - struct timeval tv_workstart; - uint32_t hashes; - - char next_work_cmd[46]; - - unsigned char clock; - int no_nonce_counter; - int good_share_counter; - time_t last_cutoff_reduced; - - unsigned char temp; -}; - static bool modminer_fpga_prepare(struct thr_info *thr) { diff --git a/fpgautils.h b/fpgautils.h index 7b8b3317..91ccb30a 100644 --- a/fpgautils.h +++ b/fpgautils.h @@ -18,11 +18,11 @@ typedef char(*autoscan_func_t)(); extern char _serial_detect(const char*dnamec, size_t dnamel, detectone_func_t, autoscan_func_t, bool force_autoscan); #define serial_detect_fauto(dname, detectone, autoscan) \ - _serial_detect(dname ":", sizeof(dname)+1, detectone, autoscan, true) + _serial_detect(dname ":", sizeof(dname), detectone, autoscan, true) #define serial_detect_auto(dname, detectone, autoscan) \ - _serial_detect(dname ":", sizeof(dname)+1, detectone, autoscan, false) + _serial_detect(dname ":", sizeof(dname), detectone, autoscan, false) #define serial_detect(dname, detectone) \ - _serial_detect(dname ":", sizeof(dname)+1, detectone, NULL, false) + _serial_detect(dname ":", sizeof(dname), detectone, NULL, false) extern char serial_autodetect_devserial(detectone_func_t, const char*prodname); extern char serial_autodetect_udev (detectone_func_t, const char*prodname); diff --git a/miner.h b/miner.h index d01e2136..c6aab1e8 100644 --- a/miner.h +++ b/miner.h @@ -751,6 +751,24 @@ struct work { time_t share_found_time; }; +#ifdef USE_MODMINER +struct modminer_fpga_state { + bool work_running; + struct work running_work; + struct timeval tv_workstart; + uint32_t hashes; + + char next_work_cmd[46]; + + unsigned char clock; + int no_nonce_counter; + int good_share_counter; + time_t last_cutoff_reduced; + + unsigned char temp; +}; +#endif + extern void get_datestamp(char *, struct timeval *); extern bool test_nonce(struct work *work, uint32_t nonce); bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce); diff --git a/miner.php b/miner.php index 8b389761..728a4ebc 100644 --- a/miner.php +++ b/miner.php @@ -60,6 +60,14 @@ $warnfont = ''; $warnoff = ''; $dfmt = 'H:i:s j-M-Y \U\T\CP'; # +# This below allows you to put your own settings into a seperate file +# so you don't need to update miner.php with your preferred settings +# every time a new version is released +# Just create the file 'myminer.php' in the same directory as +# 'miner.php' - and put your own settings in there +if (file_exists('myminer.php')) + include_once('myminer.php'); +# # Ensure it is only ever shown once global $showndate; $showndate = false;