mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-23 13:04:29 +00:00
bflsc driver support for v2 firmware
This commit is contained in:
parent
e0c4d35b28
commit
8f18d4c8b0
150
driver-bflsc.c
150
driver-bflsc.c
@ -30,6 +30,22 @@
|
|||||||
#define BLANK ""
|
#define BLANK ""
|
||||||
#define LFSTR "<LF>"
|
#define LFSTR "<LF>"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Firmware
|
||||||
|
* DRV_V2 expects (beyond V1) the GetInfo to return the chip count
|
||||||
|
* The queues are 40 instead of 20 and are *usually* consumed and filled
|
||||||
|
* in bursts due to e.g. a 16 chip device doing 16 items at a time and
|
||||||
|
* returning 16 results at a time
|
||||||
|
* If the device has varying chip speeds, it will gradually break up the
|
||||||
|
* burst of results as we progress from the last LP
|
||||||
|
* The next LP will restart all chips approximately together again
|
||||||
|
*/
|
||||||
|
enum driver_version {
|
||||||
|
BFLSC_DRVUNDEF = 0,
|
||||||
|
BFLSC_DRV1,
|
||||||
|
BFLSC_DRV2
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* With Firmware 1.0.0 and a result queue of 20 the Max is:
|
* With Firmware 1.0.0 and a result queue of 20 the Max is:
|
||||||
* inprocess = 12
|
* inprocess = 12
|
||||||
@ -37,6 +53,14 @@
|
|||||||
* 64+1+24+1+1+(1+8)*8+1 per line = 164 * 20
|
* 64+1+24+1+1+(1+8)*8+1 per line = 164 * 20
|
||||||
* OK = 3
|
* OK = 3
|
||||||
* Total: 3304
|
* Total: 3304
|
||||||
|
*
|
||||||
|
* With Firmware 1.2.* and a result queue of 40 but a limit of 15 replies:
|
||||||
|
* inprocess = 12
|
||||||
|
* max count = 9
|
||||||
|
* 64+1+24+1+1+1+1+(1+8)*8+1 per line = 166 * 15
|
||||||
|
* OK = 3
|
||||||
|
* Total: 2514
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#define BFLSC_BUFSIZ (0x1000)
|
#define BFLSC_BUFSIZ (0x1000)
|
||||||
|
|
||||||
@ -49,6 +73,7 @@
|
|||||||
#define BFLSC_DI_XLINKPRESENT "XLINK PRESENT"
|
#define BFLSC_DI_XLINKPRESENT "XLINK PRESENT"
|
||||||
#define BFLSC_DI_DEVICESINCHAIN "DEVICES IN CHAIN"
|
#define BFLSC_DI_DEVICESINCHAIN "DEVICES IN CHAIN"
|
||||||
#define BFLSC_DI_CHAINPRESENCE "CHAIN PRESENCE MASK"
|
#define BFLSC_DI_CHAINPRESENCE "CHAIN PRESENCE MASK"
|
||||||
|
#define BFLSC_DI_CHIPS "CHIP PARALLELIZATION"
|
||||||
|
|
||||||
#define FULLNONCE 0x100000000ULL
|
#define FULLNONCE 0x100000000ULL
|
||||||
|
|
||||||
@ -73,6 +98,7 @@ struct bflsc_dev {
|
|||||||
int engines; // each engine represents a 'thread' in a chip
|
int engines; // each engine represents a 'thread' in a chip
|
||||||
char *xlink_mode;
|
char *xlink_mode;
|
||||||
char *xlink_present;
|
char *xlink_present;
|
||||||
|
char *chips;
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
bool dead; // TODO: handle seperate x-link devices failing?
|
bool dead; // TODO: handle seperate x-link devices failing?
|
||||||
@ -103,6 +129,7 @@ struct bflsc_dev {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct bflsc_info {
|
struct bflsc_info {
|
||||||
|
enum driver_version driver_version;
|
||||||
pthread_rwlock_t stat_lock;
|
pthread_rwlock_t stat_lock;
|
||||||
struct thr_info results_thr;
|
struct thr_info results_thr;
|
||||||
uint64_t hashes_sent;
|
uint64_t hashes_sent;
|
||||||
@ -117,6 +144,12 @@ struct bflsc_info {
|
|||||||
bool flash_led;
|
bool flash_led;
|
||||||
bool not_first_work; // allow ignoring the first nonce error
|
bool not_first_work; // allow ignoring the first nonce error
|
||||||
bool fanauto;
|
bool fanauto;
|
||||||
|
int que_size;
|
||||||
|
int que_full_enough;
|
||||||
|
int que_watermark;
|
||||||
|
int que_noncecount;
|
||||||
|
int que_fld_min;
|
||||||
|
int que_fld_max;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BFLSC_XLINKHDR '@'
|
#define BFLSC_XLINKHDR '@'
|
||||||
@ -147,9 +180,15 @@ struct QueueJobStructure {
|
|||||||
#define QUE_RES_LINES_MIN 3
|
#define QUE_RES_LINES_MIN 3
|
||||||
#define QUE_MIDSTATE 0
|
#define QUE_MIDSTATE 0
|
||||||
#define QUE_BLOCKDATA 1
|
#define QUE_BLOCKDATA 1
|
||||||
#define QUE_NONCECOUNT 2
|
|
||||||
#define QUE_FLD_MIN 3
|
#define QUE_NONCECOUNT_V1 2
|
||||||
#define QUE_FLD_MAX 11
|
#define QUE_FLD_MIN_V1 3
|
||||||
|
#define QUE_FLD_MAX_V1 11
|
||||||
|
|
||||||
|
#define QUE_CHIP_V2 2
|
||||||
|
#define QUE_NONCECOUNT_V2 3
|
||||||
|
#define QUE_FLD_MIN_V2 4
|
||||||
|
#define QUE_FLD_MAX_V2 12
|
||||||
|
|
||||||
#define BFLSC_SIGNATURE 0xc1
|
#define BFLSC_SIGNATURE 0xc1
|
||||||
#define BFLSC_EOW 0xfe
|
#define BFLSC_EOW 0xfe
|
||||||
@ -296,12 +335,20 @@ struct SaveString {
|
|||||||
#define BAJ_LATENCY LATENCY_STD
|
#define BAJ_LATENCY LATENCY_STD
|
||||||
#define BAL_LATENCY LATENCY_STD
|
#define BAL_LATENCY LATENCY_STD
|
||||||
#define BAS_LATENCY LATENCY_STD
|
#define BAS_LATENCY LATENCY_STD
|
||||||
|
// For now a BAM doesn't really exist - it's currently 8 independent BASs
|
||||||
#define BAM_LATENCY 2
|
#define BAM_LATENCY 2
|
||||||
|
|
||||||
#define BFLSC_TEMP_SLEEPMS 5
|
#define BFLSC_TEMP_SLEEPMS 5
|
||||||
#define BFLSC_QUE_SIZE 20
|
|
||||||
#define BFLSC_QUE_FULL_ENOUGH 13
|
#define BFLSC_QUE_SIZE_V1 20
|
||||||
#define BFLSC_QUE_WATERMARK 6
|
#define BFLSC_QUE_FULL_ENOUGH_V1 13
|
||||||
|
#define BFLSC_QUE_WATERMARK_V1 6
|
||||||
|
|
||||||
|
// TODO: use 5 batch jobs
|
||||||
|
// TODO: base these numbers on the chip count?
|
||||||
|
#define BFLSC_QUE_SIZE_V2 40
|
||||||
|
#define BFLSC_QUE_FULL_ENOUGH_V2 35
|
||||||
|
#define BFLSC_QUE_WATERMARK_V2 20
|
||||||
|
|
||||||
// Must drop this far below cutoff before resuming work
|
// Must drop this far below cutoff before resuming work
|
||||||
#define BFLSC_TEMP_RECOVER 5
|
#define BFLSC_TEMP_RECOVER 5
|
||||||
@ -318,6 +365,29 @@ static const char *blank = "";
|
|||||||
|
|
||||||
struct device_drv bflsc_drv;
|
struct device_drv bflsc_drv;
|
||||||
|
|
||||||
|
static enum driver_version drv_ver(struct cgpu_info *bflsc, const char *ver)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
if (strcmp(ver, "1.0.0") == 0)
|
||||||
|
return BFLSC_DRV1;
|
||||||
|
|
||||||
|
if (strncmp(ver, "1.0", 3) == 0 || strncmp(ver, "1.1", 3)) {
|
||||||
|
applog(LOG_WARNING, "%s detect (%s) Warning assuming firmware '%s' is Ver1",
|
||||||
|
bflsc->drv->dname, bflsc->device_path, ver);
|
||||||
|
return BFLSC_DRV1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(ver, "1.2", 3) == 0)
|
||||||
|
return BFLSC_DRV2;
|
||||||
|
|
||||||
|
tmp = str_text((char *)ver);
|
||||||
|
applog(LOG_WARNING, "%s detect (%s) Warning unknown firmware '%s' using Ver2",
|
||||||
|
bflsc->drv->dname, bflsc->device_path, tmp);
|
||||||
|
free(tmp);
|
||||||
|
return BFLSC_DRV2;
|
||||||
|
}
|
||||||
|
|
||||||
static void xlinkstr(char *xlink, int dev, struct bflsc_info *sc_info)
|
static void xlinkstr(char *xlink, int dev, struct bflsc_info *sc_info)
|
||||||
{
|
{
|
||||||
if (dev > 0)
|
if (dev > 0)
|
||||||
@ -747,12 +817,7 @@ static bool getinfo(struct cgpu_info *bflsc, int dev)
|
|||||||
}
|
}
|
||||||
if (strcmp(firstname, BFLSC_DI_FIRMWARE) == 0) {
|
if (strcmp(firstname, BFLSC_DI_FIRMWARE) == 0) {
|
||||||
sc_dev.firmware = strdup(fields[0]);
|
sc_dev.firmware = strdup(fields[0]);
|
||||||
if (strcmp(sc_dev.firmware, "1.0.0")) {
|
sc_info->driver_version = drv_ver(bflsc, sc_dev.firmware);
|
||||||
tmp = str_text(items[i]);
|
|
||||||
applog(LOG_WARNING, "%s detect (%s) Warning unknown firmware '%s'",
|
|
||||||
bflsc->drv->dname, bflsc->device_path, tmp);
|
|
||||||
free(tmp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (strcmp(firstname, BFLSC_DI_ENGINES) == 0) {
|
else if (strcmp(firstname, BFLSC_DI_ENGINES) == 0) {
|
||||||
sc_dev.engines = atoi(fields[0]);
|
sc_dev.engines = atoi(fields[0]);
|
||||||
@ -777,10 +842,18 @@ static bool getinfo(struct cgpu_info *bflsc, int dev)
|
|||||||
free(tmp);
|
free(tmp);
|
||||||
goto mata;
|
goto mata;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(firstname, BFLSC_DI_CHIPS) == 0)
|
||||||
|
sc_dev.chips = strdup(fields[0]);
|
||||||
}
|
}
|
||||||
freebreakdown(&count, &firstname, &fields);
|
freebreakdown(&count, &firstname, &fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sc_info->driver_version == BFLSC_DRVUNDEF) {
|
||||||
|
applog(LOG_WARNING, "%s detect (%s) missing %s",
|
||||||
|
bflsc->drv->dname, bflsc->device_path, BFLSC_DI_FIRMWARE);
|
||||||
|
goto ne;
|
||||||
|
}
|
||||||
|
|
||||||
sc_info->sc_devs = calloc(sc_info->sc_count, sizeof(struct bflsc_dev));
|
sc_info->sc_devs = calloc(sc_info->sc_count, sizeof(struct bflsc_dev));
|
||||||
if (unlikely(!sc_info->sc_devs))
|
if (unlikely(!sc_info->sc_devs))
|
||||||
quit(1, "Failed to calloc in getinfo");
|
quit(1, "Failed to calloc in getinfo");
|
||||||
@ -887,6 +960,29 @@ reinit:
|
|||||||
if (!getinfo(bflsc, 0))
|
if (!getinfo(bflsc, 0))
|
||||||
goto unshin;
|
goto unshin;
|
||||||
|
|
||||||
|
switch (sc_info->driver_version) {
|
||||||
|
case BFLSC_DRV1:
|
||||||
|
sc_info->que_size = BFLSC_QUE_SIZE_V1;
|
||||||
|
sc_info->que_full_enough = BFLSC_QUE_FULL_ENOUGH_V1;
|
||||||
|
sc_info->que_watermark = BFLSC_QUE_WATERMARK_V1;
|
||||||
|
sc_info->que_noncecount = QUE_NONCECOUNT_V1;
|
||||||
|
sc_info->que_fld_min = QUE_FLD_MIN_V1;
|
||||||
|
sc_info->que_fld_max = QUE_FLD_MAX_V1;
|
||||||
|
break;
|
||||||
|
case BFLSC_DRV2:
|
||||||
|
case BFLSC_DRVUNDEF:
|
||||||
|
default:
|
||||||
|
sc_info->driver_version = BFLSC_DRV2;
|
||||||
|
|
||||||
|
sc_info->que_size = BFLSC_QUE_SIZE_V2;
|
||||||
|
sc_info->que_full_enough = BFLSC_QUE_FULL_ENOUGH_V2;
|
||||||
|
sc_info->que_watermark = BFLSC_QUE_WATERMARK_V2;
|
||||||
|
sc_info->que_noncecount = QUE_NONCECOUNT_V2;
|
||||||
|
sc_info->que_fld_min = QUE_FLD_MIN_V2;
|
||||||
|
sc_info->que_fld_max = QUE_FLD_MAX_V2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
sc_info->scan_sleep_time = BAS_SCAN_TIME;
|
sc_info->scan_sleep_time = BAS_SCAN_TIME;
|
||||||
sc_info->results_sleep_time = BAS_RES_TIME;
|
sc_info->results_sleep_time = BAS_RES_TIME;
|
||||||
sc_info->default_ms_work = BAS_WORK_TIME;
|
sc_info->default_ms_work = BAS_WORK_TIME;
|
||||||
@ -1280,7 +1376,7 @@ static void process_nonces(struct cgpu_info *bflsc, int dev, char *xlink, char *
|
|||||||
bool res;
|
bool res;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
if (count < QUE_FLD_MIN) {
|
if (count < sc_info->que_fld_min) {
|
||||||
tmp = str_text(data);
|
tmp = str_text(data);
|
||||||
applog(LOG_ERR, "%s%i:%s work returned too small (%d,%s)",
|
applog(LOG_ERR, "%s%i:%s work returned too small (%d,%s)",
|
||||||
bflsc->drv->name, bflsc->device_id, xlink, count, tmp);
|
bflsc->drv->name, bflsc->device_id, xlink, count, tmp);
|
||||||
@ -1289,18 +1385,18 @@ static void process_nonces(struct cgpu_info *bflsc, int dev, char *xlink, char *
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > QUE_FLD_MAX) {
|
if (count > sc_info->que_fld_max) {
|
||||||
applog(LOG_ERR, "%s%i:%s work returned too large (%d) processing %d anyway",
|
applog(LOG_ERR, "%s%i:%s work returned too large (%d) processing %d anyway",
|
||||||
bflsc->drv->name, bflsc->device_id, xlink, count, QUE_FLD_MAX);
|
bflsc->drv->name, bflsc->device_id, xlink, count, sc_info->que_fld_max);
|
||||||
count = QUE_FLD_MAX;
|
count = sc_info->que_fld_max;
|
||||||
inc_hw_errors(bflsc->thr[0]);
|
inc_hw_errors(bflsc->thr[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
num = atoi(fields[QUE_NONCECOUNT]);
|
num = atoi(fields[sc_info->que_noncecount]);
|
||||||
if (num != count - QUE_FLD_MIN) {
|
if (num != count - sc_info->que_fld_min) {
|
||||||
tmp = str_text(data);
|
tmp = str_text(data);
|
||||||
applog(LOG_ERR, "%s%i:%s incorrect data count (%d) will use %d instead from (%s)",
|
applog(LOG_ERR, "%s%i:%s incorrect data count (%d) will use %d instead from (%s)",
|
||||||
bflsc->drv->name, bflsc->device_id, xlink, num, count - QUE_FLD_MAX, tmp);
|
bflsc->drv->name, bflsc->device_id, xlink, num, count - sc_info->que_fld_max, tmp);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
inc_hw_errors(bflsc->thr[0]);
|
inc_hw_errors(bflsc->thr[0]);
|
||||||
}
|
}
|
||||||
@ -1327,7 +1423,7 @@ static void process_nonces(struct cgpu_info *bflsc, int dev, char *xlink, char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
res = false;
|
res = false;
|
||||||
for (i = QUE_FLD_MIN; i < count; i++) {
|
for (i = sc_info->que_fld_min; i < count; i++) {
|
||||||
if (strlen(fields[i]) != 8) {
|
if (strlen(fields[i]) != 8) {
|
||||||
tmp = str_text(data);
|
tmp = str_text(data);
|
||||||
applog(LOG_ERR, "%s%i:%s invalid nonce (%s) will try to process anyway",
|
applog(LOG_ERR, "%s%i:%s invalid nonce (%s) will try to process anyway",
|
||||||
@ -1593,7 +1689,7 @@ re_send:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!getokerr(bflsc, C_QUEJOBSTATUS, &err, &amount, buf, sizeof(buf))) {
|
if (!getokerr(bflsc, C_QUEJOBSTATUS, &err, &amount, buf, sizeof(buf))) {
|
||||||
// TODO: check for QUEUE FULL and set work_queued to BFLSC_QUE_SIZE
|
// TODO: check for QUEUE FULL and set work_queued to sc_info->que_size
|
||||||
// and report a code bug LOG_ERR - coz it should never happen
|
// and report a code bug LOG_ERR - coz it should never happen
|
||||||
|
|
||||||
// Try twice
|
// Try twice
|
||||||
@ -1648,7 +1744,7 @@ static bool bflsc_queue_full(struct cgpu_info *bflsc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dev == -1) {
|
if (dev == -1) {
|
||||||
que = BFLSC_QUE_SIZE * 10; // 10x is certainly above the MAX it could be
|
que = sc_info->que_size * 10; // 10x is certainly above the MAX it could be
|
||||||
// The first device with the smallest amount queued
|
// The first device with the smallest amount queued
|
||||||
for (i = 0; i < sc_info->sc_count; i++) {
|
for (i = 0; i < sc_info->sc_count; i++) {
|
||||||
if (i != tried && sc_info->sc_devs[i].work_queued < que &&
|
if (i != tried && sc_info->sc_devs[i].work_queued < que &&
|
||||||
@ -1657,7 +1753,7 @@ static bool bflsc_queue_full(struct cgpu_info *bflsc)
|
|||||||
que = sc_info->sc_devs[i].work_queued;
|
que = sc_info->sc_devs[i].work_queued;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (que > BFLSC_QUE_FULL_ENOUGH)
|
if (que > sc_info->que_full_enough)
|
||||||
dev = -1;
|
dev = -1;
|
||||||
}
|
}
|
||||||
rd_unlock(&(sc_info->stat_lock));
|
rd_unlock(&(sc_info->stat_lock));
|
||||||
@ -1740,10 +1836,10 @@ static int64_t bflsc_scanwork(struct thr_info *thr)
|
|||||||
waited = restart_wait(sc_info->scan_sleep_time);
|
waited = restart_wait(sc_info->scan_sleep_time);
|
||||||
if (waited == ETIMEDOUT) {
|
if (waited == ETIMEDOUT) {
|
||||||
unsigned int old_sleep_time, new_sleep_time = 0;
|
unsigned int old_sleep_time, new_sleep_time = 0;
|
||||||
int min_queued = BFLSC_QUE_SIZE;
|
int min_queued = sc_info->que_size;
|
||||||
/* Only adjust the scan_sleep_time if we did not receive a
|
/* Only adjust the scan_sleep_time if we did not receive a
|
||||||
* restart message while waiting. Try to adjust sleep time
|
* restart message while waiting. Try to adjust sleep time
|
||||||
* so we drop to BFLSC_QUE_WATERMARK before getting more work.
|
* so we drop to sc_info->que_watermark before getting more work.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rd_lock(&sc_info->stat_lock);
|
rd_lock(&sc_info->stat_lock);
|
||||||
@ -1756,9 +1852,9 @@ static int64_t bflsc_scanwork(struct thr_info *thr)
|
|||||||
new_sleep_time = old_sleep_time;
|
new_sleep_time = old_sleep_time;
|
||||||
|
|
||||||
/* Increase slowly but decrease quickly */
|
/* Increase slowly but decrease quickly */
|
||||||
if (min_queued > BFLSC_QUE_WATERMARK && old_sleep_time < BFLSC_MAX_SLEEP)
|
if (min_queued > sc_info->que_watermark && old_sleep_time < BFLSC_MAX_SLEEP)
|
||||||
new_sleep_time = old_sleep_time * 21 / 20;
|
new_sleep_time = old_sleep_time * 21 / 20;
|
||||||
else if (min_queued < BFLSC_QUE_WATERMARK)
|
else if (min_queued < sc_info->que_watermark)
|
||||||
new_sleep_time = old_sleep_time * 2 / 3;
|
new_sleep_time = old_sleep_time * 2 / 3;
|
||||||
|
|
||||||
/* Do not sleep more than BFLSC_MAX_SLEEP so we can always
|
/* Do not sleep more than BFLSC_MAX_SLEEP so we can always
|
||||||
|
Loading…
x
Reference in New Issue
Block a user