Browse Source

Merge branch 'bfl'

Conflicts:
	miner.h
nfactor-troky
Con Kolivas 13 years ago
parent
commit
732783faa6
  1. 94
      cgminer.c
  2. 368
      driver-bitforce.c
  3. 7
      miner.h

94
cgminer.c

@ -3373,10 +3373,6 @@ static void hashmeter(int thr_id, struct timeval *diff, @@ -3373,10 +3373,6 @@ static void hashmeter(int thr_id, struct timeval *diff,
thr_info[thr_id].cgpu->device_last_well = time(NULL);
}
/* Don't bother calculating anything if we're not displaying it */
if (opt_realquiet || !opt_log_interval)
return;
secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0);
/* So we can call hashmeter from a non worker thread */
@ -4170,6 +4166,7 @@ disabled: @@ -4170,6 +4166,7 @@ disabled:
tq_pop(mythr->q, NULL); /* Ignore ping that's popped */
thread_reportin(mythr);
applog(LOG_WARNING, "Thread %d being re-enabled", thr_id);
if (api->thread_enable) api->thread_enable(mythr);
}
sdiff.tv_sec = sdiff.tv_usec = 0;
@ -4455,9 +4452,16 @@ static void age_work(void) @@ -4455,9 +4452,16 @@ static void age_work(void)
/* Makes sure the hashmeter keeps going even if mining threads stall, updates
* the screen at regular intervals, and restarts threads if they appear to have
* died. */
#define WATCHDOG_INTERVAL 3
#define WATCHDOG_SICK_TIME 60
#define WATCHDOG_DEAD_TIME 600
#define WATCHDOG_SICK_COUNT (WATCHDOG_SICK_TIME/WATCHDOG_INTERVAL)
#define WATCHDOG_DEAD_COUNT (WATCHDOG_DEAD_TIME/WATCHDOG_INTERVAL)
#define WATCHDOG_LOW_HASH 1.0 /* consider < 1MH too low for any device */
static void *watchdog_thread(void __maybe_unused *userdata)
{
const unsigned int interval = 3;
const unsigned int interval = WATCHDOG_INTERVAL;
struct timeval zero_tv;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
@ -4530,24 +4534,27 @@ static void *watchdog_thread(void __maybe_unused *userdata) @@ -4530,24 +4534,27 @@ static void *watchdog_thread(void __maybe_unused *userdata)
}
}
#ifdef HAVE_OPENCL
for (i = 0; i < total_devices; ++i) {
struct cgpu_info *cgpu = devices[i];
struct thr_info *thr = cgpu->thr[0];
enum dev_enable *denable;
bool dev_count_well;
bool dev_count_sick;
bool dev_count_dead;
char dev_str[8];
int gpu;
if (cgpu->api != &opencl_api)
continue;
/* Use only one thread per device to determine if the GPU is healthy */
if (i >= nDevs)
break;
gpu = thr->cgpu->device_id;
if (cgpu->api->get_stats)
cgpu->api->get_stats(cgpu);
gpu = cgpu->device_id;
denable = &cgpu->deven;
sprintf(dev_str, "%s%d", cgpu->api->name, gpu);
#ifdef HAVE_ADL
if (adl_active && gpus[gpu].has_adl)
if (adl_active && cgpu->has_adl)
gpu_autotune(gpu, denable);
if (opt_debug && gpus[gpu].has_adl) {
if (opt_debug && cgpu->has_adl) {
int engineclock = 0, memclock = 0, activity = 0, fanspeed = 0, fanpercent = 0, powertune = 0;
float temp = 0, vddc = 0;
@ -4556,55 +4563,64 @@ static void *watchdog_thread(void __maybe_unused *userdata) @@ -4556,55 +4563,64 @@ static void *watchdog_thread(void __maybe_unused *userdata)
temp, fanpercent, fanspeed, engineclock, memclock, vddc, activity, powertune);
}
#endif
/* Thread is waiting on getwork or disabled */
if (thr->getwork || *denable == DEV_DISABLED)
continue;
if (gpus[gpu].status != LIFE_WELL && now.tv_sec - thr->last.tv_sec < 60) {
applog(LOG_ERR, "Device %d recovered, GPU %d declared WELL!", i, gpu);
gpus[gpu].status = LIFE_WELL;
gpus[gpu].device_last_well = time(NULL);
} else if (now.tv_sec - thr->last.tv_sec > 60 && gpus[gpu].status == LIFE_WELL) {
thr->rolling = thr->cgpu->rolling = 0;
gpus[gpu].status = LIFE_SICK;
applog(LOG_ERR, "Device %d idle for more than 60 seconds, GPU %d declared SICK!", i, gpu);
if (cgpu->rolling < WATCHDOG_LOW_HASH)
cgpu->low_count++;
else
cgpu->low_count = 0;
dev_count_well = (cgpu->low_count < WATCHDOG_SICK_COUNT);
dev_count_sick = (cgpu->low_count > WATCHDOG_SICK_COUNT);
dev_count_dead = (cgpu->low_count > WATCHDOG_DEAD_COUNT);
if (gpus[gpu].status != LIFE_WELL && (now.tv_sec - thr->last.tv_sec < WATCHDOG_SICK_TIME) && dev_count_well) {
applog(LOG_ERR, "%s: Recovered, declaring WELL!", dev_str);
cgpu->status = LIFE_WELL;
cgpu->device_last_well = time(NULL);
} else if (cgpu->status == LIFE_WELL && ((now.tv_sec - thr->last.tv_sec > WATCHDOG_SICK_TIME) || dev_count_sick)) {
thr->rolling = cgpu->rolling = 0;
cgpu->status = LIFE_SICK;
applog(LOG_ERR, "%s: Idle for more than 60 seconds, declaring SICK!", dev_str);
gettimeofday(&thr->sick, NULL);
gpus[gpu].device_last_not_well = time(NULL);
gpus[gpu].device_not_well_reason = REASON_DEV_SICK_IDLE_60;
gpus[gpu].dev_sick_idle_60_count++;
cgpu->device_last_not_well = time(NULL);
cgpu->device_not_well_reason = REASON_DEV_SICK_IDLE_60;
cgpu->dev_sick_idle_60_count++;
#ifdef HAVE_ADL
if (adl_active && gpus[gpu].has_adl && gpu_activity(gpu) > 50) {
if (adl_active && cgpu->has_adl && gpu_activity(gpu) > 50) {
applog(LOG_ERR, "GPU still showing activity suggesting a hard hang.");
applog(LOG_ERR, "Will not attempt to auto-restart it.");
} else
#endif
if (opt_restart) {
applog(LOG_ERR, "Attempting to restart GPU");
reinit_device(thr->cgpu);
applog(LOG_ERR, "%s: Attempting to restart", dev_str);
reinit_device(cgpu);
}
} else if (now.tv_sec - thr->last.tv_sec > 600 && gpus[i].status == LIFE_SICK) {
gpus[gpu].status = LIFE_DEAD;
applog(LOG_ERR, "Device %d not responding for more than 10 minutes, GPU %d declared DEAD!", i, gpu);
} else if (cgpu->status == LIFE_SICK && ((now.tv_sec - thr->last.tv_sec > WATCHDOG_DEAD_TIME) || dev_count_dead)) {
cgpu->status = LIFE_DEAD;
applog(LOG_ERR, "%s: Not responded for more than 10 minutes, declaring DEAD!", dev_str);
gettimeofday(&thr->sick, NULL);
gpus[gpu].device_last_not_well = time(NULL);
gpus[gpu].device_not_well_reason = REASON_DEV_DEAD_IDLE_600;
gpus[gpu].dev_dead_idle_600_count++;
cgpu->device_last_not_well = time(NULL);
cgpu->device_not_well_reason = REASON_DEV_DEAD_IDLE_600;
cgpu->dev_dead_idle_600_count++;
} else if (now.tv_sec - thr->sick.tv_sec > 60 &&
(gpus[i].status == LIFE_SICK || gpus[i].status == LIFE_DEAD)) {
(cgpu->status == LIFE_SICK || cgpu->status == LIFE_DEAD)) {
/* Attempt to restart a GPU that's sick or dead once every minute */
gettimeofday(&thr->sick, NULL);
#ifdef HAVE_ADL
if (adl_active && gpus[gpu].has_adl && gpu_activity(gpu) > 50) {
if (adl_active && cgpu->has_adl && gpu_activity(gpu) > 50) {
/* Again do not attempt to restart a device that may have hard hung */
} else
#endif
if (opt_restart)
reinit_device(thr->cgpu);
reinit_device(cgpu);
}
}
#endif
}
return NULL;
@ -5491,6 +5507,7 @@ begin_bench: @@ -5491,6 +5507,7 @@ begin_bench:
quit(1, "API thread create failed");
pthread_detach(thr->pth);
#ifdef HAVE_CURSES
/* Create curses input thread for keyboard input. Create this last so
* that we know all threads are created since this can call kill_work
@ -5529,3 +5546,4 @@ begin_bench: @@ -5529,3 +5546,4 @@ begin_bench:
return 0;
}

368
driver-bitforce.c

@ -20,6 +20,11 @@ @@ -20,6 +20,11 @@
#include "fpgautils.h"
#include "miner.h"
#define BITFORCE_SLEEP_MS 3000
#define BITFORCE_TIMEOUT_MS 10000
#define BITFORCE_CHECK_INTERVAL_MS 10
#define WORK_CHECK_INTERVAL_MS 50
#define MAX_START_DELAY_US 100000
struct device_api bitforce_api;
@ -29,71 +34,71 @@ static void BFgets(char *buf, size_t bufLen, int fd) @@ -29,71 +34,71 @@ static void BFgets(char *buf, size_t bufLen, int fd)
{
do
--bufLen;
while (likely(bufLen && read(fd, buf, 1) && (buf++)[0] != '\n'))
;
while (likely(bufLen && read(fd, buf, 1) && (buf++)[0] != '\n'));
buf[0] = '\0';
}
static ssize_t BFwrite2(int fd, const void *buf, ssize_t bufLen)
static ssize_t BFwrite(int fd, const void *buf, ssize_t bufLen)
{
return write(fd, buf, bufLen);
if ((bufLen) != write(fd, buf, bufLen))
return 0;
else
return bufLen;
}
#define BFwrite(fd, buf, bufLen) do { \
if ((bufLen) != BFwrite2(fd, buf, bufLen)) { \
applog(LOG_ERR, "Error writing to BitForce (" #buf ")"); \
return 0; \
} \
} while(0)
#define BFclose(fd) close(fd)
static bool bitforce_detect_one(const char *devpath)
{
char *s;
int fdDev = BFopen(devpath);
struct cgpu_info *bitforce;
char pdevbuf[0x100];
char *s;
applog(LOG_DEBUG, "BitForce Detect: Attempting to open %s", devpath);
applog(LOG_DEBUG, "BFL: Attempting to open %s", devpath);
int fdDev = BFopen(devpath);
if (unlikely(fdDev == -1)) {
applog(LOG_ERR, "BitForce Detect: Failed to open %s", devpath);
applog(LOG_ERR, "BFL: Failed to open %s", devpath);
return false;
}
BFwrite(fdDev, "ZGX", 3);
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
if (unlikely(!pdevbuf[0])) {
applog(LOG_ERR, "Error reading from BitForce (ZGX)");
applog(LOG_ERR, "BFL: Error reading (ZGX)");
return 0;
}
BFclose(fdDev);
if (unlikely(!strstr(pdevbuf, "SHA256"))) {
applog(LOG_DEBUG, "BitForce Detect: Didn't recognise BitForce on %s", devpath);
applog(LOG_ERR, "BFL: Didn't recognise BitForce on %s", devpath);
return false;
}
// We have a real BitForce!
struct cgpu_info *bitforce;
bitforce = calloc(1, sizeof(*bitforce));
bitforce->api = &bitforce_api;
bitforce->device_path = strdup(devpath);
bitforce->deven = DEV_ENABLED;
bitforce->threads = 1;
if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>"))))
{
bitforce->sleep_ms = BITFORCE_SLEEP_MS;
if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>")))) {
s[0] = '\0';
bitforce->name = strdup(pdevbuf + 7);
}
mutex_init(&bitforce->device_mutex);
return add_cgpu(bitforce);
}
static char bitforce_detect_auto()
{
return
serial_autodetect_udev (bitforce_detect_one, "BitFORCE*SHA256") ?:
return (serial_autodetect_udev (bitforce_detect_one, "BitFORCE*SHA256") ?:
serial_autodetect_devserial(bitforce_detect_one, "BitFORCE_SHA256") ?:
0;
0);
}
static void bitforce_detect()
@ -104,6 +109,7 @@ static void bitforce_detect() @@ -104,6 +109,7 @@ static void bitforce_detect()
static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce)
{
float gt = bitforce->temp;
if (gt > 0)
tailsprintf(buf, "%5.1fC ", gt);
else
@ -114,79 +120,112 @@ static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce) @@ -114,79 +120,112 @@ static void get_bitforce_statline_before(char *buf, struct cgpu_info *bitforce)
static bool bitforce_thread_prepare(struct thr_info *thr)
{
struct cgpu_info *bitforce = thr->cgpu;
int fdDev = BFopen(bitforce->device_path);
struct timeval now;
int fdDev = BFopen(bitforce->device_path);
if (unlikely(-1 == fdDev)) {
applog(LOG_ERR, "Failed to open BitForce on %s", bitforce->device_path);
if (unlikely(fdDev == -1)) {
applog(LOG_ERR, "BFL%i: Failed to open %s", bitforce->device_id, bitforce->device_path);
return false;
}
bitforce->device_fd = fdDev;
applog(LOG_INFO, "Opened BitForce on %s", bitforce->device_path);
applog(LOG_INFO, "BFL%i: Opened %s", bitforce->device_id, bitforce->device_path);
gettimeofday(&now, NULL);
get_datestamp(bitforce->init, &now);
return true;
}
static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint64_t __maybe_unused max_nonce)
static void biforce_clear_buffer(struct cgpu_info *bitforce)
{
struct cgpu_info *bitforce = thr->cgpu;
int fdDev = bitforce->device_fd;
char pdevbuf[0x100];
int i, thr_id = thr->id;
applog(LOG_DEBUG, "BFL%i: Clearing read buffer", bitforce->device_id);
mutex_lock(&bitforce->device_mutex);
do {
pdevbuf[0] = '\0';
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
} while (pdevbuf[0]);
mutex_unlock(&bitforce->device_mutex);
}
void bitforce_init(struct cgpu_info *bitforce)
{
char *devpath = bitforce->device_path;
int fdDev = bitforce->device_fd;
char pdevbuf[0x100];
unsigned char ob[61] = ">>>>>>>>12345678901234567890123456789012123456789012>>>>>>>>";
struct timeval tdiff;
char *pnoncebuf;
char *s;
uint32_t nonce;
BFwrite(fdDev, "ZDX", 3);
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
if (unlikely(!pdevbuf[0])) {
applog(LOG_ERR, "Error reading from BitForce (ZDX)");
return 0;
}
if (unlikely(pdevbuf[0] != 'O' || pdevbuf[1] != 'K')) {
applog(LOG_ERR, "BitForce ZDX reports: %s", pdevbuf);
return 0;
}
applog(LOG_WARNING, "BFL%i: Re-initalizing", bitforce->device_id);
memcpy(ob + 8, work->midstate, 32);
memcpy(ob + 8 + 32, work->data + 64, 12);
BFwrite(fdDev, ob, 60);
if (opt_debug) {
s = bin2hex(ob + 8, 44);
applog(LOG_DEBUG, "BitForce block data: %s", s);
free(s);
biforce_clear_buffer(bitforce);
mutex_lock(&bitforce->device_mutex);
if (fdDev)
BFclose(fdDev);
bitforce->device_fd = 0;
fdDev = BFopen(devpath);
if (unlikely(fdDev == -1)) {
mutex_unlock(&bitforce->device_mutex);
applog(LOG_ERR, "BFL%i: Failed to open %s", bitforce->device_id, devpath);
return;
}
BFwrite(fdDev, "ZGX", 3);
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
if (unlikely(!pdevbuf[0])) {
applog(LOG_ERR, "Error reading from BitForce (block data)");
return 0;
mutex_unlock(&bitforce->device_mutex);
applog(LOG_ERR, "BFL%i: Error reading (ZGX)", bitforce->device_id);
return;
}
if (unlikely(pdevbuf[0] != 'O' || pdevbuf[1] != 'K')) {
applog(LOG_ERR, "BitForce block data reports: %s", pdevbuf);
return 0;
if (unlikely(!strstr(pdevbuf, "SHA256"))) {
mutex_unlock(&bitforce->device_mutex);
applog(LOG_ERR, "BFL%i: Didn't recognise BitForce on %s returned: %s", bitforce->device_id, devpath, pdevbuf);
return;
}
if (likely((!memcmp(pdevbuf, ">>>ID: ", 7)) && (s = strstr(pdevbuf + 3, ">>>")))) {
s[0] = '\0';
bitforce->name = strdup(pdevbuf + 7);
}
bitforce->device_fd = fdDev;
mutex_unlock(&bitforce->device_mutex);
}
static bool bitforce_get_temp(struct cgpu_info *bitforce)
{
int fdDev = bitforce->device_fd;
char pdevbuf[0x100];
char *s;
if (!fdDev)
return false;
mutex_lock(&bitforce->device_mutex);
BFwrite(fdDev, "ZLX", 3);
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
mutex_unlock(&bitforce->device_mutex);
if (unlikely(!pdevbuf[0])) {
applog(LOG_ERR, "Error reading from BitForce (ZKX)");
return 0;
applog(LOG_ERR, "BFL%i: Error: Get temp returned empty string", bitforce->device_id);
bitforce->temp = 0;
return false;
}
if ((!strncasecmp(pdevbuf, "TEMP", 4)) && (s = strchr(pdevbuf + 4, ':'))) {
float temp = strtof(s + 1, NULL);
if (temp > 0) {
bitforce->temp = temp;
if (temp > bitforce->cutofftemp) {
applog(LOG_WARNING, "Hit thermal cutoff limit on %s %d, disabling!", bitforce->api->name, bitforce->device_id);
applog(LOG_WARNING, "BFL%i: Hit thermal cutoff limit, disabling!", bitforce->device_id);
bitforce->deven = DEV_RECOVER;
bitforce->device_last_not_well = time(NULL);
@ -195,46 +234,114 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6 @@ -195,46 +234,114 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6
}
}
}
return true;
}
/* Initially wait 2/3 of the average cycle time so we can request more
* work before full scan is up ~ 3.4 seconds */
tdiff.tv_sec = 3;
tdiff.tv_usec = 4000000;
if (!restart_wait(&tdiff))
return 0;
queue_request(thr, false);
i = 3400;
static bool bitforce_send_work(struct thr_info *thr, struct work *work)
{
unsigned char ob[61] = ">>>>>>>>12345678901234567890123456789012123456789012>>>>>>>>";
struct cgpu_info *bitforce = thr->cgpu;
int fdDev = bitforce->device_fd;
char pdevbuf[0x100];
char *s;
/* Now wait another second; no bistream should be finished by now */
tdiff.tv_sec = 1;
tdiff.tv_usec = 0;
if (!restart_wait(&tdiff))
return 0;
i += 1000;
if (!fdDev)
return false;
re_send:
mutex_lock(&bitforce->device_mutex);
BFwrite(fdDev, "ZDX", 3);
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
if (!pdevbuf[0] || (pdevbuf[0] == 'B')) {
mutex_unlock(&bitforce->device_mutex);
bitforce->wait_ms += WORK_CHECK_INTERVAL_MS;
usleep(WORK_CHECK_INTERVAL_MS * 1000);
goto re_send;
} else if (unlikely(pdevbuf[0] != 'O' || pdevbuf[1] != 'K')) {
mutex_unlock(&bitforce->device_mutex);
applog(LOG_ERR, "BFL%i: Error: Send work reports: %s", bitforce->device_id, pdevbuf);
return false;
}
/* Now start looking for results. Stupid polling every 10ms... */
while (42) {
if (unlikely(work_restart[thr_id].restart))
return 0;
usleep(10000);
i += 10;
memcpy(ob + 8, work->midstate, 32);
memcpy(ob + 8 + 32, work->data + 64, 12);
BFwrite(fdDev, "ZFX", 3);
BFwrite(fdDev, ob, 60);
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
mutex_unlock(&bitforce->device_mutex);
if (opt_debug) {
s = bin2hex(ob + 8, 44);
applog(LOG_DEBUG, "BFL%i: block data: %s", bitforce->device_id, s);
free(s);
}
if (unlikely(!pdevbuf[0])) {
applog(LOG_ERR, "Error reading from BitForce (ZFX)");
return 0;
applog(LOG_ERR, "BFL%i: Error: Send block data returned empty string", bitforce->device_id);
return false;
}
if (unlikely(pdevbuf[0] != 'O' || pdevbuf[1] != 'K')) {
applog(LOG_ERR, "BFL%i: Error: Send block data reports: %s", bitforce->device_id, pdevbuf);
return false;
}
if (pdevbuf[0] != 'B')
return true;
}
static uint64_t bitforce_get_result(struct thr_info *thr, struct work *work)
{
unsigned int delay_time_ms = BITFORCE_CHECK_INTERVAL_MS;
struct cgpu_info *bitforce = thr->cgpu;
int fdDev = bitforce->device_fd;
char pdevbuf[0x100];
char *pnoncebuf;
uint32_t nonce;
if (!fdDev)
return 0;
while (bitforce->wait_ms < BITFORCE_TIMEOUT_MS) {
if (unlikely(work_restart[thr->id].restart))
return 1;
mutex_lock(&bitforce->device_mutex);
BFwrite(fdDev, "ZFX", 3);
BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
mutex_unlock(&bitforce->device_mutex);
if (pdevbuf[0] && pdevbuf[0] != 'B') /* BFL does not respond during throttling */
break;
/* if BFL is throttling, no point checking so quickly */
delay_time_ms = (pdevbuf[0] ? BITFORCE_CHECK_INTERVAL_MS : 2*WORK_CHECK_INTERVAL_MS);
usleep(delay_time_ms * 1000);
bitforce->wait_ms += delay_time_ms;
}
if (bitforce->wait_ms >= BITFORCE_TIMEOUT_MS) {
applog(LOG_ERR, "BFL%i: took longer than 10s", bitforce->device_id);
bitforce->device_last_not_well = time(NULL);
bitforce->device_not_well_reason = REASON_DEV_OVER_HEAT;
bitforce->dev_over_heat_count++;
return 1;
} else if (pdevbuf[0] == 'N') {/* Hashing complete (NONCE-FOUND or NO-NONCE) */
/* Simple timing adjustment */
delay_time_ms = bitforce->sleep_ms;
if (bitforce->wait_ms > (bitforce->sleep_ms + BITFORCE_CHECK_INTERVAL_MS))
bitforce->sleep_ms += (unsigned int) ((double) (bitforce->wait_ms - bitforce->sleep_ms) / 1.6);
else if (bitforce->wait_ms == bitforce->sleep_ms)
bitforce->sleep_ms -= BITFORCE_CHECK_INTERVAL_MS;
if (delay_time_ms != bitforce->sleep_ms)
applog(LOG_DEBUG, "BFL%i: Wait time changed to: %d. Waited: %d", bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms);
}
applog(LOG_DEBUG, "BitForce waited %dms until %s\n", i, pdevbuf);
applog(LOG_DEBUG, "BFL%i: waited %dms until %s", bitforce->device_id, bitforce->wait_ms, pdevbuf);
work->blk.nonce = 0xffffffff;
if (pdevbuf[2] == '-')
return 0xffffffff;
return 0xffffffff; /* No valid nonce found */
else if (pdevbuf[0] == 'I')
return 1; /* Device idle */
else if (strncasecmp(pdevbuf, "NONCE-FOUND", 11)) {
applog(LOG_ERR, "BitForce result reports: %s", pdevbuf);
return 0;
applog(LOG_WARNING, "BFL%i: Error: Get result reports: %s", bitforce->device_id, pdevbuf);
return 1;
}
pnoncebuf = &pdevbuf[12];
@ -244,7 +351,6 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6 @@ -244,7 +351,6 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6
#ifndef __BIG_ENDIAN__
nonce = swab32(nonce);
#endif
submit_nonce(thr, work, nonce);
if (pnoncebuf[8] != ',')
break;
@ -254,11 +360,95 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6 @@ -254,11 +360,95 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6
return 0xffffffff;
}
static void bitforce_shutdown(struct thr_info *thr)
{
struct cgpu_info *bitforce = thr->cgpu;
BFclose(bitforce->device_fd);
bitforce->device_fd = 0;
}
static void biforce_thread_enable(struct thr_info *thr)
{
struct cgpu_info *bitforce = thr->cgpu;
bitforce_init(bitforce);
}
static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint64_t __maybe_unused max_nonce)
{
struct cgpu_info *bitforce = thr->cgpu;
unsigned int sleep_time;
struct timeval tdiff;
uint64_t ret;
bitforce->wait_ms = 0;
ret = bitforce_send_work(thr, work);
/* Initially wait 2/3 of the average cycle time so we can request more
work before full scan is up */
sleep_time = (2 * bitforce->sleep_ms) / 3;
tdiff.tv_sec = sleep_time / 1000;
tdiff.tv_usec = sleep_time * 1000 - (tdiff.tv_sec * 1000000);
if (!restart_wait(&tdiff))
return 1;
bitforce->wait_ms += sleep_time;
queue_request(thr, false);
/* Now wait athe final 1/3rd; no bitforce should be finished by now */
sleep_time = bitforce->sleep_ms - sleep_time;
tdiff.tv_sec = sleep_time / 1000;
tdiff.tv_usec = sleep_time * 1000 - (tdiff.tv_sec * 1000000);
if (!restart_wait(&tdiff))
return 1;
bitforce->wait_ms += sleep_time;
if (ret)
ret = bitforce_get_result(thr, work);
if (!ret) {
ret = 1;
applog(LOG_ERR, "BFL%i: Comms error", bitforce->device_id);
bitforce->device_last_not_well = time(NULL);
bitforce->device_not_well_reason = REASON_DEV_NOSTART;
bitforce->dev_nostart_count++;
/* empty read buffer */
biforce_clear_buffer(bitforce);
}
return ret;
}
static bool bitforce_get_stats(struct cgpu_info *bitforce)
{
return bitforce_get_temp(bitforce);
}
static bool bitforce_thread_init(struct thr_info *thr)
{
struct cgpu_info *bitforce = thr->cgpu;
unsigned int wait;
/* Pause each new thread a random time between 0-100ms
so the devices aren't making calls all at the same time. */
wait = (rand() * MAX_START_DELAY_US)/RAND_MAX;
applog(LOG_DEBUG, "BFL%i: Delaying start by %dms", bitforce->device_id, wait / 1000);
usleep(wait);
return true;
}
struct device_api bitforce_api = {
.dname = "bitforce",
.name = "BFL",
.api_detect = bitforce_detect,
.reinit_device = bitforce_init,
.get_statline_before = get_bitforce_statline_before,
.get_stats = bitforce_get_stats,
.thread_prepare = bitforce_thread_prepare,
.thread_init = bitforce_thread_init,
.scanhash = bitforce_scanhash,
.thread_shutdown = bitforce_shutdown,
.thread_enable = biforce_thread_enable
};

7
miner.h

@ -236,6 +236,7 @@ struct device_api { @@ -236,6 +236,7 @@ struct device_api {
void (*get_statline_before)(char*, struct cgpu_info*);
void (*get_statline)(char*, struct cgpu_info*);
struct api_data *(*get_api_stats)(struct cgpu_info*);
bool (*get_stats)(struct cgpu_info*);
// Thread-specific functions
bool (*thread_prepare)(struct thr_info*);
@ -245,6 +246,7 @@ struct device_api { @@ -245,6 +246,7 @@ struct device_api {
bool (*prepare_work)(struct thr_info*, struct work*);
uint64_t (*scanhash)(struct thr_info*, struct work*, uint64_t);
void (*thread_shutdown)(struct thr_info*);
void (*thread_enable)(struct thr_info*);
};
enum dev_enable {
@ -315,12 +317,17 @@ struct cgpu_info { @@ -315,12 +317,17 @@ struct cgpu_info {
#endif
int device_fd;
};
#ifdef USE_BITFORCE
unsigned int wait_ms;
unsigned int sleep_ms;
#endif
pthread_mutex_t device_mutex;
enum dev_enable deven;
int accepted;
int rejected;
int hw_errors;
unsigned int low_count;
double rolling;
double total_mhashes;
double utility;

Loading…
Cancel
Save