compress/isal: support burst enqueue/dequeue
[dpdk.git] / drivers / compress / isal / isal_compress_pmd.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4 #include <isa-l.h>
5
6 #include <rte_bus_vdev.h>
7 #include <rte_common.h>
8 #include <rte_malloc.h>
9 #include <rte_compressdev_pmd.h>
10
11 #include "isal_compress_pmd_private.h"
12
13 #define RTE_COMP_ISAL_WINDOW_SIZE 15
14 #define RTE_COMP_ISAL_LEVEL_ZERO 0 /* ISA-L Level 0 used for fixed Huffman */
15 #define RTE_COMP_ISAL_LEVEL_ONE 1
16 #define RTE_COMP_ISAL_LEVEL_TWO 2
17 #define RTE_COMP_ISAL_LEVEL_THREE 3 /* Optimised for AVX512 & AVX2 only */
18
19 int isal_logtype_driver;
20
21 /* Verify and set private xform parameters */
22 int
23 isal_comp_set_priv_xform_parameters(struct isal_priv_xform *priv_xform,
24                 const struct rte_comp_xform *xform)
25 {
26         if (xform == NULL)
27                 return -EINVAL;
28
29         /* Set compression private xform variables */
30         if (xform->type == RTE_COMP_COMPRESS) {
31                 /* Set private xform type - COMPRESS/DECOMPRESS */
32                 priv_xform->type = RTE_COMP_COMPRESS;
33
34                 /* Set private xform algorithm */
35                 if (xform->compress.algo != RTE_COMP_ALGO_DEFLATE) {
36                         if (xform->compress.algo == RTE_COMP_ALGO_NULL) {
37                                 ISAL_PMD_LOG(ERR, "By-pass not supported\n");
38                                 return -ENOTSUP;
39                         }
40                         ISAL_PMD_LOG(ERR, "Algorithm not supported\n");
41                         return -ENOTSUP;
42                 }
43                 priv_xform->compress.algo = RTE_COMP_ALGO_DEFLATE;
44
45                 /* Set private xform checksum - raw deflate by default */
46                 if (xform->compress.chksum != RTE_COMP_CHECKSUM_NONE) {
47                         ISAL_PMD_LOG(ERR, "Checksum not supported\n");
48                         return -ENOTSUP;
49                 }
50
51                 /* Set private xform window size, 32K supported */
52                 if (xform->compress.window_size == RTE_COMP_ISAL_WINDOW_SIZE)
53                         priv_xform->compress.window_size =
54                                         RTE_COMP_ISAL_WINDOW_SIZE;
55                 else {
56                         ISAL_PMD_LOG(ERR, "Window size not supported\n");
57                         return -ENOTSUP;
58                 }
59
60                 /* Set private xform huffman type */
61                 switch (xform->compress.deflate.huffman) {
62                 case(RTE_COMP_HUFFMAN_DEFAULT):
63                         priv_xform->compress.deflate.huffman =
64                                         RTE_COMP_HUFFMAN_DEFAULT;
65                         break;
66                 case(RTE_COMP_HUFFMAN_FIXED):
67                         priv_xform->compress.deflate.huffman =
68                                         RTE_COMP_HUFFMAN_FIXED;
69                         break;
70                 case(RTE_COMP_HUFFMAN_DYNAMIC):
71                         priv_xform->compress.deflate.huffman =
72                                         RTE_COMP_HUFFMAN_DYNAMIC;
73                         break;
74                 default:
75                         ISAL_PMD_LOG(ERR, "Huffman code not supported\n");
76                         return -ENOTSUP;
77                 }
78
79                 /* Set private xform level.
80                  * Checking compliance with compressdev API, -1 <= level => 9
81                  */
82                 if (xform->compress.level < RTE_COMP_LEVEL_PMD_DEFAULT ||
83                                 xform->compress.level > RTE_COMP_LEVEL_MAX) {
84                         ISAL_PMD_LOG(ERR, "Compression level out of range\n");
85                         return -EINVAL;
86                 }
87                 /* Check for Compressdev API level 0, No compression
88                  * not supported in ISA-L
89                  */
90                 else if (xform->compress.level == RTE_COMP_LEVEL_NONE) {
91                         ISAL_PMD_LOG(ERR, "No Compression not supported\n");
92                         return -ENOTSUP;
93                 }
94                 /* If using fixed huffman code, level must be 0 */
95                 else if (priv_xform->compress.deflate.huffman ==
96                                 RTE_COMP_HUFFMAN_FIXED) {
97                         ISAL_PMD_LOG(DEBUG, "ISA-L level 0 used due to a"
98                                         " fixed huffman code\n");
99                         priv_xform->compress.level = RTE_COMP_ISAL_LEVEL_ZERO;
100                         priv_xform->level_buffer_size =
101                                         ISAL_DEF_LVL0_DEFAULT;
102                 } else {
103                         /* Mapping API levels to ISA-L levels 1,2 & 3 */
104                         switch (xform->compress.level) {
105                         case RTE_COMP_LEVEL_PMD_DEFAULT:
106                                 /* Default is 1 if not using fixed huffman */
107                                 priv_xform->compress.level =
108                                                 RTE_COMP_ISAL_LEVEL_ONE;
109                                 priv_xform->level_buffer_size =
110                                                 ISAL_DEF_LVL1_DEFAULT;
111                                 break;
112                         case RTE_COMP_LEVEL_MIN:
113                                 priv_xform->compress.level =
114                                                 RTE_COMP_ISAL_LEVEL_ONE;
115                                 priv_xform->level_buffer_size =
116                                                 ISAL_DEF_LVL1_DEFAULT;
117                                 break;
118                         case RTE_COMP_ISAL_LEVEL_TWO:
119                                 priv_xform->compress.level =
120                                                 RTE_COMP_ISAL_LEVEL_TWO;
121                                 priv_xform->level_buffer_size =
122                                                 ISAL_DEF_LVL2_DEFAULT;
123                                 break;
124                         /* Level 3 or higher requested */
125                         default:
126                                 /* Check for AVX512, to use ISA-L level 3 */
127                                 if (rte_cpu_get_flag_enabled(
128                                                 RTE_CPUFLAG_AVX512F)) {
129                                         priv_xform->compress.level =
130                                                 RTE_COMP_ISAL_LEVEL_THREE;
131                                         priv_xform->level_buffer_size =
132                                                 ISAL_DEF_LVL3_DEFAULT;
133                                 }
134                                 /* Check for AVX2, to use ISA-L level 3 */
135                                 else if (rte_cpu_get_flag_enabled(
136                                                 RTE_CPUFLAG_AVX2)) {
137                                         priv_xform->compress.level =
138                                                 RTE_COMP_ISAL_LEVEL_THREE;
139                                         priv_xform->level_buffer_size =
140                                                 ISAL_DEF_LVL3_DEFAULT;
141                                 } else {
142                                         ISAL_PMD_LOG(DEBUG, "Requested ISA-L level"
143                                                 " 3 or above; Level 3 optimized"
144                                                 " for AVX512 & AVX2 only."
145                                                 " level changed to 2.\n");
146                                         priv_xform->compress.level =
147                                                 RTE_COMP_ISAL_LEVEL_TWO;
148                                         priv_xform->level_buffer_size =
149                                                 ISAL_DEF_LVL2_DEFAULT;
150                                 }
151                         }
152                 }
153         }
154
155         /* Set decompression private xform variables */
156         else if (xform->type == RTE_COMP_DECOMPRESS) {
157
158                 /* Set private xform type - COMPRESS/DECOMPRESS */
159                 priv_xform->type = RTE_COMP_DECOMPRESS;
160
161                 /* Set private xform algorithm */
162                 if (xform->decompress.algo != RTE_COMP_ALGO_DEFLATE) {
163                         if (xform->decompress.algo == RTE_COMP_ALGO_NULL) {
164                                 ISAL_PMD_LOG(ERR, "By pass not supported\n");
165                                 return -ENOTSUP;
166                         }
167                         ISAL_PMD_LOG(ERR, "Algorithm not supported\n");
168                         return -ENOTSUP;
169                 }
170                 priv_xform->decompress.algo = RTE_COMP_ALGO_DEFLATE;
171
172                 /* Set private xform checksum - raw deflate by default */
173                 if (xform->compress.chksum != RTE_COMP_CHECKSUM_NONE) {
174                         ISAL_PMD_LOG(ERR, "Checksum not supported\n");
175                         return -ENOTSUP;
176                 }
177
178                 /* Set private xform window size, 32K supported */
179                 if (xform->decompress.window_size == RTE_COMP_ISAL_WINDOW_SIZE)
180                         priv_xform->decompress.window_size =
181                                         RTE_COMP_ISAL_WINDOW_SIZE;
182                 else {
183                         ISAL_PMD_LOG(ERR, "Window size not supported\n");
184                         return -ENOTSUP;
185                 }
186         }
187         return 0;
188 }
189
190 /* Process compression/decompression operation */
191 static int
192 process_op(struct isal_comp_qp *qp __rte_unused,
193                 struct rte_comp_op *op __rte_unused,
194                 struct isal_priv_xform *priv_xform)
195 {
196         switch (priv_xform->type) {
197         case RTE_COMP_COMPRESS:
198                 break;
199         case RTE_COMP_DECOMPRESS:
200                 break;
201         default:
202                 ISAL_PMD_LOG(ERR, "Operation Not Supported\n");
203                 return -ENOTSUP;
204         }
205         return 0;
206 }
207
208 /* Enqueue burst */
209 static uint16_t
210 isal_comp_pmd_enqueue_burst(void *queue_pair, struct rte_comp_op **ops,
211                         uint16_t nb_ops)
212 {
213         struct isal_comp_qp *qp = queue_pair;
214         uint16_t i;
215         int retval;
216         int16_t num_enq = RTE_MIN(qp->num_free_elements, nb_ops);
217
218         for (i = 0; i < num_enq; i++) {
219                 if (unlikely(ops[i]->op_type != RTE_COMP_OP_STATELESS)) {
220                         ops[i]->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
221                         ISAL_PMD_LOG(ERR, "Stateful operation not Supported\n");
222                         qp->qp_stats.enqueue_err_count++;
223                         continue;
224                 }
225                 retval = process_op(qp, ops[i], ops[i]->private_xform);
226                 if (unlikely(retval < 0) ||
227                                 ops[i]->status != RTE_COMP_OP_STATUS_SUCCESS) {
228                         qp->qp_stats.enqueue_err_count++;
229                 }
230         }
231
232         retval = rte_ring_enqueue_burst(qp->processed_pkts, (void *)ops,
233                         num_enq, NULL);
234         qp->num_free_elements -= retval;
235         qp->qp_stats.enqueued_count += retval;
236
237         return retval;
238 }
239
240 /* Dequeue burst */
241 static uint16_t
242 isal_comp_pmd_dequeue_burst(void *queue_pair, struct rte_comp_op **ops,
243                 uint16_t nb_ops)
244 {
245         struct isal_comp_qp *qp = queue_pair;
246         uint16_t nb_dequeued;
247
248         nb_dequeued = rte_ring_dequeue_burst(qp->processed_pkts, (void **)ops,
249                         nb_ops, NULL);
250         qp->num_free_elements += nb_dequeued;
251         qp->qp_stats.dequeued_count += nb_dequeued;
252
253         return nb_dequeued;
254 }
255
256 /* Create ISA-L compression device */
257 static int
258 compdev_isal_create(const char *name, struct rte_vdev_device *vdev,
259                 struct rte_compressdev_pmd_init_params *init_params)
260 {
261         struct rte_compressdev *dev;
262
263         dev = rte_compressdev_pmd_create(name, &vdev->device,
264                         sizeof(struct isal_comp_private), init_params);
265         if (dev == NULL) {
266                 ISAL_PMD_LOG(ERR, "failed to create compressdev vdev");
267                 return -EFAULT;
268         }
269
270         dev->dev_ops = isal_compress_pmd_ops;
271
272         /* register rx/tx burst functions for data path */
273         dev->dequeue_burst = isal_comp_pmd_dequeue_burst;
274         dev->enqueue_burst = isal_comp_pmd_enqueue_burst;
275
276         return 0;
277 }
278
279 /** Remove compression device */
280 static int
281 compdev_isal_remove_dev(struct rte_vdev_device *vdev)
282 {
283         struct rte_compressdev *compdev;
284         const char *name;
285
286         name = rte_vdev_device_name(vdev);
287         if (name == NULL)
288                 return -EINVAL;
289
290         compdev = rte_compressdev_pmd_get_named_dev(name);
291         if (compdev == NULL)
292                 return -ENODEV;
293
294         return rte_compressdev_pmd_destroy(compdev);
295 }
296
297 /** Initialise ISA-L compression device */
298 static int
299 compdev_isal_probe(struct rte_vdev_device *dev)
300 {
301         struct rte_compressdev_pmd_init_params init_params = {
302                 "",
303                 rte_socket_id(),
304         };
305         const char *name, *args;
306         int retval;
307
308         name = rte_vdev_device_name(dev);
309         if (name == NULL)
310                 return -EINVAL;
311
312         args = rte_vdev_device_args(dev);
313
314         retval = rte_compressdev_pmd_parse_input_args(&init_params, args);
315         if (retval) {
316                 ISAL_PMD_LOG(ERR,
317                         "Failed to parse initialisation arguments[%s]\n", args);
318                 return -EINVAL;
319         }
320
321         return compdev_isal_create(name, dev, &init_params);
322 }
323
324 static struct rte_vdev_driver compdev_isal_pmd_drv = {
325         .probe = compdev_isal_probe,
326         .remove = compdev_isal_remove_dev,
327 };
328
329 RTE_PMD_REGISTER_VDEV(COMPDEV_NAME_ISAL_PMD, compdev_isal_pmd_drv);
330 RTE_PMD_REGISTER_PARAM_STRING(COMPDEV_NAME_ISAL_PMD,
331         "socket_id=<int>");
332
333 RTE_INIT(isal_init_log);
334
335 static void
336 isal_init_log(void)
337 {
338         isal_logtype_driver = rte_log_register("comp_isal");
339         if (isal_logtype_driver >= 0)
340                 rte_log_set_level(isal_logtype_driver, RTE_LOG_INFO);
341 }