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