cryptodev: move session init out of pool creation
[dpdk.git] / lib / librte_cryptodev / rte_cryptodev.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2015-2017 Intel Corporation. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of Intel Corporation nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <sys/types.h>
34 #include <sys/queue.h>
35 #include <ctype.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include <errno.h>
41 #include <stdint.h>
42 #include <inttypes.h>
43 #include <netinet/in.h>
44
45 #include <rte_byteorder.h>
46 #include <rte_log.h>
47 #include <rte_debug.h>
48 #include <rte_dev.h>
49 #include <rte_interrupts.h>
50 #include <rte_memory.h>
51 #include <rte_memcpy.h>
52 #include <rte_memzone.h>
53 #include <rte_launch.h>
54 #include <rte_tailq.h>
55 #include <rte_eal.h>
56 #include <rte_per_lcore.h>
57 #include <rte_lcore.h>
58 #include <rte_atomic.h>
59 #include <rte_branch_prediction.h>
60 #include <rte_common.h>
61 #include <rte_mempool.h>
62 #include <rte_malloc.h>
63 #include <rte_mbuf.h>
64 #include <rte_errno.h>
65 #include <rte_spinlock.h>
66 #include <rte_string_fns.h>
67
68 #include "rte_crypto.h"
69 #include "rte_cryptodev.h"
70 #include "rte_cryptodev_pmd.h"
71
72 struct rte_cryptodev rte_crypto_devices[RTE_CRYPTO_MAX_DEVS];
73
74 struct rte_cryptodev *rte_cryptodevs = &rte_crypto_devices[0];
75
76 static struct rte_cryptodev_global cryptodev_globals = {
77                 .devs                   = &rte_crypto_devices[0],
78                 .data                   = { NULL },
79                 .nb_devs                = 0,
80                 .max_devs               = RTE_CRYPTO_MAX_DEVS
81 };
82
83 struct rte_cryptodev_global *rte_cryptodev_globals = &cryptodev_globals;
84
85 /* spinlock for crypto device callbacks */
86 static rte_spinlock_t rte_cryptodev_cb_lock = RTE_SPINLOCK_INITIALIZER;
87
88
89 /**
90  * The user application callback description.
91  *
92  * It contains callback address to be registered by user application,
93  * the pointer to the parameters for callback, and the event type.
94  */
95 struct rte_cryptodev_callback {
96         TAILQ_ENTRY(rte_cryptodev_callback) next; /**< Callbacks list */
97         rte_cryptodev_cb_fn cb_fn;              /**< Callback address */
98         void *cb_arg;                           /**< Parameter for callback */
99         enum rte_cryptodev_event_type event;    /**< Interrupt event type */
100         uint32_t active;                        /**< Callback is executing */
101 };
102
103 /**
104  * The crypto cipher algorithm strings identifiers.
105  * It could be used in application command line.
106  */
107 const char *
108 rte_crypto_cipher_algorithm_strings[] = {
109         [RTE_CRYPTO_CIPHER_3DES_CBC]    = "3des-cbc",
110         [RTE_CRYPTO_CIPHER_3DES_ECB]    = "3des-ecb",
111         [RTE_CRYPTO_CIPHER_3DES_CTR]    = "3des-ctr",
112
113         [RTE_CRYPTO_CIPHER_AES_CBC]     = "aes-cbc",
114         [RTE_CRYPTO_CIPHER_AES_CTR]     = "aes-ctr",
115         [RTE_CRYPTO_CIPHER_AES_DOCSISBPI]       = "aes-docsisbpi",
116         [RTE_CRYPTO_CIPHER_AES_ECB]     = "aes-ecb",
117         [RTE_CRYPTO_CIPHER_AES_F8]      = "aes-f8",
118         [RTE_CRYPTO_CIPHER_AES_XTS]     = "aes-xts",
119
120         [RTE_CRYPTO_CIPHER_ARC4]        = "arc4",
121
122         [RTE_CRYPTO_CIPHER_DES_CBC]     = "des-cbc",
123         [RTE_CRYPTO_CIPHER_DES_DOCSISBPI]       = "des-docsisbpi",
124
125         [RTE_CRYPTO_CIPHER_NULL]        = "null",
126
127         [RTE_CRYPTO_CIPHER_KASUMI_F8]   = "kasumi-f8",
128         [RTE_CRYPTO_CIPHER_SNOW3G_UEA2] = "snow3g-uea2",
129         [RTE_CRYPTO_CIPHER_ZUC_EEA3]    = "zuc-eea3"
130 };
131
132 /**
133  * The crypto cipher operation strings identifiers.
134  * It could be used in application command line.
135  */
136 const char *
137 rte_crypto_cipher_operation_strings[] = {
138                 [RTE_CRYPTO_CIPHER_OP_ENCRYPT]  = "encrypt",
139                 [RTE_CRYPTO_CIPHER_OP_DECRYPT]  = "decrypt"
140 };
141
142 /**
143  * The crypto auth algorithm strings identifiers.
144  * It could be used in application command line.
145  */
146 const char *
147 rte_crypto_auth_algorithm_strings[] = {
148         [RTE_CRYPTO_AUTH_AES_CBC_MAC]   = "aes-cbc-mac",
149         [RTE_CRYPTO_AUTH_AES_CMAC]      = "aes-cmac",
150         [RTE_CRYPTO_AUTH_AES_GMAC]      = "aes-gmac",
151         [RTE_CRYPTO_AUTH_AES_XCBC_MAC]  = "aes-xcbc-mac",
152
153         [RTE_CRYPTO_AUTH_MD5]           = "md5",
154         [RTE_CRYPTO_AUTH_MD5_HMAC]      = "md5-hmac",
155
156         [RTE_CRYPTO_AUTH_NULL]          = "null",
157
158         [RTE_CRYPTO_AUTH_SHA1]          = "sha1",
159         [RTE_CRYPTO_AUTH_SHA1_HMAC]     = "sha1-hmac",
160
161         [RTE_CRYPTO_AUTH_SHA224]        = "sha2-224",
162         [RTE_CRYPTO_AUTH_SHA224_HMAC]   = "sha2-224-hmac",
163         [RTE_CRYPTO_AUTH_SHA256]        = "sha2-256",
164         [RTE_CRYPTO_AUTH_SHA256_HMAC]   = "sha2-256-hmac",
165         [RTE_CRYPTO_AUTH_SHA384]        = "sha2-384",
166         [RTE_CRYPTO_AUTH_SHA384_HMAC]   = "sha2-384-hmac",
167         [RTE_CRYPTO_AUTH_SHA512]        = "sha2-512",
168         [RTE_CRYPTO_AUTH_SHA512_HMAC]   = "sha2-512-hmac",
169
170         [RTE_CRYPTO_AUTH_KASUMI_F9]     = "kasumi-f9",
171         [RTE_CRYPTO_AUTH_SNOW3G_UIA2]   = "snow3g-uia2",
172         [RTE_CRYPTO_AUTH_ZUC_EIA3]      = "zuc-eia3"
173 };
174
175 /**
176  * The crypto AEAD algorithm strings identifiers.
177  * It could be used in application command line.
178  */
179 const char *
180 rte_crypto_aead_algorithm_strings[] = {
181         [RTE_CRYPTO_AEAD_AES_CCM]       = "aes-ccm",
182         [RTE_CRYPTO_AEAD_AES_GCM]       = "aes-gcm",
183 };
184
185 /**
186  * The crypto AEAD operation strings identifiers.
187  * It could be used in application command line.
188  */
189 const char *
190 rte_crypto_aead_operation_strings[] = {
191         [RTE_CRYPTO_AEAD_OP_ENCRYPT]    = "encrypt",
192         [RTE_CRYPTO_AEAD_OP_DECRYPT]    = "decrypt"
193 };
194
195 int
196 rte_cryptodev_get_cipher_algo_enum(enum rte_crypto_cipher_algorithm *algo_enum,
197                 const char *algo_string)
198 {
199         unsigned int i;
200
201         for (i = 1; i < RTE_DIM(rte_crypto_cipher_algorithm_strings); i++) {
202                 if (strcmp(algo_string, rte_crypto_cipher_algorithm_strings[i]) == 0) {
203                         *algo_enum = (enum rte_crypto_cipher_algorithm) i;
204                         return 0;
205                 }
206         }
207
208         /* Invalid string */
209         return -1;
210 }
211
212 int
213 rte_cryptodev_get_auth_algo_enum(enum rte_crypto_auth_algorithm *algo_enum,
214                 const char *algo_string)
215 {
216         unsigned int i;
217
218         for (i = 1; i < RTE_DIM(rte_crypto_auth_algorithm_strings); i++) {
219                 if (strcmp(algo_string, rte_crypto_auth_algorithm_strings[i]) == 0) {
220                         *algo_enum = (enum rte_crypto_auth_algorithm) i;
221                         return 0;
222                 }
223         }
224
225         /* Invalid string */
226         return -1;
227 }
228
229 int
230 rte_cryptodev_get_aead_algo_enum(enum rte_crypto_aead_algorithm *algo_enum,
231                 const char *algo_string)
232 {
233         unsigned int i;
234
235         for (i = 1; i < RTE_DIM(rte_crypto_aead_algorithm_strings); i++) {
236                 if (strcmp(algo_string, rte_crypto_aead_algorithm_strings[i]) == 0) {
237                         *algo_enum = (enum rte_crypto_aead_algorithm) i;
238                         return 0;
239                 }
240         }
241
242         /* Invalid string */
243         return -1;
244 }
245
246 /**
247  * The crypto auth operation strings identifiers.
248  * It could be used in application command line.
249  */
250 const char *
251 rte_crypto_auth_operation_strings[] = {
252                 [RTE_CRYPTO_AUTH_OP_VERIFY]     = "verify",
253                 [RTE_CRYPTO_AUTH_OP_GENERATE]   = "generate"
254 };
255
256 const struct rte_cryptodev_symmetric_capability *
257 rte_cryptodev_sym_capability_get(uint8_t dev_id,
258                 const struct rte_cryptodev_sym_capability_idx *idx)
259 {
260         const struct rte_cryptodev_capabilities *capability;
261         struct rte_cryptodev_info dev_info;
262         int i = 0;
263
264         rte_cryptodev_info_get(dev_id, &dev_info);
265
266         while ((capability = &dev_info.capabilities[i++])->op !=
267                         RTE_CRYPTO_OP_TYPE_UNDEFINED) {
268                 if (capability->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC)
269                         continue;
270
271                 if (capability->sym.xform_type != idx->type)
272                         continue;
273
274                 if (idx->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
275                         capability->sym.auth.algo == idx->algo.auth)
276                         return &capability->sym;
277
278                 if (idx->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
279                         capability->sym.cipher.algo == idx->algo.cipher)
280                         return &capability->sym;
281
282                 if (idx->type == RTE_CRYPTO_SYM_XFORM_AEAD &&
283                                 capability->sym.aead.algo == idx->algo.aead)
284                         return &capability->sym;
285         }
286
287         return NULL;
288
289 }
290
291 #define param_range_check(x, y) \
292         (((x < y.min) || (x > y.max)) || \
293         (y.increment != 0 && (x % y.increment) != 0))
294
295 int
296 rte_cryptodev_sym_capability_check_cipher(
297                 const struct rte_cryptodev_symmetric_capability *capability,
298                 uint16_t key_size, uint16_t iv_size)
299 {
300         if (param_range_check(key_size, capability->cipher.key_size))
301                 return -1;
302
303         if (param_range_check(iv_size, capability->cipher.iv_size))
304                 return -1;
305
306         return 0;
307 }
308
309 int
310 rte_cryptodev_sym_capability_check_auth(
311                 const struct rte_cryptodev_symmetric_capability *capability,
312                 uint16_t key_size, uint16_t digest_size, uint16_t aad_size,
313                 uint16_t iv_size)
314 {
315         if (param_range_check(key_size, capability->auth.key_size))
316                 return -1;
317
318         if (param_range_check(digest_size, capability->auth.digest_size))
319                 return -1;
320
321         if (param_range_check(aad_size, capability->auth.aad_size))
322                 return -1;
323
324         if (param_range_check(iv_size, capability->auth.iv_size))
325                 return -1;
326
327         return 0;
328 }
329
330 int
331 rte_cryptodev_sym_capability_check_aead(
332                 const struct rte_cryptodev_symmetric_capability *capability,
333                 uint16_t key_size, uint16_t digest_size, uint16_t aad_size,
334                 uint16_t iv_size)
335 {
336         if (param_range_check(key_size, capability->aead.key_size))
337                 return -1;
338
339         if (param_range_check(digest_size, capability->aead.digest_size))
340                 return -1;
341
342         if (param_range_check(aad_size, capability->aead.aad_size))
343                 return -1;
344
345         if (param_range_check(iv_size, capability->aead.iv_size))
346                 return -1;
347
348         return 0;
349 }
350
351 const char *
352 rte_cryptodev_get_feature_name(uint64_t flag)
353 {
354         switch (flag) {
355         case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
356                 return "SYMMETRIC_CRYPTO";
357         case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
358                 return "ASYMMETRIC_CRYPTO";
359         case RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING:
360                 return "SYM_OPERATION_CHAINING";
361         case RTE_CRYPTODEV_FF_CPU_SSE:
362                 return "CPU_SSE";
363         case RTE_CRYPTODEV_FF_CPU_AVX:
364                 return "CPU_AVX";
365         case RTE_CRYPTODEV_FF_CPU_AVX2:
366                 return "CPU_AVX2";
367         case RTE_CRYPTODEV_FF_CPU_AESNI:
368                 return "CPU_AESNI";
369         case RTE_CRYPTODEV_FF_HW_ACCELERATED:
370                 return "HW_ACCELERATED";
371         case RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER:
372                 return "MBUF_SCATTER_GATHER";
373         case RTE_CRYPTODEV_FF_CPU_NEON:
374                 return "CPU_NEON";
375         case RTE_CRYPTODEV_FF_CPU_ARM_CE:
376                 return "CPU_ARM_CE";
377         default:
378                 return NULL;
379         }
380 }
381
382 int
383 rte_cryptodev_create_vdev(const char *name, const char *args)
384 {
385         return rte_vdev_init(name, args);
386 }
387
388 struct rte_cryptodev *
389 rte_cryptodev_pmd_get_dev(uint8_t dev_id)
390 {
391         return &rte_cryptodev_globals->devs[dev_id];
392 }
393
394 struct rte_cryptodev *
395 rte_cryptodev_pmd_get_named_dev(const char *name)
396 {
397         struct rte_cryptodev *dev;
398         unsigned int i;
399
400         if (name == NULL)
401                 return NULL;
402
403         for (i = 0; i < rte_cryptodev_globals->max_devs; i++) {
404                 dev = &rte_cryptodev_globals->devs[i];
405
406                 if ((dev->attached == RTE_CRYPTODEV_ATTACHED) &&
407                                 (strcmp(dev->data->name, name) == 0))
408                         return dev;
409         }
410
411         return NULL;
412 }
413
414 unsigned int
415 rte_cryptodev_pmd_is_valid_dev(uint8_t dev_id)
416 {
417         struct rte_cryptodev *dev = NULL;
418
419         if (dev_id >= rte_cryptodev_globals->nb_devs)
420                 return 0;
421
422         dev = rte_cryptodev_pmd_get_dev(dev_id);
423         if (dev->attached != RTE_CRYPTODEV_ATTACHED)
424                 return 0;
425         else
426                 return 1;
427 }
428
429
430 int
431 rte_cryptodev_get_dev_id(const char *name)
432 {
433         unsigned i;
434
435         if (name == NULL)
436                 return -1;
437
438         for (i = 0; i < rte_cryptodev_globals->nb_devs; i++)
439                 if ((strcmp(rte_cryptodev_globals->devs[i].data->name, name)
440                                 == 0) &&
441                                 (rte_cryptodev_globals->devs[i].attached ==
442                                                 RTE_CRYPTODEV_ATTACHED))
443                         return i;
444
445         return -1;
446 }
447
448 uint8_t
449 rte_cryptodev_count(void)
450 {
451         return rte_cryptodev_globals->nb_devs;
452 }
453
454 uint8_t
455 rte_cryptodev_device_count_by_driver(uint8_t driver_id)
456 {
457         uint8_t i, dev_count = 0;
458
459         for (i = 0; i < rte_cryptodev_globals->max_devs; i++)
460                 if (rte_cryptodev_globals->devs[i].driver_id == driver_id &&
461                         rte_cryptodev_globals->devs[i].attached ==
462                                         RTE_CRYPTODEV_ATTACHED)
463                         dev_count++;
464
465         return dev_count;
466 }
467
468 uint8_t
469 rte_cryptodev_devices_get(const char *driver_name, uint8_t *devices,
470         uint8_t nb_devices)
471 {
472         uint8_t i, count = 0;
473         struct rte_cryptodev *devs = rte_cryptodev_globals->devs;
474         uint8_t max_devs = rte_cryptodev_globals->max_devs;
475
476         for (i = 0; i < max_devs && count < nb_devices; i++) {
477
478                 if (devs[i].attached == RTE_CRYPTODEV_ATTACHED) {
479                         int cmp;
480
481                         cmp = strncmp(devs[i].device->driver->name,
482                                         driver_name,
483                                         strlen(driver_name));
484
485                         if (cmp == 0)
486                                 devices[count++] = devs[i].data->dev_id;
487                 }
488         }
489
490         return count;
491 }
492
493 int
494 rte_cryptodev_socket_id(uint8_t dev_id)
495 {
496         struct rte_cryptodev *dev;
497
498         if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
499                 return -1;
500
501         dev = rte_cryptodev_pmd_get_dev(dev_id);
502
503         return dev->data->socket_id;
504 }
505
506 static inline int
507 rte_cryptodev_data_alloc(uint8_t dev_id, struct rte_cryptodev_data **data,
508                 int socket_id)
509 {
510         char mz_name[RTE_CRYPTODEV_NAME_MAX_LEN];
511         const struct rte_memzone *mz;
512         int n;
513
514         /* generate memzone name */
515         n = snprintf(mz_name, sizeof(mz_name), "rte_cryptodev_data_%u", dev_id);
516         if (n >= (int)sizeof(mz_name))
517                 return -EINVAL;
518
519         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
520                 mz = rte_memzone_reserve(mz_name,
521                                 sizeof(struct rte_cryptodev_data),
522                                 socket_id, 0);
523         } else
524                 mz = rte_memzone_lookup(mz_name);
525
526         if (mz == NULL)
527                 return -ENOMEM;
528
529         *data = mz->addr;
530         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
531                 memset(*data, 0, sizeof(struct rte_cryptodev_data));
532
533         return 0;
534 }
535
536 static uint8_t
537 rte_cryptodev_find_free_device_index(void)
538 {
539         uint8_t dev_id;
540
541         for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++) {
542                 if (rte_crypto_devices[dev_id].attached ==
543                                 RTE_CRYPTODEV_DETACHED)
544                         return dev_id;
545         }
546         return RTE_CRYPTO_MAX_DEVS;
547 }
548
549 struct rte_cryptodev *
550 rte_cryptodev_pmd_allocate(const char *name, int socket_id)
551 {
552         struct rte_cryptodev *cryptodev;
553         uint8_t dev_id;
554
555         if (rte_cryptodev_pmd_get_named_dev(name) != NULL) {
556                 CDEV_LOG_ERR("Crypto device with name %s already "
557                                 "allocated!", name);
558                 return NULL;
559         }
560
561         dev_id = rte_cryptodev_find_free_device_index();
562         if (dev_id == RTE_CRYPTO_MAX_DEVS) {
563                 CDEV_LOG_ERR("Reached maximum number of crypto devices");
564                 return NULL;
565         }
566
567         cryptodev = rte_cryptodev_pmd_get_dev(dev_id);
568
569         if (cryptodev->data == NULL) {
570                 struct rte_cryptodev_data *cryptodev_data =
571                                 cryptodev_globals.data[dev_id];
572
573                 int retval = rte_cryptodev_data_alloc(dev_id, &cryptodev_data,
574                                 socket_id);
575
576                 if (retval < 0 || cryptodev_data == NULL)
577                         return NULL;
578
579                 cryptodev->data = cryptodev_data;
580
581                 snprintf(cryptodev->data->name, RTE_CRYPTODEV_NAME_MAX_LEN,
582                                 "%s", name);
583
584                 cryptodev->data->dev_id = dev_id;
585                 cryptodev->data->socket_id = socket_id;
586                 cryptodev->data->dev_started = 0;
587
588                 cryptodev->attached = RTE_CRYPTODEV_ATTACHED;
589
590                 cryptodev_globals.nb_devs++;
591         }
592
593         return cryptodev;
594 }
595
596 int
597 rte_cryptodev_pmd_release_device(struct rte_cryptodev *cryptodev)
598 {
599         int ret;
600
601         if (cryptodev == NULL)
602                 return -EINVAL;
603
604         /* Close device only if device operations have been set */
605         if (cryptodev->dev_ops) {
606                 ret = rte_cryptodev_close(cryptodev->data->dev_id);
607                 if (ret < 0)
608                         return ret;
609         }
610
611         cryptodev->attached = RTE_CRYPTODEV_DETACHED;
612         cryptodev_globals.nb_devs--;
613         return 0;
614 }
615
616 uint16_t
617 rte_cryptodev_queue_pair_count(uint8_t dev_id)
618 {
619         struct rte_cryptodev *dev;
620
621         dev = &rte_crypto_devices[dev_id];
622         return dev->data->nb_queue_pairs;
623 }
624
625 static int
626 rte_cryptodev_queue_pairs_config(struct rte_cryptodev *dev, uint16_t nb_qpairs,
627                 int socket_id)
628 {
629         struct rte_cryptodev_info dev_info;
630         void **qp;
631         unsigned i;
632
633         if ((dev == NULL) || (nb_qpairs < 1)) {
634                 CDEV_LOG_ERR("invalid param: dev %p, nb_queues %u",
635                                                         dev, nb_qpairs);
636                 return -EINVAL;
637         }
638
639         CDEV_LOG_DEBUG("Setup %d queues pairs on device %u",
640                         nb_qpairs, dev->data->dev_id);
641
642         memset(&dev_info, 0, sizeof(struct rte_cryptodev_info));
643
644         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
645         (*dev->dev_ops->dev_infos_get)(dev, &dev_info);
646
647         if (nb_qpairs > (dev_info.max_nb_queue_pairs)) {
648                 CDEV_LOG_ERR("Invalid num queue_pairs (%u) for dev %u",
649                                 nb_qpairs, dev->data->dev_id);
650             return -EINVAL;
651         }
652
653         if (dev->data->queue_pairs == NULL) { /* first time configuration */
654                 dev->data->queue_pairs = rte_zmalloc_socket(
655                                 "cryptodev->queue_pairs",
656                                 sizeof(dev->data->queue_pairs[0]) * nb_qpairs,
657                                 RTE_CACHE_LINE_SIZE, socket_id);
658
659                 if (dev->data->queue_pairs == NULL) {
660                         dev->data->nb_queue_pairs = 0;
661                         CDEV_LOG_ERR("failed to get memory for qp meta data, "
662                                                         "nb_queues %u",
663                                                         nb_qpairs);
664                         return -(ENOMEM);
665                 }
666         } else { /* re-configure */
667                 int ret;
668                 uint16_t old_nb_queues = dev->data->nb_queue_pairs;
669
670                 qp = dev->data->queue_pairs;
671
672                 RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_release,
673                                 -ENOTSUP);
674
675                 for (i = nb_qpairs; i < old_nb_queues; i++) {
676                         ret = (*dev->dev_ops->queue_pair_release)(dev, i);
677                         if (ret < 0)
678                                 return ret;
679                 }
680
681                 qp = rte_realloc(qp, sizeof(qp[0]) * nb_qpairs,
682                                 RTE_CACHE_LINE_SIZE);
683                 if (qp == NULL) {
684                         CDEV_LOG_ERR("failed to realloc qp meta data,"
685                                                 " nb_queues %u", nb_qpairs);
686                         return -(ENOMEM);
687                 }
688
689                 if (nb_qpairs > old_nb_queues) {
690                         uint16_t new_qs = nb_qpairs - old_nb_queues;
691
692                         memset(qp + old_nb_queues, 0,
693                                 sizeof(qp[0]) * new_qs);
694                 }
695
696                 dev->data->queue_pairs = qp;
697
698         }
699         dev->data->nb_queue_pairs = nb_qpairs;
700         return 0;
701 }
702
703 int
704 rte_cryptodev_queue_pair_start(uint8_t dev_id, uint16_t queue_pair_id)
705 {
706         struct rte_cryptodev *dev;
707
708         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
709                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
710                 return -EINVAL;
711         }
712
713         dev = &rte_crypto_devices[dev_id];
714         if (queue_pair_id >= dev->data->nb_queue_pairs) {
715                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
716                 return -EINVAL;
717         }
718
719         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_start, -ENOTSUP);
720
721         return dev->dev_ops->queue_pair_start(dev, queue_pair_id);
722
723 }
724
725 int
726 rte_cryptodev_queue_pair_stop(uint8_t dev_id, uint16_t queue_pair_id)
727 {
728         struct rte_cryptodev *dev;
729
730         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
731                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
732                 return -EINVAL;
733         }
734
735         dev = &rte_crypto_devices[dev_id];
736         if (queue_pair_id >= dev->data->nb_queue_pairs) {
737                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
738                 return -EINVAL;
739         }
740
741         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_stop, -ENOTSUP);
742
743         return dev->dev_ops->queue_pair_stop(dev, queue_pair_id);
744
745 }
746
747 static int
748 rte_cryptodev_sym_session_pool_create(struct rte_cryptodev *dev,
749                 unsigned nb_objs, unsigned obj_cache_size, int socket_id);
750
751 int
752 rte_cryptodev_configure(uint8_t dev_id, struct rte_cryptodev_config *config)
753 {
754         struct rte_cryptodev *dev;
755         int diag;
756
757         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
758                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
759                 return -EINVAL;
760         }
761
762         dev = &rte_crypto_devices[dev_id];
763
764         if (dev->data->dev_started) {
765                 CDEV_LOG_ERR(
766                     "device %d must be stopped to allow configuration", dev_id);
767                 return -EBUSY;
768         }
769
770         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);
771
772         /* Setup new number of queue pairs and reconfigure device. */
773         diag = rte_cryptodev_queue_pairs_config(dev, config->nb_queue_pairs,
774                         config->socket_id);
775         if (diag != 0) {
776                 CDEV_LOG_ERR("dev%d rte_crypto_dev_queue_pairs_config = %d",
777                                 dev_id, diag);
778                 return diag;
779         }
780
781         /* Setup Session mempool for device */
782         diag = rte_cryptodev_sym_session_pool_create(dev,
783                         config->session_mp.nb_objs,
784                         config->session_mp.cache_size,
785                         config->socket_id);
786         if (diag != 0)
787                 return diag;
788
789         return (*dev->dev_ops->dev_configure)(dev, config);
790 }
791
792
793 int
794 rte_cryptodev_start(uint8_t dev_id)
795 {
796         struct rte_cryptodev *dev;
797         int diag;
798
799         CDEV_LOG_DEBUG("Start dev_id=%" PRIu8, dev_id);
800
801         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
802                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
803                 return -EINVAL;
804         }
805
806         dev = &rte_crypto_devices[dev_id];
807
808         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP);
809
810         if (dev->data->dev_started != 0) {
811                 CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already started",
812                         dev_id);
813                 return 0;
814         }
815
816         diag = (*dev->dev_ops->dev_start)(dev);
817         if (diag == 0)
818                 dev->data->dev_started = 1;
819         else
820                 return diag;
821
822         return 0;
823 }
824
825 void
826 rte_cryptodev_stop(uint8_t dev_id)
827 {
828         struct rte_cryptodev *dev;
829
830         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
831                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
832                 return;
833         }
834
835         dev = &rte_crypto_devices[dev_id];
836
837         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);
838
839         if (dev->data->dev_started == 0) {
840                 CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already stopped",
841                         dev_id);
842                 return;
843         }
844
845         (*dev->dev_ops->dev_stop)(dev);
846         dev->data->dev_started = 0;
847 }
848
849 int
850 rte_cryptodev_close(uint8_t dev_id)
851 {
852         struct rte_cryptodev *dev;
853         int retval;
854
855         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
856                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
857                 return -1;
858         }
859
860         dev = &rte_crypto_devices[dev_id];
861
862         /* Device must be stopped before it can be closed */
863         if (dev->data->dev_started == 1) {
864                 CDEV_LOG_ERR("Device %u must be stopped before closing",
865                                 dev_id);
866                 return -EBUSY;
867         }
868
869         /* We can't close the device if there are outstanding sessions in use */
870         if (dev->data->session_pool != NULL) {
871                 if (!rte_mempool_full(dev->data->session_pool)) {
872                         CDEV_LOG_ERR("dev_id=%u close failed, session mempool "
873                                         "has sessions still in use, free "
874                                         "all sessions before calling close",
875                                         (unsigned)dev_id);
876                         return -EBUSY;
877                 }
878         }
879
880         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);
881         retval = (*dev->dev_ops->dev_close)(dev);
882
883         if (retval < 0)
884                 return retval;
885
886         return 0;
887 }
888
889 int
890 rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
891                 const struct rte_cryptodev_qp_conf *qp_conf, int socket_id)
892 {
893         struct rte_cryptodev *dev;
894
895         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
896                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
897                 return -EINVAL;
898         }
899
900         dev = &rte_crypto_devices[dev_id];
901         if (queue_pair_id >= dev->data->nb_queue_pairs) {
902                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
903                 return -EINVAL;
904         }
905
906         if (dev->data->dev_started) {
907                 CDEV_LOG_ERR(
908                     "device %d must be stopped to allow configuration", dev_id);
909                 return -EBUSY;
910         }
911
912         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_setup, -ENOTSUP);
913
914         return (*dev->dev_ops->queue_pair_setup)(dev, queue_pair_id, qp_conf,
915                         socket_id);
916 }
917
918
919 int
920 rte_cryptodev_stats_get(uint8_t dev_id, struct rte_cryptodev_stats *stats)
921 {
922         struct rte_cryptodev *dev;
923
924         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
925                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
926                 return -ENODEV;
927         }
928
929         if (stats == NULL) {
930                 CDEV_LOG_ERR("Invalid stats ptr");
931                 return -EINVAL;
932         }
933
934         dev = &rte_crypto_devices[dev_id];
935         memset(stats, 0, sizeof(*stats));
936
937         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_get, -ENOTSUP);
938         (*dev->dev_ops->stats_get)(dev, stats);
939         return 0;
940 }
941
942 void
943 rte_cryptodev_stats_reset(uint8_t dev_id)
944 {
945         struct rte_cryptodev *dev;
946
947         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
948                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
949                 return;
950         }
951
952         dev = &rte_crypto_devices[dev_id];
953
954         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
955         (*dev->dev_ops->stats_reset)(dev);
956 }
957
958
959 void
960 rte_cryptodev_info_get(uint8_t dev_id, struct rte_cryptodev_info *dev_info)
961 {
962         struct rte_cryptodev *dev;
963
964         if (dev_id >= cryptodev_globals.nb_devs) {
965                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
966                 return;
967         }
968
969         dev = &rte_crypto_devices[dev_id];
970
971         memset(dev_info, 0, sizeof(struct rte_cryptodev_info));
972
973         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
974         (*dev->dev_ops->dev_infos_get)(dev, dev_info);
975
976         dev_info->driver_name = dev->device->driver->name;
977 }
978
979
980 int
981 rte_cryptodev_callback_register(uint8_t dev_id,
982                         enum rte_cryptodev_event_type event,
983                         rte_cryptodev_cb_fn cb_fn, void *cb_arg)
984 {
985         struct rte_cryptodev *dev;
986         struct rte_cryptodev_callback *user_cb;
987
988         if (!cb_fn)
989                 return -EINVAL;
990
991         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
992                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
993                 return -EINVAL;
994         }
995
996         dev = &rte_crypto_devices[dev_id];
997         rte_spinlock_lock(&rte_cryptodev_cb_lock);
998
999         TAILQ_FOREACH(user_cb, &(dev->link_intr_cbs), next) {
1000                 if (user_cb->cb_fn == cb_fn &&
1001                         user_cb->cb_arg == cb_arg &&
1002                         user_cb->event == event) {
1003                         break;
1004                 }
1005         }
1006
1007         /* create a new callback. */
1008         if (user_cb == NULL) {
1009                 user_cb = rte_zmalloc("INTR_USER_CALLBACK",
1010                                 sizeof(struct rte_cryptodev_callback), 0);
1011                 if (user_cb != NULL) {
1012                         user_cb->cb_fn = cb_fn;
1013                         user_cb->cb_arg = cb_arg;
1014                         user_cb->event = event;
1015                         TAILQ_INSERT_TAIL(&(dev->link_intr_cbs), user_cb, next);
1016                 }
1017         }
1018
1019         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1020         return (user_cb == NULL) ? -ENOMEM : 0;
1021 }
1022
1023 int
1024 rte_cryptodev_callback_unregister(uint8_t dev_id,
1025                         enum rte_cryptodev_event_type event,
1026                         rte_cryptodev_cb_fn cb_fn, void *cb_arg)
1027 {
1028         int ret;
1029         struct rte_cryptodev *dev;
1030         struct rte_cryptodev_callback *cb, *next;
1031
1032         if (!cb_fn)
1033                 return -EINVAL;
1034
1035         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1036                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1037                 return -EINVAL;
1038         }
1039
1040         dev = &rte_crypto_devices[dev_id];
1041         rte_spinlock_lock(&rte_cryptodev_cb_lock);
1042
1043         ret = 0;
1044         for (cb = TAILQ_FIRST(&dev->link_intr_cbs); cb != NULL; cb = next) {
1045
1046                 next = TAILQ_NEXT(cb, next);
1047
1048                 if (cb->cb_fn != cb_fn || cb->event != event ||
1049                                 (cb->cb_arg != (void *)-1 &&
1050                                 cb->cb_arg != cb_arg))
1051                         continue;
1052
1053                 /*
1054                  * if this callback is not executing right now,
1055                  * then remove it.
1056                  */
1057                 if (cb->active == 0) {
1058                         TAILQ_REMOVE(&(dev->link_intr_cbs), cb, next);
1059                         rte_free(cb);
1060                 } else {
1061                         ret = -EAGAIN;
1062                 }
1063         }
1064
1065         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1066         return ret;
1067 }
1068
1069 void
1070 rte_cryptodev_pmd_callback_process(struct rte_cryptodev *dev,
1071         enum rte_cryptodev_event_type event)
1072 {
1073         struct rte_cryptodev_callback *cb_lst;
1074         struct rte_cryptodev_callback dev_cb;
1075
1076         rte_spinlock_lock(&rte_cryptodev_cb_lock);
1077         TAILQ_FOREACH(cb_lst, &(dev->link_intr_cbs), next) {
1078                 if (cb_lst->cb_fn == NULL || cb_lst->event != event)
1079                         continue;
1080                 dev_cb = *cb_lst;
1081                 cb_lst->active = 1;
1082                 rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1083                 dev_cb.cb_fn(dev->data->dev_id, dev_cb.event,
1084                                                 dev_cb.cb_arg);
1085                 rte_spinlock_lock(&rte_cryptodev_cb_lock);
1086                 cb_lst->active = 0;
1087         }
1088         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1089 }
1090
1091
1092 static void
1093 rte_cryptodev_sym_session_init(struct rte_mempool *mp,
1094                 const struct rte_cryptodev *dev,
1095                 struct rte_cryptodev_sym_session *sess)
1096 {
1097         memset(sess, 0, mp->elt_size);
1098
1099         sess->dev_id = dev->data->dev_id;
1100         sess->driver_id = dev->driver_id;
1101         sess->mp = mp;
1102
1103         if (dev->dev_ops->session_initialize)
1104                 (*dev->dev_ops->session_initialize)(mp, sess);
1105 }
1106
1107 static int
1108 rte_cryptodev_sym_session_pool_create(struct rte_cryptodev *dev,
1109                 unsigned nb_objs, unsigned obj_cache_size, int socket_id)
1110 {
1111         char mp_name[RTE_CRYPTODEV_NAME_MAX_LEN];
1112         unsigned priv_sess_size;
1113
1114         unsigned n = snprintf(mp_name, sizeof(mp_name), "cdev_%d_sess_mp",
1115                         dev->data->dev_id);
1116         if (n > sizeof(mp_name)) {
1117                 CDEV_LOG_ERR("Unable to create unique name for session mempool");
1118                 return -ENOMEM;
1119         }
1120
1121         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_get_size, -ENOTSUP);
1122         priv_sess_size = (*dev->dev_ops->session_get_size)(dev);
1123         if (priv_sess_size == 0) {
1124                 CDEV_LOG_ERR("%s returned and invalid private session size ",
1125                                                 dev->data->name);
1126                 return -ENOMEM;
1127         }
1128
1129         unsigned elt_size = sizeof(struct rte_cryptodev_sym_session) +
1130                         priv_sess_size;
1131
1132         dev->data->session_pool = rte_mempool_lookup(mp_name);
1133         if (dev->data->session_pool != NULL) {
1134                 if ((dev->data->session_pool->elt_size != elt_size) ||
1135                                 (dev->data->session_pool->cache_size <
1136                                 obj_cache_size) ||
1137                                 (dev->data->session_pool->size < nb_objs)) {
1138
1139                         CDEV_LOG_ERR("%s mempool already exists with different"
1140                                         " initialization parameters", mp_name);
1141                         dev->data->session_pool = NULL;
1142                         return -ENOMEM;
1143                 }
1144         } else {
1145                 dev->data->session_pool = rte_mempool_create(
1146                                 mp_name, /* mempool name */
1147                                 nb_objs, /* number of elements*/
1148                                 elt_size, /* element size*/
1149                                 obj_cache_size, /* Cache size*/
1150                                 0, /* private data size */
1151                                 NULL, /* obj initialization constructor */
1152                                 NULL, /* obj initialization constructor arg */
1153                                 NULL, /**< obj constructor*/
1154                                 dev, /* obj constructor arg */
1155                                 socket_id, /* socket id */
1156                                 0); /* flags */
1157
1158                 if (dev->data->session_pool == NULL) {
1159                         CDEV_LOG_ERR("%s mempool allocation failed", mp_name);
1160                         return -ENOMEM;
1161                 }
1162         }
1163
1164         CDEV_LOG_DEBUG("%s mempool created!", mp_name);
1165         return 0;
1166 }
1167
1168 struct rte_cryptodev_sym_session *
1169 rte_cryptodev_sym_session_create(uint8_t dev_id,
1170                 struct rte_crypto_sym_xform *xform)
1171 {
1172         struct rte_cryptodev *dev;
1173         struct rte_cryptodev_sym_session *sess;
1174         void *_sess;
1175
1176         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1177                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
1178                 return NULL;
1179         }
1180
1181         dev = &rte_crypto_devices[dev_id];
1182
1183         /* Allocate a session structure from the session pool */
1184         if (rte_mempool_get(dev->data->session_pool, &_sess)) {
1185                 CDEV_LOG_ERR("Couldn't get object from session mempool");
1186                 return NULL;
1187         }
1188
1189         sess = _sess;
1190
1191         rte_cryptodev_sym_session_init(dev->data->session_pool, dev,
1192                                         sess);
1193         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_configure, NULL);
1194         if (dev->dev_ops->session_configure(dev, xform, sess->_private) ==
1195                         NULL) {
1196                 CDEV_LOG_ERR("dev_id %d failed to configure session details",
1197                                 dev_id);
1198
1199                 /* Return session to mempool */
1200                 rte_mempool_put(sess->mp, _sess);
1201                 return NULL;
1202         }
1203
1204         return sess;
1205 }
1206
1207 int
1208 rte_cryptodev_queue_pair_attach_sym_session(uint16_t qp_id,
1209                 struct rte_cryptodev_sym_session *sess)
1210 {
1211         struct rte_cryptodev *dev;
1212
1213         if (!rte_cryptodev_pmd_is_valid_dev(sess->dev_id)) {
1214                 CDEV_LOG_ERR("Invalid dev_id=%d", sess->dev_id);
1215                 return -EINVAL;
1216         }
1217
1218         dev = &rte_crypto_devices[sess->dev_id];
1219
1220         /* The API is optional, not returning error if driver do not suuport */
1221         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->qp_attach_session, 0);
1222         if (dev->dev_ops->qp_attach_session(dev, qp_id, sess->_private)) {
1223                 CDEV_LOG_ERR("dev_id %d failed to attach qp: %d with session",
1224                                 sess->dev_id, qp_id);
1225                 return -EPERM;
1226         }
1227
1228         return 0;
1229 }
1230
1231 int
1232 rte_cryptodev_queue_pair_detach_sym_session(uint16_t qp_id,
1233                 struct rte_cryptodev_sym_session *sess)
1234 {
1235         struct rte_cryptodev *dev;
1236
1237         if (!rte_cryptodev_pmd_is_valid_dev(sess->dev_id)) {
1238                 CDEV_LOG_ERR("Invalid dev_id=%d", sess->dev_id);
1239                 return -EINVAL;
1240         }
1241
1242         dev = &rte_crypto_devices[sess->dev_id];
1243
1244         /* The API is optional, not returning error if driver do not suuport */
1245         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->qp_detach_session, 0);
1246         if (dev->dev_ops->qp_detach_session(dev, qp_id, sess->_private)) {
1247                 CDEV_LOG_ERR("dev_id %d failed to detach qp: %d from session",
1248                                 sess->dev_id, qp_id);
1249                 return -EPERM;
1250         }
1251
1252         return 0;
1253 }
1254 struct rte_cryptodev_sym_session *
1255 rte_cryptodev_sym_session_free(uint8_t dev_id,
1256                 struct rte_cryptodev_sym_session *sess)
1257 {
1258         struct rte_cryptodev *dev;
1259
1260         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1261                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
1262                 return sess;
1263         }
1264
1265         dev = &rte_crypto_devices[dev_id];
1266
1267         /* Check the session belongs to this device type */
1268         if (sess->driver_id != dev->driver_id)
1269                 return sess;
1270
1271         /* Let device implementation clear session material */
1272         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_clear, sess);
1273         dev->dev_ops->session_clear(dev, (void *)sess->_private);
1274
1275         /* Return session to mempool */
1276         rte_mempool_put(sess->mp, (void *)sess);
1277
1278         return NULL;
1279 }
1280
1281 /** Initialise rte_crypto_op mempool element */
1282 static void
1283 rte_crypto_op_init(struct rte_mempool *mempool,
1284                 void *opaque_arg,
1285                 void *_op_data,
1286                 __rte_unused unsigned i)
1287 {
1288         struct rte_crypto_op *op = _op_data;
1289         enum rte_crypto_op_type type = *(enum rte_crypto_op_type *)opaque_arg;
1290
1291         memset(_op_data, 0, mempool->elt_size);
1292
1293         __rte_crypto_op_reset(op, type);
1294
1295         op->phys_addr = rte_mem_virt2phy(_op_data);
1296         op->mempool = mempool;
1297 }
1298
1299
1300 struct rte_mempool *
1301 rte_crypto_op_pool_create(const char *name, enum rte_crypto_op_type type,
1302                 unsigned nb_elts, unsigned cache_size, uint16_t priv_size,
1303                 int socket_id)
1304 {
1305         struct rte_crypto_op_pool_private *priv;
1306
1307         unsigned elt_size = sizeof(struct rte_crypto_op) +
1308                         sizeof(struct rte_crypto_sym_op) +
1309                         priv_size;
1310
1311         /* lookup mempool in case already allocated */
1312         struct rte_mempool *mp = rte_mempool_lookup(name);
1313
1314         if (mp != NULL) {
1315                 priv = (struct rte_crypto_op_pool_private *)
1316                                 rte_mempool_get_priv(mp);
1317
1318                 if (mp->elt_size != elt_size ||
1319                                 mp->cache_size < cache_size ||
1320                                 mp->size < nb_elts ||
1321                                 priv->priv_size <  priv_size) {
1322                         mp = NULL;
1323                         CDEV_LOG_ERR("Mempool %s already exists but with "
1324                                         "incompatible parameters", name);
1325                         return NULL;
1326                 }
1327                 return mp;
1328         }
1329
1330         mp = rte_mempool_create(
1331                         name,
1332                         nb_elts,
1333                         elt_size,
1334                         cache_size,
1335                         sizeof(struct rte_crypto_op_pool_private),
1336                         NULL,
1337                         NULL,
1338                         rte_crypto_op_init,
1339                         &type,
1340                         socket_id,
1341                         0);
1342
1343         if (mp == NULL) {
1344                 CDEV_LOG_ERR("Failed to create mempool %s", name);
1345                 return NULL;
1346         }
1347
1348         priv = (struct rte_crypto_op_pool_private *)
1349                         rte_mempool_get_priv(mp);
1350
1351         priv->priv_size = priv_size;
1352         priv->type = type;
1353
1354         return mp;
1355 }
1356
1357 int
1358 rte_cryptodev_pmd_create_dev_name(char *name, const char *dev_name_prefix)
1359 {
1360         struct rte_cryptodev *dev = NULL;
1361         uint32_t i = 0;
1362
1363         if (name == NULL)
1364                 return -EINVAL;
1365
1366         for (i = 0; i < RTE_CRYPTO_MAX_DEVS; i++) {
1367                 int ret = snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN,
1368                                 "%s_%u", dev_name_prefix, i);
1369
1370                 if (ret < 0)
1371                         return ret;
1372
1373                 dev = rte_cryptodev_pmd_get_named_dev(name);
1374                 if (!dev)
1375                         return 0;
1376         }
1377
1378         return -1;
1379 }
1380
1381 TAILQ_HEAD(cryptodev_driver_list, cryptodev_driver);
1382
1383 static struct cryptodev_driver_list cryptodev_driver_list =
1384         TAILQ_HEAD_INITIALIZER(cryptodev_driver_list);
1385
1386 struct cryptodev_driver {
1387         TAILQ_ENTRY(cryptodev_driver) next; /**< Next in list. */
1388         const struct rte_driver *driver;
1389         uint8_t id;
1390 };
1391
1392 static uint8_t nb_drivers;
1393
1394 int
1395 rte_cryptodev_driver_id_get(const char *name)
1396 {
1397         struct cryptodev_driver *driver;
1398         const char *driver_name;
1399
1400         if (name == NULL) {
1401                 RTE_LOG(DEBUG, CRYPTODEV, "name pointer NULL");
1402                 return -1;
1403         }
1404
1405         TAILQ_FOREACH(driver, &cryptodev_driver_list, next) {
1406                 driver_name = driver->driver->name;
1407                 if (strncmp(driver_name, name, strlen(driver_name)) == 0)
1408                         return driver->id;
1409         }
1410         return -1;
1411 }
1412
1413 const char *
1414 rte_cryptodev_driver_name_get(uint8_t driver_id)
1415 {
1416         struct cryptodev_driver *driver;
1417
1418         TAILQ_FOREACH(driver, &cryptodev_driver_list, next)
1419                 if (driver->id == driver_id)
1420                         return driver->driver->name;
1421         return NULL;
1422 }
1423
1424 uint8_t
1425 rte_cryptodev_allocate_driver(const struct rte_driver *drv)
1426 {
1427         struct cryptodev_driver *driver;
1428
1429         driver = malloc(sizeof(*driver));
1430         driver->driver = drv;
1431         driver->id = nb_drivers;
1432
1433         TAILQ_INSERT_TAIL(&cryptodev_driver_list, driver, next);
1434
1435         return nb_drivers++;
1436 }