|
|
@@ -72,6 +72,7 @@ struct knc_core_state {
|
|
|
int slot;
|
|
|
uint32_t nonce;
|
|
|
} last_nonce;
|
|
|
+ uint32_t last_nonce_verified;
|
|
|
uint32_t works;
|
|
|
uint32_t shares;
|
|
|
uint32_t errors;
|
|
|
@@ -633,7 +634,7 @@ static void knc_core_failure(struct knc_core_state *core)
|
|
|
}
|
|
|
|
|
|
static
|
|
|
-void knc_core_handle_nonce(struct thr_info *thr, struct knc_core_state *core, int slot, uint32_t nonce)
|
|
|
+void knc_core_handle_nonce(struct thr_info *thr, struct knc_core_state *core, int slot, uint32_t nonce, bool comm_errors)
|
|
|
{
|
|
|
int i;
|
|
|
if (!slot)
|
|
|
@@ -646,17 +647,23 @@ void knc_core_handle_nonce(struct thr_info *thr, struct knc_core_state *core, in
|
|
|
if (slot == core->workslot[i].slot && core->workslot[i].work) {
|
|
|
struct cgpu_info * const proc = core->die->proc;
|
|
|
struct thr_info * const corethr = proc->thr[0];
|
|
|
-
|
|
|
- applog(LOG_INFO, "%"PRIpreprv"[%d] found nonce %08x", proc->proc_repr, core->core, nonce);
|
|
|
+ char *comm_err_str = comm_errors ? " (comm error)" : "";
|
|
|
+
|
|
|
+ applog(LOG_INFO, "%"PRIpreprv"[%d] found nonce %08x%s", proc->proc_repr, core->core, nonce, comm_err_str);
|
|
|
if (submit_nonce(corethr, core->workslot[i].work, nonce)) {
|
|
|
- /* Good share */
|
|
|
- core->shares++;
|
|
|
- core->die->knc->shares++;
|
|
|
- hashes_done2(corethr, 0x100000000, NULL);
|
|
|
+ if (nonce != core->last_nonce_verified) {
|
|
|
+ /* Good share */
|
|
|
+ core->shares++;
|
|
|
+ core->die->knc->shares++;
|
|
|
+ hashes_done2(corethr, 0x100000000, NULL);
|
|
|
+ core->last_nonce_verified = nonce;
|
|
|
+ } else {
|
|
|
+ applog(LOG_INFO, "%"PRIpreprv"[%d] duplicate nonce %08x%s", proc->proc_repr, core->core, nonce, comm_err_str);
|
|
|
+ }
|
|
|
/* This core is useful. Ignore any errors */
|
|
|
core->errors_now = 0;
|
|
|
} else {
|
|
|
- applog(LOG_INFO, "%"PRIpreprv"[%d] hwerror nonce %08x", proc->proc_repr, core->core, nonce);
|
|
|
+ applog(LOG_INFO, "%"PRIpreprv"[%d] hwerror nonce %08x%s", proc->proc_repr, core->core, nonce, comm_err_str);
|
|
|
/* Bad share */
|
|
|
knc_core_failure(core);
|
|
|
}
|
|
|
@@ -664,7 +671,7 @@ void knc_core_handle_nonce(struct thr_info *thr, struct knc_core_state *core, in
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int knc_core_process_report(struct thr_info *thr, struct knc_core_state *core, uint8_t *response)
|
|
|
+static int knc_core_process_report(struct thr_info *thr, struct knc_core_state *core, uint8_t *response, bool comm_errors)
|
|
|
{
|
|
|
struct cgpu_info * const proc = core->die->proc;
|
|
|
struct knc_report *report = &core->report;
|
|
|
@@ -680,45 +687,47 @@ static int knc_core_process_report(struct thr_info *thr, struct knc_core_state *
|
|
|
break;
|
|
|
}
|
|
|
while(n-- > 0) {
|
|
|
- knc_core_handle_nonce(thr, core, report->nonce[n].slot, report->nonce[n].nonce);
|
|
|
+ knc_core_handle_nonce(thr, core, report->nonce[n].slot, report->nonce[n].nonce, comm_errors);
|
|
|
}
|
|
|
|
|
|
- if (report->active_slot && core->workslot[0].slot != report->active_slot) {
|
|
|
- had_event = true;
|
|
|
- applog(LOG_INFO, "%"PRIpreprv"[%d]: New work %d %d / %d %d %d", proc->proc_repr, core->core, report->active_slot, report->next_slot, core->workslot[0].slot, core->workslot[1].slot, core->workslot[2].slot);
|
|
|
- /* Core switched to next work */
|
|
|
- if (core->workslot[0].work) {
|
|
|
- core->die->knc->completed++;
|
|
|
- core->completed++;
|
|
|
- applog(LOG_INFO, "%"PRIpreprv"[%d]: Work completed!", proc->proc_repr, core->core);
|
|
|
- KNC_FREE_WORK(core->workslot[0].work);
|
|
|
- }
|
|
|
- core->workslot[0] = core->workslot[1];
|
|
|
- core->workslot[1].work = NULL;
|
|
|
- core->workslot[1].slot = -1;
|
|
|
-
|
|
|
- /* or did it switch directly to pending work? */
|
|
|
- if (report->active_slot == core->workslot[2].slot) {
|
|
|
- applog(LOG_INFO, "%"PRIpreprv"[%d]: New work %d %d %d %d (pending)", proc->proc_repr, core->core, report->active_slot, core->workslot[0].slot, core->workslot[1].slot, core->workslot[2].slot);
|
|
|
- if (core->workslot[0].work)
|
|
|
+ if (!comm_errors) {
|
|
|
+ if (report->active_slot && core->workslot[0].slot != report->active_slot) {
|
|
|
+ had_event = true;
|
|
|
+ applog(LOG_INFO, "%"PRIpreprv"[%d]: New work %d %d / %d %d %d", proc->proc_repr, core->core, report->active_slot, report->next_slot, core->workslot[0].slot, core->workslot[1].slot, core->workslot[2].slot);
|
|
|
+ /* Core switched to next work */
|
|
|
+ if (core->workslot[0].work) {
|
|
|
+ core->die->knc->completed++;
|
|
|
+ core->completed++;
|
|
|
+ applog(LOG_INFO, "%"PRIpreprv"[%d]: Work completed!", proc->proc_repr, core->core);
|
|
|
KNC_FREE_WORK(core->workslot[0].work);
|
|
|
- core->workslot[0] = core->workslot[2];
|
|
|
+ }
|
|
|
+ core->workslot[0] = core->workslot[1];
|
|
|
+ core->workslot[1].work = NULL;
|
|
|
+ core->workslot[1].slot = -1;
|
|
|
+
|
|
|
+ /* or did it switch directly to pending work? */
|
|
|
+ if (report->active_slot == core->workslot[2].slot) {
|
|
|
+ applog(LOG_INFO, "%"PRIpreprv"[%d]: New work %d %d %d %d (pending)", proc->proc_repr, core->core, report->active_slot, core->workslot[0].slot, core->workslot[1].slot, core->workslot[2].slot);
|
|
|
+ if (core->workslot[0].work)
|
|
|
+ KNC_FREE_WORK(core->workslot[0].work);
|
|
|
+ core->workslot[0] = core->workslot[2];
|
|
|
+ core->workslot[2].work = NULL;
|
|
|
+ core->workslot[2].slot = -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (report->next_state && core->workslot[2].slot > 0 && (core->workslot[2].slot == report->next_slot || report->next_slot == -1)) {
|
|
|
+ had_event = true;
|
|
|
+ applog(LOG_INFO, "%"PRIpreprv"[%d]: Accepted work %d %d %d %d (pending)", proc->proc_repr, core->core, report->active_slot, core->workslot[0].slot, core->workslot[1].slot, core->workslot[2].slot);
|
|
|
+ /* core accepted next work */
|
|
|
+ if (core->workslot[1].work)
|
|
|
+ KNC_FREE_WORK(core->workslot[1].work);
|
|
|
+ core->workslot[1] = core->workslot[2];
|
|
|
core->workslot[2].work = NULL;
|
|
|
core->workslot[2].slot = -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (report->next_state && core->workslot[2].slot > 0 && (core->workslot[2].slot == report->next_slot || report->next_slot == -1)) {
|
|
|
- had_event = true;
|
|
|
- applog(LOG_INFO, "%"PRIpreprv"[%d]: Accepted work %d %d %d %d (pending)", proc->proc_repr, core->core, report->active_slot, core->workslot[0].slot, core->workslot[1].slot, core->workslot[2].slot);
|
|
|
- /* core accepted next work */
|
|
|
- if (core->workslot[1].work)
|
|
|
- KNC_FREE_WORK(core->workslot[1].work);
|
|
|
- core->workslot[1] = core->workslot[2];
|
|
|
- core->workslot[2].work = NULL;
|
|
|
- core->workslot[2].slot = -1;
|
|
|
- }
|
|
|
-
|
|
|
if (core->workslot[2].work && knc_transfer_completed(core->die->knc, core->transfer_stamp)) {
|
|
|
had_event = true;
|
|
|
applog(LOG_INFO, "%"PRIpreprv"[%d]: Setwork failed?", proc->proc_repr, core->core);
|
|
|
@@ -750,11 +759,14 @@ static void knc_process_responses(struct thr_info *thr)
|
|
|
/* Invert KNC_ACCEPTED to simplify logics below */
|
|
|
if (response_info->type == KNC_SETWORK && !KNC_IS_ERROR(status))
|
|
|
status ^= KNC_ACCEPTED;
|
|
|
+ bool comm_errors = false;
|
|
|
if (core->die->version != KNC_VERSION_JUPITER && status != 0) {
|
|
|
- applog(LOG_INFO, "%"PRIpreprv"[%d]: Communication error (%x / %d)", proc->proc_repr, core->core, status, i);
|
|
|
- if (status == KNC_ACCEPTED) {
|
|
|
+ if (response_info->type == KNC_SETWORK && status == KNC_ACCEPTED) {
|
|
|
/* Core refused our work vector. Likely out of sync. Reset it */
|
|
|
core->inuse = false;
|
|
|
+ } else {
|
|
|
+ applog(LOG_INFO, "%"PRIpreprv"[%d]: Communication error (%x / %d)", proc->proc_repr, core->core, status, i);
|
|
|
+ comm_errors = true;
|
|
|
}
|
|
|
knc_core_failure(core);
|
|
|
}
|
|
|
@@ -762,7 +774,7 @@ static void knc_process_responses(struct thr_info *thr)
|
|
|
case KNC_REPORT:
|
|
|
case KNC_SETWORK:
|
|
|
/* Should we care about failed SETWORK explicit? Or simply handle it by next state not loaded indication in reports? */
|
|
|
- knc_core_process_report(thr, core, rxbuf);
|
|
|
+ knc_core_process_report(thr, core, rxbuf, comm_errors);
|
|
|
break;
|
|
|
default:
|
|
|
break;
|