xref: /spdk/module/accel/dpdk_cryptodev/accel_dpdk_cryptodev.c (revision a3ae6eaa75cd933b3c198db169c751ca335b5be7)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2018 Intel Corporation.
3  *   Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
4  *   All rights reserved.
5  */
6 
7 #include "accel_dpdk_cryptodev.h"
8 
9 #include "spdk/accel.h"
10 #include "spdk_internal/accel_module.h"
11 #include "spdk/env.h"
12 #include "spdk/likely.h"
13 #include "spdk/thread.h"
14 #include "spdk/util.h"
15 #include "spdk/log.h"
16 #include "spdk/json.h"
17 #include "spdk_internal/sgl.h"
18 
19 #include <rte_bus_vdev.h>
20 #include <rte_crypto.h>
21 #include <rte_cryptodev.h>
22 #include <rte_mbuf_dyn.h>
23 
24 /* The VF spread is the number of queue pairs between virtual functions, we use this to
25  * load balance the QAT device.
26  */
27 #define ACCEL_DPDK_CRYPTODEV_QAT_VF_SPREAD		32
28 
29 /* Max length in byte of a crypto operation */
30 #define ACCEL_DPDK_CRYPTODEV_CRYPTO_MAX_IO		(64 * 1024)
31 
32 /* This controls how many ops will be dequeued from the crypto driver in one run
33  * of the poller. It is mainly a performance knob as it effectively determines how
34  * much work the poller has to do.  However even that can vary between crypto drivers
35  * as the ACCEL_DPDK_CRYPTODEV_AESNI_MB driver for example does all the crypto work on dequeue whereas the
36  * QAT driver just dequeues what has been completed already.
37  */
38 #define ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE	64
39 
40 /* When enqueueing, we need to supply the crypto driver with an array of pointers to
41  * operation structs. As each of these can be max 512B, we can adjust the ACCEL_DPDK_CRYPTODEV_CRYPTO_MAX_IO
42  * value in conjunction with the other defines to make sure we're not using crazy amounts
43  * of memory. All of these numbers can and probably should be adjusted based on the
44  * workload. By default we'll use the worst case (smallest) block size for the
45  * minimum number of array entries. As an example, a ACCEL_DPDK_CRYPTODEV_CRYPTO_MAX_IO size of 64K with 512B
46  * blocks would give us an enqueue array size of 128.
47  */
48 #define ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE (ACCEL_DPDK_CRYPTODEV_CRYPTO_MAX_IO / 512)
49 
50 /* The number of MBUFS we need must be a power of two and to support other small IOs
51  * in addition to the limits mentioned above, we go to the next power of two. It is
52  * big number because it is one mempool for source and destination mbufs. It may
53  * need to be bigger to support multiple crypto drivers at once.
54  */
55 #define ACCEL_DPDK_CRYPTODEV_NUM_MBUFS			32768
56 #define ACCEL_DPDK_CRYPTODEV_POOL_CACHE_SIZE		256
57 #define ACCEL_DPDK_CRYPTODEV_MAX_CRYPTO_VOLUMES		128
58 #define ACCEL_DPDK_CRYPTODEV_NUM_SESSIONS		(2 * ACCEL_DPDK_CRYPTODEV_MAX_CRYPTO_VOLUMES)
59 #define ACCEL_DPDK_CRYPTODEV_SESS_MEMPOOL_CACHE_SIZE	0
60 
61 /* This is the max number of IOs we can supply to any crypto device QP at one time.
62  * It can vary between drivers.
63  */
64 #define ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS		2048
65 
66 /* At this moment DPDK descriptors allocation for mlx5 has some issues. We use 512
67  * as a compromise value between performance and the time spent for initialization. */
68 #define ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS_MLX5	512
69 
70 #define ACCEL_DPDK_CRYPTODEV_AESNI_MB_NUM_QP		64
71 
72 /* Common for suported devices. */
73 #define ACCEL_DPDK_CRYPTODEV_DEFAULT_NUM_XFORMS		2
74 #define ACCEL_DPDK_CRYPTODEV_IV_OFFSET (sizeof(struct rte_crypto_op) + \
75                 sizeof(struct rte_crypto_sym_op) + \
76                 (ACCEL_DPDK_CRYPTODEV_DEFAULT_NUM_XFORMS * \
77                  sizeof(struct rte_crypto_sym_xform)))
78 #define ACCEL_DPDK_CRYPTODEV_IV_LENGTH			16
79 #define ACCEL_DPDK_CRYPTODEV_QUEUED_OP_OFFSET (ACCEL_DPDK_CRYPTODEV_IV_OFFSET + ACCEL_DPDK_CRYPTODEV_IV_LENGTH)
80 
81 /* Driver names */
82 #define ACCEL_DPDK_CRYPTODEV_AESNI_MB	"crypto_aesni_mb"
83 #define ACCEL_DPDK_CRYPTODEV_QAT	"crypto_qat"
84 #define ACCEL_DPDK_CRYPTODEV_QAT_ASYM	"crypto_qat_asym"
85 #define ACCEL_DPDK_CRYPTODEV_MLX5	"mlx5_pci"
86 
87 /* Supported ciphers */
88 #define ACCEL_DPDK_CRYPTODEV_AES_CBC	"AES_CBC" /* QAT and ACCEL_DPDK_CRYPTODEV_AESNI_MB */
89 #define ACCEL_DPDK_CRYPTODEV_AES_XTS	"AES_XTS" /* QAT and MLX5 */
90 
91 /* Specific to AES_CBC. */
92 #define ACCEL_DPDK_CRYPTODEV_AES_CBC_KEY_LENGTH			16
93 #define ACCEL_DPDK_CRYPTODEV_AES_XTS_128_BLOCK_KEY_LENGTH	16 /* AES-XTS-128 block key size. */
94 #define ACCEL_DPDK_CRYPTODEV_AES_XTS_256_BLOCK_KEY_LENGTH	32 /* AES-XTS-256 block key size. */
95 #define ACCEL_DPDK_CRYPTODEV_AES_XTS_512_BLOCK_KEY_LENGTH	64 /* AES-XTS-512 block key size. */
96 
97 #define ACCEL_DPDK_CRYPTODEV_AES_XTS_TWEAK_KEY_LENGTH		16 /* XTS part key size is always 128 bit. */
98 
99 /* Used to store IO context in mbuf */
100 static const struct rte_mbuf_dynfield rte_mbuf_dynfield_io_context = {
101 	.name = "context_accel_dpdk_cryptodev",
102 	.size = sizeof(uint64_t),
103 	.align = __alignof__(uint64_t),
104 	.flags = 0,
105 };
106 
107 struct accel_dpdk_cryptodev_device;
108 
109 enum accel_dpdk_cryptodev_driver_type {
110 	ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB = 0,
111 	ACCEL_DPDK_CRYPTODEV_DRIVER_QAT,
112 	ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI,
113 	ACCEL_DPDK_CRYPTODEV_DRIVER_LAST
114 };
115 
116 enum accel_dpdk_crypto_dev_cipher_type {
117 	ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC,
118 	ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS
119 };
120 
121 struct accel_dpdk_cryptodev_qp {
122 	struct accel_dpdk_cryptodev_device *device;	/* ptr to crypto device */
123 	uint32_t num_enqueued_ops;	/* Used to decide whether to poll the qp or not */
124 	uint8_t qp; /* queue identifier */
125 	bool in_use; /* whether this node is in use or not */
126 	uint8_t index; /* used by QAT to load balance placement of qpairs */
127 	TAILQ_ENTRY(accel_dpdk_cryptodev_qp) link;
128 };
129 
130 struct accel_dpdk_cryptodev_device {
131 	enum accel_dpdk_cryptodev_driver_type type;
132 	struct rte_cryptodev_info cdev_info; /* includes DPDK device friendly name */
133 	uint32_t qp_desc_nr; /* max number of qp descriptors to be enqueued in burst */
134 	uint8_t cdev_id; /* identifier for the device */
135 	TAILQ_HEAD(, accel_dpdk_cryptodev_qp) qpairs;
136 	TAILQ_ENTRY(accel_dpdk_cryptodev_device) link;
137 };
138 
139 struct accel_dpdk_cryptodev_key_handle {
140 	struct accel_dpdk_cryptodev_device *device;
141 	TAILQ_ENTRY(accel_dpdk_cryptodev_key_handle) link;
142 	struct rte_cryptodev_sym_session *session_encrypt;	/* encryption session for this key */
143 	struct rte_cryptodev_sym_session *session_decrypt;	/* decryption session for this key */
144 	struct rte_crypto_sym_xform cipher_xform;		/* crypto control struct for this key */
145 };
146 
147 struct accel_dpdk_cryptodev_key_priv {
148 	enum accel_dpdk_cryptodev_driver_type driver;
149 	enum accel_dpdk_crypto_dev_cipher_type cipher;
150 	char *xts_key;
151 	TAILQ_HEAD(, accel_dpdk_cryptodev_key_handle) dev_keys;
152 };
153 
154 /* For queueing up crypto operations that we can't submit for some reason */
155 struct accel_dpdk_cryptodev_queued_op {
156 	struct accel_dpdk_cryptodev_qp *qp;
157 	struct rte_crypto_op *crypto_op;
158 	struct accel_dpdk_cryptodev_task *task;
159 	TAILQ_ENTRY(accel_dpdk_cryptodev_queued_op) link;
160 };
161 #define ACCEL_DPDK_CRYPTODEV_QUEUED_OP_LENGTH (sizeof(struct accel_dpdk_cryptodev_queued_op))
162 
163 /* The crypto channel struct. It is allocated and freed on my behalf by the io channel code.
164  * We store things in here that are needed on per thread basis like the base_channel for this thread,
165  * and the poller for this thread.
166  */
167 struct accel_dpdk_cryptodev_io_channel {
168 	/* completion poller */
169 	struct spdk_poller *poller;
170 	/* Array of qpairs for each available device. The specific device will be selected depending on the crypto key */
171 	struct accel_dpdk_cryptodev_qp *device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_LAST];
172 	/* queued for re-submission to CryptoDev */
173 	TAILQ_HEAD(, accel_dpdk_cryptodev_queued_op) queued_cry_ops;
174 };
175 
176 struct accel_dpdk_cryptodev_task {
177 	struct spdk_accel_task base;
178 	uint32_t cryop_cnt_remaining;
179 	bool is_failed;
180 	TAILQ_ENTRY(accel_dpdk_cryptodev_task) link;
181 };
182 
183 /* Shared mempools between all devices on this system */
184 static struct rte_mempool *g_session_mp = NULL;
185 static struct rte_mempool *g_session_mp_priv = NULL;
186 static struct rte_mempool *g_mbuf_mp = NULL;            /* mbuf mempool */
187 static int g_mbuf_offset;
188 static struct rte_mempool *g_crypto_op_mp = NULL;	/* crypto operations, must be rte* mempool */
189 
190 static struct rte_mbuf_ext_shared_info g_shinfo = {};   /* used by DPDK mbuf macro */
191 
192 static uint8_t g_qat_total_qp = 0;
193 static uint8_t g_next_qat_index;
194 
195 static const char *g_driver_names[] = {
196 	[ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB]	= ACCEL_DPDK_CRYPTODEV_AESNI_MB,
197 	[ACCEL_DPDK_CRYPTODEV_DRIVER_QAT]	= ACCEL_DPDK_CRYPTODEV_QAT,
198 	[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI]	= ACCEL_DPDK_CRYPTODEV_MLX5
199 };
200 static const char *g_cipher_names[] = {
201 	[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC]	= ACCEL_DPDK_CRYPTODEV_AES_CBC,
202 	[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS]	= ACCEL_DPDK_CRYPTODEV_AES_XTS,
203 };
204 
205 static enum accel_dpdk_cryptodev_driver_type g_dpdk_cryptodev_driver =
206 	ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB;
207 
208 /* Global list of all crypto devices */
209 static TAILQ_HEAD(, accel_dpdk_cryptodev_device) g_crypto_devices = TAILQ_HEAD_INITIALIZER(
210 			g_crypto_devices);
211 static pthread_mutex_t g_device_lock = PTHREAD_MUTEX_INITIALIZER;
212 
213 static struct spdk_accel_module_if g_accel_dpdk_cryptodev_module;
214 
215 void
216 accel_dpdk_cryptodev_enable(void)
217 {
218 	spdk_accel_module_list_add(&g_accel_dpdk_cryptodev_module);
219 }
220 
221 int
222 accel_dpdk_cryptodev_set_driver(const char *driver_name)
223 {
224 	if (strcmp(driver_name, ACCEL_DPDK_CRYPTODEV_QAT) == 0) {
225 		g_dpdk_cryptodev_driver = ACCEL_DPDK_CRYPTODEV_DRIVER_QAT;
226 	} else if (strcmp(driver_name, ACCEL_DPDK_CRYPTODEV_AESNI_MB) == 0) {
227 		g_dpdk_cryptodev_driver = ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB;
228 	} else if (strcmp(driver_name, ACCEL_DPDK_CRYPTODEV_MLX5) == 0) {
229 		g_dpdk_cryptodev_driver = ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI;
230 	} else {
231 		SPDK_ERRLOG("Unsupported driver %s\n", driver_name);
232 		return -EINVAL;
233 	}
234 
235 	SPDK_NOTICELOG("Using driver %s\n", driver_name);
236 
237 	return 0;
238 }
239 
240 const char *
241 accel_dpdk_cryptodev_get_driver(void)
242 {
243 	return g_driver_names[g_dpdk_cryptodev_driver];
244 }
245 
246 static void
247 cancel_queued_crypto_ops(struct accel_dpdk_cryptodev_io_channel *crypto_ch,
248 			 struct accel_dpdk_cryptodev_task *task)
249 {
250 	struct rte_mbuf *mbufs_to_free[2 * ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE];
251 	struct rte_crypto_op *cancelled_ops[ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE];
252 	struct accel_dpdk_cryptodev_queued_op *op_to_cancel, *tmp_op;
253 	struct rte_crypto_op *crypto_op;
254 	int num_mbufs = 0, num_dequeued_ops = 0;
255 
256 	/* Remove all ops from the failed IO. Since we don't know the
257 	 * order we have to check them all. */
258 	TAILQ_FOREACH_SAFE(op_to_cancel, &crypto_ch->queued_cry_ops, link, tmp_op) {
259 		/* Checking if this is our op. One IO contains multiple ops. */
260 		if (task == op_to_cancel->task) {
261 			crypto_op = op_to_cancel->crypto_op;
262 			TAILQ_REMOVE(&crypto_ch->queued_cry_ops, op_to_cancel, link);
263 
264 			/* Populating lists for freeing mbufs and ops. */
265 			mbufs_to_free[num_mbufs++] = (void *)crypto_op->sym->m_src;
266 			if (crypto_op->sym->m_dst) {
267 				mbufs_to_free[num_mbufs++] = (void *)crypto_op->sym->m_dst;
268 			}
269 			cancelled_ops[num_dequeued_ops++] = crypto_op;
270 		}
271 	}
272 
273 	/* Now bulk free both mbufs and crypto operations. */
274 	if (num_dequeued_ops > 0) {
275 		rte_mempool_put_bulk(g_crypto_op_mp, (void **)cancelled_ops,
276 				     num_dequeued_ops);
277 		assert(num_mbufs > 0);
278 		/* This also releases chained mbufs if any. */
279 		rte_pktmbuf_free_bulk(mbufs_to_free, num_mbufs);
280 	}
281 }
282 
283 static inline uint16_t
284 accel_dpdk_cryptodev_poll_qp(struct accel_dpdk_cryptodev_qp *qp)
285 {
286 	struct rte_crypto_op *dequeued_ops[ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE];
287 	struct rte_mbuf *mbufs_to_free[2 * ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE];
288 	struct accel_dpdk_cryptodev_task *task;
289 	uint32_t num_mbufs = 0;
290 	int i;
291 	uint16_t num_dequeued_ops;
292 
293 	/* Each run of the poller will get just what the device has available
294 	 * at the moment we call it, we don't check again after draining the
295 	 * first batch.
296 	 */
297 	num_dequeued_ops = rte_cryptodev_dequeue_burst(qp->device->cdev_id, qp->qp,
298 			   dequeued_ops, ACCEL_DPDK_CRYPTODEV_MAX_DEQUEUE_BURST_SIZE);
299 	/* Check if operation was processed successfully */
300 	for (i = 0; i < num_dequeued_ops; i++) {
301 
302 		/* We don't know the order or association of the crypto ops wrt any
303 		 * particular task so need to look at each and determine if it's
304 		 * the last one for it's task or not.
305 		 */
306 		task = (struct accel_dpdk_cryptodev_task *)*RTE_MBUF_DYNFIELD(dequeued_ops[i]->sym->m_src,
307 				g_mbuf_offset, uint64_t *);
308 		assert(task != NULL);
309 
310 		if (dequeued_ops[i]->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
311 			SPDK_ERRLOG("error with op %d status %u\n", i, dequeued_ops[i]->status);
312 			/* Update the task status to error, we'll still process the
313 			 * rest of the crypto ops for this task though so they
314 			 * aren't left hanging.
315 			 */
316 			task->is_failed = true;
317 		}
318 
319 		/* Return the associated src and dst mbufs by collecting them into
320 		 * an array that we can use the bulk API to free after the loop.
321 		 */
322 		*RTE_MBUF_DYNFIELD(dequeued_ops[i]->sym->m_src, g_mbuf_offset, uint64_t *) = 0;
323 		mbufs_to_free[num_mbufs++] = (void *)dequeued_ops[i]->sym->m_src;
324 		if (dequeued_ops[i]->sym->m_dst) {
325 			mbufs_to_free[num_mbufs++] = (void *)dequeued_ops[i]->sym->m_dst;
326 		}
327 
328 		assert(task->cryop_cnt_remaining > 0);
329 		/* done encrypting, complete the task */
330 		if (--task->cryop_cnt_remaining == 0) {
331 			/* Complete the IO */
332 			spdk_accel_task_complete(&task->base, task->is_failed ? -EINVAL : 0);
333 		}
334 	}
335 
336 	/* Now bulk free both mbufs and crypto operations. */
337 	if (num_dequeued_ops > 0) {
338 		rte_mempool_put_bulk(g_crypto_op_mp, (void **)dequeued_ops, num_dequeued_ops);
339 		assert(num_mbufs > 0);
340 		/* This also releases chained mbufs if any. */
341 		rte_pktmbuf_free_bulk(mbufs_to_free, num_mbufs);
342 	}
343 
344 	assert(qp->num_enqueued_ops >= num_dequeued_ops);
345 	qp->num_enqueued_ops -= num_dequeued_ops;
346 
347 	return num_dequeued_ops;
348 }
349 
350 /* This is the poller for the crypto module. It uses a single API to dequeue whatever is ready at
351  * the device. Then we need to decide if what we've got so far (including previous poller
352  * runs) totals up to one or more complete task */
353 static int
354 accel_dpdk_cryptodev_poller(void *args)
355 {
356 	struct accel_dpdk_cryptodev_io_channel *crypto_ch = args;
357 	struct accel_dpdk_cryptodev_qp *qp;
358 	struct accel_dpdk_cryptodev_task *task;
359 	struct accel_dpdk_cryptodev_queued_op *op_to_resubmit;
360 	uint32_t num_dequeued_ops = 0, num_enqueued_ops = 0;
361 	uint16_t enqueued;
362 	int i;
363 
364 	for (i = 0; i < ACCEL_DPDK_CRYPTODEV_DRIVER_LAST; i++) {
365 		qp = crypto_ch->device_qp[i];
366 		/* Avoid polling "idle" qps since it may affect performance */
367 		if (qp && qp->num_enqueued_ops) {
368 			num_dequeued_ops += accel_dpdk_cryptodev_poll_qp(qp);
369 		}
370 	}
371 
372 	/* Check if there are any queued crypto ops to process */
373 	while (!TAILQ_EMPTY(&crypto_ch->queued_cry_ops)) {
374 		op_to_resubmit = TAILQ_FIRST(&crypto_ch->queued_cry_ops);
375 		task = op_to_resubmit->task;
376 		qp = op_to_resubmit->qp;
377 		enqueued = rte_cryptodev_enqueue_burst(qp->device->cdev_id,
378 						       qp->qp,
379 						       &op_to_resubmit->crypto_op,
380 						       1);
381 		if (enqueued == 1) {
382 			TAILQ_REMOVE(&crypto_ch->queued_cry_ops, op_to_resubmit, link);
383 			qp->num_enqueued_ops++;
384 			num_enqueued_ops++;
385 		} else {
386 			if (op_to_resubmit->crypto_op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED) {
387 				/* If we couldn't get one, just break and try again later. */
388 				break;
389 			} else {
390 				/* Something is really wrong with the op. Most probably the
391 				 * mbuf is broken or the HW is not able to process the request.
392 				 * Fail the IO and remove its ops from the queued ops list. */
393 				task->is_failed = true;
394 
395 				cancel_queued_crypto_ops(crypto_ch, task);
396 
397 				/* Fail the IO if there is nothing left on device. */
398 				if (--task->cryop_cnt_remaining == 0) {
399 					spdk_accel_task_complete(&task->base, -EFAULT);
400 				}
401 			}
402 		}
403 	}
404 
405 	return !!(num_dequeued_ops + num_enqueued_ops);
406 }
407 
408 /* Allocate the new mbuf of @remainder size with data pointed by @addr and attach
409  * it to the @orig_mbuf. */
410 static inline int
411 accel_dpdk_cryptodev_mbuf_chain_remainder(struct accel_dpdk_cryptodev_task *task,
412 		struct rte_mbuf *orig_mbuf, uint8_t *addr, uint64_t *_remainder)
413 {
414 	uint64_t phys_addr, phys_len, remainder = *_remainder;
415 	struct rte_mbuf *chain_mbuf;
416 	int rc;
417 
418 	phys_len = remainder;
419 	phys_addr = spdk_vtophys((void *)addr, &phys_len);
420 	if (spdk_unlikely(phys_addr == SPDK_VTOPHYS_ERROR)) {
421 		return -EFAULT;
422 	}
423 	remainder = spdk_min(remainder, phys_len);
424 	rc = rte_pktmbuf_alloc_bulk(g_mbuf_mp, (struct rte_mbuf **)&chain_mbuf, 1);
425 	if (spdk_unlikely(rc)) {
426 		return -ENOMEM;
427 	}
428 	/* Store context in every mbuf as we don't know anything about completion order */
429 	*RTE_MBUF_DYNFIELD(chain_mbuf, g_mbuf_offset, uint64_t *) = (uint64_t)task;
430 	rte_pktmbuf_attach_extbuf(chain_mbuf, addr, phys_addr, remainder, &g_shinfo);
431 	rte_pktmbuf_append(chain_mbuf, remainder);
432 
433 	/* Chained buffer is released by rte_pktbuf_free_bulk() automagicaly. */
434 	rte_pktmbuf_chain(orig_mbuf, chain_mbuf);
435 	*_remainder = remainder;
436 
437 	return 0;
438 }
439 
440 /* Attach data buffer pointed by @addr to @mbuf. Return utilized len of the
441  * contiguous space that was physically available. */
442 static inline uint64_t
443 accel_dpdk_cryptodev_mbuf_attach_buf(struct accel_dpdk_cryptodev_task *task, struct rte_mbuf *mbuf,
444 				     uint8_t *addr, uint32_t len)
445 {
446 	uint64_t phys_addr, phys_len;
447 
448 	/* Store context in every mbuf as we don't know anything about completion order */
449 	*RTE_MBUF_DYNFIELD(mbuf, g_mbuf_offset, uint64_t *) = (uint64_t)task;
450 
451 	phys_len = len;
452 	phys_addr = spdk_vtophys((void *)addr, &phys_len);
453 	if (spdk_unlikely(phys_addr == SPDK_VTOPHYS_ERROR || phys_len == 0)) {
454 		return 0;
455 	}
456 	assert(phys_len <= len);
457 
458 	/* Set the mbuf elements address and length. */
459 	rte_pktmbuf_attach_extbuf(mbuf, addr, phys_addr, phys_len, &g_shinfo);
460 	rte_pktmbuf_append(mbuf, phys_len);
461 
462 	return phys_len;
463 }
464 
465 static inline struct accel_dpdk_cryptodev_key_handle *
466 accel_dpdk_find_key_handle_in_channel(struct accel_dpdk_cryptodev_io_channel *crypto_ch,
467 				      struct accel_dpdk_cryptodev_key_priv *key)
468 {
469 	struct accel_dpdk_cryptodev_key_handle *key_handle;
470 
471 	if (key->driver == ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI) {
472 		/* Crypto key is registered on all available devices while io_channel opens CQ/QP on a single device.
473 		 * We need to iterate a list of key entries to find a suitable device */
474 		TAILQ_FOREACH(key_handle, &key->dev_keys, link) {
475 			if (key_handle->device->cdev_id ==
476 			    crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI]->device->cdev_id) {
477 				return key_handle;
478 			}
479 		}
480 		return NULL;
481 	} else {
482 		return TAILQ_FIRST(&key->dev_keys);
483 	}
484 }
485 
486 static inline int
487 accel_dpdk_cryptodev_task_alloc_resources(struct rte_mbuf **src_mbufs, struct rte_mbuf **dst_mbufs,
488 		struct rte_crypto_op **crypto_ops, int count)
489 {
490 	int rc;
491 
492 	/* Get the number of source mbufs that we need. These will always be 1:1 because we
493 	 * don't support chaining. The reason we don't is because of our decision to use
494 	 * LBA as IV, there can be no case where we'd need >1 mbuf per crypto op or the
495 	 * op would be > 1 LBA.
496 	 */
497 	rc = rte_pktmbuf_alloc_bulk(g_mbuf_mp, src_mbufs, count);
498 	if (rc) {
499 		SPDK_ERRLOG("Failed to get src_mbufs!\n");
500 		return -ENOMEM;
501 	}
502 
503 	/* Get the same amount to describe destination. If crypto operation is inline then we don't just skip it */
504 	if (dst_mbufs) {
505 		rc = rte_pktmbuf_alloc_bulk(g_mbuf_mp, dst_mbufs, count);
506 		if (rc) {
507 			SPDK_ERRLOG("Failed to get dst_mbufs!\n");
508 			goto err_free_src;
509 		}
510 	}
511 
512 #ifdef __clang_analyzer__
513 	/* silence scan-build false positive */
514 	SPDK_CLANG_ANALYZER_PREINIT_PTR_ARRAY(crypto_ops, ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE,
515 					      0x1000);
516 #endif
517 	/* Allocate crypto operations. */
518 	rc = rte_crypto_op_bulk_alloc(g_crypto_op_mp,
519 				      RTE_CRYPTO_OP_TYPE_SYMMETRIC,
520 				      crypto_ops, count);
521 	if (rc < count) {
522 		SPDK_ERRLOG("Failed to allocate crypto ops!\n");
523 		goto err_free_ops;
524 	}
525 
526 	return 0;
527 
528 err_free_ops:
529 	if (rc > 0) {
530 		rte_mempool_put_bulk(g_crypto_op_mp, (void **)crypto_ops, rc);
531 	}
532 	if (dst_mbufs) {
533 		/* This also releases chained mbufs if any. */
534 		rte_pktmbuf_free_bulk(dst_mbufs, count);
535 	}
536 err_free_src:
537 	/* This also releases chained mbufs if any. */
538 	rte_pktmbuf_free_bulk(src_mbufs, count);
539 
540 	return -ENOMEM;
541 }
542 
543 static inline int
544 accel_dpdk_cryptodev_mbuf_add_single_block(struct spdk_iov_sgl *sgl, struct rte_mbuf *mbuf,
545 		struct accel_dpdk_cryptodev_task *task)
546 {
547 	int rc;
548 	uint8_t *buf_addr;
549 	uint64_t phys_len;
550 	uint64_t remainder;
551 	uint64_t buf_len = spdk_min(task->base.block_size, sgl->iov->iov_len - sgl->iov_offset);
552 
553 	buf_addr = sgl->iov->iov_base + sgl->iov_offset;
554 	phys_len = accel_dpdk_cryptodev_mbuf_attach_buf(task, mbuf, buf_addr, buf_len);
555 	if (spdk_unlikely(phys_len == 0)) {
556 		return -EFAULT;
557 	}
558 	buf_len = spdk_min(buf_len, phys_len);
559 	spdk_iov_sgl_advance(sgl, buf_len);
560 
561 	/* Handle the case of page boundary. */
562 	remainder = task->base.block_size - buf_len;
563 	while (remainder) {
564 		buf_len = spdk_min(remainder, sgl->iov->iov_len - sgl->iov_offset);
565 		buf_addr = sgl->iov->iov_base + sgl->iov_offset;
566 		rc = accel_dpdk_cryptodev_mbuf_chain_remainder(task, mbuf, buf_addr, &buf_len);
567 		if (spdk_unlikely(rc)) {
568 			return rc;
569 		}
570 		spdk_iov_sgl_advance(sgl, buf_len);
571 		remainder -= buf_len;
572 	}
573 
574 	return 0;
575 }
576 
577 static inline void
578 accel_dpdk_cryptodev_op_set_iv(struct rte_crypto_op *crypto_op, uint64_t iv)
579 {
580 	uint8_t *iv_ptr = rte_crypto_op_ctod_offset(crypto_op, uint8_t *, ACCEL_DPDK_CRYPTODEV_IV_OFFSET);
581 
582 	/* Set the IV - we use the LBA of the crypto_op */
583 	memset(iv_ptr, 0, ACCEL_DPDK_CRYPTODEV_IV_LENGTH);
584 	rte_memcpy(iv_ptr, &iv, sizeof(uint64_t));
585 }
586 
587 static int
588 accel_dpdk_cryptodev_process_task(struct accel_dpdk_cryptodev_io_channel *crypto_ch,
589 				  struct accel_dpdk_cryptodev_task *task)
590 {
591 	uint16_t num_enqueued_ops;
592 	uint32_t cryop_cnt;
593 	uint32_t crypto_len = task->base.block_size;
594 	uint64_t dst_length, total_length;
595 	uint64_t iv_start = task->base.iv;
596 	struct accel_dpdk_cryptodev_queued_op *op_to_queue;
597 	uint32_t i, crypto_index;
598 	struct rte_crypto_op *crypto_ops[ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE];
599 	struct rte_mbuf *src_mbufs[ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE];
600 	struct rte_mbuf *dst_mbufs[ACCEL_DPDK_CRYPTODEV_MAX_ENQUEUE_ARRAY_SIZE];
601 	struct rte_cryptodev_sym_session *session;
602 	struct accel_dpdk_cryptodev_key_priv *priv;
603 	struct accel_dpdk_cryptodev_key_handle *key_handle;
604 	struct accel_dpdk_cryptodev_qp *qp;
605 	struct accel_dpdk_cryptodev_device *dev;
606 	struct spdk_iov_sgl src, dst = {};
607 	bool inplace = true;
608 	int rc;
609 
610 	if (spdk_unlikely(!task->base.crypto_key ||
611 			  task->base.crypto_key->module_if != &g_accel_dpdk_cryptodev_module)) {
612 		return -EINVAL;
613 	}
614 
615 	total_length = 0;
616 	for (i = 0; i < task->base.s.iovcnt; i++) {
617 		total_length += task->base.s.iovs[i].iov_len;
618 	}
619 	dst_length = 0;
620 	for (i = 0; i < task->base.d.iovcnt; i++) {
621 		dst_length += task->base.d.iovs[i].iov_len;
622 	}
623 
624 	if (spdk_unlikely(total_length != dst_length || !total_length)) {
625 		return -ERANGE;
626 	}
627 	if (spdk_unlikely(total_length % task->base.block_size != 0)) {
628 		return -EINVAL;
629 	}
630 
631 	priv = task->base.crypto_key->priv;
632 	assert(priv->driver < ACCEL_DPDK_CRYPTODEV_DRIVER_LAST);
633 
634 	if (total_length > ACCEL_DPDK_CRYPTODEV_CRYPTO_MAX_IO) {
635 		return -E2BIG;
636 	}
637 
638 	cryop_cnt =  total_length / task->base.block_size;
639 	qp = crypto_ch->device_qp[priv->driver];
640 	assert(qp);
641 	dev = qp->device;
642 	assert(dev);
643 
644 	key_handle = accel_dpdk_find_key_handle_in_channel(crypto_ch, priv);
645 	if (spdk_unlikely(!key_handle)) {
646 		SPDK_ERRLOG("Failed to find a key handle, driver %s, cipher %s\n", g_driver_names[priv->driver],
647 			    g_cipher_names[priv->cipher]);
648 		return -EINVAL;
649 	}
650 	/* mlx5_pci binds keys to a specific device, we can't use a key with any device */
651 	assert(dev == key_handle->device || priv->driver != ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI);
652 
653 	if (task->base.op_code == ACCEL_OPC_ENCRYPT) {
654 		session = key_handle->session_encrypt;
655 	} else if (task->base.op_code == ACCEL_OPC_DECRYPT) {
656 		session = key_handle->session_decrypt;
657 	} else {
658 		return -EINVAL;
659 	}
660 
661 	/* Check if crypto operation is inplace: no destination or source == destination */
662 	if (task->base.s.iovcnt == task->base.d.iovcnt) {
663 		if (memcmp(task->base.s.iovs, task->base.d.iovs, sizeof(struct iovec) * task->base.s.iovcnt) != 0) {
664 			inplace = false;
665 		}
666 	} else if (task->base.d.iovcnt != 0) {
667 		inplace = false;
668 	}
669 
670 	rc = accel_dpdk_cryptodev_task_alloc_resources(src_mbufs, inplace ? NULL : dst_mbufs, crypto_ops,
671 			cryop_cnt);
672 	if (rc) {
673 		return rc;
674 	}
675 	/* This value is used in the completion callback to determine when the accel task is complete.
676 	 */
677 	task->cryop_cnt_remaining = cryop_cnt;
678 
679 	/* As we don't support chaining because of a decision to use LBA as IV, construction
680 	 * of crypto operations is straightforward. We build both the op, the mbuf and the
681 	 * dst_mbuf in our local arrays by looping through the length of the accel task and
682 	 * picking off LBA sized blocks of memory from the IOVs as we walk through them. Each
683 	 * LBA sized chunk of memory will correspond 1:1 to a crypto operation and a single
684 	 * mbuf per crypto operation.
685 	 */
686 	spdk_iov_sgl_init(&src, task->base.s.iovs, task->base.s.iovcnt, 0);
687 	if (!inplace) {
688 		spdk_iov_sgl_init(&dst, task->base.d.iovs, task->base.d.iovcnt, 0);
689 	}
690 
691 	for (crypto_index = 0; crypto_index < cryop_cnt; crypto_index++) {
692 		rc = accel_dpdk_cryptodev_mbuf_add_single_block(&src, src_mbufs[crypto_index], task);
693 		if (spdk_unlikely(rc)) {
694 			goto err_free_ops;
695 		}
696 		accel_dpdk_cryptodev_op_set_iv(crypto_ops[crypto_index], iv_start);
697 		iv_start++;
698 
699 		/* Set the data to encrypt/decrypt length */
700 		crypto_ops[crypto_index]->sym->cipher.data.length = crypto_len;
701 		crypto_ops[crypto_index]->sym->cipher.data.offset = 0;
702 		rte_crypto_op_attach_sym_session(crypto_ops[crypto_index], session);
703 
704 		/* link the mbuf to the crypto op. */
705 		crypto_ops[crypto_index]->sym->m_src = src_mbufs[crypto_index];
706 
707 		if (inplace) {
708 			crypto_ops[crypto_index]->sym->m_dst = NULL;
709 		} else {
710 			rc = accel_dpdk_cryptodev_mbuf_add_single_block(&dst, dst_mbufs[crypto_index], task);
711 			if (spdk_unlikely(rc)) {
712 				goto err_free_ops;
713 			}
714 			crypto_ops[crypto_index]->sym->m_dst = dst_mbufs[crypto_index];
715 		}
716 	}
717 
718 	/* Enqueue everything we've got but limit by the max number of descriptors we
719 	 * configured the crypto device for.
720 	 */
721 	num_enqueued_ops = rte_cryptodev_enqueue_burst(dev->cdev_id, qp->qp, crypto_ops, spdk_min(cryop_cnt,
722 			   dev->qp_desc_nr));
723 
724 	qp->num_enqueued_ops += num_enqueued_ops;
725 	/* We were unable to enqueue everything but did get some, so need to decide what
726 	 * to do based on the status of the last op.
727 	 */
728 	if (num_enqueued_ops < cryop_cnt) {
729 		switch (crypto_ops[num_enqueued_ops]->status) {
730 		case RTE_CRYPTO_OP_STATUS_NOT_PROCESSED:
731 			/* Queue them up on a linked list to be resubmitted via the poller. */
732 			for (crypto_index = num_enqueued_ops; crypto_index < cryop_cnt; crypto_index++) {
733 				op_to_queue = (struct accel_dpdk_cryptodev_queued_op *)rte_crypto_op_ctod_offset(
734 						      crypto_ops[crypto_index],
735 						      uint8_t *, ACCEL_DPDK_CRYPTODEV_QUEUED_OP_OFFSET);
736 				op_to_queue->qp = qp;
737 				op_to_queue->crypto_op = crypto_ops[crypto_index];
738 				op_to_queue->task = task;
739 				TAILQ_INSERT_TAIL(&crypto_ch->queued_cry_ops, op_to_queue, link);
740 			}
741 			break;
742 		default:
743 			/* For all other statuses, mark task as failed so that the poller will pick
744 			 * the failure up for the overall task status.
745 			 */
746 			task->is_failed = true;
747 			if (num_enqueued_ops == 0) {
748 				/* If nothing was enqueued, but the last one wasn't because of
749 				 * busy, fail it now as the poller won't know anything about it.
750 				 */
751 				rc = -EINVAL;
752 				goto err_free_ops;
753 			}
754 			break;
755 		}
756 	}
757 
758 	return 0;
759 
760 	/* Error cleanup paths. */
761 err_free_ops:
762 	if (!inplace) {
763 		/* This also releases chained mbufs if any. */
764 		rte_pktmbuf_free_bulk(dst_mbufs, cryop_cnt);
765 	}
766 	rte_mempool_put_bulk(g_crypto_op_mp, (void **)crypto_ops, cryop_cnt);
767 	/* This also releases chained mbufs if any. */
768 	rte_pktmbuf_free_bulk(src_mbufs, cryop_cnt);
769 	return rc;
770 }
771 
772 static inline struct accel_dpdk_cryptodev_qp *
773 accel_dpdk_cryptodev_get_next_device_qpair(enum accel_dpdk_cryptodev_driver_type type)
774 {
775 	struct accel_dpdk_cryptodev_device *device, *device_tmp;
776 	struct accel_dpdk_cryptodev_qp *qpair;
777 
778 	TAILQ_FOREACH_SAFE(device, &g_crypto_devices, link, device_tmp) {
779 		if (device->type != type) {
780 			continue;
781 		}
782 		TAILQ_FOREACH(qpair, &device->qpairs, link) {
783 			if (!qpair->in_use) {
784 				qpair->in_use = true;
785 				return qpair;
786 			}
787 		}
788 	}
789 
790 	return NULL;
791 }
792 
793 /* Helper function for the channel creation callback.
794  * Returns the number of drivers assigned to the channel */
795 static uint32_t
796 accel_dpdk_cryptodev_assign_device_qps(struct accel_dpdk_cryptodev_io_channel *crypto_ch)
797 {
798 	struct accel_dpdk_cryptodev_device *device;
799 	struct accel_dpdk_cryptodev_qp *device_qp;
800 	uint32_t num_drivers = 0;
801 	bool qat_found = false;
802 
803 	pthread_mutex_lock(&g_device_lock);
804 
805 	TAILQ_FOREACH(device, &g_crypto_devices, link) {
806 		if (device->type == ACCEL_DPDK_CRYPTODEV_DRIVER_QAT && !qat_found) {
807 			/* For some QAT devices, the optimal qp to use is every 32nd as this spreads the
808 			 * workload out over the multiple virtual functions in the device. For the devices
809 			 * where this isn't the case, it doesn't hurt.
810 			 */
811 			TAILQ_FOREACH(device_qp, &device->qpairs, link) {
812 				if (device_qp->index != g_next_qat_index) {
813 					continue;
814 				}
815 				if (device_qp->in_use == false) {
816 					assert(crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_QAT] == NULL);
817 					crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_QAT] = device_qp;
818 					device_qp->in_use = true;
819 					g_next_qat_index = (g_next_qat_index + ACCEL_DPDK_CRYPTODEV_QAT_VF_SPREAD) % g_qat_total_qp;
820 					qat_found = true;
821 					num_drivers++;
822 					break;
823 				} else {
824 					/* if the preferred index is used, skip to the next one in this set. */
825 					g_next_qat_index = (g_next_qat_index + 1) % g_qat_total_qp;
826 				}
827 			}
828 		}
829 	}
830 
831 	/* For ACCEL_DPDK_CRYPTODEV_AESNI_MB and MLX5_PCI select devices in round-robin manner */
832 	device_qp = accel_dpdk_cryptodev_get_next_device_qpair(ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB);
833 	if (device_qp) {
834 		assert(crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB] == NULL);
835 		crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB] = device_qp;
836 		num_drivers++;
837 	}
838 
839 	device_qp = accel_dpdk_cryptodev_get_next_device_qpair(ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI);
840 	if (device_qp) {
841 		assert(crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI] == NULL);
842 		crypto_ch->device_qp[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI] = device_qp;
843 		num_drivers++;
844 	}
845 
846 	pthread_mutex_unlock(&g_device_lock);
847 
848 	return num_drivers;
849 }
850 
851 static void
852 _accel_dpdk_cryptodev_destroy_cb(void *io_device, void *ctx_buf)
853 {
854 	struct accel_dpdk_cryptodev_io_channel *crypto_ch = (struct accel_dpdk_cryptodev_io_channel *)
855 			ctx_buf;
856 	int i;
857 
858 	pthread_mutex_lock(&g_device_lock);
859 	for (i = 0; i < ACCEL_DPDK_CRYPTODEV_DRIVER_LAST; i++) {
860 		if (crypto_ch->device_qp[i]) {
861 			crypto_ch->device_qp[i]->in_use = false;
862 		}
863 	}
864 	pthread_mutex_unlock(&g_device_lock);
865 
866 	spdk_poller_unregister(&crypto_ch->poller);
867 }
868 
869 static int
870 _accel_dpdk_cryptodev_create_cb(void *io_device, void *ctx_buf)
871 {
872 	struct accel_dpdk_cryptodev_io_channel *crypto_ch = (struct accel_dpdk_cryptodev_io_channel *)
873 			ctx_buf;
874 
875 	crypto_ch->poller = SPDK_POLLER_REGISTER(accel_dpdk_cryptodev_poller, crypto_ch, 0);
876 	if (!accel_dpdk_cryptodev_assign_device_qps(crypto_ch)) {
877 		SPDK_ERRLOG("No crypto drivers assigned\n");
878 		spdk_poller_unregister(&crypto_ch->poller);
879 		return -EINVAL;
880 	}
881 
882 	/* We use this to queue up crypto ops when the device is busy. */
883 	TAILQ_INIT(&crypto_ch->queued_cry_ops);
884 
885 	return 0;
886 }
887 
888 static struct spdk_io_channel *
889 accel_dpdk_cryptodev_get_io_channel(void)
890 {
891 	return spdk_get_io_channel(&g_accel_dpdk_cryptodev_module);
892 }
893 
894 static size_t
895 accel_dpdk_cryptodev_ctx_size(void)
896 {
897 	return sizeof(struct accel_dpdk_cryptodev_task);
898 }
899 
900 static bool
901 accel_dpdk_cryptodev_supports_opcode(enum accel_opcode opc)
902 {
903 	switch (opc) {
904 	case ACCEL_OPC_ENCRYPT:
905 	case ACCEL_OPC_DECRYPT:
906 		return true;
907 	default:
908 		return false;
909 	}
910 }
911 
912 static int
913 accel_dpdk_cryptodev_submit_tasks(struct spdk_io_channel *_ch, struct spdk_accel_task *_task)
914 {
915 	struct accel_dpdk_cryptodev_task *task = SPDK_CONTAINEROF(_task, struct accel_dpdk_cryptodev_task,
916 			base);
917 	struct accel_dpdk_cryptodev_io_channel *ch = spdk_io_channel_get_ctx(_ch);
918 
919 	return accel_dpdk_cryptodev_process_task(ch, task);
920 }
921 
922 /* Dummy function used by DPDK to free ext attached buffers to mbufs, we free them ourselves but
923  * this callback has to be here. */
924 static void
925 shinfo_free_cb(void *arg1, void *arg2)
926 {
927 }
928 
929 static int
930 accel_dpdk_cryptodev_create(uint8_t index, uint16_t num_lcores)
931 {
932 	struct rte_cryptodev_qp_conf qp_conf = { .mp_session = g_session_mp, .mp_session_private = g_session_mp_priv };
933 	/* Setup queue pairs. */
934 	struct rte_cryptodev_config conf = { .socket_id = SPDK_ENV_SOCKET_ID_ANY };
935 	struct accel_dpdk_cryptodev_device *device;
936 	uint8_t j, cdev_id, cdrv_id;
937 	struct accel_dpdk_cryptodev_qp *dev_qp;
938 	int rc;
939 
940 	device = calloc(1, sizeof(*device));
941 	if (!device) {
942 		return -ENOMEM;
943 	}
944 
945 	/* Get details about this device. */
946 	rte_cryptodev_info_get(index, &device->cdev_info);
947 	cdrv_id = device->cdev_info.driver_id;
948 	cdev_id = device->cdev_id = index;
949 
950 	if (strcmp(device->cdev_info.driver_name, ACCEL_DPDK_CRYPTODEV_QAT) == 0) {
951 		device->qp_desc_nr = ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS;
952 		device->type = ACCEL_DPDK_CRYPTODEV_DRIVER_QAT;
953 	} else if (strcmp(device->cdev_info.driver_name, ACCEL_DPDK_CRYPTODEV_AESNI_MB) == 0) {
954 		device->qp_desc_nr = ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS;
955 		device->type = ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB;
956 	} else if (strcmp(device->cdev_info.driver_name, ACCEL_DPDK_CRYPTODEV_MLX5) == 0) {
957 		device->qp_desc_nr = ACCEL_DPDK_CRYPTODEV_QP_DESCRIPTORS_MLX5;
958 		device->type = ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI;
959 	} else if (strcmp(device->cdev_info.driver_name, ACCEL_DPDK_CRYPTODEV_QAT_ASYM) == 0) {
960 		/* ACCEL_DPDK_CRYPTODEV_QAT_ASYM devices are not supported at this time. */
961 		rc = 0;
962 		goto err;
963 	} else {
964 		SPDK_ERRLOG("Failed to start device %u. Invalid driver name \"%s\"\n",
965 			    cdev_id, device->cdev_info.driver_name);
966 		rc = -EINVAL;
967 		goto err;
968 	}
969 
970 	/* Before going any further, make sure we have enough resources for this
971 	 * device type to function.  We need a unique queue pair per core accross each
972 	 * device type to remain lockless....
973 	 */
974 	if ((rte_cryptodev_device_count_by_driver(cdrv_id) *
975 	     device->cdev_info.max_nb_queue_pairs) < num_lcores) {
976 		SPDK_ERRLOG("Insufficient unique queue pairs available for %s\n",
977 			    device->cdev_info.driver_name);
978 		SPDK_ERRLOG("Either add more crypto devices or decrease core count\n");
979 		rc = -EINVAL;
980 		goto err;
981 	}
982 
983 	conf.nb_queue_pairs = device->cdev_info.max_nb_queue_pairs;
984 	rc = rte_cryptodev_configure(cdev_id, &conf);
985 	if (rc < 0) {
986 		SPDK_ERRLOG("Failed to configure cryptodev %u: error %d\n",
987 			    cdev_id, rc);
988 		rc = -EINVAL;
989 		goto err;
990 	}
991 
992 	/* Pre-setup all potential qpairs now and assign them in the channel
993 	 * callback. If we were to create them there, we'd have to stop the
994 	 * entire device affecting all other threads that might be using it
995 	 * even on other queue pairs.
996 	 */
997 	qp_conf.nb_descriptors = device->qp_desc_nr;
998 	for (j = 0; j < device->cdev_info.max_nb_queue_pairs; j++) {
999 		rc = rte_cryptodev_queue_pair_setup(cdev_id, j, &qp_conf, SOCKET_ID_ANY);
1000 		if (rc < 0) {
1001 			SPDK_ERRLOG("Failed to setup queue pair %u on "
1002 				    "cryptodev %u: error %d\n", j, cdev_id, rc);
1003 			rc = -EINVAL;
1004 			goto err_qp_setup;
1005 		}
1006 	}
1007 
1008 	rc = rte_cryptodev_start(cdev_id);
1009 	if (rc < 0) {
1010 		SPDK_ERRLOG("Failed to start device %u: error %d\n", cdev_id, rc);
1011 		rc = -EINVAL;
1012 		goto err_dev_start;
1013 	}
1014 
1015 	TAILQ_INIT(&device->qpairs);
1016 	/* Build up lists of device/qp combinations per PMD */
1017 	for (j = 0; j < device->cdev_info.max_nb_queue_pairs; j++) {
1018 		dev_qp = calloc(1, sizeof(*dev_qp));
1019 		if (!dev_qp) {
1020 			rc = -ENOMEM;
1021 			goto err_qp_alloc;
1022 		}
1023 		dev_qp->device = device;
1024 		dev_qp->qp = j;
1025 		dev_qp->in_use = false;
1026 		TAILQ_INSERT_TAIL(&device->qpairs, dev_qp, link);
1027 		if (device->type == ACCEL_DPDK_CRYPTODEV_DRIVER_QAT) {
1028 			dev_qp->index = g_qat_total_qp++;
1029 		}
1030 	}
1031 	/* Add to our list of available crypto devices. */
1032 	TAILQ_INSERT_TAIL(&g_crypto_devices, device, link);
1033 
1034 	return 0;
1035 
1036 err_qp_alloc:
1037 	TAILQ_FOREACH(dev_qp, &device->qpairs, link) {
1038 		if (dev_qp->device->cdev_id != device->cdev_id) {
1039 			continue;
1040 		}
1041 		free(dev_qp);
1042 		if (device->type == ACCEL_DPDK_CRYPTODEV_DRIVER_QAT) {
1043 			assert(g_qat_total_qp);
1044 			g_qat_total_qp--;
1045 		}
1046 	}
1047 	rte_cryptodev_stop(cdev_id);
1048 err_dev_start:
1049 err_qp_setup:
1050 	rte_cryptodev_close(cdev_id);
1051 err:
1052 	free(device);
1053 
1054 	return rc;
1055 }
1056 
1057 static void
1058 accel_dpdk_cryptodev_release(struct accel_dpdk_cryptodev_device *device)
1059 {
1060 	struct accel_dpdk_cryptodev_qp *dev_qp, *tmp;
1061 
1062 	assert(device);
1063 
1064 	TAILQ_FOREACH_SAFE(dev_qp, &device->qpairs, link, tmp) {
1065 		free(dev_qp);
1066 	}
1067 	if (device->type == ACCEL_DPDK_CRYPTODEV_DRIVER_QAT) {
1068 		assert(g_qat_total_qp >= device->cdev_info.max_nb_queue_pairs);
1069 		g_qat_total_qp -= device->cdev_info.max_nb_queue_pairs;
1070 	}
1071 	rte_cryptodev_stop(device->cdev_id);
1072 	rte_cryptodev_close(device->cdev_id);
1073 	free(device);
1074 }
1075 
1076 static int
1077 accel_dpdk_cryptodev_init(void)
1078 {
1079 	uint8_t cdev_count;
1080 	uint8_t cdev_id;
1081 	int i, rc;
1082 	struct accel_dpdk_cryptodev_device *device, *tmp_dev;
1083 	unsigned int max_sess_size = 0, sess_size;
1084 	uint16_t num_lcores = rte_lcore_count();
1085 	char aesni_args[32];
1086 
1087 	/* Only the first call via module init should init the crypto drivers. */
1088 	if (g_session_mp != NULL) {
1089 		return 0;
1090 	}
1091 
1092 	/* We always init ACCEL_DPDK_CRYPTODEV_AESNI_MB */
1093 	snprintf(aesni_args, sizeof(aesni_args), "max_nb_queue_pairs=%d",
1094 		 ACCEL_DPDK_CRYPTODEV_AESNI_MB_NUM_QP);
1095 	rc = rte_vdev_init(ACCEL_DPDK_CRYPTODEV_AESNI_MB, aesni_args);
1096 	if (rc) {
1097 		SPDK_NOTICELOG("Failed to create virtual PMD %s: error %d. "
1098 			       "Possibly %s is not supported by DPDK library. "
1099 			       "Keep going...\n", ACCEL_DPDK_CRYPTODEV_AESNI_MB, rc, ACCEL_DPDK_CRYPTODEV_AESNI_MB);
1100 	}
1101 
1102 	/* If we have no crypto devices, there's no reason to continue. */
1103 	cdev_count = rte_cryptodev_count();
1104 	SPDK_NOTICELOG("Found crypto devices: %d\n", (int)cdev_count);
1105 	if (cdev_count == 0) {
1106 		return 0;
1107 	}
1108 
1109 	g_mbuf_offset = rte_mbuf_dynfield_register(&rte_mbuf_dynfield_io_context);
1110 	if (g_mbuf_offset < 0) {
1111 		SPDK_ERRLOG("error registering dynamic field with DPDK\n");
1112 		return -EINVAL;
1113 	}
1114 
1115 	/* Create global mempools, shared by all devices regardless of type */
1116 	/* First determine max session size, most pools are shared by all the devices,
1117 	 * so we need to find the global max sessions size. */
1118 	for (cdev_id = 0; cdev_id < cdev_count; cdev_id++) {
1119 		sess_size = rte_cryptodev_sym_get_private_session_size(cdev_id);
1120 		if (sess_size > max_sess_size) {
1121 			max_sess_size = sess_size;
1122 		}
1123 	}
1124 
1125 	g_session_mp_priv = rte_mempool_create("dpdk_crypto_ses_mp_priv",
1126 					       ACCEL_DPDK_CRYPTODEV_NUM_SESSIONS, max_sess_size, ACCEL_DPDK_CRYPTODEV_SESS_MEMPOOL_CACHE_SIZE, 0,
1127 					       NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0);
1128 	if (g_session_mp_priv == NULL) {
1129 		SPDK_ERRLOG("Cannot create private session pool max size 0x%x\n", max_sess_size);
1130 		return -ENOMEM;
1131 	}
1132 
1133 	g_session_mp = rte_cryptodev_sym_session_pool_create("dpdk_crypto_ses_mp",
1134 			ACCEL_DPDK_CRYPTODEV_NUM_SESSIONS, 0, ACCEL_DPDK_CRYPTODEV_SESS_MEMPOOL_CACHE_SIZE, 0,
1135 			SOCKET_ID_ANY);
1136 	if (g_session_mp == NULL) {
1137 		SPDK_ERRLOG("Cannot create session pool max size 0x%x\n", max_sess_size);
1138 		rc = -ENOMEM;
1139 		goto error_create_session_mp;
1140 	}
1141 
1142 	g_mbuf_mp = rte_pktmbuf_pool_create("dpdk_crypto_mbuf_mp", ACCEL_DPDK_CRYPTODEV_NUM_MBUFS,
1143 					    ACCEL_DPDK_CRYPTODEV_POOL_CACHE_SIZE,
1144 					    0, 0, SPDK_ENV_SOCKET_ID_ANY);
1145 	if (g_mbuf_mp == NULL) {
1146 		SPDK_ERRLOG("Cannot create mbuf pool\n");
1147 		rc = -ENOMEM;
1148 		goto error_create_mbuf;
1149 	}
1150 
1151 	/* We use per op private data as suggested by DPDK and to store the IV and
1152 	 * our own struct for queueing ops. */
1153 	g_crypto_op_mp = rte_crypto_op_pool_create("dpdk_crypto_op_mp",
1154 			 RTE_CRYPTO_OP_TYPE_SYMMETRIC, ACCEL_DPDK_CRYPTODEV_NUM_MBUFS, ACCEL_DPDK_CRYPTODEV_POOL_CACHE_SIZE,
1155 			 (ACCEL_DPDK_CRYPTODEV_DEFAULT_NUM_XFORMS * sizeof(struct rte_crypto_sym_xform)) +
1156 			 ACCEL_DPDK_CRYPTODEV_IV_LENGTH + ACCEL_DPDK_CRYPTODEV_QUEUED_OP_LENGTH, rte_socket_id());
1157 	if (g_crypto_op_mp == NULL) {
1158 		SPDK_ERRLOG("Cannot create op pool\n");
1159 		rc = -ENOMEM;
1160 		goto error_create_op;
1161 	}
1162 
1163 	/* Init all devices */
1164 	for (i = 0; i < cdev_count; i++) {
1165 		rc = accel_dpdk_cryptodev_create(i, num_lcores);
1166 		if (rc) {
1167 			goto err;
1168 		}
1169 	}
1170 
1171 	g_shinfo.free_cb = shinfo_free_cb;
1172 
1173 	spdk_io_device_register(&g_accel_dpdk_cryptodev_module, _accel_dpdk_cryptodev_create_cb,
1174 				_accel_dpdk_cryptodev_destroy_cb, sizeof(struct accel_dpdk_cryptodev_io_channel),
1175 				"accel_dpdk_cryptodev");
1176 
1177 	return 0;
1178 
1179 	/* Error cleanup paths. */
1180 err:
1181 	TAILQ_FOREACH_SAFE(device, &g_crypto_devices, link, tmp_dev) {
1182 		TAILQ_REMOVE(&g_crypto_devices, device, link);
1183 		accel_dpdk_cryptodev_release(device);
1184 	}
1185 	rte_mempool_free(g_crypto_op_mp);
1186 	g_crypto_op_mp = NULL;
1187 error_create_op:
1188 	rte_mempool_free(g_mbuf_mp);
1189 	g_mbuf_mp = NULL;
1190 error_create_mbuf:
1191 	rte_mempool_free(g_session_mp);
1192 	g_session_mp = NULL;
1193 error_create_session_mp:
1194 	if (g_session_mp_priv != NULL) {
1195 		rte_mempool_free(g_session_mp_priv);
1196 		g_session_mp_priv = NULL;
1197 	}
1198 	return rc;
1199 }
1200 
1201 static void
1202 accel_dpdk_cryptodev_fini_cb(void *io_device)
1203 {
1204 	struct accel_dpdk_cryptodev_device *device, *tmp;
1205 
1206 	TAILQ_FOREACH_SAFE(device, &g_crypto_devices, link, tmp) {
1207 		TAILQ_REMOVE(&g_crypto_devices, device, link);
1208 		accel_dpdk_cryptodev_release(device);
1209 	}
1210 	rte_vdev_uninit(ACCEL_DPDK_CRYPTODEV_AESNI_MB);
1211 
1212 	rte_mempool_free(g_crypto_op_mp);
1213 	rte_mempool_free(g_mbuf_mp);
1214 	rte_mempool_free(g_session_mp);
1215 	if (g_session_mp_priv != NULL) {
1216 		rte_mempool_free(g_session_mp_priv);
1217 	}
1218 
1219 	spdk_accel_module_finish();
1220 }
1221 
1222 /* Called when the entire module is being torn down. */
1223 static void
1224 accel_dpdk_cryptodev_fini(void *ctx)
1225 {
1226 	spdk_io_device_unregister(&g_accel_dpdk_cryptodev_module, accel_dpdk_cryptodev_fini_cb);
1227 }
1228 
1229 static int
1230 accel_dpdk_cryptodev_key_handle_configure(struct spdk_accel_crypto_key *key,
1231 		struct accel_dpdk_cryptodev_key_handle *key_handle)
1232 {
1233 	struct accel_dpdk_cryptodev_key_priv *priv = key->priv;
1234 	int rc;
1235 
1236 	key_handle->session_encrypt = rte_cryptodev_sym_session_create(g_session_mp);
1237 	if (!key_handle->session_encrypt) {
1238 		SPDK_ERRLOG("Failed to create encrypt crypto session.\n");
1239 		return -EINVAL;
1240 	}
1241 	key_handle->session_decrypt = rte_cryptodev_sym_session_create(g_session_mp);
1242 	if (!key_handle->session_decrypt) {
1243 		SPDK_ERRLOG("Failed to create decrypt crypto session.\n");
1244 		rc = -EINVAL;
1245 		goto err_ses_encrypt;
1246 	}
1247 	key_handle->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1248 	key_handle->cipher_xform.cipher.iv.offset = ACCEL_DPDK_CRYPTODEV_IV_OFFSET;
1249 	key_handle->cipher_xform.cipher.iv.length = ACCEL_DPDK_CRYPTODEV_IV_LENGTH;
1250 
1251 	switch (priv->cipher) {
1252 	case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC:
1253 		key_handle->cipher_xform.cipher.key.data = key->key;
1254 		key_handle->cipher_xform.cipher.key.length = key->key_size;
1255 		key_handle->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
1256 		break;
1257 	case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS:
1258 		key_handle->cipher_xform.cipher.key.data = priv->xts_key;
1259 		key_handle->cipher_xform.cipher.key.length = key->key_size + key->key2_size;
1260 		key_handle->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_XTS;
1261 		break;
1262 	default:
1263 		SPDK_ERRLOG("Invalid cipher name %s.\n", key->param.cipher);
1264 		rc = -EINVAL;
1265 		goto err_ses_decrypt;
1266 	}
1267 
1268 	key_handle->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
1269 	rc = rte_cryptodev_sym_session_init(key_handle->device->cdev_id, key_handle->session_encrypt,
1270 					    &key_handle->cipher_xform,
1271 					    g_session_mp_priv ? g_session_mp_priv : g_session_mp);
1272 	if (rc < 0) {
1273 		SPDK_ERRLOG("Failed to init encrypt session: error %d\n", rc);
1274 		rc = -EINVAL;
1275 		goto err_ses_decrypt;
1276 	}
1277 
1278 	key_handle->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
1279 	rc = rte_cryptodev_sym_session_init(key_handle->device->cdev_id, key_handle->session_decrypt,
1280 					    &key_handle->cipher_xform,
1281 					    g_session_mp_priv ? g_session_mp_priv : g_session_mp);
1282 	if (rc < 0) {
1283 		SPDK_ERRLOG("Failed to init decrypt session: error %d\n", rc);
1284 		rc = -EINVAL;
1285 		goto err_ses_decrypt;
1286 	}
1287 
1288 	return 0;
1289 
1290 err_ses_decrypt:
1291 	rte_cryptodev_sym_session_free(key_handle->session_decrypt);
1292 err_ses_encrypt:
1293 	rte_cryptodev_sym_session_free(key_handle->session_encrypt);
1294 
1295 	return rc;
1296 }
1297 
1298 static int
1299 accel_dpdk_cryptodev_validate_parameters(enum accel_dpdk_cryptodev_driver_type driver,
1300 		enum accel_dpdk_crypto_dev_cipher_type cipher, struct spdk_accel_crypto_key *key)
1301 {
1302 	/* Check that all required parameters exist */
1303 	switch (cipher) {
1304 	case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC:
1305 		if (!key->key || !key->key_size) {
1306 			SPDK_ERRLOG("ACCEL_DPDK_CRYPTODEV_AES_CBC requires a key\n");
1307 			return -1;
1308 		}
1309 		if (key->key2 || key->key2_size) {
1310 			SPDK_ERRLOG("ACCEL_DPDK_CRYPTODEV_AES_CBC doesn't use key2\n");
1311 			return -1;
1312 		}
1313 		break;
1314 	case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS:
1315 		if (!key->key || !key->key_size || !key->key2 || !key->key2_size) {
1316 			SPDK_ERRLOG("ACCEL_DPDK_CRYPTODEV_AES_XTS requires both key and key2\n");
1317 			return -1;
1318 		}
1319 		break;
1320 	default:
1321 		return -1;
1322 	}
1323 
1324 	/* Check driver/cipher combinations and key lengths */
1325 	switch (cipher) {
1326 	case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC:
1327 		if (driver == ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI) {
1328 			SPDK_ERRLOG("Driver %s only supports cipher %s\n",
1329 				    g_driver_names[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI],
1330 				    g_cipher_names[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS]);
1331 			return -1;
1332 		}
1333 		if (key->key_size != ACCEL_DPDK_CRYPTODEV_AES_CBC_KEY_LENGTH) {
1334 			SPDK_ERRLOG("Invalid key size %zu for cipher %s, should be %d\n", key->key_size,
1335 				    g_cipher_names[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC], ACCEL_DPDK_CRYPTODEV_AES_CBC_KEY_LENGTH);
1336 			return -1;
1337 		}
1338 		break;
1339 	case ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS:
1340 		switch (driver) {
1341 		case ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI:
1342 			if (key->key_size != ACCEL_DPDK_CRYPTODEV_AES_XTS_256_BLOCK_KEY_LENGTH &&
1343 			    key->key_size != ACCEL_DPDK_CRYPTODEV_AES_XTS_512_BLOCK_KEY_LENGTH) {
1344 				SPDK_ERRLOG("Invalid key size %zu for driver %s, cipher %s, supported %d or %d\n",
1345 					    key->key_size, g_driver_names[ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI],
1346 					    g_cipher_names[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS],
1347 					    ACCEL_DPDK_CRYPTODEV_AES_XTS_256_BLOCK_KEY_LENGTH,
1348 					    ACCEL_DPDK_CRYPTODEV_AES_XTS_512_BLOCK_KEY_LENGTH);
1349 				return -1;
1350 			}
1351 			break;
1352 		case ACCEL_DPDK_CRYPTODEV_DRIVER_QAT:
1353 		case ACCEL_DPDK_CRYPTODEV_DRIVER_AESNI_MB:
1354 			if (key->key_size != ACCEL_DPDK_CRYPTODEV_AES_XTS_128_BLOCK_KEY_LENGTH) {
1355 				SPDK_ERRLOG("Invalid key size %zu, supported %d\n", key->key_size,
1356 					    ACCEL_DPDK_CRYPTODEV_AES_XTS_128_BLOCK_KEY_LENGTH);
1357 				return -1;
1358 			}
1359 			break;
1360 		default:
1361 			SPDK_ERRLOG("Incorrect driver type %d\n", driver);
1362 			assert(0);
1363 			return -1;
1364 		}
1365 		if (key->key2_size != ACCEL_DPDK_CRYPTODEV_AES_XTS_TWEAK_KEY_LENGTH) {
1366 			SPDK_ERRLOG("Cipher %s requires key2 size %d\n",
1367 				    g_cipher_names[ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC], ACCEL_DPDK_CRYPTODEV_AES_XTS_TWEAK_KEY_LENGTH);
1368 			return -1;
1369 		}
1370 		break;
1371 	}
1372 
1373 	return 0;
1374 }
1375 
1376 static void
1377 accel_dpdk_cryptodev_key_deinit(struct spdk_accel_crypto_key *key)
1378 {
1379 	struct accel_dpdk_cryptodev_key_handle *key_handle, *key_handle_tmp;
1380 	struct accel_dpdk_cryptodev_key_priv *priv = key->priv;
1381 
1382 	TAILQ_FOREACH_SAFE(key_handle, &priv->dev_keys, link, key_handle_tmp) {
1383 		rte_cryptodev_sym_session_free(key_handle->session_encrypt);
1384 		rte_cryptodev_sym_session_free(key_handle->session_decrypt);
1385 		TAILQ_REMOVE(&priv->dev_keys, key_handle, link);
1386 		spdk_memset_s(key_handle, sizeof(*key_handle), 0, sizeof(*key_handle));
1387 		free(key_handle);
1388 	}
1389 
1390 	if (priv->xts_key) {
1391 		spdk_memset_s(priv->xts_key, key->key_size + key->key2_size, 0, key->key_size + key->key2_size);
1392 	}
1393 	free(priv->xts_key);
1394 	free(priv);
1395 }
1396 
1397 static int
1398 accel_dpdk_cryptodev_key_init(struct spdk_accel_crypto_key *key)
1399 {
1400 	struct accel_dpdk_cryptodev_device *device;
1401 	struct accel_dpdk_cryptodev_key_priv *priv;
1402 	struct accel_dpdk_cryptodev_key_handle *key_handle;
1403 	enum accel_dpdk_cryptodev_driver_type driver;
1404 	enum accel_dpdk_crypto_dev_cipher_type cipher;
1405 
1406 	if (!key->param.cipher) {
1407 		SPDK_ERRLOG("Cipher is missing\n");
1408 		return -EINVAL;
1409 	}
1410 
1411 	if (strcmp(key->param.cipher, ACCEL_DPDK_CRYPTODEV_AES_CBC) == 0) {
1412 		cipher = ACCEL_DPDK_CRYPTODEV_CIPHER_AES_CBC;
1413 	} else if (strcmp(key->param.cipher, ACCEL_DPDK_CRYPTODEV_AES_XTS) == 0) {
1414 		cipher = ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS;
1415 	} else {
1416 		SPDK_ERRLOG("Unsupported cipher name %s.\n", key->param.cipher);
1417 		return -EINVAL;
1418 	}
1419 
1420 	driver = g_dpdk_cryptodev_driver;
1421 
1422 	if (accel_dpdk_cryptodev_validate_parameters(driver, cipher, key)) {
1423 		return -EINVAL;
1424 	}
1425 
1426 	priv = calloc(1, sizeof(*priv));
1427 	if (!priv) {
1428 		SPDK_ERRLOG("Memory allocation failed\n");
1429 		return -ENOMEM;
1430 	}
1431 	key->priv = priv;
1432 	priv->driver = driver;
1433 	priv->cipher = cipher;
1434 	TAILQ_INIT(&priv->dev_keys);
1435 
1436 	if (cipher == ACCEL_DPDK_CRYPTODEV_CIPHER_AES_XTS) {
1437 		/* DPDK expects the keys to be concatenated together. */
1438 		priv->xts_key = calloc(key->key_size + key->key2_size + 1, sizeof(char));
1439 		if (!priv->xts_key) {
1440 			SPDK_ERRLOG("Memory allocation failed\n");
1441 			accel_dpdk_cryptodev_key_deinit(key);
1442 			return -ENOMEM;
1443 		}
1444 		memcpy(priv->xts_key, key->key, key->key_size);
1445 		memcpy(priv->xts_key + key->key_size, key->key2, key->key2_size);
1446 	}
1447 
1448 	pthread_mutex_lock(&g_device_lock);
1449 	TAILQ_FOREACH(device, &g_crypto_devices, link) {
1450 		if (device->type != driver) {
1451 			continue;
1452 		}
1453 		key_handle = calloc(1, sizeof(*key_handle));
1454 		if (!key_handle) {
1455 			pthread_mutex_unlock(&g_device_lock);
1456 			accel_dpdk_cryptodev_key_deinit(key);
1457 			return -ENOMEM;
1458 		}
1459 		key_handle->device = device;
1460 		TAILQ_INSERT_TAIL(&priv->dev_keys, key_handle, link);
1461 		if (accel_dpdk_cryptodev_key_handle_configure(key, key_handle)) {
1462 			pthread_mutex_unlock(&g_device_lock);
1463 			accel_dpdk_cryptodev_key_deinit(key);
1464 			return -ENOMEM;
1465 		}
1466 		if (driver != ACCEL_DPDK_CRYPTODEV_DRIVER_MLX5_PCI) {
1467 			/* For MLX5_PCI we need to register a key on each device since
1468 			 * the key is bound to a specific Protection Domain,
1469 			 * so don't break the loop */
1470 			break;
1471 		}
1472 	}
1473 	pthread_mutex_unlock(&g_device_lock);
1474 
1475 	if (TAILQ_EMPTY(&priv->dev_keys)) {
1476 		free(priv);
1477 		return -ENODEV;
1478 	}
1479 
1480 	return 0;
1481 }
1482 
1483 static void
1484 accel_dpdk_cryptodev_write_config_json(struct spdk_json_write_ctx *w)
1485 {
1486 	spdk_json_write_object_begin(w);
1487 	spdk_json_write_named_string(w, "method", "dpdk_cryptodev_scan_accel_module");
1488 	spdk_json_write_object_end(w);
1489 
1490 	spdk_json_write_object_begin(w);
1491 	spdk_json_write_named_string(w, "method", "dpdk_cryptodev_set_driver");
1492 	spdk_json_write_named_object_begin(w, "params");
1493 	spdk_json_write_named_string(w, "driver_name", g_driver_names[g_dpdk_cryptodev_driver]);
1494 	spdk_json_write_object_end(w);
1495 	spdk_json_write_object_end(w);
1496 }
1497 
1498 static struct spdk_accel_module_if g_accel_dpdk_cryptodev_module = {
1499 	.module_init		= accel_dpdk_cryptodev_init,
1500 	.module_fini		= accel_dpdk_cryptodev_fini,
1501 	.write_config_json	= accel_dpdk_cryptodev_write_config_json,
1502 	.get_ctx_size		= accel_dpdk_cryptodev_ctx_size,
1503 	.name			= "dpdk_cryptodev",
1504 	.supports_opcode	= accel_dpdk_cryptodev_supports_opcode,
1505 	.get_io_channel		= accel_dpdk_cryptodev_get_io_channel,
1506 	.submit_tasks		= accel_dpdk_cryptodev_submit_tasks,
1507 	.crypto_key_init	= accel_dpdk_cryptodev_key_init,
1508 	.crypto_key_deinit	= accel_dpdk_cryptodev_key_deinit,
1509 };
1510