cryptodev: add user defined name for vdev
[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         default:
244                 return NULL;
245         }
246 }
247
248 int
249 rte_cryptodev_create_vdev(const char *name, const char *args)
250 {
251         return rte_eal_vdev_init(name, args);
252 }
253
254 int
255 rte_cryptodev_get_dev_id(const char *name)
256 {
257         unsigned i;
258
259         if (name == NULL)
260                 return -1;
261
262         for (i = 0; i < rte_cryptodev_globals->nb_devs; i++)
263                 if ((strcmp(rte_cryptodev_globals->devs[i].data->name, name)
264                                 == 0) &&
265                                 (rte_cryptodev_globals->devs[i].attached ==
266                                                 RTE_CRYPTODEV_ATTACHED))
267                         return i;
268
269         return -1;
270 }
271
272 uint8_t
273 rte_cryptodev_count(void)
274 {
275         return rte_cryptodev_globals->nb_devs;
276 }
277
278 uint8_t
279 rte_cryptodev_count_devtype(enum rte_cryptodev_type type)
280 {
281         uint8_t i, dev_count = 0;
282
283         for (i = 0; i < rte_cryptodev_globals->max_devs; i++)
284                 if (rte_cryptodev_globals->devs[i].dev_type == type &&
285                         rte_cryptodev_globals->devs[i].attached ==
286                                         RTE_CRYPTODEV_ATTACHED)
287                         dev_count++;
288
289         return dev_count;
290 }
291
292 int
293 rte_cryptodev_socket_id(uint8_t dev_id)
294 {
295         struct rte_cryptodev *dev;
296
297         if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
298                 return -1;
299
300         dev = rte_cryptodev_pmd_get_dev(dev_id);
301
302         return dev->data->socket_id;
303 }
304
305 static inline int
306 rte_cryptodev_data_alloc(uint8_t dev_id, struct rte_cryptodev_data **data,
307                 int socket_id)
308 {
309         char mz_name[RTE_CRYPTODEV_NAME_MAX_LEN];
310         const struct rte_memzone *mz;
311         int n;
312
313         /* generate memzone name */
314         n = snprintf(mz_name, sizeof(mz_name), "rte_cryptodev_data_%u", dev_id);
315         if (n >= (int)sizeof(mz_name))
316                 return -EINVAL;
317
318         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
319                 mz = rte_memzone_reserve(mz_name,
320                                 sizeof(struct rte_cryptodev_data),
321                                 socket_id, 0);
322         } else
323                 mz = rte_memzone_lookup(mz_name);
324
325         if (mz == NULL)
326                 return -ENOMEM;
327
328         *data = mz->addr;
329         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
330                 memset(*data, 0, sizeof(struct rte_cryptodev_data));
331
332         return 0;
333 }
334
335 static uint8_t
336 rte_cryptodev_find_free_device_index(void)
337 {
338         uint8_t dev_id;
339
340         for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++) {
341                 if (rte_crypto_devices[dev_id].attached ==
342                                 RTE_CRYPTODEV_DETACHED)
343                         return dev_id;
344         }
345         return RTE_CRYPTO_MAX_DEVS;
346 }
347
348 struct rte_cryptodev *
349 rte_cryptodev_pmd_allocate(const char *name, int socket_id)
350 {
351         struct rte_cryptodev *cryptodev;
352         uint8_t dev_id;
353
354         if (rte_cryptodev_pmd_get_named_dev(name) != NULL) {
355                 CDEV_LOG_ERR("Crypto device with name %s already "
356                                 "allocated!", name);
357                 return NULL;
358         }
359
360         dev_id = rte_cryptodev_find_free_device_index();
361         if (dev_id == RTE_CRYPTO_MAX_DEVS) {
362                 CDEV_LOG_ERR("Reached maximum number of crypto devices");
363                 return NULL;
364         }
365
366         cryptodev = rte_cryptodev_pmd_get_dev(dev_id);
367
368         if (cryptodev->data == NULL) {
369                 struct rte_cryptodev_data *cryptodev_data =
370                                 cryptodev_globals.data[dev_id];
371
372                 int retval = rte_cryptodev_data_alloc(dev_id, &cryptodev_data,
373                                 socket_id);
374
375                 if (retval < 0 || cryptodev_data == NULL)
376                         return NULL;
377
378                 cryptodev->data = cryptodev_data;
379
380                 snprintf(cryptodev->data->name, RTE_CRYPTODEV_NAME_MAX_LEN,
381                                 "%s", name);
382
383                 cryptodev->data->dev_id = dev_id;
384                 cryptodev->data->socket_id = socket_id;
385                 cryptodev->data->dev_started = 0;
386
387                 cryptodev->attached = RTE_CRYPTODEV_ATTACHED;
388
389                 cryptodev_globals.nb_devs++;
390         }
391
392         return cryptodev;
393 }
394
395 int
396 rte_cryptodev_pmd_release_device(struct rte_cryptodev *cryptodev)
397 {
398         int ret;
399
400         if (cryptodev == NULL)
401                 return -EINVAL;
402
403         ret = rte_cryptodev_close(cryptodev->data->dev_id);
404         if (ret < 0)
405                 return ret;
406
407         cryptodev->attached = RTE_CRYPTODEV_DETACHED;
408         cryptodev_globals.nb_devs--;
409         return 0;
410 }
411
412 struct rte_cryptodev *
413 rte_cryptodev_pmd_virtual_dev_init(const char *name, size_t dev_private_size,
414                 int socket_id)
415 {
416         struct rte_cryptodev *cryptodev;
417
418         /* allocate device structure */
419         cryptodev = rte_cryptodev_pmd_allocate(name, socket_id);
420         if (cryptodev == NULL)
421                 return NULL;
422
423         /* allocate private device structure */
424         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
425                 cryptodev->data->dev_private =
426                                 rte_zmalloc_socket("cryptodev device private",
427                                                 dev_private_size,
428                                                 RTE_CACHE_LINE_SIZE,
429                                                 socket_id);
430
431                 if (cryptodev->data->dev_private == NULL)
432                         rte_panic("Cannot allocate memzone for private device"
433                                         " data");
434         }
435
436         /* initialise user call-back tail queue */
437         TAILQ_INIT(&(cryptodev->link_intr_cbs));
438
439         return cryptodev;
440 }
441
442 int
443 rte_cryptodev_pci_probe(struct rte_pci_driver *pci_drv,
444                         struct rte_pci_device *pci_dev)
445 {
446         struct rte_cryptodev_driver *cryptodrv;
447         struct rte_cryptodev *cryptodev;
448
449         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
450
451         int retval;
452
453         cryptodrv = (struct rte_cryptodev_driver *)pci_drv;
454         if (cryptodrv == NULL)
455                 return -ENODEV;
456
457         rte_eal_pci_device_name(&pci_dev->addr, cryptodev_name,
458                         sizeof(cryptodev_name));
459
460         cryptodev = rte_cryptodev_pmd_allocate(cryptodev_name, rte_socket_id());
461         if (cryptodev == NULL)
462                 return -ENOMEM;
463
464         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
465                 cryptodev->data->dev_private =
466                                 rte_zmalloc_socket(
467                                                 "cryptodev private structure",
468                                                 cryptodrv->dev_private_size,
469                                                 RTE_CACHE_LINE_SIZE,
470                                                 rte_socket_id());
471
472                 if (cryptodev->data->dev_private == NULL)
473                         rte_panic("Cannot allocate memzone for private "
474                                         "device data");
475         }
476
477         cryptodev->pci_dev = pci_dev;
478         cryptodev->driver = cryptodrv;
479
480         /* init user callbacks */
481         TAILQ_INIT(&(cryptodev->link_intr_cbs));
482
483         /* Invoke PMD device initialization function */
484         retval = (*cryptodrv->cryptodev_init)(cryptodrv, cryptodev);
485         if (retval == 0)
486                 return 0;
487
488         CDEV_LOG_ERR("driver %s: crypto_dev_init(vendor_id=0x%x device_id=0x%x)"
489                         " failed", pci_drv->driver.name,
490                         (unsigned) pci_dev->id.vendor_id,
491                         (unsigned) pci_dev->id.device_id);
492
493         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
494                 rte_free(cryptodev->data->dev_private);
495
496         cryptodev->attached = RTE_CRYPTODEV_DETACHED;
497         cryptodev_globals.nb_devs--;
498
499         return -ENXIO;
500 }
501
502 int
503 rte_cryptodev_pci_remove(struct rte_pci_device *pci_dev)
504 {
505         const struct rte_cryptodev_driver *cryptodrv;
506         struct rte_cryptodev *cryptodev;
507         char cryptodev_name[RTE_CRYPTODEV_NAME_MAX_LEN];
508         int ret;
509
510         if (pci_dev == NULL)
511                 return -EINVAL;
512
513         rte_eal_pci_device_name(&pci_dev->addr, cryptodev_name,
514                         sizeof(cryptodev_name));
515
516         cryptodev = rte_cryptodev_pmd_get_named_dev(cryptodev_name);
517         if (cryptodev == NULL)
518                 return -ENODEV;
519
520         cryptodrv = (const struct rte_cryptodev_driver *)pci_dev->driver;
521         if (cryptodrv == NULL)
522                 return -ENODEV;
523
524         /* Invoke PMD device uninit function */
525         if (*cryptodrv->cryptodev_uninit) {
526                 ret = (*cryptodrv->cryptodev_uninit)(cryptodrv, cryptodev);
527                 if (ret)
528                         return ret;
529         }
530
531         /* free crypto device */
532         rte_cryptodev_pmd_release_device(cryptodev);
533
534         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
535                 rte_free(cryptodev->data->dev_private);
536
537         cryptodev->pci_dev = NULL;
538         cryptodev->driver = NULL;
539         cryptodev->data = NULL;
540
541         return 0;
542 }
543
544 uint16_t
545 rte_cryptodev_queue_pair_count(uint8_t dev_id)
546 {
547         struct rte_cryptodev *dev;
548
549         dev = &rte_crypto_devices[dev_id];
550         return dev->data->nb_queue_pairs;
551 }
552
553 static int
554 rte_cryptodev_queue_pairs_config(struct rte_cryptodev *dev, uint16_t nb_qpairs,
555                 int socket_id)
556 {
557         struct rte_cryptodev_info dev_info;
558         void **qp;
559         unsigned i;
560
561         if ((dev == NULL) || (nb_qpairs < 1)) {
562                 CDEV_LOG_ERR("invalid param: dev %p, nb_queues %u",
563                                                         dev, nb_qpairs);
564                 return -EINVAL;
565         }
566
567         CDEV_LOG_DEBUG("Setup %d queues pairs on device %u",
568                         nb_qpairs, dev->data->dev_id);
569
570         memset(&dev_info, 0, sizeof(struct rte_cryptodev_info));
571
572         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
573         (*dev->dev_ops->dev_infos_get)(dev, &dev_info);
574
575         if (nb_qpairs > (dev_info.max_nb_queue_pairs)) {
576                 CDEV_LOG_ERR("Invalid num queue_pairs (%u) for dev %u",
577                                 nb_qpairs, dev->data->dev_id);
578             return -EINVAL;
579         }
580
581         if (dev->data->queue_pairs == NULL) { /* first time configuration */
582                 dev->data->queue_pairs = rte_zmalloc_socket(
583                                 "cryptodev->queue_pairs",
584                                 sizeof(dev->data->queue_pairs[0]) * nb_qpairs,
585                                 RTE_CACHE_LINE_SIZE, socket_id);
586
587                 if (dev->data->queue_pairs == NULL) {
588                         dev->data->nb_queue_pairs = 0;
589                         CDEV_LOG_ERR("failed to get memory for qp meta data, "
590                                                         "nb_queues %u",
591                                                         nb_qpairs);
592                         return -(ENOMEM);
593                 }
594         } else { /* re-configure */
595                 int ret;
596                 uint16_t old_nb_queues = dev->data->nb_queue_pairs;
597
598                 qp = dev->data->queue_pairs;
599
600                 RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_release,
601                                 -ENOTSUP);
602
603                 for (i = nb_qpairs; i < old_nb_queues; i++) {
604                         ret = (*dev->dev_ops->queue_pair_release)(dev, i);
605                         if (ret < 0)
606                                 return ret;
607                 }
608
609                 qp = rte_realloc(qp, sizeof(qp[0]) * nb_qpairs,
610                                 RTE_CACHE_LINE_SIZE);
611                 if (qp == NULL) {
612                         CDEV_LOG_ERR("failed to realloc qp meta data,"
613                                                 " nb_queues %u", nb_qpairs);
614                         return -(ENOMEM);
615                 }
616
617                 if (nb_qpairs > old_nb_queues) {
618                         uint16_t new_qs = nb_qpairs - old_nb_queues;
619
620                         memset(qp + old_nb_queues, 0,
621                                 sizeof(qp[0]) * new_qs);
622                 }
623
624                 dev->data->queue_pairs = qp;
625
626         }
627         dev->data->nb_queue_pairs = nb_qpairs;
628         return 0;
629 }
630
631 int
632 rte_cryptodev_queue_pair_start(uint8_t dev_id, uint16_t queue_pair_id)
633 {
634         struct rte_cryptodev *dev;
635
636         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
637                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
638                 return -EINVAL;
639         }
640
641         dev = &rte_crypto_devices[dev_id];
642         if (queue_pair_id >= dev->data->nb_queue_pairs) {
643                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
644                 return -EINVAL;
645         }
646
647         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_start, -ENOTSUP);
648
649         return dev->dev_ops->queue_pair_start(dev, queue_pair_id);
650
651 }
652
653 int
654 rte_cryptodev_queue_pair_stop(uint8_t dev_id, uint16_t queue_pair_id)
655 {
656         struct rte_cryptodev *dev;
657
658         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
659                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
660                 return -EINVAL;
661         }
662
663         dev = &rte_crypto_devices[dev_id];
664         if (queue_pair_id >= dev->data->nb_queue_pairs) {
665                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
666                 return -EINVAL;
667         }
668
669         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_stop, -ENOTSUP);
670
671         return dev->dev_ops->queue_pair_stop(dev, queue_pair_id);
672
673 }
674
675 static int
676 rte_cryptodev_sym_session_pool_create(struct rte_cryptodev *dev,
677                 unsigned nb_objs, unsigned obj_cache_size, int socket_id);
678
679 int
680 rte_cryptodev_configure(uint8_t dev_id, struct rte_cryptodev_config *config)
681 {
682         struct rte_cryptodev *dev;
683         int diag;
684
685         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
686                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
687                 return -EINVAL;
688         }
689
690         dev = &rte_crypto_devices[dev_id];
691
692         if (dev->data->dev_started) {
693                 CDEV_LOG_ERR(
694                     "device %d must be stopped to allow configuration", dev_id);
695                 return -EBUSY;
696         }
697
698         /* Setup new number of queue pairs and reconfigure device. */
699         diag = rte_cryptodev_queue_pairs_config(dev, config->nb_queue_pairs,
700                         config->socket_id);
701         if (diag != 0) {
702                 CDEV_LOG_ERR("dev%d rte_crypto_dev_queue_pairs_config = %d",
703                                 dev_id, diag);
704                 return diag;
705         }
706
707         /* Setup Session mempool for device */
708         return rte_cryptodev_sym_session_pool_create(dev,
709                         config->session_mp.nb_objs,
710                         config->session_mp.cache_size,
711                         config->socket_id);
712 }
713
714
715 int
716 rte_cryptodev_start(uint8_t dev_id)
717 {
718         struct rte_cryptodev *dev;
719         int diag;
720
721         CDEV_LOG_DEBUG("Start dev_id=%" PRIu8, dev_id);
722
723         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
724                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
725                 return -EINVAL;
726         }
727
728         dev = &rte_crypto_devices[dev_id];
729
730         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP);
731
732         if (dev->data->dev_started != 0) {
733                 CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already started",
734                         dev_id);
735                 return 0;
736         }
737
738         diag = (*dev->dev_ops->dev_start)(dev);
739         if (diag == 0)
740                 dev->data->dev_started = 1;
741         else
742                 return diag;
743
744         return 0;
745 }
746
747 void
748 rte_cryptodev_stop(uint8_t dev_id)
749 {
750         struct rte_cryptodev *dev;
751
752         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
753                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
754                 return;
755         }
756
757         dev = &rte_crypto_devices[dev_id];
758
759         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);
760
761         if (dev->data->dev_started == 0) {
762                 CDEV_LOG_ERR("Device with dev_id=%" PRIu8 " already stopped",
763                         dev_id);
764                 return;
765         }
766
767         dev->data->dev_started = 0;
768         (*dev->dev_ops->dev_stop)(dev);
769 }
770
771 int
772 rte_cryptodev_close(uint8_t dev_id)
773 {
774         struct rte_cryptodev *dev;
775         int retval;
776
777         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
778                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
779                 return -1;
780         }
781
782         dev = &rte_crypto_devices[dev_id];
783
784         /* Device must be stopped before it can be closed */
785         if (dev->data->dev_started == 1) {
786                 CDEV_LOG_ERR("Device %u must be stopped before closing",
787                                 dev_id);
788                 return -EBUSY;
789         }
790
791         /* We can't close the device if there are outstanding sessions in use */
792         if (dev->data->session_pool != NULL) {
793                 if (!rte_mempool_full(dev->data->session_pool)) {
794                         CDEV_LOG_ERR("dev_id=%u close failed, session mempool "
795                                         "has sessions still in use, free "
796                                         "all sessions before calling close",
797                                         (unsigned)dev_id);
798                         return -EBUSY;
799                 }
800         }
801
802         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);
803         retval = (*dev->dev_ops->dev_close)(dev);
804
805         if (retval < 0)
806                 return retval;
807
808         return 0;
809 }
810
811 int
812 rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
813                 const struct rte_cryptodev_qp_conf *qp_conf, int socket_id)
814 {
815         struct rte_cryptodev *dev;
816
817         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
818                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
819                 return -EINVAL;
820         }
821
822         dev = &rte_crypto_devices[dev_id];
823         if (queue_pair_id >= dev->data->nb_queue_pairs) {
824                 CDEV_LOG_ERR("Invalid queue_pair_id=%d", queue_pair_id);
825                 return -EINVAL;
826         }
827
828         if (dev->data->dev_started) {
829                 CDEV_LOG_ERR(
830                     "device %d must be stopped to allow configuration", dev_id);
831                 return -EBUSY;
832         }
833
834         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_setup, -ENOTSUP);
835
836         return (*dev->dev_ops->queue_pair_setup)(dev, queue_pair_id, qp_conf,
837                         socket_id);
838 }
839
840
841 int
842 rte_cryptodev_stats_get(uint8_t dev_id, struct rte_cryptodev_stats *stats)
843 {
844         struct rte_cryptodev *dev;
845
846         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
847                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
848                 return -ENODEV;
849         }
850
851         if (stats == NULL) {
852                 CDEV_LOG_ERR("Invalid stats ptr");
853                 return -EINVAL;
854         }
855
856         dev = &rte_crypto_devices[dev_id];
857         memset(stats, 0, sizeof(*stats));
858
859         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_get, -ENOTSUP);
860         (*dev->dev_ops->stats_get)(dev, stats);
861         return 0;
862 }
863
864 void
865 rte_cryptodev_stats_reset(uint8_t dev_id)
866 {
867         struct rte_cryptodev *dev;
868
869         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
870                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
871                 return;
872         }
873
874         dev = &rte_crypto_devices[dev_id];
875
876         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset);
877         (*dev->dev_ops->stats_reset)(dev);
878 }
879
880
881 void
882 rte_cryptodev_info_get(uint8_t dev_id, struct rte_cryptodev_info *dev_info)
883 {
884         struct rte_cryptodev *dev;
885
886         if (dev_id >= cryptodev_globals.nb_devs) {
887                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
888                 return;
889         }
890
891         dev = &rte_crypto_devices[dev_id];
892
893         memset(dev_info, 0, sizeof(struct rte_cryptodev_info));
894
895         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
896         (*dev->dev_ops->dev_infos_get)(dev, dev_info);
897
898         dev_info->pci_dev = dev->pci_dev;
899         if (dev->driver)
900                 dev_info->driver_name = dev->driver->pci_drv.driver.name;
901 }
902
903
904 int
905 rte_cryptodev_callback_register(uint8_t dev_id,
906                         enum rte_cryptodev_event_type event,
907                         rte_cryptodev_cb_fn cb_fn, void *cb_arg)
908 {
909         struct rte_cryptodev *dev;
910         struct rte_cryptodev_callback *user_cb;
911
912         if (!cb_fn)
913                 return -EINVAL;
914
915         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
916                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
917                 return -EINVAL;
918         }
919
920         dev = &rte_crypto_devices[dev_id];
921         rte_spinlock_lock(&rte_cryptodev_cb_lock);
922
923         TAILQ_FOREACH(user_cb, &(dev->link_intr_cbs), next) {
924                 if (user_cb->cb_fn == cb_fn &&
925                         user_cb->cb_arg == cb_arg &&
926                         user_cb->event == event) {
927                         break;
928                 }
929         }
930
931         /* create a new callback. */
932         if (user_cb == NULL) {
933                 user_cb = rte_zmalloc("INTR_USER_CALLBACK",
934                                 sizeof(struct rte_cryptodev_callback), 0);
935                 if (user_cb != NULL) {
936                         user_cb->cb_fn = cb_fn;
937                         user_cb->cb_arg = cb_arg;
938                         user_cb->event = event;
939                         TAILQ_INSERT_TAIL(&(dev->link_intr_cbs), user_cb, next);
940                 }
941         }
942
943         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
944         return (user_cb == NULL) ? -ENOMEM : 0;
945 }
946
947 int
948 rte_cryptodev_callback_unregister(uint8_t dev_id,
949                         enum rte_cryptodev_event_type event,
950                         rte_cryptodev_cb_fn cb_fn, void *cb_arg)
951 {
952         int ret;
953         struct rte_cryptodev *dev;
954         struct rte_cryptodev_callback *cb, *next;
955
956         if (!cb_fn)
957                 return -EINVAL;
958
959         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
960                 CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
961                 return -EINVAL;
962         }
963
964         dev = &rte_crypto_devices[dev_id];
965         rte_spinlock_lock(&rte_cryptodev_cb_lock);
966
967         ret = 0;
968         for (cb = TAILQ_FIRST(&dev->link_intr_cbs); cb != NULL; cb = next) {
969
970                 next = TAILQ_NEXT(cb, next);
971
972                 if (cb->cb_fn != cb_fn || cb->event != event ||
973                                 (cb->cb_arg != (void *)-1 &&
974                                 cb->cb_arg != cb_arg))
975                         continue;
976
977                 /*
978                  * if this callback is not executing right now,
979                  * then remove it.
980                  */
981                 if (cb->active == 0) {
982                         TAILQ_REMOVE(&(dev->link_intr_cbs), cb, next);
983                         rte_free(cb);
984                 } else {
985                         ret = -EAGAIN;
986                 }
987         }
988
989         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
990         return ret;
991 }
992
993 void
994 rte_cryptodev_pmd_callback_process(struct rte_cryptodev *dev,
995         enum rte_cryptodev_event_type event)
996 {
997         struct rte_cryptodev_callback *cb_lst;
998         struct rte_cryptodev_callback dev_cb;
999
1000         rte_spinlock_lock(&rte_cryptodev_cb_lock);
1001         TAILQ_FOREACH(cb_lst, &(dev->link_intr_cbs), next) {
1002                 if (cb_lst->cb_fn == NULL || cb_lst->event != event)
1003                         continue;
1004                 dev_cb = *cb_lst;
1005                 cb_lst->active = 1;
1006                 rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1007                 dev_cb.cb_fn(dev->data->dev_id, dev_cb.event,
1008                                                 dev_cb.cb_arg);
1009                 rte_spinlock_lock(&rte_cryptodev_cb_lock);
1010                 cb_lst->active = 0;
1011         }
1012         rte_spinlock_unlock(&rte_cryptodev_cb_lock);
1013 }
1014
1015
1016 static void
1017 rte_cryptodev_sym_session_init(struct rte_mempool *mp,
1018                 void *opaque_arg,
1019                 void *_sess,
1020                 __rte_unused unsigned i)
1021 {
1022         struct rte_cryptodev_sym_session *sess = _sess;
1023         struct rte_cryptodev *dev = opaque_arg;
1024
1025         memset(sess, 0, mp->elt_size);
1026
1027         sess->dev_id = dev->data->dev_id;
1028         sess->dev_type = dev->dev_type;
1029         sess->mp = mp;
1030
1031         if (dev->dev_ops->session_initialize)
1032                 (*dev->dev_ops->session_initialize)(mp, sess);
1033 }
1034
1035 static int
1036 rte_cryptodev_sym_session_pool_create(struct rte_cryptodev *dev,
1037                 unsigned nb_objs, unsigned obj_cache_size, int socket_id)
1038 {
1039         char mp_name[RTE_CRYPTODEV_NAME_MAX_LEN];
1040         unsigned priv_sess_size;
1041
1042         unsigned n = snprintf(mp_name, sizeof(mp_name), "cdev_%d_sess_mp",
1043                         dev->data->dev_id);
1044         if (n > sizeof(mp_name)) {
1045                 CDEV_LOG_ERR("Unable to create unique name for session mempool");
1046                 return -ENOMEM;
1047         }
1048
1049         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_get_size, -ENOTSUP);
1050         priv_sess_size = (*dev->dev_ops->session_get_size)(dev);
1051         if (priv_sess_size == 0) {
1052                 CDEV_LOG_ERR("%s returned and invalid private session size ",
1053                                                 dev->data->name);
1054                 return -ENOMEM;
1055         }
1056
1057         unsigned elt_size = sizeof(struct rte_cryptodev_sym_session) +
1058                         priv_sess_size;
1059
1060         dev->data->session_pool = rte_mempool_lookup(mp_name);
1061         if (dev->data->session_pool != NULL) {
1062                 if ((dev->data->session_pool->elt_size != elt_size) ||
1063                                 (dev->data->session_pool->cache_size <
1064                                 obj_cache_size) ||
1065                                 (dev->data->session_pool->size < nb_objs)) {
1066
1067                         CDEV_LOG_ERR("%s mempool already exists with different"
1068                                         " initialization parameters", mp_name);
1069                         dev->data->session_pool = NULL;
1070                         return -ENOMEM;
1071                 }
1072         } else {
1073                 dev->data->session_pool = rte_mempool_create(
1074                                 mp_name, /* mempool name */
1075                                 nb_objs, /* number of elements*/
1076                                 elt_size, /* element size*/
1077                                 obj_cache_size, /* Cache size*/
1078                                 0, /* private data size */
1079                                 NULL, /* obj initialization constructor */
1080                                 NULL, /* obj initialization constructor arg */
1081                                 rte_cryptodev_sym_session_init,
1082                                 /**< obj constructor*/
1083                                 dev, /* obj constructor arg */
1084                                 socket_id, /* socket id */
1085                                 0); /* flags */
1086
1087                 if (dev->data->session_pool == NULL) {
1088                         CDEV_LOG_ERR("%s mempool allocation failed", mp_name);
1089                         return -ENOMEM;
1090                 }
1091         }
1092
1093         CDEV_LOG_DEBUG("%s mempool created!", mp_name);
1094         return 0;
1095 }
1096
1097 struct rte_cryptodev_sym_session *
1098 rte_cryptodev_sym_session_create(uint8_t dev_id,
1099                 struct rte_crypto_sym_xform *xform)
1100 {
1101         struct rte_cryptodev *dev;
1102         struct rte_cryptodev_sym_session *sess;
1103         void *_sess;
1104
1105         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1106                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
1107                 return NULL;
1108         }
1109
1110         dev = &rte_crypto_devices[dev_id];
1111
1112         /* Allocate a session structure from the session pool */
1113         if (rte_mempool_get(dev->data->session_pool, &_sess)) {
1114                 CDEV_LOG_ERR("Couldn't get object from session mempool");
1115                 return NULL;
1116         }
1117
1118         sess = (struct rte_cryptodev_sym_session *)_sess;
1119
1120         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_configure, NULL);
1121         if (dev->dev_ops->session_configure(dev, xform, sess->_private) ==
1122                         NULL) {
1123                 CDEV_LOG_ERR("dev_id %d failed to configure session details",
1124                                 dev_id);
1125
1126                 /* Return session to mempool */
1127                 rte_mempool_put(sess->mp, _sess);
1128                 return NULL;
1129         }
1130
1131         return sess;
1132 }
1133
1134 struct rte_cryptodev_sym_session *
1135 rte_cryptodev_sym_session_free(uint8_t dev_id,
1136                 struct rte_cryptodev_sym_session *sess)
1137 {
1138         struct rte_cryptodev *dev;
1139
1140         if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
1141                 CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
1142                 return sess;
1143         }
1144
1145         dev = &rte_crypto_devices[dev_id];
1146
1147         /* Check the session belongs to this device type */
1148         if (sess->dev_type != dev->dev_type)
1149                 return sess;
1150
1151         /* Let device implementation clear session material */
1152         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_clear, sess);
1153         dev->dev_ops->session_clear(dev, (void *)sess->_private);
1154
1155         /* Return session to mempool */
1156         rte_mempool_put(sess->mp, (void *)sess);
1157
1158         return NULL;
1159 }
1160
1161 /** Initialise rte_crypto_op mempool element */
1162 static void
1163 rte_crypto_op_init(struct rte_mempool *mempool,
1164                 void *opaque_arg,
1165                 void *_op_data,
1166                 __rte_unused unsigned i)
1167 {
1168         struct rte_crypto_op *op = _op_data;
1169         enum rte_crypto_op_type type = *(enum rte_crypto_op_type *)opaque_arg;
1170
1171         memset(_op_data, 0, mempool->elt_size);
1172
1173         __rte_crypto_op_reset(op, type);
1174
1175         op->phys_addr = rte_mem_virt2phy(_op_data);
1176         op->mempool = mempool;
1177 }
1178
1179
1180 struct rte_mempool *
1181 rte_crypto_op_pool_create(const char *name, enum rte_crypto_op_type type,
1182                 unsigned nb_elts, unsigned cache_size, uint16_t priv_size,
1183                 int socket_id)
1184 {
1185         struct rte_crypto_op_pool_private *priv;
1186
1187         unsigned elt_size = sizeof(struct rte_crypto_op) +
1188                         sizeof(struct rte_crypto_sym_op) +
1189                         priv_size;
1190
1191         /* lookup mempool in case already allocated */
1192         struct rte_mempool *mp = rte_mempool_lookup(name);
1193
1194         if (mp != NULL) {
1195                 priv = (struct rte_crypto_op_pool_private *)
1196                                 rte_mempool_get_priv(mp);
1197
1198                 if (mp->elt_size != elt_size ||
1199                                 mp->cache_size < cache_size ||
1200                                 mp->size < nb_elts ||
1201                                 priv->priv_size <  priv_size) {
1202                         mp = NULL;
1203                         CDEV_LOG_ERR("Mempool %s already exists but with "
1204                                         "incompatible parameters", name);
1205                         return NULL;
1206                 }
1207                 return mp;
1208         }
1209
1210         mp = rte_mempool_create(
1211                         name,
1212                         nb_elts,
1213                         elt_size,
1214                         cache_size,
1215                         sizeof(struct rte_crypto_op_pool_private),
1216                         NULL,
1217                         NULL,
1218                         rte_crypto_op_init,
1219                         &type,
1220                         socket_id,
1221                         0);
1222
1223         if (mp == NULL) {
1224                 CDEV_LOG_ERR("Failed to create mempool %s", name);
1225                 return NULL;
1226         }
1227
1228         priv = (struct rte_crypto_op_pool_private *)
1229                         rte_mempool_get_priv(mp);
1230
1231         priv->priv_size = priv_size;
1232         priv->type = type;
1233
1234         return mp;
1235 }
1236
1237 int
1238 rte_cryptodev_pmd_create_dev_name(char *name, const char *dev_name_prefix)
1239 {
1240         struct rte_cryptodev *dev = NULL;
1241         uint32_t i = 0;
1242
1243         if (name == NULL)
1244                 return -EINVAL;
1245
1246         for (i = 0; i < RTE_CRYPTO_MAX_DEVS; i++) {
1247                 int ret = snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN,
1248                                 "%s_%u", dev_name_prefix, i);
1249
1250                 if (ret < 0)
1251                         return ret;
1252
1253                 dev = rte_cryptodev_pmd_get_named_dev(name);
1254                 if (!dev)
1255                         return 0;
1256         }
1257
1258         return -1;
1259 }