xref: /freebsd/sys/dev/qat/qat_api/common/compression/dc_datapath.c (revision 25b18d8935a5ee933d5465f5db41ad58c26590f9)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 /**
5  *****************************************************************************
6  * @file dc_datapath.c
7  *
8  * @defgroup Dc_DataCompression DC Data Compression
9  *
10  * @ingroup Dc_DataCompression
11  *
12  * @description
13  *      Implementation of the Data Compression datapath operations.
14  *
15  *****************************************************************************/
16 
17 /*
18 *******************************************************************************
19 * Include public/global header files
20 *******************************************************************************
21 */
22 #include "cpa.h"
23 #include "cpa_dc.h"
24 #include "cpa_dc_dp.h"
25 
26 /*
27 *******************************************************************************
28 * Include private header files
29 *******************************************************************************
30 */
31 #include "dc_session.h"
32 #include "dc_datapath.h"
33 #include "sal_statistics.h"
34 #include "lac_common.h"
35 #include "lac_mem.h"
36 #include "lac_mem_pools.h"
37 #include "sal_types_compression.h"
38 #include "dc_stats.h"
39 #include "lac_buffer_desc.h"
40 #include "lac_sal.h"
41 #include "lac_log.h"
42 #include "lac_sync.h"
43 #include "sal_service_state.h"
44 #include "sal_qat_cmn_msg.h"
45 #include "sal_hw_gen.h"
46 #include "dc_error_counter.h"
47 #define DC_COMP_MAX_BUFF_SIZE (1024 * 64)
48 
49 static QatUtilsAtomic dcErrorCount[MAX_DC_ERROR_TYPE];
50 
51 void
52 dcErrorLog(CpaDcReqStatus dcError)
53 {
54 	Cpa32U absError = 0;
55 
56 	absError = abs(dcError);
57 	if ((dcError < CPA_DC_OK) && (absError < MAX_DC_ERROR_TYPE)) {
58 		qatUtilsAtomicInc(&(dcErrorCount[absError]));
59 	}
60 }
61 
62 Cpa64U
63 getDcErrorCounter(CpaDcReqStatus dcError)
64 {
65 	Cpa32U absError = 0;
66 
67 	absError = abs(dcError);
68 	if (!(dcError >= CPA_DC_OK || dcError < CPA_DC_EMPTY_DYM_BLK)) {
69 		return (Cpa64U)qatUtilsAtomicGet(&dcErrorCount[absError]);
70 	}
71 
72 	return 0;
73 }
74 
75 static inline void
76 dcUpdateXltOverflowChecksumsGen4(const dc_compression_cookie_t *pCookie,
77 				 const icp_qat_fw_resp_comp_pars_t *pRespPars,
78 				 CpaDcRqResults *pDcResults)
79 {
80 	dc_session_desc_t *pSessionDesc =
81 	    DC_SESSION_DESC_FROM_CTX_GET(pCookie->pSessionHandle);
82 
83 	/* Recompute CRC checksum when either the checksum type
84 	 * is CPA_DC_CRC32 or when the integrity CRCs are enabled.
85 	 */
86 	if (CPA_DC_CRC32 == pSessionDesc->checksumType) {
87 		pDcResults->checksum = pRespPars->crc.legacy.curr_crc32;
88 
89 		/* No need to recalculate the swCrc64I here as this will get
90 		 * handled later in dcHandleIntegrityChecksumsGen4.
91 		 */
92 	} else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
93 		pDcResults->checksum = pRespPars->crc.legacy.curr_adler_32;
94 	}
95 }
96 
97 void
98 dcCompression_ProcessCallback(void *pRespMsg)
99 {
100 	CpaStatus status = CPA_STATUS_SUCCESS;
101 	icp_qat_fw_comp_resp_t *pCompRespMsg = NULL;
102 	void *callbackTag = NULL;
103 	Cpa64U *pReqData = NULL;
104 	CpaDcDpOpData *pResponse = NULL;
105 	CpaDcRqResults *pResults = NULL;
106 	CpaDcCallbackFn pCbFunc = NULL;
107 	dc_session_desc_t *pSessionDesc = NULL;
108 	sal_compression_service_t *pService = NULL;
109 	dc_compression_cookie_t *pCookie = NULL;
110 	CpaDcOpData *pOpData = NULL;
111 	CpaBoolean cmpPass = CPA_TRUE, xlatPass = CPA_TRUE;
112 	CpaBoolean isDcDp = CPA_FALSE;
113 	CpaBoolean integrityCrcCheck = CPA_FALSE;
114 	CpaBoolean verifyHwIntegrityCrcs = CPA_FALSE;
115 	Cpa8U cmpErr = ERR_CODE_NO_ERROR, xlatErr = ERR_CODE_NO_ERROR;
116 	dc_request_dir_t compDecomp = DC_COMPRESSION_REQUEST;
117 	Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK;
118 	Cpa8U hdrFlags = 0;
119 
120 	/* Cast response message to compression response message type */
121 	pCompRespMsg = (icp_qat_fw_comp_resp_t *)pRespMsg;
122 
123 	/* Extract request data pointer from the opaque data */
124 	LAC_MEM_SHARED_READ_TO_PTR(pCompRespMsg->opaque_data, pReqData);
125 
126 	/* Extract fields from the request data structure */
127 	pCookie = (dc_compression_cookie_t *)pReqData;
128 	if (!pCookie)
129 		return;
130 
131 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pCookie->pSessionHandle);
132 	pService = (sal_compression_service_t *)(pCookie->dcInstance);
133 
134 	isDcDp = pSessionDesc->isDcDp;
135 	if (CPA_TRUE == isDcDp) {
136 		pResponse = (CpaDcDpOpData *)pReqData;
137 		pResults = &(pResponse->results);
138 
139 		if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) {
140 			compDecomp = DC_DECOMPRESSION_REQUEST;
141 		}
142 		pCookie = NULL;
143 	} else {
144 		pResults = pCookie->pResults;
145 		callbackTag = pCookie->callbackTag;
146 		pCbFunc = pCookie->pSessionDesc->pCompressionCb;
147 		compDecomp = pCookie->compDecomp;
148 		pOpData = pCookie->pDcOpData;
149 	}
150 
151 	opStatus = pCompRespMsg->comn_resp.comn_status;
152 
153 	if (NULL != pOpData) {
154 		verifyHwIntegrityCrcs = pOpData->verifyHwIntegrityCrcs;
155 	}
156 
157 	hdrFlags = pCompRespMsg->comn_resp.hdr_flags;
158 
159 	/* Get the cmp error code */
160 	cmpErr = pCompRespMsg->comn_resp.comn_error.s1.cmp_err_code;
161 	if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(opStatus)) {
162 		/* Compression not supported by firmware, set produced/consumed
163 		   to zero
164 		   and call the cb function with status CPA_STATUS_UNSUPPORTED
165 		   */
166 		QAT_UTILS_LOG("Compression feature not supported\n");
167 		status = CPA_STATUS_UNSUPPORTED;
168 		pResults->status = (Cpa8S)cmpErr;
169 		pResults->consumed = 0;
170 		pResults->produced = 0;
171 		if (CPA_TRUE == isDcDp) {
172 			if (pResponse)
173 				pResponse->responseStatus =
174 				    CPA_STATUS_UNSUPPORTED;
175 			(pService->pDcDpCb)(pResponse);
176 		} else {
177 			/* Free the memory pool */
178 			if (NULL != pCookie) {
179 				Lac_MemPoolEntryFree(pCookie);
180 				pCookie = NULL;
181 			}
182 			if (NULL != pCbFunc) {
183 				pCbFunc(callbackTag, status);
184 			}
185 		}
186 		if (DC_COMPRESSION_REQUEST == compDecomp) {
187 			COMPRESSION_STAT_INC(numCompCompletedErrors, pService);
188 		} else {
189 			COMPRESSION_STAT_INC(numDecompCompletedErrors,
190 					     pService);
191 		}
192 		return;
193 	} else {
194 		/* Check compression response status */
195 		cmpPass =
196 		    (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK ==
197 				 ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(opStatus));
198 	}
199 
200 	if (isDcGen2x(pService)) {
201 		/* QAT1.7 and QAT 1.8 hardware */
202 		if (CPA_DC_INCOMPLETE_FILE_ERR == (Cpa8S)cmpErr) {
203 			cmpPass = CPA_TRUE;
204 			cmpErr = ERR_CODE_NO_ERROR;
205 		}
206 	} else {
207 		/* QAT2.0 hardware cancels the incomplete file errors
208 		 * only for DEFLATE algorithm.
209 		 * Decompression direction is not tested in the callback as
210 		 * the request does not allow it.
211 		 */
212 		if ((pSessionDesc->compType == CPA_DC_DEFLATE) &&
213 		    (CPA_DC_INCOMPLETE_FILE_ERR == (Cpa8S)cmpErr)) {
214 			cmpPass = CPA_TRUE;
215 			cmpErr = ERR_CODE_NO_ERROR;
216 		}
217 	}
218 	/* log the slice hang and endpoint push/pull error inside the response
219 	 */
220 	if (ERR_CODE_SSM_ERROR == (Cpa8S)cmpErr) {
221 		QAT_UTILS_LOG(
222 		    "Slice hang detected on the compression slice.\n");
223 	} else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)cmpErr) {
224 		QAT_UTILS_LOG(
225 		    "PCIe End Point Push/Pull or TI/RI Parity error detected.\n");
226 	}
227 
228 	/* We return the compression error code for now. We would need to update
229 	 * the API if we decide to return both error codes */
230 	pResults->status = (Cpa8S)cmpErr;
231 
232 	/* Check the translator status */
233 	if ((DC_COMPRESSION_REQUEST == compDecomp) &&
234 	    (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) {
235 		/* Check translator response status */
236 		xlatPass =
237 		    (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK ==
238 				 ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(opStatus));
239 
240 		/* Get the translator error code */
241 		xlatErr = pCompRespMsg->comn_resp.comn_error.s1.xlat_err_code;
242 
243 		/* Return a fatal error or a potential error in the translator
244 		 * slice if the compression slice did not return any error */
245 		if ((CPA_DC_OK == pResults->status) ||
246 		    (CPA_DC_FATALERR == (Cpa8S)xlatErr)) {
247 			pResults->status = (Cpa8S)xlatErr;
248 		}
249 	}
250 	/* Update dc error counter */
251 	dcErrorLog(pResults->status);
252 
253 	if (CPA_FALSE == isDcDp) {
254 		/* In case of any error for an end of packet request, we need to
255 		 * update
256 		 * the request type for the following request */
257 		if (CPA_DC_FLUSH_FINAL == pCookie->flushFlag && cmpPass &&
258 		    xlatPass) {
259 			pSessionDesc->requestType = DC_REQUEST_FIRST;
260 		} else {
261 			pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT;
262 		}
263 		if ((CPA_DC_STATEFUL == pSessionDesc->sessState) ||
264 		    ((CPA_DC_STATELESS == pSessionDesc->sessState) &&
265 		     (DC_COMPRESSION_REQUEST == compDecomp))) {
266 			/* Overflow is a valid use case for Traditional API
267 			 * only. Stateful Overflow is supported in both
268 			 * compression and decompression direction. Stateless
269 			 * Overflow is supported only in compression direction.
270 			 */
271 			if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr)
272 				cmpPass = CPA_TRUE;
273 
274 			if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) {
275 				if (isDcGen4x(pService) &&
276 				    (CPA_TRUE ==
277 				     pService->comp_device_data
278 					 .translatorOverflow)) {
279 					pResults->consumed =
280 					    pCompRespMsg->comp_resp_pars
281 						.input_byte_counter;
282 
283 					dcUpdateXltOverflowChecksumsGen4(
284 					    pCookie,
285 					    &pCompRespMsg->comp_resp_pars,
286 					    pResults);
287 				}
288 				xlatPass = CPA_TRUE;
289 			}
290 		}
291 	} else {
292 		if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr) {
293 			cmpPass = CPA_FALSE;
294 		}
295 		if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) {
296 			/* XLT overflow is not valid for Data Plane requests */
297 			xlatPass = CPA_FALSE;
298 		}
299 	}
300 
301 	if ((CPA_TRUE == cmpPass) && (CPA_TRUE == xlatPass)) {
302 		/* Extract the response from the firmware */
303 		pResults->consumed =
304 		    pCompRespMsg->comp_resp_pars.input_byte_counter;
305 		pResults->produced =
306 		    pCompRespMsg->comp_resp_pars.output_byte_counter;
307 		pSessionDesc->cumulativeConsumedBytes += pResults->consumed;
308 
309 		/* Handle Checksum for end to end data integrity. */
310 		if (CPA_TRUE ==
311 			pService->generic_service_info.integrityCrcCheck &&
312 		    CPA_TRUE == integrityCrcCheck) {
313 			pSessionDesc->previousChecksum =
314 			    pSessionDesc->seedSwCrc.swCrc32I;
315 		} else if (CPA_DC_OVERFLOW != (Cpa8S)xlatErr) {
316 			if (CPA_DC_CRC32 == pSessionDesc->checksumType) {
317 				pResults->checksum =
318 				    pCompRespMsg->comp_resp_pars.crc.legacy
319 					.curr_crc32;
320 			} else if (CPA_DC_ADLER32 ==
321 				   pSessionDesc->checksumType) {
322 				pResults->checksum =
323 				    pCompRespMsg->comp_resp_pars.crc.legacy
324 					.curr_adler_32;
325 			}
326 			pSessionDesc->previousChecksum = pResults->checksum;
327 		}
328 
329 		if (DC_DECOMPRESSION_REQUEST == compDecomp) {
330 			pResults->endOfLastBlock =
331 			    (ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET ==
332 			     ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET(
333 				 opStatus));
334 		}
335 
336 		/* Save the checksum for the next request */
337 		if ((CPA_DC_OVERFLOW != (Cpa8S)xlatErr) &&
338 		    (CPA_TRUE == verifyHwIntegrityCrcs)) {
339 			pSessionDesc->previousChecksum =
340 			    pSessionDesc->seedSwCrc.swCrc32I;
341 		}
342 
343 		/* Check if a CNV recovery happened and
344 		 * increase stats counter
345 		 */
346 		if ((DC_COMPRESSION_REQUEST == compDecomp) &&
347 		    ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(hdrFlags) &&
348 		    ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_GET(hdrFlags)) {
349 			COMPRESSION_STAT_INC(numCompCnvErrorsRecovered,
350 					     pService);
351 		}
352 
353 		if (CPA_TRUE == isDcDp) {
354 			if (pResponse)
355 				pResponse->responseStatus = CPA_STATUS_SUCCESS;
356 		} else {
357 			if (DC_COMPRESSION_REQUEST == compDecomp) {
358 				COMPRESSION_STAT_INC(numCompCompleted,
359 						     pService);
360 			} else {
361 				COMPRESSION_STAT_INC(numDecompCompleted,
362 						     pService);
363 			}
364 		}
365 	} else {
366 #ifdef ICP_DC_RETURN_COUNTERS_ON_ERROR
367 		/* Extract the response from the firmware */
368 		pResults->consumed =
369 		    pCompRespMsg->comp_resp_pars.input_byte_counter;
370 		pResults->produced =
371 		    pCompRespMsg->comp_resp_pars.output_byte_counter;
372 
373 		if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
374 			pSessionDesc->cumulativeConsumedBytes +=
375 			    pResults->consumed;
376 		} else {
377 			/* In the stateless case all requests have both SOP and
378 			 * EOP set */
379 			pSessionDesc->cumulativeConsumedBytes =
380 			    pResults->consumed;
381 		}
382 #else
383 		pResults->consumed = 0;
384 		pResults->produced = 0;
385 #endif
386 		if (CPA_DC_OVERFLOW == pResults->status &&
387 		    CPA_DC_STATELESS == pSessionDesc->sessState) {
388 			/* This error message will be returned by Data Plane API
389 			 * in both
390 			 * compression and decompression direction. With
391 			 * Traditional API
392 			 * this error message will be returned only in stateless
393 			 * decompression direction */
394 			QAT_UTILS_LOG(
395 			    "Unrecoverable error: stateless overflow. You may need to increase the size of your destination buffer.\n");
396 		}
397 
398 		if (CPA_TRUE == isDcDp) {
399 			if (pResponse)
400 				pResponse->responseStatus = CPA_STATUS_FAIL;
401 		} else {
402 			if (CPA_DC_OK != pResults->status &&
403 			    CPA_DC_INCOMPLETE_FILE_ERR != pResults->status) {
404 				status = CPA_STATUS_FAIL;
405 			}
406 
407 			if (DC_COMPRESSION_REQUEST == compDecomp) {
408 				COMPRESSION_STAT_INC(numCompCompletedErrors,
409 						     pService);
410 			} else {
411 				COMPRESSION_STAT_INC(numDecompCompletedErrors,
412 						     pService);
413 			}
414 		}
415 	}
416 
417 	if (CPA_TRUE == isDcDp) {
418 		/* Decrement number of stateless pending callbacks for session
419 		 */
420 		pSessionDesc->pendingDpStatelessCbCount--;
421 		(pService->pDcDpCb)(pResponse);
422 	} else {
423 		/* Decrement number of pending callbacks for session */
424 		if (CPA_DC_STATELESS == pSessionDesc->sessState) {
425 			qatUtilsAtomicDec(
426 			    &(pCookie->pSessionDesc->pendingStatelessCbCount));
427 		} else if (0 !=
428 			   qatUtilsAtomicGet(&pCookie->pSessionDesc
429 						  ->pendingStatefulCbCount)) {
430 			qatUtilsAtomicDec(
431 			    &(pCookie->pSessionDesc->pendingStatefulCbCount));
432 		}
433 
434 		/* Free the memory pool */
435 		if (NULL != pCookie) {
436 			Lac_MemPoolEntryFree(pCookie);
437 			pCookie = NULL;
438 		}
439 
440 		if (NULL != pCbFunc) {
441 			pCbFunc(callbackTag, status);
442 		}
443 	}
444 }
445 
446 /**
447  *****************************************************************************
448  * @ingroup Dc_DataCompression
449  *      Check that all the parameters in the pOpData structure are valid
450  *
451  * @description
452  *      Check that all the parameters in the pOpData structure are valid
453  *
454  * @param[in]   pService              Pointer to the compression service
455  * @param[in]   pOpData               Pointer to request information structure
456  *                                    holding parameters for cpaDcCompress2 and
457  *                                    CpaDcDecompressData2
458  * @retval CPA_STATUS_SUCCESS         Function executed successfully
459  * @retval CPA_STATUS_INVALID_PARAM   Invalid parameter passed in
460  *
461  *****************************************************************************/
462 CpaStatus
463 dcCheckOpData(sal_compression_service_t *pService, CpaDcOpData *pOpData)
464 {
465 	CpaDcSkipMode skipMode = 0;
466 
467 	if ((pOpData->flushFlag < CPA_DC_FLUSH_NONE) ||
468 	    (pOpData->flushFlag > CPA_DC_FLUSH_FULL)) {
469 		LAC_INVALID_PARAM_LOG("Invalid flushFlag value");
470 		return CPA_STATUS_INVALID_PARAM;
471 	}
472 
473 	skipMode = pOpData->inputSkipData.skipMode;
474 	if ((skipMode < CPA_DC_SKIP_DISABLED) ||
475 	    (skipMode > CPA_DC_SKIP_STRIDE)) {
476 		LAC_INVALID_PARAM_LOG("Invalid input skip mode value");
477 		return CPA_STATUS_INVALID_PARAM;
478 	}
479 
480 	skipMode = pOpData->outputSkipData.skipMode;
481 	if ((skipMode < CPA_DC_SKIP_DISABLED) ||
482 	    (skipMode > CPA_DC_SKIP_STRIDE)) {
483 		LAC_INVALID_PARAM_LOG("Invalid output skip mode value");
484 		return CPA_STATUS_INVALID_PARAM;
485 	}
486 
487 	if (pOpData->integrityCrcCheck == CPA_FALSE &&
488 	    pOpData->verifyHwIntegrityCrcs == CPA_TRUE) {
489 		LAC_INVALID_PARAM_LOG(
490 		    "integrityCrcCheck must be set to true"
491 		    "in order to enable verifyHwIntegrityCrcs");
492 		return CPA_STATUS_INVALID_PARAM;
493 	}
494 
495 	if (pOpData->integrityCrcCheck != CPA_TRUE &&
496 	    pOpData->integrityCrcCheck != CPA_FALSE) {
497 		LAC_INVALID_PARAM_LOG("Invalid integrityCrcCheck value");
498 		return CPA_STATUS_INVALID_PARAM;
499 	}
500 
501 	if (pOpData->verifyHwIntegrityCrcs != CPA_TRUE &&
502 	    pOpData->verifyHwIntegrityCrcs != CPA_FALSE) {
503 		LAC_INVALID_PARAM_LOG("Invalid verifyHwIntegrityCrcs value");
504 		return CPA_STATUS_INVALID_PARAM;
505 	}
506 
507 	if (pOpData->compressAndVerify != CPA_TRUE &&
508 	    pOpData->compressAndVerify != CPA_FALSE) {
509 		LAC_INVALID_PARAM_LOG("Invalid cnv decompress check value");
510 		return CPA_STATUS_INVALID_PARAM;
511 	}
512 
513 	if (CPA_TRUE == pOpData->integrityCrcCheck &&
514 	    CPA_FALSE == pService->generic_service_info.integrityCrcCheck) {
515 		LAC_INVALID_PARAM_LOG("Integrity CRC check is not "
516 				      "supported on this device");
517 		return CPA_STATUS_INVALID_PARAM;
518 	}
519 
520 	if (CPA_TRUE == pOpData->integrityCrcCheck &&
521 	    NULL == pOpData->pCrcData) {
522 		LAC_INVALID_PARAM_LOG("Integrity CRC data structure "
523 				      "not intialized in CpaDcOpData");
524 		return CPA_STATUS_INVALID_PARAM;
525 	}
526 
527 	return CPA_STATUS_SUCCESS;
528 }
529 
530 /**
531  *****************************************************************************
532  * @ingroup Dc_DataCompression
533  *      Check the compression source buffer for Batch and Pack API.
534  *
535  * @description
536  *      Check that all the parameters used for Pack compression
537  *      request are valid. This function essentially checks the source buffer
538  *      parameters and results structure parameters.
539  *
540  * @param[in]   pSessionHandle        Session handle
541  * @param[in]   pSrcBuff              Pointer to data buffer for compression
542  * @param[in]   pDestBuff             Pointer to buffer space allocated for
543  *                                    output data
544  * @param[in]   pResults              Pointer to results structure
545  * @param[in]   flushFlag             Indicates the type of flush to be
546  *                                    performed
547  * @param[in]   srcBuffSize           Size of the source buffer
548  *
549  * @retval CPA_STATUS_SUCCESS         Function executed successfully
550  * @retval CPA_STATUS_INVALID_PARAM   Invalid parameter passed in
551  *
552  *****************************************************************************/
553 static CpaStatus
554 dcCheckSourceData(CpaDcSessionHandle pSessionHandle,
555 		  CpaBufferList *pSrcBuff,
556 		  CpaBufferList *pDestBuff,
557 		  CpaDcRqResults *pResults,
558 		  CpaDcFlush flushFlag,
559 		  Cpa64U srcBuffSize,
560 		  CpaDcSkipData *skipData)
561 {
562 	dc_session_desc_t *pSessionDesc = NULL;
563 
564 	LAC_CHECK_NULL_PARAM(pSessionHandle);
565 	LAC_CHECK_NULL_PARAM(pSrcBuff);
566 	LAC_CHECK_NULL_PARAM(pDestBuff);
567 	LAC_CHECK_NULL_PARAM(pResults);
568 
569 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
570 	if (NULL == pSessionDesc) {
571 		LAC_INVALID_PARAM_LOG("Session handle not as expected");
572 		return CPA_STATUS_INVALID_PARAM;
573 	}
574 
575 	if ((flushFlag < CPA_DC_FLUSH_NONE) ||
576 	    (flushFlag > CPA_DC_FLUSH_FULL)) {
577 		LAC_INVALID_PARAM_LOG("Invalid flushFlag value");
578 		return CPA_STATUS_INVALID_PARAM;
579 	}
580 
581 	if (pSrcBuff == pDestBuff) {
582 		LAC_INVALID_PARAM_LOG("In place operation not supported");
583 		return CPA_STATUS_INVALID_PARAM;
584 	}
585 
586 	/* Compressing zero bytes is not supported for stateless sessions
587 	 * for non Batch and Pack requests */
588 	if ((CPA_DC_STATELESS == pSessionDesc->sessState) &&
589 	    (0 == srcBuffSize) && (NULL == skipData)) {
590 		LAC_INVALID_PARAM_LOG(
591 		    "The source buffer size needs to be greater than "
592 		    "zero bytes for stateless sessions");
593 		return CPA_STATUS_INVALID_PARAM;
594 	}
595 
596 	if (srcBuffSize > DC_BUFFER_MAX_SIZE) {
597 		LAC_INVALID_PARAM_LOG(
598 		    "The source buffer size needs to be less than or "
599 		    "equal to 2^32-1 bytes");
600 		return CPA_STATUS_INVALID_PARAM;
601 	}
602 
603 	return CPA_STATUS_SUCCESS;
604 }
605 
606 /**
607  *****************************************************************************
608  * @ingroup Dc_DataCompression
609  *      Check the compression or decompression function parameters.
610  *
611  * @description
612  *      Check that all the parameters used for a Batch and Pack compression
613  *      request are valid. This function essentially checks the destination
614  *      buffer parameters and intermediate buffer parameters.
615  *
616  * @param[in]   pService              Pointer to the compression service
617  * @param[in]   pSessionHandle        Session handle
618  * @param[in]   pDestBuff             Pointer to buffer space allocated for
619  *                                    output data
620  * @param[in]   compDecomp            Direction of the operation
621  *
622  * @retval CPA_STATUS_SUCCESS         Function executed successfully
623  * @retval CPA_STATUS_INVALID_PARAM   Invalid parameter passed in
624  *
625  *****************************************************************************/
626 static CpaStatus
627 dcCheckDestinationData(sal_compression_service_t *pService,
628 		       CpaDcSessionHandle pSessionHandle,
629 		       CpaBufferList *pDestBuff,
630 		       dc_request_dir_t compDecomp)
631 {
632 	dc_session_desc_t *pSessionDesc = NULL;
633 	Cpa64U destBuffSize = 0;
634 
635 	LAC_CHECK_NULL_PARAM(pSessionHandle);
636 	LAC_CHECK_NULL_PARAM(pDestBuff);
637 
638 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
639 	if (NULL == pSessionDesc) {
640 		LAC_INVALID_PARAM_LOG("Session handle not as expected");
641 		return CPA_STATUS_INVALID_PARAM;
642 	}
643 
644 	if (LacBuffDesc_BufferListVerify(pDestBuff,
645 					 &destBuffSize,
646 					 LAC_NO_ALIGNMENT_SHIFT) !=
647 	    CPA_STATUS_SUCCESS) {
648 		LAC_INVALID_PARAM_LOG(
649 		    "Invalid destination buffer list parameter");
650 		return CPA_STATUS_INVALID_PARAM;
651 	}
652 
653 	if (destBuffSize > DC_BUFFER_MAX_SIZE) {
654 		LAC_INVALID_PARAM_LOG(
655 		    "The destination buffer size needs to be less "
656 		    "than or equal to 2^32-1 bytes");
657 		return CPA_STATUS_INVALID_PARAM;
658 	}
659 
660 	if (CPA_TRUE == pSessionDesc->isDcDp) {
661 		LAC_INVALID_PARAM_LOG(
662 		    "The session type should not be data plane");
663 		return CPA_STATUS_INVALID_PARAM;
664 	}
665 
666 	if (DC_COMPRESSION_REQUEST == compDecomp) {
667 		if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) {
668 
669 			/* Check if intermediate buffers are supported */
670 			if ((isDcGen2x(pService)) &&
671 			    ((0 == pService->pInterBuffPtrsArrayPhyAddr) ||
672 			     (NULL == pService->pInterBuffPtrsArray))) {
673 				LAC_LOG_ERROR(
674 				    "No intermediate buffer defined for this instance "
675 				    "- see cpaDcStartInstance");
676 				return CPA_STATUS_INVALID_PARAM;
677 			}
678 
679 			/* Ensure that the destination buffer size is greater or
680 			 * equal to 128B */
681 			if (destBuffSize < DC_DEST_BUFFER_DYN_MIN_SIZE) {
682 				LAC_INVALID_PARAM_LOG(
683 				    "Destination buffer size should be "
684 				    "greater or equal to 128B");
685 				return CPA_STATUS_INVALID_PARAM;
686 			}
687 		} else
688 		{
689 			/* Ensure that the destination buffer size is greater or
690 			 * equal to devices min output buff size */
691 			if (destBuffSize <
692 			    pService->comp_device_data.minOutputBuffSize) {
693 				LAC_INVALID_PARAM_LOG1(
694 				    "Destination buffer size should be "
695 				    "greater or equal to %d bytes",
696 				    pService->comp_device_data
697 					.minOutputBuffSize);
698 				return CPA_STATUS_INVALID_PARAM;
699 			}
700 		}
701 	} else {
702 		/* Ensure that the destination buffer size is greater than
703 		 * 0 bytes */
704 		if (destBuffSize < DC_DEST_BUFFER_DEC_MIN_SIZE) {
705 			LAC_INVALID_PARAM_LOG(
706 			    "Destination buffer size should be "
707 			    "greater than 0 bytes");
708 			return CPA_STATUS_INVALID_PARAM;
709 		}
710 	}
711 	return CPA_STATUS_SUCCESS;
712 }
713 
714 /**
715  *****************************************************************************
716  * @ingroup Dc_DataCompression
717  *      Populate the compression request parameters
718  *
719  * @description
720  *      This function will populate the compression request parameters
721  *
722  * @param[out]  pCompReqParams   Pointer to the compression request parameters
723  * @param[in]   pCookie          Pointer to the compression cookie
724  *
725  *****************************************************************************/
726 static void
727 dcCompRequestParamsPopulate(icp_qat_fw_comp_req_params_t *pCompReqParams,
728 			    dc_compression_cookie_t *pCookie)
729 {
730 	pCompReqParams->comp_len = pCookie->srcTotalDataLenInBytes;
731 	pCompReqParams->out_buffer_sz = pCookie->dstTotalDataLenInBytes;
732 }
733 
734 /**
735  *****************************************************************************
736  * @ingroup Dc_DataCompression
737  *      Create the requests for compression or decompression
738  *
739  * @description
740  *      Create the requests for compression or decompression. This function
741  *      will update the cookie will all required information.
742  *
743  * @param{out]  pCookie             Pointer to the compression cookie
744  * @param[in]   pService            Pointer to the compression service
745  * @param[in]   pSessionDesc        Pointer to the session descriptor
746  * @param[in    pSessionHandle      Session handle
747  * @param[in]   pSrcBuff            Pointer to data buffer for compression
748  * @param[in]   pDestBuff           Pointer to buffer space for data after
749  *                                  compression
750  * @param[in]   pResults            Pointer to results structure
751  * @param[in]   flushFlag           Indicates the type of flush to be
752  *                                  performed
753  * @param[in]   pOpData             Pointer to request information structure
754  *                                  holding parameters for cpaDcCompress2
755  *                                  and CpaDcDecompressData2
756  * @param[in]   callbackTag         Pointer to the callback tag
757  * @param[in]   compDecomp          Direction of the operation
758  * @param[in]   compressAndVerify   Compress and Verify
759  *
760  * @retval CPA_STATUS_SUCCESS       Function executed successfully
761  * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in
762  *
763  *****************************************************************************/
764 static CpaStatus
765 dcCreateRequest(dc_compression_cookie_t *pCookie,
766 		sal_compression_service_t *pService,
767 		dc_session_desc_t *pSessionDesc,
768 		CpaDcSessionHandle pSessionHandle,
769 		CpaBufferList *pSrcBuff,
770 		CpaBufferList *pDestBuff,
771 		CpaDcRqResults *pResults,
772 		CpaDcFlush flushFlag,
773 		CpaDcOpData *pOpData,
774 		void *callbackTag,
775 		dc_request_dir_t compDecomp,
776 		dc_cnv_mode_t cnvMode)
777 {
778 	icp_qat_fw_comp_req_t *pMsg = NULL;
779 	icp_qat_fw_comp_req_params_t *pCompReqParams = NULL;
780 	Cpa64U srcAddrPhys = 0, dstAddrPhys = 0;
781 	Cpa64U srcTotalDataLenInBytes = 0, dstTotalDataLenInBytes = 0;
782 
783 	Cpa32U rpCmdFlags = 0;
784 	Cpa8U sop = ICP_QAT_FW_COMP_SOP;
785 	Cpa8U eop = ICP_QAT_FW_COMP_EOP;
786 	Cpa8U bFinal = ICP_QAT_FW_COMP_NOT_BFINAL;
787 	Cpa8U crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY;
788 	Cpa8U cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV;
789 	Cpa8U cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY;
790 	CpaBoolean cnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX;
791 	CpaBoolean integrityCrcCheck = CPA_FALSE;
792 	CpaStatus status = CPA_STATUS_SUCCESS;
793 	CpaDcFlush flush = CPA_DC_FLUSH_NONE;
794 	Cpa32U initial_adler = 1;
795 	Cpa32U initial_crc32 = 0;
796 	icp_qat_fw_comp_req_t *pReqCache = NULL;
797 
798 	/* Write the buffer descriptors */
799 	status = LacBuffDesc_BufferListDescWriteAndGetSize(
800 	    pSrcBuff,
801 	    &srcAddrPhys,
802 	    CPA_FALSE,
803 	    &srcTotalDataLenInBytes,
804 	    &(pService->generic_service_info));
805 	if (status != CPA_STATUS_SUCCESS) {
806 		return status;
807 	}
808 
809 	status = LacBuffDesc_BufferListDescWriteAndGetSize(
810 	    pDestBuff,
811 	    &dstAddrPhys,
812 	    CPA_FALSE,
813 	    &dstTotalDataLenInBytes,
814 	    &(pService->generic_service_info));
815 	if (status != CPA_STATUS_SUCCESS) {
816 		return status;
817 	}
818 
819 	/* Populate the compression cookie */
820 	pCookie->dcInstance = pService;
821 	pCookie->pSessionHandle = pSessionHandle;
822 	pCookie->callbackTag = callbackTag;
823 	pCookie->pSessionDesc = pSessionDesc;
824 	pCookie->pDcOpData = pOpData;
825 	pCookie->pResults = pResults;
826 	pCookie->compDecomp = compDecomp;
827 	pCookie->pUserSrcBuff = NULL;
828 	pCookie->pUserDestBuff = NULL;
829 
830 	/* Extract flush flag from either the opData or from the
831 	 * parameter. Opdata have been introduce with APIs
832 	 * cpaDcCompressData2 and cpaDcDecompressData2 */
833 	if (NULL != pOpData) {
834 		flush = pOpData->flushFlag;
835 		integrityCrcCheck = pOpData->integrityCrcCheck;
836 	} else {
837 		flush = flushFlag;
838 	}
839 	pCookie->flushFlag = flush;
840 
841 	/* The firmware expects the length in bytes for source and destination
842 	 * to be Cpa32U parameters. However the total data length could be
843 	 * bigger as allocated by the user. We ensure that this is not the case
844 	 * in dcCheckSourceData and cast the values to Cpa32U here */
845 	pCookie->srcTotalDataLenInBytes = (Cpa32U)srcTotalDataLenInBytes;
846 	if ((isDcGen2x(pService)) && (DC_COMPRESSION_REQUEST == compDecomp) &&
847 	    (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) {
848 		if (pService->minInterBuffSizeInBytes <
849 		    (Cpa32U)dstTotalDataLenInBytes) {
850 			pCookie->dstTotalDataLenInBytes =
851 			    (Cpa32U)(pService->minInterBuffSizeInBytes);
852 		} else {
853 			pCookie->dstTotalDataLenInBytes =
854 			    (Cpa32U)dstTotalDataLenInBytes;
855 		}
856 	} else
857 	{
858 		pCookie->dstTotalDataLenInBytes =
859 		    (Cpa32U)dstTotalDataLenInBytes;
860 	}
861 
862 	/* Device can not decompress an odd byte decompression request
863 	 * if bFinal is not set
864 	 */
865 	if (CPA_TRUE != pService->comp_device_data.oddByteDecompNobFinal) {
866 		if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
867 		    (CPA_DC_FLUSH_FINAL != flushFlag) &&
868 		    (DC_DECOMPRESSION_REQUEST == compDecomp) &&
869 		    (pCookie->srcTotalDataLenInBytes & 0x1)) {
870 			pCookie->srcTotalDataLenInBytes--;
871 		}
872 	}
873 	/* Device can not decompress odd byte interim requests */
874 	if (CPA_TRUE != pService->comp_device_data.oddByteDecompInterim) {
875 		if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
876 		    (CPA_DC_FLUSH_FINAL != flushFlag) &&
877 		    (CPA_DC_FLUSH_FULL != flushFlag) &&
878 		    (DC_DECOMPRESSION_REQUEST == compDecomp) &&
879 		    (pCookie->srcTotalDataLenInBytes & 0x1)) {
880 			pCookie->srcTotalDataLenInBytes--;
881 		}
882 	}
883 
884 	pMsg = (icp_qat_fw_comp_req_t *)&pCookie->request;
885 
886 	if (DC_COMPRESSION_REQUEST == compDecomp) {
887 		pReqCache = &(pSessionDesc->reqCacheComp);
888 	} else {
889 		pReqCache = &(pSessionDesc->reqCacheDecomp);
890 	}
891 
892 	/* Fills the msg from the template cached in the session descriptor */
893 	memcpy((void *)pMsg,
894 	       (void *)(pReqCache),
895 	       LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES);
896 
897 	if (DC_REQUEST_FIRST == pSessionDesc->requestType) {
898 		initial_adler = 1;
899 		initial_crc32 = 0;
900 
901 		if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
902 			pSessionDesc->previousChecksum = initial_adler;
903 		} else {
904 			pSessionDesc->previousChecksum = initial_crc32;
905 		}
906 	} else if (CPA_DC_STATELESS == pSessionDesc->sessState) {
907 		pSessionDesc->previousChecksum = pResults->checksum;
908 
909 		if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
910 			initial_adler = pSessionDesc->previousChecksum;
911 		} else {
912 			initial_crc32 = pSessionDesc->previousChecksum;
913 		}
914 	}
915 
916 	/* Backup source and destination buffer addresses,
917 	 * CRC calculations both for CNV and translator overflow
918 	 * will be performed on them in the callback function.
919 	 */
920 	pCookie->pUserSrcBuff = pSrcBuff;
921 	pCookie->pUserDestBuff = pDestBuff;
922 
923 	/*
924 	 * Due to implementation of CNV support and need for backwards
925 	 * compatibility certain fields in the request and response structs had
926 	 * been changed, moved or placed in unions cnvMode flag signifies fields
927 	 * to be selected from req/res
928 	 *
929 	 * Doing extended crc checks makes sense only when we want to do the
930 	 * actual CNV
931 	 */
932 	if (CPA_TRUE == pService->generic_service_info.integrityCrcCheck &&
933 	    CPA_TRUE == integrityCrcCheck) {
934 		pMsg->comp_pars.crc.crc_data_addr =
935 		    pSessionDesc->physDataIntegrityCrcs;
936 		crcMode = ICP_QAT_FW_COMP_CRC_MODE_E2E;
937 	} else {
938 		/* Legacy request structure */
939 		pMsg->comp_pars.crc.legacy.initial_adler = initial_adler;
940 		pMsg->comp_pars.crc.legacy.initial_crc32 = initial_crc32;
941 		crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY;
942 	}
943 
944 	/* Populate the cmdFlags */
945 	if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
946 		pSessionDesc->previousRequestType = pSessionDesc->requestType;
947 
948 		if (DC_REQUEST_FIRST == pSessionDesc->requestType) {
949 			/* Update the request type for following requests */
950 			pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT;
951 
952 			/* Reinitialise the cumulative amount of consumed bytes
953 			 */
954 			pSessionDesc->cumulativeConsumedBytes = 0;
955 
956 			if (DC_COMPRESSION_REQUEST == compDecomp) {
957 				pSessionDesc->isSopForCompressionProcessed =
958 				    CPA_TRUE;
959 			} else if (DC_DECOMPRESSION_REQUEST == compDecomp) {
960 				pSessionDesc->isSopForDecompressionProcessed =
961 				    CPA_TRUE;
962 			}
963 		} else {
964 			if (DC_COMPRESSION_REQUEST == compDecomp) {
965 				if (CPA_TRUE ==
966 				    pSessionDesc
967 					->isSopForCompressionProcessed) {
968 					sop = ICP_QAT_FW_COMP_NOT_SOP;
969 				} else {
970 					pSessionDesc
971 					    ->isSopForCompressionProcessed =
972 					    CPA_TRUE;
973 				}
974 			} else if (DC_DECOMPRESSION_REQUEST == compDecomp) {
975 				if (CPA_TRUE ==
976 				    pSessionDesc
977 					->isSopForDecompressionProcessed) {
978 					sop = ICP_QAT_FW_COMP_NOT_SOP;
979 				} else {
980 					pSessionDesc
981 					    ->isSopForDecompressionProcessed =
982 					    CPA_TRUE;
983 				}
984 			}
985 		}
986 
987 		if ((CPA_DC_FLUSH_FINAL == flush) ||
988 		    (CPA_DC_FLUSH_FULL == flush)) {
989 			/* Update the request type for following requests */
990 			pSessionDesc->requestType = DC_REQUEST_FIRST;
991 		} else {
992 			eop = ICP_QAT_FW_COMP_NOT_EOP;
993 		}
994 	} else {
995 		if (DC_REQUEST_FIRST == pSessionDesc->requestType) {
996 			/* Reinitialise the cumulative amount of consumed bytes
997 			 */
998 			pSessionDesc->cumulativeConsumedBytes = 0;
999 		}
1000 	}
1001 
1002 	/* (LW 14 - 15) */
1003 	pCompReqParams = &(pMsg->comp_pars);
1004 	dcCompRequestParamsPopulate(pCompReqParams, pCookie);
1005 	if (CPA_DC_FLUSH_FINAL == flush) {
1006 		bFinal = ICP_QAT_FW_COMP_BFINAL;
1007 	}
1008 
1009 	switch (cnvMode) {
1010 	case DC_CNVNR:
1011 		cnvRecovery = ICP_QAT_FW_COMP_CNV_RECOVERY;
1012 	/* Fall through is intended here, because for CNVNR
1013 	 * cnvDecompReq also needs to be set */
1014 	case DC_CNV:
1015 		cnvDecompReq = ICP_QAT_FW_COMP_CNV;
1016 		if (isDcGen4x(pService)) {
1017 			cnvErrorInjection = pSessionDesc->cnvErrorInjection;
1018 		}
1019 		break;
1020 	case DC_NO_CNV:
1021 		cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV;
1022 		cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY;
1023 		break;
1024 	}
1025 
1026 	/* LW 18 */
1027 	rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(sop,
1028 							   eop,
1029 							   bFinal,
1030 							   cnvDecompReq,
1031 							   cnvRecovery,
1032 							   cnvErrorInjection,
1033 							   crcMode);
1034 
1035 	pMsg->comp_pars.req_par_flags = rpCmdFlags;
1036 
1037 	/* Populates the QAT common request middle part of the message
1038 	 * (LW 6 to 11) */
1039 	SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pMsg,
1040 			      pCookie,
1041 			      DC_DEFAULT_QAT_PTR_TYPE,
1042 			      srcAddrPhys,
1043 			      dstAddrPhys,
1044 			      0,
1045 			      0);
1046 
1047 	return CPA_STATUS_SUCCESS;
1048 }
1049 
1050 /**
1051  *****************************************************************************
1052  * @ingroup Dc_DataCompression
1053  *      Send a compression request to QAT
1054  *
1055  * @description
1056  *      Send the requests for compression or decompression to QAT
1057  *
1058  * @param{in]   pCookie               Pointer to the compression cookie
1059  * @param[in]   pService              Pointer to the compression service
1060  * @param[in]   pSessionDesc          Pointer to the session descriptor
1061  * @param[in]   compDecomp            Direction of the operation
1062  *
1063  * @retval CPA_STATUS_SUCCESS         Function executed successfully
1064  * @retval CPA_STATUS_INVALID_PARAM   Invalid parameter passed in
1065  *
1066  *****************************************************************************/
1067 static CpaStatus
1068 dcSendRequest(dc_compression_cookie_t *pCookie,
1069 	      sal_compression_service_t *pService,
1070 	      dc_session_desc_t *pSessionDesc,
1071 	      dc_request_dir_t compDecomp)
1072 {
1073 	CpaStatus status = CPA_STATUS_SUCCESS;
1074 
1075 	/* Send to QAT */
1076 	status = icp_adf_transPutMsg(pService->trans_handle_compression_tx,
1077 				     (void *)&(pCookie->request),
1078 				     LAC_QAT_DC_REQ_SZ_LW);
1079 
1080 	if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
1081 	    (CPA_STATUS_RETRY == status)) {
1082 		/* reset requestType after receiving an retry on
1083 		 * the stateful request */
1084 		pSessionDesc->requestType = pSessionDesc->previousRequestType;
1085 	}
1086 
1087 	return status;
1088 }
1089 
1090 /**
1091  *****************************************************************************
1092  * @ingroup Dc_DataCompression
1093  *      Process the synchronous and asynchronous case for compression or
1094  *      decompression
1095  *
1096  * @description
1097  *      Process the synchronous and asynchronous case for compression or
1098  *      decompression. This function will then create and send the request to
1099  *      the firmware.
1100  *
1101  * @param[in]   pService            Pointer to the compression service
1102  * @param[in]   pSessionDesc        Pointer to the session descriptor
1103  * @param[in]   dcInstance          Instance handle derived from discovery
1104  *                                  functions
1105  * @param[in]   pSessionHandle      Session handle
1106  * @param[in]   numRequests         Number of operations in the batch request
1107  * @param[in]   pBatchOpData        Address of the list of jobs to be processed
1108  * @param[in]   pSrcBuff            Pointer to data buffer for compression
1109  * @param[in]   pDestBuff           Pointer to buffer space for data after
1110  *                                  compression
1111  * @param[in]   pResults            Pointer to results structure
1112  * @param[in]   flushFlag           Indicates the type of flush to be
1113  *                                  performed
1114  * @param[in]   pOpData             Pointer to request information structure
1115  *                                  holding parameters for cpaDcCompress2 and
1116  *                                  CpaDcDecompressData2
1117  * @param[in]   callbackTag         Pointer to the callback tag
1118  * @param[in]   compDecomp          Direction of the operation
1119  * @param[in]   isAsyncMode         Used to know if synchronous or asynchronous
1120  *                                  mode
1121  * @param[in]   cnvMode             CNV Mode
1122  *
1123  * @retval CPA_STATUS_SUCCESS       Function executed successfully
1124  * @retval CPA_STATUS_RETRY         Retry operation
1125  * @retval CPA_STATUS_FAIL          Function failed
1126  * @retval CPA_STATUS_RESOURCE      Resource error
1127  *
1128  *****************************************************************************/
1129 static CpaStatus
1130 dcCompDecompData(sal_compression_service_t *pService,
1131 		 dc_session_desc_t *pSessionDesc,
1132 		 CpaInstanceHandle dcInstance,
1133 		 CpaDcSessionHandle pSessionHandle,
1134 		 CpaBufferList *pSrcBuff,
1135 		 CpaBufferList *pDestBuff,
1136 		 CpaDcRqResults *pResults,
1137 		 CpaDcFlush flushFlag,
1138 		 CpaDcOpData *pOpData,
1139 		 void *callbackTag,
1140 		 dc_request_dir_t compDecomp,
1141 		 CpaBoolean isAsyncMode,
1142 		 dc_cnv_mode_t cnvMode)
1143 {
1144 	CpaStatus status = CPA_STATUS_SUCCESS;
1145 	dc_compression_cookie_t *pCookie = NULL;
1146 
1147 	if ((LacSync_GenWakeupSyncCaller == pSessionDesc->pCompressionCb) &&
1148 	    isAsyncMode == CPA_TRUE) {
1149 		lac_sync_op_data_t *pSyncCallbackData = NULL;
1150 
1151 		status = LacSync_CreateSyncCookie(&pSyncCallbackData);
1152 
1153 		if (CPA_STATUS_SUCCESS == status) {
1154 			status = dcCompDecompData(pService,
1155 						  pSessionDesc,
1156 						  dcInstance,
1157 						  pSessionHandle,
1158 						  pSrcBuff,
1159 						  pDestBuff,
1160 						  pResults,
1161 						  flushFlag,
1162 						  pOpData,
1163 						  pSyncCallbackData,
1164 						  compDecomp,
1165 						  CPA_FALSE,
1166 						  cnvMode);
1167 		} else {
1168 			return status;
1169 		}
1170 
1171 		if (CPA_STATUS_SUCCESS == status) {
1172 			CpaStatus syncStatus = CPA_STATUS_SUCCESS;
1173 
1174 			syncStatus =
1175 			    LacSync_WaitForCallback(pSyncCallbackData,
1176 						    DC_SYNC_CALLBACK_TIMEOUT,
1177 						    &status,
1178 						    NULL);
1179 
1180 			/* If callback doesn't come back */
1181 			if (CPA_STATUS_SUCCESS != syncStatus) {
1182 				if (DC_COMPRESSION_REQUEST == compDecomp) {
1183 					COMPRESSION_STAT_INC(
1184 					    numCompCompletedErrors, pService);
1185 				} else {
1186 					COMPRESSION_STAT_INC(
1187 					    numDecompCompletedErrors, pService);
1188 				}
1189 				LAC_LOG_ERROR("Callback timed out");
1190 				status = syncStatus;
1191 			}
1192 		} else {
1193 			/* As the Request was not sent the Callback will never
1194 			 * be called, so need to indicate that we're finished
1195 			 * with cookie so it can be destroyed. */
1196 			LacSync_SetSyncCookieComplete(pSyncCallbackData);
1197 		}
1198 
1199 		LacSync_DestroySyncCookie(&pSyncCallbackData);
1200 		return status;
1201 	}
1202 
1203 	/* Allocate the compression cookie
1204 	 * The memory is freed in callback or in sendRequest if an error occurs
1205 	 */
1206 	pCookie = (dc_compression_cookie_t *)Lac_MemPoolEntryAlloc(
1207 	    pService->compression_mem_pool);
1208 	if (NULL == pCookie) {
1209 		LAC_LOG_ERROR("Cannot get mem pool entry for compression");
1210 		status = CPA_STATUS_RESOURCE;
1211 	} else if ((void *)CPA_STATUS_RETRY == pCookie) {
1212 		pCookie = NULL;
1213 		status = CPA_STATUS_RETRY;
1214 	}
1215 
1216 	if (CPA_STATUS_SUCCESS == status) {
1217 		status = dcCreateRequest(pCookie,
1218 					 pService,
1219 					 pSessionDesc,
1220 					 pSessionHandle,
1221 					 pSrcBuff,
1222 					 pDestBuff,
1223 					 pResults,
1224 					 flushFlag,
1225 					 pOpData,
1226 					 callbackTag,
1227 					 compDecomp,
1228 					 cnvMode);
1229 	}
1230 
1231 	if (CPA_STATUS_SUCCESS == status) {
1232 		/* Increment number of pending callbacks for session */
1233 		if (CPA_DC_STATELESS == pSessionDesc->sessState) {
1234 			qatUtilsAtomicInc(
1235 			    &(pSessionDesc->pendingStatelessCbCount));
1236 		}
1237 		status =
1238 		    dcSendRequest(pCookie, pService, pSessionDesc, compDecomp);
1239 	}
1240 
1241 	if (CPA_STATUS_SUCCESS == status) {
1242 		if (DC_COMPRESSION_REQUEST == compDecomp) {
1243 			COMPRESSION_STAT_INC(numCompRequests, pService);
1244 		} else {
1245 			COMPRESSION_STAT_INC(numDecompRequests, pService);
1246 		}
1247 	} else {
1248 		if (DC_COMPRESSION_REQUEST == compDecomp) {
1249 			COMPRESSION_STAT_INC(numCompRequestsErrors, pService);
1250 		} else {
1251 			COMPRESSION_STAT_INC(numDecompRequestsErrors, pService);
1252 		}
1253 
1254 		/* Decrement number of pending callbacks for session */
1255 		if (CPA_DC_STATELESS == pSessionDesc->sessState) {
1256 			qatUtilsAtomicDec(
1257 			    &(pSessionDesc->pendingStatelessCbCount));
1258 		} else {
1259 			qatUtilsAtomicDec(
1260 			    &(pSessionDesc->pendingStatefulCbCount));
1261 		}
1262 
1263 		/* Free the memory pool */
1264 		if (NULL != pCookie) {
1265 			if (status != CPA_STATUS_UNSUPPORTED) {
1266 				/* Free the memory pool */
1267 				Lac_MemPoolEntryFree(pCookie);
1268 				pCookie = NULL;
1269 			}
1270 		}
1271 	}
1272 
1273 	return status;
1274 }
1275 
1276 /**
1277  *****************************************************************************
1278  * @ingroup Dc_DataCompression
1279  *      Handle zero length compression or decompression requests
1280  *
1281  * @description
1282  *      Handle zero length compression or decompression requests
1283  *
1284  * @param[in]   pService              Pointer to the compression service
1285  * @param[in]   pSessionDesc          Pointer to the session descriptor
1286  * @param[in]   pResults              Pointer to results structure
1287  * @param[in]   flushFlag             Indicates the type of flush to be
1288  *                                    performed
1289  * @param[in]   callbackTag           User supplied value to help correlate
1290  *                                    the callback with its associated request
1291  * @param[in]   compDecomp            Direction of the operation
1292  *
1293  * @retval CPA_TRUE                   Zero length SOP or MOP processed
1294  * @retval CPA_FALSE                  Zero length EOP
1295  *
1296  *****************************************************************************/
1297 static CpaStatus
1298 dcZeroLengthRequests(sal_compression_service_t *pService,
1299 		     dc_session_desc_t *pSessionDesc,
1300 		     CpaDcRqResults *pResults,
1301 		     CpaDcFlush flushFlag,
1302 		     void *callbackTag,
1303 		     dc_request_dir_t compDecomp)
1304 {
1305 	CpaBoolean status = CPA_FALSE;
1306 	CpaDcCallbackFn pCbFunc = pSessionDesc->pCompressionCb;
1307 
1308 	if (DC_REQUEST_FIRST == pSessionDesc->requestType) {
1309 		/* Reinitialise the cumulative amount of consumed bytes */
1310 		pSessionDesc->cumulativeConsumedBytes = 0;
1311 
1312 		/* Zero length SOP */
1313 		if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
1314 			pResults->checksum = 1;
1315 		} else {
1316 			pResults->checksum = 0;
1317 		}
1318 
1319 		status = CPA_TRUE;
1320 	} else if ((CPA_DC_FLUSH_NONE == flushFlag) ||
1321 		   (CPA_DC_FLUSH_SYNC == flushFlag)) {
1322 		/* Zero length MOP */
1323 		pResults->checksum = pSessionDesc->previousChecksum;
1324 		status = CPA_TRUE;
1325 	}
1326 
1327 	if (CPA_TRUE == status) {
1328 		pResults->status = CPA_DC_OK;
1329 		pResults->produced = 0;
1330 		pResults->consumed = 0;
1331 
1332 		/* Increment statistics */
1333 		if (DC_COMPRESSION_REQUEST == compDecomp) {
1334 			COMPRESSION_STAT_INC(numCompRequests, pService);
1335 			COMPRESSION_STAT_INC(numCompCompleted, pService);
1336 		} else {
1337 			COMPRESSION_STAT_INC(numDecompRequests, pService);
1338 			COMPRESSION_STAT_INC(numDecompCompleted, pService);
1339 		}
1340 
1341 		LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
1342 
1343 		if ((NULL != pCbFunc) &&
1344 		    (LacSync_GenWakeupSyncCaller != pCbFunc)) {
1345 			pCbFunc(callbackTag, CPA_STATUS_SUCCESS);
1346 		}
1347 
1348 		return CPA_TRUE;
1349 	}
1350 
1351 	return CPA_FALSE;
1352 }
1353 
1354 static CpaStatus
1355 dcParamCheck(CpaInstanceHandle dcInstance,
1356 	     CpaDcSessionHandle pSessionHandle,
1357 	     sal_compression_service_t *pService,
1358 	     CpaBufferList *pSrcBuff,
1359 	     CpaBufferList *pDestBuff,
1360 	     CpaDcRqResults *pResults,
1361 	     dc_session_desc_t *pSessionDesc,
1362 	     CpaDcFlush flushFlag,
1363 	     Cpa64U srcBuffSize)
1364 {
1365 
1366 	if (dcCheckSourceData(pSessionHandle,
1367 			      pSrcBuff,
1368 			      pDestBuff,
1369 			      pResults,
1370 			      flushFlag,
1371 			      srcBuffSize,
1372 			      NULL) != CPA_STATUS_SUCCESS) {
1373 		return CPA_STATUS_INVALID_PARAM;
1374 	}
1375 	if (dcCheckDestinationData(
1376 		pService, pSessionHandle, pDestBuff, DC_COMPRESSION_REQUEST) !=
1377 	    CPA_STATUS_SUCCESS) {
1378 		return CPA_STATUS_INVALID_PARAM;
1379 	}
1380 	if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) {
1381 		LAC_INVALID_PARAM_LOG("Invalid sessDirection value");
1382 		return CPA_STATUS_INVALID_PARAM;
1383 	}
1384 	return CPA_STATUS_SUCCESS;
1385 }
1386 
1387 CpaStatus
1388 cpaDcCompressData(CpaInstanceHandle dcInstance,
1389 		  CpaDcSessionHandle pSessionHandle,
1390 		  CpaBufferList *pSrcBuff,
1391 		  CpaBufferList *pDestBuff,
1392 		  CpaDcRqResults *pResults,
1393 		  CpaDcFlush flushFlag,
1394 		  void *callbackTag)
1395 {
1396 	sal_compression_service_t *pService = NULL;
1397 	dc_session_desc_t *pSessionDesc = NULL;
1398 	CpaInstanceHandle insHandle = NULL;
1399 	Cpa64U srcBuffSize = 0;
1400 
1401 
1402 	if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
1403 		insHandle = dcGetFirstHandle();
1404 	} else {
1405 		insHandle = dcInstance;
1406 	}
1407 
1408 	pService = (sal_compression_service_t *)insHandle;
1409 
1410 	LAC_CHECK_NULL_PARAM(insHandle);
1411 	LAC_CHECK_NULL_PARAM(pSessionHandle);
1412 
1413 	/* Check if SAL is initialised otherwise return an error */
1414 	SAL_RUNNING_CHECK(insHandle);
1415 
1416 	/* This check is outside the parameter checking as it is needed to
1417 	 * manage zero length requests */
1418 	if (LacBuffDesc_BufferListVerifyNull(pSrcBuff,
1419 					     &srcBuffSize,
1420 					     LAC_NO_ALIGNMENT_SHIFT) !=
1421 	    CPA_STATUS_SUCCESS) {
1422 		LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter");
1423 		return CPA_STATUS_INVALID_PARAM;
1424 	}
1425 
1426 	/* Ensure this is a compression instance */
1427 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
1428 
1429 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
1430 	if (CPA_STATUS_SUCCESS !=
1431 	    dcParamCheck(insHandle,
1432 			 pSessionHandle,
1433 			 pService,
1434 			 pSrcBuff,
1435 			 pDestBuff,
1436 			 pResults,
1437 			 pSessionDesc,
1438 			 flushFlag,
1439 			 srcBuffSize)) {
1440 		return CPA_STATUS_INVALID_PARAM;
1441 	}
1442 	if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
1443 		LAC_INVALID_PARAM_LOG(
1444 		    "Invalid session state, stateful sessions "
1445 		    "are not supported");
1446 		return CPA_STATUS_UNSUPPORTED;
1447 	}
1448 
1449 	if (!(pService->generic_service_info.dcExtendedFeatures &
1450 	      DC_CNV_EXTENDED_CAPABILITY)) {
1451 		LAC_INVALID_PARAM_LOG(
1452 		    "CompressAndVerify feature not supported");
1453 		return CPA_STATUS_UNSUPPORTED;
1454 	}
1455 
1456 	if (!(pService->generic_service_info.dcExtendedFeatures &
1457 	      DC_CNVNR_EXTENDED_CAPABILITY)) {
1458 		LAC_INVALID_PARAM_LOG(
1459 		    "CompressAndVerifyAndRecovery feature not supported");
1460 		return CPA_STATUS_UNSUPPORTED;
1461 	}
1462 
1463 	return dcCompDecompData(pService,
1464 				pSessionDesc,
1465 				insHandle,
1466 				pSessionHandle,
1467 				pSrcBuff,
1468 				pDestBuff,
1469 				pResults,
1470 				flushFlag,
1471 				NULL,
1472 				callbackTag,
1473 				DC_COMPRESSION_REQUEST,
1474 				CPA_TRUE,
1475 				DC_CNVNR);
1476 }
1477 
1478 CpaStatus
1479 cpaDcCompressData2(CpaInstanceHandle dcInstance,
1480 		   CpaDcSessionHandle pSessionHandle,
1481 		   CpaBufferList *pSrcBuff,
1482 		   CpaBufferList *pDestBuff,
1483 		   CpaDcOpData *pOpData,
1484 		   CpaDcRqResults *pResults,
1485 		   void *callbackTag)
1486 {
1487 	sal_compression_service_t *pService = NULL;
1488 	dc_session_desc_t *pSessionDesc = NULL;
1489 	CpaInstanceHandle insHandle = NULL;
1490 	Cpa64U srcBuffSize = 0;
1491 	dc_cnv_mode_t cnvMode = DC_NO_CNV;
1492 
1493 	LAC_CHECK_NULL_PARAM(pOpData);
1494 
1495 	if (((CPA_TRUE != pOpData->compressAndVerify) &&
1496 	     (CPA_FALSE != pOpData->compressAndVerify)) ||
1497 	    ((CPA_FALSE != pOpData->compressAndVerifyAndRecover) &&
1498 	     (CPA_TRUE != pOpData->compressAndVerifyAndRecover))) {
1499 		return CPA_STATUS_INVALID_PARAM;
1500 	}
1501 
1502 	if ((CPA_FALSE == pOpData->compressAndVerify) &&
1503 	    (CPA_TRUE == pOpData->compressAndVerifyAndRecover)) {
1504 		return CPA_STATUS_INVALID_PARAM;
1505 	}
1506 
1507 
1508 	if ((CPA_TRUE == pOpData->compressAndVerify) &&
1509 	    (CPA_TRUE == pOpData->compressAndVerifyAndRecover) &&
1510 	    (CPA_FALSE == pOpData->integrityCrcCheck)) {
1511 		return cpaDcCompressData(dcInstance,
1512 					 pSessionHandle,
1513 					 pSrcBuff,
1514 					 pDestBuff,
1515 					 pResults,
1516 					 pOpData->flushFlag,
1517 					 callbackTag);
1518 	}
1519 
1520 	if (CPA_FALSE == pOpData->compressAndVerify) {
1521 		LAC_INVALID_PARAM_LOG(
1522 		    "Data compression without verification not allowed");
1523 		return CPA_STATUS_UNSUPPORTED;
1524 	}
1525 
1526 
1527 	if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
1528 		insHandle = dcGetFirstHandle();
1529 	} else {
1530 		insHandle = dcInstance;
1531 	}
1532 
1533 	pService = (sal_compression_service_t *)insHandle;
1534 
1535 	LAC_CHECK_NULL_PARAM(insHandle);
1536 	LAC_CHECK_NULL_PARAM(pSessionHandle);
1537 	LAC_CHECK_NULL_PARAM(pOpData);
1538 
1539 	/* Check if SAL is initialised otherwise return an error */
1540 	SAL_RUNNING_CHECK(insHandle);
1541 
1542 	/* This check is outside the parameter checking as it is needed to
1543 	 * manage zero length requests */
1544 	if (LacBuffDesc_BufferListVerifyNull(pSrcBuff,
1545 					     &srcBuffSize,
1546 					     LAC_NO_ALIGNMENT_SHIFT) !=
1547 	    CPA_STATUS_SUCCESS) {
1548 		LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter");
1549 		return CPA_STATUS_INVALID_PARAM;
1550 	}
1551 
1552 	/* Ensure this is a compression instance */
1553 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
1554 
1555 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
1556 
1557 	if (CPA_TRUE == pOpData->compressAndVerify &&
1558 	    CPA_DC_STATEFUL == pSessionDesc->sessState) {
1559 		LAC_INVALID_PARAM_LOG(
1560 		    "Invalid session state, stateful sessions "
1561 		    "not supported with CNV");
1562 		return CPA_STATUS_UNSUPPORTED;
1563 	}
1564 
1565 	if (!(pService->generic_service_info.dcExtendedFeatures &
1566 	      DC_CNV_EXTENDED_CAPABILITY) &&
1567 	    (CPA_TRUE == pOpData->compressAndVerify)) {
1568 		LAC_INVALID_PARAM_LOG(
1569 		    "CompressAndVerify feature not supported");
1570 		return CPA_STATUS_UNSUPPORTED;
1571 	}
1572 
1573 	if (CPA_STATUS_SUCCESS !=
1574 	    dcParamCheck(insHandle,
1575 			 pSessionHandle,
1576 			 pService,
1577 			 pSrcBuff,
1578 			 pDestBuff,
1579 			 pResults,
1580 			 pSessionDesc,
1581 			 pOpData->flushFlag,
1582 			 srcBuffSize)) {
1583 		return CPA_STATUS_INVALID_PARAM;
1584 	}
1585 	if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData)) {
1586 		return CPA_STATUS_INVALID_PARAM;
1587 	}
1588 	if (CPA_TRUE != pOpData->compressAndVerify) {
1589 		if (srcBuffSize > DC_COMP_MAX_BUFF_SIZE) {
1590 			LAC_LOG_ERROR(
1591 			    "Compression payload greater than 64KB is "
1592 			    "unsupported, when CnV is disabled\n");
1593 			return CPA_STATUS_UNSUPPORTED;
1594 		}
1595 	}
1596 
1597 	if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
1598 		/* Lock the session to check if there are in-flight stateful
1599 		 * requests */
1600 		LAC_SPINLOCK(&(pSessionDesc->sessionLock));
1601 
1602 		/* Check if there is already one in-flight stateful request */
1603 		if (0 !=
1604 		    qatUtilsAtomicGet(
1605 			&(pSessionDesc->pendingStatefulCbCount))) {
1606 			LAC_LOG_ERROR(
1607 			    "Only one in-flight stateful request supported");
1608 			LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
1609 			return CPA_STATUS_RETRY;
1610 		}
1611 
1612 		if (0 == srcBuffSize) {
1613 			if (CPA_TRUE ==
1614 			    dcZeroLengthRequests(pService,
1615 						 pSessionDesc,
1616 						 pResults,
1617 						 pOpData->flushFlag,
1618 						 callbackTag,
1619 						 DC_COMPRESSION_REQUEST)) {
1620 				return CPA_STATUS_SUCCESS;
1621 			}
1622 		}
1623 
1624 		qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount));
1625 		LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
1626 	}
1627 
1628 	if (CPA_TRUE == pOpData->compressAndVerify) {
1629 		cnvMode = DC_CNV;
1630 	}
1631 
1632 	return dcCompDecompData(pService,
1633 				pSessionDesc,
1634 				insHandle,
1635 				pSessionHandle,
1636 				pSrcBuff,
1637 				pDestBuff,
1638 				pResults,
1639 				pOpData->flushFlag,
1640 				pOpData,
1641 				callbackTag,
1642 				DC_COMPRESSION_REQUEST,
1643 				CPA_TRUE,
1644 				cnvMode);
1645 }
1646 
1647 static CpaStatus
1648 dcDecompressDataCheck(CpaInstanceHandle insHandle,
1649 		      CpaDcSessionHandle pSessionHandle,
1650 		      CpaBufferList *pSrcBuff,
1651 		      CpaBufferList *pDestBuff,
1652 		      CpaDcRqResults *pResults,
1653 		      CpaDcFlush flushFlag,
1654 		      Cpa64U *srcBufferSize)
1655 {
1656 	sal_compression_service_t *pService = NULL;
1657 	dc_session_desc_t *pSessionDesc = NULL;
1658 	Cpa64U srcBuffSize = 0;
1659 
1660 	pService = (sal_compression_service_t *)insHandle;
1661 
1662 	LAC_CHECK_NULL_PARAM(insHandle);
1663 
1664 	/* Check if SAL is initialised otherwise return an error */
1665 	SAL_RUNNING_CHECK(insHandle);
1666 
1667 	/* This check is outside the parameter checking as it is needed to
1668 	 * manage zero length requests */
1669 	if (LacBuffDesc_BufferListVerifyNull(pSrcBuff,
1670 					     &srcBuffSize,
1671 					     LAC_NO_ALIGNMENT_SHIFT) !=
1672 	    CPA_STATUS_SUCCESS) {
1673 		LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter");
1674 		return CPA_STATUS_INVALID_PARAM;
1675 	}
1676 
1677 	/* Ensure this is a compression instance */
1678 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
1679 
1680 	if (dcCheckSourceData(pSessionHandle,
1681 			      pSrcBuff,
1682 			      pDestBuff,
1683 			      pResults,
1684 			      flushFlag,
1685 			      srcBuffSize,
1686 			      NULL) != CPA_STATUS_SUCCESS) {
1687 		return CPA_STATUS_INVALID_PARAM;
1688 	}
1689 	if (dcCheckDestinationData(pService,
1690 				   pSessionHandle,
1691 				   pDestBuff,
1692 				   DC_DECOMPRESSION_REQUEST) !=
1693 	    CPA_STATUS_SUCCESS) {
1694 		return CPA_STATUS_INVALID_PARAM;
1695 	}
1696 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
1697 
1698 	if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) {
1699 		LAC_INVALID_PARAM_LOG("Invalid sessDirection value");
1700 		return CPA_STATUS_INVALID_PARAM;
1701 	}
1702 
1703 
1704 	*srcBufferSize = srcBuffSize;
1705 
1706 	return CPA_STATUS_SUCCESS;
1707 }
1708 
1709 CpaStatus
1710 cpaDcDecompressData(CpaInstanceHandle dcInstance,
1711 		    CpaDcSessionHandle pSessionHandle,
1712 		    CpaBufferList *pSrcBuff,
1713 		    CpaBufferList *pDestBuff,
1714 		    CpaDcRqResults *pResults,
1715 		    CpaDcFlush flushFlag,
1716 		    void *callbackTag)
1717 {
1718 	sal_compression_service_t *pService = NULL;
1719 	dc_session_desc_t *pSessionDesc = NULL;
1720 	CpaInstanceHandle insHandle = NULL;
1721 	Cpa64U srcBuffSize = 0;
1722 	CpaStatus status = CPA_STATUS_SUCCESS;
1723 
1724 
1725 	if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
1726 		insHandle = dcGetFirstHandle();
1727 	} else {
1728 		insHandle = dcInstance;
1729 	}
1730 
1731 	status = dcDecompressDataCheck(insHandle,
1732 				       pSessionHandle,
1733 				       pSrcBuff,
1734 				       pDestBuff,
1735 				       pResults,
1736 				       flushFlag,
1737 				       &srcBuffSize);
1738 	if (CPA_STATUS_SUCCESS != status) {
1739 		return status;
1740 	}
1741 
1742 	pService = (sal_compression_service_t *)insHandle;
1743 
1744 	/* Check if SAL is initialised otherwise return an error */
1745 	SAL_RUNNING_CHECK(insHandle);
1746 
1747 	/* This check is outside the parameter checking as it is needed to
1748 	 * manage zero length requests */
1749 	if (CPA_STATUS_SUCCESS !=
1750 	    LacBuffDesc_BufferListVerifyNull(pSrcBuff,
1751 					     &srcBuffSize,
1752 					     LAC_NO_ALIGNMENT_SHIFT)) {
1753 		QAT_UTILS_LOG("Invalid source buffer list parameter");
1754 		return CPA_STATUS_INVALID_PARAM;
1755 	}
1756 
1757 	/* Ensure this is a compression instance */
1758 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
1759 
1760 	if (dcCheckSourceData(pSessionHandle,
1761 			      pSrcBuff,
1762 			      pDestBuff,
1763 			      pResults,
1764 			      flushFlag,
1765 			      srcBuffSize,
1766 			      NULL) != CPA_STATUS_SUCCESS) {
1767 		return CPA_STATUS_INVALID_PARAM;
1768 	}
1769 	if (dcCheckDestinationData(pService,
1770 				   pSessionHandle,
1771 				   pDestBuff,
1772 				   DC_DECOMPRESSION_REQUEST) !=
1773 	    CPA_STATUS_SUCCESS) {
1774 		return CPA_STATUS_INVALID_PARAM;
1775 	}
1776 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
1777 
1778 	if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) {
1779 		QAT_UTILS_LOG("Invalid sessDirection value");
1780 		return CPA_STATUS_INVALID_PARAM;
1781 	}
1782 
1783 
1784 	if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
1785 		/* Lock the session to check if there are in-flight stateful
1786 		 * requests */
1787 		LAC_SPINLOCK(&(pSessionDesc->sessionLock));
1788 
1789 		/* Check if there is already one in-flight stateful request */
1790 		if (0 !=
1791 		    qatUtilsAtomicGet(
1792 			&(pSessionDesc->pendingStatefulCbCount))) {
1793 			LAC_LOG_ERROR(
1794 			    "Only one in-flight stateful request supported");
1795 			LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
1796 			return CPA_STATUS_RETRY;
1797 		}
1798 
1799 		/* Gen 4 handle 0 len requests in FW */
1800 		if (isDcGen2x(pService)) {
1801 			if ((0 == srcBuffSize) ||
1802 			    ((1 == srcBuffSize) &&
1803 			     (CPA_DC_FLUSH_FINAL != flushFlag) &&
1804 			     (CPA_DC_FLUSH_FULL != flushFlag))) {
1805 				if (CPA_TRUE ==
1806 				    dcZeroLengthRequests(
1807 					pService,
1808 					pSessionDesc,
1809 					pResults,
1810 					flushFlag,
1811 					callbackTag,
1812 					DC_DECOMPRESSION_REQUEST)) {
1813 					return CPA_STATUS_SUCCESS;
1814 				}
1815 			}
1816 		}
1817 
1818 		qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount));
1819 		LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
1820 	}
1821 
1822 	return dcCompDecompData(pService,
1823 				pSessionDesc,
1824 				insHandle,
1825 				pSessionHandle,
1826 				pSrcBuff,
1827 				pDestBuff,
1828 				pResults,
1829 				flushFlag,
1830 				NULL,
1831 				callbackTag,
1832 				DC_DECOMPRESSION_REQUEST,
1833 				CPA_TRUE,
1834 				DC_NO_CNV);
1835 }
1836 
1837 CpaStatus
1838 cpaDcDecompressData2(CpaInstanceHandle dcInstance,
1839 		     CpaDcSessionHandle pSessionHandle,
1840 		     CpaBufferList *pSrcBuff,
1841 		     CpaBufferList *pDestBuff,
1842 		     CpaDcOpData *pOpData,
1843 		     CpaDcRqResults *pResults,
1844 		     void *callbackTag)
1845 {
1846 	sal_compression_service_t *pService = NULL;
1847 	dc_session_desc_t *pSessionDesc = NULL;
1848 	CpaInstanceHandle insHandle = NULL;
1849 	CpaStatus status = CPA_STATUS_SUCCESS;
1850 	Cpa64U srcBuffSize = 0;
1851 	LAC_CHECK_NULL_PARAM(pOpData);
1852 
1853 	if (CPA_FALSE == pOpData->integrityCrcCheck) {
1854 
1855 		return cpaDcDecompressData(dcInstance,
1856 					   pSessionHandle,
1857 					   pSrcBuff,
1858 					   pDestBuff,
1859 					   pResults,
1860 					   pOpData->flushFlag,
1861 					   callbackTag);
1862 	}
1863 
1864 
1865 	if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
1866 		insHandle = dcGetFirstHandle();
1867 	} else {
1868 		insHandle = dcInstance;
1869 	}
1870 
1871 	status = dcDecompressDataCheck(insHandle,
1872 				       pSessionHandle,
1873 				       pSrcBuff,
1874 				       pDestBuff,
1875 				       pResults,
1876 				       pOpData->flushFlag,
1877 				       &srcBuffSize);
1878 	if (CPA_STATUS_SUCCESS != status) {
1879 		return status;
1880 	}
1881 
1882 	pService = (sal_compression_service_t *)insHandle;
1883 
1884 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
1885 
1886 	LAC_CHECK_NULL_PARAM(insHandle);
1887 
1888 	/* Check if SAL is initialised otherwise return an error */
1889 	SAL_RUNNING_CHECK(insHandle);
1890 
1891 	/* This check is outside the parameter checking as it is needed to
1892 	 * manage zero length requests */
1893 	if (CPA_STATUS_SUCCESS !=
1894 	    LacBuffDesc_BufferListVerifyNull(pSrcBuff,
1895 					     &srcBuffSize,
1896 					     LAC_NO_ALIGNMENT_SHIFT)) {
1897 		QAT_UTILS_LOG("Invalid source buffer list parameter");
1898 		return CPA_STATUS_INVALID_PARAM;
1899 	}
1900 
1901 	/* Ensure this is a compression instance */
1902 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
1903 
1904 	if (CPA_STATUS_SUCCESS !=
1905 	    dcCheckSourceData(pSessionHandle,
1906 			      pSrcBuff,
1907 			      pDestBuff,
1908 			      pResults,
1909 			      CPA_DC_FLUSH_NONE,
1910 			      srcBuffSize,
1911 			      NULL)) {
1912 		return CPA_STATUS_INVALID_PARAM;
1913 	}
1914 	if (CPA_STATUS_SUCCESS !=
1915 	    dcCheckDestinationData(pService,
1916 				   pSessionHandle,
1917 				   pDestBuff,
1918 				   DC_DECOMPRESSION_REQUEST)) {
1919 		return CPA_STATUS_INVALID_PARAM;
1920 	}
1921 
1922 	if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData)) {
1923 		return CPA_STATUS_INVALID_PARAM;
1924 	}
1925 
1926 	if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) {
1927 		QAT_UTILS_LOG("Invalid sessDirection value");
1928 		return CPA_STATUS_INVALID_PARAM;
1929 	}
1930 
1931 
1932 	if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
1933 		/* Lock the session to check if there are in-flight stateful
1934 		 * requests */
1935 		LAC_SPINLOCK(&(pSessionDesc->sessionLock));
1936 
1937 		/* Check if there is already one in-flight stateful request */
1938 		if (0 !=
1939 		    qatUtilsAtomicGet(
1940 			&(pSessionDesc->pendingStatefulCbCount))) {
1941 			LAC_LOG_ERROR(
1942 			    "Only one in-flight stateful request supported");
1943 			LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
1944 			return CPA_STATUS_RETRY;
1945 		}
1946 
1947 		/* Gen 4 handle 0 len requests in FW */
1948 		if (isDcGen2x(pService)) {
1949 			if ((0 == srcBuffSize) ||
1950 			    ((1 == srcBuffSize) &&
1951 			     (CPA_DC_FLUSH_FINAL != pOpData->flushFlag) &&
1952 			     (CPA_DC_FLUSH_FULL != pOpData->flushFlag))) {
1953 				if (CPA_TRUE ==
1954 				    dcZeroLengthRequests(
1955 					pService,
1956 					pSessionDesc,
1957 					pResults,
1958 					pOpData->flushFlag,
1959 					callbackTag,
1960 					DC_DECOMPRESSION_REQUEST)) {
1961 					return CPA_STATUS_SUCCESS;
1962 				}
1963 			}
1964 		}
1965 		qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount));
1966 		LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
1967 	}
1968 
1969 	return dcCompDecompData(pService,
1970 				pSessionDesc,
1971 				insHandle,
1972 				pSessionHandle,
1973 				pSrcBuff,
1974 				pDestBuff,
1975 				pResults,
1976 				pOpData->flushFlag,
1977 				pOpData,
1978 				callbackTag,
1979 				DC_DECOMPRESSION_REQUEST,
1980 				CPA_TRUE,
1981 				DC_NO_CNV);
1982 }
1983