Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2020 Intel Corporation.
3 : : * Copyright (c) 2022, 2023 NVIDIA CORPORATION & AFFILIATES.
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : :
9 : : #include "spdk/accel_module.h"
10 : :
11 : : #include "accel_internal.h"
12 : :
13 : : #include "spdk/dma.h"
14 : : #include "spdk/env.h"
15 : : #include "spdk/likely.h"
16 : : #include "spdk/log.h"
17 : : #include "spdk/thread.h"
18 : : #include "spdk/json.h"
19 : : #include "spdk/crc32.h"
20 : : #include "spdk/util.h"
21 : : #include "spdk/hexlify.h"
22 : : #include "spdk/string.h"
23 : :
24 : : /* Accelerator Framework: The following provides a top level
25 : : * generic API for the accelerator functions defined here. Modules,
26 : : * such as the one in /module/accel/ioat, supply the implementation
27 : : * with the exception of the pure software implementation contained
28 : : * later in this file.
29 : : */
30 : :
31 : : #define ALIGN_4K 0x1000
32 : : #define MAX_TASKS_PER_CHANNEL 0x800
33 : : #define ACCEL_SMALL_CACHE_SIZE 128
34 : : #define ACCEL_LARGE_CACHE_SIZE 16
35 : : /* Set MSB, so we don't return NULL pointers as buffers */
36 : : #define ACCEL_BUFFER_BASE ((void *)(1ull << 63))
37 : : #define ACCEL_BUFFER_OFFSET_MASK ((uintptr_t)ACCEL_BUFFER_BASE - 1)
38 : :
39 : : #define ACCEL_CRYPTO_TWEAK_MODE_DEFAULT SPDK_ACCEL_CRYPTO_TWEAK_MODE_SIMPLE_LBA
40 : :
41 : : struct accel_module {
42 : : struct spdk_accel_module_if *module;
43 : : bool supports_memory_domains;
44 : : };
45 : :
46 : : /* Largest context size for all accel modules */
47 : : static size_t g_max_accel_module_size = sizeof(struct spdk_accel_task);
48 : :
49 : : static struct spdk_accel_module_if *g_accel_module = NULL;
50 : : static spdk_accel_fini_cb g_fini_cb_fn = NULL;
51 : : static void *g_fini_cb_arg = NULL;
52 : : static bool g_modules_started = false;
53 : : static struct spdk_memory_domain *g_accel_domain;
54 : :
55 : : /* Global list of registered accelerator modules */
56 : : static TAILQ_HEAD(, spdk_accel_module_if) spdk_accel_module_list =
57 : : TAILQ_HEAD_INITIALIZER(spdk_accel_module_list);
58 : :
59 : : /* Crypto keyring */
60 : : static TAILQ_HEAD(, spdk_accel_crypto_key) g_keyring = TAILQ_HEAD_INITIALIZER(g_keyring);
61 : : static struct spdk_spinlock g_keyring_spin;
62 : :
63 : : /* Global array mapping capabilities to modules */
64 : : static struct accel_module g_modules_opc[SPDK_ACCEL_OPC_LAST] = {};
65 : : static char *g_modules_opc_override[SPDK_ACCEL_OPC_LAST] = {};
66 : : TAILQ_HEAD(, spdk_accel_driver) g_accel_drivers = TAILQ_HEAD_INITIALIZER(g_accel_drivers);
67 : : static struct spdk_accel_driver *g_accel_driver;
68 : : static struct spdk_accel_opts g_opts = {
69 : : .small_cache_size = ACCEL_SMALL_CACHE_SIZE,
70 : : .large_cache_size = ACCEL_LARGE_CACHE_SIZE,
71 : : .task_count = MAX_TASKS_PER_CHANNEL,
72 : : .sequence_count = MAX_TASKS_PER_CHANNEL,
73 : : .buf_count = MAX_TASKS_PER_CHANNEL,
74 : : };
75 : : static struct accel_stats g_stats;
76 : : static struct spdk_spinlock g_stats_lock;
77 : :
78 : : static const char *g_opcode_strings[SPDK_ACCEL_OPC_LAST] = {
79 : : "copy", "fill", "dualcast", "compare", "crc32c", "copy_crc32c",
80 : : "compress", "decompress", "encrypt", "decrypt", "xor",
81 : : "dif_verify", "dif_generate", "dif_generate_copy"
82 : : };
83 : :
84 : : enum accel_sequence_state {
85 : : ACCEL_SEQUENCE_STATE_INIT,
86 : : ACCEL_SEQUENCE_STATE_CHECK_VIRTBUF,
87 : : ACCEL_SEQUENCE_STATE_AWAIT_VIRTBUF,
88 : : ACCEL_SEQUENCE_STATE_CHECK_BOUNCEBUF,
89 : : ACCEL_SEQUENCE_STATE_AWAIT_BOUNCEBUF,
90 : : ACCEL_SEQUENCE_STATE_PULL_DATA,
91 : : ACCEL_SEQUENCE_STATE_AWAIT_PULL_DATA,
92 : : ACCEL_SEQUENCE_STATE_EXEC_TASK,
93 : : ACCEL_SEQUENCE_STATE_AWAIT_TASK,
94 : : ACCEL_SEQUENCE_STATE_COMPLETE_TASK,
95 : : ACCEL_SEQUENCE_STATE_NEXT_TASK,
96 : : ACCEL_SEQUENCE_STATE_PUSH_DATA,
97 : : ACCEL_SEQUENCE_STATE_AWAIT_PUSH_DATA,
98 : : ACCEL_SEQUENCE_STATE_DRIVER_EXEC_TASKS,
99 : : ACCEL_SEQUENCE_STATE_DRIVER_AWAIT_TASKS,
100 : : ACCEL_SEQUENCE_STATE_DRIVER_COMPLETE_TASKS,
101 : : ACCEL_SEQUENCE_STATE_ERROR,
102 : : ACCEL_SEQUENCE_STATE_MAX,
103 : : };
104 : :
105 : : static const char *g_seq_states[]
106 : : __attribute__((unused)) = {
107 : : [ACCEL_SEQUENCE_STATE_INIT] = "init",
108 : : [ACCEL_SEQUENCE_STATE_CHECK_VIRTBUF] = "check-virtbuf",
109 : : [ACCEL_SEQUENCE_STATE_AWAIT_VIRTBUF] = "await-virtbuf",
110 : : [ACCEL_SEQUENCE_STATE_CHECK_BOUNCEBUF] = "check-bouncebuf",
111 : : [ACCEL_SEQUENCE_STATE_AWAIT_BOUNCEBUF] = "await-bouncebuf",
112 : : [ACCEL_SEQUENCE_STATE_PULL_DATA] = "pull-data",
113 : : [ACCEL_SEQUENCE_STATE_AWAIT_PULL_DATA] = "await-pull-data",
114 : : [ACCEL_SEQUENCE_STATE_EXEC_TASK] = "exec-task",
115 : : [ACCEL_SEQUENCE_STATE_AWAIT_TASK] = "await-task",
116 : : [ACCEL_SEQUENCE_STATE_COMPLETE_TASK] = "complete-task",
117 : : [ACCEL_SEQUENCE_STATE_NEXT_TASK] = "next-task",
118 : : [ACCEL_SEQUENCE_STATE_PUSH_DATA] = "push-data",
119 : : [ACCEL_SEQUENCE_STATE_AWAIT_PUSH_DATA] = "await-push-data",
120 : : [ACCEL_SEQUENCE_STATE_DRIVER_EXEC_TASKS] = "driver-exec-tasks",
121 : : [ACCEL_SEQUENCE_STATE_DRIVER_AWAIT_TASKS] = "driver-await-tasks",
122 : : [ACCEL_SEQUENCE_STATE_DRIVER_COMPLETE_TASKS] = "driver-complete-tasks",
123 : : [ACCEL_SEQUENCE_STATE_ERROR] = "error",
124 : : [ACCEL_SEQUENCE_STATE_MAX] = "",
125 : : };
126 : :
127 : : #define ACCEL_SEQUENCE_STATE_STRING(s) \
128 : : (((s) >= ACCEL_SEQUENCE_STATE_INIT && (s) < ACCEL_SEQUENCE_STATE_MAX) \
129 : : ? g_seq_states[s] : "unknown")
130 : :
131 : : struct accel_buffer {
132 : : struct spdk_accel_sequence *seq;
133 : : void *buf;
134 : : uint64_t len;
135 : : struct spdk_iobuf_entry iobuf;
136 : : spdk_accel_sequence_get_buf_cb cb_fn;
137 : : void *cb_ctx;
138 : : SLIST_ENTRY(accel_buffer) link;
139 : : };
140 : :
141 : : struct accel_io_channel {
142 : : struct spdk_io_channel *module_ch[SPDK_ACCEL_OPC_LAST];
143 : : struct spdk_io_channel *driver_channel;
144 : : void *task_pool_base;
145 : : struct spdk_accel_sequence *seq_pool_base;
146 : : struct accel_buffer *buf_pool_base;
147 : : struct spdk_accel_task_aux_data *task_aux_data_base;
148 : : STAILQ_HEAD(, spdk_accel_task) task_pool;
149 : : SLIST_HEAD(, spdk_accel_task_aux_data) task_aux_data_pool;
150 : : SLIST_HEAD(, spdk_accel_sequence) seq_pool;
151 : : SLIST_HEAD(, accel_buffer) buf_pool;
152 : : struct spdk_iobuf_channel iobuf;
153 : : struct accel_stats stats;
154 : : };
155 : :
156 : : TAILQ_HEAD(accel_sequence_tasks, spdk_accel_task);
157 : :
158 : : struct spdk_accel_sequence {
159 : : struct accel_io_channel *ch;
160 : : struct accel_sequence_tasks tasks;
161 : : SLIST_HEAD(, accel_buffer) bounce_bufs;
162 : : int status;
163 : : /* state uses enum accel_sequence_state */
164 : : uint8_t state;
165 : : bool in_process_sequence;
166 : : spdk_accel_completion_cb cb_fn;
167 : : void *cb_arg;
168 : : SLIST_ENTRY(spdk_accel_sequence) link;
169 : : };
170 : : SPDK_STATIC_ASSERT(sizeof(struct spdk_accel_sequence) == 64, "invalid size");
171 : :
172 : : #define accel_update_stats(ch, event, v) \
173 : : do { \
174 : : (ch)->stats.event += (v); \
175 : : } while (0)
176 : :
177 : : #define accel_update_task_stats(ch, task, event, v) \
178 : : accel_update_stats(ch, operations[(task)->op_code].event, v)
179 : :
180 : : static inline void accel_sequence_task_cb(void *cb_arg, int status);
181 : :
182 : : static inline void
183 : 718730942 : accel_sequence_set_state(struct spdk_accel_sequence *seq, enum accel_sequence_state state)
184 : : {
185 [ - + - + : 718730942 : SPDK_DEBUGLOG(accel, "seq=%p, setting state: %s -> %s\n", seq,
- - - - ]
186 : : ACCEL_SEQUENCE_STATE_STRING(seq->state), ACCEL_SEQUENCE_STATE_STRING(state));
187 [ - + - - ]: 718730942 : assert(seq->state != ACCEL_SEQUENCE_STATE_ERROR || state == ACCEL_SEQUENCE_STATE_ERROR);
188 : 718730942 : seq->state = state;
189 : 718730942 : }
190 : :
191 : : static void
192 : 54 : accel_sequence_set_fail(struct spdk_accel_sequence *seq, int status)
193 : : {
194 : 54 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_ERROR);
195 [ - + ]: 54 : assert(status != 0);
196 : 54 : seq->status = status;
197 : 54 : }
198 : :
199 : : int
200 : 1726 : spdk_accel_get_opc_module_name(enum spdk_accel_opcode opcode, const char **module_name)
201 : : {
202 [ - + ]: 1726 : if (opcode >= SPDK_ACCEL_OPC_LAST) {
203 : : /* invalid opcode */
204 : 0 : return -EINVAL;
205 : : }
206 : :
207 [ + - ]: 1726 : if (g_modules_opc[opcode].module) {
208 : 1726 : *module_name = g_modules_opc[opcode].module->name;
209 : : } else {
210 : 0 : return -ENOENT;
211 : : }
212 : :
213 : 1726 : return 0;
214 : : }
215 : :
216 : : void
217 : 0 : _accel_for_each_module(struct module_info *info, _accel_for_each_module_fn fn)
218 : : {
219 : : struct spdk_accel_module_if *accel_module;
220 : : enum spdk_accel_opcode opcode;
221 : 0 : int j = 0;
222 : :
223 [ # # ]: 0 : TAILQ_FOREACH(accel_module, &spdk_accel_module_list, tailq) {
224 [ # # ]: 0 : for (opcode = 0; opcode < SPDK_ACCEL_OPC_LAST; opcode++) {
225 [ # # ]: 0 : if (accel_module->supports_opcode(opcode)) {
226 : 0 : info->ops[j] = opcode;
227 : 0 : j++;
228 : : }
229 : : }
230 : 0 : info->name = accel_module->name;
231 : 0 : info->num_ops = j;
232 : 0 : fn(info);
233 : 0 : j = 0;
234 : : }
235 : 0 : }
236 : :
237 : : const char *
238 : 1344 : spdk_accel_get_opcode_name(enum spdk_accel_opcode opcode)
239 : : {
240 [ + - ]: 1344 : if (opcode < SPDK_ACCEL_OPC_LAST) {
241 : 1344 : return g_opcode_strings[opcode];
242 : : }
243 : :
244 : 0 : return NULL;
245 : : }
246 : :
247 : : int
248 : 91 : spdk_accel_assign_opc(enum spdk_accel_opcode opcode, const char *name)
249 : : {
250 : : char *copy;
251 : :
252 [ - + - + ]: 91 : if (g_modules_started == true) {
253 : : /* we don't allow re-assignment once things have started */
254 : 0 : return -EINVAL;
255 : : }
256 : :
257 [ - + ]: 91 : if (opcode >= SPDK_ACCEL_OPC_LAST) {
258 : : /* invalid opcode */
259 : 0 : return -EINVAL;
260 : : }
261 : :
262 [ - + ]: 91 : copy = strdup(name);
263 [ - + ]: 91 : if (copy == NULL) {
264 : 0 : return -ENOMEM;
265 : : }
266 : :
267 : : /* module selection will be validated after the framework starts. */
268 : 91 : free(g_modules_opc_override[opcode]);
269 : 91 : g_modules_opc_override[opcode] = copy;
270 : :
271 : 91 : return 0;
272 : : }
273 : :
274 : : void
275 : 350478760 : spdk_accel_task_complete(struct spdk_accel_task *accel_task, int status)
276 : : {
277 : 350478760 : struct accel_io_channel *accel_ch = accel_task->accel_ch;
278 : : spdk_accel_completion_cb cb_fn;
279 : : void *cb_arg;
280 : :
281 : 350478760 : accel_update_task_stats(accel_ch, accel_task, executed, 1);
282 : 350478760 : accel_update_task_stats(accel_ch, accel_task, num_bytes, accel_task->nbytes);
283 [ + + ]: 350478760 : if (spdk_unlikely(status != 0)) {
284 : 144 : accel_update_task_stats(accel_ch, accel_task, failed, 1);
285 : : }
286 : :
287 [ + + ]: 350478760 : if (accel_task->seq) {
288 : 102329955 : accel_sequence_task_cb(accel_task->seq, status);
289 : 102329955 : return;
290 : : }
291 : :
292 : 248148795 : cb_fn = accel_task->cb_fn;
293 : 248148795 : cb_arg = accel_task->cb_arg;
294 : :
295 [ + + + + ]: 248148795 : if (accel_task->has_aux) {
296 : 167600837 : SLIST_INSERT_HEAD(&accel_ch->task_aux_data_pool, accel_task->aux, link);
297 : 167600837 : accel_task->aux = NULL;
298 : 167600837 : accel_task->has_aux = false;
299 : : }
300 : :
301 : : /* We should put the accel_task into the list firstly in order to avoid
302 : : * the accel task list is exhausted when there is recursive call to
303 : : * allocate accel_task in user's call back function (cb_fn)
304 : : */
305 [ + + ]: 248148795 : STAILQ_INSERT_HEAD(&accel_ch->task_pool, accel_task, link);
306 : :
307 : 248148795 : cb_fn(cb_arg, status);
308 : : }
309 : :
310 : : inline static struct spdk_accel_task *
311 : 355969202 : _get_task(struct accel_io_channel *accel_ch, spdk_accel_completion_cb cb_fn, void *cb_arg)
312 : : {
313 : : struct spdk_accel_task *accel_task;
314 : :
315 : 355969202 : accel_task = STAILQ_FIRST(&accel_ch->task_pool);
316 [ + + ]: 355969202 : if (spdk_unlikely(accel_task == NULL)) {
317 : 150327 : accel_update_stats(accel_ch, retry.task, 1);
318 : 150327 : return NULL;
319 : : }
320 : :
321 [ + + ]: 355818875 : STAILQ_REMOVE_HEAD(&accel_ch->task_pool, link);
322 : 355818875 : accel_task->link.stqe_next = NULL;
323 : :
324 : 355818875 : accel_task->cb_fn = cb_fn;
325 : 355818875 : accel_task->cb_arg = cb_arg;
326 : 355818875 : accel_task->accel_ch = accel_ch;
327 : 355818875 : accel_task->s.iovs = NULL;
328 : 355818875 : accel_task->d.iovs = NULL;
329 : :
330 : 355818875 : return accel_task;
331 : : }
332 : :
333 : : static inline int
334 : 350478742 : accel_submit_task(struct accel_io_channel *accel_ch, struct spdk_accel_task *task)
335 : : {
336 : 350478742 : struct spdk_io_channel *module_ch = accel_ch->module_ch[task->op_code];
337 : 350478742 : struct spdk_accel_module_if *module = g_modules_opc[task->op_code].module;
338 : : int rc;
339 : :
340 : 350478742 : rc = module->submit_tasks(module_ch, task);
341 [ + + ]: 350478742 : if (spdk_unlikely(rc != 0)) {
342 : 12 : accel_update_task_stats(accel_ch, task, failed, 1);
343 : : }
344 : :
345 : 350478742 : return rc;
346 : : }
347 : :
348 : : static inline uint64_t
349 : 194997443 : accel_get_iovlen(struct iovec *iovs, uint32_t iovcnt)
350 : : {
351 : 194997443 : uint64_t result = 0;
352 : : uint32_t i;
353 : :
354 [ + + ]: 427463723 : for (i = 0; i < iovcnt; ++i) {
355 : 232466280 : result += iovs[i].iov_len;
356 : : }
357 : :
358 : 194997443 : return result;
359 : : }
360 : :
361 : : #define ACCEL_TASK_ALLOC_AUX_BUF(task) \
362 : : do { \
363 : : (task)->aux = SLIST_FIRST(&(task)->accel_ch->task_aux_data_pool); \
364 : : if (spdk_unlikely(!(task)->aux)) { \
365 : : SPDK_ERRLOG("Fatal problem, aux data was not allocated\n"); \
366 : : STAILQ_INSERT_HEAD(&(task)->accel_ch->task_pool, (task), link); \
367 : : assert(0); \
368 : : return -ENOMEM; \
369 : : } \
370 : : SLIST_REMOVE_HEAD(&(task)->accel_ch->task_aux_data_pool, link); \
371 : : (task)->has_aux = true; \
372 : : } while (0)
373 : :
374 [ - + ]: 3033 : SPDK_LOG_DEPRECATION_REGISTER(accel_flags,
375 : : "The flags parameter is unused and deprecated",
376 : : "v24.05", 0);
377 : :
378 : : /* \b `flags` is int in API, since it is not used anywahere. we narrowed it down to uint8_t internally
379 : : * To prevent possible problems in the future, add a macro which checks that the value of `flags` passed in the API
380 : : * doesn't exceed 1 byte. */
381 : : #define ACCEL_ASSIGN_FLAGS(task, flags) \
382 : : do { \
383 : : assert(((flags) & (~0xff)) == 0 && "task::flags needs to be extended"); \
384 : : (task)->flags = (uint8_t)(flags); \
385 : : if ((task)->flags) { \
386 : : SPDK_LOG_DEPRECATED(accel_flags); \
387 : : } \
388 : : } while (0) \
389 : :
390 : : /* Accel framework public API for copy function */
391 : : int
392 : 20495007 : spdk_accel_submit_copy(struct spdk_io_channel *ch, void *dst, void *src,
393 : : uint64_t nbytes, int flags, spdk_accel_completion_cb cb_fn, void *cb_arg)
394 : : {
395 : 20495007 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
396 : : struct spdk_accel_task *accel_task;
397 : :
398 : 20495007 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
399 [ + + ]: 20495007 : if (spdk_unlikely(accel_task == NULL)) {
400 : 6 : return -ENOMEM;
401 : : }
402 : :
403 [ - + - - ]: 20495001 : ACCEL_TASK_ALLOC_AUX_BUF(accel_task);
404 : :
405 : 20495001 : accel_task->s.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_SRC];
406 : 20495001 : accel_task->d.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_DST];
407 : 20495001 : accel_task->d.iovs[0].iov_base = dst;
408 : 20495001 : accel_task->d.iovs[0].iov_len = nbytes;
409 : 20495001 : accel_task->d.iovcnt = 1;
410 : 20495001 : accel_task->s.iovs[0].iov_base = src;
411 : 20495001 : accel_task->s.iovs[0].iov_len = nbytes;
412 : 20495001 : accel_task->s.iovcnt = 1;
413 : 20495001 : accel_task->nbytes = nbytes;
414 : 20495001 : accel_task->op_code = SPDK_ACCEL_OPC_COPY;
415 : 20495001 : accel_task->src_domain = NULL;
416 : 20495001 : accel_task->dst_domain = NULL;
417 [ - + - + ]: 20495001 : ACCEL_ASSIGN_FLAGS(accel_task, flags);
418 : :
419 : 20495001 : return accel_submit_task(accel_ch, accel_task);
420 : : }
421 : :
422 : : /* Accel framework public API for dual cast copy function */
423 : : int
424 : 20287800 : spdk_accel_submit_dualcast(struct spdk_io_channel *ch, void *dst1,
425 : : void *dst2, void *src, uint64_t nbytes, int flags,
426 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
427 : : {
428 : 20287800 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
429 : : struct spdk_accel_task *accel_task;
430 : :
431 [ + + + + ]: 20287800 : if ((uintptr_t)dst1 & (ALIGN_4K - 1) || (uintptr_t)dst2 & (ALIGN_4K - 1)) {
432 : 12 : SPDK_ERRLOG("Dualcast requires 4K alignment on dst addresses\n");
433 : 12 : return -EINVAL;
434 : : }
435 : :
436 : 20287788 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
437 [ + + ]: 20287788 : if (spdk_unlikely(accel_task == NULL)) {
438 : 6 : return -ENOMEM;
439 : : }
440 : :
441 [ - + - - ]: 20287782 : ACCEL_TASK_ALLOC_AUX_BUF(accel_task);
442 : :
443 : 20287782 : accel_task->s.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_SRC];
444 : 20287782 : accel_task->d.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_DST];
445 : 20287782 : accel_task->d2.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_DST2];
446 : 20287782 : accel_task->d.iovs[0].iov_base = dst1;
447 : 20287782 : accel_task->d.iovs[0].iov_len = nbytes;
448 : 20287782 : accel_task->d.iovcnt = 1;
449 : 20287782 : accel_task->d2.iovs[0].iov_base = dst2;
450 : 20287782 : accel_task->d2.iovs[0].iov_len = nbytes;
451 : 20287782 : accel_task->d2.iovcnt = 1;
452 : 20287782 : accel_task->s.iovs[0].iov_base = src;
453 : 20287782 : accel_task->s.iovs[0].iov_len = nbytes;
454 : 20287782 : accel_task->s.iovcnt = 1;
455 : 20287782 : accel_task->nbytes = nbytes;
456 : 20287782 : accel_task->op_code = SPDK_ACCEL_OPC_DUALCAST;
457 : 20287782 : accel_task->src_domain = NULL;
458 : 20287782 : accel_task->dst_domain = NULL;
459 [ - + - + ]: 20287782 : ACCEL_ASSIGN_FLAGS(accel_task, flags);
460 : :
461 : 20287782 : return accel_submit_task(accel_ch, accel_task);
462 : : }
463 : :
464 : : /* Accel framework public API for compare function */
465 : :
466 : : int
467 : 30382188 : spdk_accel_submit_compare(struct spdk_io_channel *ch, void *src1,
468 : : void *src2, uint64_t nbytes, spdk_accel_completion_cb cb_fn,
469 : : void *cb_arg)
470 : : {
471 : 30382188 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
472 : : struct spdk_accel_task *accel_task;
473 : :
474 : 30382188 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
475 [ + + ]: 30382188 : if (spdk_unlikely(accel_task == NULL)) {
476 : 6 : return -ENOMEM;
477 : : }
478 : :
479 [ - + - - ]: 30382182 : ACCEL_TASK_ALLOC_AUX_BUF(accel_task);
480 : :
481 : 30382182 : accel_task->s.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_SRC];
482 : 30382182 : accel_task->s2.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_SRC2];
483 : 30382182 : accel_task->s.iovs[0].iov_base = src1;
484 : 30382182 : accel_task->s.iovs[0].iov_len = nbytes;
485 : 30382182 : accel_task->s.iovcnt = 1;
486 : 30382182 : accel_task->s2.iovs[0].iov_base = src2;
487 : 30382182 : accel_task->s2.iovs[0].iov_len = nbytes;
488 : 30382182 : accel_task->s2.iovcnt = 1;
489 : 30382182 : accel_task->nbytes = nbytes;
490 : 30382182 : accel_task->op_code = SPDK_ACCEL_OPC_COMPARE;
491 : 30382182 : accel_task->src_domain = NULL;
492 : 30382182 : accel_task->dst_domain = NULL;
493 : 30382182 : accel_task->flags = 0;
494 : :
495 : 30382182 : return accel_submit_task(accel_ch, accel_task);
496 : : }
497 : :
498 : : /* Accel framework public API for fill function */
499 : : int
500 : 41173502 : spdk_accel_submit_fill(struct spdk_io_channel *ch, void *dst,
501 : : uint8_t fill, uint64_t nbytes, int flags,
502 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
503 : : {
504 : 41173502 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
505 : : struct spdk_accel_task *accel_task;
506 : :
507 : 41173502 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
508 [ + + ]: 41173502 : if (spdk_unlikely(accel_task == NULL)) {
509 : 6 : return -ENOMEM;
510 : : }
511 : :
512 [ - + - - ]: 41173496 : ACCEL_TASK_ALLOC_AUX_BUF(accel_task);
513 : :
514 : 41173496 : accel_task->d.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_DST];
515 : 41173496 : accel_task->d.iovs[0].iov_base = dst;
516 : 41173496 : accel_task->d.iovs[0].iov_len = nbytes;
517 : 41173496 : accel_task->d.iovcnt = 1;
518 : 41173496 : accel_task->nbytes = nbytes;
519 [ - + ]: 41173496 : memset(&accel_task->fill_pattern, fill, sizeof(uint64_t));
520 : 41173496 : accel_task->op_code = SPDK_ACCEL_OPC_FILL;
521 : 41173496 : accel_task->src_domain = NULL;
522 : 41173496 : accel_task->dst_domain = NULL;
523 [ - + - + ]: 41173496 : ACCEL_ASSIGN_FLAGS(accel_task, flags);
524 : :
525 : 41173496 : return accel_submit_task(accel_ch, accel_task);
526 : : }
527 : :
528 : : /* Accel framework public API for CRC-32C function */
529 : : int
530 : 12 : spdk_accel_submit_crc32c(struct spdk_io_channel *ch, uint32_t *crc_dst,
531 : : void *src, uint32_t seed, uint64_t nbytes, spdk_accel_completion_cb cb_fn,
532 : : void *cb_arg)
533 : : {
534 : 12 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
535 : : struct spdk_accel_task *accel_task;
536 : :
537 : 12 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
538 [ + + ]: 12 : if (spdk_unlikely(accel_task == NULL)) {
539 : 6 : return -ENOMEM;
540 : : }
541 : :
542 [ - + - - ]: 6 : ACCEL_TASK_ALLOC_AUX_BUF(accel_task);
543 : :
544 : 6 : accel_task->s.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_SRC];
545 : 6 : accel_task->s.iovs[0].iov_base = src;
546 : 6 : accel_task->s.iovs[0].iov_len = nbytes;
547 : 6 : accel_task->s.iovcnt = 1;
548 : 6 : accel_task->nbytes = nbytes;
549 : 6 : accel_task->crc_dst = crc_dst;
550 : 6 : accel_task->seed = seed;
551 : 6 : accel_task->op_code = SPDK_ACCEL_OPC_CRC32C;
552 : 6 : accel_task->src_domain = NULL;
553 : 6 : accel_task->dst_domain = NULL;
554 : 6 : accel_task->flags = 0;
555 : :
556 : 6 : return accel_submit_task(accel_ch, accel_task);
557 : : }
558 : :
559 : : /* Accel framework public API for chained CRC-32C function */
560 : : int
561 : 43986354 : spdk_accel_submit_crc32cv(struct spdk_io_channel *ch, uint32_t *crc_dst,
562 : : struct iovec *iov, uint32_t iov_cnt, uint32_t seed,
563 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
564 : : {
565 : 43986354 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
566 : : struct spdk_accel_task *accel_task;
567 : :
568 [ - + ]: 43986354 : if (iov == NULL) {
569 : 0 : SPDK_ERRLOG("iov should not be NULL");
570 : 0 : return -EINVAL;
571 : : }
572 : :
573 [ - + ]: 43986354 : if (!iov_cnt) {
574 : 0 : SPDK_ERRLOG("iovcnt should not be zero value\n");
575 : 0 : return -EINVAL;
576 : : }
577 : :
578 : 43986354 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
579 [ - + ]: 43986354 : if (spdk_unlikely(accel_task == NULL)) {
580 : 0 : SPDK_ERRLOG("no memory\n");
581 : 0 : assert(0);
582 : : return -ENOMEM;
583 : : }
584 : :
585 : 43986354 : accel_task->s.iovs = iov;
586 : 43986354 : accel_task->s.iovcnt = iov_cnt;
587 : 43986354 : accel_task->nbytes = accel_get_iovlen(iov, iov_cnt);
588 : 43986354 : accel_task->crc_dst = crc_dst;
589 : 43986354 : accel_task->seed = seed;
590 : 43986354 : accel_task->op_code = SPDK_ACCEL_OPC_CRC32C;
591 : 43986354 : accel_task->src_domain = NULL;
592 : 43986354 : accel_task->dst_domain = NULL;
593 : 43986354 : accel_task->flags = 0;
594 : :
595 : 43986354 : return accel_submit_task(accel_ch, accel_task);
596 : : }
597 : :
598 : : /* Accel framework public API for copy with CRC-32C function */
599 : : int
600 : 12 : spdk_accel_submit_copy_crc32c(struct spdk_io_channel *ch, void *dst,
601 : : void *src, uint32_t *crc_dst, uint32_t seed, uint64_t nbytes,
602 : : int flags, spdk_accel_completion_cb cb_fn, void *cb_arg)
603 : : {
604 : 12 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
605 : : struct spdk_accel_task *accel_task;
606 : :
607 : 12 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
608 [ + + ]: 12 : if (spdk_unlikely(accel_task == NULL)) {
609 : 6 : return -ENOMEM;
610 : : }
611 : :
612 [ - + - - ]: 6 : ACCEL_TASK_ALLOC_AUX_BUF(accel_task);
613 : :
614 : 6 : accel_task->s.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_SRC];
615 : 6 : accel_task->d.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_DST];
616 : 6 : accel_task->d.iovs[0].iov_base = dst;
617 : 6 : accel_task->d.iovs[0].iov_len = nbytes;
618 : 6 : accel_task->d.iovcnt = 1;
619 : 6 : accel_task->s.iovs[0].iov_base = src;
620 : 6 : accel_task->s.iovs[0].iov_len = nbytes;
621 : 6 : accel_task->s.iovcnt = 1;
622 : 6 : accel_task->nbytes = nbytes;
623 : 6 : accel_task->crc_dst = crc_dst;
624 : 6 : accel_task->seed = seed;
625 : 6 : accel_task->op_code = SPDK_ACCEL_OPC_COPY_CRC32C;
626 : 6 : accel_task->src_domain = NULL;
627 : 6 : accel_task->dst_domain = NULL;
628 [ - + - + ]: 6 : ACCEL_ASSIGN_FLAGS(accel_task, flags);
629 : :
630 : 6 : return accel_submit_task(accel_ch, accel_task);
631 : : }
632 : :
633 : : /* Accel framework public API for chained copy + CRC-32C function */
634 : : int
635 : 23269824 : spdk_accel_submit_copy_crc32cv(struct spdk_io_channel *ch, void *dst,
636 : : struct iovec *src_iovs, uint32_t iov_cnt, uint32_t *crc_dst,
637 : : uint32_t seed, int flags, spdk_accel_completion_cb cb_fn, void *cb_arg)
638 : : {
639 : 23269824 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
640 : : struct spdk_accel_task *accel_task;
641 : : uint64_t nbytes;
642 : :
643 [ - + ]: 23269824 : if (src_iovs == NULL) {
644 : 0 : SPDK_ERRLOG("iov should not be NULL");
645 : 0 : return -EINVAL;
646 : : }
647 : :
648 [ - + ]: 23269824 : if (!iov_cnt) {
649 : 0 : SPDK_ERRLOG("iovcnt should not be zero value\n");
650 : 0 : return -EINVAL;
651 : : }
652 : :
653 : 23269824 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
654 [ - + ]: 23269824 : if (spdk_unlikely(accel_task == NULL)) {
655 : 0 : SPDK_ERRLOG("no memory\n");
656 : 0 : assert(0);
657 : : return -ENOMEM;
658 : : }
659 : :
660 : 23269824 : nbytes = accel_get_iovlen(src_iovs, iov_cnt);
661 : :
662 [ - + - - ]: 23269824 : ACCEL_TASK_ALLOC_AUX_BUF(accel_task);
663 : :
664 : 23269824 : accel_task->d.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_DST];
665 : 23269824 : accel_task->d.iovs[0].iov_base = dst;
666 : 23269824 : accel_task->d.iovs[0].iov_len = nbytes;
667 : 23269824 : accel_task->d.iovcnt = 1;
668 : 23269824 : accel_task->s.iovs = src_iovs;
669 : 23269824 : accel_task->s.iovcnt = iov_cnt;
670 : 23269824 : accel_task->nbytes = nbytes;
671 : 23269824 : accel_task->crc_dst = crc_dst;
672 : 23269824 : accel_task->seed = seed;
673 : 23269824 : accel_task->op_code = SPDK_ACCEL_OPC_COPY_CRC32C;
674 : 23269824 : accel_task->src_domain = NULL;
675 : 23269824 : accel_task->dst_domain = NULL;
676 [ - + - + ]: 23269824 : ACCEL_ASSIGN_FLAGS(accel_task, flags);
677 : :
678 : 23269824 : return accel_submit_task(accel_ch, accel_task);
679 : : }
680 : :
681 : : int
682 : 3260673 : spdk_accel_submit_compress(struct spdk_io_channel *ch, void *dst, uint64_t nbytes,
683 : : struct iovec *src_iovs, size_t src_iovcnt, uint32_t *output_size, int flags,
684 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
685 : : {
686 : 3260673 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
687 : : struct spdk_accel_task *accel_task;
688 : :
689 : 3260673 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
690 [ - + ]: 3260673 : if (spdk_unlikely(accel_task == NULL)) {
691 : 0 : return -ENOMEM;
692 : : }
693 : :
694 [ - + - - ]: 3260673 : ACCEL_TASK_ALLOC_AUX_BUF(accel_task);
695 : :
696 : 3260673 : accel_task->d.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_DST];
697 : 3260673 : accel_task->d.iovs[0].iov_base = dst;
698 : 3260673 : accel_task->d.iovs[0].iov_len = nbytes;
699 : 3260673 : accel_task->d.iovcnt = 1;
700 : 3260673 : accel_task->output_size = output_size;
701 : 3260673 : accel_task->s.iovs = src_iovs;
702 : 3260673 : accel_task->s.iovcnt = src_iovcnt;
703 : 3260673 : accel_task->nbytes = nbytes;
704 : 3260673 : accel_task->op_code = SPDK_ACCEL_OPC_COMPRESS;
705 : 3260673 : accel_task->src_domain = NULL;
706 : 3260673 : accel_task->dst_domain = NULL;
707 [ - + - + ]: 3260673 : ACCEL_ASSIGN_FLAGS(accel_task, flags);
708 : :
709 : 3260673 : return accel_submit_task(accel_ch, accel_task);
710 : : }
711 : :
712 : : int
713 : 19475741 : spdk_accel_submit_decompress(struct spdk_io_channel *ch, struct iovec *dst_iovs,
714 : : size_t dst_iovcnt, struct iovec *src_iovs, size_t src_iovcnt,
715 : : uint32_t *output_size, int flags, spdk_accel_completion_cb cb_fn,
716 : : void *cb_arg)
717 : : {
718 : 19475741 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
719 : : struct spdk_accel_task *accel_task;
720 : :
721 : 19475741 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
722 [ - + ]: 19475741 : if (spdk_unlikely(accel_task == NULL)) {
723 : 0 : return -ENOMEM;
724 : : }
725 : :
726 : 19475741 : accel_task->output_size = output_size;
727 : 19475741 : accel_task->s.iovs = src_iovs;
728 : 19475741 : accel_task->s.iovcnt = src_iovcnt;
729 : 19475741 : accel_task->d.iovs = dst_iovs;
730 : 19475741 : accel_task->d.iovcnt = dst_iovcnt;
731 : 19475741 : accel_task->nbytes = accel_get_iovlen(src_iovs, src_iovcnt);
732 : 19475741 : accel_task->op_code = SPDK_ACCEL_OPC_DECOMPRESS;
733 : 19475741 : accel_task->src_domain = NULL;
734 : 19475741 : accel_task->dst_domain = NULL;
735 [ - + - + ]: 19475741 : ACCEL_ASSIGN_FLAGS(accel_task, flags);
736 : :
737 : 19475741 : return accel_submit_task(accel_ch, accel_task);
738 : : }
739 : :
740 : : int
741 : 5 : spdk_accel_submit_encrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key,
742 : : struct iovec *dst_iovs, uint32_t dst_iovcnt,
743 : : struct iovec *src_iovs, uint32_t src_iovcnt,
744 : : uint64_t iv, uint32_t block_size, int flags,
745 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
746 : : {
747 : 5 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
748 : : struct spdk_accel_task *accel_task;
749 : :
750 [ + - - + : 5 : if (spdk_unlikely(!dst_iovs || !dst_iovcnt || !src_iovs || !src_iovcnt || !key || !block_size)) {
+ - - + +
- - + + -
- + + - -
+ ]
751 : 0 : return -EINVAL;
752 : : }
753 : :
754 : 5 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
755 [ - + ]: 5 : if (spdk_unlikely(accel_task == NULL)) {
756 : 0 : return -ENOMEM;
757 : : }
758 : :
759 : 5 : accel_task->crypto_key = key;
760 : 5 : accel_task->s.iovs = src_iovs;
761 : 5 : accel_task->s.iovcnt = src_iovcnt;
762 : 5 : accel_task->d.iovs = dst_iovs;
763 : 5 : accel_task->d.iovcnt = dst_iovcnt;
764 : 5 : accel_task->nbytes = accel_get_iovlen(src_iovs, src_iovcnt);
765 : 5 : accel_task->iv = iv;
766 : 5 : accel_task->block_size = block_size;
767 : 5 : accel_task->op_code = SPDK_ACCEL_OPC_ENCRYPT;
768 : 5 : accel_task->src_domain = NULL;
769 : 5 : accel_task->dst_domain = NULL;
770 [ - + - + ]: 5 : ACCEL_ASSIGN_FLAGS(accel_task, flags);
771 : :
772 : 5 : return accel_submit_task(accel_ch, accel_task);
773 : : }
774 : :
775 : : int
776 : 0 : spdk_accel_submit_decrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key,
777 : : struct iovec *dst_iovs, uint32_t dst_iovcnt,
778 : : struct iovec *src_iovs, uint32_t src_iovcnt,
779 : : uint64_t iv, uint32_t block_size, int flags,
780 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
781 : : {
782 : 0 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
783 : : struct spdk_accel_task *accel_task;
784 : :
785 [ # # # # : 0 : if (spdk_unlikely(!dst_iovs || !dst_iovcnt || !src_iovs || !src_iovcnt || !key || !block_size)) {
# # # # #
# # # # #
# # # # #
# ]
786 : 0 : return -EINVAL;
787 : : }
788 : :
789 : 0 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
790 [ # # ]: 0 : if (spdk_unlikely(accel_task == NULL)) {
791 : 0 : return -ENOMEM;
792 : : }
793 : :
794 : 0 : accel_task->crypto_key = key;
795 : 0 : accel_task->s.iovs = src_iovs;
796 : 0 : accel_task->s.iovcnt = src_iovcnt;
797 : 0 : accel_task->d.iovs = dst_iovs;
798 : 0 : accel_task->d.iovcnt = dst_iovcnt;
799 : 0 : accel_task->nbytes = accel_get_iovlen(src_iovs, src_iovcnt);
800 : 0 : accel_task->iv = iv;
801 : 0 : accel_task->block_size = block_size;
802 : 0 : accel_task->op_code = SPDK_ACCEL_OPC_DECRYPT;
803 : 0 : accel_task->src_domain = NULL;
804 : 0 : accel_task->dst_domain = NULL;
805 [ # # # # ]: 0 : ACCEL_ASSIGN_FLAGS(accel_task, flags);
806 : :
807 : 0 : return accel_submit_task(accel_ch, accel_task);
808 : : }
809 : :
810 : : int
811 : 28731909 : spdk_accel_submit_xor(struct spdk_io_channel *ch, void *dst, void **sources, uint32_t nsrcs,
812 : : uint64_t nbytes, spdk_accel_completion_cb cb_fn, void *cb_arg)
813 : : {
814 : 28731909 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
815 : : struct spdk_accel_task *accel_task;
816 : :
817 : 28731909 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
818 [ + + ]: 28731909 : if (spdk_unlikely(accel_task == NULL)) {
819 : 6 : return -ENOMEM;
820 : : }
821 : :
822 [ - + - - ]: 28731903 : ACCEL_TASK_ALLOC_AUX_BUF(accel_task);
823 : :
824 : 28731903 : accel_task->d.iovs = &accel_task->aux->iovs[SPDK_ACCEL_AUX_IOV_DST];
825 : 28731903 : accel_task->nsrcs.srcs = sources;
826 : 28731903 : accel_task->nsrcs.cnt = nsrcs;
827 : 28731903 : accel_task->d.iovs[0].iov_base = dst;
828 : 28731903 : accel_task->d.iovs[0].iov_len = nbytes;
829 : 28731903 : accel_task->d.iovcnt = 1;
830 : 28731903 : accel_task->nbytes = nbytes;
831 : 28731903 : accel_task->op_code = SPDK_ACCEL_OPC_XOR;
832 : 28731903 : accel_task->src_domain = NULL;
833 : 28731903 : accel_task->dst_domain = NULL;
834 : :
835 : 28731903 : return accel_submit_task(accel_ch, accel_task);
836 : : }
837 : :
838 : : int
839 : 5367196 : spdk_accel_submit_dif_verify(struct spdk_io_channel *ch,
840 : : struct iovec *iovs, size_t iovcnt, uint32_t num_blocks,
841 : : const struct spdk_dif_ctx *ctx, struct spdk_dif_error *err,
842 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
843 : : {
844 : 5367196 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
845 : : struct spdk_accel_task *accel_task;
846 : :
847 : 5367196 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
848 [ - + ]: 5367196 : if (accel_task == NULL) {
849 : 0 : return -ENOMEM;
850 : : }
851 : :
852 : 5367196 : accel_task->s.iovs = iovs;
853 : 5367196 : accel_task->s.iovcnt = iovcnt;
854 : 5367196 : accel_task->dif.ctx = ctx;
855 : 5367196 : accel_task->dif.err = err;
856 : 5367196 : accel_task->dif.num_blocks = num_blocks;
857 : 5367196 : accel_task->nbytes = num_blocks * ctx->block_size;
858 : 5367196 : accel_task->op_code = SPDK_ACCEL_OPC_DIF_VERIFY;
859 : 5367196 : accel_task->src_domain = NULL;
860 : 5367196 : accel_task->dst_domain = NULL;
861 : :
862 : 5367196 : return accel_submit_task(accel_ch, accel_task);
863 : : }
864 : :
865 : : int
866 : 6658496 : spdk_accel_submit_dif_generate(struct spdk_io_channel *ch,
867 : : struct iovec *iovs, size_t iovcnt, uint32_t num_blocks,
868 : : const struct spdk_dif_ctx *ctx,
869 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
870 : : {
871 : 6658496 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
872 : : struct spdk_accel_task *accel_task;
873 : :
874 : 6658496 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
875 [ - + ]: 6658496 : if (accel_task == NULL) {
876 : 0 : return -ENOMEM;
877 : : }
878 : :
879 : 6658496 : accel_task->s.iovs = iovs;
880 : 6658496 : accel_task->s.iovcnt = iovcnt;
881 : 6658496 : accel_task->dif.ctx = ctx;
882 : 6658496 : accel_task->dif.num_blocks = num_blocks;
883 : 6658496 : accel_task->nbytes = num_blocks * ctx->block_size;
884 : 6658496 : accel_task->op_code = SPDK_ACCEL_OPC_DIF_GENERATE;
885 : 6658496 : accel_task->src_domain = NULL;
886 : 6658496 : accel_task->dst_domain = NULL;
887 : :
888 : 6658496 : return accel_submit_task(accel_ch, accel_task);
889 : : }
890 : :
891 : : int
892 : 5060168 : spdk_accel_submit_dif_generate_copy(struct spdk_io_channel *ch, struct iovec *dst_iovs,
893 : : size_t dst_iovcnt, struct iovec *src_iovs, size_t src_iovcnt,
894 : : uint32_t num_blocks, const struct spdk_dif_ctx *ctx,
895 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
896 : : {
897 : 5060168 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
898 : : struct spdk_accel_task *accel_task;
899 : :
900 : 5060168 : accel_task = _get_task(accel_ch, cb_fn, cb_arg);
901 [ - + ]: 5060168 : if (accel_task == NULL) {
902 : 0 : return -ENOMEM;
903 : : }
904 : :
905 : 5060168 : accel_task->s.iovs = src_iovs;
906 : 5060168 : accel_task->s.iovcnt = src_iovcnt;
907 : 5060168 : accel_task->d.iovs = dst_iovs;
908 : 5060168 : accel_task->d.iovcnt = dst_iovcnt;
909 : 5060168 : accel_task->dif.ctx = ctx;
910 : 5060168 : accel_task->dif.num_blocks = num_blocks;
911 : 5060168 : accel_task->nbytes = num_blocks * ctx->block_size;
912 : 5060168 : accel_task->op_code = SPDK_ACCEL_OPC_DIF_GENERATE_COPY;
913 : 5060168 : accel_task->src_domain = NULL;
914 : 5060168 : accel_task->dst_domain = NULL;
915 : :
916 : 5060168 : return accel_submit_task(accel_ch, accel_task);
917 : : }
918 : :
919 : : static inline struct accel_buffer *
920 : 4830861 : accel_get_buf(struct accel_io_channel *ch, uint64_t len)
921 : : {
922 : : struct accel_buffer *buf;
923 : :
924 : 4830861 : buf = SLIST_FIRST(&ch->buf_pool);
925 [ - + ]: 4830861 : if (spdk_unlikely(buf == NULL)) {
926 : 0 : accel_update_stats(ch, retry.bufdesc, 1);
927 : 0 : return NULL;
928 : : }
929 : :
930 : 4830861 : SLIST_REMOVE_HEAD(&ch->buf_pool, link);
931 : 4830861 : buf->len = len;
932 : 4830861 : buf->buf = NULL;
933 : 4830861 : buf->seq = NULL;
934 : 4830861 : buf->cb_fn = NULL;
935 : :
936 : 4830861 : return buf;
937 : : }
938 : :
939 : : static inline void
940 : 4830861 : accel_put_buf(struct accel_io_channel *ch, struct accel_buffer *buf)
941 : : {
942 [ + + ]: 4830861 : if (buf->buf != NULL) {
943 : 1178973 : spdk_iobuf_put(&ch->iobuf, buf->buf, buf->len);
944 : : }
945 : :
946 : 4830861 : SLIST_INSERT_HEAD(&ch->buf_pool, buf, link);
947 : 4830861 : }
948 : :
949 : : static inline struct spdk_accel_sequence *
950 : 101191895 : accel_sequence_get(struct accel_io_channel *ch)
951 : : {
952 : : struct spdk_accel_sequence *seq;
953 : :
954 : 101191895 : seq = SLIST_FIRST(&ch->seq_pool);
955 [ + + ]: 101191895 : if (spdk_unlikely(seq == NULL)) {
956 : 3616 : accel_update_stats(ch, retry.sequence, 1);
957 : 3616 : return NULL;
958 : : }
959 : :
960 : 101188279 : SLIST_REMOVE_HEAD(&ch->seq_pool, link);
961 : :
962 : 101188279 : TAILQ_INIT(&seq->tasks);
963 : 101188279 : SLIST_INIT(&seq->bounce_bufs);
964 : :
965 : 101188279 : seq->ch = ch;
966 : 101188279 : seq->status = 0;
967 : 101188279 : seq->state = ACCEL_SEQUENCE_STATE_INIT;
968 : 101188279 : seq->in_process_sequence = false;
969 : :
970 : 101188279 : return seq;
971 : : }
972 : :
973 : : static inline void
974 : 101188279 : accel_sequence_put(struct spdk_accel_sequence *seq)
975 : : {
976 : 101188279 : struct accel_io_channel *ch = seq->ch;
977 : : struct accel_buffer *buf;
978 : :
979 [ + + ]: 101783981 : while (!SLIST_EMPTY(&seq->bounce_bufs)) {
980 : 595702 : buf = SLIST_FIRST(&seq->bounce_bufs);
981 : 595702 : SLIST_REMOVE_HEAD(&seq->bounce_bufs, link);
982 : 595702 : accel_put_buf(seq->ch, buf);
983 : : }
984 : :
985 [ - + ]: 101188279 : assert(TAILQ_EMPTY(&seq->tasks));
986 : 101188279 : seq->ch = NULL;
987 : :
988 : 101188279 : SLIST_INSERT_HEAD(&ch->seq_pool, seq, link);
989 : 101188279 : }
990 : :
991 : : static void accel_sequence_task_cb(void *cb_arg, int status);
992 : :
993 : : static inline struct spdk_accel_task *
994 : 107820301 : accel_sequence_get_task(struct accel_io_channel *ch, struct spdk_accel_sequence *seq,
995 : : spdk_accel_step_cb cb_fn, void *cb_arg)
996 : : {
997 : : struct spdk_accel_task *task;
998 : :
999 : 107820301 : task = _get_task(ch, NULL, NULL);
1000 [ + + ]: 107820301 : if (spdk_unlikely(task == NULL)) {
1001 : 150279 : return task;
1002 : : }
1003 : :
1004 : 107670022 : task->step_cb_fn = cb_fn;
1005 : 107670022 : task->cb_arg = cb_arg;
1006 : 107670022 : task->seq = seq;
1007 : :
1008 : 107670022 : return task;
1009 : : }
1010 : :
1011 : : int
1012 : 100342029 : spdk_accel_append_copy(struct spdk_accel_sequence **pseq, struct spdk_io_channel *ch,
1013 : : struct iovec *dst_iovs, uint32_t dst_iovcnt,
1014 : : struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
1015 : : struct iovec *src_iovs, uint32_t src_iovcnt,
1016 : : struct spdk_memory_domain *src_domain, void *src_domain_ctx,
1017 : : int flags, spdk_accel_step_cb cb_fn, void *cb_arg)
1018 : : {
1019 : 100342029 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
1020 : : struct spdk_accel_task *task;
1021 : 100342029 : struct spdk_accel_sequence *seq = *pseq;
1022 : :
1023 [ + + ]: 100342029 : if (seq == NULL) {
1024 : 94955843 : seq = accel_sequence_get(accel_ch);
1025 [ + + ]: 94955843 : if (spdk_unlikely(seq == NULL)) {
1026 : 3604 : return -ENOMEM;
1027 : : }
1028 : : }
1029 : :
1030 [ - + ]: 100338425 : assert(seq->ch == accel_ch);
1031 : 100338425 : task = accel_sequence_get_task(accel_ch, seq, cb_fn, cb_arg);
1032 [ + + ]: 100338425 : if (spdk_unlikely(task == NULL)) {
1033 [ + + ]: 55100 : if (*pseq == NULL) {
1034 : 8866 : accel_sequence_put(seq);
1035 : : }
1036 : :
1037 : 55100 : return -ENOMEM;
1038 : : }
1039 : :
1040 : 100283325 : task->dst_domain = dst_domain;
1041 : 100283325 : task->dst_domain_ctx = dst_domain_ctx;
1042 : 100283325 : task->d.iovs = dst_iovs;
1043 : 100283325 : task->d.iovcnt = dst_iovcnt;
1044 : 100283325 : task->src_domain = src_domain;
1045 : 100283325 : task->src_domain_ctx = src_domain_ctx;
1046 : 100283325 : task->s.iovs = src_iovs;
1047 : 100283325 : task->s.iovcnt = src_iovcnt;
1048 : 100283325 : task->nbytes = accel_get_iovlen(src_iovs, src_iovcnt);
1049 : 100283325 : task->op_code = SPDK_ACCEL_OPC_COPY;
1050 [ - + - + ]: 100283325 : ACCEL_ASSIGN_FLAGS(task, flags);
1051 : :
1052 : 100283325 : TAILQ_INSERT_TAIL(&seq->tasks, task, seq_link);
1053 : 100283325 : *pseq = seq;
1054 : :
1055 : 100283325 : return 0;
1056 : : }
1057 : :
1058 : : int
1059 : 249 : spdk_accel_append_fill(struct spdk_accel_sequence **pseq, struct spdk_io_channel *ch,
1060 : : void *buf, uint64_t len,
1061 : : struct spdk_memory_domain *domain, void *domain_ctx, uint8_t pattern,
1062 : : int flags, spdk_accel_step_cb cb_fn, void *cb_arg)
1063 : : {
1064 : 249 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
1065 : : struct spdk_accel_task *task;
1066 : 249 : struct spdk_accel_sequence *seq = *pseq;
1067 : :
1068 [ + + ]: 249 : if (seq == NULL) {
1069 : 143 : seq = accel_sequence_get(accel_ch);
1070 [ + + ]: 143 : if (spdk_unlikely(seq == NULL)) {
1071 : 6 : return -ENOMEM;
1072 : : }
1073 : : }
1074 : :
1075 [ - + ]: 243 : assert(seq->ch == accel_ch);
1076 : 243 : task = accel_sequence_get_task(accel_ch, seq, cb_fn, cb_arg);
1077 [ + + ]: 243 : if (spdk_unlikely(task == NULL)) {
1078 [ + - ]: 6 : if (*pseq == NULL) {
1079 : 6 : accel_sequence_put(seq);
1080 : : }
1081 : :
1082 : 6 : return -ENOMEM;
1083 : : }
1084 : :
1085 [ - + ]: 237 : memset(&task->fill_pattern, pattern, sizeof(uint64_t));
1086 : :
1087 : 237 : task->aux = SLIST_FIRST(&task->accel_ch->task_aux_data_pool);
1088 [ - + ]: 237 : if (spdk_unlikely(!task->aux)) {
1089 : 0 : SPDK_ERRLOG("Fatal problem, aux data was not allocated\n");
1090 [ # # ]: 0 : if (*pseq == NULL) {
1091 : 0 : accel_sequence_put((seq));
1092 : : }
1093 [ # # ]: 0 : STAILQ_INSERT_HEAD(&task->accel_ch->task_pool, task, link);
1094 : 0 : task->seq = NULL;
1095 : 0 : assert(0);
1096 : : return -ENOMEM;
1097 : : }
1098 : 237 : SLIST_REMOVE_HEAD(&task->accel_ch->task_aux_data_pool, link);
1099 : 237 : task->has_aux = true;
1100 : :
1101 : 237 : task->d.iovs = &task->aux->iovs[SPDK_ACCEL_AUX_IOV_DST];
1102 : 237 : task->d.iovs[0].iov_base = buf;
1103 : 237 : task->d.iovs[0].iov_len = len;
1104 : 237 : task->d.iovcnt = 1;
1105 : 237 : task->nbytes = len;
1106 : 237 : task->src_domain = NULL;
1107 : 237 : task->dst_domain = domain;
1108 : 237 : task->dst_domain_ctx = domain_ctx;
1109 : 237 : task->op_code = SPDK_ACCEL_OPC_FILL;
1110 [ - + - + ]: 237 : ACCEL_ASSIGN_FLAGS(task, flags);
1111 : :
1112 : 237 : TAILQ_INSERT_TAIL(&seq->tasks, task, seq_link);
1113 : 237 : *pseq = seq;
1114 : :
1115 : 237 : return 0;
1116 : : }
1117 : :
1118 : : int
1119 : 275 : spdk_accel_append_decompress(struct spdk_accel_sequence **pseq, struct spdk_io_channel *ch,
1120 : : struct iovec *dst_iovs, size_t dst_iovcnt,
1121 : : struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
1122 : : struct iovec *src_iovs, size_t src_iovcnt,
1123 : : struct spdk_memory_domain *src_domain, void *src_domain_ctx,
1124 : : int flags, spdk_accel_step_cb cb_fn, void *cb_arg)
1125 : : {
1126 : 275 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
1127 : : struct spdk_accel_task *task;
1128 : 275 : struct spdk_accel_sequence *seq = *pseq;
1129 : :
1130 [ + + ]: 275 : if (seq == NULL) {
1131 : 122 : seq = accel_sequence_get(accel_ch);
1132 [ + + ]: 122 : if (spdk_unlikely(seq == NULL)) {
1133 : 6 : return -ENOMEM;
1134 : : }
1135 : : }
1136 : :
1137 [ - + ]: 269 : assert(seq->ch == accel_ch);
1138 : 269 : task = accel_sequence_get_task(accel_ch, seq, cb_fn, cb_arg);
1139 [ + + ]: 269 : if (spdk_unlikely(task == NULL)) {
1140 [ + - ]: 6 : if (*pseq == NULL) {
1141 : 6 : accel_sequence_put(seq);
1142 : : }
1143 : :
1144 : 6 : return -ENOMEM;
1145 : : }
1146 : :
1147 : : /* TODO: support output_size for chaining */
1148 : 263 : task->output_size = NULL;
1149 : 263 : task->dst_domain = dst_domain;
1150 : 263 : task->dst_domain_ctx = dst_domain_ctx;
1151 : 263 : task->d.iovs = dst_iovs;
1152 : 263 : task->d.iovcnt = dst_iovcnt;
1153 : 263 : task->src_domain = src_domain;
1154 : 263 : task->src_domain_ctx = src_domain_ctx;
1155 : 263 : task->s.iovs = src_iovs;
1156 : 263 : task->s.iovcnt = src_iovcnt;
1157 : 263 : task->nbytes = accel_get_iovlen(src_iovs, src_iovcnt);
1158 : 263 : task->op_code = SPDK_ACCEL_OPC_DECOMPRESS;
1159 [ - + - + ]: 263 : ACCEL_ASSIGN_FLAGS(task, flags);
1160 : :
1161 : 263 : TAILQ_INSERT_TAIL(&seq->tasks, task, seq_link);
1162 : 263 : *pseq = seq;
1163 : :
1164 : 263 : return 0;
1165 : : }
1166 : :
1167 : : int
1168 : 4235133 : spdk_accel_append_encrypt(struct spdk_accel_sequence **pseq, struct spdk_io_channel *ch,
1169 : : struct spdk_accel_crypto_key *key,
1170 : : struct iovec *dst_iovs, uint32_t dst_iovcnt,
1171 : : struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
1172 : : struct iovec *src_iovs, uint32_t src_iovcnt,
1173 : : struct spdk_memory_domain *src_domain, void *src_domain_ctx,
1174 : : uint64_t iv, uint32_t block_size, int flags,
1175 : : spdk_accel_step_cb cb_fn, void *cb_arg)
1176 : : {
1177 : 4235133 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
1178 : : struct spdk_accel_task *task;
1179 : 4235133 : struct spdk_accel_sequence *seq = *pseq;
1180 : :
1181 [ + - + - : 4235133 : assert(dst_iovs && dst_iovcnt && src_iovs && src_iovcnt && key && block_size);
+ - + - +
- + + ]
1182 : :
1183 [ + + ]: 4235133 : if (seq == NULL) {
1184 : 3646766 : seq = accel_sequence_get(accel_ch);
1185 [ - + ]: 3646766 : if (spdk_unlikely(seq == NULL)) {
1186 : 0 : return -ENOMEM;
1187 : : }
1188 : : }
1189 : :
1190 [ - + ]: 4235133 : assert(seq->ch == accel_ch);
1191 : 4235133 : task = accel_sequence_get_task(accel_ch, seq, cb_fn, cb_arg);
1192 [ + + ]: 4235133 : if (spdk_unlikely(task == NULL)) {
1193 [ + + ]: 31446 : if (*pseq == NULL) {
1194 : 26312 : accel_sequence_put(seq);
1195 : : }
1196 : :
1197 : 31446 : return -ENOMEM;
1198 : : }
1199 : :
1200 : 4203687 : task->crypto_key = key;
1201 : 4203687 : task->src_domain = src_domain;
1202 : 4203687 : task->src_domain_ctx = src_domain_ctx;
1203 : 4203687 : task->s.iovs = src_iovs;
1204 : 4203687 : task->s.iovcnt = src_iovcnt;
1205 : 4203687 : task->dst_domain = dst_domain;
1206 : 4203687 : task->dst_domain_ctx = dst_domain_ctx;
1207 : 4203687 : task->d.iovs = dst_iovs;
1208 : 4203687 : task->d.iovcnt = dst_iovcnt;
1209 : 4203687 : task->nbytes = accel_get_iovlen(src_iovs, src_iovcnt);
1210 : 4203687 : task->iv = iv;
1211 : 4203687 : task->block_size = block_size;
1212 : 4203687 : task->op_code = SPDK_ACCEL_OPC_ENCRYPT;
1213 [ - + - + ]: 4203687 : ACCEL_ASSIGN_FLAGS(task, flags);
1214 : :
1215 : 4203687 : TAILQ_INSERT_TAIL(&seq->tasks, task, seq_link);
1216 : 4203687 : *pseq = seq;
1217 : :
1218 : 4203687 : return 0;
1219 : : }
1220 : :
1221 : : int
1222 : 2480382 : spdk_accel_append_decrypt(struct spdk_accel_sequence **pseq, struct spdk_io_channel *ch,
1223 : : struct spdk_accel_crypto_key *key,
1224 : : struct iovec *dst_iovs, uint32_t dst_iovcnt,
1225 : : struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
1226 : : struct iovec *src_iovs, uint32_t src_iovcnt,
1227 : : struct spdk_memory_domain *src_domain, void *src_domain_ctx,
1228 : : uint64_t iv, uint32_t block_size, int flags,
1229 : : spdk_accel_step_cb cb_fn, void *cb_arg)
1230 : : {
1231 : 2480382 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
1232 : : struct spdk_accel_task *task;
1233 : 2480382 : struct spdk_accel_sequence *seq = *pseq;
1234 : :
1235 [ + - + - : 2480382 : assert(dst_iovs && dst_iovcnt && src_iovs && src_iovcnt && key && block_size);
+ - + - +
- + + ]
1236 : :
1237 [ + + ]: 2480382 : if (seq == NULL) {
1238 : 1999301 : seq = accel_sequence_get(accel_ch);
1239 [ - + ]: 1999301 : if (spdk_unlikely(seq == NULL)) {
1240 : 0 : return -ENOMEM;
1241 : : }
1242 : : }
1243 : :
1244 [ - + ]: 2480382 : assert(seq->ch == accel_ch);
1245 : 2480382 : task = accel_sequence_get_task(accel_ch, seq, cb_fn, cb_arg);
1246 [ + + ]: 2480382 : if (spdk_unlikely(task == NULL)) {
1247 [ + + ]: 63721 : if (*pseq == NULL) {
1248 : 53209 : accel_sequence_put(seq);
1249 : : }
1250 : :
1251 : 63721 : return -ENOMEM;
1252 : : }
1253 : :
1254 : 2416661 : task->crypto_key = key;
1255 : 2416661 : task->src_domain = src_domain;
1256 : 2416661 : task->src_domain_ctx = src_domain_ctx;
1257 : 2416661 : task->s.iovs = src_iovs;
1258 : 2416661 : task->s.iovcnt = src_iovcnt;
1259 : 2416661 : task->dst_domain = dst_domain;
1260 : 2416661 : task->dst_domain_ctx = dst_domain_ctx;
1261 : 2416661 : task->d.iovs = dst_iovs;
1262 : 2416661 : task->d.iovcnt = dst_iovcnt;
1263 : 2416661 : task->nbytes = accel_get_iovlen(src_iovs, src_iovcnt);
1264 : 2416661 : task->iv = iv;
1265 : 2416661 : task->block_size = block_size;
1266 : 2416661 : task->op_code = SPDK_ACCEL_OPC_DECRYPT;
1267 [ - + - + ]: 2416661 : ACCEL_ASSIGN_FLAGS(task, flags);
1268 : :
1269 : 2416661 : TAILQ_INSERT_TAIL(&seq->tasks, task, seq_link);
1270 : 2416661 : *pseq = seq;
1271 : :
1272 : 2416661 : return 0;
1273 : : }
1274 : :
1275 : : int
1276 : 765849 : spdk_accel_append_crc32c(struct spdk_accel_sequence **pseq, struct spdk_io_channel *ch,
1277 : : uint32_t *dst, struct iovec *iovs, uint32_t iovcnt,
1278 : : struct spdk_memory_domain *domain, void *domain_ctx,
1279 : : uint32_t seed, spdk_accel_step_cb cb_fn, void *cb_arg)
1280 : : {
1281 : 765849 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
1282 : : struct spdk_accel_task *task;
1283 : 765849 : struct spdk_accel_sequence *seq = *pseq;
1284 : :
1285 [ + + ]: 765849 : if (seq == NULL) {
1286 : 589720 : seq = accel_sequence_get(accel_ch);
1287 [ - + ]: 589720 : if (spdk_unlikely(seq == NULL)) {
1288 : 0 : return -ENOMEM;
1289 : : }
1290 : : }
1291 : :
1292 [ - + ]: 765849 : assert(seq->ch == accel_ch);
1293 : 765849 : task = accel_sequence_get_task(accel_ch, seq, cb_fn, cb_arg);
1294 [ - + ]: 765849 : if (spdk_unlikely(task == NULL)) {
1295 [ # # ]: 0 : if (*pseq == NULL) {
1296 : 0 : accel_sequence_put(seq);
1297 : : }
1298 : :
1299 : 0 : return -ENOMEM;
1300 : : }
1301 : :
1302 : 765849 : task->s.iovs = iovs;
1303 : 765849 : task->s.iovcnt = iovcnt;
1304 : 765849 : task->src_domain = domain;
1305 : 765849 : task->src_domain_ctx = domain_ctx;
1306 : 765849 : task->nbytes = accel_get_iovlen(iovs, iovcnt);
1307 : 765849 : task->crc_dst = dst;
1308 : 765849 : task->seed = seed;
1309 : 765849 : task->op_code = SPDK_ACCEL_OPC_CRC32C;
1310 : 765849 : task->dst_domain = NULL;
1311 : :
1312 : 765849 : TAILQ_INSERT_TAIL(&seq->tasks, task, seq_link);
1313 : 765849 : *pseq = seq;
1314 : :
1315 : 765849 : return 0;
1316 : : }
1317 : :
1318 : : int
1319 : 4235159 : spdk_accel_get_buf(struct spdk_io_channel *ch, uint64_t len, void **buf,
1320 : : struct spdk_memory_domain **domain, void **domain_ctx)
1321 : : {
1322 : 4235159 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
1323 : : struct accel_buffer *accel_buf;
1324 : :
1325 : 4235159 : accel_buf = accel_get_buf(accel_ch, len);
1326 [ - + ]: 4235159 : if (spdk_unlikely(accel_buf == NULL)) {
1327 : 0 : return -ENOMEM;
1328 : : }
1329 : :
1330 : : /* We always return the same pointer and identify the buffers through domain_ctx */
1331 : 4235159 : *buf = ACCEL_BUFFER_BASE;
1332 : 4235159 : *domain_ctx = accel_buf;
1333 : 4235159 : *domain = g_accel_domain;
1334 : :
1335 : 4235159 : return 0;
1336 : : }
1337 : :
1338 : : void
1339 : 4235159 : spdk_accel_put_buf(struct spdk_io_channel *ch, void *buf,
1340 : : struct spdk_memory_domain *domain, void *domain_ctx)
1341 : : {
1342 : 4235159 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
1343 : 4235159 : struct accel_buffer *accel_buf = domain_ctx;
1344 : :
1345 [ - + ]: 4235159 : assert(domain == g_accel_domain);
1346 [ - + ]: 4235159 : assert(buf == ACCEL_BUFFER_BASE);
1347 : :
1348 : 4235159 : accel_put_buf(accel_ch, accel_buf);
1349 : 4235159 : }
1350 : :
1351 : : static void
1352 : 107670022 : accel_sequence_complete_task(struct spdk_accel_sequence *seq, struct spdk_accel_task *task)
1353 : : {
1354 : 107670022 : struct accel_io_channel *ch = seq->ch;
1355 : : spdk_accel_step_cb cb_fn;
1356 : : void *cb_arg;
1357 : :
1358 [ + + ]: 107670022 : TAILQ_REMOVE(&seq->tasks, task, seq_link);
1359 : 107670022 : cb_fn = task->step_cb_fn;
1360 : 107670022 : cb_arg = task->cb_arg;
1361 : 107670022 : task->seq = NULL;
1362 [ + + + + ]: 107670022 : if (task->has_aux) {
1363 : 1762373 : SLIST_INSERT_HEAD(&ch->task_aux_data_pool, task->aux, link);
1364 : 1762373 : task->aux = NULL;
1365 : 1762373 : task->has_aux = false;
1366 : : }
1367 [ + + ]: 107670022 : STAILQ_INSERT_HEAD(&ch->task_pool, task, link);
1368 [ + + ]: 107670022 : if (cb_fn != NULL) {
1369 : 766724 : cb_fn(cb_arg);
1370 : : }
1371 : 107670022 : }
1372 : :
1373 : : static void
1374 : 101099880 : accel_sequence_complete_tasks(struct spdk_accel_sequence *seq)
1375 : : {
1376 : : struct spdk_accel_task *task;
1377 : :
1378 [ + + ]: 101099988 : while (!TAILQ_EMPTY(&seq->tasks)) {
1379 : 108 : task = TAILQ_FIRST(&seq->tasks);
1380 : 108 : accel_sequence_complete_task(seq, task);
1381 : : }
1382 : 101099880 : }
1383 : :
1384 : : static void
1385 : 101099868 : accel_sequence_complete(struct spdk_accel_sequence *seq)
1386 : : {
1387 [ - + - + ]: 101099868 : SPDK_DEBUGLOG(accel, "Completed sequence: %p with status: %d\n", seq, seq->status);
1388 : :
1389 : 101099868 : accel_update_stats(seq->ch, sequence_executed, 1);
1390 [ + + ]: 101099868 : if (spdk_unlikely(seq->status != 0)) {
1391 : 60 : accel_update_stats(seq->ch, sequence_failed, 1);
1392 : : }
1393 : :
1394 : : /* First notify all users that appended operations to this sequence */
1395 : 101099868 : accel_sequence_complete_tasks(seq);
1396 : :
1397 : : /* Then notify the user that finished the sequence */
1398 : 101099868 : seq->cb_fn(seq->cb_arg, seq->status);
1399 : :
1400 : 101099868 : accel_sequence_put(seq);
1401 : 101099868 : }
1402 : :
1403 : : static void
1404 : 1166590 : accel_update_virt_iov(struct iovec *diov, struct iovec *siov, struct accel_buffer *accel_buf)
1405 : : {
1406 : : uintptr_t offset;
1407 : :
1408 : 1166590 : offset = (uintptr_t)siov->iov_base & ACCEL_BUFFER_OFFSET_MASK;
1409 [ - + ]: 1166590 : assert(offset < accel_buf->len);
1410 : :
1411 : 1166590 : diov->iov_base = (char *)accel_buf->buf + offset;
1412 : 1166590 : diov->iov_len = siov->iov_len;
1413 : 1166590 : }
1414 : :
1415 : : static void
1416 : 583271 : accel_sequence_set_virtbuf(struct spdk_accel_sequence *seq, struct accel_buffer *buf)
1417 : : {
1418 : : struct spdk_accel_task *task;
1419 : : struct iovec *iov;
1420 : :
1421 : : /* Now that we've allocated the actual data buffer for this accel_buffer, update all tasks
1422 : : * in a sequence that were using it.
1423 : : */
1424 [ + + ]: 1749861 : TAILQ_FOREACH(task, &seq->tasks, seq_link) {
1425 [ + + + + ]: 1166590 : if (task->src_domain == g_accel_domain && task->src_domain_ctx == buf) {
1426 [ + + + - ]: 583277 : if (!task->has_aux) {
1427 : 583277 : task->aux = SLIST_FIRST(&task->accel_ch->task_aux_data_pool);
1428 [ - + ]: 583277 : assert(task->aux && "Can't allocate aux data structure");
1429 : 583277 : task->has_aux = true;
1430 : 583277 : SLIST_REMOVE_HEAD(&task->accel_ch->task_aux_data_pool, link);
1431 : : }
1432 : :
1433 : 583277 : iov = &task->aux->iovs[SPDK_ACCEL_AXU_IOV_VIRT_SRC];
1434 [ - + ]: 583277 : assert(task->s.iovcnt == 1);
1435 : 583277 : accel_update_virt_iov(iov, &task->s.iovs[0], buf);
1436 : 583277 : task->src_domain = NULL;
1437 : 583277 : task->s.iovs = iov;
1438 : : }
1439 [ + + + + ]: 1166590 : if (task->dst_domain == g_accel_domain && task->dst_domain_ctx == buf) {
1440 [ + + + + ]: 583313 : if (!task->has_aux) {
1441 : 583223 : task->aux = SLIST_FIRST(&task->accel_ch->task_aux_data_pool);
1442 [ - + ]: 583223 : assert(task->aux && "Can't allocate aux data structure");
1443 : 583223 : task->has_aux = true;
1444 : 583223 : SLIST_REMOVE_HEAD(&task->accel_ch->task_aux_data_pool, link);
1445 : : }
1446 : :
1447 : 583313 : iov = &task->aux->iovs[SPDK_ACCEL_AXU_IOV_VIRT_DST];
1448 [ - + ]: 583313 : assert(task->d.iovcnt == 1);
1449 : 583313 : accel_update_virt_iov(iov, &task->d.iovs[0], buf);
1450 : 583313 : task->dst_domain = NULL;
1451 : 583313 : task->d.iovs = iov;
1452 : : }
1453 : : }
1454 : 583271 : }
1455 : :
1456 : : static void accel_process_sequence(struct spdk_accel_sequence *seq);
1457 : :
1458 : : static void
1459 : 18 : accel_iobuf_get_virtbuf_cb(struct spdk_iobuf_entry *entry, void *buf)
1460 : : {
1461 : : struct accel_buffer *accel_buf;
1462 : :
1463 : 18 : accel_buf = SPDK_CONTAINEROF(entry, struct accel_buffer, iobuf);
1464 : :
1465 [ - + ]: 18 : assert(accel_buf->seq != NULL);
1466 [ - + ]: 18 : assert(accel_buf->buf == NULL);
1467 : 18 : accel_buf->buf = buf;
1468 : :
1469 [ - + ]: 18 : assert(accel_buf->seq->state == ACCEL_SEQUENCE_STATE_AWAIT_VIRTBUF);
1470 : 18 : accel_sequence_set_state(accel_buf->seq, ACCEL_SEQUENCE_STATE_CHECK_VIRTBUF);
1471 : 18 : accel_sequence_set_virtbuf(accel_buf->seq, accel_buf);
1472 : 18 : accel_process_sequence(accel_buf->seq);
1473 : 18 : }
1474 : :
1475 : : static bool
1476 : 1178973 : accel_sequence_alloc_buf(struct spdk_accel_sequence *seq, struct accel_buffer *buf,
1477 : : spdk_iobuf_get_cb cb_fn)
1478 : : {
1479 : 1178973 : struct accel_io_channel *ch = seq->ch;
1480 : :
1481 [ - + ]: 1178973 : assert(buf->buf == NULL);
1482 [ - + ]: 1178973 : assert(buf->seq == NULL);
1483 : :
1484 : 1178973 : buf->seq = seq;
1485 : 1178973 : buf->buf = spdk_iobuf_get(&ch->iobuf, buf->len, &buf->iobuf, cb_fn);
1486 [ + + ]: 1178973 : if (buf->buf == NULL) {
1487 : 30 : accel_update_stats(ch, retry.iobuf, 1);
1488 : 30 : return false;
1489 : : }
1490 : :
1491 : 1178943 : return true;
1492 : : }
1493 : :
1494 : : static bool
1495 : 102329925 : accel_sequence_check_virtbuf(struct spdk_accel_sequence *seq, struct spdk_accel_task *task)
1496 : : {
1497 : : /* If a task doesn't have dst/src (e.g. fill, crc32), its dst/src domain should be set to
1498 : : * NULL */
1499 [ - + ]: 102329925 : if (task->src_domain == g_accel_domain) {
1500 [ # # ]: 0 : if (!accel_sequence_alloc_buf(seq, task->src_domain_ctx,
1501 : : accel_iobuf_get_virtbuf_cb)) {
1502 : 0 : return false;
1503 : : }
1504 : :
1505 : 0 : accel_sequence_set_virtbuf(seq, task->src_domain_ctx);
1506 : : }
1507 : :
1508 [ + + ]: 102329925 : if (task->dst_domain == g_accel_domain) {
1509 [ + + ]: 583271 : if (!accel_sequence_alloc_buf(seq, task->dst_domain_ctx,
1510 : : accel_iobuf_get_virtbuf_cb)) {
1511 : 18 : return false;
1512 : : }
1513 : :
1514 : 583253 : accel_sequence_set_virtbuf(seq, task->dst_domain_ctx);
1515 : : }
1516 : :
1517 : 102329907 : return true;
1518 : : }
1519 : :
1520 : : static void
1521 : 0 : accel_sequence_get_buf_cb(struct spdk_iobuf_entry *entry, void *buf)
1522 : : {
1523 : : struct accel_buffer *accel_buf;
1524 : :
1525 : 0 : accel_buf = SPDK_CONTAINEROF(entry, struct accel_buffer, iobuf);
1526 : :
1527 [ # # ]: 0 : assert(accel_buf->seq != NULL);
1528 [ # # ]: 0 : assert(accel_buf->buf == NULL);
1529 : 0 : accel_buf->buf = buf;
1530 : :
1531 : 0 : accel_sequence_set_virtbuf(accel_buf->seq, accel_buf);
1532 : 0 : accel_buf->cb_fn(accel_buf->seq, accel_buf->cb_ctx);
1533 : 0 : }
1534 : :
1535 : : bool
1536 : 0 : spdk_accel_alloc_sequence_buf(struct spdk_accel_sequence *seq, void *buf,
1537 : : struct spdk_memory_domain *domain, void *domain_ctx,
1538 : : spdk_accel_sequence_get_buf_cb cb_fn, void *cb_ctx)
1539 : : {
1540 : 0 : struct accel_buffer *accel_buf = domain_ctx;
1541 : :
1542 [ # # ]: 0 : assert(domain == g_accel_domain);
1543 : 0 : accel_buf->cb_fn = cb_fn;
1544 : 0 : accel_buf->cb_ctx = cb_ctx;
1545 : :
1546 [ # # ]: 0 : if (!accel_sequence_alloc_buf(seq, accel_buf, accel_sequence_get_buf_cb)) {
1547 : 0 : return false;
1548 : : }
1549 : :
1550 : 0 : accel_sequence_set_virtbuf(seq, accel_buf);
1551 : :
1552 : 0 : return true;
1553 : : }
1554 : :
1555 : : struct spdk_accel_task *
1556 : 144 : spdk_accel_sequence_first_task(struct spdk_accel_sequence *seq)
1557 : : {
1558 : 144 : return TAILQ_FIRST(&seq->tasks);
1559 : : }
1560 : :
1561 : : struct spdk_accel_task *
1562 : 0 : spdk_accel_sequence_next_task(struct spdk_accel_task *task)
1563 : : {
1564 : 0 : return TAILQ_NEXT(task, seq_link);
1565 : : }
1566 : :
1567 : : static inline void
1568 : 595702 : accel_set_bounce_buffer(struct spdk_accel_bounce_buffer *bounce, struct iovec **iovs,
1569 : : uint32_t *iovcnt, struct spdk_memory_domain **domain, void **domain_ctx,
1570 : : struct accel_buffer *buf)
1571 : : {
1572 : 595702 : bounce->orig_iovs = *iovs;
1573 : 595702 : bounce->orig_iovcnt = *iovcnt;
1574 : 595702 : bounce->orig_domain = *domain;
1575 : 595702 : bounce->orig_domain_ctx = *domain_ctx;
1576 : 595702 : bounce->iov.iov_base = buf->buf;
1577 : 595702 : bounce->iov.iov_len = buf->len;
1578 : :
1579 : 595702 : *iovs = &bounce->iov;
1580 : 595702 : *iovcnt = 1;
1581 : 595702 : *domain = NULL;
1582 : 595702 : }
1583 : :
1584 : : static void
1585 : 6 : accel_iobuf_get_src_bounce_cb(struct spdk_iobuf_entry *entry, void *buf)
1586 : : {
1587 : : struct spdk_accel_task *task;
1588 : : struct accel_buffer *accel_buf;
1589 : :
1590 : 6 : accel_buf = SPDK_CONTAINEROF(entry, struct accel_buffer, iobuf);
1591 [ - + ]: 6 : assert(accel_buf->buf == NULL);
1592 : 6 : accel_buf->buf = buf;
1593 : :
1594 : 6 : task = TAILQ_FIRST(&accel_buf->seq->tasks);
1595 [ - + ]: 6 : assert(task != NULL);
1596 : :
1597 [ - + ]: 6 : assert(accel_buf->seq->state == ACCEL_SEQUENCE_STATE_AWAIT_BOUNCEBUF);
1598 : 6 : accel_sequence_set_state(accel_buf->seq, ACCEL_SEQUENCE_STATE_CHECK_BOUNCEBUF);
1599 [ - + ]: 6 : assert(task->aux);
1600 [ - + - + ]: 6 : assert(task->has_aux);
1601 : 6 : accel_set_bounce_buffer(&task->aux->bounce.s, &task->s.iovs, &task->s.iovcnt, &task->src_domain,
1602 : : &task->src_domain_ctx, accel_buf);
1603 : 6 : accel_process_sequence(accel_buf->seq);
1604 : 6 : }
1605 : :
1606 : : static void
1607 : 6 : accel_iobuf_get_dst_bounce_cb(struct spdk_iobuf_entry *entry, void *buf)
1608 : : {
1609 : : struct spdk_accel_task *task;
1610 : : struct accel_buffer *accel_buf;
1611 : :
1612 : 6 : accel_buf = SPDK_CONTAINEROF(entry, struct accel_buffer, iobuf);
1613 [ - + ]: 6 : assert(accel_buf->buf == NULL);
1614 : 6 : accel_buf->buf = buf;
1615 : :
1616 : 6 : task = TAILQ_FIRST(&accel_buf->seq->tasks);
1617 [ - + ]: 6 : assert(task != NULL);
1618 : :
1619 [ - + ]: 6 : assert(accel_buf->seq->state == ACCEL_SEQUENCE_STATE_AWAIT_BOUNCEBUF);
1620 : 6 : accel_sequence_set_state(accel_buf->seq, ACCEL_SEQUENCE_STATE_CHECK_BOUNCEBUF);
1621 [ - + ]: 6 : assert(task->aux);
1622 [ - + - + ]: 6 : assert(task->has_aux);
1623 : 6 : accel_set_bounce_buffer(&task->aux->bounce.d, &task->d.iovs, &task->d.iovcnt, &task->dst_domain,
1624 : : &task->dst_domain_ctx, accel_buf);
1625 : 6 : accel_process_sequence(accel_buf->seq);
1626 : 6 : }
1627 : :
1628 : : static int
1629 : 102329829 : accel_sequence_check_bouncebuf(struct spdk_accel_sequence *seq, struct spdk_accel_task *task)
1630 : : {
1631 : : struct accel_buffer *buf;
1632 : :
1633 [ + + ]: 102329829 : if (task->src_domain != NULL) {
1634 : : /* By the time we're here, accel buffers should have been allocated */
1635 [ - + ]: 178462 : assert(task->src_domain != g_accel_domain);
1636 : :
1637 [ + + + + ]: 178462 : if (!task->has_aux) {
1638 : 178456 : task->aux = SLIST_FIRST(&task->accel_ch->task_aux_data_pool);
1639 [ - + ]: 178456 : if (spdk_unlikely(!task->aux)) {
1640 : 0 : SPDK_ERRLOG("Can't allocate aux data structure\n");
1641 : 0 : assert(0);
1642 : : return -EAGAIN;
1643 : : }
1644 : 178456 : task->has_aux = true;
1645 : 178456 : SLIST_REMOVE_HEAD(&task->accel_ch->task_aux_data_pool, link);
1646 : : }
1647 : 178462 : buf = accel_get_buf(seq->ch, accel_get_iovlen(task->s.iovs, task->s.iovcnt));
1648 [ - + ]: 178462 : if (buf == NULL) {
1649 : 0 : SPDK_ERRLOG("Couldn't allocate buffer descriptor\n");
1650 : 0 : return -ENOMEM;
1651 : : }
1652 : :
1653 : 178462 : SLIST_INSERT_HEAD(&seq->bounce_bufs, buf, link);
1654 [ + + ]: 178462 : if (!accel_sequence_alloc_buf(seq, buf, accel_iobuf_get_src_bounce_cb)) {
1655 : 6 : return -EAGAIN;
1656 : : }
1657 : :
1658 : 178456 : accel_set_bounce_buffer(&task->aux->bounce.s, &task->s.iovs, &task->s.iovcnt,
1659 : : &task->src_domain, &task->src_domain_ctx, buf);
1660 : : }
1661 : :
1662 [ + + ]: 102329823 : if (task->dst_domain != NULL) {
1663 : : /* By the time we're here, accel buffers should have been allocated */
1664 [ - + ]: 417240 : assert(task->dst_domain != g_accel_domain);
1665 : :
1666 [ - + + + ]: 417240 : if (!task->has_aux) {
1667 : 417180 : task->aux = SLIST_FIRST(&task->accel_ch->task_aux_data_pool);
1668 [ - + ]: 417180 : if (spdk_unlikely(!task->aux)) {
1669 : 0 : SPDK_ERRLOG("Can't allocate aux data structure\n");
1670 : 0 : assert(0);
1671 : : return -EAGAIN;
1672 : : }
1673 : 417180 : task->has_aux = true;
1674 : 417180 : SLIST_REMOVE_HEAD(&task->accel_ch->task_aux_data_pool, link);
1675 : : }
1676 : 417240 : buf = accel_get_buf(seq->ch, accel_get_iovlen(task->d.iovs, task->d.iovcnt));
1677 [ - + ]: 417240 : if (buf == NULL) {
1678 : : /* The src buffer will be released when a sequence is completed */
1679 : 0 : SPDK_ERRLOG("Couldn't allocate buffer descriptor\n");
1680 : 0 : return -ENOMEM;
1681 : : }
1682 : :
1683 : 417240 : SLIST_INSERT_HEAD(&seq->bounce_bufs, buf, link);
1684 [ + + ]: 417240 : if (!accel_sequence_alloc_buf(seq, buf, accel_iobuf_get_dst_bounce_cb)) {
1685 : 6 : return -EAGAIN;
1686 : : }
1687 : :
1688 : 417234 : accel_set_bounce_buffer(&task->aux->bounce.d, &task->d.iovs, &task->d.iovcnt,
1689 : : &task->dst_domain, &task->dst_domain_ctx, buf);
1690 : : }
1691 : :
1692 : 102329817 : return 0;
1693 : : }
1694 : :
1695 : : static void
1696 : 178456 : accel_task_pull_data_cb(void *ctx, int status)
1697 : : {
1698 : 178456 : struct spdk_accel_sequence *seq = ctx;
1699 : :
1700 [ - + ]: 178456 : assert(seq->state == ACCEL_SEQUENCE_STATE_AWAIT_PULL_DATA);
1701 [ + + ]: 178456 : if (spdk_likely(status == 0)) {
1702 : 178450 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_EXEC_TASK);
1703 : : } else {
1704 : 6 : accel_sequence_set_fail(seq, status);
1705 : : }
1706 : :
1707 : 178456 : accel_process_sequence(seq);
1708 : 178456 : }
1709 : :
1710 : : static void
1711 : 178462 : accel_task_pull_data(struct spdk_accel_sequence *seq, struct spdk_accel_task *task)
1712 : : {
1713 : : int rc;
1714 : :
1715 [ - + - + ]: 178462 : assert(task->has_aux);
1716 [ - + ]: 178462 : assert(task->aux);
1717 [ - + ]: 178462 : assert(task->aux->bounce.s.orig_iovs != NULL);
1718 [ - + ]: 178462 : assert(task->aux->bounce.s.orig_domain != NULL);
1719 [ - + ]: 178462 : assert(task->aux->bounce.s.orig_domain != g_accel_domain);
1720 [ - + - + ]: 178462 : assert(!g_modules_opc[task->op_code].supports_memory_domains);
1721 : :
1722 : 713794 : rc = spdk_memory_domain_pull_data(task->aux->bounce.s.orig_domain,
1723 : 178462 : task->aux->bounce.s.orig_domain_ctx,
1724 : 356906 : task->aux->bounce.s.orig_iovs, task->aux->bounce.s.orig_iovcnt,
1725 : : task->s.iovs, task->s.iovcnt,
1726 : : accel_task_pull_data_cb, seq);
1727 [ + + ]: 178462 : if (spdk_unlikely(rc != 0)) {
1728 : 6 : SPDK_ERRLOG("Failed to pull data from memory domain: %s, rc: %d\n",
1729 : : spdk_memory_domain_get_dma_device_id(task->aux->bounce.s.orig_domain), rc);
1730 : 6 : accel_sequence_set_fail(seq, rc);
1731 : : }
1732 : 178462 : }
1733 : :
1734 : : static void
1735 : 417222 : accel_task_push_data_cb(void *ctx, int status)
1736 : : {
1737 : 417222 : struct spdk_accel_sequence *seq = ctx;
1738 : :
1739 [ - + ]: 417222 : assert(seq->state == ACCEL_SEQUENCE_STATE_AWAIT_PUSH_DATA);
1740 [ + + ]: 417222 : if (spdk_likely(status == 0)) {
1741 : 417216 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_NEXT_TASK);
1742 : : } else {
1743 : 6 : accel_sequence_set_fail(seq, status);
1744 : : }
1745 : :
1746 : 417222 : accel_process_sequence(seq);
1747 : 417222 : }
1748 : :
1749 : : static void
1750 : 417228 : accel_task_push_data(struct spdk_accel_sequence *seq, struct spdk_accel_task *task)
1751 : : {
1752 : : int rc;
1753 : :
1754 [ - + - + ]: 417228 : assert(task->has_aux);
1755 [ - + ]: 417228 : assert(task->aux);
1756 [ - + ]: 417228 : assert(task->aux->bounce.d.orig_iovs != NULL);
1757 [ - + ]: 417228 : assert(task->aux->bounce.d.orig_domain != NULL);
1758 [ - + ]: 417228 : assert(task->aux->bounce.d.orig_domain != g_accel_domain);
1759 [ - + - + ]: 417228 : assert(!g_modules_opc[task->op_code].supports_memory_domains);
1760 : :
1761 : 1668864 : rc = spdk_memory_domain_push_data(task->aux->bounce.d.orig_domain,
1762 : 417228 : task->aux->bounce.d.orig_domain_ctx,
1763 : 834440 : task->aux->bounce.d.orig_iovs, task->aux->bounce.d.orig_iovcnt,
1764 : : task->d.iovs, task->d.iovcnt,
1765 : : accel_task_push_data_cb, seq);
1766 [ + + ]: 417228 : if (spdk_unlikely(rc != 0)) {
1767 : 6 : SPDK_ERRLOG("Failed to push data to memory domain: %s, rc: %d\n",
1768 : : spdk_memory_domain_get_dma_device_id(task->aux->bounce.s.orig_domain), rc);
1769 : 6 : accel_sequence_set_fail(seq, rc);
1770 : : }
1771 : 417228 : }
1772 : :
1773 : : static void
1774 : 204025571 : accel_process_sequence(struct spdk_accel_sequence *seq)
1775 : : {
1776 : 204025571 : struct accel_io_channel *accel_ch = seq->ch;
1777 : : struct spdk_accel_task *task;
1778 : : enum accel_sequence_state state;
1779 : : int rc;
1780 : :
1781 : : /* Prevent recursive calls to this function */
1782 [ + + + + ]: 204025571 : if (spdk_unlikely(seq->in_process_sequence)) {
1783 : 444 : return;
1784 : : }
1785 : 204025127 : seq->in_process_sequence = true;
1786 : :
1787 : 204025127 : task = TAILQ_FIRST(&seq->tasks);
1788 : : do {
1789 : 410689378 : state = seq->state;
1790 [ + + + + : 410689378 : switch (state) {
+ + + + +
+ + + - ]
1791 : 102329937 : case ACCEL_SEQUENCE_STATE_INIT:
1792 [ + + ]: 102329937 : if (g_accel_driver != NULL) {
1793 : 78 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_DRIVER_EXEC_TASKS);
1794 : 78 : break;
1795 : : }
1796 : : /* Fall through */
1797 : : case ACCEL_SEQUENCE_STATE_CHECK_VIRTBUF:
1798 : 102329925 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_AWAIT_VIRTBUF);
1799 [ + + ]: 102329925 : if (!accel_sequence_check_virtbuf(seq, task)) {
1800 : : /* We couldn't allocate a buffer, wait until one is available */
1801 : 18 : break;
1802 : : }
1803 : 102329907 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_CHECK_BOUNCEBUF);
1804 : : /* Fall through */
1805 : 102329919 : case ACCEL_SEQUENCE_STATE_CHECK_BOUNCEBUF:
1806 : : /* If a module supports memory domains, we don't need to allocate bounce
1807 : : * buffers */
1808 [ + + + + ]: 102329919 : if (g_modules_opc[task->op_code].supports_memory_domains) {
1809 : 90 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_EXEC_TASK);
1810 : 90 : break;
1811 : : }
1812 : 102329829 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_AWAIT_BOUNCEBUF);
1813 : 102329829 : rc = accel_sequence_check_bouncebuf(seq, task);
1814 [ + + ]: 102329829 : if (spdk_unlikely(rc != 0)) {
1815 : : /* We couldn't allocate a buffer, wait until one is available */
1816 [ + - ]: 12 : if (rc == -EAGAIN) {
1817 : 12 : break;
1818 : : }
1819 : 0 : accel_sequence_set_fail(seq, rc);
1820 : 0 : break;
1821 : : }
1822 [ + + + + : 102329817 : if (task->has_aux && task->s.iovs == &task->aux->bounce.s.iov) {
+ + ]
1823 [ - + ]: 178462 : assert(task->aux->bounce.s.orig_iovs);
1824 : 178462 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_PULL_DATA);
1825 : 178462 : break;
1826 : : }
1827 : 102151355 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_EXEC_TASK);
1828 : : /* Fall through */
1829 : 102329895 : case ACCEL_SEQUENCE_STATE_EXEC_TASK:
1830 [ - + - + ]: 102329895 : SPDK_DEBUGLOG(accel, "Executing %s operation, sequence: %p\n",
1831 : : g_opcode_strings[task->op_code], seq);
1832 : :
1833 : 102329895 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_AWAIT_TASK);
1834 : 102329895 : rc = accel_submit_task(accel_ch, task);
1835 [ + + ]: 102329895 : if (spdk_unlikely(rc != 0)) {
1836 : 12 : SPDK_ERRLOG("Failed to submit %s operation, sequence: %p\n",
1837 : : g_opcode_strings[task->op_code], seq);
1838 : 12 : accel_sequence_set_fail(seq, rc);
1839 : : }
1840 : 102329895 : break;
1841 : 178462 : case ACCEL_SEQUENCE_STATE_PULL_DATA:
1842 : 178462 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_AWAIT_PULL_DATA);
1843 : 178462 : accel_task_pull_data(seq, task);
1844 : 178462 : break;
1845 : 102329871 : case ACCEL_SEQUENCE_STATE_COMPLETE_TASK:
1846 [ + + + + : 102329871 : if (task->has_aux && task->d.iovs == &task->aux->bounce.d.iov) {
+ + ]
1847 [ - + ]: 417228 : assert(task->aux->bounce.d.orig_iovs);
1848 : 417228 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_PUSH_DATA);
1849 : 417228 : break;
1850 : : }
1851 : 101912643 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_NEXT_TASK);
1852 : 101912643 : break;
1853 : 417228 : case ACCEL_SEQUENCE_STATE_PUSH_DATA:
1854 : 417228 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_AWAIT_PUSH_DATA);
1855 : 417228 : accel_task_push_data(seq, task);
1856 : 417228 : break;
1857 : 102329859 : case ACCEL_SEQUENCE_STATE_NEXT_TASK:
1858 : 102329859 : accel_sequence_complete_task(seq, task);
1859 : : /* Check if there are any remaining tasks */
1860 : 102329859 : task = TAILQ_FIRST(&seq->tasks);
1861 [ + + ]: 102329859 : if (task == NULL) {
1862 : : /* Immediately return here to make sure we don't touch the sequence
1863 : : * after it's completed */
1864 : 101099790 : accel_sequence_complete(seq);
1865 : 101099790 : return;
1866 : : }
1867 : 1230069 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_INIT);
1868 : 1230069 : break;
1869 : 78 : case ACCEL_SEQUENCE_STATE_DRIVER_EXEC_TASKS:
1870 [ - + ]: 78 : assert(!TAILQ_EMPTY(&seq->tasks));
1871 : :
1872 : 78 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_DRIVER_AWAIT_TASKS);
1873 : 78 : rc = g_accel_driver->execute_sequence(accel_ch->driver_channel, seq);
1874 [ + + ]: 78 : if (spdk_unlikely(rc != 0)) {
1875 : 6 : SPDK_ERRLOG("Failed to execute sequence: %p using driver: %s\n",
1876 : : seq, g_accel_driver->name);
1877 : 6 : accel_sequence_set_fail(seq, rc);
1878 : : }
1879 : 78 : break;
1880 : 66 : case ACCEL_SEQUENCE_STATE_DRIVER_COMPLETE_TASKS:
1881 : : /* Get the task again, as the driver might have completed some tasks
1882 : : * synchronously */
1883 : 66 : task = TAILQ_FIRST(&seq->tasks);
1884 [ + + ]: 66 : if (task == NULL) {
1885 : : /* Immediately return here to make sure we don't touch the sequence
1886 : : * after it's completed */
1887 : 18 : accel_sequence_complete(seq);
1888 : 18 : return;
1889 : : }
1890 : : /* We don't want to execute the next task through the driver, so we
1891 : : * explicitly omit the INIT state here */
1892 : 48 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_CHECK_VIRTBUF);
1893 : 48 : break;
1894 : 60 : case ACCEL_SEQUENCE_STATE_ERROR:
1895 : : /* Immediately return here to make sure we don't touch the sequence
1896 : : * after it's completed */
1897 [ - + ]: 60 : assert(seq->status != 0);
1898 : 60 : accel_sequence_complete(seq);
1899 : 60 : return;
1900 : 102925219 : case ACCEL_SEQUENCE_STATE_AWAIT_VIRTBUF:
1901 : : case ACCEL_SEQUENCE_STATE_AWAIT_BOUNCEBUF:
1902 : : case ACCEL_SEQUENCE_STATE_AWAIT_PULL_DATA:
1903 : : case ACCEL_SEQUENCE_STATE_AWAIT_TASK:
1904 : : case ACCEL_SEQUENCE_STATE_AWAIT_PUSH_DATA:
1905 : : case ACCEL_SEQUENCE_STATE_DRIVER_AWAIT_TASKS:
1906 : 102925219 : break;
1907 : 0 : default:
1908 : 0 : assert(0 && "bad state");
1909 : : break;
1910 : : }
1911 [ + + ]: 309589490 : } while (seq->state != state);
1912 : :
1913 : 102925219 : seq->in_process_sequence = false;
1914 : : }
1915 : :
1916 : : static void
1917 : 102329955 : accel_sequence_task_cb(void *cb_arg, int status)
1918 : : {
1919 : 102329955 : struct spdk_accel_sequence *seq = cb_arg;
1920 : 102329955 : struct spdk_accel_task *task = TAILQ_FIRST(&seq->tasks);
1921 : :
1922 [ + + - ]: 102329955 : switch (seq->state) {
1923 : 102329883 : case ACCEL_SEQUENCE_STATE_AWAIT_TASK:
1924 : 102329883 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_COMPLETE_TASK);
1925 [ + + ]: 102329883 : if (spdk_unlikely(status != 0)) {
1926 : 12 : SPDK_ERRLOG("Failed to execute %s operation, sequence: %p\n",
1927 : : g_opcode_strings[task->op_code], seq);
1928 : 12 : accel_sequence_set_fail(seq, status);
1929 : : }
1930 : :
1931 : 102329883 : accel_process_sequence(seq);
1932 : 102329883 : break;
1933 : 72 : case ACCEL_SEQUENCE_STATE_DRIVER_AWAIT_TASKS:
1934 [ - + ]: 72 : assert(g_accel_driver != NULL);
1935 : : /* Immediately remove the task from the outstanding list to make sure the next call
1936 : : * to spdk_accel_sequence_first_task() doesn't return it */
1937 : 72 : accel_sequence_complete_task(seq, task);
1938 [ + + ]: 72 : if (spdk_unlikely(status != 0)) {
1939 : 6 : SPDK_ERRLOG("Failed to execute %s operation, sequence: %p through "
1940 : : "driver: %s\n", g_opcode_strings[task->op_code], seq,
1941 : : g_accel_driver->name);
1942 : : /* Update status without using accel_sequence_set_fail() to avoid changing
1943 : : * seq's state to ERROR until driver calls spdk_accel_sequence_continue() */
1944 : 6 : seq->status = status;
1945 : : }
1946 : 72 : break;
1947 : 0 : default:
1948 : 0 : assert(0 && "bad state");
1949 : : break;
1950 : : }
1951 : 102329955 : }
1952 : :
1953 : : void
1954 : 72 : spdk_accel_sequence_continue(struct spdk_accel_sequence *seq)
1955 : : {
1956 [ - + ]: 72 : assert(g_accel_driver != NULL);
1957 [ - + ]: 72 : assert(seq->state == ACCEL_SEQUENCE_STATE_DRIVER_AWAIT_TASKS);
1958 : :
1959 [ + + ]: 72 : if (spdk_likely(seq->status == 0)) {
1960 : 66 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_DRIVER_COMPLETE_TASKS);
1961 : : } else {
1962 : 6 : accel_sequence_set_state(seq, ACCEL_SEQUENCE_STATE_ERROR);
1963 : : }
1964 : :
1965 : 72 : accel_process_sequence(seq);
1966 : 72 : }
1967 : :
1968 : : static bool
1969 : 5340013 : accel_compare_iovs(struct iovec *iova, uint32_t iovacnt, struct iovec *iovb, uint32_t iovbcnt)
1970 : : {
1971 : : /* For now, just do a dumb check that the iovecs arrays are exactly the same */
1972 [ - + ]: 5340013 : if (iovacnt != iovbcnt) {
1973 : 0 : return false;
1974 : : }
1975 : :
1976 [ - + - + ]: 5340013 : return memcmp(iova, iovb, sizeof(*iova) * iovacnt) == 0;
1977 : : }
1978 : :
1979 : : static bool
1980 : 3620570 : accel_task_set_dstbuf(struct spdk_accel_task *task, struct spdk_accel_task *next)
1981 : : {
1982 : : struct spdk_accel_task *prev;
1983 : :
1984 [ + + - ]: 3620570 : switch (task->op_code) {
1985 : 3620546 : case SPDK_ACCEL_OPC_DECOMPRESS:
1986 : : case SPDK_ACCEL_OPC_FILL:
1987 : : case SPDK_ACCEL_OPC_ENCRYPT:
1988 : : case SPDK_ACCEL_OPC_DECRYPT:
1989 [ - + ]: 3620546 : if (task->dst_domain != next->src_domain) {
1990 : 0 : return false;
1991 : : }
1992 [ + + ]: 3620546 : if (!accel_compare_iovs(task->d.iovs, task->d.iovcnt,
1993 : : next->s.iovs, next->s.iovcnt)) {
1994 : 6 : return false;
1995 : : }
1996 : 3620540 : task->d.iovs = next->d.iovs;
1997 : 3620540 : task->d.iovcnt = next->d.iovcnt;
1998 : 3620540 : task->dst_domain = next->dst_domain;
1999 : 3620540 : task->dst_domain_ctx = next->dst_domain_ctx;
2000 : 3620540 : break;
2001 : 24 : case SPDK_ACCEL_OPC_CRC32C:
2002 : : /* crc32 is special, because it doesn't have a dst buffer */
2003 [ - + ]: 24 : if (task->src_domain != next->src_domain) {
2004 : 0 : return false;
2005 : : }
2006 [ + + ]: 24 : if (!accel_compare_iovs(task->s.iovs, task->s.iovcnt,
2007 : : next->s.iovs, next->s.iovcnt)) {
2008 : 6 : return false;
2009 : : }
2010 : : /* We can only change crc32's buffer if we can change previous task's buffer */
2011 : 18 : prev = TAILQ_PREV(task, accel_sequence_tasks, seq_link);
2012 [ + + ]: 18 : if (prev == NULL) {
2013 : 6 : return false;
2014 : : }
2015 [ - + ]: 12 : if (!accel_task_set_dstbuf(prev, next)) {
2016 : 0 : return false;
2017 : : }
2018 : 12 : task->s.iovs = next->d.iovs;
2019 : 12 : task->s.iovcnt = next->d.iovcnt;
2020 : 12 : task->src_domain = next->dst_domain;
2021 : 12 : task->src_domain_ctx = next->dst_domain_ctx;
2022 : 12 : break;
2023 : 0 : default:
2024 : 0 : return false;
2025 : : }
2026 : :
2027 : 3620552 : return true;
2028 : : }
2029 : :
2030 : : static void
2031 : 6511430 : accel_sequence_merge_tasks(struct spdk_accel_sequence *seq, struct spdk_accel_task *task,
2032 : : struct spdk_accel_task **next_task)
2033 : : {
2034 : 6511430 : struct spdk_accel_task *next = *next_task;
2035 : :
2036 [ + + - ]: 6511430 : switch (task->op_code) {
2037 : 1719449 : case SPDK_ACCEL_OPC_COPY:
2038 : : /* We only allow changing src of operations that actually have a src, e.g. we never
2039 : : * do it for fill. Theoretically, it is possible, but we'd have to be careful to
2040 : : * change the src of the operation after fill (which in turn could also be a fill).
2041 : : * So, for the sake of simplicity, skip this type of operations for now.
2042 : : */
2043 [ + + ]: 1719449 : if (next->op_code != SPDK_ACCEL_OPC_DECOMPRESS &&
2044 [ + + ]: 1719417 : next->op_code != SPDK_ACCEL_OPC_COPY &&
2045 [ + + ]: 1719411 : next->op_code != SPDK_ACCEL_OPC_ENCRYPT &&
2046 [ + + ]: 1719395 : next->op_code != SPDK_ACCEL_OPC_DECRYPT &&
2047 [ + + ]: 12 : next->op_code != SPDK_ACCEL_OPC_CRC32C) {
2048 : 6 : break;
2049 : : }
2050 [ - + ]: 1719443 : if (task->dst_domain != next->src_domain) {
2051 : 0 : break;
2052 : : }
2053 [ - + ]: 1719443 : if (!accel_compare_iovs(task->d.iovs, task->d.iovcnt,
2054 : : next->s.iovs, next->s.iovcnt)) {
2055 : 0 : break;
2056 : : }
2057 : 1719443 : next->s.iovs = task->s.iovs;
2058 : 1719443 : next->s.iovcnt = task->s.iovcnt;
2059 : 1719443 : next->src_domain = task->src_domain;
2060 : 1719443 : next->src_domain_ctx = task->src_domain_ctx;
2061 : 1719443 : accel_sequence_complete_task(seq, task);
2062 : 1719443 : break;
2063 : 4791981 : case SPDK_ACCEL_OPC_DECOMPRESS:
2064 : : case SPDK_ACCEL_OPC_FILL:
2065 : : case SPDK_ACCEL_OPC_ENCRYPT:
2066 : : case SPDK_ACCEL_OPC_DECRYPT:
2067 : : case SPDK_ACCEL_OPC_CRC32C:
2068 : : /* We can only merge tasks when one of them is a copy */
2069 [ + + ]: 4791981 : if (next->op_code != SPDK_ACCEL_OPC_COPY) {
2070 : 1171423 : break;
2071 : : }
2072 [ + + ]: 3620558 : if (!accel_task_set_dstbuf(task, next)) {
2073 : 18 : break;
2074 : : }
2075 : : /* We're removing next_task from the tasks queue, so we need to update its pointer,
2076 : : * so that the TAILQ_FOREACH_SAFE() loop below works correctly */
2077 : 3620540 : *next_task = TAILQ_NEXT(next, seq_link);
2078 : 3620540 : accel_sequence_complete_task(seq, next);
2079 : 3620540 : break;
2080 : 0 : default:
2081 : 0 : assert(0 && "bad opcode");
2082 : : break;
2083 : : }
2084 : 6511430 : }
2085 : :
2086 : : void
2087 : 101099868 : spdk_accel_sequence_finish(struct spdk_accel_sequence *seq,
2088 : : spdk_accel_completion_cb cb_fn, void *cb_arg)
2089 : : {
2090 : 54311101 : struct spdk_accel_task *task, *next;
2091 : :
2092 : : /* Try to remove any copy operations if possible */
2093 [ + + ]: 107611298 : TAILQ_FOREACH_SAFE(task, &seq->tasks, seq_link, next) {
2094 [ + + ]: 104049452 : if (next == NULL) {
2095 : 97538022 : break;
2096 : : }
2097 : 6511430 : accel_sequence_merge_tasks(seq, task, &next);
2098 : : }
2099 : :
2100 : 101099868 : seq->cb_fn = cb_fn;
2101 : 101099868 : seq->cb_arg = cb_arg;
2102 : :
2103 : 101099868 : accel_process_sequence(seq);
2104 : 101099868 : }
2105 : :
2106 : : void
2107 : 51069284 : spdk_accel_sequence_reverse(struct spdk_accel_sequence *seq)
2108 : : {
2109 : 51069284 : struct accel_sequence_tasks tasks = TAILQ_HEAD_INITIALIZER(tasks);
2110 : : struct spdk_accel_task *task;
2111 : :
2112 [ + - - + ]: 51069284 : TAILQ_SWAP(&tasks, &seq->tasks, spdk_accel_task, seq_link);
2113 : :
2114 [ + + ]: 104445897 : while (!TAILQ_EMPTY(&tasks)) {
2115 : 53376613 : task = TAILQ_FIRST(&tasks);
2116 [ + + ]: 53376613 : TAILQ_REMOVE(&tasks, task, seq_link);
2117 [ + + ]: 53376613 : TAILQ_INSERT_HEAD(&seq->tasks, task, seq_link);
2118 : : }
2119 : 51069284 : }
2120 : :
2121 : : void
2122 : 636884 : spdk_accel_sequence_abort(struct spdk_accel_sequence *seq)
2123 : : {
2124 [ + + ]: 636884 : if (seq == NULL) {
2125 : 636872 : return;
2126 : : }
2127 : :
2128 : 12 : accel_sequence_complete_tasks(seq);
2129 : 12 : accel_sequence_put(seq);
2130 : : }
2131 : :
2132 : : struct spdk_memory_domain *
2133 : 163977 : spdk_accel_get_memory_domain(void)
2134 : : {
2135 : 163977 : return g_accel_domain;
2136 : : }
2137 : :
2138 : : static struct spdk_accel_module_if *
2139 : 6171 : _module_find_by_name(const char *name)
2140 : : {
2141 : 6171 : struct spdk_accel_module_if *accel_module = NULL;
2142 : :
2143 [ + + ]: 9413 : TAILQ_FOREACH(accel_module, &spdk_accel_module_list, tailq) {
2144 [ + + - + : 3318 : if (strcmp(name, accel_module->name) == 0) {
+ + ]
2145 : 76 : break;
2146 : : }
2147 : : }
2148 : :
2149 : 6171 : return accel_module;
2150 : : }
2151 : :
2152 : : static inline struct spdk_accel_crypto_key *
2153 : 262 : _accel_crypto_key_get(const char *name)
2154 : : {
2155 : : struct spdk_accel_crypto_key *key;
2156 : :
2157 [ - + ]: 262 : assert(spdk_spin_held(&g_keyring_spin));
2158 : :
2159 [ + + ]: 538 : TAILQ_FOREACH(key, &g_keyring, link) {
2160 [ + + - + : 414 : if (strcmp(name, key->param.key_name) == 0) {
+ + ]
2161 : 138 : return key;
2162 : : }
2163 : : }
2164 : :
2165 : 124 : return NULL;
2166 : : }
2167 : :
2168 : : static void
2169 : 119 : accel_crypto_key_free_mem(struct spdk_accel_crypto_key *key)
2170 : : {
2171 [ + - ]: 119 : if (key->param.hex_key) {
2172 : 119 : spdk_memset_s(key->param.hex_key, key->key_size * 2, 0, key->key_size * 2);
2173 : 119 : free(key->param.hex_key);
2174 : : }
2175 [ + + ]: 119 : if (key->param.hex_key2) {
2176 : 59 : spdk_memset_s(key->param.hex_key2, key->key2_size * 2, 0, key->key2_size * 2);
2177 : 59 : free(key->param.hex_key2);
2178 : : }
2179 : 119 : free(key->param.tweak_mode);
2180 : 119 : free(key->param.key_name);
2181 : 119 : free(key->param.cipher);
2182 [ + - ]: 119 : if (key->key) {
2183 : 119 : spdk_memset_s(key->key, key->key_size, 0, key->key_size);
2184 : 119 : free(key->key);
2185 : : }
2186 [ + + ]: 119 : if (key->key2) {
2187 : 59 : spdk_memset_s(key->key2, key->key2_size, 0, key->key2_size);
2188 : 59 : free(key->key2);
2189 : : }
2190 : 119 : free(key);
2191 : 119 : }
2192 : :
2193 : : static void
2194 : 119 : accel_crypto_key_destroy_unsafe(struct spdk_accel_crypto_key *key)
2195 : : {
2196 [ - + ]: 119 : assert(key->module_if);
2197 [ - + ]: 119 : assert(key->module_if->crypto_key_deinit);
2198 : :
2199 : 119 : key->module_if->crypto_key_deinit(key);
2200 : 119 : accel_crypto_key_free_mem(key);
2201 : 119 : }
2202 : :
2203 : : /*
2204 : : * This function mitigates a timing side channel which could be caused by using strcmp()
2205 : : * Please refer to chapter "Mitigating Information Leakage Based on Variable Timing" in
2206 : : * the article [1] for more details
2207 : : * [1] https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/secure-coding/mitigate-timing-side-channel-crypto-implementation.html
2208 : : */
2209 : : static bool
2210 : 59 : accel_aes_xts_keys_equal(const char *k1, size_t k1_len, const char *k2, size_t k2_len)
2211 : : {
2212 : : size_t i;
2213 : 59 : volatile size_t x = k1_len ^ k2_len;
2214 : :
2215 [ + + ]: 1003 : for (i = 0; ((i < k1_len) & (i < k2_len)); i++) {
2216 : 944 : x |= k1[i] ^ k2[i];
2217 : : }
2218 : :
2219 : 59 : return x == 0;
2220 : : }
2221 : :
2222 : : static const char *g_tweak_modes[] = {
2223 : : [SPDK_ACCEL_CRYPTO_TWEAK_MODE_SIMPLE_LBA] = "SIMPLE_LBA",
2224 : : [SPDK_ACCEL_CRYPTO_TWEAK_MODE_JOIN_NEG_LBA_WITH_LBA] = "JOIN_NEG_LBA_WITH_LBA",
2225 : : [SPDK_ACCEL_CRYPTO_TWEAK_MODE_INCR_512_FULL_LBA] = "INCR_512_FULL_LBA",
2226 : : [SPDK_ACCEL_CRYPTO_TWEAK_MODE_INCR_512_UPPER_LBA] = "INCR_512_UPPER_LBA",
2227 : : };
2228 : :
2229 : : static const char *g_ciphers[] = {
2230 : : [SPDK_ACCEL_CIPHER_AES_CBC] = "AES_CBC",
2231 : : [SPDK_ACCEL_CIPHER_AES_XTS] = "AES_XTS",
2232 : : };
2233 : :
2234 : : int
2235 : 119 : spdk_accel_crypto_key_create(const struct spdk_accel_crypto_key_create_param *param)
2236 : : {
2237 : : struct spdk_accel_module_if *module;
2238 : : struct spdk_accel_crypto_key *key;
2239 : : size_t hex_key_size, hex_key2_size;
2240 : 119 : bool found = false;
2241 : : size_t i;
2242 : : int rc;
2243 : :
2244 [ + - + - : 119 : if (!param || !param->hex_key || !param->cipher || !param->key_name) {
+ - - + ]
2245 : 0 : return -EINVAL;
2246 : : }
2247 : :
2248 [ - + ]: 119 : if (g_modules_opc[SPDK_ACCEL_OPC_ENCRYPT].module != g_modules_opc[SPDK_ACCEL_OPC_DECRYPT].module) {
2249 : : /* hardly ever possible, but let's check and warn the user */
2250 : 0 : SPDK_ERRLOG("Different accel modules are used for encryption and decryption\n");
2251 : : }
2252 : 119 : module = g_modules_opc[SPDK_ACCEL_OPC_ENCRYPT].module;
2253 : :
2254 [ - + ]: 119 : if (!module) {
2255 : 0 : SPDK_ERRLOG("No accel module found assigned for crypto operation\n");
2256 : 0 : return -ENOENT;
2257 : : }
2258 : :
2259 [ + - - + ]: 119 : if (!module->crypto_key_init || !module->crypto_supports_cipher) {
2260 : 0 : SPDK_ERRLOG("Module %s doesn't support crypto operations\n", module->name);
2261 : 0 : return -ENOTSUP;
2262 : : }
2263 : :
2264 : 119 : key = calloc(1, sizeof(*key));
2265 [ - + ]: 119 : if (!key) {
2266 : 0 : return -ENOMEM;
2267 : : }
2268 : :
2269 [ - + ]: 119 : key->param.key_name = strdup(param->key_name);
2270 [ - + ]: 119 : if (!key->param.key_name) {
2271 : 0 : rc = -ENOMEM;
2272 : 0 : goto error;
2273 : : }
2274 : :
2275 [ + - ]: 178 : for (i = 0; i < SPDK_COUNTOF(g_ciphers); ++i) {
2276 [ - + ]: 178 : assert(g_ciphers[i]);
2277 : :
2278 [ + + - + : 178 : if (strncmp(param->cipher, g_ciphers[i], strlen(g_ciphers[i])) == 0) {
- + + + ]
2279 : 119 : key->cipher = i;
2280 : 119 : found = true;
2281 : 119 : break;
2282 : : }
2283 : : }
2284 : :
2285 [ - + ]: 119 : if (!found) {
2286 : 0 : SPDK_ERRLOG("Failed to parse cipher\n");
2287 : 0 : rc = -EINVAL;
2288 : 0 : goto error;
2289 : : }
2290 : :
2291 [ - + ]: 119 : key->param.cipher = strdup(param->cipher);
2292 [ - + ]: 119 : if (!key->param.cipher) {
2293 : 0 : rc = -ENOMEM;
2294 : 0 : goto error;
2295 : : }
2296 : :
2297 [ - + ]: 119 : hex_key_size = strnlen(param->hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
2298 [ - + ]: 119 : if (hex_key_size == SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH) {
2299 : 0 : SPDK_ERRLOG("key1 size exceeds max %d\n", SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
2300 : 0 : rc = -EINVAL;
2301 : 0 : goto error;
2302 : : }
2303 : :
2304 [ - + ]: 119 : if (hex_key_size == 0) {
2305 : 0 : SPDK_ERRLOG("key1 size cannot be 0\n");
2306 : 0 : rc = -EINVAL;
2307 : 0 : goto error;
2308 : : }
2309 : :
2310 [ - + ]: 119 : key->param.hex_key = strdup(param->hex_key);
2311 [ - + ]: 119 : if (!key->param.hex_key) {
2312 : 0 : rc = -ENOMEM;
2313 : 0 : goto error;
2314 : : }
2315 : :
2316 : 119 : key->key_size = hex_key_size / 2;
2317 : 119 : key->key = spdk_unhexlify(key->param.hex_key);
2318 [ - + ]: 119 : if (!key->key) {
2319 : 0 : SPDK_ERRLOG("Failed to unhexlify key1\n");
2320 : 0 : rc = -EINVAL;
2321 : 0 : goto error;
2322 : : }
2323 : :
2324 [ + + ]: 119 : if (param->hex_key2) {
2325 [ - + ]: 59 : hex_key2_size = strnlen(param->hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
2326 [ - + ]: 59 : if (hex_key2_size == SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH) {
2327 : 0 : SPDK_ERRLOG("key2 size exceeds max %d\n", SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
2328 : 0 : rc = -EINVAL;
2329 : 0 : goto error;
2330 : : }
2331 : :
2332 [ - + ]: 59 : if (hex_key2_size == 0) {
2333 : 0 : SPDK_ERRLOG("key2 size cannot be 0\n");
2334 : 0 : rc = -EINVAL;
2335 : 0 : goto error;
2336 : : }
2337 : :
2338 [ - + ]: 59 : key->param.hex_key2 = strdup(param->hex_key2);
2339 [ - + ]: 59 : if (!key->param.hex_key2) {
2340 : 0 : rc = -ENOMEM;
2341 : 0 : goto error;
2342 : : }
2343 : :
2344 : 59 : key->key2_size = hex_key2_size / 2;
2345 : 59 : key->key2 = spdk_unhexlify(key->param.hex_key2);
2346 [ - + ]: 59 : if (!key->key2) {
2347 : 0 : SPDK_ERRLOG("Failed to unhexlify key2\n");
2348 : 0 : rc = -EINVAL;
2349 : 0 : goto error;
2350 : : }
2351 : : }
2352 : :
2353 : 119 : key->tweak_mode = ACCEL_CRYPTO_TWEAK_MODE_DEFAULT;
2354 [ - + ]: 119 : if (param->tweak_mode) {
2355 : 0 : found = false;
2356 : :
2357 [ # # ]: 0 : key->param.tweak_mode = strdup(param->tweak_mode);
2358 [ # # ]: 0 : if (!key->param.tweak_mode) {
2359 : 0 : rc = -ENOMEM;
2360 : 0 : goto error;
2361 : : }
2362 : :
2363 [ # # ]: 0 : for (i = 0; i < SPDK_COUNTOF(g_tweak_modes); ++i) {
2364 [ # # ]: 0 : assert(g_tweak_modes[i]);
2365 : :
2366 [ # # # # : 0 : if (strncmp(param->tweak_mode, g_tweak_modes[i], strlen(g_tweak_modes[i])) == 0) {
# # # # ]
2367 : 0 : key->tweak_mode = i;
2368 : 0 : found = true;
2369 : 0 : break;
2370 : : }
2371 : : }
2372 : :
2373 [ # # ]: 0 : if (!found) {
2374 : 0 : SPDK_ERRLOG("Failed to parse tweak mode\n");
2375 : 0 : rc = -EINVAL;
2376 : 0 : goto error;
2377 : : }
2378 : : }
2379 : :
2380 [ + + + - ]: 119 : if ((!module->crypto_supports_tweak_mode && key->tweak_mode != ACCEL_CRYPTO_TWEAK_MODE_DEFAULT) ||
2381 [ + + - + ]: 119 : (module->crypto_supports_tweak_mode && !module->crypto_supports_tweak_mode(key->tweak_mode))) {
2382 : 0 : SPDK_ERRLOG("Module %s doesn't support %s tweak mode\n", module->name,
2383 : : g_tweak_modes[key->tweak_mode]);
2384 : 0 : rc = -EINVAL;
2385 : 0 : goto error;
2386 : : }
2387 : :
2388 [ - + ]: 119 : if (!module->crypto_supports_cipher(key->cipher, key->key_size)) {
2389 : 0 : SPDK_ERRLOG("Module %s doesn't support %s cipher with %zu key size\n", module->name,
2390 : : g_ciphers[key->cipher], key->key_size);
2391 : 0 : rc = -EINVAL;
2392 : 0 : goto error;
2393 : : }
2394 : :
2395 [ + + ]: 119 : if (key->cipher == SPDK_ACCEL_CIPHER_AES_XTS) {
2396 [ - + ]: 59 : if (!key->key2) {
2397 : 0 : SPDK_ERRLOG("%s key2 is missing\n", g_ciphers[key->cipher]);
2398 : 0 : rc = -EINVAL;
2399 : 0 : goto error;
2400 : : }
2401 : :
2402 [ - + ]: 59 : if (key->key_size != key->key2_size) {
2403 : 0 : SPDK_ERRLOG("%s key size %zu is not equal to key2 size %zu\n", g_ciphers[key->cipher],
2404 : : key->key_size,
2405 : : key->key2_size);
2406 : 0 : rc = -EINVAL;
2407 : 0 : goto error;
2408 : : }
2409 : :
2410 [ - + ]: 59 : if (accel_aes_xts_keys_equal(key->key, key->key_size, key->key2, key->key2_size)) {
2411 : 0 : SPDK_ERRLOG("%s identical keys are not secure\n", g_ciphers[key->cipher]);
2412 : 0 : rc = -EINVAL;
2413 : 0 : goto error;
2414 : : }
2415 : : }
2416 : :
2417 [ + + ]: 119 : if (key->cipher == SPDK_ACCEL_CIPHER_AES_CBC) {
2418 [ - + ]: 60 : if (key->key2_size) {
2419 : 0 : SPDK_ERRLOG("%s doesn't use key2\n", g_ciphers[key->cipher]);
2420 : 0 : rc = -EINVAL;
2421 : 0 : goto error;
2422 : : }
2423 : : }
2424 : :
2425 : 119 : key->module_if = module;
2426 : :
2427 : 119 : spdk_spin_lock(&g_keyring_spin);
2428 [ - + ]: 119 : if (_accel_crypto_key_get(param->key_name)) {
2429 : 0 : rc = -EEXIST;
2430 : : } else {
2431 : 119 : rc = module->crypto_key_init(key);
2432 [ - + ]: 119 : if (rc) {
2433 : 0 : SPDK_ERRLOG("Module %s failed to initialize crypto key\n", module->name);
2434 : : } else {
2435 : 119 : TAILQ_INSERT_TAIL(&g_keyring, key, link);
2436 : : }
2437 : : }
2438 : 119 : spdk_spin_unlock(&g_keyring_spin);
2439 : :
2440 [ - + ]: 119 : if (rc) {
2441 : 0 : goto error;
2442 : : }
2443 : :
2444 : 119 : return 0;
2445 : :
2446 : 0 : error:
2447 : 0 : accel_crypto_key_free_mem(key);
2448 : 0 : return rc;
2449 : : }
2450 : :
2451 : : int
2452 : 10 : spdk_accel_crypto_key_destroy(struct spdk_accel_crypto_key *key)
2453 : : {
2454 [ + - - + ]: 10 : if (!key || !key->module_if) {
2455 : 0 : return -EINVAL;
2456 : : }
2457 : :
2458 : 10 : spdk_spin_lock(&g_keyring_spin);
2459 [ - + ]: 10 : if (!_accel_crypto_key_get(key->param.key_name)) {
2460 : 0 : spdk_spin_unlock(&g_keyring_spin);
2461 : 0 : return -ENOENT;
2462 : : }
2463 [ - + ]: 10 : TAILQ_REMOVE(&g_keyring, key, link);
2464 : 10 : spdk_spin_unlock(&g_keyring_spin);
2465 : :
2466 : 10 : accel_crypto_key_destroy_unsafe(key);
2467 : :
2468 : 10 : return 0;
2469 : : }
2470 : :
2471 : : struct spdk_accel_crypto_key *
2472 : 133 : spdk_accel_crypto_key_get(const char *name)
2473 : : {
2474 : : struct spdk_accel_crypto_key *key;
2475 : :
2476 : 133 : spdk_spin_lock(&g_keyring_spin);
2477 : 133 : key = _accel_crypto_key_get(name);
2478 : 133 : spdk_spin_unlock(&g_keyring_spin);
2479 : :
2480 : 133 : return key;
2481 : : }
2482 : :
2483 : : /* Helper function when accel modules register with the framework. */
2484 : : void
2485 : 6089 : spdk_accel_module_list_add(struct spdk_accel_module_if *accel_module)
2486 : : {
2487 : : struct spdk_accel_module_if *tmp;
2488 : :
2489 [ - + ]: 6089 : if (_module_find_by_name(accel_module->name)) {
2490 : 0 : SPDK_NOTICELOG("Module %s already registered\n", accel_module->name);
2491 : 0 : assert(false);
2492 : : return;
2493 : : }
2494 : :
2495 [ + + ]: 7080 : TAILQ_FOREACH(tmp, &spdk_accel_module_list, tailq) {
2496 [ + + ]: 3105 : if (accel_module->priority < tmp->priority) {
2497 : 2114 : break;
2498 : : }
2499 : : }
2500 : :
2501 [ + + ]: 6089 : if (tmp != NULL) {
2502 : 2114 : TAILQ_INSERT_BEFORE(tmp, accel_module, tailq);
2503 : : } else {
2504 : 3975 : TAILQ_INSERT_TAIL(&spdk_accel_module_list, accel_module, tailq);
2505 : : }
2506 : : }
2507 : :
2508 : : /* Framework level channel create callback. */
2509 : : static int
2510 : 10347 : accel_create_channel(void *io_device, void *ctx_buf)
2511 : : {
2512 : 10347 : struct accel_io_channel *accel_ch = ctx_buf;
2513 : : struct spdk_accel_task *accel_task;
2514 : : struct spdk_accel_task_aux_data *accel_task_aux;
2515 : : struct spdk_accel_sequence *seq;
2516 : : struct accel_buffer *buf;
2517 : : size_t task_size_aligned;
2518 : : uint8_t *task_mem;
2519 : 10347 : uint32_t i = 0, j;
2520 : : int rc;
2521 : :
2522 : 10347 : task_size_aligned = SPDK_ALIGN_CEIL(g_max_accel_module_size, SPDK_CACHE_LINE_SIZE);
2523 : 10347 : accel_ch->task_pool_base = aligned_alloc(SPDK_CACHE_LINE_SIZE,
2524 : 10347 : g_opts.task_count * task_size_aligned);
2525 [ - + ]: 10347 : if (!accel_ch->task_pool_base) {
2526 : 0 : return -ENOMEM;
2527 : : }
2528 [ - + ]: 10347 : memset(accel_ch->task_pool_base, 0, g_opts.task_count * task_size_aligned);
2529 : :
2530 : 10347 : accel_ch->seq_pool_base = aligned_alloc(SPDK_CACHE_LINE_SIZE,
2531 : 10347 : g_opts.sequence_count * sizeof(struct spdk_accel_sequence));
2532 [ - + ]: 10347 : if (accel_ch->seq_pool_base == NULL) {
2533 : 0 : goto err;
2534 : : }
2535 [ - + ]: 10347 : memset(accel_ch->seq_pool_base, 0, g_opts.sequence_count * sizeof(struct spdk_accel_sequence));
2536 : :
2537 : 10347 : accel_ch->task_aux_data_base = calloc(g_opts.task_count, sizeof(struct spdk_accel_task_aux_data));
2538 [ - + ]: 10347 : if (accel_ch->task_aux_data_base == NULL) {
2539 : 0 : goto err;
2540 : : }
2541 : :
2542 : 10347 : accel_ch->buf_pool_base = calloc(g_opts.buf_count, sizeof(struct accel_buffer));
2543 [ - + ]: 10347 : if (accel_ch->buf_pool_base == NULL) {
2544 : 0 : goto err;
2545 : : }
2546 : :
2547 : 10347 : STAILQ_INIT(&accel_ch->task_pool);
2548 : 10347 : SLIST_INIT(&accel_ch->task_aux_data_pool);
2549 : 10347 : SLIST_INIT(&accel_ch->seq_pool);
2550 : 10347 : SLIST_INIT(&accel_ch->buf_pool);
2551 : :
2552 : 10347 : task_mem = accel_ch->task_pool_base;
2553 [ + + ]: 21182713 : for (i = 0; i < g_opts.task_count; i++) {
2554 : 21172364 : accel_task = (struct spdk_accel_task *)task_mem;
2555 : 21172364 : accel_task->aux = NULL;
2556 : 21172364 : STAILQ_INSERT_TAIL(&accel_ch->task_pool, accel_task, link);
2557 : 21172364 : task_mem += task_size_aligned;
2558 : 21172364 : accel_task_aux = &accel_ch->task_aux_data_base[i];
2559 : 21172364 : SLIST_INSERT_HEAD(&accel_ch->task_aux_data_pool, accel_task_aux, link);
2560 : : }
2561 [ + + ]: 21201001 : for (i = 0; i < g_opts.sequence_count; i++) {
2562 : 21190652 : seq = &accel_ch->seq_pool_base[i];
2563 : 21190652 : SLIST_INSERT_HEAD(&accel_ch->seq_pool, seq, link);
2564 : : }
2565 [ + + ]: 21201001 : for (i = 0; i < g_opts.buf_count; i++) {
2566 : 21190652 : buf = &accel_ch->buf_pool_base[i];
2567 : 21190652 : SLIST_INSERT_HEAD(&accel_ch->buf_pool, buf, link);
2568 : : }
2569 : :
2570 : : /* Assign modules and get IO channels for each */
2571 [ + + ]: 155205 : for (i = 0; i < SPDK_ACCEL_OPC_LAST; i++) {
2572 : 144858 : accel_ch->module_ch[i] = g_modules_opc[i].module->get_io_channel();
2573 : : /* This can happen if idxd runs out of channels. */
2574 [ - + ]: 144858 : if (accel_ch->module_ch[i] == NULL) {
2575 : 0 : SPDK_ERRLOG("Module %s failed to get io channel\n", g_modules_opc[i].module->name);
2576 : 0 : goto err;
2577 : : }
2578 : : }
2579 : :
2580 [ - + ]: 10347 : if (g_accel_driver != NULL) {
2581 : 0 : accel_ch->driver_channel = g_accel_driver->get_io_channel();
2582 [ # # ]: 0 : if (accel_ch->driver_channel == NULL) {
2583 : 0 : SPDK_ERRLOG("Failed to get driver's IO channel\n");
2584 : 0 : goto err;
2585 : : }
2586 : : }
2587 : :
2588 : 10347 : rc = spdk_iobuf_channel_init(&accel_ch->iobuf, "accel", g_opts.small_cache_size,
2589 : : g_opts.large_cache_size);
2590 [ - + ]: 10347 : if (rc != 0) {
2591 : 0 : SPDK_ERRLOG("Failed to initialize iobuf accel channel\n");
2592 : 0 : goto err;
2593 : : }
2594 : :
2595 : 10347 : return 0;
2596 : 0 : err:
2597 [ # # ]: 0 : if (accel_ch->driver_channel != NULL) {
2598 : 0 : spdk_put_io_channel(accel_ch->driver_channel);
2599 : : }
2600 [ # # ]: 0 : for (j = 0; j < i; j++) {
2601 : 0 : spdk_put_io_channel(accel_ch->module_ch[j]);
2602 : : }
2603 : 0 : free(accel_ch->task_pool_base);
2604 : 0 : free(accel_ch->task_aux_data_base);
2605 : 0 : free(accel_ch->seq_pool_base);
2606 : 0 : free(accel_ch->buf_pool_base);
2607 : :
2608 : 0 : return -ENOMEM;
2609 : : }
2610 : :
2611 : : static void
2612 : 10431 : accel_add_stats(struct accel_stats *total, struct accel_stats *stats)
2613 : : {
2614 : : int i;
2615 : :
2616 : 10431 : total->sequence_executed += stats->sequence_executed;
2617 : 10431 : total->sequence_failed += stats->sequence_failed;
2618 : 10431 : total->retry.task += stats->retry.task;
2619 : 10431 : total->retry.sequence += stats->retry.sequence;
2620 : 10431 : total->retry.iobuf += stats->retry.iobuf;
2621 : 10431 : total->retry.bufdesc += stats->retry.bufdesc;
2622 [ + + ]: 156465 : for (i = 0; i < SPDK_ACCEL_OPC_LAST; ++i) {
2623 : 146034 : total->operations[i].executed += stats->operations[i].executed;
2624 : 146034 : total->operations[i].failed += stats->operations[i].failed;
2625 : 146034 : total->operations[i].num_bytes += stats->operations[i].num_bytes;
2626 : : }
2627 : 10431 : }
2628 : :
2629 : : /* Framework level channel destroy callback. */
2630 : : static void
2631 : 10347 : accel_destroy_channel(void *io_device, void *ctx_buf)
2632 : : {
2633 : 10347 : struct accel_io_channel *accel_ch = ctx_buf;
2634 : : int i;
2635 : :
2636 : 10347 : spdk_iobuf_channel_fini(&accel_ch->iobuf);
2637 : :
2638 [ - + ]: 10347 : if (accel_ch->driver_channel != NULL) {
2639 : 0 : spdk_put_io_channel(accel_ch->driver_channel);
2640 : : }
2641 : :
2642 [ + + ]: 155205 : for (i = 0; i < SPDK_ACCEL_OPC_LAST; i++) {
2643 [ - + ]: 144858 : assert(accel_ch->module_ch[i] != NULL);
2644 : 144858 : spdk_put_io_channel(accel_ch->module_ch[i]);
2645 : 144858 : accel_ch->module_ch[i] = NULL;
2646 : : }
2647 : :
2648 : : /* Update global stats to make sure channel's stats aren't lost after a channel is gone */
2649 : 10347 : spdk_spin_lock(&g_stats_lock);
2650 : 10347 : accel_add_stats(&g_stats, &accel_ch->stats);
2651 : 10347 : spdk_spin_unlock(&g_stats_lock);
2652 : :
2653 : 10347 : free(accel_ch->task_pool_base);
2654 : 10347 : free(accel_ch->task_aux_data_base);
2655 : 10347 : free(accel_ch->seq_pool_base);
2656 : 10347 : free(accel_ch->buf_pool_base);
2657 : 10347 : }
2658 : :
2659 : : struct spdk_io_channel *
2660 : 29645 : spdk_accel_get_io_channel(void)
2661 : : {
2662 : 29645 : return spdk_get_io_channel(&spdk_accel_module_list);
2663 : : }
2664 : :
2665 : : static int
2666 : 2882 : accel_module_initialize(void)
2667 : : {
2668 : : struct spdk_accel_module_if *accel_module, *tmp_module;
2669 : 2882 : int rc = 0, module_rc;
2670 : :
2671 [ + + ]: 8599 : TAILQ_FOREACH_SAFE(accel_module, &spdk_accel_module_list, tailq, tmp_module) {
2672 : 5717 : module_rc = accel_module->module_init();
2673 [ - + ]: 5717 : if (module_rc) {
2674 : 0 : SPDK_ERRLOG("Module %s initialization failed with %d\n", accel_module->name, module_rc);
2675 [ # # ]: 0 : TAILQ_REMOVE(&spdk_accel_module_list, accel_module, tailq);
2676 [ # # ]: 0 : if (!rc) {
2677 : 0 : rc = module_rc;
2678 : : }
2679 : : }
2680 : :
2681 [ - + - + ]: 5717 : SPDK_DEBUGLOG(accel, "Module %s initialized.\n", accel_module->name);
2682 : : }
2683 : :
2684 : 2882 : return rc;
2685 : : }
2686 : :
2687 : : static void
2688 : 40348 : accel_module_init_opcode(enum spdk_accel_opcode opcode)
2689 : : {
2690 : 40348 : struct accel_module *module = &g_modules_opc[opcode];
2691 : 40348 : struct spdk_accel_module_if *module_if = module->module;
2692 : :
2693 [ - + ]: 40348 : if (module_if->get_memory_domains != NULL) {
2694 : 0 : module->supports_memory_domains = module_if->get_memory_domains(NULL, 0) > 0;
2695 : : }
2696 : 40348 : }
2697 : :
2698 : : int
2699 : 2882 : spdk_accel_initialize(void)
2700 : : {
2701 : : enum spdk_accel_opcode op;
2702 : 2882 : struct spdk_accel_module_if *accel_module = NULL;
2703 : : int rc;
2704 : :
2705 : : /*
2706 : : * We need a unique identifier for the accel framework, so use the
2707 : : * spdk_accel_module_list address for this purpose.
2708 : : */
2709 : 2882 : spdk_io_device_register(&spdk_accel_module_list, accel_create_channel, accel_destroy_channel,
2710 : : sizeof(struct accel_io_channel), "accel");
2711 : :
2712 : 2882 : spdk_spin_init(&g_keyring_spin);
2713 : 2882 : spdk_spin_init(&g_stats_lock);
2714 : :
2715 : 2882 : rc = spdk_memory_domain_create(&g_accel_domain, SPDK_DMA_DEVICE_TYPE_ACCEL, NULL,
2716 : : "SPDK_ACCEL_DMA_DEVICE");
2717 [ - + ]: 2882 : if (rc != 0) {
2718 : 0 : SPDK_ERRLOG("Failed to create accel memory domain\n");
2719 : 0 : return rc;
2720 : : }
2721 : :
2722 : 2882 : g_modules_started = true;
2723 : 2882 : rc = accel_module_initialize();
2724 [ - + ]: 2882 : if (rc) {
2725 : 0 : return rc;
2726 : : }
2727 : :
2728 [ - + - - ]: 2882 : if (g_accel_driver != NULL && g_accel_driver->init != NULL) {
2729 : 0 : rc = g_accel_driver->init();
2730 [ # # ]: 0 : if (rc != 0) {
2731 : 0 : SPDK_ERRLOG("Failed to initialize driver %s: %s\n", g_accel_driver->name,
2732 : : spdk_strerror(-rc));
2733 : 0 : return rc;
2734 : : }
2735 : : }
2736 : :
2737 : : /* The module list is order by priority, with the highest priority modules being at the end
2738 : : * of the list. The software module should be somewhere at the beginning of the list,
2739 : : * before all HW modules.
2740 : : * NOTE: all opcodes must be supported by software in the event that no HW modules are
2741 : : * initialized to support the operation.
2742 : : */
2743 [ + + ]: 8599 : TAILQ_FOREACH(accel_module, &spdk_accel_module_list, tailq) {
2744 [ + + ]: 85755 : for (op = 0; op < SPDK_ACCEL_OPC_LAST; op++) {
2745 [ + + ]: 80038 : if (accel_module->supports_opcode(op)) {
2746 : 43460 : g_modules_opc[op].module = accel_module;
2747 [ - + - + ]: 43460 : SPDK_DEBUGLOG(accel, "OPC 0x%x now assigned to %s\n", op, accel_module->name);
2748 : : }
2749 : : }
2750 : :
2751 [ + + ]: 5717 : if (accel_module->get_ctx_size != NULL) {
2752 [ + + ]: 5693 : g_max_accel_module_size = spdk_max(g_max_accel_module_size,
2753 : : accel_module->get_ctx_size());
2754 : : }
2755 : : }
2756 : :
2757 : : /* Now lets check for overrides and apply all that exist */
2758 [ + + ]: 43230 : for (op = 0; op < SPDK_ACCEL_OPC_LAST; op++) {
2759 [ + + ]: 40348 : if (g_modules_opc_override[op] != NULL) {
2760 : 70 : accel_module = _module_find_by_name(g_modules_opc_override[op]);
2761 [ - + ]: 70 : if (accel_module == NULL) {
2762 : 0 : SPDK_ERRLOG("Invalid module name of %s\n", g_modules_opc_override[op]);
2763 : 0 : return -EINVAL;
2764 : : }
2765 [ - + ]: 70 : if (accel_module->supports_opcode(op) == false) {
2766 : 0 : SPDK_ERRLOG("Module %s does not support op code %d\n", accel_module->name, op);
2767 : 0 : return -EINVAL;
2768 : : }
2769 : 70 : g_modules_opc[op].module = accel_module;
2770 : : }
2771 : : }
2772 : :
2773 [ - + ]: 2882 : if (g_modules_opc[SPDK_ACCEL_OPC_ENCRYPT].module != g_modules_opc[SPDK_ACCEL_OPC_DECRYPT].module) {
2774 : 0 : SPDK_ERRLOG("Different accel modules are assigned to encrypt and decrypt operations");
2775 : 0 : return -EINVAL;
2776 : : }
2777 : :
2778 [ + + ]: 43230 : for (op = 0; op < SPDK_ACCEL_OPC_LAST; op++) {
2779 [ - + ]: 40348 : assert(g_modules_opc[op].module != NULL);
2780 : 40348 : accel_module_init_opcode(op);
2781 : : }
2782 : :
2783 : 2882 : rc = spdk_iobuf_register_module("accel");
2784 [ - + ]: 2882 : if (rc != 0) {
2785 : 0 : SPDK_ERRLOG("Failed to register accel iobuf module\n");
2786 : 0 : return rc;
2787 : : }
2788 : :
2789 : 2882 : return 0;
2790 : : }
2791 : :
2792 : : static void
2793 : 2882 : accel_module_finish_cb(void)
2794 : : {
2795 : 2882 : spdk_accel_fini_cb cb_fn = g_fini_cb_fn;
2796 : :
2797 : 2882 : cb_fn(g_fini_cb_arg);
2798 : 2882 : g_fini_cb_fn = NULL;
2799 : 2882 : g_fini_cb_arg = NULL;
2800 : 2882 : }
2801 : :
2802 : : static void
2803 : 14 : accel_write_overridden_opc(struct spdk_json_write_ctx *w, const char *opc_str,
2804 : : const char *module_str)
2805 : : {
2806 : 14 : spdk_json_write_object_begin(w);
2807 : 14 : spdk_json_write_named_string(w, "method", "accel_assign_opc");
2808 : 14 : spdk_json_write_named_object_begin(w, "params");
2809 : 14 : spdk_json_write_named_string(w, "opname", opc_str);
2810 : 14 : spdk_json_write_named_string(w, "module", module_str);
2811 : 14 : spdk_json_write_object_end(w);
2812 : 14 : spdk_json_write_object_end(w);
2813 : 14 : }
2814 : :
2815 : : static void
2816 : 23 : __accel_crypto_key_dump_param(struct spdk_json_write_ctx *w, struct spdk_accel_crypto_key *key)
2817 : : {
2818 : 23 : spdk_json_write_named_string(w, "name", key->param.key_name);
2819 : 23 : spdk_json_write_named_string(w, "cipher", key->param.cipher);
2820 : 23 : spdk_json_write_named_string(w, "key", key->param.hex_key);
2821 [ + + ]: 23 : if (key->param.hex_key2) {
2822 : 5 : spdk_json_write_named_string(w, "key2", key->param.hex_key2);
2823 : : }
2824 : :
2825 [ - + ]: 23 : if (key->param.tweak_mode) {
2826 : 0 : spdk_json_write_named_string(w, "tweak_mode", key->param.tweak_mode);
2827 : : }
2828 : 23 : }
2829 : :
2830 : : void
2831 : 9 : _accel_crypto_key_dump_param(struct spdk_json_write_ctx *w, struct spdk_accel_crypto_key *key)
2832 : : {
2833 : 9 : spdk_json_write_object_begin(w);
2834 : 9 : __accel_crypto_key_dump_param(w, key);
2835 : 9 : spdk_json_write_object_end(w);
2836 : 9 : }
2837 : :
2838 : : static void
2839 : 14 : _accel_crypto_key_write_config_json(struct spdk_json_write_ctx *w,
2840 : : struct spdk_accel_crypto_key *key)
2841 : : {
2842 : 14 : spdk_json_write_object_begin(w);
2843 : 14 : spdk_json_write_named_string(w, "method", "accel_crypto_key_create");
2844 : 14 : spdk_json_write_named_object_begin(w, "params");
2845 : 14 : __accel_crypto_key_dump_param(w, key);
2846 : 14 : spdk_json_write_object_end(w);
2847 : 14 : spdk_json_write_object_end(w);
2848 : 14 : }
2849 : :
2850 : : static void
2851 : 117 : accel_write_options(struct spdk_json_write_ctx *w)
2852 : : {
2853 : 117 : spdk_json_write_object_begin(w);
2854 : 117 : spdk_json_write_named_string(w, "method", "accel_set_options");
2855 : 117 : spdk_json_write_named_object_begin(w, "params");
2856 : 117 : spdk_json_write_named_uint32(w, "small_cache_size", g_opts.small_cache_size);
2857 : 117 : spdk_json_write_named_uint32(w, "large_cache_size", g_opts.large_cache_size);
2858 : 117 : spdk_json_write_named_uint32(w, "task_count", g_opts.task_count);
2859 : 117 : spdk_json_write_named_uint32(w, "sequence_count", g_opts.sequence_count);
2860 : 117 : spdk_json_write_named_uint32(w, "buf_count", g_opts.buf_count);
2861 : 117 : spdk_json_write_object_end(w);
2862 : 117 : spdk_json_write_object_end(w);
2863 : 117 : }
2864 : :
2865 : : static void
2866 : 117 : _accel_crypto_keys_write_config_json(struct spdk_json_write_ctx *w, bool full_dump)
2867 : : {
2868 : : struct spdk_accel_crypto_key *key;
2869 : :
2870 : 117 : spdk_spin_lock(&g_keyring_spin);
2871 [ + + ]: 131 : TAILQ_FOREACH(key, &g_keyring, link) {
2872 [ + - ]: 14 : if (full_dump) {
2873 : 14 : _accel_crypto_key_write_config_json(w, key);
2874 : : } else {
2875 : 0 : _accel_crypto_key_dump_param(w, key);
2876 : : }
2877 : : }
2878 : 117 : spdk_spin_unlock(&g_keyring_spin);
2879 : 117 : }
2880 : :
2881 : : void
2882 : 0 : _accel_crypto_keys_dump_param(struct spdk_json_write_ctx *w)
2883 : : {
2884 : 0 : _accel_crypto_keys_write_config_json(w, false);
2885 : 0 : }
2886 : :
2887 : : void
2888 : 117 : spdk_accel_write_config_json(struct spdk_json_write_ctx *w)
2889 : : {
2890 : : struct spdk_accel_module_if *accel_module;
2891 : : int i;
2892 : :
2893 : 117 : spdk_json_write_array_begin(w);
2894 : 117 : accel_write_options(w);
2895 : :
2896 [ + + ]: 358 : TAILQ_FOREACH(accel_module, &spdk_accel_module_list, tailq) {
2897 [ + + ]: 241 : if (accel_module->write_config_json) {
2898 : 124 : accel_module->write_config_json(w);
2899 : : }
2900 : : }
2901 [ + + ]: 1755 : for (i = 0; i < SPDK_ACCEL_OPC_LAST; i++) {
2902 [ + + ]: 1638 : if (g_modules_opc_override[i]) {
2903 : 14 : accel_write_overridden_opc(w, g_opcode_strings[i], g_modules_opc_override[i]);
2904 : : }
2905 : : }
2906 : :
2907 : 117 : _accel_crypto_keys_write_config_json(w, true);
2908 : :
2909 : 117 : spdk_json_write_array_end(w);
2910 : 117 : }
2911 : :
2912 : : void
2913 : 8599 : spdk_accel_module_finish(void)
2914 : : {
2915 [ + + ]: 8599 : if (!g_accel_module) {
2916 : 2882 : g_accel_module = TAILQ_FIRST(&spdk_accel_module_list);
2917 : : } else {
2918 : 5717 : g_accel_module = TAILQ_NEXT(g_accel_module, tailq);
2919 : : }
2920 : :
2921 [ + + ]: 8599 : if (!g_accel_module) {
2922 [ - + - - ]: 2882 : if (g_accel_driver != NULL && g_accel_driver->fini != NULL) {
2923 : 0 : g_accel_driver->fini();
2924 : : }
2925 : :
2926 : 2882 : spdk_spin_destroy(&g_keyring_spin);
2927 : 2882 : spdk_spin_destroy(&g_stats_lock);
2928 [ + - ]: 2882 : if (g_accel_domain) {
2929 : 2882 : spdk_memory_domain_destroy(g_accel_domain);
2930 : 2882 : g_accel_domain = NULL;
2931 : : }
2932 : 2882 : accel_module_finish_cb();
2933 : 2882 : return;
2934 : : }
2935 : :
2936 [ + + ]: 5717 : if (g_accel_module->module_fini) {
2937 : 5693 : spdk_thread_send_msg(spdk_get_thread(), g_accel_module->module_fini, NULL);
2938 : : } else {
2939 : 24 : spdk_accel_module_finish();
2940 : : }
2941 : : }
2942 : :
2943 : : static void
2944 : 2882 : accel_io_device_unregister_cb(void *io_device)
2945 : : {
2946 : : struct spdk_accel_crypto_key *key, *key_tmp;
2947 : : enum spdk_accel_opcode op;
2948 : :
2949 : 2882 : spdk_spin_lock(&g_keyring_spin);
2950 [ + + ]: 2991 : TAILQ_FOREACH_SAFE(key, &g_keyring, link, key_tmp) {
2951 : 109 : accel_crypto_key_destroy_unsafe(key);
2952 : : }
2953 : 2882 : spdk_spin_unlock(&g_keyring_spin);
2954 : :
2955 [ + + ]: 43230 : for (op = 0; op < SPDK_ACCEL_OPC_LAST; op++) {
2956 [ + + ]: 40348 : if (g_modules_opc_override[op] != NULL) {
2957 : 70 : free(g_modules_opc_override[op]);
2958 : 70 : g_modules_opc_override[op] = NULL;
2959 : : }
2960 : 40348 : g_modules_opc[op].module = NULL;
2961 : : }
2962 : :
2963 : 2882 : spdk_accel_module_finish();
2964 : 2882 : }
2965 : :
2966 : : void
2967 : 2882 : spdk_accel_finish(spdk_accel_fini_cb cb_fn, void *cb_arg)
2968 : : {
2969 [ - + ]: 2882 : assert(cb_fn != NULL);
2970 : :
2971 : 2882 : g_fini_cb_fn = cb_fn;
2972 : 2882 : g_fini_cb_arg = cb_arg;
2973 : :
2974 : 2882 : spdk_io_device_unregister(&spdk_accel_module_list, accel_io_device_unregister_cb);
2975 : 2882 : }
2976 : :
2977 : : static struct spdk_accel_driver *
2978 : 12 : accel_find_driver(const char *name)
2979 : : {
2980 : : struct spdk_accel_driver *driver;
2981 : :
2982 [ + + ]: 12 : TAILQ_FOREACH(driver, &g_accel_drivers, tailq) {
2983 [ + + - + : 6 : if (strcmp(driver->name, name) == 0) {
+ - ]
2984 : 6 : return driver;
2985 : : }
2986 : : }
2987 : :
2988 : 6 : return NULL;
2989 : : }
2990 : :
2991 : : int
2992 : 6 : spdk_accel_set_driver(const char *name)
2993 : : {
2994 : : struct spdk_accel_driver *driver;
2995 : :
2996 : 6 : driver = accel_find_driver(name);
2997 [ - + ]: 6 : if (driver == NULL) {
2998 : 0 : SPDK_ERRLOG("Couldn't find driver named '%s'\n", name);
2999 : 0 : return -ENODEV;
3000 : : }
3001 : :
3002 : 6 : g_accel_driver = driver;
3003 : :
3004 : 6 : return 0;
3005 : : }
3006 : :
3007 : : void
3008 : 6 : spdk_accel_driver_register(struct spdk_accel_driver *driver)
3009 : : {
3010 [ - + ]: 6 : if (accel_find_driver(driver->name)) {
3011 : 0 : SPDK_ERRLOG("Driver named '%s' has already been registered\n", driver->name);
3012 : 0 : assert(0);
3013 : : return;
3014 : : }
3015 : :
3016 : 6 : TAILQ_INSERT_TAIL(&g_accel_drivers, driver, tailq);
3017 : : }
3018 : :
3019 : : int
3020 : 191 : spdk_accel_set_opts(const struct spdk_accel_opts *opts)
3021 : : {
3022 [ - + ]: 191 : if (opts->size > sizeof(*opts)) {
3023 : 0 : return -EINVAL;
3024 : : }
3025 : :
3026 [ - + - + ]: 191 : memcpy(&g_opts, opts, opts->size);
3027 : :
3028 : 191 : return 0;
3029 : : }
3030 : :
3031 : : void
3032 : 191 : spdk_accel_get_opts(struct spdk_accel_opts *opts)
3033 : : {
3034 : 191 : size_t size = opts->size;
3035 : :
3036 [ - + ]: 191 : assert(size <= sizeof(*opts));
3037 : :
3038 [ - + - + ]: 191 : memcpy(opts, &g_opts, spdk_min(sizeof(*opts), size));
3039 : 191 : opts->size = size;
3040 : 191 : }
3041 : :
3042 : : struct accel_get_stats_ctx {
3043 : : struct accel_stats stats;
3044 : : accel_get_stats_cb cb_fn;
3045 : : void *cb_arg;
3046 : : };
3047 : :
3048 : : static void
3049 : 52 : accel_get_channel_stats_done(struct spdk_io_channel_iter *iter, int status)
3050 : : {
3051 : 52 : struct accel_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(iter);
3052 : :
3053 : 52 : ctx->cb_fn(&ctx->stats, ctx->cb_arg);
3054 : 52 : free(ctx);
3055 : 52 : }
3056 : :
3057 : : static void
3058 : 32 : accel_get_channel_stats(struct spdk_io_channel_iter *iter)
3059 : : {
3060 : 32 : struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(iter);
3061 : 32 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
3062 : 32 : struct accel_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(iter);
3063 : :
3064 : 32 : accel_add_stats(&ctx->stats, &accel_ch->stats);
3065 : 32 : spdk_for_each_channel_continue(iter, 0);
3066 : 32 : }
3067 : :
3068 : : int
3069 : 52 : accel_get_stats(accel_get_stats_cb cb_fn, void *cb_arg)
3070 : : {
3071 : : struct accel_get_stats_ctx *ctx;
3072 : :
3073 : 52 : ctx = calloc(1, sizeof(*ctx));
3074 [ - + ]: 52 : if (ctx == NULL) {
3075 : 0 : return -ENOMEM;
3076 : : }
3077 : :
3078 : 52 : spdk_spin_lock(&g_stats_lock);
3079 : 52 : accel_add_stats(&ctx->stats, &g_stats);
3080 : 52 : spdk_spin_unlock(&g_stats_lock);
3081 : :
3082 : 52 : ctx->cb_fn = cb_fn;
3083 : 52 : ctx->cb_arg = cb_arg;
3084 : :
3085 : 52 : spdk_for_each_channel(&spdk_accel_module_list, accel_get_channel_stats, ctx,
3086 : : accel_get_channel_stats_done);
3087 : :
3088 : 52 : return 0;
3089 : : }
3090 : :
3091 : : void
3092 : 1176 : spdk_accel_get_opcode_stats(struct spdk_io_channel *ch, enum spdk_accel_opcode opcode,
3093 : : struct spdk_accel_opcode_stats *stats, size_t size)
3094 : : {
3095 : 1176 : struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch);
3096 : :
3097 : : #define FIELD_OK(field) \
3098 : : offsetof(struct spdk_accel_opcode_stats, field) + sizeof(stats->field) <= size
3099 : :
3100 : : #define SET_FIELD(field, value) \
3101 : : if (FIELD_OK(field)) { \
3102 : : stats->field = value; \
3103 : : }
3104 : :
3105 [ + - ]: 1176 : SET_FIELD(executed, accel_ch->stats.operations[opcode].executed);
3106 [ + - ]: 1176 : SET_FIELD(failed, accel_ch->stats.operations[opcode].failed);
3107 [ + - ]: 1176 : SET_FIELD(num_bytes, accel_ch->stats.operations[opcode].num_bytes);
3108 : :
3109 : : #undef FIELD_OK
3110 : : #undef SET_FIELD
3111 : 1176 : }
3112 : :
3113 : : uint8_t
3114 : 684 : spdk_accel_get_buf_align(enum spdk_accel_opcode opcode,
3115 : : const struct spdk_accel_operation_exec_ctx *ctx)
3116 : : {
3117 : 684 : struct spdk_accel_module_if *module = g_modules_opc[opcode].module;
3118 : 684 : struct spdk_accel_opcode_info modinfo = {}, drvinfo = {};
3119 : :
3120 [ - + - - ]: 684 : if (g_accel_driver != NULL && g_accel_driver->get_operation_info != NULL) {
3121 : 0 : g_accel_driver->get_operation_info(opcode, ctx, &drvinfo);
3122 : : }
3123 : :
3124 [ + - ]: 684 : if (module->get_operation_info != NULL) {
3125 : 684 : module->get_operation_info(opcode, ctx, &modinfo);
3126 : : }
3127 : :
3128 : : /* If a driver is set, it'll execute most of the operations, while the rest will usually
3129 : : * fall back to accel_sw, which doesn't have any alignment requiremenets. However, to be
3130 : : * extra safe, return the max(driver, module) if a driver delegates some operations to a
3131 : : * hardware module. */
3132 : 684 : return spdk_max(modinfo.required_alignment, drvinfo.required_alignment);
3133 : : }
3134 : :
3135 : : struct spdk_accel_module_if *
3136 : 2774 : spdk_accel_get_module(const char *name)
3137 : : {
3138 : : struct spdk_accel_module_if *module;
3139 : :
3140 [ + - ]: 5548 : TAILQ_FOREACH(module, &spdk_accel_module_list, tailq) {
3141 [ + + - + : 5548 : if (strcmp(module->name, name) == 0) {
+ + ]
3142 : 2774 : return module;
3143 : : }
3144 : : }
3145 : :
3146 : 0 : return NULL;
3147 : : }
3148 : :
3149 : 3033 : SPDK_LOG_REGISTER_COMPONENT(accel)
|