fpga-mgr-test.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * KUnit test for the FPGA Manager
  4. *
  5. * Copyright (C) 2023 Red Hat, Inc.
  6. *
  7. * Author: Marco Pagani <marpagan@redhat.com>
  8. */
  9. #include <kunit/device.h>
  10. #include <kunit/test.h>
  11. #include <linux/fpga/fpga-mgr.h>
  12. #include <linux/module.h>
  13. #include <linux/scatterlist.h>
  14. #include <linux/types.h>
  15. #define HEADER_FILL 'H'
  16. #define IMAGE_FILL 'P'
  17. #define IMAGE_BLOCK 1024
  18. #define HEADER_SIZE IMAGE_BLOCK
  19. #define IMAGE_SIZE (IMAGE_BLOCK * 4)
  20. struct mgr_stats {
  21. bool header_match;
  22. bool image_match;
  23. u32 seq_num;
  24. u32 op_parse_header_seq;
  25. u32 op_write_init_seq;
  26. u32 op_write_seq;
  27. u32 op_write_sg_seq;
  28. u32 op_write_complete_seq;
  29. enum fpga_mgr_states op_parse_header_state;
  30. enum fpga_mgr_states op_write_init_state;
  31. enum fpga_mgr_states op_write_state;
  32. enum fpga_mgr_states op_write_sg_state;
  33. enum fpga_mgr_states op_write_complete_state;
  34. };
  35. struct mgr_ctx {
  36. struct fpga_image_info *img_info;
  37. struct fpga_manager *mgr;
  38. struct device *dev;
  39. struct mgr_stats stats;
  40. };
  41. /*
  42. * Wrappers to avoid cast warnings when passing action functions directly
  43. * to kunit_add_action().
  44. */
  45. KUNIT_DEFINE_ACTION_WRAPPER(sg_free_table_wrapper, sg_free_table,
  46. struct sg_table *);
  47. KUNIT_DEFINE_ACTION_WRAPPER(fpga_image_info_free_wrapper, fpga_image_info_free,
  48. struct fpga_image_info *);
  49. /**
  50. * init_test_buffer() - Allocate and initialize a test image in a buffer.
  51. * @test: KUnit test context object.
  52. * @count: image size in bytes.
  53. *
  54. * Return: pointer to the newly allocated image.
  55. */
  56. static char *init_test_buffer(struct kunit *test, size_t count)
  57. {
  58. char *buf;
  59. KUNIT_ASSERT_GE(test, count, HEADER_SIZE);
  60. buf = kunit_kzalloc(test, count, GFP_KERNEL);
  61. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
  62. memset(buf, HEADER_FILL, HEADER_SIZE);
  63. memset(buf + HEADER_SIZE, IMAGE_FILL, count - HEADER_SIZE);
  64. return buf;
  65. }
  66. /*
  67. * Check the image header. Do not return an error code if the image check fails
  68. * since, in this case, it is a failure of the FPGA manager itself, not this
  69. * op that tests it.
  70. */
  71. static int op_parse_header(struct fpga_manager *mgr, struct fpga_image_info *info,
  72. const char *buf, size_t count)
  73. {
  74. struct mgr_stats *stats = mgr->priv;
  75. size_t i;
  76. stats->op_parse_header_state = mgr->state;
  77. stats->op_parse_header_seq = stats->seq_num++;
  78. /* Set header_size and data_size for later */
  79. info->header_size = HEADER_SIZE;
  80. info->data_size = info->count - HEADER_SIZE;
  81. stats->header_match = true;
  82. for (i = 0; i < info->header_size; i++) {
  83. if (buf[i] != HEADER_FILL) {
  84. stats->header_match = false;
  85. break;
  86. }
  87. }
  88. return 0;
  89. }
  90. static int op_write_init(struct fpga_manager *mgr, struct fpga_image_info *info,
  91. const char *buf, size_t count)
  92. {
  93. struct mgr_stats *stats = mgr->priv;
  94. stats->op_write_init_state = mgr->state;
  95. stats->op_write_init_seq = stats->seq_num++;
  96. return 0;
  97. }
  98. /*
  99. * Check the image data. As with op_parse_header, do not return an error code
  100. * if the image check fails.
  101. */
  102. static int op_write(struct fpga_manager *mgr, const char *buf, size_t count)
  103. {
  104. struct mgr_stats *stats = mgr->priv;
  105. size_t i;
  106. stats->op_write_state = mgr->state;
  107. stats->op_write_seq = stats->seq_num++;
  108. stats->image_match = true;
  109. for (i = 0; i < count; i++) {
  110. if (buf[i] != IMAGE_FILL) {
  111. stats->image_match = false;
  112. break;
  113. }
  114. }
  115. return 0;
  116. }
  117. /*
  118. * Check the image data, but first skip the header since write_sg will get
  119. * the whole image in sg_table. As with op_parse_header, do not return an
  120. * error code if the image check fails.
  121. */
  122. static int op_write_sg(struct fpga_manager *mgr, struct sg_table *sgt)
  123. {
  124. struct mgr_stats *stats = mgr->priv;
  125. struct sg_mapping_iter miter;
  126. char *img;
  127. size_t i;
  128. stats->op_write_sg_state = mgr->state;
  129. stats->op_write_sg_seq = stats->seq_num++;
  130. stats->image_match = true;
  131. sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG);
  132. if (!sg_miter_skip(&miter, HEADER_SIZE)) {
  133. stats->image_match = false;
  134. goto out;
  135. }
  136. while (sg_miter_next(&miter)) {
  137. img = miter.addr;
  138. for (i = 0; i < miter.length; i++) {
  139. if (img[i] != IMAGE_FILL) {
  140. stats->image_match = false;
  141. goto out;
  142. }
  143. }
  144. }
  145. out:
  146. sg_miter_stop(&miter);
  147. return 0;
  148. }
  149. static int op_write_complete(struct fpga_manager *mgr, struct fpga_image_info *info)
  150. {
  151. struct mgr_stats *stats = mgr->priv;
  152. stats->op_write_complete_state = mgr->state;
  153. stats->op_write_complete_seq = stats->seq_num++;
  154. return 0;
  155. }
  156. /*
  157. * Fake FPGA manager that implements all ops required to check the programming
  158. * sequence using a single contiguous buffer and a scatter gather table.
  159. */
  160. static const struct fpga_manager_ops fake_mgr_ops = {
  161. .skip_header = true,
  162. .parse_header = op_parse_header,
  163. .write_init = op_write_init,
  164. .write = op_write,
  165. .write_sg = op_write_sg,
  166. .write_complete = op_write_complete,
  167. };
  168. static void fpga_mgr_test_get(struct kunit *test)
  169. {
  170. struct mgr_ctx *ctx = test->priv;
  171. struct fpga_manager *mgr;
  172. mgr = fpga_mgr_get(ctx->dev);
  173. KUNIT_EXPECT_PTR_EQ(test, mgr, ctx->mgr);
  174. fpga_mgr_put(ctx->mgr);
  175. }
  176. static void fpga_mgr_test_lock(struct kunit *test)
  177. {
  178. struct mgr_ctx *ctx = test->priv;
  179. int ret;
  180. ret = fpga_mgr_lock(ctx->mgr);
  181. KUNIT_EXPECT_EQ(test, ret, 0);
  182. ret = fpga_mgr_lock(ctx->mgr);
  183. KUNIT_EXPECT_EQ(test, ret, -EBUSY);
  184. fpga_mgr_unlock(ctx->mgr);
  185. }
  186. /* Check the programming sequence using an image in a buffer */
  187. static void fpga_mgr_test_img_load_buf(struct kunit *test)
  188. {
  189. struct mgr_ctx *ctx = test->priv;
  190. char *img_buf;
  191. int ret;
  192. img_buf = init_test_buffer(test, IMAGE_SIZE);
  193. ctx->img_info->count = IMAGE_SIZE;
  194. ctx->img_info->buf = img_buf;
  195. ret = fpga_mgr_load(ctx->mgr, ctx->img_info);
  196. KUNIT_EXPECT_EQ(test, ret, 0);
  197. KUNIT_EXPECT_TRUE(test, ctx->stats.header_match);
  198. KUNIT_EXPECT_TRUE(test, ctx->stats.image_match);
  199. KUNIT_EXPECT_EQ(test, ctx->stats.op_parse_header_state, FPGA_MGR_STATE_PARSE_HEADER);
  200. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_state, FPGA_MGR_STATE_WRITE_INIT);
  201. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_state, FPGA_MGR_STATE_WRITE);
  202. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_state, FPGA_MGR_STATE_WRITE_COMPLETE);
  203. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_seq, ctx->stats.op_parse_header_seq + 1);
  204. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_seq, ctx->stats.op_parse_header_seq + 2);
  205. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_seq, ctx->stats.op_parse_header_seq + 3);
  206. }
  207. /* Check the programming sequence using an image in a scatter gather table */
  208. static void fpga_mgr_test_img_load_sgt(struct kunit *test)
  209. {
  210. struct mgr_ctx *ctx = test->priv;
  211. struct sg_table *sgt;
  212. char *img_buf;
  213. int ret;
  214. img_buf = init_test_buffer(test, IMAGE_SIZE);
  215. sgt = kunit_kzalloc(test, sizeof(*sgt), GFP_KERNEL);
  216. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sgt);
  217. ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
  218. KUNIT_ASSERT_EQ(test, ret, 0);
  219. sg_init_one(sgt->sgl, img_buf, IMAGE_SIZE);
  220. ret = kunit_add_action_or_reset(test, sg_free_table_wrapper, sgt);
  221. KUNIT_ASSERT_EQ(test, ret, 0);
  222. ctx->img_info->sgt = sgt;
  223. ret = fpga_mgr_load(ctx->mgr, ctx->img_info);
  224. KUNIT_EXPECT_EQ(test, ret, 0);
  225. KUNIT_EXPECT_TRUE(test, ctx->stats.header_match);
  226. KUNIT_EXPECT_TRUE(test, ctx->stats.image_match);
  227. KUNIT_EXPECT_EQ(test, ctx->stats.op_parse_header_state, FPGA_MGR_STATE_PARSE_HEADER);
  228. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_state, FPGA_MGR_STATE_WRITE_INIT);
  229. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_sg_state, FPGA_MGR_STATE_WRITE);
  230. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_state, FPGA_MGR_STATE_WRITE_COMPLETE);
  231. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_seq, ctx->stats.op_parse_header_seq + 1);
  232. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_sg_seq, ctx->stats.op_parse_header_seq + 2);
  233. KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_seq, ctx->stats.op_parse_header_seq + 3);
  234. }
  235. static int fpga_mgr_test_init(struct kunit *test)
  236. {
  237. struct mgr_ctx *ctx;
  238. int ret;
  239. ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
  240. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
  241. ctx->dev = kunit_device_register(test, "fpga-manager-test-dev");
  242. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->dev);
  243. ctx->mgr = devm_fpga_mgr_register(ctx->dev, "Fake FPGA Manager", &fake_mgr_ops,
  244. &ctx->stats);
  245. KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->mgr));
  246. ctx->img_info = fpga_image_info_alloc(ctx->dev);
  247. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->img_info);
  248. ret = kunit_add_action_or_reset(test, fpga_image_info_free_wrapper, ctx->img_info);
  249. KUNIT_ASSERT_EQ(test, ret, 0);
  250. test->priv = ctx;
  251. return 0;
  252. }
  253. static struct kunit_case fpga_mgr_test_cases[] = {
  254. KUNIT_CASE(fpga_mgr_test_get),
  255. KUNIT_CASE(fpga_mgr_test_lock),
  256. KUNIT_CASE(fpga_mgr_test_img_load_buf),
  257. KUNIT_CASE(fpga_mgr_test_img_load_sgt),
  258. {}
  259. };
  260. static struct kunit_suite fpga_mgr_suite = {
  261. .name = "fpga_mgr",
  262. .init = fpga_mgr_test_init,
  263. .test_cases = fpga_mgr_test_cases,
  264. };
  265. kunit_test_suite(fpga_mgr_suite);
  266. MODULE_LICENSE("GPL");