From b9968156bae95f14a30b8befb3e74d8d620f1920 Mon Sep 17 00:00:00 2001 From: Kano Date: Wed, 13 Feb 2013 11:13:30 +1100 Subject: [PATCH] MMQ rewrite the last of the old scanhash loop and drastically reduce CPU --- driver-modminer.c | 78 +++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 53 deletions(-) diff --git a/driver-modminer.c b/driver-modminer.c index 22812aa5..10d42a3b 100644 --- a/driver-modminer.c +++ b/driver-modminer.c @@ -595,8 +595,6 @@ static bool modminer_fpga_prepare(struct thr_info *thr) struct modminer_fpga_state *state; state = thr->cgpu_data = calloc(1, sizeof(struct modminer_fpga_state)); - state->next_work_cmd[0] = MODMINER_SEND_WORK; - state->next_work_cmd[1] = modminer->fpgaid; state->shares_to_good = MODMINER_EARLY_UP; state->overheated = false; @@ -773,24 +771,19 @@ static void get_modminer_statline_before(char *buf, struct cgpu_info *modminer) strcat(buf, info); } -static bool modminer_prepare_next_work(struct modminer_fpga_state *state, struct work *work) -{ - char *midstate = state->next_work_cmd + 2; - char *taildata = midstate + 32; - if (!(memcmp(midstate, work->midstate, 32) || memcmp(taildata, work->data + 64, 12))) - return false; - memcpy(midstate, work->midstate, 32); - memcpy(taildata, work->data + 64, 12); - return true; -} - -static bool modminer_start_work(struct thr_info *thr) +static bool modminer_start_work(struct thr_info *thr, struct work *work) { struct cgpu_info *modminer = thr->cgpu; struct modminer_fpga_state *state = thr->cgpu_data; int err, amount; + char cmd[48]; bool sta; + cmd[0] = MODMINER_SEND_WORK; + cmd[1] = modminer->fpgaid; + memcpy(&cmd[2], work->midstate, 32); + memcpy(&cmd[34], work->data + 64, 12); + if (state->first_work.tv_sec == 0) gettimeofday(&state->first_work, NULL); @@ -799,7 +792,7 @@ static bool modminer_start_work(struct thr_info *thr) mutex_lock(modminer->modminer_mutex); - if ((err = usb_write(modminer, (char *)(state->next_work_cmd), 46, &amount, C_SENDWORK)) < 0 || amount != 46) { + if ((err = usb_write(modminer, cmd, 46, &amount, C_SENDWORK)) < 0 || amount != 46) { mutex_unlock(modminer->modminer_mutex); applog(LOG_ERR, "%s%u: Start work failed (%d:%d)", @@ -809,7 +802,6 @@ static bool modminer_start_work(struct thr_info *thr) } gettimeofday(&state->tv_workstart, NULL); - state->hashes = 0; sta = get_status(modminer, "start work", C_SENDWORKSTATUS); @@ -903,11 +895,10 @@ static const double processtime = 17.0; // 160Mhz is 26.84 - when overheated ensure we don't throw away shares static const double overheattime = 26.9; -static uint64_t modminer_process_results(struct thr_info *thr) +static uint64_t modminer_process_results(struct thr_info *thr, struct work *work) { struct cgpu_info *modminer = thr->cgpu; struct modminer_fpga_state *state = thr->cgpu_data; - struct work *work = &state->running_work; struct timeval now; char cmd[2]; uint32_t nonce; @@ -931,14 +922,14 @@ static uint64_t modminer_process_results(struct thr_info *thr) timeoutloop = 0; temploop = 0; - while (1) { + while (0x80085) { mutex_lock(modminer->modminer_mutex); if ((err = usb_write(modminer, cmd, 2, &amount, C_REQUESTWORKSTATUS)) < 0 || amount != 2) { mutex_unlock(modminer->modminer_mutex); // timeoutloop never resets so the timeouts can't // accumulate much during a single item of work - if (err == LIBUSB_ERROR_TIMEOUT && ++timeoutloop < 10) { + if (err == LIBUSB_ERROR_TIMEOUT && ++timeoutloop < 5) { state->timeout_fail++; goto tryagain; } @@ -1033,8 +1024,8 @@ tryagain: break; if (state->overheated == true) { - // don't check every time - if (++temploop > 30) { + // don't check every time (every ~1/2 sec) + if (++temploop > 4) { check_temperature(thr); temploop = 0; } @@ -1050,7 +1041,8 @@ tryagain: if (tdiff(&now, &state->tv_workstart) > timeout) break; - nmsleep(10); + // 1/10th sec to lower CPU usage + nmsleep(100); if (work_restart(thr)) break; } @@ -1064,21 +1056,17 @@ tryagain: // Overheat will complete the nonce range if (hashes > 0xffffffff) hashes = 0xffffffff; - else - if (hashes <= state->hashes) - hashes = 1; - else - hashes -= state->hashes; - state->hashes += hashes; + + work->blk.nonce = 0xffffffff; + return hashes; } static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_t __maybe_unused max_nonce) { struct modminer_fpga_state *state = thr->cgpu_data; - int64_t hashes = 0; - bool startwork; struct timeval tv1, tv2; + int64_t hashes; // Device is gone if (thr->cgpu->usbinfo.nodev) @@ -1087,8 +1075,6 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ // Don't start new work if overheated if (state->overheated == true) { gettimeofday(&tv1, NULL); - if (state->work_running) - state->work_running = false; while (state->overheated == true) { check_temperature(thr); @@ -1100,7 +1086,7 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ if (state->overheated == true) { gettimeofday(&tv2, NULL); - // give up on this work item + // give up on this work item after 30s if (work_restart(thr) || tdiff(&tv2, &tv1) > 30) return 0; @@ -1110,27 +1096,13 @@ static int64_t modminer_scanhash(struct thr_info *thr, struct work *work, int64_ } } - startwork = modminer_prepare_next_work(state, work); - if (state->work_running) { - hashes = modminer_process_results(thr); - if (hashes == -1) - return hashes; - - if (work_restart(thr)) { - state->work_running = false; - return 0; - } - } else - state->work_running = true; + if (!modminer_start_work(thr, work)) + return -1; - if (startwork) { - if (!modminer_start_work(thr)) - return -1; - __copy_work(&state->running_work, work); - } + hashes = modminer_process_results(thr, work); + if (hashes == -1) + return hashes; - // This is intentionally early - work->blk.nonce += hashes; return hashes; }