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