net/ice: clean input set macro definition
[dpdk.git] / drivers / compress / mlx5 / mlx5_compress.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2021 Mellanox Technologies, Ltd
3  */
4
5 #include <rte_malloc.h>
6 #include <rte_log.h>
7 #include <rte_errno.h>
8 #include <rte_pci.h>
9 #include <rte_spinlock.h>
10 #include <rte_comp.h>
11 #include <rte_compressdev.h>
12 #include <rte_compressdev_pmd.h>
13
14 #include <mlx5_glue.h>
15 #include <mlx5_common.h>
16 #include <mlx5_common_pci.h>
17 #include <mlx5_devx_cmds.h>
18 #include <mlx5_common_os.h>
19 #include <mlx5_common_devx.h>
20 #include <mlx5_common_mr.h>
21 #include <mlx5_prm.h>
22
23 #include "mlx5_compress_utils.h"
24
25 #define MLX5_COMPRESS_DRIVER_NAME mlx5_compress
26 #define MLX5_COMPRESS_LOG_NAME    pmd.compress.mlx5
27 #define MLX5_COMPRESS_MAX_QPS 1024
28 #define MLX5_COMP_MAX_WIN_SIZE_CONF 6u
29
30 struct mlx5_compress_xform {
31         LIST_ENTRY(mlx5_compress_xform) next;
32         enum rte_comp_xform_type type;
33         enum rte_comp_checksum_type csum_type;
34         uint32_t opcode;
35         uint32_t gga_ctrl1; /* BE. */
36 };
37
38 struct mlx5_compress_priv {
39         TAILQ_ENTRY(mlx5_compress_priv) next;
40         struct ibv_context *ctx; /* Device context. */
41         struct rte_pci_device *pci_dev;
42         struct rte_compressdev *cdev;
43         void *uar;
44         uint32_t pdn; /* Protection Domain number. */
45         uint8_t min_block_size;
46         /* Minimum huffman block size supported by the device. */
47         struct ibv_pd *pd;
48         struct rte_compressdev_config dev_config;
49         LIST_HEAD(xform_list, mlx5_compress_xform) xform_list;
50         rte_spinlock_t xform_sl;
51         struct mlx5_mr_share_cache mr_scache; /* Global shared MR cache. */
52         volatile uint64_t *uar_addr;
53 #ifndef RTE_ARCH_64
54         rte_spinlock_t uar32_sl;
55 #endif /* RTE_ARCH_64 */
56 };
57
58 struct mlx5_compress_qp {
59         uint16_t qp_id;
60         uint16_t entries_n;
61         uint16_t pi;
62         uint16_t ci;
63         struct mlx5_mr_ctrl mr_ctrl;
64         int socket_id;
65         struct mlx5_devx_cq cq;
66         struct mlx5_devx_sq sq;
67         struct mlx5_pmd_mr opaque_mr;
68         struct rte_comp_op **ops;
69         struct mlx5_compress_priv *priv;
70         struct rte_compressdev_stats stats;
71 };
72
73 TAILQ_HEAD(mlx5_compress_privs, mlx5_compress_priv) mlx5_compress_priv_list =
74                                 TAILQ_HEAD_INITIALIZER(mlx5_compress_priv_list);
75 static pthread_mutex_t priv_list_lock = PTHREAD_MUTEX_INITIALIZER;
76
77 int mlx5_compress_logtype;
78
79 static const struct rte_compressdev_capabilities mlx5_caps[] = {
80         {
81                 .algo = RTE_COMP_ALGO_NULL,
82                 .comp_feature_flags = RTE_COMP_FF_ADLER32_CHECKSUM |
83                                       RTE_COMP_FF_CRC32_CHECKSUM |
84                                       RTE_COMP_FF_CRC32_ADLER32_CHECKSUM |
85                                       RTE_COMP_FF_SHAREABLE_PRIV_XFORM,
86         },
87         {
88                 .algo = RTE_COMP_ALGO_DEFLATE,
89                 .comp_feature_flags = RTE_COMP_FF_ADLER32_CHECKSUM |
90                                       RTE_COMP_FF_CRC32_CHECKSUM |
91                                       RTE_COMP_FF_CRC32_ADLER32_CHECKSUM |
92                                       RTE_COMP_FF_SHAREABLE_PRIV_XFORM |
93                                       RTE_COMP_FF_HUFFMAN_FIXED |
94                                       RTE_COMP_FF_HUFFMAN_DYNAMIC,
95                 .window_size = {.min = 10, .max = 15, .increment = 1},
96         },
97         {
98                 .algo = RTE_COMP_ALGO_LIST_END,
99         }
100 };
101
102 static void
103 mlx5_compress_dev_info_get(struct rte_compressdev *dev,
104                            struct rte_compressdev_info *info)
105 {
106         RTE_SET_USED(dev);
107         if (info != NULL) {
108                 info->max_nb_queue_pairs = MLX5_COMPRESS_MAX_QPS;
109                 info->feature_flags = RTE_COMPDEV_FF_HW_ACCELERATED;
110                 info->capabilities = mlx5_caps;
111         }
112 }
113
114 static int
115 mlx5_compress_dev_configure(struct rte_compressdev *dev,
116                             struct rte_compressdev_config *config)
117 {
118         struct mlx5_compress_priv *priv;
119
120         if (dev == NULL || config == NULL)
121                 return -EINVAL;
122         priv = dev->data->dev_private;
123         priv->dev_config = *config;
124         return 0;
125 }
126
127 static int
128 mlx5_compress_dev_close(struct rte_compressdev *dev)
129 {
130         RTE_SET_USED(dev);
131         return 0;
132 }
133
134 static int
135 mlx5_compress_qp_release(struct rte_compressdev *dev, uint16_t qp_id)
136 {
137         struct mlx5_compress_qp *qp = dev->data->queue_pairs[qp_id];
138
139         if (qp->sq.sq != NULL)
140                 mlx5_devx_sq_destroy(&qp->sq);
141         if (qp->cq.cq != NULL)
142                 mlx5_devx_cq_destroy(&qp->cq);
143         if (qp->opaque_mr.obj != NULL) {
144                 void *opaq = qp->opaque_mr.addr;
145
146                 mlx5_common_verbs_dereg_mr(&qp->opaque_mr);
147                 if (opaq != NULL)
148                         rte_free(opaq);
149         }
150         mlx5_mr_btree_free(&qp->mr_ctrl.cache_bh);
151         rte_free(qp);
152         dev->data->queue_pairs[qp_id] = NULL;
153         return 0;
154 }
155
156 static void
157 mlx5_compress_init_sq(struct mlx5_compress_qp *qp)
158 {
159         volatile struct mlx5_gga_wqe *restrict wqe =
160                                     (volatile struct mlx5_gga_wqe *)qp->sq.wqes;
161         volatile struct mlx5_gga_compress_opaque *opaq = qp->opaque_mr.addr;
162         const uint32_t sq_ds = rte_cpu_to_be_32((qp->sq.sq->id << 8) | 4u);
163         const uint32_t flags = RTE_BE32(MLX5_COMP_ALWAYS <<
164                                         MLX5_COMP_MODE_OFFSET);
165         const uint32_t opaq_lkey = rte_cpu_to_be_32(qp->opaque_mr.lkey);
166         int i;
167
168         /* All the next fields state should stay constant. */
169         for (i = 0; i < qp->entries_n; ++i, ++wqe) {
170                 wqe->sq_ds = sq_ds;
171                 wqe->flags = flags;
172                 wqe->opaque_lkey = opaq_lkey;
173                 wqe->opaque_vaddr = rte_cpu_to_be_64
174                                                 ((uint64_t)(uintptr_t)&opaq[i]);
175         }
176 }
177
178 static int
179 mlx5_compress_qp_setup(struct rte_compressdev *dev, uint16_t qp_id,
180                        uint32_t max_inflight_ops, int socket_id)
181 {
182         struct mlx5_compress_priv *priv = dev->data->dev_private;
183         struct mlx5_compress_qp *qp;
184         struct mlx5_devx_cq_attr cq_attr = {
185                 .uar_page_id = mlx5_os_get_devx_uar_page_id(priv->uar),
186         };
187         struct mlx5_devx_create_sq_attr sq_attr = {
188                 .user_index = qp_id,
189                 .wq_attr = (struct mlx5_devx_wq_attr){
190                         .pd = priv->pdn,
191                         .uar_page = mlx5_os_get_devx_uar_page_id(priv->uar),
192                 },
193         };
194         struct mlx5_devx_modify_sq_attr modify_attr = {
195                 .state = MLX5_SQC_STATE_RDY,
196         };
197         uint32_t log_ops_n = rte_log2_u32(max_inflight_ops);
198         uint32_t alloc_size = sizeof(*qp);
199         void *opaq_buf;
200         int ret;
201
202         alloc_size = RTE_ALIGN(alloc_size, RTE_CACHE_LINE_SIZE);
203         alloc_size += sizeof(struct rte_comp_op *) * (1u << log_ops_n);
204         qp = rte_zmalloc_socket(__func__, alloc_size, RTE_CACHE_LINE_SIZE,
205                                 socket_id);
206         if (qp == NULL) {
207                 DRV_LOG(ERR, "Failed to allocate qp memory.");
208                 rte_errno = ENOMEM;
209                 return -rte_errno;
210         }
211         dev->data->queue_pairs[qp_id] = qp;
212         opaq_buf = rte_calloc(__func__, 1u << log_ops_n,
213                               sizeof(struct mlx5_gga_compress_opaque),
214                               sizeof(struct mlx5_gga_compress_opaque));
215         if (opaq_buf == NULL) {
216                 DRV_LOG(ERR, "Failed to allocate opaque memory.");
217                 rte_errno = ENOMEM;
218                 goto err;
219         }
220         if (mlx5_mr_btree_init(&qp->mr_ctrl.cache_bh, MLX5_MR_BTREE_CACHE_N,
221                                priv->dev_config.socket_id)) {
222                 DRV_LOG(ERR, "Cannot allocate MR Btree for qp %u.",
223                         (uint32_t)qp_id);
224                 rte_errno = ENOMEM;
225                 goto err;
226         }
227         qp->entries_n = 1 << log_ops_n;
228         qp->socket_id = socket_id;
229         qp->qp_id = qp_id;
230         qp->priv = priv;
231         qp->ops = (struct rte_comp_op **)RTE_ALIGN((uintptr_t)(qp + 1),
232                                                    RTE_CACHE_LINE_SIZE);
233         if (mlx5_common_verbs_reg_mr(priv->pd, opaq_buf, qp->entries_n *
234                                         sizeof(struct mlx5_gga_compress_opaque),
235                                                          &qp->opaque_mr) != 0) {
236                 rte_free(opaq_buf);
237                 DRV_LOG(ERR, "Failed to register opaque MR.");
238                 rte_errno = ENOMEM;
239                 goto err;
240         }
241         ret = mlx5_devx_cq_create(priv->ctx, &qp->cq, log_ops_n, &cq_attr,
242                                   socket_id);
243         if (ret != 0) {
244                 DRV_LOG(ERR, "Failed to create CQ.");
245                 goto err;
246         }
247         sq_attr.cqn = qp->cq.cq->id;
248         ret = mlx5_devx_sq_create(priv->ctx, &qp->sq, log_ops_n, &sq_attr,
249                                   socket_id);
250         if (ret != 0) {
251                 DRV_LOG(ERR, "Failed to create SQ.");
252                 goto err;
253         }
254         mlx5_compress_init_sq(qp);
255         ret = mlx5_devx_cmd_modify_sq(qp->sq.sq, &modify_attr);
256         if (ret != 0) {
257                 DRV_LOG(ERR, "Can't change SQ state to ready.");
258                 goto err;
259         }
260         DRV_LOG(INFO, "QP %u: SQN=0x%X CQN=0x%X entries num = %u\n",
261                 (uint32_t)qp_id, qp->sq.sq->id, qp->cq.cq->id, qp->entries_n);
262         return 0;
263 err:
264         mlx5_compress_qp_release(dev, qp_id);
265         return -1;
266 }
267
268 static int
269 mlx5_compress_xform_free(struct rte_compressdev *dev, void *xform)
270 {
271         struct mlx5_compress_priv *priv = dev->data->dev_private;
272
273         rte_spinlock_lock(&priv->xform_sl);
274         LIST_REMOVE((struct mlx5_compress_xform *)xform, next);
275         rte_spinlock_unlock(&priv->xform_sl);
276         rte_free(xform);
277         return 0;
278 }
279
280 static int
281 mlx5_compress_xform_create(struct rte_compressdev *dev,
282                            const struct rte_comp_xform *xform,
283                            void **private_xform)
284 {
285         struct mlx5_compress_priv *priv = dev->data->dev_private;
286         struct mlx5_compress_xform *xfrm;
287         uint32_t size;
288
289         if (xform->type == RTE_COMP_COMPRESS && xform->compress.level ==
290                                                           RTE_COMP_LEVEL_NONE) {
291                 DRV_LOG(ERR, "Non-compressed block is not supported.");
292                 return -ENOTSUP;
293         }
294         if ((xform->type == RTE_COMP_COMPRESS && xform->compress.hash_algo !=
295              RTE_COMP_HASH_ALGO_NONE) || (xform->type == RTE_COMP_DECOMPRESS &&
296                       xform->decompress.hash_algo != RTE_COMP_HASH_ALGO_NONE)) {
297                 DRV_LOG(ERR, "SHA is not supported.");
298                 return -ENOTSUP;
299         }
300         xfrm = rte_zmalloc_socket(__func__, sizeof(*xfrm), 0,
301                                                     priv->dev_config.socket_id);
302         if (xfrm == NULL)
303                 return -ENOMEM;
304         xfrm->opcode = MLX5_OPCODE_MMO;
305         xfrm->type = xform->type;
306         switch (xform->type) {
307         case RTE_COMP_COMPRESS:
308                 switch (xform->compress.algo) {
309                 case RTE_COMP_ALGO_NULL:
310                         xfrm->opcode += MLX5_OPC_MOD_MMO_DMA <<
311                                                         WQE_CSEG_OPC_MOD_OFFSET;
312                         break;
313                 case RTE_COMP_ALGO_DEFLATE:
314                         size = 1 << xform->compress.window_size;
315                         size /= MLX5_GGA_COMP_WIN_SIZE_UNITS;
316                         xfrm->gga_ctrl1 += RTE_MIN(rte_log2_u32(size),
317                                          MLX5_COMP_MAX_WIN_SIZE_CONF) <<
318                                            WQE_GGA_COMP_WIN_SIZE_OFFSET;
319                         if (xform->compress.level == RTE_COMP_LEVEL_PMD_DEFAULT)
320                                 size = MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX;
321                         else
322                                 size = priv->min_block_size - 1 +
323                                                           xform->compress.level;
324                         xfrm->gga_ctrl1 += RTE_MIN(size,
325                                             MLX5_GGA_COMP_LOG_BLOCK_SIZE_MAX) <<
326                                                  WQE_GGA_COMP_BLOCK_SIZE_OFFSET;
327                         xfrm->opcode += MLX5_OPC_MOD_MMO_COMP <<
328                                                         WQE_CSEG_OPC_MOD_OFFSET;
329                         size = xform->compress.deflate.huffman ==
330                                                       RTE_COMP_HUFFMAN_DYNAMIC ?
331                                             MLX5_GGA_COMP_LOG_DYNAMIC_SIZE_MAX :
332                                              MLX5_GGA_COMP_LOG_DYNAMIC_SIZE_MIN;
333                         xfrm->gga_ctrl1 += size <<
334                                                WQE_GGA_COMP_DYNAMIC_SIZE_OFFSET;
335                         break;
336                 default:
337                         goto err;
338                 }
339                 xfrm->csum_type = xform->compress.chksum;
340                 break;
341         case RTE_COMP_DECOMPRESS:
342                 switch (xform->decompress.algo) {
343                 case RTE_COMP_ALGO_NULL:
344                         xfrm->opcode += MLX5_OPC_MOD_MMO_DMA <<
345                                                         WQE_CSEG_OPC_MOD_OFFSET;
346                         break;
347                 case RTE_COMP_ALGO_DEFLATE:
348                         xfrm->opcode += MLX5_OPC_MOD_MMO_DECOMP <<
349                                                         WQE_CSEG_OPC_MOD_OFFSET;
350                         break;
351                 default:
352                         goto err;
353                 }
354                 xfrm->csum_type = xform->decompress.chksum;
355                 break;
356         default:
357                 DRV_LOG(ERR, "Algorithm %u is not supported.", xform->type);
358                 goto err;
359         }
360         DRV_LOG(DEBUG, "New xform: gga ctrl1 = 0x%08X opcode = 0x%08X csum "
361                 "type = %d.", xfrm->gga_ctrl1, xfrm->opcode, xfrm->csum_type);
362         xfrm->gga_ctrl1 = rte_cpu_to_be_32(xfrm->gga_ctrl1);
363         rte_spinlock_lock(&priv->xform_sl);
364         LIST_INSERT_HEAD(&priv->xform_list, xfrm, next);
365         rte_spinlock_unlock(&priv->xform_sl);
366         *private_xform = xfrm;
367         return 0;
368 err:
369         rte_free(xfrm);
370         return -ENOTSUP;
371 }
372
373 static void
374 mlx5_compress_dev_stop(struct rte_compressdev *dev)
375 {
376         RTE_SET_USED(dev);
377 }
378
379 static int
380 mlx5_compress_dev_start(struct rte_compressdev *dev)
381 {
382         RTE_SET_USED(dev);
383         return 0;
384 }
385
386 static void
387 mlx5_compress_stats_get(struct rte_compressdev *dev,
388                 struct rte_compressdev_stats *stats)
389 {
390         int qp_id;
391
392         for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
393                 struct mlx5_compress_qp *qp = dev->data->queue_pairs[qp_id];
394
395                 stats->enqueued_count += qp->stats.enqueued_count;
396                 stats->dequeued_count += qp->stats.dequeued_count;
397                 stats->enqueue_err_count += qp->stats.enqueue_err_count;
398                 stats->dequeue_err_count += qp->stats.dequeue_err_count;
399         }
400 }
401
402 static void
403 mlx5_compress_stats_reset(struct rte_compressdev *dev)
404 {
405         int qp_id;
406
407         for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
408                 struct mlx5_compress_qp *qp = dev->data->queue_pairs[qp_id];
409
410                 memset(&qp->stats, 0, sizeof(qp->stats));
411         }
412 }
413
414 static struct rte_compressdev_ops mlx5_compress_ops = {
415         .dev_configure          = mlx5_compress_dev_configure,
416         .dev_start              = mlx5_compress_dev_start,
417         .dev_stop               = mlx5_compress_dev_stop,
418         .dev_close              = mlx5_compress_dev_close,
419         .dev_infos_get          = mlx5_compress_dev_info_get,
420         .stats_get              = mlx5_compress_stats_get,
421         .stats_reset            = mlx5_compress_stats_reset,
422         .queue_pair_setup       = mlx5_compress_qp_setup,
423         .queue_pair_release     = mlx5_compress_qp_release,
424         .private_xform_create   = mlx5_compress_xform_create,
425         .private_xform_free     = mlx5_compress_xform_free,
426         .stream_create          = NULL,
427         .stream_free            = NULL,
428 };
429
430 static __rte_always_inline uint32_t
431 mlx5_compress_dseg_set(struct mlx5_compress_qp *qp,
432                        volatile struct mlx5_wqe_dseg *restrict dseg,
433                        struct rte_mbuf *restrict mbuf,
434                        uint32_t offset, uint32_t len)
435 {
436         uintptr_t addr = rte_pktmbuf_mtod_offset(mbuf, uintptr_t, offset);
437
438         dseg->bcount = rte_cpu_to_be_32(len);
439         dseg->lkey = mlx5_mr_addr2mr_bh(qp->priv->pd, 0, &qp->priv->mr_scache,
440                                         &qp->mr_ctrl, addr,
441                                         !!(mbuf->ol_flags & EXT_ATTACHED_MBUF));
442         dseg->pbuf = rte_cpu_to_be_64(addr);
443         return dseg->lkey;
444 }
445
446 /*
447  * Provide safe 64bit store operation to mlx5 UAR region for both 32bit and
448  * 64bit architectures.
449  */
450 static __rte_always_inline void
451 mlx5_compress_uar_write(uint64_t val, struct mlx5_compress_priv *priv)
452 {
453 #ifdef RTE_ARCH_64
454         *priv->uar_addr = val;
455 #else /* !RTE_ARCH_64 */
456         rte_spinlock_lock(&priv->uar32_sl);
457         *(volatile uint32_t *)priv->uar_addr = val;
458         rte_io_wmb();
459         *((volatile uint32_t *)priv->uar_addr + 1) = val >> 32;
460         rte_spinlock_unlock(&priv->uar32_sl);
461 #endif
462 }
463
464 static uint16_t
465 mlx5_compress_enqueue_burst(void *queue_pair, struct rte_comp_op **ops,
466                             uint16_t nb_ops)
467 {
468         struct mlx5_compress_qp *qp = queue_pair;
469         volatile struct mlx5_gga_wqe *wqes = (volatile struct mlx5_gga_wqe *)
470                                                               qp->sq.wqes, *wqe;
471         struct mlx5_compress_xform *xform;
472         struct rte_comp_op *op;
473         uint16_t mask = qp->entries_n - 1;
474         uint16_t remain = qp->entries_n - (qp->pi - qp->ci);
475         uint16_t idx;
476         bool invalid;
477
478         if (remain < nb_ops)
479                 nb_ops = remain;
480         else
481                 remain = nb_ops;
482         if (unlikely(remain == 0))
483                 return 0;
484         do {
485                 idx = qp->pi & mask;
486                 wqe = &wqes[idx];
487                 rte_prefetch0(&wqes[(qp->pi + 1) & mask]);
488                 op = *ops++;
489                 xform = op->private_xform;
490                 /*
491                  * Check operation arguments and error cases:
492                  *   - Operation type must be state-less.
493                  *   - Compress operation flush flag must be FULL or FINAL.
494                  *   - Source and destination buffers must be mapped internally.
495                  */
496                 invalid = op->op_type != RTE_COMP_OP_STATELESS ||
497                                             (xform->type == RTE_COMP_COMPRESS &&
498                                           op->flush_flag < RTE_COMP_FLUSH_FULL);
499                 if (unlikely(invalid ||
500                              (mlx5_compress_dseg_set(qp, &wqe->gather,
501                                                      op->m_src,
502                                                      op->src.offset,
503                                                      op->src.length) ==
504                                                                   UINT32_MAX) ||
505                              (mlx5_compress_dseg_set(qp, &wqe->scatter,
506                                                 op->m_dst,
507                                                 op->dst.offset,
508                                                 rte_pktmbuf_pkt_len(op->m_dst) -
509                                                               op->dst.offset) ==
510                                                                  UINT32_MAX))) {
511                         op->status = invalid ? RTE_COMP_OP_STATUS_INVALID_ARGS :
512                                                        RTE_COMP_OP_STATUS_ERROR;
513                         nb_ops -= remain;
514                         if (unlikely(nb_ops == 0))
515                                 return 0;
516                         break;
517                 }
518                 wqe->gga_ctrl1 = xform->gga_ctrl1;
519                 wqe->opcode = rte_cpu_to_be_32(xform->opcode + (qp->pi << 8));
520                 qp->ops[idx] = op;
521                 qp->pi++;
522         } while (--remain);
523         qp->stats.enqueued_count += nb_ops;
524         rte_io_wmb();
525         qp->sq.db_rec[MLX5_SND_DBR] = rte_cpu_to_be_32(qp->pi);
526         rte_wmb();
527         mlx5_compress_uar_write(*(volatile uint64_t *)wqe, qp->priv);
528         rte_wmb();
529         return nb_ops;
530 }
531
532 static void
533 mlx5_compress_dump_err_objs(volatile uint32_t *cqe, volatile uint32_t *wqe,
534                              volatile uint32_t *opaq)
535 {
536         size_t i;
537
538         DRV_LOG(ERR, "Error cqe:");
539         for (i = 0; i < sizeof(struct mlx5_err_cqe) >> 2; i += 4)
540                 DRV_LOG(ERR, "%08X %08X %08X %08X", cqe[i], cqe[i + 1],
541                         cqe[i + 2], cqe[i + 3]);
542         DRV_LOG(ERR, "\nError wqe:");
543         for (i = 0; i < sizeof(struct mlx5_gga_wqe) >> 2; i += 4)
544                 DRV_LOG(ERR, "%08X %08X %08X %08X", wqe[i], wqe[i + 1],
545                         wqe[i + 2], wqe[i + 3]);
546         DRV_LOG(ERR, "\nError opaq:");
547         for (i = 0; i < sizeof(struct mlx5_gga_compress_opaque) >> 2; i += 4)
548                 DRV_LOG(ERR, "%08X %08X %08X %08X", opaq[i], opaq[i + 1],
549                         opaq[i + 2], opaq[i + 3]);
550 }
551
552 static void
553 mlx5_compress_cqe_err_handle(struct mlx5_compress_qp *qp,
554                              struct rte_comp_op *op)
555 {
556         const uint32_t idx = qp->ci & (qp->entries_n - 1);
557         volatile struct mlx5_err_cqe *cqe = (volatile struct mlx5_err_cqe *)
558                                                               &qp->cq.cqes[idx];
559         volatile struct mlx5_gga_wqe *wqes = (volatile struct mlx5_gga_wqe *)
560                                                                     qp->sq.wqes;
561         volatile struct mlx5_gga_compress_opaque *opaq = qp->opaque_mr.addr;
562
563         op->status = RTE_COMP_OP_STATUS_ERROR;
564         op->consumed = 0;
565         op->produced = 0;
566         op->output_chksum = 0;
567         op->debug_status = rte_be_to_cpu_32(opaq[idx].syndrom) |
568                               ((uint64_t)rte_be_to_cpu_32(cqe->syndrome) << 32);
569         mlx5_compress_dump_err_objs((volatile uint32_t *)cqe,
570                                  (volatile uint32_t *)&wqes[idx],
571                                  (volatile uint32_t *)&opaq[idx]);
572         qp->stats.dequeue_err_count++;
573 }
574
575 static uint16_t
576 mlx5_compress_dequeue_burst(void *queue_pair, struct rte_comp_op **ops,
577                             uint16_t nb_ops)
578 {
579         struct mlx5_compress_qp *qp = queue_pair;
580         volatile struct mlx5_compress_xform *restrict xform;
581         volatile struct mlx5_cqe *restrict cqe;
582         volatile struct mlx5_gga_compress_opaque *opaq = qp->opaque_mr.addr;
583         struct rte_comp_op *restrict op;
584         const unsigned int cq_size = qp->entries_n;
585         const unsigned int mask = cq_size - 1;
586         uint32_t idx;
587         uint32_t next_idx = qp->ci & mask;
588         const uint16_t max = RTE_MIN((uint16_t)(qp->pi - qp->ci), nb_ops);
589         uint16_t i = 0;
590         int ret;
591
592         if (unlikely(max == 0))
593                 return 0;
594         do {
595                 idx = next_idx;
596                 next_idx = (qp->ci + 1) & mask;
597                 rte_prefetch0(&qp->cq.cqes[next_idx]);
598                 rte_prefetch0(qp->ops[next_idx]);
599                 op = qp->ops[idx];
600                 cqe = &qp->cq.cqes[idx];
601                 ret = check_cqe(cqe, cq_size, qp->ci);
602                 /*
603                  * Be sure owner read is done before any other cookie field or
604                  * opaque field.
605                  */
606                 rte_io_rmb();
607                 if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) {
608                         if (likely(ret == MLX5_CQE_STATUS_HW_OWN))
609                                 break;
610                         mlx5_compress_cqe_err_handle(qp, op);
611                 } else {
612                         xform = op->private_xform;
613                         op->status = RTE_COMP_OP_STATUS_SUCCESS;
614                         op->consumed = op->src.length;
615                         op->produced = rte_be_to_cpu_32(cqe->byte_cnt);
616                         MLX5_ASSERT(cqe->byte_cnt ==
617                                     opaq[idx].scattered_length);
618                         switch (xform->csum_type) {
619                         case RTE_COMP_CHECKSUM_CRC32:
620                                 op->output_chksum = (uint64_t)rte_be_to_cpu_32
621                                                     (opaq[idx].crc32);
622                                 break;
623                         case RTE_COMP_CHECKSUM_ADLER32:
624                                 op->output_chksum = (uint64_t)rte_be_to_cpu_32
625                                             (opaq[idx].adler32) << 32;
626                                 break;
627                         case RTE_COMP_CHECKSUM_CRC32_ADLER32:
628                                 op->output_chksum = (uint64_t)rte_be_to_cpu_32
629                                                              (opaq[idx].crc32) |
630                                                      ((uint64_t)rte_be_to_cpu_32
631                                                      (opaq[idx].adler32) << 32);
632                                 break;
633                         default:
634                                 break;
635                         }
636                 }
637                 ops[i++] = op;
638                 qp->ci++;
639         } while (i < max);
640         if (likely(i != 0)) {
641                 rte_io_wmb();
642                 qp->cq.db_rec[0] = rte_cpu_to_be_32(qp->ci);
643                 qp->stats.dequeued_count += i;
644         }
645         return i;
646 }
647
648 static struct ibv_device *
649 mlx5_compress_get_ib_device_match(struct rte_pci_addr *addr)
650 {
651         int n;
652         struct ibv_device **ibv_list = mlx5_glue->get_device_list(&n);
653         struct ibv_device *ibv_match = NULL;
654
655         if (ibv_list == NULL) {
656                 rte_errno = ENOSYS;
657                 return NULL;
658         }
659         while (n-- > 0) {
660                 struct rte_pci_addr paddr;
661
662                 DRV_LOG(DEBUG, "Checking device \"%s\"..", ibv_list[n]->name);
663                 if (mlx5_dev_to_pci_addr(ibv_list[n]->ibdev_path, &paddr) != 0)
664                         continue;
665                 if (rte_pci_addr_cmp(addr, &paddr) != 0)
666                         continue;
667                 ibv_match = ibv_list[n];
668                 break;
669         }
670         if (ibv_match == NULL)
671                 rte_errno = ENOENT;
672         mlx5_glue->free_device_list(ibv_list);
673         return ibv_match;
674 }
675
676 static void
677 mlx5_compress_hw_global_release(struct mlx5_compress_priv *priv)
678 {
679         if (priv->pd != NULL) {
680                 claim_zero(mlx5_glue->dealloc_pd(priv->pd));
681                 priv->pd = NULL;
682         }
683         if (priv->uar != NULL) {
684                 mlx5_glue->devx_free_uar(priv->uar);
685                 priv->uar = NULL;
686         }
687 }
688
689 static int
690 mlx5_compress_pd_create(struct mlx5_compress_priv *priv)
691 {
692 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
693         struct mlx5dv_obj obj;
694         struct mlx5dv_pd pd_info;
695         int ret;
696
697         priv->pd = mlx5_glue->alloc_pd(priv->ctx);
698         if (priv->pd == NULL) {
699                 DRV_LOG(ERR, "Failed to allocate PD.");
700                 return errno ? -errno : -ENOMEM;
701         }
702         obj.pd.in = priv->pd;
703         obj.pd.out = &pd_info;
704         ret = mlx5_glue->dv_init_obj(&obj, MLX5DV_OBJ_PD);
705         if (ret != 0) {
706                 DRV_LOG(ERR, "Fail to get PD object info.");
707                 mlx5_glue->dealloc_pd(priv->pd);
708                 priv->pd = NULL;
709                 return -errno;
710         }
711         priv->pdn = pd_info.pdn;
712         return 0;
713 #else
714         (void)priv;
715         DRV_LOG(ERR, "Cannot get pdn - no DV support.");
716         return -ENOTSUP;
717 #endif /* HAVE_IBV_FLOW_DV_SUPPORT */
718 }
719
720 static int
721 mlx5_compress_hw_global_prepare(struct mlx5_compress_priv *priv)
722 {
723         if (mlx5_compress_pd_create(priv) != 0)
724                 return -1;
725         priv->uar = mlx5_devx_alloc_uar(priv->ctx, -1);
726         if (priv->uar == NULL || mlx5_os_get_devx_uar_reg_addr(priv->uar) ==
727             NULL) {
728                 rte_errno = errno;
729                 claim_zero(mlx5_glue->dealloc_pd(priv->pd));
730                 DRV_LOG(ERR, "Failed to allocate UAR.");
731                 return -1;
732         }
733         priv->uar_addr = mlx5_os_get_devx_uar_reg_addr(priv->uar);
734         MLX5_ASSERT(priv->uar_addr);
735 #ifndef RTE_ARCH_64
736         rte_spinlock_init(&priv->uar32_sl);
737 #endif /* RTE_ARCH_64 */
738         return 0;
739 }
740
741 /**
742  * DPDK callback to register a PCI device.
743  *
744  * This function spawns compress device out of a given PCI device.
745  *
746  * @param[in] pci_drv
747  *   PCI driver structure (mlx5_compress_driver).
748  * @param[in] pci_dev
749  *   PCI device information.
750  *
751  * @return
752  *   0 on success, 1 to skip this driver, a negative errno value otherwise
753  *   and rte_errno is set.
754  */
755 static int
756 mlx5_compress_pci_probe(struct rte_pci_driver *pci_drv,
757                         struct rte_pci_device *pci_dev)
758 {
759         struct ibv_device *ibv;
760         struct rte_compressdev *cdev;
761         struct ibv_context *ctx;
762         struct mlx5_compress_priv *priv;
763         struct mlx5_hca_attr att = { 0 };
764         struct rte_compressdev_pmd_init_params init_params = {
765                 .name = "",
766                 .socket_id = pci_dev->device.numa_node,
767         };
768
769         RTE_SET_USED(pci_drv);
770         if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
771                 DRV_LOG(ERR, "Non-primary process type is not supported.");
772                 rte_errno = ENOTSUP;
773                 return -rte_errno;
774         }
775         ibv = mlx5_compress_get_ib_device_match(&pci_dev->addr);
776         if (ibv == NULL) {
777                 DRV_LOG(ERR, "No matching IB device for PCI slot "
778                         PCI_PRI_FMT ".", pci_dev->addr.domain,
779                         pci_dev->addr.bus, pci_dev->addr.devid,
780                         pci_dev->addr.function);
781                 return -rte_errno;
782         }
783         DRV_LOG(INFO, "PCI information matches for device \"%s\".", ibv->name);
784         ctx = mlx5_glue->dv_open_device(ibv);
785         if (ctx == NULL) {
786                 DRV_LOG(ERR, "Failed to open IB device \"%s\".", ibv->name);
787                 rte_errno = ENODEV;
788                 return -rte_errno;
789         }
790         if (mlx5_devx_cmd_query_hca_attr(ctx, &att) != 0 ||
791             att.mmo_compress_en == 0 || att.mmo_decompress_en == 0 ||
792             att.mmo_dma_en == 0) {
793                 DRV_LOG(ERR, "Not enough capabilities to support compress "
794                         "operations, maybe old FW/OFED version?");
795                 claim_zero(mlx5_glue->close_device(ctx));
796                 rte_errno = ENOTSUP;
797                 return -ENOTSUP;
798         }
799         cdev = rte_compressdev_pmd_create(ibv->name, &pci_dev->device,
800                                           sizeof(*priv), &init_params);
801         if (cdev == NULL) {
802                 DRV_LOG(ERR, "Failed to create device \"%s\".", ibv->name);
803                 claim_zero(mlx5_glue->close_device(ctx));
804                 return -ENODEV;
805         }
806         DRV_LOG(INFO,
807                 "Compress device %s was created successfully.", ibv->name);
808         cdev->dev_ops = &mlx5_compress_ops;
809         cdev->dequeue_burst = mlx5_compress_dequeue_burst;
810         cdev->enqueue_burst = mlx5_compress_enqueue_burst;
811         cdev->feature_flags = RTE_COMPDEV_FF_HW_ACCELERATED;
812         priv = cdev->data->dev_private;
813         priv->ctx = ctx;
814         priv->pci_dev = pci_dev;
815         priv->cdev = cdev;
816         priv->min_block_size = att.compress_min_block_size;
817         if (mlx5_compress_hw_global_prepare(priv) != 0) {
818                 rte_compressdev_pmd_destroy(priv->cdev);
819                 claim_zero(mlx5_glue->close_device(priv->ctx));
820                 return -1;
821         }
822         if (mlx5_mr_btree_init(&priv->mr_scache.cache,
823                              MLX5_MR_BTREE_CACHE_N * 2, rte_socket_id()) != 0) {
824                 DRV_LOG(ERR, "Failed to allocate shared cache MR memory.");
825                 mlx5_compress_hw_global_release(priv);
826                 rte_compressdev_pmd_destroy(priv->cdev);
827                 claim_zero(mlx5_glue->close_device(priv->ctx));
828                 rte_errno = ENOMEM;
829                 return -rte_errno;
830         }
831         priv->mr_scache.reg_mr_cb = mlx5_common_verbs_reg_mr;
832         priv->mr_scache.dereg_mr_cb = mlx5_common_verbs_dereg_mr;
833         pthread_mutex_lock(&priv_list_lock);
834         TAILQ_INSERT_TAIL(&mlx5_compress_priv_list, priv, next);
835         pthread_mutex_unlock(&priv_list_lock);
836         return 0;
837 }
838
839 /**
840  * DPDK callback to remove a PCI device.
841  *
842  * This function removes all compress devices belong to a given PCI device.
843  *
844  * @param[in] pci_dev
845  *   Pointer to the PCI device.
846  *
847  * @return
848  *   0 on success, the function cannot fail.
849  */
850 static int
851 mlx5_compress_pci_remove(struct rte_pci_device *pdev)
852 {
853         struct mlx5_compress_priv *priv = NULL;
854
855         pthread_mutex_lock(&priv_list_lock);
856         TAILQ_FOREACH(priv, &mlx5_compress_priv_list, next)
857                 if (rte_pci_addr_cmp(&priv->pci_dev->addr, &pdev->addr) != 0)
858                         break;
859         if (priv)
860                 TAILQ_REMOVE(&mlx5_compress_priv_list, priv, next);
861         pthread_mutex_unlock(&priv_list_lock);
862         if (priv) {
863                 mlx5_mr_release_cache(&priv->mr_scache);
864                 mlx5_compress_hw_global_release(priv);
865                 rte_compressdev_pmd_destroy(priv->cdev);
866                 claim_zero(mlx5_glue->close_device(priv->ctx));
867         }
868         return 0;
869 }
870
871 static const struct rte_pci_id mlx5_compress_pci_id_map[] = {
872         {
873                 RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX,
874                                 PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF)
875         },
876         {
877                 .vendor_id = 0
878         }
879 };
880
881 static struct mlx5_pci_driver mlx5_compress_driver = {
882         .driver_class = MLX5_CLASS_COMPRESS,
883         .pci_driver = {
884                 .driver = {
885                         .name = RTE_STR(MLX5_COMPRESS_DRIVER_NAME),
886                 },
887                 .id_table = mlx5_compress_pci_id_map,
888                 .probe = mlx5_compress_pci_probe,
889                 .remove = mlx5_compress_pci_remove,
890                 .drv_flags = 0,
891         },
892 };
893
894 RTE_INIT(rte_mlx5_compress_init)
895 {
896         mlx5_common_init();
897         if (mlx5_glue != NULL)
898                 mlx5_pci_driver_register(&mlx5_compress_driver);
899 }
900
901 RTE_LOG_REGISTER(mlx5_compress_logtype, MLX5_COMPRESS_LOG_NAME, NOTICE)
902 RTE_PMD_EXPORT_NAME(MLX5_COMPRESS_DRIVER_NAME, __COUNTER__);
903 RTE_PMD_REGISTER_PCI_TABLE(MLX5_COMPRESS_DRIVER_NAME, mlx5_compress_pci_id_map);
904 RTE_PMD_REGISTER_KMOD_DEP(MLX5_COMPRESS_DRIVER_NAME, "* ib_uverbs & mlx5_core & mlx5_ib");