driver-knc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /*
  2. * Copyright 2013 Luke Dashjr
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 3 of the License, or (at your option)
  7. * any later version. See COPYING for more details.
  8. */
  9. #include "config.h"
  10. #include <stdbool.h>
  11. #include <stddef.h>
  12. #include <stdint.h>
  13. #include <sys/ioctl.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #ifdef HAVE_LINUX_I2C_DEV_USER_H
  18. #include <linux/i2c-dev-user.h>
  19. #else
  20. #include <linux/i2c-dev.h>
  21. #endif
  22. #include <linux/spi/spidev.h>
  23. #include <uthash.h>
  24. #include "deviceapi.h"
  25. #include "logging.h"
  26. #include "miner.h"
  27. #include "spidevc.h"
  28. #define KNC_POLL_INTERVAL_US 10000
  29. #define KNC_SPI_SPEED 3000000
  30. #define KNC_SPI_DELAY 0
  31. #define KNC_SPI_MODE (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
  32. #define KNC_SPI_BITS 8
  33. static const char * const i2cpath = "/dev/i2c-2";
  34. #define KNC_I2C_TEMPLATE "/dev/i2c-%d"
  35. enum knc_request_cmd {
  36. KNC_REQ_SUBMIT_WORK = 2,
  37. KNC_REQ_FLUSH_QUEUE = 3,
  38. };
  39. enum knc_reply_type {
  40. KNC_REPLY_NONCE_FOUND = 1,
  41. KNC_REPLY_WORK_DONE = 2,
  42. };
  43. struct device_drv knc_drv;
  44. struct knc_device {
  45. int i2c;
  46. struct spi_port *spi;
  47. struct cgpu_info *cgpu;
  48. bool need_flush;
  49. struct work *workqueue;
  50. int workqueue_size;
  51. int workqueue_max;
  52. int next_id;
  53. struct work *devicework;
  54. };
  55. struct knc_core {
  56. int asicno;
  57. int coreno;
  58. };
  59. static
  60. bool knc_detect_one(const char *devpath)
  61. {
  62. static struct cgpu_info *prev_cgpu = NULL;
  63. struct cgpu_info *cgpu;
  64. int i;
  65. const int fd = open(i2cpath, O_RDWR);
  66. char *leftover = NULL;
  67. const int i2cslave = strtol(devpath, &leftover, 0);
  68. uint8_t buf[0x20];
  69. if (leftover && leftover[0])
  70. return false;
  71. if (unlikely(fd == -1))
  72. {
  73. applog(LOG_DEBUG, "%s: Failed to open %s", __func__, i2cpath);
  74. return false;
  75. }
  76. if (ioctl(fd, I2C_SLAVE, i2cslave))
  77. {
  78. close(fd);
  79. applog(LOG_DEBUG, "%s: Failed to select i2c slave 0x%x",
  80. __func__, i2cslave);
  81. return false;
  82. }
  83. i = i2c_smbus_read_i2c_block_data(fd, 0, 0x20, buf);
  84. close(fd);
  85. if (-1 == i)
  86. {
  87. applog(LOG_DEBUG, "%s: 0x%x: Failed to read i2c block data",
  88. __func__, i2cslave);
  89. return false;
  90. }
  91. for (i = 0; ; ++i)
  92. {
  93. if (buf[i] == 3)
  94. break;
  95. if (i == 0x1f)
  96. return false;
  97. }
  98. cgpu = malloc(sizeof(*cgpu));
  99. *cgpu = (struct cgpu_info){
  100. .drv = &knc_drv,
  101. .device_path = strdup(devpath),
  102. .deven = DEV_ENABLED,
  103. .procs = 192,
  104. .threads = prev_cgpu ? 0 : 1,
  105. };
  106. const bool rv = add_cgpu_slave(cgpu, prev_cgpu);
  107. prev_cgpu = cgpu;
  108. return rv;
  109. }
  110. static int knc_detect_auto(void)
  111. {
  112. const int first = 0x20, last = 0x26;
  113. char devpath[4];
  114. int found = 0, i;
  115. for (i = first; i <= last; ++i)
  116. {
  117. sprintf(devpath, "%d", i);
  118. if (knc_detect_one(devpath))
  119. ++found;
  120. }
  121. return found;
  122. }
  123. static void knc_detect(void)
  124. {
  125. generic_detect(&knc_drv, knc_detect_one, knc_detect_auto, GDF_REQUIRE_DNAME | GDF_DEFAULT_NOAUTO);
  126. }
  127. static
  128. bool knc_spi_open(const char *repr, struct spi_port * const spi)
  129. {
  130. const char * const spipath = "/dev/spidev1.0";
  131. const int fd = open(spipath, O_RDWR);
  132. const uint8_t lsbfirst = 0;
  133. if (fd == -1)
  134. return false;
  135. if (ioctl(fd, SPI_IOC_WR_MODE , &spi->mode )) goto fail;
  136. if (ioctl(fd, SPI_IOC_WR_LSB_FIRST , &lsbfirst )) goto fail;
  137. if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi->bits )) goto fail;
  138. if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ , &spi->speed)) goto fail;
  139. spi->fd = fd;
  140. return true;
  141. fail:
  142. close(fd);
  143. spi->fd = -1;
  144. applog(LOG_WARNING, "%s: Failed to open %s", repr, spipath);
  145. return false;
  146. }
  147. static
  148. bool knc_spi_txrx(struct spi_port * const spi)
  149. {
  150. const void * const wrbuf = spi_gettxbuf(spi);
  151. void * const rdbuf = spi_getrxbuf(spi);
  152. const size_t bufsz = spi_getbufsz(spi);
  153. const int fd = spi->fd;
  154. struct spi_ioc_transfer xf = {
  155. .tx_buf = (uintptr_t) wrbuf,
  156. .rx_buf = (uintptr_t) rdbuf,
  157. .len = bufsz,
  158. .delay_usecs = spi->delay,
  159. .speed_hz = spi->speed,
  160. .bits_per_word = spi->bits,
  161. };
  162. return (ioctl(fd, SPI_IOC_MESSAGE(1), &xf) > 0);
  163. }
  164. static
  165. void knc_clean_flush(struct spi_port * const spi)
  166. {
  167. const uint8_t flushcmd = KNC_REQ_FLUSH_QUEUE << 4;
  168. const size_t spi_req_sz = 0x1000;
  169. spi_clear_buf(spi);
  170. spi_emit_buf(spi, &flushcmd, 1);
  171. spi_emit_nop(spi, spi_req_sz - spi_getbufsz(spi));
  172. applog(LOG_DEBUG, "%s: Issuing flush command to clear out device queues", knc_drv.dname);
  173. spi_txrx(spi);
  174. }
  175. static
  176. bool knc_init(struct thr_info * const thr)
  177. {
  178. const int max_cores = 192;
  179. struct thr_info *mythr;
  180. struct cgpu_info * const cgpu = thr->cgpu, *proc;
  181. struct knc_device *knc;
  182. struct knc_core *knccore;
  183. struct spi_port *spi;
  184. const int i2c = open(i2cpath, O_RDWR);
  185. int i2cslave, i, j;
  186. uint8_t buf[0x20];
  187. if (unlikely(i2c == -1))
  188. {
  189. applog(LOG_DEBUG, "%s: Failed to open %s", __func__, i2cpath);
  190. return false;
  191. }
  192. knc = malloc(sizeof(*knc));
  193. for (proc = cgpu; proc; )
  194. {
  195. if (proc->device != proc)
  196. {
  197. applog(LOG_WARNING, "%"PRIpreprv": Extra processor?", proc->proc_repr);
  198. continue;
  199. }
  200. i2cslave = atoi(proc->device_path);
  201. if (ioctl(i2c, I2C_SLAVE, i2cslave))
  202. {
  203. applog(LOG_DEBUG, "%s: Failed to select i2c slave 0x%x",
  204. __func__, i2cslave);
  205. return false;
  206. }
  207. for (i = 0; i < max_cores; i += 0x20)
  208. {
  209. i2c_smbus_read_i2c_block_data(i2c, i, 0x20, buf);
  210. for (j = 0; j < 0x20; ++j)
  211. {
  212. mythr = proc->thr[0];
  213. mythr->cgpu_data = knccore = malloc(sizeof(*knccore));
  214. *knccore = (struct knc_core){
  215. .asicno = i2cslave - 0x20,
  216. .coreno = i + j,
  217. };
  218. if (proc != cgpu)
  219. mythr->queue_full = true;
  220. proc->device_data = knc;
  221. if (buf[j] != 3)
  222. proc->deven = DEV_DISABLED;
  223. proc = proc->next_proc;
  224. if ((!proc) || proc->device == proc)
  225. goto nomorecores;
  226. }
  227. }
  228. nomorecores: ;
  229. }
  230. spi = malloc(sizeof(*spi));
  231. *knc = (struct knc_device){
  232. .i2c = i2c,
  233. .spi = spi,
  234. .cgpu = cgpu,
  235. .workqueue_max = 1,
  236. };
  237. *spi = (struct spi_port){
  238. .txrx = knc_spi_txrx,
  239. .cgpu = cgpu,
  240. .repr = knc_drv.dname,
  241. .logprio = LOG_ERR,
  242. .speed = KNC_SPI_SPEED,
  243. .delay = KNC_SPI_DELAY,
  244. .mode = KNC_SPI_MODE,
  245. .bits = KNC_SPI_BITS,
  246. };
  247. if (!knc_spi_open(cgpu->dev_repr, spi))
  248. return false;
  249. knc_clean_flush(spi);
  250. timer_set_now(&thr->tv_poll);
  251. return true;
  252. }
  253. static
  254. void knc_remove_local_queue(struct knc_device * const knc, struct work * const work)
  255. {
  256. DL_DELETE(knc->workqueue, work);
  257. free_work(work);
  258. --knc->workqueue_size;
  259. }
  260. static
  261. void knc_prune_local_queue(struct thr_info *thr)
  262. {
  263. struct cgpu_info * const cgpu = thr->cgpu;
  264. struct knc_device * const knc = cgpu->device_data;
  265. struct work *work, *tmp;
  266. DL_FOREACH_SAFE(knc->workqueue, work, tmp)
  267. {
  268. if (stale_work(work, false))
  269. knc_remove_local_queue(knc, work);
  270. }
  271. thr->queue_full = (knc->workqueue_size >= knc->workqueue_max);
  272. }
  273. static
  274. bool knc_queue_append(struct thr_info * const thr, struct work * const work)
  275. {
  276. struct cgpu_info * const cgpu = thr->cgpu;
  277. struct knc_device * const knc = cgpu->device_data;
  278. if (knc->workqueue_size >= knc->workqueue_max)
  279. {
  280. knc_prune_local_queue(thr);
  281. if (thr->queue_full)
  282. return false;
  283. }
  284. DL_APPEND(knc->workqueue, work);
  285. ++knc->workqueue_size;
  286. thr->queue_full = (knc->workqueue_size >= knc->workqueue_max);
  287. if (thr->queue_full)
  288. knc_prune_local_queue(thr);
  289. return true;
  290. }
  291. #define HASH_LAST_ADDED(head, out) \
  292. (out = (head) ? (ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail)) : NULL)
  293. static
  294. void knc_queue_flush(struct thr_info * const thr)
  295. {
  296. struct cgpu_info * const cgpu = thr->cgpu;
  297. struct knc_device * const knc = cgpu->device_data;
  298. struct work *work, *tmp;
  299. if (knc->cgpu != cgpu)
  300. return;
  301. DL_FOREACH_SAFE(knc->workqueue, work, tmp)
  302. {
  303. knc_remove_local_queue(knc, work);
  304. }
  305. thr->queue_full = false;
  306. HASH_LAST_ADDED(knc->devicework, work);
  307. if (work && stale_work(work, true))
  308. {
  309. knc->need_flush = true;
  310. timer_set_now(&thr->tv_poll);
  311. }
  312. }
  313. static inline
  314. uint16_t get_u16be(const void * const p)
  315. {
  316. const uint8_t * const b = p;
  317. return (((uint16_t)b[0]) << 8) | b[1];
  318. }
  319. static inline
  320. uint32_t get_u32be(const void * const p)
  321. {
  322. const uint8_t * const b = p;
  323. return (((uint32_t)b[0]) << 0x18)
  324. | (((uint32_t)b[1]) << 0x10)
  325. | (((uint32_t)b[2]) << 8)
  326. | b[3];
  327. }
  328. static
  329. void knc_poll(struct thr_info * const thr)
  330. {
  331. struct thr_info *mythr;
  332. struct cgpu_info * const cgpu = thr->cgpu, *proc;
  333. struct knc_device * const knc = cgpu->device_data;
  334. struct spi_port * const spi = knc->spi;
  335. struct knc_core *knccore;
  336. struct work *work, *tmp;
  337. uint8_t buf[0x30], *rxbuf;
  338. int works_sent = 0, asicno, i;
  339. uint16_t workaccept;
  340. int workid = knc->next_id;
  341. uint32_t nonce, coreno;
  342. size_t spi_req_sz = 0x1000;
  343. unsigned long delay_usecs = KNC_POLL_INTERVAL_US;
  344. knc_prune_local_queue(thr);
  345. spi_clear_buf(spi);
  346. if (knc->need_flush)
  347. {
  348. applog(LOG_NOTICE, "%s: Abandoning stale searches to restart", knc_drv.dname);
  349. buf[0] = KNC_REQ_FLUSH_QUEUE << 4;
  350. spi_emit_buf(spi, buf, sizeof(buf));
  351. }
  352. DL_FOREACH(knc->workqueue, work)
  353. {
  354. buf[0] = KNC_REQ_SUBMIT_WORK << 4;
  355. buf[1] = 0;
  356. buf[2] = (workid >> 8) & 0x7f;
  357. buf[3] = workid & 0xff;
  358. for (i = 0; i < 0x20; ++i)
  359. buf[4 + i] = work->midstate[0x1f - i];
  360. for (i = 0; i < 0xc; ++i)
  361. buf[0x24 + i] = work->data[0x4b - i];
  362. spi_emit_buf(spi, buf, sizeof(buf));
  363. ++works_sent;
  364. ++workid;
  365. }
  366. spi_emit_nop(spi, spi_req_sz - spi_getbufsz(spi));
  367. spi_txrx(spi);
  368. rxbuf = spi_getrxbuf(spi);
  369. if (rxbuf[3] & 1)
  370. applog(LOG_DEBUG, "%s: Receive buffer overflow reported", knc_drv.dname);
  371. workaccept = get_u16be(&rxbuf[6]);
  372. applog(LOG_DEBUG, "%s: %lu/%d jobs accepted to queue (max=%d)",
  373. knc_drv.dname, (unsigned long)workaccept, works_sent, knc->workqueue_max);
  374. while (true)
  375. {
  376. rxbuf += 0xc;
  377. spi_req_sz -= 0xc;
  378. if (spi_req_sz < 0xc)
  379. break;
  380. const int rtype = rxbuf[0] >> 6;
  381. if (rtype && opt_debug)
  382. {
  383. char x[(0xc * 2) + 1];
  384. bin2hex(x, rxbuf, 0xc);
  385. applog(LOG_DEBUG, "%s: RECV: %s", knc_drv.dname, x);
  386. }
  387. if (rtype != KNC_REPLY_NONCE_FOUND && rtype != KNC_REPLY_WORK_DONE)
  388. continue;
  389. asicno = (rxbuf[0] & 0x38) >> 3;
  390. coreno = get_u32be(&rxbuf[8]);
  391. proc = cgpu;
  392. while (true)
  393. {
  394. knccore = proc->thr[0]->cgpu_data;
  395. if (knccore->asicno == asicno)
  396. break;
  397. do {
  398. proc = proc->next_proc;
  399. } while(proc != proc->device);
  400. }
  401. for (i = 0; i < coreno; ++i)
  402. proc = proc->next_proc;
  403. mythr = proc->thr[0];
  404. i = get_u16be(&rxbuf[2]);
  405. HASH_FIND_INT(knc->devicework, &i, work);
  406. if (!work)
  407. {
  408. const char * const msgtype = (rtype == KNC_REPLY_NONCE_FOUND) ? "nonce found" : "work done";
  409. applog(LOG_WARNING, "%"PRIpreprv": Got %s message about unknown work 0x%04x",
  410. proc->proc_repr, msgtype, i);
  411. if (KNC_REPLY_NONCE_FOUND == rtype)
  412. {
  413. nonce = get_u32be(&rxbuf[4]);
  414. nonce = le32toh(nonce);
  415. inc_hw_errors2(mythr, NULL, &nonce);
  416. }
  417. else
  418. inc_hw_errors2(mythr, NULL, NULL);
  419. continue;
  420. }
  421. switch (rtype)
  422. {
  423. case KNC_REPLY_NONCE_FOUND:
  424. nonce = get_u32be(&rxbuf[4]);
  425. nonce = le32toh(nonce);
  426. submit_nonce(mythr, work, nonce);
  427. break;
  428. case KNC_REPLY_WORK_DONE:
  429. HASH_DEL(knc->devicework, work);
  430. free_work(work);
  431. hashes_done2(mythr, 0x100000000, NULL);
  432. break;
  433. }
  434. }
  435. if (knc->need_flush)
  436. {
  437. knc->need_flush = false;
  438. HASH_ITER(hh, knc->devicework, work, tmp)
  439. {
  440. HASH_DEL(knc->devicework, work);
  441. free_work(work);
  442. }
  443. delay_usecs = 0;
  444. }
  445. if (workaccept)
  446. {
  447. if (workaccept >= knc->workqueue_max)
  448. {
  449. knc->workqueue_max = workaccept;
  450. delay_usecs = 0;
  451. }
  452. DL_FOREACH_SAFE(knc->workqueue, work, tmp)
  453. {
  454. --knc->workqueue_size;
  455. DL_DELETE(knc->workqueue, work);
  456. work->device_id = knc->next_id++ & 0x7fff;
  457. HASH_ADD_INT(knc->devicework, device_id, work);
  458. if (!--workaccept)
  459. break;
  460. }
  461. thr->queue_full = (knc->workqueue_size >= knc->workqueue_max);
  462. }
  463. timer_set_delay_from_now(&thr->tv_poll, delay_usecs);
  464. }
  465. static
  466. bool _knc_core_setstatus(struct thr_info * const thr, uint8_t val)
  467. {
  468. struct cgpu_info * const proc = thr->cgpu;
  469. struct knc_device * const knc = proc->device_data;
  470. struct knc_core * const knccore = thr->cgpu_data;
  471. const int i2c = knc->i2c;
  472. const int i2cslave = 0x20 + knccore->asicno;
  473. if (ioctl(i2c, I2C_SLAVE, i2cslave))
  474. {
  475. applog(LOG_DEBUG, "%"PRIpreprv": %s: Failed to select i2c slave 0x%x",
  476. proc->proc_repr, __func__, i2cslave);
  477. return false;
  478. }
  479. return (-1 != i2c_smbus_write_byte_data(i2c, knccore->coreno, val));
  480. }
  481. static
  482. void knc_core_disable(struct thr_info * const thr)
  483. {
  484. _knc_core_setstatus(thr, 0);
  485. }
  486. static
  487. void knc_core_enable(struct thr_info * const thr)
  488. {
  489. _knc_core_setstatus(thr, 1);
  490. }
  491. static
  492. bool knc_get_stats(struct cgpu_info * const cgpu)
  493. {
  494. if (cgpu->device != cgpu)
  495. return true;
  496. struct knc_core * const knccore = cgpu->thr[0]->cgpu_data;
  497. struct cgpu_info *proc;
  498. const int i2cdev = knccore->asicno + 3;
  499. const int i2cslave = 0x48;
  500. int i2c;
  501. int32_t rawtemp;
  502. float temp;
  503. bool rv = false;
  504. char i2cpath[sizeof(KNC_I2C_TEMPLATE)];
  505. sprintf(i2cpath, KNC_I2C_TEMPLATE, i2cdev);
  506. i2c = open(i2cpath, O_RDWR);
  507. if (i2c == -1)
  508. {
  509. applog(LOG_DEBUG, "%s: %s: Failed to open %s",
  510. cgpu->dev_repr, __func__, i2cpath);
  511. return false;
  512. }
  513. if (ioctl(i2c, I2C_SLAVE, i2cslave))
  514. {
  515. applog(LOG_DEBUG, "%s: %s: Failed to select i2c slave 0x%x",
  516. cgpu->dev_repr, __func__, i2cslave);
  517. goto out;
  518. }
  519. rawtemp = i2c_smbus_read_word_data(i2c, 0);
  520. if (rawtemp == -1)
  521. goto out;
  522. temp = ((float)(rawtemp & 0xff));
  523. if (rawtemp & 0x100)
  524. temp += 0.5;
  525. for (proc = cgpu; proc && proc->device == cgpu; proc = proc->next_proc)
  526. proc->temp = temp;
  527. rv = true;
  528. out:
  529. close(i2c);
  530. return rv;
  531. }
  532. struct device_drv knc_drv = {
  533. .dname = "knc",
  534. .name = "KNC",
  535. .drv_detect = knc_detect,
  536. .thread_init = knc_init,
  537. .thread_disable = knc_core_disable,
  538. .thread_enable = knc_core_enable,
  539. .minerloop = minerloop_queue,
  540. .queue_append = knc_queue_append,
  541. .queue_flush = knc_queue_flush,
  542. .poll = knc_poll,
  543. .get_stats = knc_get_stats,
  544. };