driver-titan.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /*
  2. * Copyright 2014 Vitalii Demianets
  3. * Copyright 2014 KnCMiner
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the Free
  7. * Software Foundation; either version 3 of the License, or (at your option)
  8. * any later version. See COPYING for more details.
  9. */
  10. #include <fcntl.h>
  11. #include <sys/ioctl.h>
  12. #include <linux/spi/spidev.h>
  13. #include "deviceapi.h"
  14. #include "logging.h"
  15. #include "lowl-spi.h"
  16. #include "miner.h"
  17. #include "util.h"
  18. #include "titan-asic.h"
  19. #define KNC_TITAN_DEFAULT_FREQUENCY 600
  20. #define KNC_TITAN_HWERR_DISABLE_SECS 10
  21. #define KNC_POLL_INTERVAL_US 10000
  22. #define KNC_TITAN_SPI_SPEED 3000000
  23. #define KNC_TITAN_SPI_DELAY 0
  24. #define KNC_TITAN_SPI_MODE (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
  25. #define KNC_TITAN_SPI_BITS 8
  26. BFG_REGISTER_DRIVER(knc_titan_drv)
  27. static const struct bfg_set_device_definition knc_titan_set_device_funcs[];
  28. struct knc_titan_core {
  29. int asicno;
  30. int dieno; /* inside asic */
  31. int coreno; /* inside die */
  32. struct knc_titan_die *die;
  33. struct cgpu_info *proc;
  34. int next_slot;
  35. int hwerr_in_row;
  36. int hwerr_disable_time;
  37. struct timeval enable_at;
  38. struct timeval first_hwerr;
  39. };
  40. struct knc_titan_die {
  41. int asicno;
  42. int dieno; /* inside asic */
  43. int cores;
  44. struct cgpu_info *first_proc;
  45. int freq;
  46. };
  47. struct knc_titan_info {
  48. struct spi_port *spi;
  49. struct cgpu_info *cgpu;
  50. int cores;
  51. struct knc_titan_die dies[KNC_TITAN_MAX_ASICS][KNC_TITAN_DIES_PER_ASIC];
  52. bool need_flush;
  53. struct work *workqueue;
  54. int workqueue_size;
  55. int workqueue_max;
  56. int next_id;
  57. struct work *devicework;
  58. };
  59. static bool knc_titan_spi_open(const char *repr, struct spi_port * const spi)
  60. {
  61. const char * const spipath = "/dev/spidev0.1";
  62. const int fd = open(spipath, O_RDWR);
  63. const uint8_t lsbfirst = 0;
  64. if (0 > fd)
  65. return false;
  66. if (ioctl(fd, SPI_IOC_WR_MODE , &spi->mode )) goto fail;
  67. if (ioctl(fd, SPI_IOC_WR_LSB_FIRST , &lsbfirst )) goto fail;
  68. if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi->bits )) goto fail;
  69. if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ , &spi->speed)) goto fail;
  70. spi->fd = fd;
  71. return true;
  72. fail:
  73. close(fd);
  74. spi->fd = -1;
  75. applog(LOG_WARNING, "%s: Failed to open %s", repr, spipath);
  76. return false;
  77. }
  78. #define knc_titan_spi_txrx linux_spi_txrx
  79. static bool knc_titan_detect_one(const char *devpath)
  80. {
  81. static struct cgpu_info *prev_cgpu = NULL;
  82. struct cgpu_info *cgpu;
  83. struct spi_port *spi;
  84. struct knc_titan_info *knc;
  85. int cores = 0, asic, die;
  86. struct titan_info_response resp;
  87. char repr[6];
  88. cgpu = malloc(sizeof(*cgpu));
  89. if (unlikely(!cgpu))
  90. quit(1, "Failed to alloc cgpu_info");
  91. if (!prev_cgpu) {
  92. spi = calloc(1, sizeof(*spi));
  93. if (unlikely(!spi))
  94. quit(1, "Failed to alloc spi_port");
  95. /* Be careful, read lowl-spi.h comments for warnings */
  96. memset(spi, 0, sizeof(*spi));
  97. spi->txrx = knc_titan_spi_txrx;
  98. spi->cgpu = cgpu;
  99. spi->repr = knc_titan_drv.dname;
  100. spi->logprio = LOG_ERR;
  101. spi->speed = KNC_TITAN_SPI_SPEED;
  102. spi->delay = KNC_TITAN_SPI_DELAY;
  103. spi->mode = KNC_TITAN_SPI_MODE;
  104. spi->bits = KNC_TITAN_SPI_BITS;
  105. if (!knc_titan_spi_open(knc_titan_drv.name, spi)) {
  106. free(cgpu);
  107. return false;
  108. }
  109. knc = calloc(1, sizeof(*knc));
  110. if (unlikely(!knc))
  111. quit(1, "Failed to alloc knc_titan_info");
  112. knc->spi = spi;
  113. knc->cgpu = cgpu;
  114. knc->workqueue_max = 1;
  115. } else {
  116. knc = prev_cgpu->device_data;
  117. spi = knc->spi;
  118. }
  119. snprintf(repr, sizeof(repr), "%s %s", knc_titan_drv.name, devpath);
  120. asic = atoi(devpath);
  121. for (die = 0; die < KNC_TITAN_DIES_PER_ASIC; ++die) {
  122. if (!knc_titan_spi_get_info(repr, spi, &resp, die, KNC_TITAN_CORES_PER_DIE))
  123. continue;
  124. if (0 < resp.cores) {
  125. knc->dies[asic][die] = (struct knc_titan_die) {
  126. .asicno = asic,
  127. .dieno = die,
  128. .cores = resp.cores,
  129. .first_proc = cgpu,
  130. .freq = KNC_TITAN_DEFAULT_FREQUENCY,
  131. };
  132. cores += resp.cores;
  133. } else {
  134. knc->dies[asic][die] = (struct knc_titan_die) {
  135. .asicno = -INT_MAX,
  136. .dieno = -INT_MAX,
  137. .cores = 0,
  138. .first_proc = NULL,
  139. };
  140. }
  141. }
  142. if (0 == cores) {
  143. free(cgpu);
  144. if (!prev_cgpu) {
  145. free(knc);
  146. close(spi->fd);
  147. free(spi);
  148. }
  149. return false;
  150. }
  151. applog(LOG_NOTICE, "%s: Found ASIC with %d cores", repr, cores);
  152. *cgpu = (struct cgpu_info) {
  153. .drv = &knc_titan_drv,
  154. .device_path = strdup(devpath),
  155. .set_device_funcs = knc_titan_set_device_funcs,
  156. .deven = DEV_ENABLED,
  157. .procs = cores,
  158. .threads = prev_cgpu ? 0 : 1,
  159. .device_data = knc,
  160. };
  161. const bool rv = add_cgpu_slave(cgpu, prev_cgpu);
  162. prev_cgpu = cgpu;
  163. return rv;
  164. }
  165. static int knc_titan_detect_auto(void)
  166. {
  167. const int first = 0, last = KNC_TITAN_MAX_ASICS - 1;
  168. char devpath[256];
  169. int found = 0, i;
  170. for (i = first; i <= last; ++i)
  171. {
  172. sprintf(devpath, "%d", i);
  173. if (knc_titan_detect_one(devpath))
  174. ++found;
  175. }
  176. return found;
  177. }
  178. static void knc_titan_detect(void)
  179. {
  180. generic_detect(&knc_titan_drv, knc_titan_detect_one, knc_titan_detect_auto, GDF_REQUIRE_DNAME | GDF_DEFAULT_NOAUTO);
  181. }
  182. static bool knc_titan_init(struct thr_info * const thr)
  183. {
  184. const int max_cores = KNC_TITAN_CORES_PER_ASIC;
  185. struct thr_info *mythr;
  186. struct cgpu_info * const cgpu = thr->cgpu, *proc;
  187. struct knc_titan_core *knccore;
  188. struct knc_titan_info *knc;
  189. int i, asic, die, core_base;
  190. int total_cores = 0;
  191. for (proc = cgpu; proc; ) {
  192. if (proc->device != proc) {
  193. applog(LOG_WARNING, "%"PRIpreprv": Extra processor?", proc->proc_repr);
  194. proc = proc->next_proc;
  195. continue;
  196. }
  197. asic = atoi(proc->device_path);
  198. knc = proc->device_data;
  199. die = 0;
  200. core_base = 0;
  201. for (i = 0; i < max_cores; ++i) {
  202. while (i >= (core_base + knc->dies[asic][die].cores)) {
  203. core_base += knc->dies[asic][die].cores;
  204. if (++die >= KNC_TITAN_DIES_PER_ASIC)
  205. break;
  206. }
  207. if (die >= KNC_TITAN_DIES_PER_ASIC)
  208. break;
  209. mythr = proc->thr[0];
  210. mythr->cgpu_data = knccore = malloc(sizeof(*knccore));
  211. if (unlikely(!knccore))
  212. quit(1, "Failed to alloc knc_titan_core");
  213. *knccore = (struct knc_titan_core) {
  214. .asicno = asic,
  215. .dieno = die,
  216. .coreno = i - core_base,
  217. .next_slot = 1,
  218. .die = &(knc->dies[asic][die]),
  219. .proc = proc,
  220. .hwerr_in_row = 0,
  221. .hwerr_disable_time = KNC_TITAN_HWERR_DISABLE_SECS,
  222. };
  223. timer_set_now(&knccore->enable_at);
  224. proc->device_data = knc;
  225. ++total_cores;
  226. applog(LOG_DEBUG, "%s Allocated core %d:%d:%d", proc->device->dev_repr, asic, die, (i - core_base));
  227. proc = proc->next_proc;
  228. if ((!proc) || proc->device == proc)
  229. break;
  230. }
  231. knc->cores = total_cores;
  232. }
  233. cgpu_set_defaults(cgpu);
  234. if (0 >= total_cores)
  235. return false;
  236. /* Init nonce ranges for cores */
  237. double nonce_step = 4294967296.0 / total_cores;
  238. double nonce_f = 0.0;
  239. struct titan_setup_core_params setup_params = {
  240. .bad_address_mask = {0, 0},
  241. .bad_address_match = {0x3FF, 0x3FF},
  242. .difficulty = 0xC,
  243. .thread_enable = 0xFF,
  244. .thread_base_address = {0, 1, 2, 3, 4, 5, 6, 7},
  245. .lookup_gap_mask = {0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7},
  246. .N_mask = {0, 0, 0, 0, 0, 0, 0, 0},
  247. .N_shift = {0, 0, 0, 0, 0, 0, 0, 0},
  248. .nonce_bottom = 0,
  249. .nonce_top = 0xFFFFFFFF,
  250. };
  251. for (proc = cgpu; proc; proc = proc->next_proc) {
  252. nonce_f += nonce_step;
  253. setup_params.nonce_bottom = setup_params.nonce_top + 1;
  254. if (NULL != proc->next_proc)
  255. setup_params.nonce_top = nonce_f;
  256. else
  257. setup_params.nonce_top = 0xFFFFFFFF;
  258. knc = proc->device_data;
  259. mythr = proc->thr[0];
  260. knccore = mythr->cgpu_data;
  261. applog(LOG_DEBUG, "%s Setup core %d:%d:%d, nonces 0x%08X - 0x%08X", proc->device->dev_repr, knccore->asicno, knccore->dieno, knccore->coreno, setup_params.nonce_bottom, setup_params.nonce_top);
  262. knc_titan_setup_core(proc->device->dev_repr, knc->spi, &setup_params, knccore->dieno, knccore->coreno);
  263. }
  264. timer_set_now(&thr->tv_poll);
  265. return true;
  266. }
  267. static void knc_titan_set_queue_full(struct knc_titan_info * const knc)
  268. {
  269. const bool full = (knc->workqueue_size >= knc->workqueue_max);
  270. struct cgpu_info *proc;
  271. for (proc = knc->cgpu; proc; proc = proc->next_proc) {
  272. struct thr_info * const thr = proc->thr[0];
  273. thr->queue_full = full;
  274. }
  275. }
  276. static void knc_titan_remove_local_queue(struct knc_titan_info * const knc, struct work * const work)
  277. {
  278. DL_DELETE(knc->workqueue, work);
  279. free_work(work);
  280. --knc->workqueue_size;
  281. }
  282. static void knc_titan_prune_local_queue(struct thr_info *thr)
  283. {
  284. struct cgpu_info * const cgpu = thr->cgpu;
  285. struct knc_titan_info * const knc = cgpu->device_data;
  286. struct work *work, *tmp;
  287. DL_FOREACH_SAFE(knc->workqueue, work, tmp) {
  288. if (stale_work(work, false))
  289. knc_titan_remove_local_queue(knc, work);
  290. }
  291. knc_titan_set_queue_full(knc);
  292. }
  293. static bool knc_titan_queue_append(struct thr_info * const thr, struct work * const work)
  294. {
  295. struct cgpu_info * const cgpu = thr->cgpu;
  296. struct knc_titan_info * const knc = cgpu->device_data;
  297. if (knc->workqueue_size >= knc->workqueue_max) {
  298. knc_titan_prune_local_queue(thr);
  299. if (thr->queue_full)
  300. return false;
  301. }
  302. DL_APPEND(knc->workqueue, work);
  303. ++knc->workqueue_size;
  304. knc_titan_set_queue_full(knc);
  305. if (thr->queue_full)
  306. knc_titan_prune_local_queue(thr);
  307. return true;
  308. }
  309. #define HASH_LAST_ADDED(head, out) \
  310. (out = (head) ? (ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail)) : NULL)
  311. static void knc_titan_queue_flush(struct thr_info * const thr)
  312. {
  313. struct cgpu_info * const cgpu = thr->cgpu;
  314. struct knc_titan_info * const knc = cgpu->device_data;
  315. struct work *work, *tmp;
  316. if (knc->cgpu != cgpu)
  317. return;
  318. DL_FOREACH_SAFE(knc->workqueue, work, tmp){
  319. knc_titan_remove_local_queue(knc, work);
  320. }
  321. knc_titan_set_queue_full(knc);
  322. HASH_LAST_ADDED(knc->devicework, work);
  323. if (work && stale_work(work, true)) {
  324. knc->need_flush = true;
  325. timer_set_now(&thr->tv_poll);
  326. }
  327. }
  328. static void knc_titan_poll(struct thr_info * const thr)
  329. {
  330. struct cgpu_info * const cgpu = thr->cgpu;
  331. struct knc_titan_info * const knc = cgpu->device_data;
  332. struct spi_port * const spi = knc->spi;
  333. struct knc_titan_core *knccore;
  334. struct work *work, *tmp;
  335. int workaccept = 0;
  336. unsigned long delay_usecs = KNC_POLL_INTERVAL_US;
  337. struct titan_report report;
  338. bool urgent = false;
  339. knc_titan_prune_local_queue(thr);
  340. spi_clear_buf(spi);
  341. if (knc->need_flush) {
  342. applog(LOG_NOTICE, "%s: Flushing stale works", knc_titan_drv.dname);
  343. urgent = true;
  344. }
  345. knccore = cgpu->thr[0]->cgpu_data;
  346. DL_FOREACH(knc->workqueue, work) {
  347. bool work_accepted;
  348. if (!knc_titan_set_work(cgpu->dev_repr, knc->spi, &report, 0, 0xFFFF, knccore->next_slot, work, urgent, &work_accepted))
  349. work_accepted = false;
  350. if (!work_accepted)
  351. break;
  352. if (++(knccore->next_slot) >= 16)
  353. knccore->next_slot = 1;
  354. urgent = false;
  355. ++workaccept;
  356. }
  357. applog(LOG_DEBUG, "%s: %d jobs accepted to queue (max=%d)", knc_titan_drv.dname, workaccept, knc->workqueue_max);
  358. while (true) {
  359. /* TODO: collect reports from processors */
  360. }
  361. if (knc->need_flush) {
  362. knc->need_flush = false;
  363. HASH_ITER(hh, knc->devicework, work, tmp)
  364. {
  365. HASH_DEL(knc->devicework, work);
  366. free_work(work);
  367. }
  368. delay_usecs = 0;
  369. }
  370. if (workaccept) {
  371. if (workaccept >= knc->workqueue_max) {
  372. knc->workqueue_max = workaccept;
  373. delay_usecs = 0;
  374. }
  375. DL_FOREACH_SAFE(knc->workqueue, work, tmp) {
  376. --knc->workqueue_size;
  377. DL_DELETE(knc->workqueue, work);
  378. work->device_id = knc->next_id++;
  379. HASH_ADD(hh, knc->devicework, device_id, sizeof(work->device_id), work);
  380. if (!--workaccept)
  381. break;
  382. }
  383. knc_titan_set_queue_full(knc);
  384. }
  385. timer_set_delay_from_now(&thr->tv_poll, delay_usecs);
  386. }
  387. /*
  388. * specify settings / options via RPC or command line
  389. */
  390. /* support for --set-device
  391. * must be set before probing the device
  392. */
  393. static void knc_titan_set_clock_freq(struct cgpu_info * const device, int const val)
  394. {
  395. }
  396. static const char *knc_titan_set_clock(struct cgpu_info * const device, const char * const option, const char * const setting, char * const replybuf, enum bfg_set_device_replytype * const success)
  397. {
  398. knc_titan_set_clock_freq(device, atoi(setting));
  399. return NULL;
  400. }
  401. static const struct bfg_set_device_definition knc_titan_set_device_funcs[] = {
  402. { "clock", knc_titan_set_clock, NULL },
  403. { NULL },
  404. };
  405. /*
  406. * specify settings / options via TUI
  407. */
  408. #ifdef HAVE_CURSES
  409. static void knc_titan_tui_wlogprint_choices(struct cgpu_info * const proc)
  410. {
  411. wlogprint("[C]lock speed ");
  412. }
  413. static const char *knc_titan_tui_handle_choice(struct cgpu_info * const proc, const int input)
  414. {
  415. static char buf[0x100]; /* Static for replies */
  416. switch (input)
  417. {
  418. case 'c': case 'C':
  419. {
  420. sprintf(buf, "Set clock speed");
  421. char * const setting = curses_input(buf);
  422. knc_titan_set_clock_freq(proc->device, atoi(setting));
  423. return "Clock speed changed\n";
  424. }
  425. }
  426. return NULL;
  427. }
  428. static void knc_titan_wlogprint_status(struct cgpu_info * const proc)
  429. {
  430. wlogprint("Clock speed: N/A\n");
  431. }
  432. #endif
  433. struct device_drv knc_titan_drv =
  434. {
  435. /* metadata */
  436. .dname = "titan",
  437. .name = "KNC",
  438. .supported_algos = POW_SCRYPT,
  439. .drv_detect = knc_titan_detect,
  440. .thread_init = knc_titan_init,
  441. /* specify mining type - queue */
  442. .minerloop = minerloop_queue,
  443. .queue_append = knc_titan_queue_append,
  444. .queue_flush = knc_titan_queue_flush,
  445. .poll = knc_titan_poll,
  446. /* TUI support - e.g. setting clock via UI */
  447. #ifdef HAVE_CURSES
  448. .proc_wlogprint_status = knc_titan_wlogprint_status,
  449. .proc_tui_wlogprint_choices = knc_titan_tui_wlogprint_choices,
  450. .proc_tui_handle_choice = knc_titan_tui_handle_choice,
  451. #endif
  452. };