/ driver-klondike.c
driver-klondike.c
1 /* 2 * Copyright 2013 Andrew Smith 3 * Copyright 2013 Con Kolivas 4 * Copyright 2013 Chris Savery 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 3 of the License, or (at your option) 9 * any later version. See COPYING for more details. 10 */ 11 12 #include <float.h> 13 #include <limits.h> 14 #include <pthread.h> 15 #include <stdint.h> 16 #include <stdio.h> 17 #include <strings.h> 18 #include <sys/time.h> 19 #include <unistd.h> 20 #include <math.h> 21 22 #include "config.h" 23 24 #include "compat.h" 25 #include "miner.h" 26 #include "usbutils.h" 27 28 #define K1 "K1" 29 #define K16 "K16" 30 #define K64 "K64" 31 32 static const char *msg_detect_send = "DSend"; 33 static const char *msg_detect_reply = "DReply"; 34 static const char *msg_send = "Send"; 35 static const char *msg_reply = "Reply"; 36 37 #define KLN_CMD_ABORT 'A' 38 #define KLN_CMD_CONFIG 'C' 39 #define KLN_CMD_ENABLE 'E' 40 #define KLN_CMD_IDENT 'I' 41 #define KLN_CMD_NONCE '=' 42 #define KLN_CMD_STATUS 'S' 43 #define KLN_CMD_WORK 'W' 44 45 #define KLN_CMD_ENABLE_OFF '0' 46 #define KLN_CMD_ENABLE_ON '1' 47 48 #define MIDSTATE_BYTES 32 49 #define MERKLE_OFFSET 64 50 #define MERKLE_BYTES 12 51 52 #define REPLY_SIZE 15 // adequate for all types of replies 53 #define MAX_KLINES 1024 // unhandled reply limit 54 #define REPLY_WAIT_TIME 100 // poll interval for a cmd waiting it's reply 55 #define CMD_REPLY_RETRIES 8 // how many retries for cmds 56 #define MAX_WORK_COUNT 4 // for now, must be binary multiple and match firmware 57 #define TACH_FACTOR 87890 // fan rpm divisor 58 59 #define KLN_KILLWORK_TEMP 53.5 60 #define KLN_COOLED_DOWN 45.5 61 62 /* 63 * Work older than 5s will already be completed 64 * FYI it must not be possible to complete 256 work 65 * items this quickly on a single device - 66 * thus limited to 219.9GH/s per device 67 */ 68 #define OLD_WORK_MS ((int)(5 * 1000)) 69 70 /* 71 * How many incorrect slave counts to ignore in a row 72 * 2 means it allows random grabage returned twice 73 * Until slaves are implemented, this should never occur 74 * so allowing 2 in a row should ignore random errros 75 */ 76 #define KLN_ISS_IGNORE 2 77 78 /* 79 * If the queue status hasn't been updated for this long then do it now 80 * 5GH/s = 859ms per full nonce range 81 */ 82 #define LATE_UPDATE_MS ((int)(2.5 * 1000)) 83 84 // If 5 late updates in a row, try to reset the device 85 #define LATE_UPDATE_LIMIT 5 86 87 // If the reset fails sleep for 1s 88 #define LATE_UPDATE_SLEEP_MS 1000 89 90 // However give up after 8s 91 #define LATE_UPDATE_NODEV_MS ((int)(8.0 * 1000)) 92 93 struct device_drv klondike_drv; 94 95 typedef struct klondike_header { 96 uint8_t cmd; 97 uint8_t dev; 98 uint8_t buf[REPLY_SIZE-2]; 99 } HEADER; 100 101 #define K_2(_bytes) ((int)(_bytes[0]) + \ 102 ((int)(_bytes[1]) << 8)) 103 104 #define K_4(_bytes) ((uint64_t)(_bytes[0]) + \ 105 ((uint64_t)(_bytes[1]) << 8) + \ 106 ((uint64_t)(_bytes[2]) << 16) + \ 107 ((uint64_t)(_bytes[3]) << 24)) 108 109 #define K_SERIAL(_serial) K_4(_serial) 110 #define K_HASHCOUNT(_hashcount) K_2(_hashcount) 111 #define K_MAXCOUNT(_maxcount) K_2(_maxcount) 112 #define K_NONCE(_nonce) K_4(_nonce) 113 #define K_HASHCLOCK(_hashclock) K_2(_hashclock) 114 115 #define SET_HASHCLOCK(_hashclock, _value) do { \ 116 (_hashclock)[0] = (uint8_t)((_value) & 0xff); \ 117 (_hashclock)[1] = (uint8_t)(((_value) >> 8) & 0xff); \ 118 } while(0) 119 120 #define KSENDHD(_add) (sizeof(uint8_t) + sizeof(uint8_t) + _add) 121 122 typedef struct klondike_id { 123 uint8_t cmd; 124 uint8_t dev; 125 uint8_t version; 126 uint8_t product[7]; 127 uint8_t serial[4]; 128 } IDENTITY; 129 130 typedef struct klondike_status { 131 uint8_t cmd; 132 uint8_t dev; 133 uint8_t state; 134 uint8_t chipcount; 135 uint8_t slavecount; 136 uint8_t workqc; 137 uint8_t workid; 138 uint8_t temp; 139 uint8_t fanspeed; 140 uint8_t errorcount; 141 uint8_t hashcount[2]; 142 uint8_t maxcount[2]; 143 uint8_t noise; 144 } WORKSTATUS; 145 146 typedef struct _worktask { 147 uint8_t cmd; 148 uint8_t dev; 149 uint8_t workid; 150 uint8_t midstate[32]; 151 uint8_t merkle[12]; 152 } WORKTASK; 153 154 typedef struct _workresult { 155 uint8_t cmd; 156 uint8_t dev; 157 uint8_t workid; 158 uint8_t nonce[4]; 159 } WORKRESULT; 160 161 typedef struct klondike_cfg { 162 uint8_t cmd; 163 uint8_t dev; 164 uint8_t hashclock[2]; 165 uint8_t temptarget; 166 uint8_t tempcritical; 167 uint8_t fantarget; 168 uint8_t pad2; 169 } WORKCFG; 170 171 typedef struct kline { 172 union { 173 HEADER hd; 174 IDENTITY id; 175 WORKSTATUS ws; 176 WORKTASK wt; 177 WORKRESULT wr; 178 WORKCFG cfg; 179 }; 180 } KLINE; 181 182 #define zero_kline(_kline) memset((void *)(_kline), 0, sizeof(KLINE)); 183 184 typedef struct device_info { 185 uint32_t noncecount; 186 uint32_t nextworkid; 187 uint16_t lasthashcount; 188 uint64_t totalhashcount; 189 uint32_t rangesize; 190 uint32_t *chipstats; 191 } DEVINFO; 192 193 typedef struct klist { 194 struct klist *prev; 195 struct klist *next; 196 KLINE kline; 197 struct timeval tv_when; 198 int block_seq; 199 bool ready; 200 bool working; 201 } KLIST; 202 203 typedef struct jobque { 204 int workqc; 205 struct timeval last_update; 206 bool overheat; 207 bool flushed; 208 int late_update_count; 209 int late_update_sequential; 210 } JOBQUE; 211 212 struct klondike_info { 213 pthread_rwlock_t stat_lock; 214 struct thr_info replies_thr; 215 cglock_t klist_lock; 216 KLIST *used; 217 KLIST *free; 218 int kline_count; 219 int used_count; 220 int block_seq; 221 KLIST *status; 222 DEVINFO *devinfo; 223 KLIST *cfg; 224 JOBQUE *jobque; 225 int noncecount; 226 uint64_t hashcount; 227 uint64_t errorcount; 228 uint64_t noisecount; 229 int incorrect_slave_sequential; 230 231 // us Delay from USB reply to being processed 232 double delay_count; 233 double delay_total; 234 double delay_min; 235 double delay_max; 236 237 struct timeval tv_last_nonce_received; 238 239 // Time from recieving one nonce to the next 240 double nonce_count; 241 double nonce_total; 242 double nonce_min; 243 double nonce_max; 244 245 int wque_size; 246 int wque_cleared; 247 248 bool initialised; 249 }; 250 251 static KLIST *new_klist_set(struct cgpu_info *klncgpu) 252 { 253 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 254 KLIST *klist = NULL; 255 int i; 256 257 klist = calloc(MAX_KLINES, sizeof(*klist)); 258 if (!klist) 259 quit(1, "Failed to calloc klist - when old count=%d", klninfo->kline_count); 260 261 klninfo->kline_count += MAX_KLINES; 262 263 klist[0].prev = NULL; 264 klist[0].next = &(klist[1]); 265 for (i = 1; i < MAX_KLINES-1; i++) { 266 klist[i].prev = &klist[i-1]; 267 klist[i].next = &klist[i+1]; 268 } 269 klist[MAX_KLINES-1].prev = &(klist[MAX_KLINES-2]); 270 klist[MAX_KLINES-1].next = NULL; 271 272 return klist; 273 } 274 275 static KLIST *allocate_kitem(struct cgpu_info *klncgpu) 276 { 277 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 278 KLIST *kitem = NULL; 279 int ran_out = 0; 280 char errbuf[1024]; 281 282 cg_wlock(&klninfo->klist_lock); 283 284 if (klninfo->free == NULL) { 285 ran_out = klninfo->kline_count; 286 klninfo->free = new_klist_set(klncgpu); 287 snprintf(errbuf, sizeof(errbuf), 288 "%s%i: KLINE count exceeded %d, now %d", 289 klncgpu->drv->name, klncgpu->device_id, 290 ran_out, klninfo->kline_count); 291 } 292 293 kitem = klninfo->free; 294 295 klninfo->free = klninfo->free->next; 296 if (klninfo->free) 297 klninfo->free->prev = NULL; 298 299 kitem->next = klninfo->used; 300 kitem->prev = NULL; 301 if (kitem->next) 302 kitem->next->prev = kitem; 303 klninfo->used = kitem; 304 305 kitem->ready = false; 306 kitem->working = false; 307 308 memset((void *)&(kitem->kline), 0, sizeof(kitem->kline)); 309 310 klninfo->used_count++; 311 312 cg_wunlock(&klninfo->klist_lock); 313 314 if (ran_out > 0) 315 applog(LOG_WARNING, "%s", errbuf); 316 317 return kitem; 318 } 319 320 static KLIST *release_kitem(struct cgpu_info *klncgpu, KLIST *kitem) 321 { 322 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 323 324 cg_wlock(&klninfo->klist_lock); 325 326 if (kitem == klninfo->used) 327 klninfo->used = kitem->next; 328 329 if (kitem->next) 330 kitem->next->prev = kitem->prev; 331 if (kitem->prev) 332 kitem->prev->next = kitem->next; 333 334 kitem->next = klninfo->free; 335 if (klninfo->free) 336 klninfo->free->prev = kitem; 337 338 kitem->prev = NULL; 339 340 klninfo->free = kitem; 341 342 klninfo->used_count--; 343 344 cg_wunlock(&klninfo->klist_lock); 345 346 return NULL; 347 } 348 349 static double cvtKlnToC(uint8_t temp) 350 { 351 double Rt, stein, celsius; 352 353 if (temp == 0) 354 return 0.0; 355 356 Rt = 1000.0 * 255.0 / (double)temp - 1000.0; 357 358 stein = log(Rt / 2200.0) / 3987.0; 359 360 stein += 1.0 / (double)(25.0 + 273.15); 361 362 celsius = (1.0 / stein) - 273.15; 363 364 // For display of bad data 365 if (celsius < 0.0) 366 celsius = 0.0; 367 if (celsius > 200.0) 368 celsius = 200.0; 369 370 return celsius; 371 } 372 373 static int cvtCToKln(double deg) 374 { 375 double Rt, stein, temp; 376 377 if (deg < 0.0) 378 deg = 0.0; 379 380 stein = 1.0 / (deg + 273.15); 381 382 stein -= 1.0 / (double)(25.0 + 273.15); 383 384 Rt = exp(stein * 3987.0) * 2200.0; 385 386 if (Rt == -1000.0) 387 Rt++; 388 389 temp = 1000.0 * 256.0 / (Rt + 1000.0); 390 391 if (temp > 255) 392 temp = 255; 393 if (temp < 0) 394 temp = 0; 395 396 return (int)temp; 397 } 398 399 // Change this to LOG_WARNING if you wish to always see the replies 400 #define READ_DEBUG LOG_DEBUG 401 402 static void display_kline(struct cgpu_info *klncgpu, KLINE *kline, const char *msg) 403 { 404 char *hexdata; 405 406 switch (kline->hd.cmd) { 407 case KLN_CMD_NONCE: 408 applog(READ_DEBUG, 409 "%s%i:%d %s work [%c] dev=%d workid=%d" 410 " nonce=0x%08x", 411 klncgpu->drv->name, klncgpu->device_id, 412 (int)(kline->wr.dev), msg, kline->wr.cmd, 413 (int)(kline->wr.dev), 414 (int)(kline->wr.workid), 415 (unsigned int)K_NONCE(kline->wr.nonce) - 0xC0); 416 break; 417 case KLN_CMD_STATUS: 418 case KLN_CMD_WORK: 419 case KLN_CMD_ENABLE: 420 case KLN_CMD_ABORT: 421 applog(READ_DEBUG, 422 "%s%i:%d %s status [%c] dev=%d chips=%d" 423 " slaves=%d workcq=%d workid=%d temp=%d fan=%d" 424 " errors=%d hashes=%d max=%d noise=%d", 425 klncgpu->drv->name, klncgpu->device_id, 426 (int)(kline->ws.dev), msg, kline->ws.cmd, 427 (int)(kline->ws.dev), 428 (int)(kline->ws.chipcount), 429 (int)(kline->ws.slavecount), 430 (int)(kline->ws.workqc), 431 (int)(kline->ws.workid), 432 (int)(kline->ws.temp), 433 (int)(kline->ws.fanspeed), 434 (int)(kline->ws.errorcount), 435 K_HASHCOUNT(kline->ws.hashcount), 436 K_MAXCOUNT(kline->ws.maxcount), 437 (int)(kline->ws.noise)); 438 break; 439 case KLN_CMD_CONFIG: 440 applog(READ_DEBUG, 441 "%s%i:%d %s config [%c] dev=%d clock=%d" 442 " temptarget=%d tempcrit=%d fan=%d", 443 klncgpu->drv->name, klncgpu->device_id, 444 (int)(kline->cfg.dev), msg, kline->cfg.cmd, 445 (int)(kline->cfg.dev), 446 K_HASHCLOCK(kline->cfg.hashclock), 447 (int)(kline->cfg.temptarget), 448 (int)(kline->cfg.tempcritical), 449 (int)(kline->cfg.fantarget)); 450 break; 451 case KLN_CMD_IDENT: 452 applog(READ_DEBUG, 453 "%s%i:%d %s info [%c] version=0x%02x prod=%.7s" 454 " serial=0x%08x", 455 klncgpu->drv->name, klncgpu->device_id, 456 (int)(kline->hd.dev), msg, kline->hd.cmd, 457 (int)(kline->id.version), 458 kline->id.product, 459 (unsigned int)K_SERIAL(kline->id.serial)); 460 break; 461 default: 462 hexdata = bin2hex((unsigned char *)&(kline->hd.dev), REPLY_SIZE - 1); 463 applog(LOG_ERR, 464 "%s%i:%d %s [%c:%s] unknown and ignored", 465 klncgpu->drv->name, klncgpu->device_id, 466 (int)(kline->hd.dev), msg, kline->hd.cmd, 467 hexdata); 468 free(hexdata); 469 break; 470 } 471 } 472 473 static void display_send_kline(struct cgpu_info *klncgpu, KLINE *kline, const char *msg) 474 { 475 char *hexdata; 476 477 switch (kline->hd.cmd) { 478 case KLN_CMD_WORK: 479 applog(READ_DEBUG, 480 "%s%i:%d %s work [%c] dev=%d workid=0x%02x ...", 481 klncgpu->drv->name, klncgpu->device_id, 482 (int)(kline->wt.dev), msg, kline->ws.cmd, 483 (int)(kline->wt.dev), 484 (int)(kline->wt.workid)); 485 break; 486 case KLN_CMD_CONFIG: 487 applog(READ_DEBUG, 488 "%s%i:%d %s config [%c] dev=%d clock=%d" 489 " temptarget=%d tempcrit=%d fan=%d", 490 klncgpu->drv->name, klncgpu->device_id, 491 (int)(kline->cfg.dev), msg, kline->cfg.cmd, 492 (int)(kline->cfg.dev), 493 K_HASHCLOCK(kline->cfg.hashclock), 494 (int)(kline->cfg.temptarget), 495 (int)(kline->cfg.tempcritical), 496 (int)(kline->cfg.fantarget)); 497 break; 498 case KLN_CMD_IDENT: 499 case KLN_CMD_STATUS: 500 case KLN_CMD_ABORT: 501 applog(READ_DEBUG, 502 "%s%i:%d %s cmd [%c]", 503 klncgpu->drv->name, klncgpu->device_id, 504 (int)(kline->hd.dev), msg, kline->hd.cmd); 505 break; 506 case KLN_CMD_ENABLE: 507 applog(READ_DEBUG, 508 "%s%i:%d %s enable [%c] enable=%c", 509 klncgpu->drv->name, klncgpu->device_id, 510 (int)(kline->hd.dev), msg, kline->hd.cmd, 511 (char)(kline->hd.buf[0])); 512 break; 513 case KLN_CMD_NONCE: 514 default: 515 hexdata = bin2hex((unsigned char *)&(kline->hd.dev), REPLY_SIZE - 1); 516 applog(LOG_ERR, 517 "%s%i:%d %s [%c:%s] unknown/unexpected and ignored", 518 klncgpu->drv->name, klncgpu->device_id, 519 (int)(kline->hd.dev), msg, kline->hd.cmd, 520 hexdata); 521 free(hexdata); 522 break; 523 } 524 } 525 526 static bool SendCmd(struct cgpu_info *klncgpu, KLINE *kline, int datalen) 527 { 528 int err, amt, writ; 529 530 if (klncgpu->usbinfo.nodev) 531 return false; 532 533 display_send_kline(klncgpu, kline, msg_send); 534 writ = KSENDHD(datalen); 535 err = usb_write(klncgpu, (char *)kline, writ, &amt, C_REQUESTRESULTS); 536 if (err < 0 || amt != writ) { 537 applog(LOG_ERR, "%s%i:%d Cmd:%c Dev:%d, write failed (%d:%d:%d)", 538 klncgpu->drv->name, klncgpu->device_id, 539 (int)(kline->hd.dev), 540 kline->hd.cmd, (int)(kline->hd.dev), 541 writ, amt, err); 542 return false; 543 } 544 545 return true; 546 } 547 548 static KLIST *GetReply(struct cgpu_info *klncgpu, uint8_t cmd, uint8_t dev) 549 { 550 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 551 KLIST *kitem; 552 int retries = CMD_REPLY_RETRIES; 553 554 while (retries-- > 0 && klncgpu->shutdown == false) { 555 cgsleep_ms(REPLY_WAIT_TIME); 556 cg_rlock(&klninfo->klist_lock); 557 kitem = klninfo->used; 558 while (kitem) { 559 if (kitem->kline.hd.cmd == cmd && 560 kitem->kline.hd.dev == dev && 561 kitem->ready == true && kitem->working == false) { 562 kitem->working = true; 563 cg_runlock(&klninfo->klist_lock); 564 return kitem; 565 } 566 kitem = kitem->next; 567 } 568 cg_runlock(&klninfo->klist_lock); 569 } 570 return NULL; 571 } 572 573 static KLIST *SendCmdGetReply(struct cgpu_info *klncgpu, KLINE *kline, int datalen) 574 { 575 if (!SendCmd(klncgpu, kline, datalen)) 576 return NULL; 577 578 return GetReply(klncgpu, kline->hd.cmd, kline->hd.dev); 579 } 580 581 static bool klondike_get_stats(struct cgpu_info *klncgpu) 582 { 583 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 584 KLIST *kitem; 585 KLINE kline; 586 int slaves, dev; 587 588 if (klncgpu->usbinfo.nodev || klninfo->status == NULL) 589 return false; 590 591 applog(LOG_DEBUG, "%s%i: getting status", 592 klncgpu->drv->name, klncgpu->device_id); 593 594 rd_lock(&(klninfo->stat_lock)); 595 slaves = klninfo->status[0].kline.ws.slavecount; 596 rd_unlock(&(klninfo->stat_lock)); 597 598 // loop thru devices and get status for each 599 for (dev = 0; dev <= slaves; dev++) { 600 zero_kline(&kline); 601 kline.hd.cmd = KLN_CMD_STATUS; 602 kline.hd.dev = dev; 603 kitem = SendCmdGetReply(klncgpu, &kline, 0); 604 if (kitem != NULL) { 605 wr_lock(&(klninfo->stat_lock)); 606 memcpy((void *)(&(klninfo->status[dev])), 607 (void *)kitem, 608 sizeof(klninfo->status[dev])); 609 wr_unlock(&(klninfo->stat_lock)); 610 kitem = release_kitem(klncgpu, kitem); 611 } else { 612 applog(LOG_ERR, "%s%i:%d failed to update stats", 613 klncgpu->drv->name, klncgpu->device_id, dev); 614 } 615 } 616 return true; 617 } 618 619 // TODO: this only enables the master (no slaves) 620 static bool kln_enable(struct cgpu_info *klncgpu) 621 { 622 KLIST *kitem; 623 KLINE kline; 624 int tries = 2; 625 bool ok = false; 626 627 zero_kline(&kline); 628 kline.hd.cmd = KLN_CMD_ENABLE; 629 kline.hd.dev = 0; 630 kline.hd.buf[0] = KLN_CMD_ENABLE_ON; 631 632 while (tries-- > 0) { 633 kitem = SendCmdGetReply(klncgpu, &kline, 1); 634 if (kitem) { 635 kitem = release_kitem(klncgpu, kitem); 636 ok = true; 637 break; 638 } 639 cgsleep_ms(50); 640 } 641 642 if (ok) 643 cgsleep_ms(50); 644 645 return ok; 646 } 647 648 static void kln_disable(struct cgpu_info *klncgpu, int dev, bool all) 649 { 650 KLINE kline; 651 int i; 652 653 zero_kline(&kline); 654 kline.hd.cmd = KLN_CMD_ENABLE; 655 kline.hd.buf[0] = KLN_CMD_ENABLE_OFF; 656 for (i = (all ? 0 : dev); i <= dev; i++) { 657 kline.hd.dev = i; 658 SendCmd(klncgpu, &kline, KSENDHD(1)); 659 } 660 } 661 662 static bool klondike_init(struct cgpu_info *klncgpu) 663 { 664 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 665 KLIST *kitem; 666 KLINE kline; 667 int slaves, dev; 668 669 klninfo->initialised = false; 670 671 zero_kline(&kline); 672 kline.hd.cmd = KLN_CMD_STATUS; 673 kline.hd.dev = 0; 674 kitem = SendCmdGetReply(klncgpu, &kline, 0); 675 if (kitem == NULL) 676 return false; 677 678 slaves = kitem->kline.ws.slavecount; 679 if (klninfo->status == NULL) { 680 applog(LOG_DEBUG, "%s%i: initializing data", 681 klncgpu->drv->name, klncgpu->device_id); 682 683 // alloc space for status, devinfo, cfg and jobque for master and slaves 684 klninfo->status = calloc(slaves+1, sizeof(*(klninfo->status))); 685 if (unlikely(!klninfo->status)) 686 quit(1, "Failed to calloc status array in klondke_get_stats"); 687 klninfo->devinfo = calloc(slaves+1, sizeof(*(klninfo->devinfo))); 688 if (unlikely(!klninfo->devinfo)) 689 quit(1, "Failed to calloc devinfo array in klondke_get_stats"); 690 klninfo->cfg = calloc(slaves+1, sizeof(*(klninfo->cfg))); 691 if (unlikely(!klninfo->cfg)) 692 quit(1, "Failed to calloc cfg array in klondke_get_stats"); 693 klninfo->jobque = calloc(slaves+1, sizeof(*(klninfo->jobque))); 694 if (unlikely(!klninfo->jobque)) 695 quit(1, "Failed to calloc jobque array in klondke_get_stats"); 696 } 697 698 memcpy((void *)(&(klninfo->status[0])), (void *)kitem, sizeof(klninfo->status[0])); 699 kitem = release_kitem(klncgpu, kitem); 700 701 // zero init triggers read back only 702 zero_kline(&kline); 703 kline.cfg.cmd = KLN_CMD_CONFIG; 704 705 int size = 2; 706 707 // boundaries are checked by device, with valid values returned 708 if (opt_klondike_options != NULL) { 709 int hashclock; 710 double temptarget; 711 712 sscanf(opt_klondike_options, "%d:%lf", &hashclock, &temptarget); 713 SET_HASHCLOCK(kline.cfg.hashclock, hashclock); 714 kline.cfg.temptarget = cvtCToKln(temptarget); 715 kline.cfg.tempcritical = 0; // hard code for old firmware 716 kline.cfg.fantarget = 0xff; // hard code for old firmware 717 size = sizeof(kline.cfg) - 2; 718 } 719 720 for (dev = 0; dev <= slaves; dev++) { 721 kline.cfg.dev = dev; 722 kitem = SendCmdGetReply(klncgpu, &kline, size); 723 if (kitem != NULL) { 724 memcpy((void *)&(klninfo->cfg[dev]), kitem, sizeof(klninfo->cfg[dev])); 725 applog(LOG_WARNING, "%s%i:%d config (%d: Clk: %d, T:%.0lf, C:%.0lf, F:%d)", 726 klncgpu->drv->name, klncgpu->device_id, dev, 727 dev, K_HASHCLOCK(klninfo->cfg[dev].kline.cfg.hashclock), 728 cvtKlnToC(klninfo->cfg[dev].kline.cfg.temptarget), 729 cvtKlnToC(klninfo->cfg[dev].kline.cfg.tempcritical), 730 (int)100*klninfo->cfg[dev].kline.cfg.fantarget/256); 731 kitem = release_kitem(klncgpu, kitem); 732 } 733 } 734 klondike_get_stats(klncgpu); 735 klninfo->initialised = true; 736 for (dev = 0; dev <= slaves; dev++) { 737 klninfo->devinfo[dev].rangesize = ((uint64_t)1<<32) / klninfo->status[dev].kline.ws.chipcount; 738 klninfo->devinfo[dev].chipstats = calloc(klninfo->status[dev].kline.ws.chipcount*2 , sizeof(uint32_t)); 739 } 740 741 bool ok = kln_enable(klncgpu); 742 743 if (!ok) 744 applog(LOG_ERR, "%s%i: failed to enable", klncgpu->drv->name, klncgpu->device_id); 745 746 return ok; 747 } 748 749 static void control_init(struct cgpu_info *klncgpu) 750 { 751 int err, interface; 752 753 if (klncgpu->usbinfo.nodev) 754 return; 755 756 interface = usb_interface(klncgpu); 757 758 err = usb_transfer(klncgpu, 0, 9, 1, interface, C_RESET); 759 760 applog(LOG_DEBUG, "%s%i: reset got err %d", 761 klncgpu->drv->name, klncgpu->device_id, err); 762 } 763 764 static struct cgpu_info *klondike_detect_one(struct libusb_device *dev, struct usb_find_devices *found) 765 { 766 struct cgpu_info *klncgpu = usb_alloc_cgpu(&klondike_drv, 1); 767 struct klondike_info *klninfo = NULL; 768 KLINE kline; 769 770 if (unlikely(!klncgpu)) 771 quit(1, "Failed to calloc klncgpu in klondike_detect_one"); 772 773 klninfo = calloc(1, sizeof(*klninfo)); 774 if (unlikely(!klninfo)) 775 quit(1, "Failed to calloc klninfo in klondke_detect_one"); 776 klncgpu->device_data = (void *)klninfo; 777 778 klninfo->free = new_klist_set(klncgpu); 779 780 if (usb_init(klncgpu, dev, found)) { 781 int sent, recd, err; 782 KLIST kitem; 783 int attempts = 0; 784 785 control_init(klncgpu); 786 787 while (attempts++ < 3) { 788 kline.hd.cmd = KLN_CMD_IDENT; 789 kline.hd.dev = 0; 790 display_send_kline(klncgpu, &kline, msg_detect_send); 791 err = usb_write(klncgpu, (char *)&(kline.hd), 2, &sent, C_REQUESTRESULTS); 792 if (err < 0 || sent != 2) { 793 applog(LOG_ERR, "%s (%s) detect write failed (%d:%d)", 794 klncgpu->drv->dname, 795 klncgpu->device_path, 796 sent, err); 797 } 798 cgsleep_ms(REPLY_WAIT_TIME*10); 799 err = usb_read(klncgpu, (char *)&(kitem.kline), REPLY_SIZE, &recd, C_GETRESULTS); 800 if (err < 0) { 801 applog(LOG_ERR, "%s (%s) detect read failed (%d:%d)", 802 klncgpu->drv->dname, 803 klncgpu->device_path, 804 recd, err); 805 } else if (recd < 1) { 806 applog(LOG_ERR, "%s (%s) detect empty reply (%d)", 807 klncgpu->drv->dname, 808 klncgpu->device_path, 809 recd); 810 } else if (kitem.kline.hd.cmd == KLN_CMD_IDENT && kitem.kline.hd.dev == 0) { 811 display_kline(klncgpu, &kitem.kline, msg_detect_reply); 812 applog(LOG_DEBUG, "%s (%s) detect successful (%d attempt%s)", 813 klncgpu->drv->dname, 814 klncgpu->device_path, 815 attempts, attempts == 1 ? "" : "s"); 816 if (!add_cgpu(klncgpu)) 817 break; 818 update_usb_stats(klncgpu); 819 applog(LOG_DEBUG, "Klondike cgpu added"); 820 rwlock_init(&klninfo->stat_lock); 821 cglock_init(&klninfo->klist_lock); 822 return klncgpu; 823 } 824 } 825 usb_uninit(klncgpu); 826 } 827 free(klninfo->free); 828 free(klninfo); 829 free(klncgpu); 830 return NULL; 831 } 832 833 static void klondike_detect(bool __maybe_unused hotplug) 834 { 835 usb_detect(&klondike_drv, klondike_detect_one); 836 } 837 838 static void klondike_identify(__maybe_unused struct cgpu_info *klncgpu) 839 { 840 /* 841 KLINE kline; 842 843 zero_kline(&kline); 844 kline.hd.cmd = KLN_CMD_IDENT; 845 kline.hd.dev = 0; 846 SendCmdGetReply(klncgpu, &kline, KSENDHD(0)); 847 */ 848 } 849 850 static void klondike_check_nonce(struct cgpu_info *klncgpu, KLIST *kitem) 851 { 852 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 853 struct work *work, *look, *tmp; 854 KLINE *kline = &(kitem->kline); 855 struct timeval tv_now; 856 double us_diff; 857 uint32_t nonce = K_NONCE(kline->wr.nonce) - 0xC0; 858 859 applog(LOG_DEBUG, "%s%i:%d FOUND NONCE (%02x:%08x)", 860 klncgpu->drv->name, klncgpu->device_id, (int)(kline->wr.dev), 861 kline->wr.workid, (unsigned int)nonce); 862 863 work = NULL; 864 cgtime(&tv_now); 865 rd_lock(&(klncgpu->qlock)); 866 HASH_ITER(hh, klncgpu->queued_work, look, tmp) { 867 if (ms_tdiff(&tv_now, &(look->tv_stamp)) < OLD_WORK_MS && 868 (look->subid == (kline->wr.dev*256 + kline->wr.workid))) { 869 work = look; 870 break; 871 } 872 } 873 rd_unlock(&(klncgpu->qlock)); 874 875 if (work) { 876 wr_lock(&(klninfo->stat_lock)); 877 klninfo->devinfo[kline->wr.dev].noncecount++; 878 klninfo->noncecount++; 879 wr_unlock(&(klninfo->stat_lock)); 880 881 applog(LOG_DEBUG, "%s%i:%d SUBMIT NONCE (%02x:%08x)", 882 klncgpu->drv->name, klncgpu->device_id, (int)(kline->wr.dev), 883 kline->wr.workid, (unsigned int)nonce); 884 885 cgtime(&tv_now); 886 bool ok = submit_nonce(klncgpu->thr[0], work, nonce); 887 888 applog(LOG_DEBUG, "%s%i:%d chip stats %d, %08x, %d, %d", 889 klncgpu->drv->name, klncgpu->device_id, (int)(kline->wr.dev), 890 kline->wr.dev, (unsigned int)nonce, 891 klninfo->devinfo[kline->wr.dev].rangesize, 892 klninfo->status[kline->wr.dev].kline.ws.chipcount); 893 894 klninfo->devinfo[kline->wr.dev].chipstats[(nonce / klninfo->devinfo[kline->wr.dev].rangesize) + (ok ? 0 : klninfo->status[kline->wr.dev].kline.ws.chipcount)]++; 895 896 us_diff = us_tdiff(&tv_now, &(kitem->tv_when)); 897 if (klninfo->delay_count == 0) { 898 klninfo->delay_min = us_diff; 899 klninfo->delay_max = us_diff; 900 } else { 901 if (klninfo->delay_min > us_diff) 902 klninfo->delay_min = us_diff; 903 if (klninfo->delay_max < us_diff) 904 klninfo->delay_max = us_diff; 905 } 906 klninfo->delay_count++; 907 klninfo->delay_total += us_diff; 908 909 if (klninfo->nonce_count > 0) { 910 us_diff = us_tdiff(&(kitem->tv_when), &(klninfo->tv_last_nonce_received)); 911 if (klninfo->nonce_count == 1) { 912 klninfo->nonce_min = us_diff; 913 klninfo->nonce_max = us_diff; 914 } else { 915 if (klninfo->nonce_min > us_diff) 916 klninfo->nonce_min = us_diff; 917 if (klninfo->nonce_max < us_diff) 918 klninfo->nonce_max = us_diff; 919 } 920 klninfo->nonce_total += us_diff; 921 } 922 klninfo->nonce_count++; 923 924 memcpy(&(klninfo->tv_last_nonce_received), &(kitem->tv_when), 925 sizeof(klninfo->tv_last_nonce_received)); 926 927 return; 928 } 929 930 applog(LOG_ERR, "%s%i:%d unknown work (%02x:%08x) - ignored", 931 klncgpu->drv->name, klncgpu->device_id, (int)(kline->wr.dev), 932 kline->wr.workid, (unsigned int)nonce); 933 934 //inc_hw_errors(klncgpu->thr[0]); 935 } 936 937 // thread to keep looking for replies 938 static void *klondike_get_replies(void *userdata) 939 { 940 struct cgpu_info *klncgpu = (struct cgpu_info *)userdata; 941 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 942 KLIST *kitem = NULL; 943 char *hexdata; 944 int err, recd, slaves, dev, isc; 945 bool overheat, sent; 946 947 applog(LOG_DEBUG, "%s%i: listening for replies", 948 klncgpu->drv->name, klncgpu->device_id); 949 950 while (klncgpu->shutdown == false) { 951 if (klncgpu->usbinfo.nodev) 952 return NULL; 953 954 if (kitem == NULL) 955 kitem = allocate_kitem(klncgpu); 956 else 957 memset((void *)&(kitem->kline), 0, sizeof(kitem->kline)); 958 959 err = usb_read(klncgpu, (char *)&(kitem->kline), REPLY_SIZE, &recd, C_GETRESULTS); 960 if (err || recd != REPLY_SIZE) { 961 if (err != -7) 962 applog(LOG_ERR, "%s%i: reply err=%d amt=%d", 963 klncgpu->drv->name, klncgpu->device_id, 964 err, recd); 965 } 966 if (!err && recd == REPLY_SIZE) { 967 cgtime(&(kitem->tv_when)); 968 rd_lock(&(klninfo->stat_lock)); 969 kitem->block_seq = klninfo->block_seq; 970 rd_unlock(&(klninfo->stat_lock)); 971 if (opt_log_level <= READ_DEBUG) { 972 hexdata = bin2hex((unsigned char *)&(kitem->kline.hd.dev), recd-1); 973 applog(READ_DEBUG, "%s%i:%d reply [%c:%s]", 974 klncgpu->drv->name, klncgpu->device_id, 975 (int)(kitem->kline.hd.dev), 976 kitem->kline.hd.cmd, hexdata); 977 free(hexdata); 978 } 979 980 // We can't check this until it's initialised 981 if (klninfo->initialised) { 982 rd_lock(&(klninfo->stat_lock)); 983 slaves = klninfo->status[0].kline.ws.slavecount; 984 rd_unlock(&(klninfo->stat_lock)); 985 986 if (kitem->kline.hd.dev > slaves) { 987 applog(LOG_ERR, "%s%i: reply [%c] has invalid dev=%d (max=%d) using 0", 988 klncgpu->drv->name, klncgpu->device_id, 989 (char)(kitem->kline.hd.cmd), 990 (int)(kitem->kline.hd.dev), 991 slaves); 992 /* TODO: this is rather problematic if there are slaves 993 * however without slaves - it should always be zero */ 994 kitem->kline.hd.dev = 0; 995 } else { 996 wr_lock(&(klninfo->stat_lock)); 997 klninfo->jobque[kitem->kline.hd.dev].late_update_sequential = 0; 998 wr_unlock(&(klninfo->stat_lock)); 999 } 1000 } 1001 1002 switch (kitem->kline.hd.cmd) { 1003 case KLN_CMD_NONCE: 1004 klondike_check_nonce(klncgpu, kitem); 1005 display_kline(klncgpu, &kitem->kline, msg_reply); 1006 break; 1007 case KLN_CMD_WORK: 1008 // We can't do/check this until it's initialised 1009 if (klninfo->initialised) { 1010 dev = kitem->kline.ws.dev; 1011 if (kitem->kline.ws.workqc == 0) { 1012 bool idle = false; 1013 rd_lock(&(klninfo->stat_lock)); 1014 if (klninfo->jobque[dev].flushed == false) 1015 idle = true; 1016 slaves = klninfo->status[0].kline.ws.slavecount; 1017 rd_unlock(&(klninfo->stat_lock)); 1018 if (idle) 1019 applog(LOG_WARNING, "%s%i:%d went idle before work was sent", 1020 klncgpu->drv->name, 1021 klncgpu->device_id, 1022 dev); 1023 } 1024 wr_lock(&(klninfo->stat_lock)); 1025 klninfo->jobque[dev].flushed = false; 1026 wr_unlock(&(klninfo->stat_lock)); 1027 } 1028 case KLN_CMD_STATUS: 1029 case KLN_CMD_ABORT: 1030 // We can't do/check this until it's initialised 1031 if (klninfo->initialised) { 1032 isc = 0; 1033 dev = kitem->kline.ws.dev; 1034 wr_lock(&(klninfo->stat_lock)); 1035 klninfo->jobque[dev].workqc = (int)(kitem->kline.ws.workqc); 1036 cgtime(&(klninfo->jobque[dev].last_update)); 1037 slaves = klninfo->status[0].kline.ws.slavecount; 1038 overheat = klninfo->jobque[dev].overheat; 1039 if (dev == 0) { 1040 if (kitem->kline.ws.slavecount != slaves) 1041 isc = ++klninfo->incorrect_slave_sequential; 1042 else 1043 isc = klninfo->incorrect_slave_sequential = 0; 1044 } 1045 wr_unlock(&(klninfo->stat_lock)); 1046 1047 if (isc) { 1048 applog(LOG_ERR, "%s%i:%d reply [%c] has a diff" 1049 " # of slaves=%d (curr=%d)%s", 1050 klncgpu->drv->name, 1051 klncgpu->device_id, 1052 dev, 1053 (char)(kitem->kline.ws.cmd), 1054 (int)(kitem->kline.ws.slavecount), 1055 slaves, 1056 isc <= KLN_ISS_IGNORE ? "" : 1057 " disabling device"); 1058 if (isc > KLN_ISS_IGNORE) 1059 usb_nodev(klncgpu); 1060 break; 1061 } 1062 1063 if (!overheat) { 1064 double temp = cvtKlnToC(kitem->kline.ws.temp); 1065 if (temp >= KLN_KILLWORK_TEMP) { 1066 KLINE kline; 1067 1068 wr_lock(&(klninfo->stat_lock)); 1069 klninfo->jobque[dev].overheat = true; 1070 wr_unlock(&(klninfo->stat_lock)); 1071 1072 applog(LOG_WARNING, "%s%i:%d Critical overheat (%.0fC)", 1073 klncgpu->drv->name, 1074 klncgpu->device_id, 1075 dev, temp); 1076 1077 zero_kline(&kline); 1078 kline.hd.cmd = KLN_CMD_ABORT; 1079 kline.hd.dev = dev; 1080 sent = SendCmd(klncgpu, &kline, KSENDHD(0)); 1081 kln_disable(klncgpu, dev, false); 1082 if (!sent) { 1083 applog(LOG_ERR, "%s%i:%d overheat failed to" 1084 " abort work - disabling device", 1085 klncgpu->drv->name, 1086 klncgpu->device_id, 1087 dev); 1088 usb_nodev(klncgpu); 1089 } 1090 } 1091 } 1092 } 1093 case KLN_CMD_ENABLE: 1094 wr_lock(&(klninfo->stat_lock)); 1095 klninfo->errorcount += kitem->kline.ws.errorcount; 1096 klninfo->noisecount += kitem->kline.ws.noise; 1097 wr_unlock(&(klninfo->stat_lock)); 1098 display_kline(klncgpu, &kitem->kline, msg_reply); 1099 kitem->ready = true; 1100 kitem = NULL; 1101 break; 1102 case KLN_CMD_CONFIG: 1103 display_kline(klncgpu, &kitem->kline, msg_reply); 1104 kitem->ready = true; 1105 kitem = NULL; 1106 break; 1107 case KLN_CMD_IDENT: 1108 display_kline(klncgpu, &kitem->kline, msg_reply); 1109 kitem->ready = true; 1110 kitem = NULL; 1111 break; 1112 default: 1113 display_kline(klncgpu, &kitem->kline, msg_reply); 1114 break; 1115 } 1116 } 1117 } 1118 return NULL; 1119 } 1120 1121 static void klondike_flush_work(struct cgpu_info *klncgpu) 1122 { 1123 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 1124 KLIST *kitem; 1125 KLINE kline; 1126 int slaves, dev; 1127 1128 if (klninfo->initialised) { 1129 wr_lock(&(klninfo->stat_lock)); 1130 klninfo->block_seq++; 1131 slaves = klninfo->status[0].kline.ws.slavecount; 1132 wr_unlock(&(klninfo->stat_lock)); 1133 1134 applog(LOG_DEBUG, "%s%i: flushing work", 1135 klncgpu->drv->name, klncgpu->device_id); 1136 zero_kline(&kline); 1137 kline.hd.cmd = KLN_CMD_ABORT; 1138 for (dev = 0; dev <= slaves; dev++) { 1139 kline.hd.dev = dev; 1140 kitem = SendCmdGetReply(klncgpu, &kline, KSENDHD(0)); 1141 if (kitem != NULL) { 1142 wr_lock(&(klninfo->stat_lock)); 1143 memcpy((void *)&(klninfo->status[dev]), 1144 kitem, 1145 sizeof(klninfo->status[dev])); 1146 klninfo->jobque[dev].flushed = true; 1147 wr_unlock(&(klninfo->stat_lock)); 1148 kitem = release_kitem(klncgpu, kitem); 1149 } 1150 } 1151 } 1152 } 1153 1154 static bool klondike_thread_prepare(struct thr_info *thr) 1155 { 1156 struct cgpu_info *klncgpu = thr->cgpu; 1157 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 1158 1159 if (thr_info_create(&(klninfo->replies_thr), NULL, klondike_get_replies, (void *)klncgpu)) { 1160 applog(LOG_ERR, "%s%i: thread create failed", klncgpu->drv->name, klncgpu->device_id); 1161 return false; 1162 } 1163 pthread_detach(klninfo->replies_thr.pth); 1164 1165 // let the listening get started 1166 cgsleep_ms(100); 1167 1168 return klondike_init(klncgpu); 1169 } 1170 1171 static bool klondike_thread_init(struct thr_info *thr) 1172 { 1173 struct cgpu_info *klncgpu = thr->cgpu; 1174 1175 if (klncgpu->usbinfo.nodev) 1176 return false; 1177 1178 klondike_flush_work(klncgpu); 1179 1180 return true; 1181 } 1182 1183 static void klondike_shutdown(struct thr_info *thr) 1184 { 1185 struct cgpu_info *klncgpu = thr->cgpu; 1186 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 1187 1188 applog(LOG_DEBUG, "%s%i: shutting down work", 1189 klncgpu->drv->name, klncgpu->device_id); 1190 1191 kln_disable(klncgpu, klninfo->status[0].kline.ws.slavecount, true); 1192 1193 klncgpu->shutdown = true; 1194 } 1195 1196 static void klondike_thread_enable(struct thr_info *thr) 1197 { 1198 struct cgpu_info *klncgpu = thr->cgpu; 1199 1200 if (klncgpu->usbinfo.nodev) 1201 return; 1202 1203 /* 1204 KLINE kline; 1205 1206 zero_kline(&kline); 1207 kline.hd.cmd = KLN_CMD_ENABLE; 1208 kline.hd.dev = dev; 1209 kline.hd.buf[0] = KLN_CMD_ENABLE_OFF; 1210 kitem = SendCmdGetReply(klncgpu, &kline, KSENDHD(1)); 1211 */ 1212 1213 } 1214 1215 static bool klondike_send_work(struct cgpu_info *klncgpu, int dev, struct work *work) 1216 { 1217 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 1218 struct work *look, *tmp; 1219 KLINE kline; 1220 struct timeval tv_old; 1221 int wque_size, wque_cleared; 1222 1223 if (klncgpu->usbinfo.nodev) 1224 return false; 1225 1226 zero_kline(&kline); 1227 kline.wt.cmd = KLN_CMD_WORK; 1228 kline.wt.dev = dev; 1229 memcpy(kline.wt.midstate, work->midstate, MIDSTATE_BYTES); 1230 memcpy(kline.wt.merkle, work->data + MERKLE_OFFSET, MERKLE_BYTES); 1231 kline.wt.workid = (uint8_t)(klninfo->devinfo[dev].nextworkid++ & 0xFF); 1232 work->subid = dev*256 + kline.wt.workid; 1233 cgtime(&work->tv_stamp); 1234 1235 if (opt_log_level <= LOG_DEBUG) { 1236 char *hexdata = bin2hex((void *)&kline.wt, sizeof(kline.wt)); 1237 applog(LOG_DEBUG, "WORKDATA: %s", hexdata); 1238 free(hexdata); 1239 } 1240 1241 applog(LOG_DEBUG, "%s%i:%d sending work (%d:%02x)", 1242 klncgpu->drv->name, klncgpu->device_id, dev, 1243 dev, kline.wt.workid); 1244 KLIST *kitem = SendCmdGetReply(klncgpu, &kline, sizeof(kline.wt)); 1245 if (kitem != NULL) { 1246 wr_lock(&(klninfo->stat_lock)); 1247 memcpy((void *)&(klninfo->status[dev]), kitem, sizeof(klninfo->status[dev])); 1248 wr_unlock(&(klninfo->stat_lock)); 1249 kitem = release_kitem(klncgpu, kitem); 1250 1251 // remove old work 1252 wque_size = 0; 1253 wque_cleared = 0; 1254 cgtime(&tv_old); 1255 wr_lock(&klncgpu->qlock); 1256 HASH_ITER(hh, klncgpu->queued_work, look, tmp) { 1257 if (ms_tdiff(&tv_old, &(look->tv_stamp)) > OLD_WORK_MS) { 1258 __work_completed(klncgpu, look); 1259 free_work(look); 1260 wque_cleared++; 1261 } else 1262 wque_size++; 1263 } 1264 wr_unlock(&klncgpu->qlock); 1265 1266 wr_lock(&(klninfo->stat_lock)); 1267 klninfo->wque_size = wque_size; 1268 klninfo->wque_cleared = wque_cleared; 1269 wr_unlock(&(klninfo->stat_lock)); 1270 return true; 1271 } 1272 return false; 1273 } 1274 1275 static bool klondike_queue_full(struct cgpu_info *klncgpu) 1276 { 1277 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 1278 struct work *work = NULL; 1279 int dev, queued, slaves, seq, howlong; 1280 struct timeval now; 1281 bool nowork; 1282 1283 if (klncgpu->shutdown == true) 1284 return true; 1285 1286 cgtime(&now); 1287 rd_lock(&(klninfo->stat_lock)); 1288 slaves = klninfo->status[0].kline.ws.slavecount; 1289 for (dev = 0; dev <= slaves; dev++) 1290 if (ms_tdiff(&now, &(klninfo->jobque[dev].last_update)) > LATE_UPDATE_MS) { 1291 klninfo->jobque[dev].late_update_count++; 1292 seq = ++klninfo->jobque[dev].late_update_sequential; 1293 rd_unlock(&(klninfo->stat_lock)); 1294 if (seq < LATE_UPDATE_LIMIT) { 1295 applog(LOG_DEBUG, "%s%i:%d late update", 1296 klncgpu->drv->name, klncgpu->device_id, dev); 1297 klondike_get_stats(klncgpu); 1298 goto que; 1299 } else { 1300 applog(LOG_WARNING, "%s%i:%d late update (%d) reached - attempting reset", 1301 klncgpu->drv->name, klncgpu->device_id, 1302 dev, LATE_UPDATE_LIMIT); 1303 control_init(klncgpu); 1304 kln_enable(klncgpu); 1305 klondike_get_stats(klncgpu); 1306 rd_lock(&(klninfo->stat_lock)); 1307 howlong = ms_tdiff(&now, &(klninfo->jobque[dev].last_update)); 1308 if (howlong > LATE_UPDATE_MS) { 1309 rd_unlock(&(klninfo->stat_lock)); 1310 if (howlong > LATE_UPDATE_NODEV_MS) { 1311 applog(LOG_ERR, "%s%i:%d reset failed - dropping device", 1312 klncgpu->drv->name, klncgpu->device_id, dev); 1313 usb_nodev(klncgpu); 1314 } else 1315 cgsleep_ms(LATE_UPDATE_SLEEP_MS); 1316 1317 return true; 1318 } 1319 break; 1320 } 1321 } 1322 rd_unlock(&(klninfo->stat_lock)); 1323 1324 que: 1325 1326 nowork = true; 1327 for (queued = 0; queued < MAX_WORK_COUNT-1; queued++) 1328 for (dev = 0; dev <= slaves; dev++) { 1329 tryagain: 1330 rd_lock(&(klninfo->stat_lock)); 1331 if (klninfo->jobque[dev].overheat) { 1332 double temp = cvtKlnToC(klninfo->status[0].kline.ws.temp); 1333 if ((queued == MAX_WORK_COUNT-2) && 1334 ms_tdiff(&now, &(klninfo->jobque[dev].last_update)) > (LATE_UPDATE_MS/2)) { 1335 rd_unlock(&(klninfo->stat_lock)); 1336 klondike_get_stats(klncgpu); 1337 goto tryagain; 1338 } 1339 if (temp <= KLN_COOLED_DOWN) { 1340 klninfo->jobque[dev].overheat = false; 1341 rd_unlock(&(klninfo->stat_lock)); 1342 applog(LOG_WARNING, "%s%i:%d Overheat recovered (%.0fC)", 1343 klncgpu->drv->name, klncgpu->device_id, 1344 dev, temp); 1345 kln_enable(klncgpu); 1346 goto tryagain; 1347 } else { 1348 rd_unlock(&(klninfo->stat_lock)); 1349 continue; 1350 } 1351 } 1352 1353 if (klninfo->jobque[dev].workqc <= queued) { 1354 rd_unlock(&(klninfo->stat_lock)); 1355 if (!work) 1356 work = get_queued(klncgpu); 1357 if (unlikely(!work)) 1358 return false; 1359 nowork = false; 1360 if (klondike_send_work(klncgpu, dev, work)) 1361 return false; 1362 } else 1363 rd_unlock(&(klninfo->stat_lock)); 1364 } 1365 1366 if (nowork) 1367 cgsleep_ms(10); // avoid a hard loop in case we have nothing to do 1368 1369 return true; 1370 } 1371 1372 static int64_t klondike_scanwork(struct thr_info *thr) 1373 { 1374 struct cgpu_info *klncgpu = thr->cgpu; 1375 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 1376 int64_t newhashcount = 0; 1377 int dev, slaves; 1378 1379 if (klncgpu->usbinfo.nodev) 1380 return -1; 1381 1382 restart_wait(thr, 200); 1383 if (klninfo->status != NULL) { 1384 rd_lock(&(klninfo->stat_lock)); 1385 slaves = klninfo->status[0].kline.ws.slavecount; 1386 for (dev = 0; dev <= slaves; dev++) { 1387 uint64_t newhashdev = 0, hashcount; 1388 int maxcount; 1389 1390 hashcount = K_HASHCOUNT(klninfo->status[dev].kline.ws.hashcount); 1391 maxcount = K_MAXCOUNT(klninfo->status[dev].kline.ws.maxcount); 1392 // todo: chg this to check workid for wrapped instead 1393 if (klninfo->devinfo[dev].lasthashcount > hashcount) 1394 newhashdev += maxcount; // hash counter wrapped 1395 newhashdev += hashcount - klninfo->devinfo[dev].lasthashcount; 1396 klninfo->devinfo[dev].lasthashcount = hashcount; 1397 if (maxcount != 0) 1398 klninfo->hashcount += (newhashdev << 32) / maxcount; 1399 } 1400 newhashcount += 0xffffffffull * (uint64_t)klninfo->noncecount; 1401 klninfo->noncecount = 0; 1402 rd_unlock(&(klninfo->stat_lock)); 1403 } 1404 1405 return newhashcount; 1406 } 1407 1408 1409 static void get_klondike_statline_before(char *buf, size_t siz, struct cgpu_info *klncgpu) 1410 { 1411 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 1412 uint8_t temp = 0xFF; 1413 uint16_t fan = 0; 1414 uint16_t clock = 0; 1415 int dev, slaves; 1416 1417 if (klninfo->status == NULL) { 1418 blank_get_statline_before(buf, siz, klncgpu); 1419 return; 1420 } 1421 1422 rd_lock(&(klninfo->stat_lock)); 1423 slaves = klninfo->status[0].kline.ws.slavecount; 1424 for (dev = 0; dev <= slaves; dev++) { 1425 if (klninfo->status[dev].kline.ws.temp < temp) 1426 temp = klninfo->status[dev].kline.ws.temp; 1427 fan += klninfo->cfg[dev].kline.cfg.fantarget; 1428 clock += (uint16_t)K_HASHCLOCK(klninfo->cfg[dev].kline.cfg.hashclock); 1429 } 1430 rd_unlock(&(klninfo->stat_lock)); 1431 fan /= slaves + 1; 1432 //fan *= 100/255; // <-- You can't do this because int 100 / int 255 == 0 1433 fan = 100 * fan / 255; 1434 if (fan > 100) 1435 fan = 100; 1436 clock /= slaves + 1; 1437 if (clock > 999) // error - so truncate it 1438 clock = 999; 1439 1440 tailsprintf(buf, siz, "%3dMHz %3d%% %.1fC", (int)clock, (int)fan, cvtKlnToC(temp)); 1441 } 1442 1443 static struct api_data *klondike_api_stats(struct cgpu_info *klncgpu) 1444 { 1445 struct klondike_info *klninfo = (struct klondike_info *)(klncgpu->device_data); 1446 struct api_data *root = NULL; 1447 char buf[32]; 1448 int dev, slaves; 1449 1450 if (klninfo->status == NULL) 1451 return NULL; 1452 1453 rd_lock(&(klninfo->stat_lock)); 1454 slaves = klninfo->status[0].kline.ws.slavecount; 1455 for (dev = 0; dev <= slaves; dev++) { 1456 1457 float fTemp = cvtKlnToC(klninfo->status[dev].kline.ws.temp); 1458 sprintf(buf, "Temp %d", dev); 1459 root = api_add_temp(root, buf, &fTemp, true); 1460 1461 double dClk = (double)K_HASHCLOCK(klninfo->cfg[dev].kline.cfg.hashclock); 1462 sprintf(buf, "Clock %d", dev); 1463 root = api_add_freq(root, buf, &dClk, true); 1464 1465 unsigned int iFan = (unsigned int)100 * klninfo->cfg[dev].kline.cfg.fantarget / 255; 1466 sprintf(buf, "Fan Percent %d", dev); 1467 root = api_add_int(root, buf, (int *)(&iFan), true); 1468 1469 iFan = 0; 1470 if (klninfo->status[dev].kline.ws.fanspeed > 0) 1471 iFan = (unsigned int)TACH_FACTOR / klninfo->status[dev].kline.ws.fanspeed; 1472 sprintf(buf, "Fan RPM %d", dev); 1473 root = api_add_int(root, buf, (int *)(&iFan), true); 1474 1475 if (klninfo->devinfo[dev].chipstats != NULL) { 1476 char data[2048]; 1477 char one[32]; 1478 int n; 1479 1480 sprintf(buf, "Nonces / Chip %d", dev); 1481 data[0] = '\0'; 1482 for (n = 0; n < klninfo->status[dev].kline.ws.chipcount; n++) { 1483 snprintf(one, sizeof(one), "%07d ", klninfo->devinfo[dev].chipstats[n]); 1484 strcat(data, one); 1485 } 1486 root = api_add_string(root, buf, data, true); 1487 1488 sprintf(buf, "Errors / Chip %d", dev); 1489 data[0] = '\0'; 1490 for (n = 0; n < klninfo->status[dev].kline.ws.chipcount; n++) { 1491 snprintf(one, sizeof(one), "%07d ", klninfo->devinfo[dev].chipstats[n + klninfo->status[dev].kline.ws.chipcount]); 1492 strcat(data, one); 1493 } 1494 root = api_add_string(root, buf, data, true); 1495 } 1496 } 1497 1498 root = api_add_uint64(root, "Hash Count", &(klninfo->hashcount), true); 1499 root = api_add_uint64(root, "Error Count", &(klninfo->errorcount), true); 1500 root = api_add_uint64(root, "Noise Count", &(klninfo->noisecount), true); 1501 1502 root = api_add_int(root, "KLine Limit", &(klninfo->kline_count), true); 1503 root = api_add_int(root, "KLine Used", &(klninfo->used_count), true); 1504 1505 root = api_add_elapsed(root, "KQue Delay Count", &(klninfo->delay_count), true); 1506 root = api_add_elapsed(root, "KQue Delay Total", &(klninfo->delay_total), true); 1507 root = api_add_elapsed(root, "KQue Delay Min", &(klninfo->delay_min), true); 1508 root = api_add_elapsed(root, "KQue Delay Max", &(klninfo->delay_max), true); 1509 double avg; 1510 if (klninfo->delay_count == 0) 1511 avg = 0; 1512 else 1513 avg = klninfo->delay_total / klninfo->delay_count; 1514 root = api_add_diff(root, "KQue Delay Avg", &avg, true); 1515 1516 root = api_add_elapsed(root, "KQue Nonce Count", &(klninfo->nonce_count), true); 1517 root = api_add_elapsed(root, "KQue Nonce Total", &(klninfo->nonce_total), true); 1518 root = api_add_elapsed(root, "KQue Nonce Min", &(klninfo->nonce_min), true); 1519 root = api_add_elapsed(root, "KQue Nonce Max", &(klninfo->nonce_max), true); 1520 if (klninfo->nonce_count == 0) 1521 avg = 0; 1522 else 1523 avg = klninfo->nonce_total / klninfo->nonce_count; 1524 root = api_add_diff(root, "KQue Nonce Avg", &avg, true); 1525 1526 root = api_add_int(root, "WQue Size", &(klninfo->wque_size), true); 1527 root = api_add_int(root, "WQue Cleared", &(klninfo->wque_cleared), true); 1528 1529 rd_unlock(&(klninfo->stat_lock)); 1530 1531 return root; 1532 } 1533 1534 struct device_drv klondike_drv = { 1535 .drv_id = DRIVER_klondike, 1536 .dname = "Klondike", 1537 .name = "KLN", 1538 .drv_detect = klondike_detect, 1539 .get_api_stats = klondike_api_stats, 1540 .get_statline_before = get_klondike_statline_before, 1541 .get_stats = klondike_get_stats, 1542 .identify_device = klondike_identify, 1543 .thread_prepare = klondike_thread_prepare, 1544 .thread_init = klondike_thread_init, 1545 .hash_work = hash_queued_work, 1546 .scanwork = klondike_scanwork, 1547 .queue_full = klondike_queue_full, 1548 .flush_work = klondike_flush_work, 1549 .thread_shutdown = klondike_shutdown, 1550 .thread_enable = klondike_thread_enable 1551 };