xref: /dpdk/drivers/compress/nitrox/nitrox_comp_reqmgr.c (revision e99981af34632ecce3bac82d05db97b08308f9b5)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2024 Marvell.
3  */
4 
5 #include <rte_compressdev_pmd.h>
6 #include <rte_errno.h>
7 #include <rte_malloc.h>
8 #include <rte_hexdump.h>
9 
10 #include "nitrox_comp_reqmgr.h"
11 #include "nitrox_logs.h"
12 #include "rte_comp.h"
13 
14 #define NITROX_INSTR_BUFFER_DEBUG 0
15 #define NITROX_ZIP_SGL_COUNT 16
16 #define NITROX_ZIP_MAX_ZPTRS 2048
17 #define NITROX_ZIP_MAX_DATASIZE ((1 << 24) - 1)
18 #define NITROX_ZIP_MAX_ONFSIZE 1024
19 #define CMD_TIMEOUT 2
20 
21 union nitrox_zip_instr_word0 {
22 	uint64_t u64;
23 	struct {
24 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
25 		uint64_t raz0   :  8;
26 		uint64_t tol    : 24;
27 		uint64_t raz1   :  5;
28 		uint64_t exn    :  3;
29 		uint64_t raz2   :  1;
30 		uint64_t exbits :  7;
31 		uint64_t raz3   :  3;
32 		uint64_t ca     :  1;
33 		uint64_t sf     :  1;
34 		uint64_t ss     :  2;
35 		uint64_t cc     :  2;
36 		uint64_t ef     :  1;
37 		uint64_t bf     :  1;
38 		uint64_t co     :  1;
39 		uint64_t raz4   :  1;
40 		uint64_t ds     :  1;
41 		uint64_t dg     :  1;
42 		uint64_t hg     :  1;
43 #else
44 		uint64_t hg     :  1;
45 		uint64_t dg     :  1;
46 		uint64_t ds     :  1;
47 		uint64_t raz4   :  1;
48 		uint64_t co     :  1;
49 		uint64_t bf     :  1;
50 		uint64_t ef     :  1;
51 		uint64_t cc     :  2;
52 		uint64_t ss     :  2;
53 		uint64_t sf     :  1;
54 		uint64_t ca     :  1;
55 		uint64_t raz3   :  3;
56 		uint64_t exbits :  7;
57 		uint64_t raz2   :  1;
58 		uint64_t exn    :  3;
59 		uint64_t raz1   :  5;
60 		uint64_t tol    : 24;
61 		uint64_t raz0   :  8;
62 #endif
63 
64 	};
65 };
66 
67 union nitrox_zip_instr_word1 {
68 	uint64_t u64;
69 	struct {
70 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
71 		uint64_t hl             : 16;
72 		uint64_t raz0		: 16;
73 		uint64_t adlercrc32	: 32;
74 #else
75 		uint64_t adlercrc32     : 32;
76 		uint64_t raz0           : 16;
77 		uint64_t hl             : 16;
78 #endif
79 	};
80 };
81 
82 union nitrox_zip_instr_word2 {
83 	uint64_t u64;
84 	struct {
85 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
86 		uint64_t raz0   : 20;
87 		uint64_t cptr   : 44;
88 #else
89 		uint64_t cptr   : 44;
90 		uint64_t raz0   : 20;
91 #endif
92 	};
93 };
94 
95 union nitrox_zip_instr_word3 {
96 	uint64_t u64;
97 	struct {
98 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
99 		uint64_t raz0   :  4;
100 		uint64_t hlen   : 16;
101 		uint64_t hptr   : 44;
102 #else
103 		uint64_t hptr   : 44;
104 		uint64_t hlen   : 16;
105 		uint64_t raz0   :  4;
106 #endif
107 	};
108 };
109 
110 union nitrox_zip_instr_word4 {
111 	uint64_t u64;
112 	struct {
113 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
114 		uint64_t raz0   :  4;
115 		uint64_t ilen   : 16;
116 		uint64_t iptr   : 44;
117 #else
118 		uint64_t iptr   : 44;
119 		uint64_t ilen   : 16;
120 		uint64_t raz0   :  4;
121 #endif
122 	};
123 };
124 
125 union nitrox_zip_instr_word5 {
126 	uint64_t u64;
127 	struct {
128 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
129 		uint64_t raz0 :  4;
130 		uint64_t olen : 16;
131 		uint64_t optr : 44;
132 #else
133 		uint64_t optr : 44;
134 		uint64_t olen : 16;
135 		uint64_t raz0 :  4;
136 #endif
137 	};
138 };
139 
140 union nitrox_zip_instr_word6 {
141 	uint64_t u64;
142 	struct {
143 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
144 		uint64_t raz0   : 20;
145 		uint64_t rptr   : 44;
146 #else
147 		uint64_t rptr   : 44;
148 		uint64_t raz0   : 20;
149 #endif
150 	};
151 };
152 
153 union nitrox_zip_instr_word7 {
154 	uint64_t u64;
155 	struct {
156 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
157 		uint64_t grp    :  3;
158 		uint64_t raz0   : 41;
159 		uint64_t addr_msb: 20;
160 #else
161 		uint64_t addr_msb: 20;
162 		uint64_t raz0   : 41;
163 		uint64_t grp    :  3;
164 #endif
165 	};
166 };
167 
168 struct nitrox_zip_instr {
169 	union nitrox_zip_instr_word0 w0;
170 	union nitrox_zip_instr_word1 w1;
171 	union nitrox_zip_instr_word2 w2;
172 	union nitrox_zip_instr_word3 w3;
173 	union nitrox_zip_instr_word4 w4;
174 	union nitrox_zip_instr_word5 w5;
175 	union nitrox_zip_instr_word6 w6;
176 	union nitrox_zip_instr_word7 w7;
177 };
178 
179 union nitrox_zip_result_word0 {
180 	uint64_t u64;
181 	struct {
182 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
183 		uint64_t crc32  : 32;
184 		uint64_t adler32: 32;
185 #else
186 		uint64_t adler32: 32;
187 		uint64_t crc32  : 32;
188 #endif
189 	};
190 };
191 
192 union nitrox_zip_result_word1 {
193 	uint64_t u64;
194 	struct {
195 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
196 		uint64_t tbyteswritten  : 32;
197 		uint64_t tbytesread     : 32;
198 #else
199 		uint64_t tbytesread     : 32;
200 		uint64_t tbyteswritten  : 32;
201 #endif
202 	};
203 };
204 
205 union nitrox_zip_result_word2 {
206 	uint64_t u64;
207 	struct {
208 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
209 		uint64_t tbits  : 32;
210 		uint64_t raz0   :  5;
211 		uint64_t exn    :  3;
212 		uint64_t raz1   :  1;
213 		uint64_t exbits :  7;
214 		uint64_t raz2   :  7;
215 		uint64_t ef     :  1;
216 		uint64_t compcode:  8;
217 #else
218 		uint64_t compcode:  8;
219 		uint64_t ef     :  1;
220 		uint64_t raz2   :  7;
221 		uint64_t exbits :  7;
222 		uint64_t raz1   :  1;
223 		uint64_t exn    :  3;
224 		uint64_t raz0   :  5;
225 		uint64_t tbits  : 32;
226 #endif
227 	};
228 };
229 
230 struct nitrox_zip_result {
231 	union nitrox_zip_result_word0 w0;
232 	union nitrox_zip_result_word1 w1;
233 	union nitrox_zip_result_word2 w2;
234 };
235 
236 union nitrox_zip_zptr {
237 	uint64_t u64;
238 	struct {
239 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
240 		uint64_t raz0   :  3;
241 		uint64_t le     :  1;
242 		uint64_t length : 16;
243 		uint64_t addr   : 44;
244 #else
245 		uint64_t addr   : 44;
246 		uint64_t length : 16;
247 		uint64_t le     :  1;
248 		uint64_t raz0   :  3;
249 #endif
250 	} s;
251 };
252 
253 struct nitrox_zip_iova_addr {
254 	union {
255 		uint64_t u64;
256 		struct {
257 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
258 			uint64_t addr_msb: 20;
259 			uint64_t addr	: 44;
260 #else
261 			uint64_t addr	: 44;
262 			uint64_t addr_msb: 20;
263 #endif
264 		} zda;
265 
266 		struct {
267 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
268 			uint64_t addr_msb: 20;
269 			uint64_t addr	: 41;
270 			uint64_t align_8bytes: 3;
271 #else
272 			uint64_t align_8bytes: 3;
273 			uint64_t addr	: 41;
274 			uint64_t addr_msb: 20;
275 #endif
276 		} z8a;
277 	};
278 };
279 
280 enum nitrox_zip_comp_code {
281 	NITROX_CC_NOTDONE     = 0,
282 	NITROX_CC_SUCCESS     = 1,
283 	NITROX_CC_DTRUNC      = 2,
284 	NITROX_CC_STOP        = 3,
285 	NITROX_CC_ITRUNK      = 4,
286 	NITROX_CC_RBLOCK      = 5,
287 	NITROX_CC_NLEN        = 6,
288 	NITROX_CC_BADCODE     = 7,
289 	NITROX_CC_BADCODE2    = 8,
290 	NITROX_CC_ZERO_LEN    = 9,
291 	NITROX_CC_PARITY      = 10,
292 	NITROX_CC_FATAL       = 11,
293 	NITROX_CC_TIMEOUT     = 12,
294 	NITROX_CC_NPCI_ERR    = 13,
295 };
296 
297 struct nitrox_sgtable {
298 	union nitrox_zip_zptr *sgl;
299 	uint64_t addr_msb;
300 	uint32_t total_bytes;
301 	uint16_t nb_sgls;
302 	uint16_t filled_sgls;
303 };
304 
305 struct nitrox_softreq {
306 	struct nitrox_zip_instr instr;
307 	alignas(8) struct nitrox_zip_result zip_res;
308 	uint8_t decomp_threshold[NITROX_ZIP_MAX_ONFSIZE];
309 	struct rte_comp_op *op;
310 	struct nitrox_sgtable src;
311 	struct nitrox_sgtable dst;
312 	uint64_t timeout;
313 };
314 
315 #if NITROX_INSTR_BUFFER_DEBUG
316 static void nitrox_dump_databuf(const char *name, struct rte_mbuf *m,
317 				uint32_t off, uint32_t datalen)
318 {
319 	uint32_t mlen;
320 
321 	if (!rte_log_can_log(nitrox_logtype, RTE_LOG_DEBUG))
322 		return;
323 
324 	for (; m && off > rte_pktmbuf_data_len(m); m = m->next)
325 		off -= rte_pktmbuf_data_len(m);
326 
327 	mlen = rte_pktmbuf_data_len(m) - off;
328 	if (datalen <= mlen)
329 		mlen = datalen;
330 
331 	rte_hexdump(rte_log_get_stream(), name,
332 		    rte_pktmbuf_mtod_offset(m, char *, off), mlen);
333 	for (m = m->next; m && datalen; m = m->next) {
334 		mlen = rte_pktmbuf_data_len(m) < datalen ?
335 			rte_pktmbuf_data_len(m) : datalen;
336 		rte_hexdump(rte_log_get_stream(), name,
337 			    rte_pktmbuf_mtod(m, char *), mlen);
338 	}
339 
340 	NITROX_LOG_LINE(DEBUG,);
341 }
342 
343 static void nitrox_dump_zip_instr(struct nitrox_zip_instr *instr,
344 				  union nitrox_zip_zptr *hptr_arr,
345 				  union nitrox_zip_zptr *iptr_arr,
346 				  union nitrox_zip_zptr *optr_arr)
347 {
348 	uint64_t value;
349 	int i = 0;
350 
351 	NITROX_LOG_LINE(DEBUG, "\nZIP instruction..(%p)", instr);
352 	NITROX_LOG_LINE(DEBUG, "\tWORD0 = 0x%016"PRIx64, instr->w0.u64);
353 	NITROX_LOG_LINE(DEBUG, "\t\tTOL        = %d", instr->w0.tol);
354 	NITROX_LOG_LINE(DEBUG, "\t\tEXNUM      = %d", instr->w0.exn);
355 	NITROX_LOG_LINE(DEBUG, "\t\tEXBITS     = %x", instr->w0.exbits);
356 	NITROX_LOG_LINE(DEBUG, "\t\tCA         = %d", instr->w0.ca);
357 	NITROX_LOG_LINE(DEBUG, "\t\tSF         = %d", instr->w0.sf);
358 	NITROX_LOG_LINE(DEBUG, "\t\tSS         = %d", instr->w0.ss);
359 	NITROX_LOG_LINE(DEBUG, "\t\tCC         = %d", instr->w0.cc);
360 	NITROX_LOG_LINE(DEBUG, "\t\tEF         = %d", instr->w0.ef);
361 	NITROX_LOG_LINE(DEBUG, "\t\tBF         = %d", instr->w0.bf);
362 	NITROX_LOG_LINE(DEBUG, "\t\tCO         = %d", instr->w0.co);
363 	NITROX_LOG_LINE(DEBUG, "\t\tDS         = %d", instr->w0.ds);
364 	NITROX_LOG_LINE(DEBUG, "\t\tDG         = %d", instr->w0.dg);
365 	NITROX_LOG_LINE(DEBUG, "\t\tHG         = %d", instr->w0.hg);
366 	NITROX_LOG_LINE(DEBUG,);
367 
368 	NITROX_LOG_LINE(DEBUG, "\tWORD1 = 0x%016"PRIx64, instr->w1.u64);
369 	NITROX_LOG_LINE(DEBUG, "\t\tHL         = %d", instr->w1.hl);
370 	NITROX_LOG_LINE(DEBUG, "\t\tADLERCRC32 = 0x%08x", instr->w1.adlercrc32);
371 	NITROX_LOG_LINE(DEBUG,);
372 
373 	value = instr->w2.cptr;
374 	NITROX_LOG_LINE(DEBUG, "\tWORD2 = 0x%016"PRIx64, instr->w2.u64);
375 	NITROX_LOG_LINE(DEBUG, "\t\tCPTR = 0x%11"PRIx64, value);
376 	NITROX_LOG_LINE(DEBUG,);
377 
378 	value = instr->w3.hptr;
379 	NITROX_LOG_LINE(DEBUG, "\tWORD3 = 0x%016"PRIx64, instr->w3.u64);
380 	NITROX_LOG_LINE(DEBUG, "\t\tHLEN       = %d", instr->w3.hlen);
381 	NITROX_LOG_LINE(DEBUG, "\t\tHPTR = 0x%11"PRIx64, value);
382 
383 	if (instr->w0.hg && hptr_arr) {
384 		for (i = 0; i < instr->w3.hlen; i++) {
385 			value = hptr_arr[i].s.addr;
386 			NITROX_LOG_LINE(DEBUG, "\t\t\tZPTR[%d] : Length = %d Addr = 0x%11"PRIx64,
387 				     i, hptr_arr[i].s.length, value);
388 		}
389 	}
390 
391 	NITROX_LOG_LINE(DEBUG,);
392 
393 	value = instr->w4.iptr;
394 	NITROX_LOG_LINE(DEBUG, "\tWORD4 = 0x%016"PRIx64, instr->w4.u64);
395 	NITROX_LOG_LINE(DEBUG, "\t\tILEN       = %d", instr->w4.ilen);
396 	NITROX_LOG_LINE(DEBUG, "\t\tIPTR       = 0x%11"PRIx64, value);
397 	if (instr->w0.dg && iptr_arr) {
398 		for (i = 0; i < instr->w4.ilen; i++) {
399 			value = iptr_arr[i].s.addr;
400 			NITROX_LOG_LINE(DEBUG, "\t\t\tZPTR[%d] : Length = %d Addr = 0x%11"PRIx64,
401 				     i, iptr_arr[i].s.length, value);
402 		}
403 	}
404 
405 	NITROX_LOG_LINE(DEBUG,);
406 
407 	value = instr->w5.optr;
408 	NITROX_LOG_LINE(DEBUG, "\tWORD5 = 0x%016"PRIx64, instr->w5.u64);
409 	NITROX_LOG_LINE(DEBUG, "\t\t OLEN = %d", instr->w5.olen);
410 	NITROX_LOG_LINE(DEBUG, "\t\t OPTR = 0x%11"PRIx64, value);
411 	if (instr->w0.ds && optr_arr) {
412 		for (i = 0; i < instr->w5.olen; i++) {
413 			value = optr_arr[i].s.addr;
414 			NITROX_LOG_LINE(DEBUG, "\t\t\tZPTR[%d] : Length = %d Addr = 0x%11"PRIx64,
415 				     i, optr_arr[i].s.length, value);
416 		}
417 	}
418 
419 	NITROX_LOG_LINE(DEBUG,);
420 
421 	value = instr->w6.rptr;
422 	NITROX_LOG_LINE(DEBUG, "\tWORD6 = 0x%016"PRIx64, instr->w6.u64);
423 	NITROX_LOG_LINE(DEBUG, "\t\tRPTR = 0x%11"PRIx64, value);
424 	NITROX_LOG_LINE(DEBUG,);
425 
426 	NITROX_LOG_LINE(DEBUG, "\tWORD7 = 0x%016"PRIx64, instr->w7.u64);
427 	NITROX_LOG_LINE(DEBUG, "\t\tGRP        = %x", instr->w7.grp);
428 	NITROX_LOG_LINE(DEBUG, "\t\tADDR_MSB   = 0x%5x", instr->w7.addr_msb);
429 	NITROX_LOG_LINE(DEBUG,);
430 }
431 
432 static void nitrox_dump_zip_result(struct nitrox_zip_instr *instr,
433 				   struct nitrox_zip_result *result)
434 {
435 	NITROX_LOG_LINE(DEBUG, "ZIP result..(instr %p)", instr);
436 	NITROX_LOG_LINE(DEBUG, "\tWORD0 = 0x%016"PRIx64, result->w0.u64);
437 	NITROX_LOG_LINE(DEBUG, "\t\tCRC32          = 0x%8x", result->w0.crc32);
438 	NITROX_LOG_LINE(DEBUG, "\t\tADLER32        = 0x%8x", result->w0.adler32);
439 	NITROX_LOG_LINE(DEBUG,);
440 
441 	NITROX_LOG_LINE(DEBUG, "\tWORD1 = 0x%016"PRIx64, result->w1.u64);
442 	NITROX_LOG_LINE(DEBUG, "\t\tTBYTESWRITTEN  = %u", result->w1.tbyteswritten);
443 	NITROX_LOG_LINE(DEBUG, "\t\tTBYTESREAD     = %u", result->w1.tbytesread);
444 	NITROX_LOG_LINE(DEBUG,);
445 
446 	NITROX_LOG_LINE(DEBUG, "\tWORD2 = 0x%016"PRIx64, result->w2.u64);
447 	NITROX_LOG_LINE(DEBUG, "\t\tTBITS          = %u", result->w2.tbits);
448 	NITROX_LOG_LINE(DEBUG, "\t\tEXN            = %d", result->w2.exn);
449 	NITROX_LOG_LINE(DEBUG, "\t\tEBITS          = %x", result->w2.exbits);
450 	NITROX_LOG_LINE(DEBUG, "\t\tEF             = %d", result->w2.ef);
451 	NITROX_LOG_LINE(DEBUG, "\t\tCOMPCODE       = 0x%2x", result->w2.compcode);
452 	NITROX_LOG_LINE(DEBUG,);
453 }
454 #else
455 #define nitrox_dump_databuf(name, m, off, datalen)
456 #define nitrox_dump_zip_instr(instr, hptr_arr, iptr_arr, optr_arr)
457 #define nitrox_dump_zip_result(instr, result)
458 #endif
459 
460 static int handle_zero_length_compression(struct nitrox_softreq *sr,
461 					  struct nitrox_comp_xform *xform)
462 {
463 	union {
464 		uint32_t num;
465 		uint8_t bytes[4];
466 	} fblk;
467 	uint32_t dstlen, rlen;
468 	struct rte_mbuf *m;
469 	uint32_t off;
470 	uint32_t mlen;
471 	uint32_t i = 0;
472 	uint8_t *ptr;
473 
474 	fblk.num = xform->exn ? (xform->exbits & 0x7F) : 0;
475 	fblk.num |= (0x3 << xform->exn);
476 	memset(&sr->zip_res, 0, sizeof(sr->zip_res));
477 	sr->zip_res.w1.tbytesread = xform->hlen;
478 	sr->zip_res.w1.tbyteswritten = 2;
479 	sr->zip_res.w2.ef = 1;
480 	if (xform->exn == 7)
481 		sr->zip_res.w1.tbyteswritten++;
482 
483 	rlen = sr->zip_res.w1.tbyteswritten;
484 	dstlen = rte_pktmbuf_pkt_len(sr->op->m_dst) - sr->op->dst.offset;
485 	if (unlikely(dstlen < rlen))
486 		return -EIO;
487 
488 	off = sr->op->dst.offset;
489 	for (m = sr->op->m_dst; m && off > rte_pktmbuf_data_len(m); m = m->next)
490 		off -= rte_pktmbuf_data_len(m);
491 
492 	if (unlikely(!m))
493 		return -EIO;
494 
495 	mlen = rte_pktmbuf_data_len(m) - off;
496 	if (rlen <= mlen)
497 		mlen = rlen;
498 
499 	ptr = rte_pktmbuf_mtod_offset(m, uint8_t *, off);
500 	memcpy(ptr, fblk.bytes, mlen);
501 	i += mlen;
502 	rlen -= mlen;
503 	for (m = m->next; m && rlen; m = m->next) {
504 		mlen = rte_pktmbuf_data_len(m) < rlen ?
505 			rte_pktmbuf_data_len(m) : rlen;
506 		ptr = rte_pktmbuf_mtod(m, uint8_t *);
507 		memcpy(ptr, &fblk.bytes[i], mlen);
508 		i += mlen;
509 		rlen -= mlen;
510 	}
511 
512 	if (unlikely(rlen != 0))
513 		return -EIO;
514 
515 	sr->zip_res.w2.compcode = NITROX_CC_SUCCESS;
516 	sr->op->status = RTE_COMP_OP_STATUS_SUCCESS;
517 	sr->zip_res.w0.u64 = rte_cpu_to_be_64(sr->zip_res.w0.u64);
518 	sr->zip_res.w1.u64 = rte_cpu_to_be_64(sr->zip_res.w1.u64);
519 	sr->zip_res.w2.u64 = rte_cpu_to_be_64(sr->zip_res.w2.u64);
520 	return 0;
521 }
522 
523 static int create_sglist_from_mbuf(struct nitrox_sgtable *sgtbl,
524 				   struct rte_mbuf *mbuf, uint32_t off,
525 				   uint32_t datalen, uint8_t extra_segs,
526 				   int socket_id)
527 {
528 	struct rte_mbuf *m;
529 	union nitrox_zip_zptr *sgl;
530 	struct nitrox_zip_iova_addr zip_addr;
531 	uint16_t nb_segs;
532 	uint16_t i;
533 	uint32_t mlen;
534 
535 	if (unlikely(datalen > NITROX_ZIP_MAX_DATASIZE)) {
536 		NITROX_LOG_LINE(ERR, "Unsupported datalen %d, max supported %d",
537 			   datalen, NITROX_ZIP_MAX_DATASIZE);
538 		return -ENOTSUP;
539 	}
540 
541 	nb_segs = mbuf->nb_segs + extra_segs;
542 	for (m = mbuf; m && off > rte_pktmbuf_data_len(m); m = m->next) {
543 		off -= rte_pktmbuf_data_len(m);
544 		nb_segs--;
545 	}
546 
547 	if (unlikely(nb_segs > NITROX_ZIP_MAX_ZPTRS)) {
548 		NITROX_LOG_LINE(ERR, "Mbuf has more segments %d than supported",
549 			   nb_segs);
550 		return -ENOTSUP;
551 	}
552 
553 	if (unlikely(nb_segs > sgtbl->nb_sgls)) {
554 		union nitrox_zip_zptr *sgl;
555 
556 		NITROX_LOG_LINE(INFO, "Mbuf has more segs %d than allocated %d",
557 			   nb_segs, sgtbl->nb_sgls);
558 		sgl = rte_realloc_socket(sgtbl->sgl,
559 					 sizeof(*sgtbl->sgl) * nb_segs,
560 					 8, socket_id);
561 		if (unlikely(!sgl)) {
562 			NITROX_LOG_LINE(ERR, "Failed to expand sglist memory");
563 			return -ENOMEM;
564 		}
565 
566 		sgtbl->sgl = sgl;
567 		sgtbl->nb_sgls = nb_segs;
568 	}
569 
570 	sgtbl->filled_sgls = 0;
571 	sgtbl->total_bytes = 0;
572 	sgl = sgtbl->sgl;
573 	if (!m)
574 		return 0;
575 
576 	mlen = rte_pktmbuf_data_len(m) - off;
577 	if (datalen <= mlen)
578 		mlen = datalen;
579 
580 	i = 0;
581 	zip_addr.u64 = rte_pktmbuf_iova_offset(m, off);
582 	sgl[i].s.addr = zip_addr.zda.addr;
583 	sgl[i].s.length = mlen;
584 	sgl[i].s.le = 0;
585 	sgtbl->total_bytes += mlen;
586 	sgtbl->addr_msb = zip_addr.zda.addr_msb;
587 	datalen -= mlen;
588 	i++;
589 	for (m = m->next; m && datalen; m = m->next) {
590 		mlen = rte_pktmbuf_data_len(m) < datalen ?
591 			rte_pktmbuf_data_len(m) : datalen;
592 		zip_addr.u64 = rte_pktmbuf_iova(m);
593 		if (unlikely(zip_addr.zda.addr_msb != sgtbl->addr_msb)) {
594 			NITROX_LOG_LINE(ERR, "zip_ptrs have different msb addr");
595 			return -ENOTSUP;
596 		}
597 
598 		sgl[i].s.addr = zip_addr.zda.addr;
599 		sgl[i].s.length = mlen;
600 		sgl[i].s.le = 0;
601 		sgtbl->total_bytes += mlen;
602 		datalen -= mlen;
603 		i++;
604 	}
605 
606 	sgtbl->filled_sgls = i;
607 	return 0;
608 }
609 
610 static int softreq_init(struct nitrox_softreq *sr,
611 			struct nitrox_comp_xform *xform)
612 {
613 	struct rte_mempool *mp;
614 	int err;
615 	bool need_decomp_threshold;
616 
617 	mp = rte_mempool_from_obj(sr);
618 	if (unlikely(mp == NULL))
619 		return -EINVAL;
620 
621 	err = create_sglist_from_mbuf(&sr->src, sr->op->m_src,
622 				      sr->op->src.offset,
623 				      sr->op->src.length, 0, mp->socket_id);
624 	if (unlikely(err))
625 		return err;
626 
627 	need_decomp_threshold = (sr->op->op_type == RTE_COMP_OP_STATELESS &&
628 				 xform->op == NITROX_COMP_OP_DECOMPRESS);
629 	err = create_sglist_from_mbuf(&sr->dst, sr->op->m_dst,
630 			sr->op->dst.offset,
631 			rte_pktmbuf_pkt_len(sr->op->m_dst) - sr->op->dst.offset,
632 			need_decomp_threshold ? 1 : 0,
633 			mp->socket_id);
634 	if (unlikely(err))
635 		return err;
636 
637 	if (need_decomp_threshold) {
638 		struct nitrox_zip_iova_addr zip_addr;
639 		int i;
640 
641 		zip_addr.u64 = rte_mempool_virt2iova(sr) +
642 			offsetof(struct nitrox_softreq, decomp_threshold);
643 		i = sr->dst.filled_sgls;
644 		sr->dst.sgl[i].s.addr = zip_addr.zda.addr;
645 		sr->dst.sgl[i].s.length = NITROX_ZIP_MAX_ONFSIZE;
646 		sr->dst.sgl[i].s.le = 0;
647 		sr->dst.total_bytes += NITROX_ZIP_MAX_ONFSIZE;
648 		sr->dst.filled_sgls++;
649 	}
650 
651 	return 0;
652 }
653 
654 static void nitrox_zip_instr_to_b64(struct nitrox_softreq *sr)
655 {
656 	struct nitrox_zip_instr *instr = &sr->instr;
657 	int i;
658 
659 	for (i = 0; instr->w0.dg && (i < instr->w4.ilen); i++)
660 		sr->src.sgl[i].u64 = rte_cpu_to_be_64(sr->src.sgl[i].u64);
661 
662 	for (i = 0; instr->w0.ds && (i < instr->w5.olen); i++)
663 		sr->dst.sgl[i].u64 = rte_cpu_to_be_64(sr->dst.sgl[i].u64);
664 
665 	instr->w0.u64 = rte_cpu_to_be_64(instr->w0.u64);
666 	instr->w1.u64 = rte_cpu_to_be_64(instr->w1.u64);
667 	instr->w2.u64 = rte_cpu_to_be_64(instr->w2.u64);
668 	instr->w3.u64 = rte_cpu_to_be_64(instr->w3.u64);
669 	instr->w4.u64 = rte_cpu_to_be_64(instr->w4.u64);
670 	instr->w5.u64 = rte_cpu_to_be_64(instr->w5.u64);
671 	instr->w6.u64 = rte_cpu_to_be_64(instr->w6.u64);
672 	instr->w7.u64 = rte_cpu_to_be_64(instr->w7.u64);
673 }
674 
675 static int process_zip_request(struct nitrox_softreq *sr)
676 {
677 	struct nitrox_zip_instr *instr;
678 	struct nitrox_comp_xform *xform;
679 	struct nitrox_zip_iova_addr zip_addr;
680 	uint64_t iptr_msb, optr_msb, rptr_msb, cptr_msb, hptr_msb;
681 	int err;
682 
683 	xform = sr->op->private_xform;
684 	if (unlikely(xform == NULL)) {
685 		NITROX_LOG_LINE(ERR, "Invalid stateless comp op");
686 		return -EINVAL;
687 	}
688 
689 	if (unlikely(sr->op->op_type == RTE_COMP_OP_STATEFUL &&
690 		     xform->op == NITROX_COMP_OP_COMPRESS &&
691 		     sr->op->flush_flag == RTE_COMP_FLUSH_FINAL &&
692 		     sr->op->src.length == 0))
693 		return handle_zero_length_compression(sr, xform);
694 
695 	if (unlikely(sr->op->op_type == RTE_COMP_OP_STATELESS &&
696 		     xform->op == NITROX_COMP_OP_COMPRESS &&
697 		     sr->op->flush_flag != RTE_COMP_FLUSH_FULL &&
698 		     sr->op->flush_flag != RTE_COMP_FLUSH_FINAL)) {
699 		NITROX_LOG_LINE(ERR, "Invalid flush flag %d in stateless op",
700 			   sr->op->flush_flag);
701 		return -EINVAL;
702 	}
703 
704 	err = softreq_init(sr, xform);
705 	if (unlikely(err))
706 		return err;
707 
708 	instr = &sr->instr;
709 	memset(instr, 0, sizeof(*instr));
710 	/* word 0 */
711 	instr->w0.tol = sr->dst.total_bytes;
712 	instr->w0.exn = xform->exn;
713 	instr->w0.exbits = xform->exbits;
714 	instr->w0.ca = 0;
715 	if (xform->op == NITROX_COMP_OP_DECOMPRESS ||
716 	    sr->op->flush_flag == RTE_COMP_FLUSH_SYNC ||
717 	    sr->op->flush_flag == RTE_COMP_FLUSH_FULL)
718 		instr->w0.sf = 1;
719 	else
720 		instr->w0.sf = 0;
721 
722 	instr->w0.ss = xform->level;
723 	instr->w0.cc = xform->algo;
724 	if (sr->op->flush_flag == RTE_COMP_FLUSH_FINAL)
725 		instr->w0.ef = 1;
726 	else
727 		instr->w0.ef = 0;
728 
729 	instr->w0.bf = xform->bf;
730 	instr->w0.co = xform->op;
731 	if (sr->dst.filled_sgls > 1)
732 		instr->w0.ds = 1;
733 	else
734 		instr->w0.ds = 0;
735 
736 	if (sr->src.filled_sgls > 1)
737 		instr->w0.dg = 1;
738 	else
739 		instr->w0.dg = 0;
740 
741 	instr->w0.hg = 0;
742 
743 	/* word 1 */
744 	instr->w1.hl = xform->hlen;
745 	if (sr->op->op_type == RTE_COMP_OP_STATEFUL && !xform->bf)
746 		instr->w1.adlercrc32 = xform->chksum;
747 	else if (sr->op->op_type == RTE_COMP_OP_STATELESS &&
748 		 sr->op->input_chksum != 0)
749 		instr->w1.adlercrc32 = sr->op->input_chksum;
750 	else if (xform->chksum_type == NITROX_CHKSUM_TYPE_ADLER32)
751 		instr->w1.adlercrc32 = 1;
752 	else if (xform->chksum_type == NITROX_CHKSUM_TYPE_CRC32)
753 		instr->w1.adlercrc32 = 0;
754 
755 	/* word 2 */
756 	if (xform->context)
757 		zip_addr.u64 = rte_malloc_virt2iova(xform->context);
758 	else
759 		zip_addr.u64 = 0;
760 
761 	instr->w2.cptr = zip_addr.zda.addr;
762 	cptr_msb = zip_addr.zda.addr_msb;
763 
764 	/* word 3 */
765 	instr->w3.hlen = xform->hlen;
766 	if (xform->history_window)
767 		zip_addr.u64 = rte_malloc_virt2iova(xform->history_window);
768 	else
769 		zip_addr.u64 = 0;
770 
771 	instr->w3.hptr = zip_addr.zda.addr;
772 	hptr_msb = zip_addr.zda.addr_msb;
773 
774 	/* word 4 */
775 	if (sr->src.filled_sgls == 1) {
776 		instr->w4.ilen = sr->src.sgl[0].s.length;
777 		instr->w4.iptr = sr->src.sgl[0].s.addr;
778 		iptr_msb = sr->src.addr_msb;
779 	} else {
780 		zip_addr.u64 = rte_malloc_virt2iova(sr->src.sgl);
781 		instr->w4.ilen = sr->src.filled_sgls;
782 		instr->w4.iptr = zip_addr.zda.addr;
783 		iptr_msb = zip_addr.zda.addr_msb;
784 	}
785 
786 	/* word 5 */
787 	if (sr->dst.filled_sgls == 1) {
788 		instr->w5.olen = sr->dst.sgl[0].s.length;
789 		instr->w5.optr = sr->dst.sgl[0].s.addr;
790 		optr_msb = sr->dst.addr_msb;
791 	} else {
792 		zip_addr.u64 = rte_malloc_virt2iova(sr->dst.sgl);
793 		instr->w5.olen = sr->dst.filled_sgls;
794 		instr->w5.optr = zip_addr.zda.addr;
795 		optr_msb = zip_addr.zda.addr_msb;
796 	}
797 
798 	/* word 6 */
799 	memset(&sr->zip_res, 0, sizeof(sr->zip_res));
800 	zip_addr.u64 = rte_mempool_virt2iova(sr) +
801 		offsetof(struct nitrox_softreq, zip_res);
802 	instr->w6.rptr = zip_addr.zda.addr;
803 	rptr_msb = zip_addr.zda.addr_msb;
804 
805 	if (unlikely(iptr_msb != optr_msb || iptr_msb != rptr_msb ||
806 	    (xform->history_window && (iptr_msb != hptr_msb)) ||
807 	    (xform->context && (iptr_msb != cptr_msb)))) {
808 		NITROX_LOG_LINE(ERR, "addr_msb is not same for all addresses");
809 		return -ENOTSUP;
810 	}
811 
812 	/* word 7 */
813 	instr->w7.addr_msb = iptr_msb;
814 	instr->w7.grp = 0;
815 
816 	nitrox_dump_zip_instr(instr, NULL, sr->src.sgl, sr->dst.sgl);
817 	nitrox_dump_databuf("IN", sr->op->m_src, sr->op->src.offset,
818 			    sr->op->src.length);
819 	nitrox_zip_instr_to_b64(sr);
820 	return 0;
821 }
822 
823 int
824 nitrox_process_comp_req(struct rte_comp_op *op, struct nitrox_softreq *sr)
825 {
826 	int err;
827 
828 	sr->op = op;
829 	sr->op->status = RTE_COMP_OP_STATUS_NOT_PROCESSED;
830 	err = process_zip_request(sr);
831 	if (unlikely(err))
832 		goto err_exit;
833 
834 	sr->timeout = rte_get_timer_cycles() + CMD_TIMEOUT * rte_get_timer_hz();
835 	return 0;
836 err_exit:
837 	if (err == -ENOMEM)
838 		sr->op->status = RTE_COMP_OP_STATUS_ERROR;
839 	else
840 		sr->op->status = RTE_COMP_OP_STATUS_INVALID_ARGS;
841 
842 	return err;
843 }
844 
845 static struct nitrox_zip_result zip_result_to_cpu64(struct nitrox_zip_result *r)
846 {
847 	struct nitrox_zip_result out_res;
848 
849 	out_res.w2.u64 = rte_be_to_cpu_64(r->w2.u64);
850 	out_res.w1.u64 = rte_be_to_cpu_64(r->w1.u64);
851 	out_res.w0.u64 = rte_be_to_cpu_64(r->w0.u64);
852 	return out_res;
853 }
854 
855 static int post_process_zip_stateless(struct nitrox_softreq *sr,
856 				      struct nitrox_comp_xform *xform,
857 				      struct nitrox_zip_result *zip_res)
858 {
859 	int output_unused_bytes;
860 
861 	if (unlikely(zip_res->w2.compcode != NITROX_CC_SUCCESS)) {
862 		struct rte_comp_op *op = sr->op;
863 
864 		NITROX_LOG_LINE(ERR, "Dequeue error 0x%x",
865 			   zip_res->w2.compcode);
866 		if (zip_res->w2.compcode == NITROX_CC_STOP ||
867 		    zip_res->w2.compcode == NITROX_CC_DTRUNC)
868 			op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
869 		else
870 			op->status = RTE_COMP_OP_STATUS_ERROR;
871 
872 		op->consumed = 0;
873 		op->produced = 0;
874 		return -EFAULT;
875 	}
876 
877 	output_unused_bytes = sr->dst.total_bytes - zip_res->w1.tbyteswritten;
878 	if (unlikely(xform->op == NITROX_COMP_OP_DECOMPRESS &&
879 		     output_unused_bytes < NITROX_ZIP_MAX_ONFSIZE)) {
880 		NITROX_LOG_LINE(ERR, "TOL %d, Total bytes written %d",
881 			   sr->dst.total_bytes, zip_res->w1.tbyteswritten);
882 		sr->op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
883 		sr->op->consumed = 0;
884 		sr->op->produced = sr->dst.total_bytes - NITROX_ZIP_MAX_ONFSIZE;
885 		return -EIO;
886 	}
887 
888 	if (xform->chksum_type == NITROX_CHKSUM_TYPE_CRC32)
889 		sr->op->output_chksum = zip_res->w0.crc32;
890 	else if (xform->chksum_type == NITROX_CHKSUM_TYPE_ADLER32)
891 		sr->op->output_chksum = zip_res->w0.adler32;
892 
893 	sr->op->consumed = RTE_MIN(sr->op->src.length,
894 				   (uint32_t)zip_res->w1.tbytesread);
895 	sr->op->produced = zip_res->w1.tbyteswritten;
896 	sr->op->status = RTE_COMP_OP_STATUS_SUCCESS;
897 	return 0;
898 }
899 
900 static int update_history(struct rte_mbuf *mbuf, uint32_t off, uint16_t datalen,
901 			   uint8_t *dst)
902 {
903 	struct rte_mbuf *m;
904 	uint32_t mlen;
905 	uint16_t copied = 0;
906 
907 	for (m = mbuf; m && off > rte_pktmbuf_data_len(m); m = m->next)
908 		off -= rte_pktmbuf_data_len(m);
909 
910 	if (unlikely(!m)) {
911 		NITROX_LOG_LINE(ERR, "Failed to update history. Invalid mbuf");
912 		return -EINVAL;
913 	}
914 
915 	mlen = rte_pktmbuf_data_len(m) - off;
916 	if (datalen <= mlen)
917 		mlen = datalen;
918 
919 	memcpy(&dst[copied], rte_pktmbuf_mtod_offset(m, char *, off), mlen);
920 	copied += mlen;
921 	datalen -= mlen;
922 	for (m = m->next; m && datalen; m = m->next) {
923 		mlen = rte_pktmbuf_data_len(m) < datalen ?
924 			rte_pktmbuf_data_len(m) : datalen;
925 		memcpy(&dst[copied], rte_pktmbuf_mtod(m, char *), mlen);
926 		copied += mlen;
927 		datalen -= mlen;
928 	}
929 
930 	if (unlikely(datalen != 0)) {
931 		NITROX_LOG_LINE(ERR, "Failed to update history. Invalid datalen");
932 		return -EINVAL;
933 	}
934 
935 	return 0;
936 }
937 
938 static void reset_nitrox_xform(struct nitrox_comp_xform *xform)
939 {
940 	xform->hlen = 0;
941 	xform->exn = 0;
942 	xform->exbits = 0;
943 	xform->bf = true;
944 }
945 
946 static int post_process_zip_stateful(struct nitrox_softreq *sr,
947 				     struct nitrox_comp_xform *xform,
948 				     struct nitrox_zip_result *zip_res)
949 {
950 	uint32_t bytesread = 0;
951 	uint32_t chksum = 0;
952 
953 	if (unlikely(zip_res->w2.compcode == NITROX_CC_DTRUNC)) {
954 		sr->op->consumed = 0;
955 		sr->op->produced = 0;
956 		xform->hlen = 0;
957 		sr->op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE;
958 		NITROX_LOG_LINE(ERR, "Dequeue compress DTRUNC error");
959 		return 0;
960 	} else if (unlikely(zip_res->w2.compcode == NITROX_CC_STOP)) {
961 		sr->op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE;
962 		NITROX_LOG_LINE(NOTICE, "Dequeue decompress dynamic STOP");
963 	} else if (zip_res->w2.compcode == NITROX_CC_SUCCESS) {
964 		sr->op->status = RTE_COMP_OP_STATUS_SUCCESS;
965 	} else {
966 		xform->hlen = 0;
967 		xform->exn = 0;
968 		xform->exbits = 0;
969 		xform->bf = true;
970 		sr->op->status = RTE_COMP_OP_STATUS_ERROR;
971 		NITROX_LOG_LINE(ERR, "Dequeue error 0x%x",
972 			   zip_res->w2.compcode);
973 		return -EFAULT;
974 	}
975 
976 	if (xform->op == NITROX_COMP_OP_COMPRESS) {
977 		if (zip_res->w1.tbytesread < xform->hlen) {
978 			NITROX_LOG_LINE(ERR, "Invalid bytesread");
979 			reset_nitrox_xform(xform);
980 			sr->op->status = RTE_COMP_OP_STATUS_ERROR;
981 			return -EFAULT;
982 		}
983 
984 		bytesread = zip_res->w1.tbytesread - xform->hlen;
985 	} else {
986 		bytesread = RTE_MIN(sr->op->src.length,
987 				    (uint32_t)zip_res->w1.tbytesread);
988 	}
989 
990 	if ((xform->op == NITROX_COMP_OP_COMPRESS &&
991 	    (sr->op->flush_flag == RTE_COMP_FLUSH_NONE ||
992 	    sr->op->flush_flag == RTE_COMP_FLUSH_SYNC)) ||
993 	    (xform->op == NITROX_COMP_OP_DECOMPRESS && !zip_res->w2.ef)) {
994 		struct rte_mbuf *mbuf;
995 		uint32_t pktlen, m_off;
996 		int err;
997 
998 		if (xform->op == NITROX_COMP_OP_COMPRESS) {
999 			mbuf = sr->op->m_src;
1000 			pktlen = bytesread;
1001 			m_off = sr->op->src.offset;
1002 		} else {
1003 			mbuf = sr->op->m_dst;
1004 			pktlen = zip_res->w1.tbyteswritten;
1005 			m_off = sr->op->dst.offset;
1006 		}
1007 
1008 		if (pktlen >= xform->window_size) {
1009 			m_off += pktlen - xform->window_size;
1010 			err = update_history(mbuf, m_off, xform->window_size,
1011 				       xform->history_window);
1012 			xform->hlen = xform->window_size;
1013 		} else if ((xform->hlen + pktlen) <= xform->window_size) {
1014 			err = update_history(mbuf, m_off, pktlen,
1015 				       &xform->history_window[xform->hlen]);
1016 			xform->hlen += pktlen;
1017 		} else {
1018 			uint16_t shift_off, shift_len;
1019 
1020 			shift_off = pktlen + xform->hlen - xform->window_size;
1021 			shift_len = xform->hlen - shift_off;
1022 			memmove(xform->history_window,
1023 				&xform->history_window[shift_off],
1024 				shift_len);
1025 			err = update_history(mbuf, m_off, pktlen,
1026 				       &xform->history_window[shift_len]);
1027 			xform->hlen = xform->window_size;
1028 
1029 		}
1030 
1031 		if (unlikely(err)) {
1032 			sr->op->status = RTE_COMP_OP_STATUS_ERROR;
1033 			return err;
1034 		}
1035 
1036 		if (xform->op == NITROX_COMP_OP_COMPRESS) {
1037 			xform->exn = zip_res->w2.exn;
1038 			xform->exbits = zip_res->w2.exbits;
1039 		}
1040 
1041 		xform->bf = false;
1042 	} else {
1043 		reset_nitrox_xform(xform);
1044 	}
1045 
1046 	if (xform->chksum_type == NITROX_CHKSUM_TYPE_CRC32)
1047 		chksum = zip_res->w0.crc32;
1048 	else if (xform->chksum_type == NITROX_CHKSUM_TYPE_ADLER32)
1049 		chksum = zip_res->w0.adler32;
1050 
1051 	if (xform->bf)
1052 		sr->op->output_chksum = chksum;
1053 	else
1054 		xform->chksum = chksum;
1055 
1056 	sr->op->consumed = bytesread;
1057 	sr->op->produced = zip_res->w1.tbyteswritten;
1058 	return 0;
1059 }
1060 
1061 int
1062 nitrox_check_comp_req(struct nitrox_softreq *sr, struct rte_comp_op **op)
1063 {
1064 	struct nitrox_zip_result zip_res;
1065 	struct nitrox_comp_xform *xform;
1066 	int err = 0;
1067 
1068 	zip_res = zip_result_to_cpu64(&sr->zip_res);
1069 	if (zip_res.w2.compcode == NITROX_CC_NOTDONE) {
1070 		if (rte_get_timer_cycles() >= sr->timeout) {
1071 			NITROX_LOG_LINE(ERR, "Op timedout");
1072 			sr->op->status = RTE_COMP_OP_STATUS_ERROR;
1073 			err = -ETIMEDOUT;
1074 			goto exit;
1075 		} else {
1076 			return -EAGAIN;
1077 		}
1078 	}
1079 
1080 	xform = sr->op->private_xform;
1081 	if (sr->op->op_type == RTE_COMP_OP_STATELESS)
1082 		err = post_process_zip_stateless(sr, xform, &zip_res);
1083 	else
1084 		err = post_process_zip_stateful(sr, xform, &zip_res);
1085 
1086 	if (sr->op->status == RTE_COMP_OP_STATUS_SUCCESS &&
1087 	    xform->op == NITROX_COMP_OP_COMPRESS &&
1088 	    sr->op->flush_flag == RTE_COMP_FLUSH_FINAL &&
1089 	    zip_res.w2.exn) {
1090 		uint32_t datalen = zip_res.w1.tbyteswritten;
1091 		uint32_t off = sr->op->dst.offset;
1092 		struct rte_mbuf *m = sr->op->m_dst;
1093 		uint32_t mlen;
1094 		uint8_t *last_byte;
1095 
1096 		for (; m && off > rte_pktmbuf_data_len(m); m = m->next)
1097 			off -= rte_pktmbuf_data_len(m);
1098 
1099 		if (unlikely(m == NULL)) {
1100 			err = -EINVAL;
1101 			goto exit;
1102 		}
1103 
1104 		mlen = rte_pktmbuf_data_len(m) - off;
1105 		for (; m && (datalen > mlen); m = m->next)
1106 			datalen -= mlen;
1107 
1108 		if (unlikely(m == NULL)) {
1109 			err = -EINVAL;
1110 			goto exit;
1111 		}
1112 
1113 		last_byte = rte_pktmbuf_mtod_offset(m, uint8_t *, datalen - 1);
1114 		*last_byte = zip_res.w2.exbits & 0xFF;
1115 	}
1116 
1117 exit:
1118 	*op = sr->op;
1119 	nitrox_dump_zip_result(&sr->instr, &zip_res);
1120 	nitrox_dump_databuf("OUT after", sr->op->m_dst, sr->op->dst.offset,
1121 		sr->op->produced);
1122 	return err;
1123 }
1124 
1125 void *
1126 nitrox_comp_instr_addr(struct nitrox_softreq *sr)
1127 {
1128 	return &sr->instr;
1129 }
1130 
1131 static void req_pool_obj_free(struct rte_mempool *mp, void *opaque, void *obj,
1132 			      unsigned int obj_idx)
1133 {
1134 	struct nitrox_softreq *sr;
1135 
1136 	RTE_SET_USED(mp);
1137 	RTE_SET_USED(opaque);
1138 	RTE_SET_USED(obj_idx);
1139 	sr = obj;
1140 	rte_free(sr->src.sgl);
1141 	sr->src.sgl = NULL;
1142 	rte_free(sr->dst.sgl);
1143 	sr->dst.sgl = NULL;
1144 }
1145 
1146 void
1147 nitrox_comp_req_pool_free(struct rte_mempool *mp)
1148 {
1149 	rte_mempool_obj_iter(mp, req_pool_obj_free, NULL);
1150 	rte_mempool_free(mp);
1151 }
1152 
1153 static void req_pool_obj_init(struct rte_mempool *mp, void *arg, void *obj,
1154 			      unsigned int obj_idx)
1155 {
1156 	struct nitrox_softreq *sr;
1157 	int *err = arg;
1158 
1159 	RTE_SET_USED(mp);
1160 	RTE_SET_USED(obj_idx);
1161 	sr = obj;
1162 	sr->src.sgl = rte_zmalloc_socket(NULL,
1163 				sizeof(*sr->src.sgl) * NITROX_ZIP_SGL_COUNT,
1164 				8, mp->socket_id);
1165 	sr->dst.sgl = rte_zmalloc_socket(NULL,
1166 				sizeof(*sr->dst.sgl) * NITROX_ZIP_SGL_COUNT,
1167 				8, mp->socket_id);
1168 	if (sr->src.sgl == NULL || sr->dst.sgl == NULL) {
1169 		NITROX_LOG_LINE(ERR, "Failed to allocate zip_sgl memory");
1170 		*err = -ENOMEM;
1171 	}
1172 
1173 	sr->src.nb_sgls = NITROX_ZIP_SGL_COUNT;
1174 	sr->src.filled_sgls = 0;
1175 	sr->dst.nb_sgls = NITROX_ZIP_SGL_COUNT;
1176 	sr->dst.filled_sgls = 0;
1177 }
1178 
1179 struct rte_mempool *
1180 nitrox_comp_req_pool_create(struct rte_compressdev *dev, uint32_t nobjs,
1181 			   uint16_t qp_id, int socket_id)
1182 {
1183 	char softreq_pool_name[RTE_RING_NAMESIZE];
1184 	struct rte_mempool *mp;
1185 	int err = 0;
1186 
1187 	snprintf(softreq_pool_name, RTE_RING_NAMESIZE, "%s_sr_%d",
1188 		 dev->data->name, qp_id);
1189 	mp = rte_mempool_create(softreq_pool_name,
1190 				RTE_ALIGN_MUL_CEIL(nobjs, 64),
1191 				sizeof(struct nitrox_softreq),
1192 				64, 0, NULL, NULL, req_pool_obj_init, &err,
1193 				socket_id, 0);
1194 	if (unlikely(!mp))
1195 		NITROX_LOG_LINE(ERR, "Failed to create req pool, qid %d, err %d",
1196 			   qp_id, rte_errno);
1197 
1198 	if (unlikely(err)) {
1199 		nitrox_comp_req_pool_free(mp);
1200 		return NULL;
1201 	}
1202 
1203 	return mp;
1204 }
1205