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 FILL_PATTERN 255
11
12 enum test_state {
13 TEST_STATE_FILL,
14 TEST_STATE_COPY,
15 TEST_STATE_COMPARE,
16 TEST_STATE_WAIT_COMPLETION,
17 TEST_STATE_DONE
18 };
19
20 struct test_ctx {
21 enum test_state state;
22 int status;
23 char buf1[TEST_XFER_SIZE];
24 char buf2[TEST_XFER_SIZE];
25 struct spdk_io_channel *ch;
26 };
27
28 static void
test_ctx_fail(struct test_ctx * ctx)29 test_ctx_fail(struct test_ctx *ctx)
30 {
31 ctx->status = 1;
32 ctx->state = TEST_STATE_DONE;
33 }
34
35 static void process_accel(void *);
36
37 static void
fill_cb(void * arg,int status)38 fill_cb(void *arg, int status)
39 {
40 struct test_ctx *ctx = arg;
41 char expected[TEST_XFER_SIZE];
42
43 printf("Running fill callback\n");
44 if (status != 0) {
45 test_ctx_fail(ctx);
46 goto out;
47 }
48
49 memset(expected, FILL_PATTERN, sizeof(expected));
50 if (memcmp(ctx->buf1, expected, TEST_XFER_SIZE) != 0) {
51 SPDK_ERRLOG("Fill failed: buffer mismatch\n");
52 test_ctx_fail(ctx);
53 goto out;
54 }
55
56 ctx->state = TEST_STATE_COPY;
57 out:
58 process_accel(ctx);
59 }
60
61 static void
copy_cb(void * arg,int status)62 copy_cb(void *arg, int status)
63 {
64 struct test_ctx *ctx = arg;
65
66 printf("Running copy callback\n");
67 if (status != 0) {
68 test_ctx_fail(ctx);
69 goto out;
70 }
71 if (memcmp(ctx->buf1, ctx->buf2, TEST_XFER_SIZE) != 0) {
72 SPDK_ERRLOG("Copy failed: buffer mismatch\n");
73 test_ctx_fail(ctx);
74 goto out;
75 }
76
77 ctx->state = TEST_STATE_COMPARE;
78 out:
79 process_accel(ctx);
80 }
81
82 static void
compare_cb(void * arg,int status)83 compare_cb(void *arg, int status)
84 {
85 struct test_ctx *ctx = arg;
86
87 printf("Running compare callback\n");
88 if (status != 0) {
89 test_ctx_fail(ctx);
90 goto out;
91 }
92 if (memcmp(ctx->buf1, ctx->buf2, TEST_XFER_SIZE) != 0) {
93 SPDK_ERRLOG("Compare failed: buffer mismatch\n");
94 test_ctx_fail(ctx);
95 goto out;
96 }
97
98 ctx->state = TEST_STATE_DONE;
99 out:
100 process_accel(ctx);
101 }
102
103 static void
process_accel(void * _ctx)104 process_accel(void *_ctx)
105 {
106 int rc;
107 struct test_ctx *ctx = _ctx;
108 enum test_state prev_state;
109
110 do {
111 prev_state = ctx->state;
112
113 switch (ctx->state) {
114 case TEST_STATE_FILL:
115 memset(ctx->buf1, 0, sizeof(ctx->buf1));
116 memset(ctx->buf2, 0, sizeof(ctx->buf2));
117 ctx->state = TEST_STATE_WAIT_COMPLETION;
118 /* Submit fill command */
119 rc = spdk_accel_submit_fill(ctx->ch, ctx->buf1, FILL_PATTERN,
120 TEST_XFER_SIZE, fill_cb, ctx);
121 if (rc) {
122 SPDK_ERRLOG("ERROR running submit fill! exiting.\n");
123 test_ctx_fail(ctx);
124 }
125 break;
126 case TEST_STATE_COPY:
127 ctx->state = TEST_STATE_WAIT_COMPLETION;
128 /* Submit copy command */
129 rc = spdk_accel_submit_copy(ctx->ch, ctx->buf1, ctx->buf2,
130 TEST_XFER_SIZE, copy_cb, ctx);
131 if (rc) {
132 SPDK_ERRLOG("ERROR running submit copy! exiting.\n");
133 test_ctx_fail(ctx);
134 }
135 break;
136 case TEST_STATE_COMPARE:
137 ctx->state = TEST_STATE_WAIT_COMPLETION;
138 /* Submit compare command */
139 rc = spdk_accel_submit_compare(ctx->ch, ctx->buf1, ctx->buf2,
140 TEST_XFER_SIZE, compare_cb, ctx);
141 if (rc) {
142 SPDK_ERRLOG("ERROR running submit compare! exiting.\n");
143 test_ctx_fail(ctx);
144 }
145 break;
146 case TEST_STATE_WAIT_COMPLETION:
147 break;
148 case TEST_STATE_DONE:
149 spdk_put_io_channel(ctx->ch);
150 spdk_app_stop(ctx->status);
151 break;
152 }
153 } while (ctx->state != prev_state);
154 }
155
156 static void
start_accel(void * _ctx)157 start_accel(void *_ctx)
158 {
159 struct test_ctx *ctx = _ctx;
160
161 ctx->ch = spdk_accel_get_io_channel();
162 if (ctx->ch == NULL) {
163 SPDK_ERRLOG("Failed to get IO channel\n");
164 spdk_app_stop(1);
165 return;
166 }
167
168 process_accel(ctx);
169 }
170
171 int
main(int argc,char ** argv)172 main(int argc, char **argv)
173 {
174 int rc;
175 struct spdk_app_opts opts = {};
176 struct test_ctx ctx = {.state = TEST_STATE_FILL, .status = 0};
177
178 spdk_app_opts_init(&opts, sizeof(opts));
179 opts.name = "accel_external_module";
180 opts.rpc_addr = NULL;
181
182 /*
183 * Parse built-in SPDK command line parameters as well
184 * as our custom one(s).
185 */
186 if ((rc = spdk_app_parse_args(argc, argv, &opts, NULL, NULL, NULL,
187 NULL)) != SPDK_APP_PARSE_ARGS_SUCCESS) {
188 exit(rc);
189 }
190
191 rc = spdk_app_start(&opts, start_accel, &ctx);
192
193 spdk_app_fini();
194 return rc;
195 }
196