cryptodev: add asymmetric session-less feature name
[dpdk.git] / lib / librte_cryptodev / rte_cryptodev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015-2020 Intel Corporation
3  */
4
5 #include <sys/types.h>
6 #include <sys/queue.h>
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <errno.h>
13 #include <stdint.h>
14 #include <inttypes.h>
15 #include <netinet/in.h>
16
17 #include <rte_byteorder.h>
18 #include <rte_log.h>
19 #include <rte_debug.h>
20 #include <rte_dev.h>
21 #include <rte_interrupts.h>
22 #include <rte_memory.h>
23 #include <rte_memcpy.h>
24 #include <rte_memzone.h>
25 #include <rte_launch.h>
26 #include <rte_tailq.h>
27 #include <rte_eal.h>
28 #include <rte_per_lcore.h>
29 #include <rte_lcore.h>
30 #include <rte_atomic.h>
31 #include <rte_branch_prediction.h>
32 #include <rte_common.h>
33 #include <rte_mempool.h>
34 #include <rte_malloc.h>
35 #include <rte_mbuf.h>
36 #include <rte_errno.h>
37 #include <rte_spinlock.h>
38 #include <rte_string_fns.h>
39
40 #include "rte_crypto.h"
41 #include "rte_cryptodev.h"
42 #include "rte_cryptodev_pmd.h"
43
44 static uint8_t nb_drivers;
45
46 static struct rte_cryptodev rte_crypto_devices[RTE_CRYPTO_MAX_DEVS];
47
48 struct rte_cryptodev *rte_cryptodevs = rte_crypto_devices;
49
50 static struct rte_cryptodev_global cryptodev_globals = {
51                 .devs                   = rte_crypto_devices,
52                 .data                   = { NULL },
53                 .nb_devs                = 0
54 };
55
56 /* spinlock for crypto device callbacks */
57 static rte_spinlock_t rte_cryptodev_cb_lock = RTE_SPINLOCK_INITIALIZER;
58
59
60 /**
61  * The user application callback description.
62  *
63  * It contains callback address to be registered by user application,
64  * the pointer to the parameters for callback, and the event type.
65  */
66 struct rte_cryptodev_callback {
67         TAILQ_ENTRY(rte_cryptodev_callback) next; /**< Callbacks list */
68         rte_cryptodev_cb_fn cb_fn;              /**< Callback address */
69         void *cb_arg;                           /**< Parameter for callback */
70         enum rte_cryptodev_event_type event;    /**< Interrupt event type */
71         uint32_t active;                        /**< Callback is executing */
72 };
73
74 /**
75  * The crypto cipher algorithm strings identifiers.
76  * It could be used in application command line.
77  */
78 const char *
79 rte_crypto_cipher_algorithm_strings[] = {
80         [RTE_CRYPTO_CIPHER_3DES_CBC]    = "3des-cbc",
81         [RTE_CRYPTO_CIPHER_3DES_ECB]    = "3des-ecb",
82         [RTE_CRYPTO_CIPHER_3DES_CTR]    = "3des-ctr",
83
84         [RTE_CRYPTO_CIPHER_AES_CBC]     = "aes-cbc",
85         [RTE_CRYPTO_CIPHER_AES_CTR]     = "aes-ctr",
86         [RTE_CRYPTO_CIPHER_AES_DOCSISBPI]       = "aes-docsisbpi",
87         [RTE_CRYPTO_CIPHER_AES_ECB]     = "aes-ecb",
88         [RTE_CRYPTO_CIPHER_AES_F8]      = "aes-f8",
89         [RTE_CRYPTO_CIPHER_AES_XTS]     = "aes-xts",
90
91         [RTE_CRYPTO_CIPHER_ARC4]        = "arc4",
92
93         [RTE_CRYPTO_CIPHER_DES_CBC]     = "des-cbc",
94         [RTE_CRYPTO_CIPHER_DES_DOCSISBPI]       = "des-docsisbpi",
95
96         [RTE_CRYPTO_CIPHER_NULL]        = "null",
97
98         [RTE_CRYPTO_CIPHER_KASUMI_F8]   = "kasumi-f8",
99         [RTE_CRYPTO_CIPHER_SNOW3G_UEA2] = "snow3g-uea2",
100         [RTE_CRYPTO_CIPHER_ZUC_EEA3]    = "zuc-eea3"
101 };
102
103 /**
104  * The crypto cipher operation strings identifiers.
105  * It could be used in application command line.
106  */
107 const char *
108 rte_crypto_cipher_operation_strings[] = {
109                 [RTE_CRYPTO_CIPHER_OP_ENCRYPT]  = "encrypt",
110                 [RTE_CRYPTO_CIPHER_OP_DECRYPT]  = "decrypt"
111 };
112
113 /**
114  * The crypto auth algorithm strings identifiers.
115  * It could be used in application command line.
116  */
117 const char *
118 rte_crypto_auth_algorithm_strings[] = {
119         [RTE_CRYPTO_AUTH_AES_CBC_MAC]   = "aes-cbc-mac",
120         [RTE_CRYPTO_AUTH_AES_CMAC]      = "aes-cmac",
121         [RTE_CRYPTO_AUTH_AES_GMAC]      = "aes-gmac",
122         [RTE_CRYPTO_AUTH_AES_XCBC_MAC]  = "aes-xcbc-mac",
123
124         [RTE_CRYPTO_AUTH_MD5]           = "md5",
125         [RTE_CRYPTO_AUTH_MD5_HMAC]      = "md5-hmac",
126
127         [RTE_CRYPTO_AUTH_NULL]          = "null",
128
129         [RTE_CRYPTO_AUTH_SHA1]          = "sha1",
130         [RTE_CRYPTO_AUTH_SHA1_HMAC]     = "sha1-hmac",
131
132         [RTE_CRYPTO_AUTH_SHA224]        = "sha2-224",
133         [RTE_CRYPTO_AUTH_SHA224_HMAC]   = "sha2-224-hmac",
134         [RTE_CRYPTO_AUTH_SHA256]        = "sha2-256",
135         [RTE_CRYPTO_AUTH_SHA256_HMAC]   = "sha2-256-hmac",
136         [RTE_CRYPTO_AUTH_SHA384]        = "sha2-384",
137         [RTE_CRYPTO_AUTH_SHA384_HMAC]   = "sha2-384-hmac",
138         [RTE_CRYPTO_AUTH_SHA512]        = "sha2-512",
139         [RTE_CRYPTO_AUTH_SHA512_HMAC]   = "sha2-512-hmac",
140
141         [RTE_CRYPTO_AUTH_KASUMI_F9]     = "kasumi-f9",
142         [RTE_CRYPTO_AUTH_SNOW3G_UIA2]   = "snow3g-uia2",
143         [RTE_CRYPTO_AUTH_ZUC_EIA3]      = "zuc-eia3"
144 };
145
146 /**
147  * The crypto AEAD algorithm strings identifiers.
148  * It could be used in application command line.
149  */
150 const char *
151 rte_crypto_aead_algorithm_strings[] = {
152         [RTE_CRYPTO_AEAD_AES_CCM]       = "aes-ccm",
153         [RTE_CRYPTO_AEAD_AES_GCM]       = "aes-gcm",
154 };
155
156 /**
157  * The crypto AEAD operation strings identifiers.
158  * It could be used in application command line.
159  */
160 const char *
161 rte_crypto_aead_operation_strings[] = {
162         [RTE_CRYPTO_AEAD_OP_ENCRYPT]    = "encrypt",
163         [RTE_CRYPTO_AEAD_OP_DECRYPT]    = "decrypt"
164 };
165
166 /**
167  * Asymmetric crypto transform operation strings identifiers.
168  */
169 const char *rte_crypto_asym_xform_strings[] = {
170         [RTE_CRYPTO_ASYM_XFORM_NONE]    = "none",
171         [RTE_CRYPTO_ASYM_XFORM_RSA]     = "rsa",
172         [RTE_CRYPTO_ASYM_XFORM_MODEX]   = "modexp",
173         [RTE_CRYPTO_ASYM_XFORM_MODINV]  = "modinv",
174         [RTE_CRYPTO_ASYM_XFORM_DH]      = "dh",
175         [RTE_CRYPTO_ASYM_XFORM_DSA]     = "dsa",
176         [RTE_CRYPTO_ASYM_XFORM_ECDSA]   = "ecdsa",
177         [RTE_CRYPTO_ASYM_XFORM_ECPM]    = "ecpm",
178 };
179
180 /**
181  * Asymmetric crypto operation strings identifiers.
182  */
183 const char *rte_crypto_asym_op_strings[] = {
184         [RTE_CRYPTO_ASYM_OP_ENCRYPT]    = "encrypt",
185         [RTE_CRYPTO_ASYM_OP_DECRYPT]    = "decrypt",
186         [RTE_CRYPTO_ASYM_OP_SIGN]       = "sign",
187         [RTE_CRYPTO_ASYM_OP_VERIFY]     = "verify",
188         [RTE_CRYPTO_ASYM_OP_PRIVATE_KEY_GENERATE]       = "priv_key_generate",
189         [RTE_CRYPTO_ASYM_OP_PUBLIC_KEY_GENERATE] = "pub_key_generate",
190         [RTE_CRYPTO_ASYM_OP_SHARED_SECRET_COMPUTE] = "sharedsecret_compute",
191 };
192
193 /**
194  * The private data structure stored in the session mempool private data.
195  */
196 struct rte_cryptodev_sym_session_pool_private_data {
197         uint16_t nb_drivers;
198         /**< number of elements in sess_data array */
199         uint16_t user_data_sz;
200         /**< session user data will be placed after sess_data */
201 };
202
203 int
204 rte_cryptodev_get_cipher_algo_enum(enum rte_crypto_cipher_algorithm *algo_enum,
205                 const char *algo_string)
206 {
207         unsigned int i;
208
209         for (i = 1; i < RTE_DIM(rte_crypto_cipher_algorithm_strings); i++) {
210                 if (strcmp(algo_string, rte_crypto_cipher_algorithm_strings[i]) == 0) {
211                         *algo_enum = (enum rte_crypto_cipher_algorithm) i;
212                         return 0;
213                 }
214         }
215
216         /* Invalid string */
217         return -1;
218 }
219
220 int
221 rte_cryptodev_get_auth_algo_enum(enum rte_crypto_auth_algorithm *algo_enum,
222                 const char *algo_string)
223 {
224         unsigned int i;
225
226         for (i = 1; i < RTE_DIM(rte_crypto_auth_algorithm_strings); i++) {
227                 if (strcmp(algo_string, rte_crypto_auth_algorithm_strings[i]) == 0) {
228                         *algo_enum = (enum rte_crypto_auth_algorithm) i;
229                         return 0;
230                 }
231         }
232
233         /* Invalid string */
234         return -1;
235 }
236
237 int
238 rte_cryptodev_get_aead_algo_enum(enum rte_crypto_aead_algorithm *algo_enum,
239                 const char *algo_string)
240 {
241         unsigned int i;
242
243         for (i = 1; i < RTE_DIM(rte_crypto_aead_algorithm_strings); i++) {
244                 if (strcmp(algo_string, rte_crypto_aead_algorithm_strings[i]) == 0) {
245                         *algo_enum = (enum rte_crypto_aead_algorithm) i;
246                         return 0;
247                 }
248         }
249
250         /* Invalid string */
251         return -1;
252 }
253
254 int
255 rte_cryptodev_asym_get_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,
256                 const char *xform_string)
257 {
258         unsigned int i;
259
260         for (i = 1; i < RTE_DIM(rte_crypto_asym_xform_strings); i++) {
261                 if (strcmp(xform_string,
262                         rte_crypto_asym_xform_strings[i]) == 0) {
263                         *xform_enum = (enum rte_crypto_asym_xform_type) i;
264                         return 0;
265                 }
266         }
267
268         /* Invalid string */
269         return -1;
270 }
271
272 /**
273  * The crypto auth operation strings identifiers.
274  * It could be used in application command line.
275  */
276 const char *
277 rte_crypto_auth_operation_strings[] = {
278                 [RTE_CRYPTO_AUTH_OP_VERIFY]     = "verify",
279                 [RTE_CRYPTO_AUTH_OP_GENERATE]   = "generate"
280 };
281
282 const struct rte_cryptodev_symmetric_capability *
283 rte_cryptodev_sym_capability_get(uint8_t dev_id,
284                 const struct rte_cryptodev_sym_capability_idx *idx)
285 {
286         const struct rte_cryptodev_capabilities *capability;
287         struct rte_cryptodev_info dev_info;
288         int i = 0;
289
290         rte_cryptodev_info_get(dev_id, &dev_info);
291
292         while ((capability = &dev_info.capabilities[i++])->op !=
293                         RTE_CRYPTO_OP_TYPE_UNDEFINED) {
294                 if (capability->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC)
295                         continue;
296
297                 if (capability->sym.xform_type != idx->type)
298                         continue;
299
300                 if (idx->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
301                         capability->sym.auth.algo == idx->algo.auth)
302                         return &capability->sym;
303
304                 if (idx->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
305                         capability->sym.cipher.algo == idx->algo.cipher)
306                         return &capability->sym;
307
308                 if (idx->type == RTE_CRYPTO_SYM_XFORM_AEAD &&
309                                 capability->sym.aead.algo == idx->algo.aead)
310                         return &capability->sym;
311         }
312
313         return NULL;
314
315 }
316
317 static int
318 param_range_check(uint16_t size, const struct rte_crypto_param_range *range)
319 {
320         unsigned int next_size;
321
322         /* Check lower/upper bounds */
323         if (size < range->min)
324                 return -1;
325
326         if (size > range->max)
327                 return -1;
328
329         /* If range is actually only one value, size is correct */
330         if (range->increment == 0)
331                 return 0;
332
333         /* Check if value is one of the supported sizes */
334         for (next_size = range->min; next_size <= range->max;
335                         next_size += range->increment)
336                 if (size == next_size)
337                         return 0;
338
339         return -1;
340 }
341
342 const struct rte_cryptodev_asymmetric_xform_capability *
343 rte_cryptodev_asym_capability_get(uint8_t dev_id,
344                 const struct rte_cryptodev_asym_capability_idx *idx)
345 {
346         const struct rte_cryptodev_capabilities *capability;
347         struct rte_cryptodev_info dev_info;
348         unsigned int i = 0;
349
350         memset(&dev_info, 0, sizeof(struct rte_cryptodev_info));
351         rte_cryptodev_info_get(dev_id, &dev_info);
352
353         while ((capability = &dev_info.capabilities[i++])->op !=
354                         RTE_CRYPTO_OP_TYPE_UNDEFINED) {
355                 if (capability->op != RTE_CRYPTO_OP_TYPE_ASYMMETRIC)
356                         continue;
357
358                 if (capability->asym.xform_capa.xform_type == idx->type)
359                         return &capability->asym.xform_capa;
360         }
361         return NULL;
362 };
363
364 int
365 rte_cryptodev_sym_capability_check_cipher(
366                 const struct rte_cryptodev_symmetric_capability *capability,
367                 uint16_t key_size, uint16_t iv_size)
368 {
369         if (param_range_check(key_size, &capability->cipher.key_size) != 0)
370                 return -1;
371
372         if (param_range_check(iv_size, &capability->cipher.iv_size) != 0)
373                 return -1;
374
375         return 0;
376 }
377
378 int
379 rte_cryptodev_sym_capability_check_auth(
380                 const struct rte_cryptodev_symmetric_capability *capability,
381                 uint16_t key_size, uint16_t digest_size, uint16_t iv_size)
382 {
383         if (param_range_check(key_size, &capability->auth.key_size) != 0)
384                 return -1;
385
386         if (param_range_check(digest_size, &capability->auth.digest_size) != 0)
387                 return -1;
388
389         if (param_range_check(iv_size, &capability->auth.iv_size) != 0)
390                 return -1;
391
392         return 0;
393 }
394
395 int
396 rte_cryptodev_sym_capability_check_aead(
397                 const struct rte_cryptodev_symmetric_capability *capability,
398                 uint16_t key_size, uint16_t digest_size, uint16_t aad_size,
399                 uint16_t iv_size)
400 {
401         if (param_range_check(key_size, &capability->aead.key_size) != 0)
402                 return -1;
403
404         if (param_range_check(digest_size, &capability->aead.digest_size) != 0)
405                 return -1;
406
407         if (param_range_check(aad_size, &capability->aead.aad_size) != 0)
408                 return -1;
409
410         if (param_range_check(iv_size, &capability->aead.iv_size) != 0)
411                 return -1;
412
413         return 0;
414 }
415 int
416 rte_cryptodev_asym_xform_capability_check_optype(
417         const struct rte_cryptodev_asymmetric_xform_capability *capability,
418         enum rte_crypto_asym_op_type op_type)
419 {
420         if (capability->op_types & (1 << op_type))
421                 return 1;
422
423         return 0;
424 }
425
426 int
427 rte_cryptodev_asym_xform_capability_check_modlen(
428         const struct rte_cryptodev_asymmetric_xform_capability *capability,
429         uint16_t modlen)
430 {
431         /* no need to check for limits, if min or max = 0 */
432         if (capability->modlen.min != 0) {
433                 if (modlen < capability->modlen.min)
434                         return -1;
435         }
436
437         if (capability->modlen.max != 0) {
438                 if (modlen > capability->modlen.max)
439                         return -1;
440         }
441
442         /* in any case, check if given modlen is module increment */
443         if (capability->modlen.increment != 0) {
444                 if (modlen % (capability->modlen.increment))
445                         return -1;
446         }
447
448         return 0;
449 }
450
451
452 const char *
453 rte_cryptodev_get_feature_name(uint64_t flag)
454 {
455         switch (flag) {
456         case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
457                 return "SYMMETRIC_CRYPTO";
458         case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
459                 return "ASYMMETRIC_CRYPTO";
460         case RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING:
461                 return "SYM_OPERATION_CHAINING";
462         case RTE_CRYPTODEV_FF_CPU_SSE:
463                 return "CPU_SSE";
464         case RTE_CRYPTODEV_FF_CPU_AVX:
465                 return "CPU_AVX";
466         case RTE_CRYPTODEV_FF_CPU_AVX2:
467                 return "CPU_AVX2";
468         case RTE_CRYPTODEV_FF_CPU_AVX512:
469                 return "CPU_AVX512";
470         case RTE_CRYPTODEV_FF_CPU_AESNI:
471                 return "CPU_AESNI";
472         case RTE_CRYPTODEV_FF_HW_ACCELERATED:
473                 return "HW_ACCELERATED";
474         case RTE_CRYPTODEV_FF_IN_PLACE_SGL:
475                 return "IN_PLACE_SGL";
476         case RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT:
477                 return "OOP_SGL_IN_SGL_OUT";
478         case RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT:
479                 return "OOP_SGL_IN_LB_OUT";
480         case RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT:
481                 return "OOP_LB_IN_SGL_OUT";
482         case RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT:
483                 return "OOP_LB_IN_LB_OUT";
484         case RTE_CRYPTODEV_FF_CPU_NEON:
485                 return "CPU_NEON";
486         case RTE_CRYPTODEV_FF_CPU_ARM_CE:
487                 return "CPU_ARM_CE";
488         case RTE_CRYPTODEV_FF_SECURITY:
489                 return "SECURITY_PROTOCOL";
490         case RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP:
491                 return "RSA_PRIV_OP_KEY_EXP";
492         case RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT:
493                 return "RSA_PRIV_OP_KEY_QT";
494         case RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED:
495                 return "DIGEST_ENCRYPTED";
496         case RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO:
497                 return "SYM_CPU_CRYPTO";
498         case RTE_CRYPTODEV_FF_ASYM_SESSIONLESS:
499                 return "ASYM_SESSIONLESS";
500         default:
501                 return NULL;
502         }
503 }
504
505 struct rte_cryptodev *
506 rte_cryptodev_pmd_get_dev(uint8_t dev_id)
507 {
508         return &cryptodev_globals.devs[dev_id];
509 }
510
511 struct rte_cryptodev *
512 rte_cryptodev_pmd_get_named_dev(const char *name)
513 {
514         struct rte_cryptodev *dev;
515         unsigned int i;
516
517         if (name == NULL)
518                 return NULL;
519
520         for (i = 0; i < RTE_CRYPTO_MAX_DEVS; i++) {
521                 dev = &cryptodev_globals.devs[i];
522
523                 if ((dev->attached == RTE_CRYPTODEV_ATTACHED) &&
524                                 (strcmp(dev->data->name, name) == 0))
525                         return dev;
526         }
527
528         return NULL;
529 }
530
531 static inline uint8_t
532 rte_cryptodev_is_valid_device_data(uint8_t dev_id)
533 {
534         if (dev_id >= RTE_CRYPTO_MAX_DEVS ||
535                         rte_crypto_devices[dev_id].data == NULL)
536                 return 0;
537
538         return 1;
539 }
540
541 unsigned int
542 rte_cryptodev_pmd_is_valid_dev(uint8_t dev_id)
543 {
544         struct rte_cryptodev *dev = NULL;
545
546         if (!rte_cryptodev_is_valid_device_data(dev_id))
547                 return 0;
548
549         dev = rte_cryptodev_pmd_get_dev(dev_id);
550         if (dev->attached != RTE_CRYPTODEV_ATTACHED)
551                 return 0;
552         else
553                 return 1;
554 }
555
556
557 int
558 rte_cryptodev_get_dev_id(const char *name)
559 {
560         unsigned i;
561
562         if (name == NULL)
563                 return -1;
564
565         for (i = 0; i < RTE_CRYPTO_MAX_DEVS; i++) {
566                 if (!rte_cryptodev_is_valid_device_data(i))
567                         continue;
568                 if ((strcmp(cryptodev_globals.devs[i].data->name, name)
569                                 == 0) &&
570                                 (cryptodev_globals.devs[i].attached ==
571                                                 RTE_CRYPTODEV_ATTACHED))
572                         return i;
573         }
574
575         return -1;
576 }
577
578 uint8_t
579 rte_cryptodev_count(void)
580 {
581         return cryptodev_globals.nb_devs;
582 }
583
584 uint8_t
585 rte_cryptodev_device_count_by_driver(uint8_t driver_id)
586 {
587         uint8_t i, dev_count = 0;
588
589         for (i = 0; i < RTE_CRYPTO_MAX_DEVS; i++)
590                 if (cryptodev_globals.devs[i].driver_id == driver_id &&
591                         cryptodev_globals.devs[i].attached ==
592                                         RTE_CRYPTODEV_ATTACHED)
593                         dev_count++;
594
595         return dev_count;
596 }
597
598 uint8_t
599 rte_cryptodev_devices_get(const char *driver_name, uint8_t *devices,
600         uint8_t nb_devices)
601 {
602         uint8_t i, count = 0;
603         struct rte_cryptodev *devs = cryptodev_globals.devs;
604
605         for (i = 0; i < RTE_CRYPTO_MAX_DEVS && count < nb_devices; i++) {
606                 if (!rte_cryptodev_is_valid_device_data(i))
607                         continue;
608
609                 if (devs[i].attached == RTE_CRYPTODEV_ATTACHED) {
610                         int cmp;
611
612                         cmp = strncmp(devs[i].device->driver->name,
613                                         driver_name,
614                                         strlen(driver_name) + 1);
615
616                         if (cmp == 0)
617                                 devices[count++] = devs[i].data->dev_id;
618                 }
619         }
620
621         return count;
622 }
623
624 void *
625 rte_cryptodev_get_sec_ctx(uint8_t dev_id)
626 {
627         if (dev_id < RTE_CRYPTO_MAX_DEVS &&
628                         (rte_crypto_devices[dev_id].feature_flags &
629                         RTE_CRYPTODEV_FF_SECURITY))
630                 return rte_crypto_devices[dev_id].security_ctx;
631
632         return NULL;
633 }
634
635 int
636 rte_cryptodev_socket_id(uint8_t dev_id)
637 {
638         struct rte_cryptodev *dev;
639
640         if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
641                 return -1;
642
643         dev = rte_cryptodev_pmd_get_dev(dev_id);
644
645         return dev->data->socket_id;
646 }
647
648 static inline int
649 rte_cryptodev_data_alloc(uint8_t dev_id, struct rte_cryptodev_data **data,
650                 int socket_id)
651 {
652         char mz_name[RTE_MEMZONE_NAMESIZE];
653         const struct rte_memzone *mz;
654         int n;
655
656         /* generate memzone name */
657         n = snprintf(mz_name, sizeof(mz_name), "rte_cryptodev_data_%u", dev_id);
658         if (n >= (int)sizeof(mz_name))
659                 return -EINVAL;
660
661         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
662                 mz = rte_memzone_reserve(mz_name,
663                                 sizeof(struct rte_cryptodev_data),
664                                 socket_id, 0);
665         } else
666                 mz = rte_memzone_lookup(mz_name);
667
668         if (mz == NULL)
669                 return -ENOMEM;
670
671         *data = mz->addr;
672         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
673                 memset(*data, 0, sizeof(struct rte_cryptodev_data));
674
675         return 0;
676 }
677
678 static inline int
679 rte_cryptodev_data_free(uint8_t dev_id, struct rte_cryptodev_data **data)
680 {
681         char mz_name[RTE_MEMZONE_NAMESIZE];
682         const struct rte_memzone *mz;
683         int n;
684
685         /* generate memzone name */
686         n = snprintf(mz_name, sizeof(mz_name), "rte_cryptodev_data_%u", dev_id);
687         if (n >= (int)sizeof(mz_name))
688                 return -EINVAL;
689
690         mz = rte_memzone_lookup(mz_name);
691         if (mz == NULL)
692                 return -ENOMEM;
693
694         RTE_ASSERT(*data == mz->addr);
695         *data = NULL;
696
697         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
698                 return rte_memzone_free(mz);
699
700         return 0;
701 }
702
703 static uint8_t
704 rte_cryptodev_find_free_device_index(void)
705 {
706         uint8_t dev_id;
707
708         for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++) {
709                 if (rte_crypto_devices[dev_id].attached ==
710                                 RTE_CRYPTODEV_DETACHED)
711                         return dev_id;
712         }
713         return RTE_CRYPTO_MAX_DEVS;
714 }
715
716 struct rte_cryptodev *
717 rte_cryptodev_pmd_allocate(const char *name, int socket_id)
718 {
719         struct rte_cryptodev *cryptodev;
720         uint8_t dev_id;
721
722         if (rte_cryptodev_pmd_get_named_dev(name) != NULL) {
723                 CDEV_LOG_ERR("Crypto device with name %s already "
724                                 "allocated!", name);
725                 return NULL;
726         }
727
728         dev_id = rte_cryptodev_find_free_device_index();
729         if (dev_id == RTE_CRYPTO_MAX_DEVS) {
730                 CDEV_LOG_ERR("Reached maximum number of crypto devices");
731                 return NULL;
732         }
733
734         cryptodev = rte_cryptodev_pmd_get_dev(dev_id);
735
736         if (cryptodev->data == NULL) {
737                 struct rte_cryptodev_data **cryptodev_data =
738                                 &cryptodev_globals.data[dev_id];
739
740                 int retval = rte_cryptodev_data_alloc(dev_id, cryptodev_data,
741                                 socket_id);
742
743                 if (retval < 0 || *cryptodev_data == NULL)
744                         return NULL;
745
746                 cryptodev->data = *cryptodev_data;
747
748                 if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
749                         strlcpy(cryptodev->data->name, name,
750                                 RTE_CRYPTODEV_NAME_MAX_LEN);
751
752                         cryptodev->data->dev_id = dev_id;
753                         cryptodev->data->socket_id = socket_id;
754                         cryptodev->data->dev_started = 0;
755                 }
756
757                 /* init user callbacks */
758                 TAILQ_INIT(&(cryptodev->link_intr_cbs));
759
760                 cryptodev->attached = RTE_CRYPTODEV_ATTACHED;
761
762                 cryptodev_globals.nb_devs++;
763         }
764
765         return cryptodev;
766 }
767
768 int
769 rte_cryptodev_pmd_release_device(struct rte_cryptodev *cryptodev)
770 {
771         int ret;
772         uint8_t dev_id;
773
774         if (cryptodev == NULL)
775                 return -EINVAL;
776
777         dev_id = cryptodev->data->dev_id;
778
779         /* Close device only if device operations have been set */
780         if (cryptodev->dev_ops) {
781                 ret = rte_cryptodev_close(dev_id);
782                 if (ret < 0)
783                         return ret;
784         }
785
786         ret = rte_cryptodev_data_free(dev_id, &cryptodev_globals.data[dev_id]);
787         if (ret < 0)
788                 return ret;
789
790         cryptodev->attached = RTE_CRYPTODEV_DETACHED;
791         cryptodev_globals.nb_devs--;
792         return 0;
793 }
794
795 uint16_t
796 rte_cryptodev_queue_pair_count(uint8_t dev_id)
797 {
798         struct rte_cryptodev *dev;
799
800         if (!rte_cryptodev_is_valid_device_data(dev_id)) {
801                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
802                 return 0;
803         }
804
805         dev = &rte_crypto_devices[dev_id];
806         return dev->data->nb_queue_pairs;
807 }
808
809 static int
810 rte_cryptodev_queue_pairs_config(struct rte_cryptodev *dev, uint16_t nb_qpairs,
811                 int socket_id)
812 {
813         struct rte_cryptodev_info dev_info;
814         void **qp;
815         unsigned i;
816
817         if ((dev == NULL) || (nb_qpairs < 1)) {
818                 CDEV_LOG_ERR("invalid param: dev %p, nb_queues %u",
819                                                         dev, nb_qpairs);
820                 return -EINVAL;
821         }
822
823         CDEV_LOG_DEBUG("Setup %d queues pairs on device %u",
824                         nb_qpairs, dev->data->dev_id);
825
826         memset(&dev_info, 0, sizeof(struct rte_cryptodev_info));
827
828         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
829         (*dev->dev_ops->dev_infos_get)(dev, &dev_info);
830
831         if (nb_qpairs > (dev_info.max_nb_queue_pairs)) {
832                 CDEV_LOG_ERR("Invalid num queue_pairs (%u) for dev %u",
833                                 nb_qpairs, dev->data->dev_id);
834             return -EINVAL;
835         }
836
837         if (dev->data->queue_pairs == NULL) { /* first time configuration */
838                 dev->data->queue_pairs = rte_zmalloc_socket(
839                                 "cryptodev->queue_pairs",
840                                 sizeof(dev->data->queue_pairs[0]) * nb_qpairs,
841                                 RTE_CACHE_LINE_SIZE, socket_id);
842
843                 if (dev->data->queue_pairs == NULL) {
844                         dev->data->nb_queue_pairs = 0;
845                         CDEV_LOG_ERR("failed to get memory for qp meta data, "
846                                                         "nb_queues %u",
847                                                         nb_qpairs);
848                         return -(ENOMEM);
849                 }
850         } else { /* re-configure */
851                 int ret;
852                 uint16_t old_nb_queues = dev->data->nb_queue_pairs;
853
854                 qp = dev->data->queue_pairs;
855
856                 RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_release,
857                                 -ENOTSUP);
858
859                 for (i = nb_qpairs; i < old_nb_queues; i++) {
860                         ret = (*dev->dev_ops->queue_pair_release)(dev, i);
861                         if (ret < 0)
862                                 return ret;
863                 }
864
865                 qp = rte_realloc(qp, sizeof(qp[0]) * nb_qpairs,
866                                 RTE_CACHE_LINE_SIZE);
867                 if (qp == NULL) {
868                         CDEV_LOG_ERR("failed to realloc qp meta data,"
869                                                 " nb_queues %u", nb_qpairs);
870                         return -(ENOMEM);
871                 }
872
873                 if (nb_qpairs > old_nb_queues) {
874                         uint16_t new_qs = nb_qpairs - old_nb_queues;
875
876                         memset(qp + old_nb_queues, 0,
877                                 sizeof(qp[0]) * new_qs);
878                 }
879
880                 dev->data->queue_pairs = qp;
881
882         }
883         dev->data->nb_queue_pairs = nb_qpairs;
884         return 0;
885 }
886
887 int
888 rte_cryptodev_configure(uint8_t dev_id, struct rte_cryptodev_config *config)
889 {
890         struct rte_cryptodev *dev;
891         int diag;
892
893         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
894                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
895                 return -EINVAL;
896         }
897
898         dev = &rte_crypto_devices[dev_id];
899
900         if (dev->data->dev_started) {
901                 CDEV_LOG_ERR(
902                     "device %d must be stopped to allow configuration", dev_id);
903                 return -EBUSY;
904         }
905
906         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);
907
908         /* Setup new number of queue pairs and reconfigure device. */
909         diag = rte_cryptodev_queue_pairs_config(dev, config->nb_queue_pairs,
910                         config->socket_id);
911         if (diag != 0) {
912                 CDEV_LOG_ERR("dev%d rte_crypto_dev_queue_pairs_config = %d",
913                                 dev_id, diag);
914                 return diag;
915         }
916
917         return (*dev->dev_ops->dev_configure)(dev, config);
918 }
919
920
921 int
922 rte_cryptodev_start(uint8_t dev_id)
923 {
924         struct rte_cryptodev *dev;
925         int diag;
926
927         CDEV_LOG_DEBUG("Start dev_id=%" PRIu8, dev_id);
928
929         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
930                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
931                 return -EINVAL;
932         }
933
934         dev = &rte_crypto_devices[dev_id];
935
936         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP);
937
938         if (dev->data->dev_started != 0) {
939                 CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already started",
940                         dev_id);
941                 return 0;
942         }
943
944         diag = (*dev->dev_ops->dev_start)(dev);
945         if (diag == 0)
946                 dev->data->dev_started = 1;
947         else
948                 return diag;
949
950         return 0;
951 }
952
953 void
954 rte_cryptodev_stop(uint8_t dev_id)
955 {
956         struct rte_cryptodev *dev;
957
958         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
959                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
960                 return;
961         }
962
963         dev = &rte_crypto_devices[dev_id];
964
965         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);
966
967         if (dev->data->dev_started == 0) {
968                 CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already stopped",
969                         dev_id);
970                 return;
971         }
972
973         (*dev->dev_ops->dev_stop)(dev);
974         dev->data->dev_started = 0;
975 }
976
977 int
978 rte_cryptodev_close(uint8_t dev_id)
979 {
980         struct rte_cryptodev *dev;
981         int retval;
982
983         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
984                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
985                 return -1;
986         }
987
988         dev = &rte_crypto_devices[dev_id];
989
990         /* Device must be stopped before it can be closed */
991         if (dev->data->dev_started == 1) {
992                 CDEV_LOG_ERR("Device %u must be stopped before closing",
993                                 dev_id);
994                 return -EBUSY;
995         }
996
997         /* We can't close the device if there are outstanding sessions in use */
998         if (dev->data->session_pool != NULL) {
999                 if (!rte_mempool_full(dev->data->session_pool)) {
1000                         CDEV_LOG_ERR("dev_id=%u close failed, session mempool "
1001                                         "has sessions still in use, free "
1002                                         "all sessions before calling close",
1003                                         (unsigned)dev_id);
1004                         return -EBUSY;
1005                 }
1006         }
1007
1008         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);
1009         retval = (*dev->dev_ops->dev_close)(dev);
1010
1011         if (retval < 0)
1012                 return retval;
1013
1014         return 0;
1015 }
1016
1017 int
1018 rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
1019                 const struct rte_cryptodev_qp_conf *qp_conf, int socket_id)
1020
1021 {
1022         struct rte_cryptodev *dev;
1023
1024         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1025                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1026                 return -EINVAL;
1027         }
1028
1029         dev = &rte_crypto_devices[dev_id];
1030         if (queue_pair_id >= dev->data->nb_queue_pairs) {
1031                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
1032                 return -EINVAL;
1033         }
1034
1035         if (!qp_conf) {
1036                 CDEV_LOG_ERR("qp_conf cannot be NULL\n");
1037                 return -EINVAL;
1038         }
1039
1040         if ((qp_conf->mp_session && !qp_conf->mp_session_private) ||
1041                         (!qp_conf->mp_session && qp_conf->mp_session_private)) {
1042                 CDEV_LOG_ERR("Invalid mempools\n");
1043                 return -EINVAL;
1044         }
1045
1046         if (qp_conf->mp_session) {
1047                 struct rte_cryptodev_sym_session_pool_private_data *pool_priv;
1048                 uint32_t obj_size = qp_conf->mp_session->elt_size;
1049                 uint32_t obj_priv_size = qp_conf->mp_session_private->elt_size;
1050                 struct rte_cryptodev_sym_session s = {0};
1051
1052                 pool_priv = rte_mempool_get_priv(qp_conf->mp_session);
1053                 if (!pool_priv || qp_conf->mp_session->private_data_size <
1054                                 sizeof(*pool_priv)) {
1055                         CDEV_LOG_ERR("Invalid mempool\n");
1056                         return -EINVAL;
1057                 }
1058
1059                 s.nb_drivers = pool_priv->nb_drivers;
1060                 s.user_data_sz = pool_priv->user_data_sz;
1061
1062                 if ((rte_cryptodev_sym_get_existing_header_session_size(&s) >
1063                         obj_size) || (s.nb_drivers <= dev->driver_id) ||
1064                         rte_cryptodev_sym_get_private_session_size(dev_id) >
1065                                 obj_priv_size) {
1066                         CDEV_LOG_ERR("Invalid mempool\n");
1067                         return -EINVAL;
1068                 }
1069         }
1070
1071         if (dev->data->dev_started) {
1072                 CDEV_LOG_ERR(
1073                     "device %d must be stopped to allow configuration", dev_id);
1074                 return -EBUSY;
1075         }
1076
1077         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_setup, -ENOTSUP);
1078
1079         return (*dev->dev_ops->queue_pair_setup)(dev, queue_pair_id, qp_conf,
1080                         socket_id);
1081 }
1082
1083
1084 int
1085 rte_cryptodev_stats_get(uint8_t dev_id, struct rte_cryptodev_stats *stats)
1086 {
1087         struct rte_cryptodev *dev;
1088
1089         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1090                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
1091                 return -ENODEV;
1092         }
1093
1094         if (stats == NULL) {
1095                 CDEV_LOG_ERR("Invalid stats ptr");
1096                 return -EINVAL;
1097         }
1098
1099         dev = &rte_crypto_devices[dev_id];
1100         memset(stats, 0, sizeof(*stats));
1101
1102         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_get, -ENOTSUP);
1103         (*dev->dev_ops->stats_get)(dev, stats);
1104         return 0;
1105 }
1106
1107 void
1108 rte_cryptodev_stats_reset(uint8_t dev_id)
1109 {
1110         struct rte_cryptodev *dev;
1111
1112         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1113                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1114                 return;
1115         }
1116
1117         dev = &rte_crypto_devices[dev_id];
1118
1119         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
1120         (*dev->dev_ops->stats_reset)(dev);
1121 }
1122
1123
1124 void
1125 rte_cryptodev_info_get(uint8_t dev_id, struct rte_cryptodev_info *dev_info)
1126 {
1127         struct rte_cryptodev *dev;
1128
1129         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1130                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
1131                 return;
1132         }
1133
1134         dev = &rte_crypto_devices[dev_id];
1135
1136         memset(dev_info, 0, sizeof(struct rte_cryptodev_info));
1137
1138         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
1139         (*dev->dev_ops->dev_infos_get)(dev, dev_info);
1140
1141         dev_info->driver_name = dev->device->driver->name;
1142         dev_info->device = dev->device;
1143 }
1144
1145
1146 int
1147 rte_cryptodev_callback_register(uint8_t dev_id,
1148                         enum rte_cryptodev_event_type event,
1149                         rte_cryptodev_cb_fn cb_fn, void *cb_arg)
1150 {
1151         struct rte_cryptodev *dev;
1152         struct rte_cryptodev_callback *user_cb;
1153
1154         if (!cb_fn)
1155                 return -EINVAL;
1156
1157         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1158                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1159                 return -EINVAL;
1160         }
1161
1162         dev = &rte_crypto_devices[dev_id];
1163         rte_spinlock_lock(&rte_cryptodev_cb_lock);
1164
1165         TAILQ_FOREACH(user_cb, &(dev->link_intr_cbs), next) {
1166                 if (user_cb->cb_fn == cb_fn &&
1167                         user_cb->cb_arg == cb_arg &&
1168                         user_cb->event == event) {
1169                         break;
1170                 }
1171         }
1172
1173         /* create a new callback. */
1174         if (user_cb == NULL) {
1175                 user_cb = rte_zmalloc("INTR_USER_CALLBACK",
1176                                 sizeof(struct rte_cryptodev_callback), 0);
1177                 if (user_cb != NULL) {
1178                         user_cb->cb_fn = cb_fn;
1179                         user_cb->cb_arg = cb_arg;
1180                         user_cb->event = event;
1181                         TAILQ_INSERT_TAIL(&(dev->link_intr_cbs), user_cb, next);
1182                 }
1183         }
1184
1185         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1186         return (user_cb == NULL) ? -ENOMEM : 0;
1187 }
1188
1189 int
1190 rte_cryptodev_callback_unregister(uint8_t dev_id,
1191                         enum rte_cryptodev_event_type event,
1192                         rte_cryptodev_cb_fn cb_fn, void *cb_arg)
1193 {
1194         int ret;
1195         struct rte_cryptodev *dev;
1196         struct rte_cryptodev_callback *cb, *next;
1197
1198         if (!cb_fn)
1199                 return -EINVAL;
1200
1201         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1202                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1203                 return -EINVAL;
1204         }
1205
1206         dev = &rte_crypto_devices[dev_id];
1207         rte_spinlock_lock(&rte_cryptodev_cb_lock);
1208
1209         ret = 0;
1210         for (cb = TAILQ_FIRST(&dev->link_intr_cbs); cb != NULL; cb = next) {
1211
1212                 next = TAILQ_NEXT(cb, next);
1213
1214                 if (cb->cb_fn != cb_fn || cb->event != event ||
1215                                 (cb->cb_arg != (void *)-1 &&
1216                                 cb->cb_arg != cb_arg))
1217                         continue;
1218
1219                 /*
1220                  * if this callback is not executing right now,
1221                  * then remove it.
1222                  */
1223                 if (cb->active == 0) {
1224                         TAILQ_REMOVE(&(dev->link_intr_cbs), cb, next);
1225                         rte_free(cb);
1226                 } else {
1227                         ret = -EAGAIN;
1228                 }
1229         }
1230
1231         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1232         return ret;
1233 }
1234
1235 void
1236 rte_cryptodev_pmd_callback_process(struct rte_cryptodev *dev,
1237         enum rte_cryptodev_event_type event)
1238 {
1239         struct rte_cryptodev_callback *cb_lst;
1240         struct rte_cryptodev_callback dev_cb;
1241
1242         rte_spinlock_lock(&rte_cryptodev_cb_lock);
1243         TAILQ_FOREACH(cb_lst, &(dev->link_intr_cbs), next) {
1244                 if (cb_lst->cb_fn == NULL || cb_lst->event != event)
1245                         continue;
1246                 dev_cb = *cb_lst;
1247                 cb_lst->active = 1;
1248                 rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1249                 dev_cb.cb_fn(dev->data->dev_id, dev_cb.event,
1250                                                 dev_cb.cb_arg);
1251                 rte_spinlock_lock(&rte_cryptodev_cb_lock);
1252                 cb_lst->active = 0;
1253         }
1254         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1255 }
1256
1257
1258 int
1259 rte_cryptodev_sym_session_init(uint8_t dev_id,
1260                 struct rte_cryptodev_sym_session *sess,
1261                 struct rte_crypto_sym_xform *xforms,
1262                 struct rte_mempool *mp)
1263 {
1264         struct rte_cryptodev *dev;
1265         uint32_t sess_priv_sz = rte_cryptodev_sym_get_private_session_size(
1266                         dev_id);
1267         uint8_t index;
1268         int ret;
1269
1270         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1271                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1272                 return -EINVAL;
1273         }
1274
1275         dev = rte_cryptodev_pmd_get_dev(dev_id);
1276
1277         if (sess == NULL || xforms == NULL || dev == NULL)
1278                 return -EINVAL;
1279
1280         if (mp->elt_size < sess_priv_sz)
1281                 return -EINVAL;
1282
1283         index = dev->driver_id;
1284         if (index >= sess->nb_drivers)
1285                 return -EINVAL;
1286
1287         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->sym_session_configure, -ENOTSUP);
1288
1289         if (sess->sess_data[index].refcnt == 0) {
1290                 ret = dev->dev_ops->sym_session_configure(dev, xforms,
1291                                                         sess, mp);
1292                 if (ret < 0) {
1293                         CDEV_LOG_ERR(
1294                                 "dev_id %d failed to configure session details",
1295                                 dev_id);
1296                         return ret;
1297                 }
1298         }
1299
1300         sess->sess_data[index].refcnt++;
1301         return 0;
1302 }
1303
1304 int
1305 rte_cryptodev_asym_session_init(uint8_t dev_id,
1306                 struct rte_cryptodev_asym_session *sess,
1307                 struct rte_crypto_asym_xform *xforms,
1308                 struct rte_mempool *mp)
1309 {
1310         struct rte_cryptodev *dev;
1311         uint8_t index;
1312         int ret;
1313
1314         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1315                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1316                 return -EINVAL;
1317         }
1318
1319         dev = rte_cryptodev_pmd_get_dev(dev_id);
1320
1321         if (sess == NULL || xforms == NULL || dev == NULL)
1322                 return -EINVAL;
1323
1324         index = dev->driver_id;
1325
1326         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_session_configure,
1327                                 -ENOTSUP);
1328
1329         if (sess->sess_private_data[index] == NULL) {
1330                 ret = dev->dev_ops->asym_session_configure(dev,
1331                                                         xforms,
1332                                                         sess, mp);
1333                 if (ret < 0) {
1334                         CDEV_LOG_ERR(
1335                                 "dev_id %d failed to configure session details",
1336                                 dev_id);
1337                         return ret;
1338                 }
1339         }
1340
1341         return 0;
1342 }
1343
1344 struct rte_mempool *
1345 rte_cryptodev_sym_session_pool_create(const char *name, uint32_t nb_elts,
1346         uint32_t elt_size, uint32_t cache_size, uint16_t user_data_size,
1347         int socket_id)
1348 {
1349         struct rte_mempool *mp;
1350         struct rte_cryptodev_sym_session_pool_private_data *pool_priv;
1351         uint32_t obj_sz;
1352
1353         obj_sz = rte_cryptodev_sym_get_header_session_size() + user_data_size;
1354         if (obj_sz > elt_size)
1355                 CDEV_LOG_INFO("elt_size %u is expanded to %u\n", elt_size,
1356                                 obj_sz);
1357         else
1358                 obj_sz = elt_size;
1359
1360         mp = rte_mempool_create(name, nb_elts, obj_sz, cache_size,
1361                         (uint32_t)(sizeof(*pool_priv)),
1362                         NULL, NULL, NULL, NULL,
1363                         socket_id, 0);
1364         if (mp == NULL) {
1365                 CDEV_LOG_ERR("%s(name=%s) failed, rte_errno=%d\n",
1366                         __func__, name, rte_errno);
1367                 return NULL;
1368         }
1369
1370         pool_priv = rte_mempool_get_priv(mp);
1371         if (!pool_priv) {
1372                 CDEV_LOG_ERR("%s(name=%s) failed to get private data\n",
1373                         __func__, name);
1374                 rte_mempool_free(mp);
1375                 return NULL;
1376         }
1377
1378         pool_priv->nb_drivers = nb_drivers;
1379         pool_priv->user_data_sz = user_data_size;
1380
1381         return mp;
1382 }
1383
1384 static unsigned int
1385 rte_cryptodev_sym_session_data_size(struct rte_cryptodev_sym_session *sess)
1386 {
1387         return (sizeof(sess->sess_data[0]) * sess->nb_drivers) +
1388                         sess->user_data_sz;
1389 }
1390
1391 struct rte_cryptodev_sym_session *
1392 rte_cryptodev_sym_session_create(struct rte_mempool *mp)
1393 {
1394         struct rte_cryptodev_sym_session *sess;
1395         struct rte_cryptodev_sym_session_pool_private_data *pool_priv;
1396
1397         if (!mp) {
1398                 CDEV_LOG_ERR("Invalid mempool\n");
1399                 return NULL;
1400         }
1401
1402         pool_priv = rte_mempool_get_priv(mp);
1403
1404         if (!pool_priv || mp->private_data_size < sizeof(*pool_priv)) {
1405                 CDEV_LOG_ERR("Invalid mempool\n");
1406                 return NULL;
1407         }
1408
1409         /* Allocate a session structure from the session pool */
1410         if (rte_mempool_get(mp, (void **)&sess)) {
1411                 CDEV_LOG_ERR("couldn't get object from session mempool");
1412                 return NULL;
1413         }
1414
1415         sess->nb_drivers = pool_priv->nb_drivers;
1416         sess->user_data_sz = pool_priv->user_data_sz;
1417         sess->opaque_data = 0;
1418
1419         /* Clear device session pointer.
1420          * Include the flag indicating presence of user data
1421          */
1422         memset(sess->sess_data, 0,
1423                         rte_cryptodev_sym_session_data_size(sess));
1424
1425         return sess;
1426 }
1427
1428 struct rte_cryptodev_asym_session *
1429 rte_cryptodev_asym_session_create(struct rte_mempool *mp)
1430 {
1431         struct rte_cryptodev_asym_session *sess;
1432
1433         /* Allocate a session structure from the session pool */
1434         if (rte_mempool_get(mp, (void **)&sess)) {
1435                 CDEV_LOG_ERR("couldn't get object from session mempool");
1436                 return NULL;
1437         }
1438
1439         /* Clear device session pointer.
1440          * Include the flag indicating presence of private data
1441          */
1442         memset(sess, 0, (sizeof(void *) * nb_drivers) + sizeof(uint8_t));
1443
1444         return sess;
1445 }
1446
1447 int
1448 rte_cryptodev_sym_session_clear(uint8_t dev_id,
1449                 struct rte_cryptodev_sym_session *sess)
1450 {
1451         struct rte_cryptodev *dev;
1452         uint8_t driver_id;
1453
1454         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1455                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1456                 return -EINVAL;
1457         }
1458
1459         dev = rte_cryptodev_pmd_get_dev(dev_id);
1460
1461         if (dev == NULL || sess == NULL)
1462                 return -EINVAL;
1463
1464         driver_id = dev->driver_id;
1465         if (sess->sess_data[driver_id].refcnt == 0)
1466                 return 0;
1467         if (--sess->sess_data[driver_id].refcnt != 0)
1468                 return -EBUSY;
1469
1470         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->sym_session_clear, -ENOTSUP);
1471
1472         dev->dev_ops->sym_session_clear(dev, sess);
1473
1474         return 0;
1475 }
1476
1477 int
1478 rte_cryptodev_asym_session_clear(uint8_t dev_id,
1479                 struct rte_cryptodev_asym_session *sess)
1480 {
1481         struct rte_cryptodev *dev;
1482
1483         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1484                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1485                 return -EINVAL;
1486         }
1487
1488         dev = rte_cryptodev_pmd_get_dev(dev_id);
1489
1490         if (dev == NULL || sess == NULL)
1491                 return -EINVAL;
1492
1493         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_session_clear, -ENOTSUP);
1494
1495         dev->dev_ops->asym_session_clear(dev, sess);
1496
1497         return 0;
1498 }
1499
1500 int
1501 rte_cryptodev_sym_session_free(struct rte_cryptodev_sym_session *sess)
1502 {
1503         uint8_t i;
1504         struct rte_mempool *sess_mp;
1505
1506         if (sess == NULL)
1507                 return -EINVAL;
1508
1509         /* Check that all device private data has been freed */
1510         for (i = 0; i < sess->nb_drivers; i++) {
1511                 if (sess->sess_data[i].refcnt != 0)
1512                         return -EBUSY;
1513         }
1514
1515         /* Return session to mempool */
1516         sess_mp = rte_mempool_from_obj(sess);
1517         rte_mempool_put(sess_mp, sess);
1518
1519         return 0;
1520 }
1521
1522 int
1523 rte_cryptodev_asym_session_free(struct rte_cryptodev_asym_session *sess)
1524 {
1525         uint8_t i;
1526         void *sess_priv;
1527         struct rte_mempool *sess_mp;
1528
1529         if (sess == NULL)
1530                 return -EINVAL;
1531
1532         /* Check that all device private data has been freed */
1533         for (i = 0; i < nb_drivers; i++) {
1534                 sess_priv = get_asym_session_private_data(sess, i);
1535                 if (sess_priv != NULL)
1536                         return -EBUSY;
1537         }
1538
1539         /* Return session to mempool */
1540         sess_mp = rte_mempool_from_obj(sess);
1541         rte_mempool_put(sess_mp, sess);
1542
1543         return 0;
1544 }
1545
1546 unsigned int
1547 rte_cryptodev_sym_get_header_session_size(void)
1548 {
1549         /*
1550          * Header contains pointers to the private data of all registered
1551          * drivers and all necessary information to ensure safely clear
1552          * or free al session.
1553          */
1554         struct rte_cryptodev_sym_session s = {0};
1555
1556         s.nb_drivers = nb_drivers;
1557
1558         return (unsigned int)(sizeof(s) +
1559                         rte_cryptodev_sym_session_data_size(&s));
1560 }
1561
1562 unsigned int
1563 rte_cryptodev_sym_get_existing_header_session_size(
1564                 struct rte_cryptodev_sym_session *sess)
1565 {
1566         if (!sess)
1567                 return 0;
1568         else
1569                 return (unsigned int)(sizeof(*sess) +
1570                                 rte_cryptodev_sym_session_data_size(sess));
1571 }
1572
1573 unsigned int
1574 rte_cryptodev_asym_get_header_session_size(void)
1575 {
1576         /*
1577          * Header contains pointers to the private data
1578          * of all registered drivers, and a flag which
1579          * indicates presence of private data
1580          */
1581         return ((sizeof(void *) * nb_drivers) + sizeof(uint8_t));
1582 }
1583
1584 unsigned int
1585 rte_cryptodev_sym_get_private_session_size(uint8_t dev_id)
1586 {
1587         struct rte_cryptodev *dev;
1588         unsigned int priv_sess_size;
1589
1590         if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
1591                 return 0;
1592
1593         dev = rte_cryptodev_pmd_get_dev(dev_id);
1594
1595         if (*dev->dev_ops->sym_session_get_size == NULL)
1596                 return 0;
1597
1598         priv_sess_size = (*dev->dev_ops->sym_session_get_size)(dev);
1599
1600         return priv_sess_size;
1601 }
1602
1603 unsigned int
1604 rte_cryptodev_asym_get_private_session_size(uint8_t dev_id)
1605 {
1606         struct rte_cryptodev *dev;
1607         unsigned int header_size = sizeof(void *) * nb_drivers;
1608         unsigned int priv_sess_size;
1609
1610         if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
1611                 return 0;
1612
1613         dev = rte_cryptodev_pmd_get_dev(dev_id);
1614
1615         if (*dev->dev_ops->asym_session_get_size == NULL)
1616                 return 0;
1617
1618         priv_sess_size = (*dev->dev_ops->asym_session_get_size)(dev);
1619         if (priv_sess_size < header_size)
1620                 return header_size;
1621
1622         return priv_sess_size;
1623
1624 }
1625
1626 int
1627 rte_cryptodev_sym_session_set_user_data(
1628                                         struct rte_cryptodev_sym_session *sess,
1629                                         void *data,
1630                                         uint16_t size)
1631 {
1632         if (sess == NULL)
1633                 return -EINVAL;
1634
1635         if (sess->user_data_sz < size)
1636                 return -ENOMEM;
1637
1638         rte_memcpy(sess->sess_data + sess->nb_drivers, data, size);
1639         return 0;
1640 }
1641
1642 void *
1643 rte_cryptodev_sym_session_get_user_data(
1644                                         struct rte_cryptodev_sym_session *sess)
1645 {
1646         if (sess == NULL || sess->user_data_sz == 0)
1647                 return NULL;
1648
1649         return (void *)(sess->sess_data + sess->nb_drivers);
1650 }
1651
1652 static inline void
1653 sym_crypto_fill_status(struct rte_crypto_sym_vec *vec, int32_t errnum)
1654 {
1655         uint32_t i;
1656         for (i = 0; i < vec->num; i++)
1657                 vec->status[i] = errnum;
1658 }
1659
1660 uint32_t
1661 rte_cryptodev_sym_cpu_crypto_process(uint8_t dev_id,
1662         struct rte_cryptodev_sym_session *sess, union rte_crypto_sym_ofs ofs,
1663         struct rte_crypto_sym_vec *vec)
1664 {
1665         struct rte_cryptodev *dev;
1666
1667         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1668                 sym_crypto_fill_status(vec, EINVAL);
1669                 return 0;
1670         }
1671
1672         dev = rte_cryptodev_pmd_get_dev(dev_id);
1673
1674         if (*dev->dev_ops->sym_cpu_process == NULL ||
1675                 !(dev->feature_flags & RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO)) {
1676                 sym_crypto_fill_status(vec, ENOTSUP);
1677                 return 0;
1678         }
1679
1680         return dev->dev_ops->sym_cpu_process(dev, sess, ofs, vec);
1681 }
1682
1683 /** Initialise rte_crypto_op mempool element */
1684 static void
1685 rte_crypto_op_init(struct rte_mempool *mempool,
1686                 void *opaque_arg,
1687                 void *_op_data,
1688                 __rte_unused unsigned i)
1689 {
1690         struct rte_crypto_op *op = _op_data;
1691         enum rte_crypto_op_type type = *(enum rte_crypto_op_type *)opaque_arg;
1692
1693         memset(_op_data, 0, mempool->elt_size);
1694
1695         __rte_crypto_op_reset(op, type);
1696
1697         op->phys_addr = rte_mem_virt2iova(_op_data);
1698         op->mempool = mempool;
1699 }
1700
1701
1702 struct rte_mempool *
1703 rte_crypto_op_pool_create(const char *name, enum rte_crypto_op_type type,
1704                 unsigned nb_elts, unsigned cache_size, uint16_t priv_size,
1705                 int socket_id)
1706 {
1707         struct rte_crypto_op_pool_private *priv;
1708
1709         unsigned elt_size = sizeof(struct rte_crypto_op) +
1710                         priv_size;
1711
1712         if (type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
1713                 elt_size += sizeof(struct rte_crypto_sym_op);
1714         } else if (type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
1715                 elt_size += sizeof(struct rte_crypto_asym_op);
1716         } else if (type == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1717                 elt_size += RTE_MAX(sizeof(struct rte_crypto_sym_op),
1718                                     sizeof(struct rte_crypto_asym_op));
1719         } else {
1720                 CDEV_LOG_ERR("Invalid op_type\n");
1721                 return NULL;
1722         }
1723
1724         /* lookup mempool in case already allocated */
1725         struct rte_mempool *mp = rte_mempool_lookup(name);
1726
1727         if (mp != NULL) {
1728                 priv = (struct rte_crypto_op_pool_private *)
1729                                 rte_mempool_get_priv(mp);
1730
1731                 if (mp->elt_size != elt_size ||
1732                                 mp->cache_size < cache_size ||
1733                                 mp->size < nb_elts ||
1734                                 priv->priv_size <  priv_size) {
1735                         mp = NULL;
1736                         CDEV_LOG_ERR("Mempool %s already exists but with "
1737                                         "incompatible parameters", name);
1738                         return NULL;
1739                 }
1740                 return mp;
1741         }
1742
1743         mp = rte_mempool_create(
1744                         name,
1745                         nb_elts,
1746                         elt_size,
1747                         cache_size,
1748                         sizeof(struct rte_crypto_op_pool_private),
1749                         NULL,
1750                         NULL,
1751                         rte_crypto_op_init,
1752                         &type,
1753                         socket_id,
1754                         0);
1755
1756         if (mp == NULL) {
1757                 CDEV_LOG_ERR("Failed to create mempool %s", name);
1758                 return NULL;
1759         }
1760
1761         priv = (struct rte_crypto_op_pool_private *)
1762                         rte_mempool_get_priv(mp);
1763
1764         priv->priv_size = priv_size;
1765         priv->type = type;
1766
1767         return mp;
1768 }
1769
1770 int
1771 rte_cryptodev_pmd_create_dev_name(char *name, const char *dev_name_prefix)
1772 {
1773         struct rte_cryptodev *dev = NULL;
1774         uint32_t i = 0;
1775
1776         if (name == NULL)
1777                 return -EINVAL;
1778
1779         for (i = 0; i < RTE_CRYPTO_MAX_DEVS; i++) {
1780                 int ret = snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN,
1781                                 "%s_%u", dev_name_prefix, i);
1782
1783                 if (ret < 0)
1784                         return ret;
1785
1786                 dev = rte_cryptodev_pmd_get_named_dev(name);
1787                 if (!dev)
1788                         return 0;
1789         }
1790
1791         return -1;
1792 }
1793
1794 TAILQ_HEAD(cryptodev_driver_list, cryptodev_driver);
1795
1796 static struct cryptodev_driver_list cryptodev_driver_list =
1797         TAILQ_HEAD_INITIALIZER(cryptodev_driver_list);
1798
1799 int
1800 rte_cryptodev_driver_id_get(const char *name)
1801 {
1802         struct cryptodev_driver *driver;
1803         const char *driver_name;
1804
1805         if (name == NULL) {
1806                 RTE_LOG(DEBUG, CRYPTODEV, "name pointer NULL");
1807                 return -1;
1808         }
1809
1810         TAILQ_FOREACH(driver, &cryptodev_driver_list, next) {
1811                 driver_name = driver->driver->name;
1812                 if (strncmp(driver_name, name, strlen(driver_name) + 1) == 0)
1813                         return driver->id;
1814         }
1815         return -1;
1816 }
1817
1818 const char *
1819 rte_cryptodev_name_get(uint8_t dev_id)
1820 {
1821         struct rte_cryptodev *dev;
1822
1823         if (!rte_cryptodev_is_valid_device_data(dev_id)) {
1824                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1825                 return NULL;
1826         }
1827
1828         dev = rte_cryptodev_pmd_get_dev(dev_id);
1829         if (dev == NULL)
1830                 return NULL;
1831
1832         return dev->data->name;
1833 }
1834
1835 const char *
1836 rte_cryptodev_driver_name_get(uint8_t driver_id)
1837 {
1838         struct cryptodev_driver *driver;
1839
1840         TAILQ_FOREACH(driver, &cryptodev_driver_list, next)
1841                 if (driver->id == driver_id)
1842                         return driver->driver->name;
1843         return NULL;
1844 }
1845
1846 uint8_t
1847 rte_cryptodev_allocate_driver(struct cryptodev_driver *crypto_drv,
1848                 const struct rte_driver *drv)
1849 {
1850         crypto_drv->driver = drv;
1851         crypto_drv->id = nb_drivers;
1852
1853         TAILQ_INSERT_TAIL(&cryptodev_driver_list, crypto_drv, next);
1854
1855         return nb_drivers++;
1856 }