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