compressdev: add device feature flags
[dpdk.git] / lib / librte_compressdev / rte_compressdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017-2018 Intel Corporation
3  */
4
5 #include <string.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <inttypes.h>
9
10 #include <rte_malloc.h>
11 #include <rte_eal.h>
12 #include <rte_memzone.h>
13
14 #include "rte_compressdev.h"
15 #include "rte_compressdev_internal.h"
16 #include "rte_compressdev_pmd.h"
17
18 #define RTE_COMPRESSDEV_DETACHED  (0)
19 #define RTE_COMPRESSDEV_ATTACHED  (1)
20
21 struct rte_compressdev rte_comp_devices[RTE_COMPRESS_MAX_DEVS];
22
23 struct rte_compressdev *rte_compressdevs = &rte_comp_devices[0];
24
25 static struct rte_compressdev_global compressdev_globals = {
26                 .devs                   = &rte_comp_devices[0],
27                 .data                   = { NULL },
28                 .nb_devs                = 0,
29                 .max_devs               = RTE_COMPRESS_MAX_DEVS
30 };
31
32 struct rte_compressdev_global *rte_compressdev_globals = &compressdev_globals;
33
34 const char * __rte_experimental
35 rte_compressdev_get_feature_name(uint64_t flag)
36 {
37         switch (flag) {
38         case RTE_COMPDEV_FF_HW_ACCELERATED:
39                 return "HW_ACCELERATED";
40         case RTE_COMPDEV_FF_CPU_SSE:
41                 return "CPU_SSE";
42         case RTE_COMPDEV_FF_CPU_AVX:
43                 return "CPU_AVX";
44         case RTE_COMPDEV_FF_CPU_AVX2:
45                 return "CPU_AVX2";
46         case RTE_COMPDEV_FF_CPU_AVX512:
47                 return "CPU_AVX512";
48         case RTE_COMPDEV_FF_CPU_NEON:
49                 return "CPU_NEON";
50         default:
51                 return NULL;
52         }
53 }
54
55 static struct rte_compressdev *
56 rte_compressdev_get_dev(uint8_t dev_id)
57 {
58         return &rte_compressdev_globals->devs[dev_id];
59 }
60
61 struct rte_compressdev * __rte_experimental
62 rte_compressdev_pmd_get_named_dev(const char *name)
63 {
64         struct rte_compressdev *dev;
65         unsigned int i;
66
67         if (name == NULL)
68                 return NULL;
69
70         for (i = 0; i < rte_compressdev_globals->max_devs; i++) {
71                 dev = &rte_compressdev_globals->devs[i];
72
73                 if ((dev->attached == RTE_COMPRESSDEV_ATTACHED) &&
74                                 (strcmp(dev->data->name, name) == 0))
75                         return dev;
76         }
77
78         return NULL;
79 }
80
81 static unsigned int
82 rte_compressdev_is_valid_dev(uint8_t dev_id)
83 {
84         struct rte_compressdev *dev = NULL;
85
86         if (dev_id >= rte_compressdev_globals->nb_devs)
87                 return 0;
88
89         dev = rte_compressdev_get_dev(dev_id);
90         if (dev->attached != RTE_COMPRESSDEV_ATTACHED)
91                 return 0;
92         else
93                 return 1;
94 }
95
96
97 uint8_t __rte_experimental
98 rte_compressdev_count(void)
99 {
100         return rte_compressdev_globals->nb_devs;
101 }
102
103 uint8_t __rte_experimental
104 rte_compressdev_devices_get(const char *driver_name, uint8_t *devices,
105         uint8_t nb_devices)
106 {
107         uint8_t i, count = 0;
108         struct rte_compressdev *devs = rte_compressdev_globals->devs;
109         uint8_t max_devs = rte_compressdev_globals->max_devs;
110
111         for (i = 0; i < max_devs && count < nb_devices; i++) {
112
113                 if (devs[i].attached == RTE_COMPRESSDEV_ATTACHED) {
114                         int cmp;
115
116                         cmp = strncmp(devs[i].device->driver->name,
117                                         driver_name,
118                                         strlen(driver_name));
119
120                         if (cmp == 0)
121                                 devices[count++] = devs[i].data->dev_id;
122                 }
123         }
124
125         return count;
126 }
127
128 int __rte_experimental
129 rte_compressdev_socket_id(uint8_t dev_id)
130 {
131         struct rte_compressdev *dev;
132
133         if (!rte_compressdev_is_valid_dev(dev_id))
134                 return -1;
135
136         dev = rte_compressdev_get_dev(dev_id);
137
138         return dev->data->socket_id;
139 }
140
141 static inline int
142 rte_compressdev_data_alloc(uint8_t dev_id, struct rte_compressdev_data **data,
143                 int socket_id)
144 {
145         char mz_name[RTE_COMPRESSDEV_NAME_MAX_LEN];
146         const struct rte_memzone *mz;
147         int n;
148
149         /* generate memzone name */
150         n = snprintf(mz_name, sizeof(mz_name),
151                         "rte_compressdev_data_%u", dev_id);
152         if (n >= (int)sizeof(mz_name))
153                 return -EINVAL;
154
155         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
156                 mz = rte_memzone_reserve(mz_name,
157                                 sizeof(struct rte_compressdev_data),
158                                 socket_id, 0);
159         } else
160                 mz = rte_memzone_lookup(mz_name);
161
162         if (mz == NULL)
163                 return -ENOMEM;
164
165         *data = mz->addr;
166         if (rte_eal_process_type() == RTE_PROC_PRIMARY)
167                 memset(*data, 0, sizeof(struct rte_compressdev_data));
168
169         return 0;
170 }
171
172 static uint8_t
173 rte_compressdev_find_free_device_index(void)
174 {
175         uint8_t dev_id;
176
177         for (dev_id = 0; dev_id < RTE_COMPRESS_MAX_DEVS; dev_id++) {
178                 if (rte_comp_devices[dev_id].attached ==
179                                 RTE_COMPRESSDEV_DETACHED)
180                         return dev_id;
181         }
182         return RTE_COMPRESS_MAX_DEVS;
183 }
184
185 struct rte_compressdev * __rte_experimental
186 rte_compressdev_pmd_allocate(const char *name, int socket_id)
187 {
188         struct rte_compressdev *compressdev;
189         uint8_t dev_id;
190
191         if (rte_compressdev_pmd_get_named_dev(name) != NULL) {
192                 COMPRESSDEV_LOG(ERR,
193                         "comp device with name %s already allocated!", name);
194                 return NULL;
195         }
196
197         dev_id = rte_compressdev_find_free_device_index();
198         if (dev_id == RTE_COMPRESS_MAX_DEVS) {
199                 COMPRESSDEV_LOG(ERR, "Reached maximum number of comp devices");
200                 return NULL;
201         }
202         compressdev = rte_compressdev_get_dev(dev_id);
203
204         if (compressdev->data == NULL) {
205                 struct rte_compressdev_data *compressdev_data =
206                                 compressdev_globals.data[dev_id];
207
208                 int retval = rte_compressdev_data_alloc(dev_id,
209                                 &compressdev_data, socket_id);
210
211                 if (retval < 0 || compressdev_data == NULL)
212                         return NULL;
213
214                 compressdev->data = compressdev_data;
215
216                 snprintf(compressdev->data->name, RTE_COMPRESSDEV_NAME_MAX_LEN,
217                                 "%s", name);
218
219                 compressdev->data->dev_id = dev_id;
220                 compressdev->data->socket_id = socket_id;
221                 compressdev->data->dev_started = 0;
222
223                 compressdev->attached = RTE_COMPRESSDEV_ATTACHED;
224
225                 compressdev_globals.nb_devs++;
226         }
227
228         return compressdev;
229 }
230
231 int __rte_experimental
232 rte_compressdev_pmd_release_device(struct rte_compressdev *compressdev)
233 {
234         int ret;
235
236         if (compressdev == NULL)
237                 return -EINVAL;
238
239         /* Close device only if device operations have been set */
240         if (compressdev->dev_ops) {
241                 ret = rte_compressdev_close(compressdev->data->dev_id);
242                 if (ret < 0)
243                         return ret;
244         }
245
246         compressdev->attached = RTE_COMPRESSDEV_DETACHED;
247         compressdev_globals.nb_devs--;
248         return 0;
249 }
250
251 uint16_t __rte_experimental
252 rte_compressdev_queue_pair_count(uint8_t dev_id)
253 {
254         struct rte_compressdev *dev;
255
256         dev = &rte_comp_devices[dev_id];
257         return dev->data->nb_queue_pairs;
258 }
259
260 static int
261 rte_compressdev_queue_pairs_config(struct rte_compressdev *dev,
262                 uint16_t nb_qpairs, int socket_id)
263 {
264         struct rte_compressdev_info dev_info;
265         void **qp;
266         unsigned int i;
267
268         if ((dev == NULL) || (nb_qpairs < 1)) {
269                 COMPRESSDEV_LOG(ERR, "invalid param: dev %p, nb_queues %u",
270                                                         dev, nb_qpairs);
271                 return -EINVAL;
272         }
273
274         COMPRESSDEV_LOG(DEBUG, "Setup %d queues pairs on device %u",
275                         nb_qpairs, dev->data->dev_id);
276
277         memset(&dev_info, 0, sizeof(struct rte_compressdev_info));
278
279         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP);
280         (*dev->dev_ops->dev_infos_get)(dev, &dev_info);
281
282         if ((dev_info.max_nb_queue_pairs != 0) &&
283                         (nb_qpairs > dev_info.max_nb_queue_pairs)) {
284                 COMPRESSDEV_LOG(ERR, "Invalid num queue_pairs (%u) for dev %u",
285                                 nb_qpairs, dev->data->dev_id);
286                 return -EINVAL;
287         }
288
289         if (dev->data->queue_pairs == NULL) { /* first time configuration */
290                 dev->data->queue_pairs = rte_zmalloc_socket(
291                                 "compressdev->queue_pairs",
292                                 sizeof(dev->data->queue_pairs[0]) * nb_qpairs,
293                                 RTE_CACHE_LINE_SIZE, socket_id);
294
295                 if (dev->data->queue_pairs == NULL) {
296                         dev->data->nb_queue_pairs = 0;
297                         COMPRESSDEV_LOG(ERR,
298                         "failed to get memory for qp meta data, nb_queues %u",
299                                                         nb_qpairs);
300                         return -(ENOMEM);
301                 }
302         } else { /* re-configure */
303                 int ret;
304                 uint16_t old_nb_queues = dev->data->nb_queue_pairs;
305
306                 qp = dev->data->queue_pairs;
307
308                 RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_release,
309                                 -ENOTSUP);
310
311                 for (i = nb_qpairs; i < old_nb_queues; i++) {
312                         ret = (*dev->dev_ops->queue_pair_release)(dev, i);
313                         if (ret < 0)
314                                 return ret;
315                 }
316
317                 qp = rte_realloc(qp, sizeof(qp[0]) * nb_qpairs,
318                                 RTE_CACHE_LINE_SIZE);
319                 if (qp == NULL) {
320                         COMPRESSDEV_LOG(ERR,
321                         "failed to realloc qp meta data, nb_queues %u",
322                                                 nb_qpairs);
323                         return -(ENOMEM);
324                 }
325
326                 if (nb_qpairs > old_nb_queues) {
327                         uint16_t new_qs = nb_qpairs - old_nb_queues;
328
329                         memset(qp + old_nb_queues, 0,
330                                 sizeof(qp[0]) * new_qs);
331                 }
332
333                 dev->data->queue_pairs = qp;
334
335         }
336         dev->data->nb_queue_pairs = nb_qpairs;
337         return 0;
338 }
339
340 static int
341 rte_compressdev_queue_pairs_release(struct rte_compressdev *dev)
342 {
343         uint16_t num_qps, i;
344         int ret;
345
346         if (dev == NULL) {
347                 COMPRESSDEV_LOG(ERR, "invalid param: dev %p", dev);
348                 return -EINVAL;
349         }
350
351         num_qps = dev->data->nb_queue_pairs;
352
353         if (num_qps == 0)
354                 return 0;
355
356         COMPRESSDEV_LOG(DEBUG, "Free %d queues pairs on device %u",
357                         dev->data->nb_queue_pairs, dev->data->dev_id);
358
359         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_release,
360                                 -ENOTSUP);
361
362         for (i = 0; i < num_qps; i++) {
363                 ret = (*dev->dev_ops->queue_pair_release)(dev, i);
364                 if (ret < 0)
365                         return ret;
366         }
367
368         if (dev->data->queue_pairs != NULL)
369                 rte_free(dev->data->queue_pairs);
370         dev->data->queue_pairs = NULL;
371         dev->data->nb_queue_pairs = 0;
372
373         return 0;
374 }
375
376 int __rte_experimental
377 rte_compressdev_configure(uint8_t dev_id, struct rte_compressdev_config *config)
378 {
379         struct rte_compressdev *dev;
380         int diag;
381
382         if (!rte_compressdev_is_valid_dev(dev_id)) {
383                 COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id);
384                 return -EINVAL;
385         }
386
387         dev = &rte_comp_devices[dev_id];
388
389         if (dev->data->dev_started) {
390                 COMPRESSDEV_LOG(ERR,
391                     "device %d must be stopped to allow configuration", dev_id);
392                 return -EBUSY;
393         }
394
395         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);
396
397         /* Setup new number of queue pairs and reconfigure device. */
398         diag = rte_compressdev_queue_pairs_config(dev, config->nb_queue_pairs,
399                         config->socket_id);
400         if (diag != 0) {
401                 COMPRESSDEV_LOG(ERR,
402                         "dev%d rte_comp_dev_queue_pairs_config = %d",
403                                 dev_id, diag);
404                 return diag;
405         }
406
407         return (*dev->dev_ops->dev_configure)(dev, config);
408 }
409
410 int __rte_experimental
411 rte_compressdev_start(uint8_t dev_id)
412 {
413         struct rte_compressdev *dev;
414         int diag;
415
416         COMPRESSDEV_LOG(DEBUG, "Start dev_id=%" PRIu8, dev_id);
417
418         if (!rte_compressdev_is_valid_dev(dev_id)) {
419                 COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id);
420                 return -EINVAL;
421         }
422
423         dev = &rte_comp_devices[dev_id];
424
425         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP);
426
427         if (dev->data->dev_started != 0) {
428                 COMPRESSDEV_LOG(ERR,
429                     "Device with dev_id=%" PRIu8 " already started", dev_id);
430                 return 0;
431         }
432
433         diag = (*dev->dev_ops->dev_start)(dev);
434         if (diag == 0)
435                 dev->data->dev_started = 1;
436         else
437                 return diag;
438
439         return 0;
440 }
441
442 void __rte_experimental
443 rte_compressdev_stop(uint8_t dev_id)
444 {
445         struct rte_compressdev *dev;
446
447         if (!rte_compressdev_is_valid_dev(dev_id)) {
448                 COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id);
449                 return;
450         }
451
452         dev = &rte_comp_devices[dev_id];
453
454         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop);
455
456         if (dev->data->dev_started == 0) {
457                 COMPRESSDEV_LOG(ERR,
458                     "Device with dev_id=%" PRIu8 " already stopped", dev_id);
459                 return;
460         }
461
462         (*dev->dev_ops->dev_stop)(dev);
463         dev->data->dev_started = 0;
464 }
465
466 int __rte_experimental
467 rte_compressdev_close(uint8_t dev_id)
468 {
469         struct rte_compressdev *dev;
470         int retval;
471
472         if (!rte_compressdev_is_valid_dev(dev_id)) {
473                 COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id);
474                 return -1;
475         }
476
477         dev = &rte_comp_devices[dev_id];
478
479         /* Device must be stopped before it can be closed */
480         if (dev->data->dev_started == 1) {
481                 COMPRESSDEV_LOG(ERR, "Device %u must be stopped before closing",
482                                 dev_id);
483                 return -EBUSY;
484         }
485
486         /* Free queue pairs memory */
487         retval = rte_compressdev_queue_pairs_release(dev);
488
489         if (retval < 0)
490                 return retval;
491
492         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);
493         retval = (*dev->dev_ops->dev_close)(dev);
494
495         if (retval < 0)
496                 return retval;
497
498         return 0;
499 }
500
501 int __rte_experimental
502 rte_compressdev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
503                 uint32_t max_inflight_ops, int socket_id)
504 {
505         struct rte_compressdev *dev;
506
507         if (!rte_compressdev_is_valid_dev(dev_id)) {
508                 COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id);
509                 return -EINVAL;
510         }
511
512         dev = &rte_comp_devices[dev_id];
513         if (queue_pair_id >= dev->data->nb_queue_pairs) {
514                 COMPRESSDEV_LOG(ERR, "Invalid queue_pair_id=%d", queue_pair_id);
515                 return -EINVAL;
516         }
517
518         if (dev->data->dev_started) {
519                 COMPRESSDEV_LOG(ERR,
520                     "device %d must be stopped to allow configuration", dev_id);
521                 return -EBUSY;
522         }
523
524         if (max_inflight_ops == 0) {
525                 COMPRESSDEV_LOG(ERR,
526                         "Invalid maximum number of inflight operations");
527                 return -EINVAL;
528         }
529
530         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_setup, -ENOTSUP);
531
532         return (*dev->dev_ops->queue_pair_setup)(dev, queue_pair_id,
533                         max_inflight_ops, socket_id);
534 }
535
536 uint16_t __rte_experimental
537 rte_compressdev_dequeue_burst(uint8_t dev_id, uint16_t qp_id,
538                 struct rte_comp_op **ops, uint16_t nb_ops)
539 {
540         struct rte_compressdev *dev = &rte_compressdevs[dev_id];
541
542         nb_ops = (*dev->dequeue_burst)
543                         (dev->data->queue_pairs[qp_id], ops, nb_ops);
544
545         return nb_ops;
546 }
547
548 uint16_t __rte_experimental
549 rte_compressdev_enqueue_burst(uint8_t dev_id, uint16_t qp_id,
550                 struct rte_comp_op **ops, uint16_t nb_ops)
551 {
552         struct rte_compressdev *dev = &rte_compressdevs[dev_id];
553
554         return (*dev->enqueue_burst)(
555                         dev->data->queue_pairs[qp_id], ops, nb_ops);
556 }
557
558 void __rte_experimental
559 rte_compressdev_info_get(uint8_t dev_id, struct rte_compressdev_info *dev_info)
560 {
561         struct rte_compressdev *dev;
562
563         if (dev_id >= compressdev_globals.nb_devs) {
564                 COMPRESSDEV_LOG(ERR, "Invalid dev_id=%d", dev_id);
565                 return;
566         }
567
568         dev = &rte_comp_devices[dev_id];
569
570         memset(dev_info, 0, sizeof(struct rte_compressdev_info));
571
572         RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get);
573         (*dev->dev_ops->dev_infos_get)(dev, dev_info);
574
575         dev_info->driver_name = dev->device->driver->name;
576 }
577
578 int __rte_experimental
579 rte_compressdev_private_xform_create(uint8_t dev_id,
580                 const struct rte_comp_xform *xform,
581                 void **priv_xform)
582 {
583         struct rte_compressdev *dev;
584         int ret;
585
586         dev = rte_compressdev_get_dev(dev_id);
587
588         if (xform == NULL || priv_xform == NULL || dev == NULL)
589                 return -EINVAL;
590
591         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->private_xform_create, -ENOTSUP);
592         ret = (*dev->dev_ops->private_xform_create)(dev, xform, priv_xform);
593         if (ret < 0) {
594                 COMPRESSDEV_LOG(ERR,
595                         "dev_id %d failed to create private_xform: err=%d",
596                         dev_id, ret);
597                 return ret;
598         };
599
600         return 0;
601 }
602
603 int __rte_experimental
604 rte_compressdev_private_xform_free(uint8_t dev_id, void *priv_xform)
605 {
606         struct rte_compressdev *dev;
607         int ret;
608
609         dev = rte_compressdev_get_dev(dev_id);
610
611         if (dev == NULL || priv_xform == NULL)
612                 return -EINVAL;
613
614         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->private_xform_free, -ENOTSUP);
615         ret = dev->dev_ops->private_xform_free(dev, priv_xform);
616         if (ret < 0) {
617                 COMPRESSDEV_LOG(ERR,
618                         "dev_id %d failed to free private xform: err=%d",
619                         dev_id, ret);
620                 return ret;
621         };
622
623         return 0;
624 }
625
626 int __rte_experimental
627 rte_compressdev_stream_create(uint8_t dev_id,
628                 const struct rte_comp_xform *xform,
629                 void **stream)
630 {
631         struct rte_compressdev *dev;
632         int ret;
633
634         dev = rte_compressdev_get_dev(dev_id);
635
636         if (xform == NULL || dev == NULL || stream == NULL)
637                 return -EINVAL;
638
639         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stream_create, -ENOTSUP);
640         ret = (*dev->dev_ops->stream_create)(dev, xform, stream);
641         if (ret < 0) {
642                 COMPRESSDEV_LOG(ERR,
643                         "dev_id %d failed to create stream: err=%d",
644                         dev_id, ret);
645                 return ret;
646         };
647
648         return 0;
649 }
650
651
652 int __rte_experimental
653 rte_compressdev_stream_free(uint8_t dev_id, void *stream)
654 {
655         struct rte_compressdev *dev;
656         int ret;
657
658         dev = rte_compressdev_get_dev(dev_id);
659
660         if (dev == NULL || stream == NULL)
661                 return -EINVAL;
662
663         RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stream_free, -ENOTSUP);
664         ret = dev->dev_ops->stream_free(dev, stream);
665         if (ret < 0) {
666                 COMPRESSDEV_LOG(ERR,
667                         "dev_id %d failed to free stream: err=%d",
668                         dev_id, ret);
669                 return ret;
670         };
671
672         return 0;
673 }
674
675 const char * __rte_experimental
676 rte_compressdev_name_get(uint8_t dev_id)
677 {
678         struct rte_compressdev *dev = rte_compressdev_get_dev(dev_id);
679
680         if (dev == NULL)
681                 return NULL;
682
683         return dev->data->name;
684 }
685
686 RTE_INIT(rte_compressdev_log);
687
688 static void
689 rte_compressdev_log(void)
690 {
691         compressdev_logtype = rte_log_register("lib.compressdev");
692         if (compressdev_logtype >= 0)
693                 rte_log_set_level(compressdev_logtype, RTE_LOG_NOTICE);
694 }