1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2023 Intel Corporation.
3 * All rights reserved.
4 */
5
6 #include "spdk/event.h"
7 #include "spdk/accel.h"
8
9 #define TEST_XFER_SIZE 4096
10 #define INITIAL_PATTERN_0 0
11 #define INITIAL_PATTERN_1 1
12 #define INITIAL_PATTERN_2 2
13 #define FILL_PATTERN_1 255
14 #define FILL_PATTERN_2 111
15 #define IOVCNT 1
16
17 struct test_ctx {
18 char *driver_name;
19 struct spdk_io_channel *ch;
20 char buf1[TEST_XFER_SIZE];
21 char buf1_bck[TEST_XFER_SIZE];
22 char buf2[TEST_XFER_SIZE];
23 char buf2_bck[TEST_XFER_SIZE];
24 struct iovec iov1, iov2, iov1_bck, iov2_bck;
25 };
26
27 static void
test_seq_complete_cb(void * _ctx,int status)28 test_seq_complete_cb(void *_ctx, int status)
29 {
30 struct test_ctx *ctx = _ctx;
31 char expected_buf1[TEST_XFER_SIZE], expected_buf2[TEST_XFER_SIZE];
32 char expected_buf1_bck[TEST_XFER_SIZE], expected_buf2_bck[TEST_XFER_SIZE];
33
34 printf("Running sequence callback\n");
35
36 if (status != 0) {
37 SPDK_ERRLOG("Unexpected status code: %d", status);
38 goto out;
39 }
40
41 memset(expected_buf1, FILL_PATTERN_1, sizeof(expected_buf1));
42 memset(expected_buf2, FILL_PATTERN_2, sizeof(expected_buf2));
43 memset(expected_buf1_bck, 1, sizeof(expected_buf2));
44 memset(expected_buf2_bck, 2, sizeof(expected_buf2));
45
46 if (memcmp(ctx->buf1, expected_buf1, TEST_XFER_SIZE) != 0 ||
47 memcmp(ctx->buf2, expected_buf2, TEST_XFER_SIZE) != 0 ||
48 memcmp(ctx->buf1_bck, expected_buf1_bck, TEST_XFER_SIZE != 0) ||
49 memcmp(ctx->buf2_bck, expected_buf2_bck, TEST_XFER_SIZE != 0)) {
50 SPDK_ERRLOG("Sequence failed: buffers mismatch\n");
51 status = 1;
52 }
53 out:
54 spdk_put_io_channel(ctx->ch);
55 spdk_app_stop(status);
56 }
57
58 static void
start_driver(void * _ctx)59 start_driver(void *_ctx)
60 {
61 int rc = 0, completed = 0;
62 struct test_ctx *ctx = _ctx;
63 struct spdk_accel_sequence *seq = NULL;
64
65 ctx->ch = spdk_accel_get_io_channel();
66 if (ctx->ch == NULL) {
67 SPDK_ERRLOG("Failed to get IO channel\n");
68 spdk_app_stop(1);
69 return;
70 }
71
72 /* Prepare buffers */
73 memset(ctx->buf1, INITIAL_PATTERN_1, TEST_XFER_SIZE);
74 memset(ctx->buf2, INITIAL_PATTERN_2, TEST_XFER_SIZE);
75 memset(ctx->buf1_bck, INITIAL_PATTERN_0, TEST_XFER_SIZE);
76 memset(ctx->buf2_bck, INITIAL_PATTERN_0, TEST_XFER_SIZE);
77
78 ctx->iov1.iov_base = ctx->buf1;
79 ctx->iov1.iov_len = TEST_XFER_SIZE;
80
81 ctx->iov2.iov_base = ctx->buf2;
82 ctx->iov2.iov_len = TEST_XFER_SIZE;
83
84 ctx->iov1_bck.iov_base = ctx->buf1_bck;
85 ctx->iov1_bck.iov_len = TEST_XFER_SIZE;
86
87 ctx->iov2_bck.iov_base = ctx->buf2_bck;
88 ctx->iov2_bck.iov_len = TEST_XFER_SIZE;
89
90 /* Test driver implementation. Test scenario is:
91 * copy buf1 -> buf1_bck
92 * fill buf1 <- FILL_PATTERN_1
93 * copy buf2 -> buf2_bck
94 * fill buf2 <- FILL_PATTERN_2
95 */
96 rc = spdk_accel_append_copy(&seq, ctx->ch, &ctx->iov1_bck, IOVCNT, NULL, NULL,
97 &ctx->iov1, IOVCNT, NULL, NULL,
98 NULL, NULL);
99 if (rc) {
100 SPDK_ERRLOG("ERROR running append copy 1! exiting.\n");
101 goto error;
102 }
103 rc = spdk_accel_append_fill(&seq, ctx->ch, &ctx->buf1, TEST_XFER_SIZE,
104 NULL, NULL, FILL_PATTERN_1,
105 NULL, NULL);
106 if (rc) {
107 SPDK_ERRLOG("ERROR running append fill 1! exiting.\n");
108 goto error;
109 }
110 rc = spdk_accel_append_copy(&seq, ctx->ch, &ctx->iov2_bck, IOVCNT, NULL, NULL,
111 &ctx->iov2, IOVCNT, NULL, NULL,
112 NULL, NULL);
113 if (rc) {
114 SPDK_ERRLOG("ERROR running append copy 2! exiting.\n");
115 goto error;
116 }
117 rc = spdk_accel_append_fill(&seq, ctx->ch, &ctx->buf2, TEST_XFER_SIZE,
118 NULL, NULL, FILL_PATTERN_2,
119 NULL, NULL);
120 if (rc) {
121 SPDK_ERRLOG("ERROR running append fill 2! exiting.\n");
122 goto error;
123 }
124 spdk_accel_sequence_finish(seq, test_seq_complete_cb, ctx);
125 return;
126 error:
127 spdk_accel_sequence_abort(seq);
128 spdk_put_io_channel(ctx->ch);
129 spdk_app_stop(rc);
130 }
131
132 int
main(int argc,char ** argv)133 main(int argc, char **argv)
134 {
135 int rc;
136 struct spdk_app_opts opts = {};
137 struct test_ctx ctx = {};
138
139 spdk_app_opts_init(&opts, sizeof(opts));
140 opts.name = "accel_external_driver";
141 opts.rpc_addr = NULL;
142
143 /*
144 * Parse built-in SPDK command line parameters as well
145 * as our custom one(s).
146 */
147 if ((rc = spdk_app_parse_args(argc, argv, &opts, NULL, NULL, NULL,
148 NULL)) != SPDK_APP_PARSE_ARGS_SUCCESS) {
149 exit(rc);
150 }
151
152 rc = spdk_app_start(&opts, start_driver, &ctx);
153
154 /* Gracefully close out all of the SPDK subsystems. */
155 spdk_app_fini();
156 return rc;
157 }
158