cryptodev: uninline some functions
[dpdk.git] / lib / librte_cryptodev / rte_cryptodev.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2015-2016 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_pci.h>
51 #include <rte_memory.h>
52 #include <rte_memcpy.h>
53 #include <rte_memzone.h>
54 #include <rte_launch.h>
55 #include <rte_tailq.h>
56 #include <rte_eal.h>
57 #include <rte_per_lcore.h>
58 #include <rte_lcore.h>
59 #include <rte_atomic.h>
60 #include <rte_branch_prediction.h>
61 #include <rte_common.h>
62 #include <rte_mempool.h>
63 #include <rte_malloc.h>
64 #include <rte_mbuf.h>
65 #include <rte_errno.h>
66 #include <rte_spinlock.h>
67 #include <rte_string_fns.h>
68
69 #include "rte_crypto.h"
70 #include "rte_cryptodev.h"
71 #include "rte_cryptodev_pmd.h"
72
73 struct rte_cryptodev rte_crypto_devices[RTE_CRYPTO_MAX_DEVS];
74
75 struct rte_cryptodev *rte_cryptodevs = &rte_crypto_devices[0];
76
77 static struct rte_cryptodev_global cryptodev_globals = {
78                 .devs                   = &rte_crypto_devices[0],
79                 .data                   = { NULL },
80                 .nb_devs                = 0,
81                 .max_devs               = RTE_CRYPTO_MAX_DEVS
82 };
83
84 struct rte_cryptodev_global *rte_cryptodev_globals = &cryptodev_globals;
85
86 /* spinlock for crypto device callbacks */
87 static rte_spinlock_t rte_cryptodev_cb_lock = RTE_SPINLOCK_INITIALIZER;
88
89
90 /**
91  * The user application callback description.
92  *
93  * It contains callback address to be registered by user application,
94  * the pointer to the parameters for callback, and the event type.
95  */
96 struct rte_cryptodev_callback {
97         TAILQ_ENTRY(rte_cryptodev_callback) next; /**< Callbacks list */
98         rte_cryptodev_cb_fn cb_fn;              /**< Callback address */
99         void *cb_arg;                           /**< Parameter for callback */
100         enum rte_cryptodev_event_type event;    /**< Interrupt event type */
101         uint32_t active;                        /**< Callback is executing */
102 };
103
104 #define RTE_CRYPTODEV_VDEV_NAME                         ("name")
105 #define RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG                ("max_nb_queue_pairs")
106 #define RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG              ("max_nb_sessions")
107 #define RTE_CRYPTODEV_VDEV_SOCKET_ID                    ("socket_id")
108
109 static const char *cryptodev_vdev_valid_params[] = {
110         RTE_CRYPTODEV_VDEV_NAME,
111         RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
112         RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
113         RTE_CRYPTODEV_VDEV_SOCKET_ID
114 };
115
116 static uint8_t
117 number_of_sockets(void)
118 {
119         int sockets = 0;
120         int i;
121         const struct rte_memseg *ms = rte_eal_get_physmem_layout();
122
123         for (i = 0; ((i < RTE_MAX_MEMSEG) && (ms[i].addr != NULL)); i++) {
124                 if (sockets < ms[i].socket_id)
125                         sockets = ms[i].socket_id;
126         }
127
128         /* Number of sockets = maximum socket_id + 1 */
129         return ++sockets;
130 }
131
132 /** Parse integer from integer argument */
133 static int
134 parse_integer_arg(const char *key __rte_unused,
135                 const char *value, void *extra_args)
136 {
137         int *i = (int *) extra_args;
138
139         *i = atoi(value);
140         if (*i < 0) {
141                 CDEV_LOG_ERR("Argument has to be positive.");
142                 return -1;
143         }
144
145         return 0;
146 }
147
148 /** Parse name */
149 static int
150 parse_name_arg(const char *key __rte_unused,
151                 const char *value, void *extra_args)
152 {
153         struct rte_crypto_vdev_init_params *params = extra_args;
154
155         if (strlen(value) >= RTE_CRYPTODEV_NAME_MAX_LEN - 1) {
156                 CDEV_LOG_ERR("Invalid name %s, should be less than "
157                                 "%u bytes", value,
158                                 RTE_CRYPTODEV_NAME_MAX_LEN - 1);
159                 return -1;
160         }
161
162         strncpy(params->name, value, RTE_CRYPTODEV_NAME_MAX_LEN);
163
164         return 0;
165 }
166
167 int
168 rte_cryptodev_parse_vdev_init_params(struct rte_crypto_vdev_init_params *params,
169                 const char *input_args)
170 {
171         struct rte_kvargs *kvlist = NULL;
172         int ret = 0;
173
174         if (params == NULL)
175                 return -EINVAL;
176
177         if (input_args) {
178                 kvlist = rte_kvargs_parse(input_args,
179                                 cryptodev_vdev_valid_params);
180                 if (kvlist == NULL)
181                         return -1;
182
183                 ret = rte_kvargs_process(kvlist,
184                                         RTE_CRYPTODEV_VDEV_MAX_NB_QP_ARG,
185                                         &parse_integer_arg,
186                                         &params->max_nb_queue_pairs);
187                 if (ret < 0)
188                         goto free_kvlist;
189
190                 ret = rte_kvargs_process(kvlist,
191                                         RTE_CRYPTODEV_VDEV_MAX_NB_SESS_ARG,
192                                         &parse_integer_arg,
193                                         &params->max_nb_sessions);
194                 if (ret < 0)
195                         goto free_kvlist;
196
197                 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_SOCKET_ID,
198                                         &parse_integer_arg,
199                                         &params->socket_id);
200                 if (ret < 0)
201                         goto free_kvlist;
202
203                 ret = rte_kvargs_process(kvlist, RTE_CRYPTODEV_VDEV_NAME,
204                                         &parse_name_arg,
205                                         params);
206                 if (ret < 0)
207                         goto free_kvlist;
208
209                 if (params->socket_id >= number_of_sockets()) {
210                         CDEV_LOG_ERR("Invalid socket id specified to create "
211                                 "the virtual crypto device on");
212                         goto free_kvlist;
213                 }
214         }
215
216 free_kvlist:
217         rte_kvargs_free(kvlist);
218         return ret;
219 }
220
221 const char *
222 rte_cryptodev_get_feature_name(uint64_t flag)
223 {
224         switch (flag) {
225         case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
226                 return "SYMMETRIC_CRYPTO";
227         case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
228                 return "ASYMMETRIC_CRYPTO";
229         case RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING:
230                 return "SYM_OPERATION_CHAINING";
231         case RTE_CRYPTODEV_FF_CPU_SSE:
232                 return "CPU_SSE";
233         case RTE_CRYPTODEV_FF_CPU_AVX:
234                 return "CPU_AVX";
235         case RTE_CRYPTODEV_FF_CPU_AVX2:
236                 return "CPU_AVX2";
237         case RTE_CRYPTODEV_FF_CPU_AESNI:
238                 return "CPU_AESNI";
239         case RTE_CRYPTODEV_FF_HW_ACCELERATED:
240                 return "HW_ACCELERATED";
241         case RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER:
242                 return "MBUF_SCATTER_GATHER";
243         case RTE_CRYPTODEV_FF_CPU_NEON:
244                 return "CPU_NEON";
245         case RTE_CRYPTODEV_FF_CPU_ARM_CE:
246                 return "CPU_ARM_CE";
247         default:
248                 return NULL;
249         }
250 }
251
252 int
253 rte_cryptodev_create_vdev(const char *name, const char *args)
254 {
255         return rte_eal_vdev_init(name, args);
256 }
257
258 struct rte_cryptodev *
259 rte_cryptodev_pmd_get_dev(uint8_t dev_id)
260 {
261         return &rte_cryptodev_globals->devs[dev_id];
262 }
263
264 struct rte_cryptodev *
265 rte_cryptodev_pmd_get_named_dev(const char *name)
266 {
267         struct rte_cryptodev *dev;
268         unsigned int i;
269
270         if (name == NULL)
271                 return NULL;
272
273         for (i = 0; i < rte_cryptodev_globals->max_devs; i++) {
274                 dev = &rte_cryptodev_globals->devs[i];
275
276                 if ((dev->attached == RTE_CRYPTODEV_ATTACHED) &&
277                                 (strcmp(dev->data->name, name) == 0))
278                         return dev;
279         }
280
281         return NULL;
282 }
283
284 unsigned int
285 rte_cryptodev_pmd_is_valid_dev(uint8_t dev_id)
286 {
287         struct rte_cryptodev *dev = NULL;
288
289         if (dev_id >= rte_cryptodev_globals->nb_devs)
290                 return 0;
291
292         dev = rte_cryptodev_pmd_get_dev(dev_id);
293         if (dev->attached != RTE_CRYPTODEV_ATTACHED)
294                 return 0;
295         else
296                 return 1;
297 }
298
299
300 int
301 rte_cryptodev_get_dev_id(const char *name)
302 {
303         unsigned i;
304
305         if (name == NULL)
306                 return -1;
307
308         for (i = 0; i < rte_cryptodev_globals->nb_devs; i++)
309                 if ((strcmp(rte_cryptodev_globals->devs[i].data->name, name)
310                                 == 0) &&
311                                 (rte_cryptodev_globals->devs[i].attached ==
312                                                 RTE_CRYPTODEV_ATTACHED))
313                         return i;
314
315         return -1;
316 }
317
318 uint8_t
319 rte_cryptodev_count(void)
320 {
321         return rte_cryptodev_globals->nb_devs;
322 }
323
324 uint8_t
325 rte_cryptodev_count_devtype(enum rte_cryptodev_type type)
326 {
327         uint8_t i, dev_count = 0;
328
329         for (i = 0; i < rte_cryptodev_globals->max_devs; i++)
330                 if (rte_cryptodev_globals->devs[i].dev_type == type &&
331                         rte_cryptodev_globals->devs[i].attached ==
332                                         RTE_CRYPTODEV_ATTACHED)
333                         dev_count++;
334
335         return dev_count;
336 }
337
338 int
339 rte_cryptodev_socket_id(uint8_t dev_id)
340 {
341         struct rte_cryptodev *dev;
342
343         if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
344                 return -1;
345
346         dev = rte_cryptodev_pmd_get_dev(dev_id);
347
348         return dev->data->socket_id;
349 }
350
351 static inline int
352 rte_cryptodev_data_alloc(uint8_t dev_id, struct rte_cryptodev_data **data,
353                 int socket_id)
354 {
355         char mz_name[RTE_CRYPTODEV_NAME_MAX_LEN];
356         const struct rte_memzone *mz;
357         int n;
358
359         /* generate memzone name */
360         n = snprintf(mz_name, sizeof(mz_name), "rte_cryptodev_data_%u", dev_id);
361         if (n >= (int)sizeof(mz_name))
362                 return -EINVAL;
363
364         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
365                 mz = rte_memzone_reserve(mz_name,
366                                 sizeof(struct rte_cryptodev_data),
367                                 socket_id, 0);
368         } else
369                 mz = rte_memzone_lookup(mz_name);
370
371         if (mz == NULL)
372                 return -ENOMEM;
373
374         *data = mz->addr;
375         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
376                 memset(*data, 0, sizeof(struct rte_cryptodev_data));
377
378         return 0;
379 }
380
381 static uint8_t
382 rte_cryptodev_find_free_device_index(void)
383 {
384         uint8_t dev_id;
385
386         for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++) {
387                 if (rte_crypto_devices[dev_id].attached ==
388                                 RTE_CRYPTODEV_DETACHED)
389                         return dev_id;
390         }
391         return RTE_CRYPTO_MAX_DEVS;
392 }
393
394 struct rte_cryptodev *
395 rte_cryptodev_pmd_allocate(const char *name, int socket_id)
396 {
397         struct rte_cryptodev *cryptodev;
398         uint8_t dev_id;
399
400         if (rte_cryptodev_pmd_get_named_dev(name) != NULL) {
401                 CDEV_LOG_ERR("Crypto device with name %s already "
402                                 "allocated!", name);
403                 return NULL;
404         }
405
406         dev_id = rte_cryptodev_find_free_device_index();
407         if (dev_id == RTE_CRYPTO_MAX_DEVS) {
408                 CDEV_LOG_ERR("Reached maximum number of crypto devices");
409                 return NULL;
410         }
411
412         cryptodev = rte_cryptodev_pmd_get_dev(dev_id);
413
414         if (cryptodev->data == NULL) {
415                 struct rte_cryptodev_data *cryptodev_data =
416                                 cryptodev_globals.data[dev_id];
417
418                 int retval = rte_cryptodev_data_alloc(dev_id, &cryptodev_data,
419                                 socket_id);
420
421                 if (retval < 0 || cryptodev_data == NULL)
422                         return NULL;
423
424                 cryptodev->data = cryptodev_data;
425
426                 snprintf(cryptodev->data->name, RTE_CRYPTODEV_NAME_MAX_LEN,
427                                 "%s", name);
428
429                 cryptodev->data->dev_id = dev_id;
430                 cryptodev->data->socket_id = socket_id;
431                 cryptodev->data->dev_started = 0;
432
433                 cryptodev->attached = RTE_CRYPTODEV_ATTACHED;
434
435                 cryptodev_globals.nb_devs++;
436         }
437
438         return cryptodev;
439 }
440
441 int
442 rte_cryptodev_pmd_release_device(struct rte_cryptodev *cryptodev)
443 {
444         int ret;
445
446         if (cryptodev == NULL)
447                 return -EINVAL;
448
449         ret = rte_cryptodev_close(cryptodev->data->dev_id);
450         if (ret < 0)
451                 return ret;
452
453         cryptodev->attached = RTE_CRYPTODEV_DETACHED;
454         cryptodev_globals.nb_devs--;
455         return 0;
456 }
457
458 struct rte_cryptodev *
459 rte_cryptodev_pmd_virtual_dev_init(const char *name, size_t dev_private_size,
460                 int socket_id)
461 {
462         struct rte_cryptodev *cryptodev;
463
464         /* allocate device structure */
465         cryptodev = rte_cryptodev_pmd_allocate(name, socket_id);
466         if (cryptodev == NULL)
467                 return NULL;
468
469         /* allocate private device structure */
470         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
471                 cryptodev->data->dev_private =
472                                 rte_zmalloc_socket("cryptodev device private",
473                                                 dev_private_size,
474                                                 RTE_CACHE_LINE_SIZE,
475                                                 socket_id);
476
477                 if (cryptodev->data->dev_private == NULL)
478                         rte_panic("Cannot allocate memzone for private device"
479                                         " data");
480         }
481
482         /* initialise user call-back tail queue */
483         TAILQ_INIT(&(cryptodev->link_intr_cbs));
484
485         return cryptodev;
486 }
487
488 int
489 rte_cryptodev_pci_probe(struct rte_pci_driver *pci_drv,
490                         struct rte_pci_device *pci_dev)
491 {
492         struct rte_cryptodev_driver *cryptodrv;
493         struct rte_cryptodev *cryptodev;
494
495         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
496
497         int retval;
498
499         cryptodrv = (struct rte_cryptodev_driver *)pci_drv;
500         if (cryptodrv == NULL)
501                 return -ENODEV;
502
503         rte_eal_pci_device_name(&pci_dev->addr, cryptodev_name,
504                         sizeof(cryptodev_name));
505
506         cryptodev = rte_cryptodev_pmd_allocate(cryptodev_name, rte_socket_id());
507         if (cryptodev == NULL)
508                 return -ENOMEM;
509
510         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
511                 cryptodev->data->dev_private =
512                                 rte_zmalloc_socket(
513                                                 "cryptodev private structure",
514                                                 cryptodrv->dev_private_size,
515                                                 RTE_CACHE_LINE_SIZE,
516                                                 rte_socket_id());
517
518                 if (cryptodev->data->dev_private == NULL)
519                         rte_panic("Cannot allocate memzone for private "
520                                         "device data");
521         }
522
523         cryptodev->pci_dev = pci_dev;
524         cryptodev->driver = cryptodrv;
525
526         /* init user callbacks */
527         TAILQ_INIT(&(cryptodev->link_intr_cbs));
528
529         /* Invoke PMD device initialization function */
530         retval = (*cryptodrv->cryptodev_init)(cryptodrv, cryptodev);
531         if (retval == 0)
532                 return 0;
533
534         CDEV_LOG_ERR("driver %s: crypto_dev_init(vendor_id=0x%x device_id=0x%x)"
535                         " failed", pci_drv->driver.name,
536                         (unsigned) pci_dev->id.vendor_id,
537                         (unsigned) pci_dev->id.device_id);
538
539         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
540                 rte_free(cryptodev->data->dev_private);
541
542         cryptodev->attached = RTE_CRYPTODEV_DETACHED;
543         cryptodev_globals.nb_devs--;
544
545         return -ENXIO;
546 }
547
548 int
549 rte_cryptodev_pci_remove(struct rte_pci_device *pci_dev)
550 {
551         const struct rte_cryptodev_driver *cryptodrv;
552         struct rte_cryptodev *cryptodev;
553         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
554         int ret;
555
556         if (pci_dev == NULL)
557                 return -EINVAL;
558
559         rte_eal_pci_device_name(&pci_dev->addr, cryptodev_name,
560                         sizeof(cryptodev_name));
561
562         cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
563         if (cryptodev == NULL)
564                 return -ENODEV;
565
566         cryptodrv = (const struct rte_cryptodev_driver *)pci_dev->driver;
567         if (cryptodrv == NULL)
568                 return -ENODEV;
569
570         /* Invoke PMD device uninit function */
571         if (*cryptodrv->cryptodev_uninit) {
572                 ret = (*cryptodrv->cryptodev_uninit)(cryptodrv, cryptodev);
573                 if (ret)
574                         return ret;
575         }
576
577         /* free crypto device */
578         rte_cryptodev_pmd_release_device(cryptodev);
579
580         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
581                 rte_free(cryptodev->data->dev_private);
582
583         cryptodev->pci_dev = NULL;
584         cryptodev->driver = NULL;
585         cryptodev->data = NULL;
586
587         return 0;
588 }
589
590 uint16_t
591 rte_cryptodev_queue_pair_count(uint8_t dev_id)
592 {
593         struct rte_cryptodev *dev;
594
595         dev = &rte_crypto_devices[dev_id];
596         return dev->data->nb_queue_pairs;
597 }
598
599 static int
600 rte_cryptodev_queue_pairs_config(struct rte_cryptodev *dev, uint16_t nb_qpairs,
601                 int socket_id)
602 {
603         struct rte_cryptodev_info dev_info;
604         void **qp;
605         unsigned i;
606
607         if ((dev == NULL) || (nb_qpairs < 1)) {
608                 CDEV_LOG_ERR("invalid param: dev %p, nb_queues %u",
609                                                         dev, nb_qpairs);
610                 return -EINVAL;
611         }
612
613         CDEV_LOG_DEBUG("Setup %d queues pairs on device %u",
614                         nb_qpairs, dev->data->dev_id);
615
616         memset(&dev_info, 0, sizeof(struct rte_cryptodev_info));
617
618         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
619         (*dev->dev_ops->dev_infos_get)(dev, &dev_info);
620
621         if (nb_qpairs > (dev_info.max_nb_queue_pairs)) {
622                 CDEV_LOG_ERR("Invalid num queue_pairs (%u) for dev %u",
623                                 nb_qpairs, dev->data->dev_id);
624             return -EINVAL;
625         }
626
627         if (dev->data->queue_pairs == NULL) { /* first time configuration */
628                 dev->data->queue_pairs = rte_zmalloc_socket(
629                                 "cryptodev->queue_pairs",
630                                 sizeof(dev->data->queue_pairs[0]) * nb_qpairs,
631                                 RTE_CACHE_LINE_SIZE, socket_id);
632
633                 if (dev->data->queue_pairs == NULL) {
634                         dev->data->nb_queue_pairs = 0;
635                         CDEV_LOG_ERR("failed to get memory for qp meta data, "
636                                                         "nb_queues %u",
637                                                         nb_qpairs);
638                         return -(ENOMEM);
639                 }
640         } else { /* re-configure */
641                 int ret;
642                 uint16_t old_nb_queues = dev->data->nb_queue_pairs;
643
644                 qp = dev->data->queue_pairs;
645
646                 RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_release,
647                                 -ENOTSUP);
648
649                 for (i = nb_qpairs; i < old_nb_queues; i++) {
650                         ret = (*dev->dev_ops->queue_pair_release)(dev, i);
651                         if (ret < 0)
652                                 return ret;
653                 }
654
655                 qp = rte_realloc(qp, sizeof(qp[0]) * nb_qpairs,
656                                 RTE_CACHE_LINE_SIZE);
657                 if (qp == NULL) {
658                         CDEV_LOG_ERR("failed to realloc qp meta data,"
659                                                 " nb_queues %u", nb_qpairs);
660                         return -(ENOMEM);
661                 }
662
663                 if (nb_qpairs > old_nb_queues) {
664                         uint16_t new_qs = nb_qpairs - old_nb_queues;
665
666                         memset(qp + old_nb_queues, 0,
667                                 sizeof(qp[0]) * new_qs);
668                 }
669
670                 dev->data->queue_pairs = qp;
671
672         }
673         dev->data->nb_queue_pairs = nb_qpairs;
674         return 0;
675 }
676
677 int
678 rte_cryptodev_queue_pair_start(uint8_t dev_id, uint16_t queue_pair_id)
679 {
680         struct rte_cryptodev *dev;
681
682         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
683                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
684                 return -EINVAL;
685         }
686
687         dev = &rte_crypto_devices[dev_id];
688         if (queue_pair_id >= dev->data->nb_queue_pairs) {
689                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
690                 return -EINVAL;
691         }
692
693         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_start, -ENOTSUP);
694
695         return dev->dev_ops->queue_pair_start(dev, queue_pair_id);
696
697 }
698
699 int
700 rte_cryptodev_queue_pair_stop(uint8_t dev_id, uint16_t queue_pair_id)
701 {
702         struct rte_cryptodev *dev;
703
704         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
705                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
706                 return -EINVAL;
707         }
708
709         dev = &rte_crypto_devices[dev_id];
710         if (queue_pair_id >= dev->data->nb_queue_pairs) {
711                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
712                 return -EINVAL;
713         }
714
715         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_stop, -ENOTSUP);
716
717         return dev->dev_ops->queue_pair_stop(dev, queue_pair_id);
718
719 }
720
721 static int
722 rte_cryptodev_sym_session_pool_create(struct rte_cryptodev *dev,
723                 unsigned nb_objs, unsigned obj_cache_size, int socket_id);
724
725 int
726 rte_cryptodev_configure(uint8_t dev_id, struct rte_cryptodev_config *config)
727 {
728         struct rte_cryptodev *dev;
729         int diag;
730
731         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
732                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
733                 return -EINVAL;
734         }
735
736         dev = &rte_crypto_devices[dev_id];
737
738         if (dev->data->dev_started) {
739                 CDEV_LOG_ERR(
740                     "device %d must be stopped to allow configuration", dev_id);
741                 return -EBUSY;
742         }
743
744         /* Setup new number of queue pairs and reconfigure device. */
745         diag = rte_cryptodev_queue_pairs_config(dev, config->nb_queue_pairs,
746                         config->socket_id);
747         if (diag != 0) {
748                 CDEV_LOG_ERR("dev%d rte_crypto_dev_queue_pairs_config = %d",
749                                 dev_id, diag);
750                 return diag;
751         }
752
753         /* Setup Session mempool for device */
754         return rte_cryptodev_sym_session_pool_create(dev,
755                         config->session_mp.nb_objs,
756                         config->session_mp.cache_size,
757                         config->socket_id);
758 }
759
760
761 int
762 rte_cryptodev_start(uint8_t dev_id)
763 {
764         struct rte_cryptodev *dev;
765         int diag;
766
767         CDEV_LOG_DEBUG("Start dev_id=%" PRIu8, dev_id);
768
769         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
770                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
771                 return -EINVAL;
772         }
773
774         dev = &rte_crypto_devices[dev_id];
775
776         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP);
777
778         if (dev->data->dev_started != 0) {
779                 CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already started",
780                         dev_id);
781                 return 0;
782         }
783
784         diag = (*dev->dev_ops->dev_start)(dev);
785         if (diag == 0)
786                 dev->data->dev_started = 1;
787         else
788                 return diag;
789
790         return 0;
791 }
792
793 void
794 rte_cryptodev_stop(uint8_t dev_id)
795 {
796         struct rte_cryptodev *dev;
797
798         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
799                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
800                 return;
801         }
802
803         dev = &rte_crypto_devices[dev_id];
804
805         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);
806
807         if (dev->data->dev_started == 0) {
808                 CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already stopped",
809                         dev_id);
810                 return;
811         }
812
813         dev->data->dev_started = 0;
814         (*dev->dev_ops->dev_stop)(dev);
815 }
816
817 int
818 rte_cryptodev_close(uint8_t dev_id)
819 {
820         struct rte_cryptodev *dev;
821         int retval;
822
823         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
824                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
825                 return -1;
826         }
827
828         dev = &rte_crypto_devices[dev_id];
829
830         /* Device must be stopped before it can be closed */
831         if (dev->data->dev_started == 1) {
832                 CDEV_LOG_ERR("Device %u must be stopped before closing",
833                                 dev_id);
834                 return -EBUSY;
835         }
836
837         /* We can't close the device if there are outstanding sessions in use */
838         if (dev->data->session_pool != NULL) {
839                 if (!rte_mempool_full(dev->data->session_pool)) {
840                         CDEV_LOG_ERR("dev_id=%u close failed, session mempool "
841                                         "has sessions still in use, free "
842                                         "all sessions before calling close",
843                                         (unsigned)dev_id);
844                         return -EBUSY;
845                 }
846         }
847
848         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);
849         retval = (*dev->dev_ops->dev_close)(dev);
850
851         if (retval < 0)
852                 return retval;
853
854         return 0;
855 }
856
857 int
858 rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
859                 const struct rte_cryptodev_qp_conf *qp_conf, int socket_id)
860 {
861         struct rte_cryptodev *dev;
862
863         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
864                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
865                 return -EINVAL;
866         }
867
868         dev = &rte_crypto_devices[dev_id];
869         if (queue_pair_id >= dev->data->nb_queue_pairs) {
870                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
871                 return -EINVAL;
872         }
873
874         if (dev->data->dev_started) {
875                 CDEV_LOG_ERR(
876                     "device %d must be stopped to allow configuration", dev_id);
877                 return -EBUSY;
878         }
879
880         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_setup, -ENOTSUP);
881
882         return (*dev->dev_ops->queue_pair_setup)(dev, queue_pair_id, qp_conf,
883                         socket_id);
884 }
885
886
887 int
888 rte_cryptodev_stats_get(uint8_t dev_id, struct rte_cryptodev_stats *stats)
889 {
890         struct rte_cryptodev *dev;
891
892         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
893                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
894                 return -ENODEV;
895         }
896
897         if (stats == NULL) {
898                 CDEV_LOG_ERR("Invalid stats ptr");
899                 return -EINVAL;
900         }
901
902         dev = &rte_crypto_devices[dev_id];
903         memset(stats, 0, sizeof(*stats));
904
905         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_get, -ENOTSUP);
906         (*dev->dev_ops->stats_get)(dev, stats);
907         return 0;
908 }
909
910 void
911 rte_cryptodev_stats_reset(uint8_t dev_id)
912 {
913         struct rte_cryptodev *dev;
914
915         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
916                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
917                 return;
918         }
919
920         dev = &rte_crypto_devices[dev_id];
921
922         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
923         (*dev->dev_ops->stats_reset)(dev);
924 }
925
926
927 void
928 rte_cryptodev_info_get(uint8_t dev_id, struct rte_cryptodev_info *dev_info)
929 {
930         struct rte_cryptodev *dev;
931
932         if (dev_id >= cryptodev_globals.nb_devs) {
933                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
934                 return;
935         }
936
937         dev = &rte_crypto_devices[dev_id];
938
939         memset(dev_info, 0, sizeof(struct rte_cryptodev_info));
940
941         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
942         (*dev->dev_ops->dev_infos_get)(dev, dev_info);
943
944         dev_info->pci_dev = dev->pci_dev;
945         if (dev->driver)
946                 dev_info->driver_name = dev->driver->pci_drv.driver.name;
947 }
948
949
950 int
951 rte_cryptodev_callback_register(uint8_t dev_id,
952                         enum rte_cryptodev_event_type event,
953                         rte_cryptodev_cb_fn cb_fn, void *cb_arg)
954 {
955         struct rte_cryptodev *dev;
956         struct rte_cryptodev_callback *user_cb;
957
958         if (!cb_fn)
959                 return -EINVAL;
960
961         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
962                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
963                 return -EINVAL;
964         }
965
966         dev = &rte_crypto_devices[dev_id];
967         rte_spinlock_lock(&rte_cryptodev_cb_lock);
968
969         TAILQ_FOREACH(user_cb, &(dev->link_intr_cbs), next) {
970                 if (user_cb->cb_fn == cb_fn &&
971                         user_cb->cb_arg == cb_arg &&
972                         user_cb->event == event) {
973                         break;
974                 }
975         }
976
977         /* create a new callback. */
978         if (user_cb == NULL) {
979                 user_cb = rte_zmalloc("INTR_USER_CALLBACK",
980                                 sizeof(struct rte_cryptodev_callback), 0);
981                 if (user_cb != NULL) {
982                         user_cb->cb_fn = cb_fn;
983                         user_cb->cb_arg = cb_arg;
984                         user_cb->event = event;
985                         TAILQ_INSERT_TAIL(&(dev->link_intr_cbs), user_cb, next);
986                 }
987         }
988
989         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
990         return (user_cb == NULL) ? -ENOMEM : 0;
991 }
992
993 int
994 rte_cryptodev_callback_unregister(uint8_t dev_id,
995                         enum rte_cryptodev_event_type event,
996                         rte_cryptodev_cb_fn cb_fn, void *cb_arg)
997 {
998         int ret;
999         struct rte_cryptodev *dev;
1000         struct rte_cryptodev_callback *cb, *next;
1001
1002         if (!cb_fn)
1003                 return -EINVAL;
1004
1005         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1006                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
1007                 return -EINVAL;
1008         }
1009
1010         dev = &rte_crypto_devices[dev_id];
1011         rte_spinlock_lock(&rte_cryptodev_cb_lock);
1012
1013         ret = 0;
1014         for (cb = TAILQ_FIRST(&dev->link_intr_cbs); cb != NULL; cb = next) {
1015
1016                 next = TAILQ_NEXT(cb, next);
1017
1018                 if (cb->cb_fn != cb_fn || cb->event != event ||
1019                                 (cb->cb_arg != (void *)-1 &&
1020                                 cb->cb_arg != cb_arg))
1021                         continue;
1022
1023                 /*
1024                  * if this callback is not executing right now,
1025                  * then remove it.
1026                  */
1027                 if (cb->active == 0) {
1028                         TAILQ_REMOVE(&(dev->link_intr_cbs), cb, next);
1029                         rte_free(cb);
1030                 } else {
1031                         ret = -EAGAIN;
1032                 }
1033         }
1034
1035         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1036         return ret;
1037 }
1038
1039 void
1040 rte_cryptodev_pmd_callback_process(struct rte_cryptodev *dev,
1041         enum rte_cryptodev_event_type event)
1042 {
1043         struct rte_cryptodev_callback *cb_lst;
1044         struct rte_cryptodev_callback dev_cb;
1045
1046         rte_spinlock_lock(&rte_cryptodev_cb_lock);
1047         TAILQ_FOREACH(cb_lst, &(dev->link_intr_cbs), next) {
1048                 if (cb_lst->cb_fn == NULL || cb_lst->event != event)
1049                         continue;
1050                 dev_cb = *cb_lst;
1051                 cb_lst->active = 1;
1052                 rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1053                 dev_cb.cb_fn(dev->data->dev_id, dev_cb.event,
1054                                                 dev_cb.cb_arg);
1055                 rte_spinlock_lock(&rte_cryptodev_cb_lock);
1056                 cb_lst->active = 0;
1057         }
1058         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1059 }
1060
1061
1062 static void
1063 rte_cryptodev_sym_session_init(struct rte_mempool *mp,
1064                 void *opaque_arg,
1065                 void *_sess,
1066                 __rte_unused unsigned i)
1067 {
1068         struct rte_cryptodev_sym_session *sess = _sess;
1069         struct rte_cryptodev *dev = opaque_arg;
1070
1071         memset(sess, 0, mp->elt_size);
1072
1073         sess->dev_id = dev->data->dev_id;
1074         sess->dev_type = dev->dev_type;
1075         sess->mp = mp;
1076
1077         if (dev->dev_ops->session_initialize)
1078                 (*dev->dev_ops->session_initialize)(mp, sess);
1079 }
1080
1081 static int
1082 rte_cryptodev_sym_session_pool_create(struct rte_cryptodev *dev,
1083                 unsigned nb_objs, unsigned obj_cache_size, int socket_id)
1084 {
1085         char mp_name[RTE_CRYPTODEV_NAME_MAX_LEN];
1086         unsigned priv_sess_size;
1087
1088         unsigned n = snprintf(mp_name, sizeof(mp_name), "cdev_%d_sess_mp",
1089                         dev->data->dev_id);
1090         if (n > sizeof(mp_name)) {
1091                 CDEV_LOG_ERR("Unable to create unique name for session mempool");
1092                 return -ENOMEM;
1093         }
1094
1095         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_get_size, -ENOTSUP);
1096         priv_sess_size = (*dev->dev_ops->session_get_size)(dev);
1097         if (priv_sess_size == 0) {
1098                 CDEV_LOG_ERR("%s returned and invalid private session size ",
1099                                                 dev->data->name);
1100                 return -ENOMEM;
1101         }
1102
1103         unsigned elt_size = sizeof(struct rte_cryptodev_sym_session) +
1104                         priv_sess_size;
1105
1106         dev->data->session_pool = rte_mempool_lookup(mp_name);
1107         if (dev->data->session_pool != NULL) {
1108                 if ((dev->data->session_pool->elt_size != elt_size) ||
1109                                 (dev->data->session_pool->cache_size <
1110                                 obj_cache_size) ||
1111                                 (dev->data->session_pool->size < nb_objs)) {
1112
1113                         CDEV_LOG_ERR("%s mempool already exists with different"
1114                                         " initialization parameters", mp_name);
1115                         dev->data->session_pool = NULL;
1116                         return -ENOMEM;
1117                 }
1118         } else {
1119                 dev->data->session_pool = rte_mempool_create(
1120                                 mp_name, /* mempool name */
1121                                 nb_objs, /* number of elements*/
1122                                 elt_size, /* element size*/
1123                                 obj_cache_size, /* Cache size*/
1124                                 0, /* private data size */
1125                                 NULL, /* obj initialization constructor */
1126                                 NULL, /* obj initialization constructor arg */
1127                                 rte_cryptodev_sym_session_init,
1128                                 /**< obj constructor*/
1129                                 dev, /* obj constructor arg */
1130                                 socket_id, /* socket id */
1131                                 0); /* flags */
1132
1133                 if (dev->data->session_pool == NULL) {
1134                         CDEV_LOG_ERR("%s mempool allocation failed", mp_name);
1135                         return -ENOMEM;
1136                 }
1137         }
1138
1139         CDEV_LOG_DEBUG("%s mempool created!", mp_name);
1140         return 0;
1141 }
1142
1143 struct rte_cryptodev_sym_session *
1144 rte_cryptodev_sym_session_create(uint8_t dev_id,
1145                 struct rte_crypto_sym_xform *xform)
1146 {
1147         struct rte_cryptodev *dev;
1148         struct rte_cryptodev_sym_session *sess;
1149         void *_sess;
1150
1151         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1152                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
1153                 return NULL;
1154         }
1155
1156         dev = &rte_crypto_devices[dev_id];
1157
1158         /* Allocate a session structure from the session pool */
1159         if (rte_mempool_get(dev->data->session_pool, &_sess)) {
1160                 CDEV_LOG_ERR("Couldn't get object from session mempool");
1161                 return NULL;
1162         }
1163
1164         sess = (struct rte_cryptodev_sym_session *)_sess;
1165
1166         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_configure, NULL);
1167         if (dev->dev_ops->session_configure(dev, xform, sess->_private) ==
1168                         NULL) {
1169                 CDEV_LOG_ERR("dev_id %d failed to configure session details",
1170                                 dev_id);
1171
1172                 /* Return session to mempool */
1173                 rte_mempool_put(sess->mp, _sess);
1174                 return NULL;
1175         }
1176
1177         return sess;
1178 }
1179
1180 struct rte_cryptodev_sym_session *
1181 rte_cryptodev_sym_session_free(uint8_t dev_id,
1182                 struct rte_cryptodev_sym_session *sess)
1183 {
1184         struct rte_cryptodev *dev;
1185
1186         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1187                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
1188                 return sess;
1189         }
1190
1191         dev = &rte_crypto_devices[dev_id];
1192
1193         /* Check the session belongs to this device type */
1194         if (sess->dev_type != dev->dev_type)
1195                 return sess;
1196
1197         /* Let device implementation clear session material */
1198         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_clear, sess);
1199         dev->dev_ops->session_clear(dev, (void *)sess->_private);
1200
1201         /* Return session to mempool */
1202         rte_mempool_put(sess->mp, (void *)sess);
1203
1204         return NULL;
1205 }
1206
1207 /** Initialise rte_crypto_op mempool element */
1208 static void
1209 rte_crypto_op_init(struct rte_mempool *mempool,
1210                 void *opaque_arg,
1211                 void *_op_data,
1212                 __rte_unused unsigned i)
1213 {
1214         struct rte_crypto_op *op = _op_data;
1215         enum rte_crypto_op_type type = *(enum rte_crypto_op_type *)opaque_arg;
1216
1217         memset(_op_data, 0, mempool->elt_size);
1218
1219         __rte_crypto_op_reset(op, type);
1220
1221         op->phys_addr = rte_mem_virt2phy(_op_data);
1222         op->mempool = mempool;
1223 }
1224
1225
1226 struct rte_mempool *
1227 rte_crypto_op_pool_create(const char *name, enum rte_crypto_op_type type,
1228                 unsigned nb_elts, unsigned cache_size, uint16_t priv_size,
1229                 int socket_id)
1230 {
1231         struct rte_crypto_op_pool_private *priv;
1232
1233         unsigned elt_size = sizeof(struct rte_crypto_op) +
1234                         sizeof(struct rte_crypto_sym_op) +
1235                         priv_size;
1236
1237         /* lookup mempool in case already allocated */
1238         struct rte_mempool *mp = rte_mempool_lookup(name);
1239
1240         if (mp != NULL) {
1241                 priv = (struct rte_crypto_op_pool_private *)
1242                                 rte_mempool_get_priv(mp);
1243
1244                 if (mp->elt_size != elt_size ||
1245                                 mp->cache_size < cache_size ||
1246                                 mp->size < nb_elts ||
1247                                 priv->priv_size <  priv_size) {
1248                         mp = NULL;
1249                         CDEV_LOG_ERR("Mempool %s already exists but with "
1250                                         "incompatible parameters", name);
1251                         return NULL;
1252                 }
1253                 return mp;
1254         }
1255
1256         mp = rte_mempool_create(
1257                         name,
1258                         nb_elts,
1259                         elt_size,
1260                         cache_size,
1261                         sizeof(struct rte_crypto_op_pool_private),
1262                         NULL,
1263                         NULL,
1264                         rte_crypto_op_init,
1265                         &type,
1266                         socket_id,
1267                         0);
1268
1269         if (mp == NULL) {
1270                 CDEV_LOG_ERR("Failed to create mempool %s", name);
1271                 return NULL;
1272         }
1273
1274         priv = (struct rte_crypto_op_pool_private *)
1275                         rte_mempool_get_priv(mp);
1276
1277         priv->priv_size = priv_size;
1278         priv->type = type;
1279
1280         return mp;
1281 }
1282
1283 int
1284 rte_cryptodev_pmd_create_dev_name(char *name, const char *dev_name_prefix)
1285 {
1286         struct rte_cryptodev *dev = NULL;
1287         uint32_t i = 0;
1288
1289         if (name == NULL)
1290                 return -EINVAL;
1291
1292         for (i = 0; i < RTE_CRYPTO_MAX_DEVS; i++) {
1293                 int ret = snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN,
1294                                 "%s_%u", dev_name_prefix, i);
1295
1296                 if (ret < 0)
1297                         return ret;
1298
1299                 dev = rte_cryptodev_pmd_get_named_dev(name);
1300                 if (!dev)
1301                         return 0;
1302         }
1303
1304         return -1;
1305 }