nitrox_reqmgr.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/gfp.h>
  3. #include <linux/workqueue.h>
  4. #include <crypto/internal/skcipher.h>
  5. #include "nitrox_common.h"
  6. #include "nitrox_dev.h"
  7. #include "nitrox_req.h"
  8. #include "nitrox_csr.h"
  9. /* SLC_STORE_INFO */
  10. #define MIN_UDD_LEN 16
  11. /* PKT_IN_HDR + SLC_STORE_INFO */
  12. #define FDATA_SIZE 32
  13. /* Base destination port for the solicited requests */
  14. #define SOLICIT_BASE_DPORT 256
  15. #define REQ_NOT_POSTED 1
  16. #define REQ_BACKLOG 2
  17. #define REQ_POSTED 3
  18. /*
  19. * Response codes from SE microcode
  20. * 0x00 - Success
  21. * Completion with no error
  22. * 0x43 - ERR_GC_DATA_LEN_INVALID
  23. * Invalid Data length if Encryption Data length is
  24. * less than 16 bytes for AES-XTS and AES-CTS.
  25. * 0x45 - ERR_GC_CTX_LEN_INVALID
  26. * Invalid context length: CTXL != 23 words.
  27. * 0x4F - ERR_GC_DOCSIS_CIPHER_INVALID
  28. * DOCSIS support is enabled with other than
  29. * AES/DES-CBC mode encryption.
  30. * 0x50 - ERR_GC_DOCSIS_OFFSET_INVALID
  31. * Authentication offset is other than 0 with
  32. * Encryption IV source = 0.
  33. * Authentication offset is other than 8 (DES)/16 (AES)
  34. * with Encryption IV source = 1
  35. * 0x51 - ERR_GC_CRC32_INVALID_SELECTION
  36. * CRC32 is enabled for other than DOCSIS encryption.
  37. * 0x52 - ERR_GC_AES_CCM_FLAG_INVALID
  38. * Invalid flag options in AES-CCM IV.
  39. */
  40. static inline int incr_index(int index, int count, int max)
  41. {
  42. if ((index + count) >= max)
  43. index = index + count - max;
  44. else
  45. index += count;
  46. return index;
  47. }
  48. static void softreq_unmap_sgbufs(struct nitrox_softreq *sr)
  49. {
  50. struct nitrox_device *ndev = sr->ndev;
  51. struct device *dev = DEV(ndev);
  52. dma_unmap_sg(dev, sr->in.sg, sg_nents(sr->in.sg),
  53. DMA_BIDIRECTIONAL);
  54. dma_unmap_single(dev, sr->in.sgcomp_dma, sr->in.sgcomp_len,
  55. DMA_TO_DEVICE);
  56. kfree(sr->in.sgcomp);
  57. sr->in.sg = NULL;
  58. sr->in.sgmap_cnt = 0;
  59. dma_unmap_sg(dev, sr->out.sg, sg_nents(sr->out.sg),
  60. DMA_BIDIRECTIONAL);
  61. dma_unmap_single(dev, sr->out.sgcomp_dma, sr->out.sgcomp_len,
  62. DMA_TO_DEVICE);
  63. kfree(sr->out.sgcomp);
  64. sr->out.sg = NULL;
  65. sr->out.sgmap_cnt = 0;
  66. }
  67. static void softreq_destroy(struct nitrox_softreq *sr)
  68. {
  69. softreq_unmap_sgbufs(sr);
  70. kfree(sr);
  71. }
  72. /**
  73. * create_sg_component - create SG componets for N5 device.
  74. * @sr: Request structure
  75. * @sgtbl: SG table
  76. * @map_nents: number of dma mapped entries
  77. *
  78. * Component structure
  79. *
  80. * 63 48 47 32 31 16 15 0
  81. * --------------------------------------
  82. * | LEN0 | LEN1 | LEN2 | LEN3 |
  83. * |-------------------------------------
  84. * | PTR0 |
  85. * --------------------------------------
  86. * | PTR1 |
  87. * --------------------------------------
  88. * | PTR2 |
  89. * --------------------------------------
  90. * | PTR3 |
  91. * --------------------------------------
  92. *
  93. * Returns 0 if success or a negative errno code on error.
  94. */
  95. static int create_sg_component(struct nitrox_softreq *sr,
  96. struct nitrox_sgtable *sgtbl, int map_nents)
  97. {
  98. struct nitrox_device *ndev = sr->ndev;
  99. struct nitrox_sgcomp *sgcomp;
  100. struct scatterlist *sg;
  101. dma_addr_t dma;
  102. size_t sz_comp;
  103. int i, j, nr_sgcomp;
  104. nr_sgcomp = roundup(map_nents, 4) / 4;
  105. /* each component holds 4 dma pointers */
  106. sz_comp = nr_sgcomp * sizeof(*sgcomp);
  107. sgcomp = kzalloc(sz_comp, sr->gfp);
  108. if (!sgcomp)
  109. return -ENOMEM;
  110. sgtbl->sgcomp = sgcomp;
  111. sg = sgtbl->sg;
  112. /* populate device sg component */
  113. for (i = 0; i < nr_sgcomp; i++) {
  114. for (j = 0; j < 4 && sg; j++) {
  115. sgcomp[i].len[j] = cpu_to_be16(sg_dma_len(sg));
  116. sgcomp[i].dma[j] = cpu_to_be64(sg_dma_address(sg));
  117. sg = sg_next(sg);
  118. }
  119. }
  120. /* map the device sg component */
  121. dma = dma_map_single(DEV(ndev), sgtbl->sgcomp, sz_comp, DMA_TO_DEVICE);
  122. if (dma_mapping_error(DEV(ndev), dma)) {
  123. kfree(sgtbl->sgcomp);
  124. sgtbl->sgcomp = NULL;
  125. return -ENOMEM;
  126. }
  127. sgtbl->sgcomp_dma = dma;
  128. sgtbl->sgcomp_len = sz_comp;
  129. return 0;
  130. }
  131. /**
  132. * dma_map_inbufs - DMA map input sglist and creates sglist component
  133. * for N5 device.
  134. * @sr: Request structure
  135. * @req: Crypto request structre
  136. *
  137. * Returns 0 if successful or a negative errno code on error.
  138. */
  139. static int dma_map_inbufs(struct nitrox_softreq *sr,
  140. struct se_crypto_request *req)
  141. {
  142. struct device *dev = DEV(sr->ndev);
  143. struct scatterlist *sg;
  144. int i, nents, ret = 0;
  145. nents = dma_map_sg(dev, req->src, sg_nents(req->src),
  146. DMA_BIDIRECTIONAL);
  147. if (!nents)
  148. return -EINVAL;
  149. for_each_sg(req->src, sg, nents, i)
  150. sr->in.total_bytes += sg_dma_len(sg);
  151. sr->in.sg = req->src;
  152. sr->in.sgmap_cnt = nents;
  153. ret = create_sg_component(sr, &sr->in, sr->in.sgmap_cnt);
  154. if (ret)
  155. goto incomp_err;
  156. return 0;
  157. incomp_err:
  158. dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_BIDIRECTIONAL);
  159. sr->in.sgmap_cnt = 0;
  160. return ret;
  161. }
  162. static int dma_map_outbufs(struct nitrox_softreq *sr,
  163. struct se_crypto_request *req)
  164. {
  165. struct device *dev = DEV(sr->ndev);
  166. int nents, ret = 0;
  167. nents = dma_map_sg(dev, req->dst, sg_nents(req->dst),
  168. DMA_BIDIRECTIONAL);
  169. if (!nents)
  170. return -EINVAL;
  171. sr->out.sg = req->dst;
  172. sr->out.sgmap_cnt = nents;
  173. ret = create_sg_component(sr, &sr->out, sr->out.sgmap_cnt);
  174. if (ret)
  175. goto outcomp_map_err;
  176. return 0;
  177. outcomp_map_err:
  178. dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_BIDIRECTIONAL);
  179. sr->out.sgmap_cnt = 0;
  180. sr->out.sg = NULL;
  181. return ret;
  182. }
  183. static inline int softreq_map_iobuf(struct nitrox_softreq *sr,
  184. struct se_crypto_request *creq)
  185. {
  186. int ret;
  187. ret = dma_map_inbufs(sr, creq);
  188. if (ret)
  189. return ret;
  190. ret = dma_map_outbufs(sr, creq);
  191. if (ret)
  192. softreq_unmap_sgbufs(sr);
  193. return ret;
  194. }
  195. static inline void backlog_list_add(struct nitrox_softreq *sr,
  196. struct nitrox_cmdq *cmdq)
  197. {
  198. INIT_LIST_HEAD(&sr->backlog);
  199. spin_lock_bh(&cmdq->backlog_qlock);
  200. list_add_tail(&sr->backlog, &cmdq->backlog_head);
  201. atomic_inc(&cmdq->backlog_count);
  202. atomic_set(&sr->status, REQ_BACKLOG);
  203. spin_unlock_bh(&cmdq->backlog_qlock);
  204. }
  205. static inline void response_list_add(struct nitrox_softreq *sr,
  206. struct nitrox_cmdq *cmdq)
  207. {
  208. INIT_LIST_HEAD(&sr->response);
  209. spin_lock_bh(&cmdq->resp_qlock);
  210. list_add_tail(&sr->response, &cmdq->response_head);
  211. spin_unlock_bh(&cmdq->resp_qlock);
  212. }
  213. static inline void response_list_del(struct nitrox_softreq *sr,
  214. struct nitrox_cmdq *cmdq)
  215. {
  216. spin_lock_bh(&cmdq->resp_qlock);
  217. list_del(&sr->response);
  218. spin_unlock_bh(&cmdq->resp_qlock);
  219. }
  220. static struct nitrox_softreq *
  221. get_first_response_entry(struct nitrox_cmdq *cmdq)
  222. {
  223. return list_first_entry_or_null(&cmdq->response_head,
  224. struct nitrox_softreq, response);
  225. }
  226. static inline bool cmdq_full(struct nitrox_cmdq *cmdq, int qlen)
  227. {
  228. if (atomic_inc_return(&cmdq->pending_count) > qlen) {
  229. atomic_dec(&cmdq->pending_count);
  230. /* sync with other cpus */
  231. smp_mb__after_atomic();
  232. return true;
  233. }
  234. /* sync with other cpus */
  235. smp_mb__after_atomic();
  236. return false;
  237. }
  238. /**
  239. * post_se_instr - Post SE instruction to Packet Input ring
  240. * @sr: Request structure
  241. * @cmdq: Command queue structure
  242. *
  243. * Returns 0 if successful or a negative error code,
  244. * if no space in ring.
  245. */
  246. static void post_se_instr(struct nitrox_softreq *sr,
  247. struct nitrox_cmdq *cmdq)
  248. {
  249. struct nitrox_device *ndev = sr->ndev;
  250. int idx;
  251. u8 *ent;
  252. spin_lock_bh(&cmdq->cmd_qlock);
  253. idx = cmdq->write_idx;
  254. /* copy the instruction */
  255. ent = cmdq->base + (idx * cmdq->instr_size);
  256. memcpy(ent, &sr->instr, cmdq->instr_size);
  257. atomic_set(&sr->status, REQ_POSTED);
  258. response_list_add(sr, cmdq);
  259. sr->tstamp = jiffies;
  260. /* flush the command queue updates */
  261. dma_wmb();
  262. /* Ring doorbell with count 1 */
  263. writeq(1, cmdq->dbell_csr_addr);
  264. cmdq->write_idx = incr_index(idx, 1, ndev->qlen);
  265. spin_unlock_bh(&cmdq->cmd_qlock);
  266. /* increment the posted command count */
  267. atomic64_inc(&ndev->stats.posted);
  268. }
  269. static int post_backlog_cmds(struct nitrox_cmdq *cmdq)
  270. {
  271. struct nitrox_device *ndev = cmdq->ndev;
  272. struct nitrox_softreq *sr, *tmp;
  273. int ret = 0;
  274. if (!atomic_read(&cmdq->backlog_count))
  275. return 0;
  276. spin_lock_bh(&cmdq->backlog_qlock);
  277. list_for_each_entry_safe(sr, tmp, &cmdq->backlog_head, backlog) {
  278. /* submit until space available */
  279. if (unlikely(cmdq_full(cmdq, ndev->qlen))) {
  280. ret = -ENOSPC;
  281. break;
  282. }
  283. /* delete from backlog list */
  284. list_del(&sr->backlog);
  285. atomic_dec(&cmdq->backlog_count);
  286. /* sync with other cpus */
  287. smp_mb__after_atomic();
  288. /* post the command */
  289. post_se_instr(sr, cmdq);
  290. }
  291. spin_unlock_bh(&cmdq->backlog_qlock);
  292. return ret;
  293. }
  294. static int nitrox_enqueue_request(struct nitrox_softreq *sr)
  295. {
  296. struct nitrox_cmdq *cmdq = sr->cmdq;
  297. struct nitrox_device *ndev = sr->ndev;
  298. /* try to post backlog requests */
  299. post_backlog_cmds(cmdq);
  300. if (unlikely(cmdq_full(cmdq, ndev->qlen))) {
  301. if (!(sr->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
  302. /* increment drop count */
  303. atomic64_inc(&ndev->stats.dropped);
  304. return -ENOSPC;
  305. }
  306. /* add to backlog list */
  307. backlog_list_add(sr, cmdq);
  308. return -EINPROGRESS;
  309. }
  310. post_se_instr(sr, cmdq);
  311. return -EINPROGRESS;
  312. }
  313. /**
  314. * nitrox_process_se_request - Send request to SE core
  315. * @ndev: NITROX device
  316. * @req: Crypto request
  317. * @callback: Completion callback
  318. * @cb_arg: Completion callback arguments
  319. *
  320. * Returns 0 on success, or a negative error code.
  321. */
  322. int nitrox_process_se_request(struct nitrox_device *ndev,
  323. struct se_crypto_request *req,
  324. completion_t callback,
  325. void *cb_arg)
  326. {
  327. struct nitrox_softreq *sr;
  328. dma_addr_t ctx_handle = 0;
  329. int qno, ret = 0;
  330. if (!nitrox_ready(ndev))
  331. return -ENODEV;
  332. sr = kzalloc(sizeof(*sr), req->gfp);
  333. if (!sr)
  334. return -ENOMEM;
  335. sr->ndev = ndev;
  336. sr->flags = req->flags;
  337. sr->gfp = req->gfp;
  338. sr->callback = callback;
  339. sr->cb_arg = cb_arg;
  340. atomic_set(&sr->status, REQ_NOT_POSTED);
  341. sr->resp.orh = req->orh;
  342. sr->resp.completion = req->comp;
  343. ret = softreq_map_iobuf(sr, req);
  344. if (ret) {
  345. kfree(sr);
  346. return ret;
  347. }
  348. /* get the context handle */
  349. if (req->ctx_handle) {
  350. struct ctx_hdr *hdr;
  351. u8 *ctx_ptr;
  352. ctx_ptr = (u8 *)(uintptr_t)req->ctx_handle;
  353. hdr = (struct ctx_hdr *)(ctx_ptr - sizeof(struct ctx_hdr));
  354. ctx_handle = hdr->ctx_dma;
  355. }
  356. /* select the queue */
  357. qno = smp_processor_id() % ndev->nr_queues;
  358. sr->cmdq = &ndev->pkt_inq[qno];
  359. /*
  360. * 64-Byte Instruction Format
  361. *
  362. * ----------------------
  363. * | DPTR0 | 8 bytes
  364. * ----------------------
  365. * | PKT_IN_INSTR_HDR | 8 bytes
  366. * ----------------------
  367. * | PKT_IN_HDR | 16 bytes
  368. * ----------------------
  369. * | SLC_INFO | 16 bytes
  370. * ----------------------
  371. * | Front data | 16 bytes
  372. * ----------------------
  373. */
  374. /* fill the packet instruction */
  375. /* word 0 */
  376. sr->instr.dptr0 = cpu_to_be64(sr->in.sgcomp_dma);
  377. /* word 1 */
  378. sr->instr.ih.value = 0;
  379. sr->instr.ih.s.g = 1;
  380. sr->instr.ih.s.gsz = sr->in.sgmap_cnt;
  381. sr->instr.ih.s.ssz = sr->out.sgmap_cnt;
  382. sr->instr.ih.s.fsz = FDATA_SIZE + sizeof(struct gphdr);
  383. sr->instr.ih.s.tlen = sr->instr.ih.s.fsz + sr->in.total_bytes;
  384. sr->instr.ih.bev = cpu_to_be64(sr->instr.ih.value);
  385. /* word 2 */
  386. sr->instr.irh.value[0] = 0;
  387. sr->instr.irh.s.uddl = MIN_UDD_LEN;
  388. /* context length in 64-bit words */
  389. sr->instr.irh.s.ctxl = (req->ctrl.s.ctxl / 8);
  390. /* offset from solicit base port 256 */
  391. sr->instr.irh.s.destport = SOLICIT_BASE_DPORT + qno;
  392. sr->instr.irh.s.ctxc = req->ctrl.s.ctxc;
  393. sr->instr.irh.s.arg = req->ctrl.s.arg;
  394. sr->instr.irh.s.opcode = req->opcode;
  395. sr->instr.irh.bev[0] = cpu_to_be64(sr->instr.irh.value[0]);
  396. /* word 3 */
  397. sr->instr.irh.s.ctxp = cpu_to_be64(ctx_handle);
  398. /* word 4 */
  399. sr->instr.slc.value[0] = 0;
  400. sr->instr.slc.s.ssz = sr->out.sgmap_cnt;
  401. sr->instr.slc.bev[0] = cpu_to_be64(sr->instr.slc.value[0]);
  402. /* word 5 */
  403. sr->instr.slc.s.rptr = cpu_to_be64(sr->out.sgcomp_dma);
  404. /*
  405. * No conversion for front data,
  406. * It goes into payload
  407. * put GP Header in front data
  408. */
  409. sr->instr.fdata[0] = *((u64 *)&req->gph);
  410. sr->instr.fdata[1] = 0;
  411. ret = nitrox_enqueue_request(sr);
  412. if (ret == -ENOSPC)
  413. goto send_fail;
  414. return ret;
  415. send_fail:
  416. softreq_destroy(sr);
  417. return ret;
  418. }
  419. static inline int cmd_timeout(unsigned long tstamp, unsigned long timeout)
  420. {
  421. return time_after_eq(jiffies, (tstamp + timeout));
  422. }
  423. void backlog_qflush_work(struct work_struct *work)
  424. {
  425. struct nitrox_cmdq *cmdq;
  426. cmdq = container_of(work, struct nitrox_cmdq, backlog_qflush);
  427. post_backlog_cmds(cmdq);
  428. }
  429. static bool sr_completed(struct nitrox_softreq *sr)
  430. {
  431. u64 orh = READ_ONCE(*sr->resp.orh);
  432. unsigned long timeout = jiffies + msecs_to_jiffies(1);
  433. if ((orh != PENDING_SIG) && (orh & 0xff))
  434. return true;
  435. while (READ_ONCE(*sr->resp.completion) == PENDING_SIG) {
  436. if (time_after(jiffies, timeout)) {
  437. pr_err("comp not done\n");
  438. return false;
  439. }
  440. }
  441. return true;
  442. }
  443. /**
  444. * process_response_list - process completed requests
  445. * @cmdq: Command queue structure
  446. *
  447. * Returns the number of responses processed.
  448. */
  449. static void process_response_list(struct nitrox_cmdq *cmdq)
  450. {
  451. struct nitrox_device *ndev = cmdq->ndev;
  452. struct nitrox_softreq *sr;
  453. int req_completed = 0, err = 0, budget;
  454. completion_t callback;
  455. void *cb_arg;
  456. /* check all pending requests */
  457. budget = atomic_read(&cmdq->pending_count);
  458. while (req_completed < budget) {
  459. sr = get_first_response_entry(cmdq);
  460. if (!sr)
  461. break;
  462. if (atomic_read(&sr->status) != REQ_POSTED)
  463. break;
  464. /* check orh and completion bytes updates */
  465. if (!sr_completed(sr)) {
  466. /* request not completed, check for timeout */
  467. if (!cmd_timeout(sr->tstamp, ndev->timeout))
  468. break;
  469. dev_err_ratelimited(DEV(ndev),
  470. "Request timeout, orh 0x%016llx\n",
  471. READ_ONCE(*sr->resp.orh));
  472. }
  473. atomic_dec(&cmdq->pending_count);
  474. atomic64_inc(&ndev->stats.completed);
  475. /* sync with other cpus */
  476. smp_mb__after_atomic();
  477. /* remove from response list */
  478. response_list_del(sr, cmdq);
  479. /* ORH error code */
  480. err = READ_ONCE(*sr->resp.orh) & 0xff;
  481. callback = sr->callback;
  482. cb_arg = sr->cb_arg;
  483. softreq_destroy(sr);
  484. if (callback)
  485. callback(cb_arg, err);
  486. req_completed++;
  487. }
  488. }
  489. /*
  490. * pkt_slc_resp_tasklet - post processing of SE responses
  491. */
  492. void pkt_slc_resp_tasklet(unsigned long data)
  493. {
  494. struct nitrox_q_vector *qvec = (void *)(uintptr_t)(data);
  495. struct nitrox_cmdq *cmdq = qvec->cmdq;
  496. union nps_pkt_slc_cnts slc_cnts;
  497. /* read completion count */
  498. slc_cnts.value = readq(cmdq->compl_cnt_csr_addr);
  499. /* resend the interrupt if more work to do */
  500. slc_cnts.s.resend = 1;
  501. process_response_list(cmdq);
  502. /*
  503. * clear the interrupt with resend bit enabled,
  504. * MSI-X interrupt generates if Completion count > Threshold
  505. */
  506. writeq(slc_cnts.value, cmdq->compl_cnt_csr_addr);
  507. if (atomic_read(&cmdq->backlog_count))
  508. schedule_work(&cmdq->backlog_qflush);
  509. }