caamrng.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * caam - Freescale FSL CAAM support for hw_random
  4. *
  5. * Copyright 2011 Freescale Semiconductor, Inc.
  6. * Copyright 2018-2019, 2023 NXP
  7. *
  8. * Based on caamalg.c crypto API driver.
  9. *
  10. */
  11. #include <linux/hw_random.h>
  12. #include <linux/completion.h>
  13. #include <linux/atomic.h>
  14. #include <linux/dma-mapping.h>
  15. #include <linux/kernel.h>
  16. #include <linux/kfifo.h>
  17. #include "compat.h"
  18. #include "regs.h"
  19. #include "intern.h"
  20. #include "desc_constr.h"
  21. #include "jr.h"
  22. #include "error.h"
  23. #define CAAM_RNG_MAX_FIFO_STORE_SIZE 16
  24. /*
  25. * Length of used descriptors, see caam_init_desc()
  26. */
  27. #define CAAM_RNG_DESC_LEN (CAAM_CMD_SZ + \
  28. CAAM_CMD_SZ + \
  29. CAAM_CMD_SZ + CAAM_PTR_SZ_MAX)
  30. /* rng per-device context */
  31. struct caam_rng_ctx {
  32. struct hwrng rng;
  33. struct device *jrdev;
  34. struct device *ctrldev;
  35. void *desc_async;
  36. void *desc_sync;
  37. struct work_struct worker;
  38. struct kfifo fifo;
  39. };
  40. struct caam_rng_job_ctx {
  41. struct completion *done;
  42. int *err;
  43. };
  44. static struct caam_rng_ctx *to_caam_rng_ctx(struct hwrng *r)
  45. {
  46. return (struct caam_rng_ctx *)r->priv;
  47. }
  48. static void caam_rng_done(struct device *jrdev, u32 *desc, u32 err,
  49. void *context)
  50. {
  51. struct caam_rng_job_ctx *jctx = context;
  52. if (err)
  53. *jctx->err = caam_jr_strstatus(jrdev, err);
  54. complete(jctx->done);
  55. }
  56. static u32 *caam_init_desc(u32 *desc, dma_addr_t dst_dma)
  57. {
  58. init_job_desc(desc, 0); /* + 1 cmd_sz */
  59. /* Generate random bytes: + 1 cmd_sz */
  60. append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG |
  61. OP_ALG_PR_ON);
  62. /* Store bytes: + 1 cmd_sz + caam_ptr_sz */
  63. append_fifo_store(desc, dst_dma,
  64. CAAM_RNG_MAX_FIFO_STORE_SIZE, FIFOST_TYPE_RNGSTORE);
  65. print_hex_dump_debug("rng job desc@: ", DUMP_PREFIX_ADDRESS,
  66. 16, 4, desc, desc_bytes(desc), 1);
  67. return desc;
  68. }
  69. static int caam_rng_read_one(struct device *jrdev,
  70. void *dst, int len,
  71. void *desc,
  72. struct completion *done)
  73. {
  74. dma_addr_t dst_dma;
  75. int err, ret = 0;
  76. struct caam_rng_job_ctx jctx = {
  77. .done = done,
  78. .err = &ret,
  79. };
  80. len = CAAM_RNG_MAX_FIFO_STORE_SIZE;
  81. dst_dma = dma_map_single(jrdev, dst, len, DMA_FROM_DEVICE);
  82. if (dma_mapping_error(jrdev, dst_dma)) {
  83. dev_err(jrdev, "unable to map destination memory\n");
  84. return -ENOMEM;
  85. }
  86. init_completion(done);
  87. err = caam_jr_enqueue(jrdev,
  88. caam_init_desc(desc, dst_dma),
  89. caam_rng_done, &jctx);
  90. if (err == -EINPROGRESS) {
  91. wait_for_completion(done);
  92. err = 0;
  93. }
  94. dma_unmap_single(jrdev, dst_dma, len, DMA_FROM_DEVICE);
  95. return err ?: (ret ?: len);
  96. }
  97. static void caam_rng_fill_async(struct caam_rng_ctx *ctx)
  98. {
  99. struct scatterlist sg[1];
  100. struct completion done;
  101. int len, nents;
  102. sg_init_table(sg, ARRAY_SIZE(sg));
  103. nents = kfifo_dma_in_prepare(&ctx->fifo, sg, ARRAY_SIZE(sg),
  104. CAAM_RNG_MAX_FIFO_STORE_SIZE);
  105. if (!nents)
  106. return;
  107. len = caam_rng_read_one(ctx->jrdev, sg_virt(&sg[0]),
  108. sg[0].length,
  109. ctx->desc_async,
  110. &done);
  111. if (len < 0)
  112. return;
  113. kfifo_dma_in_finish(&ctx->fifo, len);
  114. }
  115. static void caam_rng_worker(struct work_struct *work)
  116. {
  117. struct caam_rng_ctx *ctx = container_of(work, struct caam_rng_ctx,
  118. worker);
  119. caam_rng_fill_async(ctx);
  120. }
  121. static int caam_read(struct hwrng *rng, void *dst, size_t max, bool wait)
  122. {
  123. struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng);
  124. int out;
  125. if (wait) {
  126. struct completion done;
  127. return caam_rng_read_one(ctx->jrdev, dst, max,
  128. ctx->desc_sync, &done);
  129. }
  130. out = kfifo_out(&ctx->fifo, dst, max);
  131. if (kfifo_is_empty(&ctx->fifo))
  132. schedule_work(&ctx->worker);
  133. return out;
  134. }
  135. static void caam_cleanup(struct hwrng *rng)
  136. {
  137. struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng);
  138. flush_work(&ctx->worker);
  139. caam_jr_free(ctx->jrdev);
  140. kfifo_free(&ctx->fifo);
  141. }
  142. #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST
  143. static inline void test_len(struct hwrng *rng, size_t len, bool wait)
  144. {
  145. u8 *buf;
  146. int read_len;
  147. struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng);
  148. struct device *dev = ctx->ctrldev;
  149. buf = kcalloc(CAAM_RNG_MAX_FIFO_STORE_SIZE, sizeof(u8), GFP_KERNEL);
  150. while (len > 0) {
  151. read_len = rng->read(rng, buf, len, wait);
  152. if (read_len < 0 || (read_len == 0 && wait)) {
  153. dev_err(dev, "RNG Read FAILED received %d bytes\n",
  154. read_len);
  155. kfree(buf);
  156. return;
  157. }
  158. print_hex_dump_debug("random bytes@: ",
  159. DUMP_PREFIX_ADDRESS, 16, 4,
  160. buf, read_len, 1);
  161. len = len - read_len;
  162. }
  163. kfree(buf);
  164. }
  165. static inline void test_mode_once(struct hwrng *rng, bool wait)
  166. {
  167. test_len(rng, 32, wait);
  168. test_len(rng, 64, wait);
  169. test_len(rng, 128, wait);
  170. }
  171. static void self_test(struct hwrng *rng)
  172. {
  173. pr_info("Executing RNG SELF-TEST with wait\n");
  174. test_mode_once(rng, true);
  175. }
  176. #endif
  177. static int caam_init(struct hwrng *rng)
  178. {
  179. struct caam_rng_ctx *ctx = to_caam_rng_ctx(rng);
  180. int err;
  181. ctx->desc_sync = devm_kzalloc(ctx->ctrldev, CAAM_RNG_DESC_LEN,
  182. GFP_KERNEL);
  183. if (!ctx->desc_sync)
  184. return -ENOMEM;
  185. ctx->desc_async = devm_kzalloc(ctx->ctrldev, CAAM_RNG_DESC_LEN,
  186. GFP_KERNEL);
  187. if (!ctx->desc_async)
  188. return -ENOMEM;
  189. if (kfifo_alloc(&ctx->fifo, ALIGN(CAAM_RNG_MAX_FIFO_STORE_SIZE,
  190. dma_get_cache_alignment()),
  191. GFP_KERNEL))
  192. return -ENOMEM;
  193. INIT_WORK(&ctx->worker, caam_rng_worker);
  194. ctx->jrdev = caam_jr_alloc();
  195. err = PTR_ERR_OR_ZERO(ctx->jrdev);
  196. if (err) {
  197. kfifo_free(&ctx->fifo);
  198. pr_err("Job Ring Device allocation for transform failed\n");
  199. return err;
  200. }
  201. /*
  202. * Fill async buffer to have early randomness data for
  203. * hw_random
  204. */
  205. caam_rng_fill_async(ctx);
  206. return 0;
  207. }
  208. int caam_rng_init(struct device *ctrldev);
  209. void caam_rng_exit(struct device *ctrldev)
  210. {
  211. devres_release_group(ctrldev, caam_rng_init);
  212. }
  213. int caam_rng_init(struct device *ctrldev)
  214. {
  215. struct caam_rng_ctx *ctx;
  216. u32 rng_inst;
  217. struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
  218. int ret;
  219. /* Check for an instantiated RNG before registration */
  220. if (priv->era < 10)
  221. rng_inst = (rd_reg32(&priv->jr[0]->perfmon.cha_num_ls) &
  222. CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT;
  223. else
  224. rng_inst = rd_reg32(&priv->jr[0]->vreg.rng) & CHA_VER_NUM_MASK;
  225. if (!rng_inst)
  226. return 0;
  227. if (!devres_open_group(ctrldev, caam_rng_init, GFP_KERNEL))
  228. return -ENOMEM;
  229. ctx = devm_kzalloc(ctrldev, sizeof(*ctx), GFP_KERNEL);
  230. if (!ctx)
  231. return -ENOMEM;
  232. ctx->ctrldev = ctrldev;
  233. ctx->rng.name = "rng-caam";
  234. ctx->rng.init = caam_init;
  235. ctx->rng.cleanup = caam_cleanup;
  236. ctx->rng.read = caam_read;
  237. ctx->rng.priv = (unsigned long)ctx;
  238. dev_info(ctrldev, "registering rng-caam\n");
  239. ret = devm_hwrng_register(ctrldev, &ctx->rng);
  240. if (ret) {
  241. caam_rng_exit(ctrldev);
  242. return ret;
  243. }
  244. #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST
  245. self_test(&ctx->rng);
  246. #endif
  247. devres_close_group(ctrldev, caam_rng_init);
  248. return 0;
  249. }