nitrox_lib.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/cpumask.h>
  3. #include <linux/dma-mapping.h>
  4. #include <linux/dmapool.h>
  5. #include <linux/delay.h>
  6. #include <linux/gfp.h>
  7. #include <linux/kernel.h>
  8. #include <linux/module.h>
  9. #include <linux/pci_regs.h>
  10. #include <linux/vmalloc.h>
  11. #include <linux/pci.h>
  12. #include "nitrox_dev.h"
  13. #include "nitrox_common.h"
  14. #include "nitrox_req.h"
  15. #include "nitrox_csr.h"
  16. #define CRYPTO_CTX_SIZE 256
  17. /* packet inuput ring alignments */
  18. #define PKTIN_Q_ALIGN_BYTES 16
  19. /* AQM Queue input alignments */
  20. #define AQM_Q_ALIGN_BYTES 32
  21. static int nitrox_cmdq_init(struct nitrox_cmdq *cmdq, int align_bytes)
  22. {
  23. struct nitrox_device *ndev = cmdq->ndev;
  24. cmdq->qsize = (ndev->qlen * cmdq->instr_size) + align_bytes;
  25. cmdq->unalign_base = dma_alloc_coherent(DEV(ndev), cmdq->qsize,
  26. &cmdq->unalign_dma,
  27. GFP_KERNEL);
  28. if (!cmdq->unalign_base)
  29. return -ENOMEM;
  30. cmdq->dma = PTR_ALIGN(cmdq->unalign_dma, align_bytes);
  31. cmdq->base = cmdq->unalign_base + (cmdq->dma - cmdq->unalign_dma);
  32. cmdq->write_idx = 0;
  33. spin_lock_init(&cmdq->cmd_qlock);
  34. spin_lock_init(&cmdq->resp_qlock);
  35. spin_lock_init(&cmdq->backlog_qlock);
  36. INIT_LIST_HEAD(&cmdq->response_head);
  37. INIT_LIST_HEAD(&cmdq->backlog_head);
  38. INIT_WORK(&cmdq->backlog_qflush, backlog_qflush_work);
  39. atomic_set(&cmdq->pending_count, 0);
  40. atomic_set(&cmdq->backlog_count, 0);
  41. return 0;
  42. }
  43. static void nitrox_cmdq_reset(struct nitrox_cmdq *cmdq)
  44. {
  45. cmdq->write_idx = 0;
  46. atomic_set(&cmdq->pending_count, 0);
  47. atomic_set(&cmdq->backlog_count, 0);
  48. }
  49. static void nitrox_cmdq_cleanup(struct nitrox_cmdq *cmdq)
  50. {
  51. struct nitrox_device *ndev;
  52. if (!cmdq)
  53. return;
  54. if (!cmdq->unalign_base)
  55. return;
  56. ndev = cmdq->ndev;
  57. cancel_work_sync(&cmdq->backlog_qflush);
  58. dma_free_coherent(DEV(ndev), cmdq->qsize,
  59. cmdq->unalign_base, cmdq->unalign_dma);
  60. nitrox_cmdq_reset(cmdq);
  61. cmdq->dbell_csr_addr = NULL;
  62. cmdq->compl_cnt_csr_addr = NULL;
  63. cmdq->unalign_base = NULL;
  64. cmdq->base = NULL;
  65. cmdq->unalign_dma = 0;
  66. cmdq->dma = 0;
  67. cmdq->qsize = 0;
  68. cmdq->instr_size = 0;
  69. }
  70. static void nitrox_free_aqm_queues(struct nitrox_device *ndev)
  71. {
  72. int i;
  73. for (i = 0; i < ndev->nr_queues; i++) {
  74. nitrox_cmdq_cleanup(ndev->aqmq[i]);
  75. kfree_sensitive(ndev->aqmq[i]);
  76. ndev->aqmq[i] = NULL;
  77. }
  78. }
  79. static int nitrox_alloc_aqm_queues(struct nitrox_device *ndev)
  80. {
  81. int i, err;
  82. for (i = 0; i < ndev->nr_queues; i++) {
  83. struct nitrox_cmdq *cmdq;
  84. u64 offset;
  85. cmdq = kzalloc_node(sizeof(*cmdq), GFP_KERNEL, ndev->node);
  86. if (!cmdq) {
  87. err = -ENOMEM;
  88. goto aqmq_fail;
  89. }
  90. cmdq->ndev = ndev;
  91. cmdq->qno = i;
  92. cmdq->instr_size = sizeof(struct aqmq_command_s);
  93. /* AQM Queue Doorbell Counter Register Address */
  94. offset = AQMQ_DRBLX(i);
  95. cmdq->dbell_csr_addr = NITROX_CSR_ADDR(ndev, offset);
  96. /* AQM Queue Commands Completed Count Register Address */
  97. offset = AQMQ_CMD_CNTX(i);
  98. cmdq->compl_cnt_csr_addr = NITROX_CSR_ADDR(ndev, offset);
  99. err = nitrox_cmdq_init(cmdq, AQM_Q_ALIGN_BYTES);
  100. if (err) {
  101. kfree_sensitive(cmdq);
  102. goto aqmq_fail;
  103. }
  104. ndev->aqmq[i] = cmdq;
  105. }
  106. return 0;
  107. aqmq_fail:
  108. nitrox_free_aqm_queues(ndev);
  109. return err;
  110. }
  111. static void nitrox_free_pktin_queues(struct nitrox_device *ndev)
  112. {
  113. int i;
  114. for (i = 0; i < ndev->nr_queues; i++) {
  115. struct nitrox_cmdq *cmdq = &ndev->pkt_inq[i];
  116. nitrox_cmdq_cleanup(cmdq);
  117. }
  118. kfree(ndev->pkt_inq);
  119. ndev->pkt_inq = NULL;
  120. }
  121. static int nitrox_alloc_pktin_queues(struct nitrox_device *ndev)
  122. {
  123. int i, err;
  124. ndev->pkt_inq = kcalloc_node(ndev->nr_queues,
  125. sizeof(struct nitrox_cmdq),
  126. GFP_KERNEL, ndev->node);
  127. if (!ndev->pkt_inq)
  128. return -ENOMEM;
  129. for (i = 0; i < ndev->nr_queues; i++) {
  130. struct nitrox_cmdq *cmdq;
  131. u64 offset;
  132. cmdq = &ndev->pkt_inq[i];
  133. cmdq->ndev = ndev;
  134. cmdq->qno = i;
  135. cmdq->instr_size = sizeof(struct nps_pkt_instr);
  136. /* packet input ring doorbell address */
  137. offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(i);
  138. cmdq->dbell_csr_addr = NITROX_CSR_ADDR(ndev, offset);
  139. /* packet solicit port completion count address */
  140. offset = NPS_PKT_SLC_CNTSX(i);
  141. cmdq->compl_cnt_csr_addr = NITROX_CSR_ADDR(ndev, offset);
  142. err = nitrox_cmdq_init(cmdq, PKTIN_Q_ALIGN_BYTES);
  143. if (err)
  144. goto pktq_fail;
  145. }
  146. return 0;
  147. pktq_fail:
  148. nitrox_free_pktin_queues(ndev);
  149. return err;
  150. }
  151. static int create_crypto_dma_pool(struct nitrox_device *ndev)
  152. {
  153. size_t size;
  154. /* Crypto context pool, 16 byte aligned */
  155. size = CRYPTO_CTX_SIZE + sizeof(struct ctx_hdr);
  156. ndev->ctx_pool = dma_pool_create("nitrox-context",
  157. DEV(ndev), size, 16, 0);
  158. if (!ndev->ctx_pool)
  159. return -ENOMEM;
  160. return 0;
  161. }
  162. static void destroy_crypto_dma_pool(struct nitrox_device *ndev)
  163. {
  164. if (!ndev->ctx_pool)
  165. return;
  166. dma_pool_destroy(ndev->ctx_pool);
  167. ndev->ctx_pool = NULL;
  168. }
  169. /*
  170. * crypto_alloc_context - Allocate crypto context from pool
  171. * @ndev: NITROX Device
  172. */
  173. void *crypto_alloc_context(struct nitrox_device *ndev)
  174. {
  175. struct ctx_hdr *ctx;
  176. struct crypto_ctx_hdr *chdr;
  177. void *vaddr;
  178. dma_addr_t dma;
  179. chdr = kmalloc(sizeof(*chdr), GFP_KERNEL);
  180. if (!chdr)
  181. return NULL;
  182. vaddr = dma_pool_zalloc(ndev->ctx_pool, GFP_KERNEL, &dma);
  183. if (!vaddr) {
  184. kfree(chdr);
  185. return NULL;
  186. }
  187. /* fill meta data */
  188. ctx = vaddr;
  189. ctx->pool = ndev->ctx_pool;
  190. ctx->dma = dma;
  191. ctx->ctx_dma = dma + sizeof(struct ctx_hdr);
  192. chdr->pool = ndev->ctx_pool;
  193. chdr->dma = dma;
  194. chdr->vaddr = vaddr;
  195. return chdr;
  196. }
  197. /**
  198. * crypto_free_context - Free crypto context to pool
  199. * @ctx: context to free
  200. */
  201. void crypto_free_context(void *ctx)
  202. {
  203. struct crypto_ctx_hdr *ctxp;
  204. if (!ctx)
  205. return;
  206. ctxp = ctx;
  207. dma_pool_free(ctxp->pool, ctxp->vaddr, ctxp->dma);
  208. kfree(ctxp);
  209. }
  210. /**
  211. * nitrox_common_sw_init - allocate software resources.
  212. * @ndev: NITROX device
  213. *
  214. * Allocates crypto context pools and command queues etc.
  215. *
  216. * Return: 0 on success, or a negative error code on error.
  217. */
  218. int nitrox_common_sw_init(struct nitrox_device *ndev)
  219. {
  220. int err = 0;
  221. /* per device crypto context pool */
  222. err = create_crypto_dma_pool(ndev);
  223. if (err)
  224. return err;
  225. err = nitrox_alloc_pktin_queues(ndev);
  226. if (err)
  227. destroy_crypto_dma_pool(ndev);
  228. err = nitrox_alloc_aqm_queues(ndev);
  229. if (err) {
  230. nitrox_free_pktin_queues(ndev);
  231. destroy_crypto_dma_pool(ndev);
  232. }
  233. return err;
  234. }
  235. /**
  236. * nitrox_common_sw_cleanup - free software resources.
  237. * @ndev: NITROX device
  238. */
  239. void nitrox_common_sw_cleanup(struct nitrox_device *ndev)
  240. {
  241. nitrox_free_aqm_queues(ndev);
  242. nitrox_free_pktin_queues(ndev);
  243. destroy_crypto_dma_pool(ndev);
  244. }