xref: /freebsd/sys/dev/qat/qat_api/common/compression/dc_session.c (revision 4f0c9b76cf75724ef0b9c59bb8c182be24361d7c)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 /**
5  *****************************************************************************
6  * @file dc_session.c
7  *
8  * @ingroup Dc_DataCompression
9  *
10  * @description
11  *      Implementation of the Data Compression session operations.
12  *
13  *****************************************************************************/
14 
15 /*
16  *******************************************************************************
17  * Include public/global header files
18  *******************************************************************************
19  */
20 #include "cpa.h"
21 #include "cpa_dc.h"
22 
23 #include "icp_qat_fw.h"
24 #include "icp_qat_fw_comp.h"
25 #include "icp_qat_hw.h"
26 
27 /*
28  *******************************************************************************
29  * Include private header files
30  *******************************************************************************
31  */
32 #include "dc_session.h"
33 #include "dc_datapath.h"
34 #include "lac_mem_pools.h"
35 #include "sal_types_compression.h"
36 #include "lac_buffer_desc.h"
37 #include "sal_service_state.h"
38 #include "sal_qat_cmn_msg.h"
39 
40 /**
41  *****************************************************************************
42  * @ingroup Dc_DataCompression
43  *      Check that pSessionData is valid
44  *
45  * @description
46  *      Check that all the parameters defined in the pSessionData are valid
47  *
48  * @param[in]       pSessionData     Pointer to a user instantiated structure
49  *                                   containing session data
50  *
51  * @retval CPA_STATUS_SUCCESS        Function executed successfully
52  * @retval CPA_STATUS_FAIL           Function failed to find device
53  * @retval CPA_STATUS_INVALID_PARAM  Invalid parameter passed in
54  * @retval CPA_STATUS_UNSUPPORTED    Unsupported algorithm/feature
55  *
56  *****************************************************************************/
57 static CpaStatus
58 dcCheckSessionData(const CpaDcSessionSetupData *pSessionData,
59 		   CpaInstanceHandle dcInstance)
60 {
61 	CpaDcInstanceCapabilities instanceCapabilities = { 0 };
62 
63 	cpaDcQueryCapabilities(dcInstance, &instanceCapabilities);
64 
65 	if ((pSessionData->compLevel < CPA_DC_L1) ||
66 	    (pSessionData->compLevel > CPA_DC_L9)) {
67 		QAT_UTILS_LOG("Invalid compLevel value\n");
68 		return CPA_STATUS_INVALID_PARAM;
69 	}
70 	if ((pSessionData->autoSelectBestHuffmanTree < CPA_DC_ASB_DISABLED) ||
71 	    (pSessionData->autoSelectBestHuffmanTree >
72 	     CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS)) {
73 		QAT_UTILS_LOG("Invalid autoSelectBestHuffmanTree value\n");
74 		return CPA_STATUS_INVALID_PARAM;
75 	}
76 	if (pSessionData->compType != CPA_DC_DEFLATE) {
77 		QAT_UTILS_LOG("Invalid compType value\n");
78 		return CPA_STATUS_INVALID_PARAM;
79 	}
80 
81 	if ((pSessionData->huffType < CPA_DC_HT_STATIC) ||
82 	    (pSessionData->huffType > CPA_DC_HT_FULL_DYNAMIC) ||
83 	    (CPA_DC_HT_PRECOMP == pSessionData->huffType)) {
84 		QAT_UTILS_LOG("Invalid huffType value\n");
85 		return CPA_STATUS_INVALID_PARAM;
86 	}
87 
88 	if ((pSessionData->sessDirection < CPA_DC_DIR_COMPRESS) ||
89 	    (pSessionData->sessDirection > CPA_DC_DIR_COMBINED)) {
90 		QAT_UTILS_LOG("Invalid sessDirection value\n");
91 		return CPA_STATUS_INVALID_PARAM;
92 	}
93 
94 	if ((pSessionData->sessState < CPA_DC_STATEFUL) ||
95 	    (pSessionData->sessState > CPA_DC_STATELESS)) {
96 		QAT_UTILS_LOG("Invalid sessState value\n");
97 		return CPA_STATUS_INVALID_PARAM;
98 	}
99 
100 	if ((pSessionData->checksum < CPA_DC_NONE) ||
101 	    (pSessionData->checksum > CPA_DC_ADLER32)) {
102 		QAT_UTILS_LOG("Invalid checksum value\n");
103 		return CPA_STATUS_INVALID_PARAM;
104 	}
105 
106 	return CPA_STATUS_SUCCESS;
107 }
108 
109 /**
110  *****************************************************************************
111  * @ingroup Dc_DataCompression
112  *      Populate the compression hardware block
113  *
114  * @description
115  *      This function will populate the compression hardware block and update
116  *      the size in bytes of the block
117  *
118  * @param[in]   pSessionDesc            Pointer to the session descriptor
119  * @param[in]   pCompConfig             Pointer to slice config word
120  * @param[in]   compDecomp              Direction of the operation
121  * @param[in]   enableDmm               Delayed Match Mode
122  *
123  *****************************************************************************/
124 static void
125 dcCompHwBlockPopulate(dc_session_desc_t *pSessionDesc,
126 		      icp_qat_hw_compression_config_t *pCompConfig,
127 		      dc_request_dir_t compDecomp,
128 		      icp_qat_hw_compression_delayed_match_t enableDmm)
129 {
130 	icp_qat_hw_compression_direction_t dir =
131 	    ICP_QAT_HW_COMPRESSION_DIR_COMPRESS;
132 	icp_qat_hw_compression_algo_t algo =
133 	    ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE;
134 	icp_qat_hw_compression_depth_t depth = ICP_QAT_HW_COMPRESSION_DEPTH_1;
135 	icp_qat_hw_compression_file_type_t filetype =
136 	    ICP_QAT_HW_COMPRESSION_FILE_TYPE_0;
137 
138 	/* Set the direction */
139 	if (DC_COMPRESSION_REQUEST == compDecomp) {
140 		dir = ICP_QAT_HW_COMPRESSION_DIR_COMPRESS;
141 	} else {
142 		dir = ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS;
143 	}
144 
145 	if (CPA_DC_DEFLATE == pSessionDesc->compType) {
146 		algo = ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE;
147 	} else {
148 		QAT_UTILS_LOG("Algorithm not supported for Compression\n");
149 	}
150 
151 	/* Set the depth */
152 	if (DC_DECOMPRESSION_REQUEST == compDecomp) {
153 		depth = ICP_QAT_HW_COMPRESSION_DEPTH_1;
154 	} else {
155 		switch (pSessionDesc->compLevel) {
156 		case CPA_DC_L1:
157 			depth = ICP_QAT_HW_COMPRESSION_DEPTH_1;
158 			break;
159 		case CPA_DC_L2:
160 			depth = ICP_QAT_HW_COMPRESSION_DEPTH_4;
161 			break;
162 		case CPA_DC_L3:
163 			depth = ICP_QAT_HW_COMPRESSION_DEPTH_8;
164 			break;
165 		default:
166 			depth = ICP_QAT_HW_COMPRESSION_DEPTH_16;
167 		}
168 	}
169 
170 	/* The file type is set to ICP_QAT_HW_COMPRESSION_FILE_TYPE_0. The other
171 	 * modes will be used in the future for precompiled huffman trees */
172 	filetype = ICP_QAT_HW_COMPRESSION_FILE_TYPE_0;
173 
174 	pCompConfig->val = ICP_QAT_HW_COMPRESSION_CONFIG_BUILD(
175 	    dir, enableDmm, algo, depth, filetype);
176 
177 	pCompConfig->reserved = 0;
178 }
179 
180 /**
181  *****************************************************************************
182  * @ingroup Dc_DataCompression
183  *      Populate the compression content descriptor
184  *
185  * @description
186  *      This function will populate the compression content descriptor
187  *
188  * @param[in]   pService                Pointer to the service
189  * @param[in]   pSessionDesc            Pointer to the session descriptor
190  * @param[in]   contextBufferAddrPhys   Physical address of the context buffer
191  * @param[out]  pMsg                    Pointer to the compression message
192  * @param[in]   nextSlice               Next slice
193  * @param[in]   compDecomp              Direction of the operation
194  *
195  *****************************************************************************/
196 static void
197 dcCompContentDescPopulate(sal_compression_service_t *pService,
198 			  dc_session_desc_t *pSessionDesc,
199 			  CpaPhysicalAddr contextBufferAddrPhys,
200 			  icp_qat_fw_comp_req_t *pMsg,
201 			  icp_qat_fw_slice_t nextSlice,
202 			  dc_request_dir_t compDecomp)
203 {
204 
205 	icp_qat_fw_comp_cd_hdr_t *pCompControlBlock = NULL;
206 	icp_qat_hw_compression_config_t *pCompConfig = NULL;
207 	CpaBoolean bankEnabled = CPA_FALSE;
208 
209 	pCompControlBlock = (icp_qat_fw_comp_cd_hdr_t *)&(pMsg->comp_cd_ctrl);
210 	pCompConfig =
211 	    (icp_qat_hw_compression_config_t *)(pMsg->cd_pars.sl
212 						    .comp_slice_cfg_word);
213 
214 	ICP_QAT_FW_COMN_NEXT_ID_SET(pCompControlBlock, nextSlice);
215 	ICP_QAT_FW_COMN_CURR_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_COMP);
216 
217 	pCompControlBlock->comp_cfg_offset = 0;
218 
219 	if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
220 	    (CPA_DC_DEFLATE == pSessionDesc->compType) &&
221 	    (DC_DECOMPRESSION_REQUEST == compDecomp)) {
222 		/* Enable A, B, C, D, and E (CAMs).  */
223 		pCompControlBlock->ram_bank_flags =
224 		    ICP_QAT_FW_COMP_RAM_FLAGS_BUILD(
225 			ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank I */
226 			ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank H */
227 			ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank G */
228 			ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank F */
229 			ICP_QAT_FW_COMP_BANK_ENABLED,  /* Bank E */
230 			ICP_QAT_FW_COMP_BANK_ENABLED,  /* Bank D */
231 			ICP_QAT_FW_COMP_BANK_ENABLED,  /* Bank C */
232 			ICP_QAT_FW_COMP_BANK_ENABLED,  /* Bank B */
233 			ICP_QAT_FW_COMP_BANK_ENABLED); /* Bank A */
234 		bankEnabled = CPA_TRUE;
235 	} else {
236 		/* Disable all banks */
237 		pCompControlBlock->ram_bank_flags =
238 		    ICP_QAT_FW_COMP_RAM_FLAGS_BUILD(
239 			ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank I */
240 			ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank H */
241 			ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank G */
242 			ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank F */
243 			ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank E */
244 			ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank D */
245 			ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank C */
246 			ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank B */
247 			ICP_QAT_FW_COMP_BANK_DISABLED); /* Bank A */
248 	}
249 
250 	if (DC_COMPRESSION_REQUEST == compDecomp) {
251 		LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL(
252 		    pService->generic_service_info,
253 		    pCompControlBlock->comp_state_addr,
254 		    pSessionDesc->stateRegistersComp);
255 	} else {
256 		LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL(
257 		    pService->generic_service_info,
258 		    pCompControlBlock->comp_state_addr,
259 		    pSessionDesc->stateRegistersDecomp);
260 	}
261 
262 	if (CPA_TRUE == bankEnabled) {
263 		pCompControlBlock->ram_banks_addr = contextBufferAddrPhys;
264 	} else {
265 		pCompControlBlock->ram_banks_addr = 0;
266 	}
267 
268 	pCompControlBlock->resrvd = 0;
269 
270 	/* Populate Compression Hardware Setup Block */
271 	dcCompHwBlockPopulate(pSessionDesc,
272 			      pCompConfig,
273 			      compDecomp,
274 			      pService->comp_device_data.enableDmm);
275 }
276 
277 /**
278  *****************************************************************************
279  * @ingroup Dc_DataCompression
280  *      Populate the translator content descriptor
281  *
282  * @description
283  *      This function will populate the translator content descriptor
284  *
285  * @param[out]  pMsg                     Pointer to the compression message
286  * @param[in]   nextSlice                Next slice
287  *
288  *****************************************************************************/
289 static void
290 dcTransContentDescPopulate(icp_qat_fw_comp_req_t *pMsg,
291 			   icp_qat_fw_slice_t nextSlice)
292 {
293 
294 	icp_qat_fw_xlt_cd_hdr_t *pTransControlBlock = NULL;
295 	pTransControlBlock = (icp_qat_fw_xlt_cd_hdr_t *)&(pMsg->u2.xlt_cd_ctrl);
296 
297 	ICP_QAT_FW_COMN_NEXT_ID_SET(pTransControlBlock, nextSlice);
298 	ICP_QAT_FW_COMN_CURR_ID_SET(pTransControlBlock, ICP_QAT_FW_SLICE_XLAT);
299 
300 	pTransControlBlock->resrvd1 = 0;
301 	pTransControlBlock->resrvd2 = 0;
302 	pTransControlBlock->resrvd3 = 0;
303 }
304 
305 /**
306  *****************************************************************************
307  * @ingroup Dc_DataCompression
308  *      Get the context size and the history size
309  *
310  * @description
311  *      This function will get the size of the context buffer and the history
312  *      buffer. The history buffer is a subset of the context buffer and its
313  *      size is needed for stateful compression.
314 
315  * @param[in]   dcInstance         DC Instance Handle
316  *
317  * @param[in]   pSessionData       Pointer to a user instantiated
318  *                                 structure containing session data
319  * @param[out]  pContextSize       Pointer to the context size
320  *
321  * @retval CPA_STATUS_SUCCESS      Function executed successfully
322  *
323  *
324  *****************************************************************************/
325 static CpaStatus
326 dcGetContextSize(CpaInstanceHandle dcInstance,
327 		 CpaDcSessionSetupData *pSessionData,
328 		 Cpa32U *pContextSize)
329 {
330 	sal_compression_service_t *pCompService = NULL;
331 
332 	pCompService = (sal_compression_service_t *)dcInstance;
333 
334 	*pContextSize = 0;
335 	if ((CPA_DC_STATEFUL == pSessionData->sessState) &&
336 	    (CPA_DC_DEFLATE == pSessionData->compType) &&
337 	    (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection)) {
338 		*pContextSize =
339 		    pCompService->comp_device_data.inflateContextSize;
340 	}
341 	return CPA_STATUS_SUCCESS;
342 }
343 
344 CpaStatus
345 dcInitSession(CpaInstanceHandle dcInstance,
346 	      CpaDcSessionHandle pSessionHandle,
347 	      CpaDcSessionSetupData *pSessionData,
348 	      CpaBufferList *pContextBuffer,
349 	      CpaDcCallbackFn callbackFn)
350 {
351 	CpaStatus status = CPA_STATUS_SUCCESS;
352 	sal_compression_service_t *pService = NULL;
353 	icp_qat_fw_comp_req_t *pReqCache = NULL;
354 	dc_session_desc_t *pSessionDesc = NULL;
355 	CpaPhysicalAddr contextAddrPhys = 0;
356 	CpaPhysicalAddr physAddress = 0;
357 	CpaPhysicalAddr physAddressAligned = 0;
358 	Cpa32U minContextSize = 0, historySize = 0;
359 	Cpa32U rpCmdFlags = 0;
360 	icp_qat_fw_serv_specif_flags cmdFlags = 0;
361 	Cpa8U secureRam = ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF;
362 	Cpa8U sessType = ICP_QAT_FW_COMP_STATELESS_SESSION;
363 	Cpa8U autoSelectBest = ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST;
364 	Cpa8U enhancedAutoSelectBest = ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST;
365 	Cpa8U disableType0EnhancedAutoSelectBest =
366 	    ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST;
367 	icp_qat_fw_la_cmd_id_t dcCmdId =
368 	    (icp_qat_fw_la_cmd_id_t)ICP_QAT_FW_COMP_CMD_STATIC;
369 	icp_qat_fw_comn_flags cmnRequestFlags = 0;
370 	dc_integrity_crc_fw_t *pDataIntegrityCrcs = NULL;
371 
372 	cmnRequestFlags =
373 	    ICP_QAT_FW_COMN_FLAGS_BUILD(DC_DEFAULT_QAT_PTR_TYPE,
374 					QAT_COMN_CD_FLD_TYPE_16BYTE_DATA);
375 
376 	pService = (sal_compression_service_t *)dcInstance;
377 
378 	secureRam = pService->comp_device_data.useDevRam;
379 
380 	LAC_CHECK_NULL_PARAM(pSessionHandle);
381 	LAC_CHECK_NULL_PARAM(pSessionData);
382 
383 	/* Check that the parameters defined in the pSessionData are valid for
384 	 * the
385 	 * device */
386 	if (CPA_STATUS_SUCCESS !=
387 	    dcCheckSessionData(pSessionData, dcInstance)) {
388 		return CPA_STATUS_INVALID_PARAM;
389 	}
390 
391 	if ((CPA_DC_STATEFUL == pSessionData->sessState) &&
392 	    (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection)) {
393 		QAT_UTILS_LOG("Stateful sessions are not supported.\n");
394 		return CPA_STATUS_UNSUPPORTED;
395 	}
396 
397 	if (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) {
398 		/* Test if DRAM is available for the intermediate buffers */
399 		if ((NULL == pService->pInterBuffPtrsArray) &&
400 		    (0 == pService->pInterBuffPtrsArrayPhyAddr)) {
401 			if (CPA_DC_ASB_STATIC_DYNAMIC ==
402 			    pSessionData->autoSelectBestHuffmanTree) {
403 				/* Define the Huffman tree as static */
404 				pSessionData->huffType = CPA_DC_HT_STATIC;
405 			} else {
406 				QAT_UTILS_LOG(
407 				    "No buffer defined for this instance - see cpaDcStartInstance.\n");
408 				return CPA_STATUS_RESOURCE;
409 			}
410 		}
411 	}
412 
413 	if ((CPA_DC_STATEFUL == pSessionData->sessState) &&
414 	    (CPA_DC_DEFLATE == pSessionData->compType)) {
415 		/* Get the size of the context buffer */
416 		status =
417 		    dcGetContextSize(dcInstance, pSessionData, &minContextSize);
418 
419 		if (CPA_STATUS_SUCCESS != status) {
420 			QAT_UTILS_LOG(
421 			    "Unable to get the context size of the session.\n");
422 			return CPA_STATUS_FAIL;
423 		}
424 
425 		/* If the minContextSize is zero it means we will not save or
426 		 * restore
427 		 * any history */
428 		if (0 != minContextSize) {
429 			Cpa64U contextBuffSize = 0;
430 
431 			LAC_CHECK_NULL_PARAM(pContextBuffer);
432 
433 			if (LacBuffDesc_BufferListVerify(
434 				pContextBuffer,
435 				&contextBuffSize,
436 				LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) {
437 				return CPA_STATUS_INVALID_PARAM;
438 			}
439 
440 			/* Ensure that the context buffer size is greater or
441 			 * equal
442 			 * to minContextSize */
443 			if (contextBuffSize < minContextSize) {
444 				QAT_UTILS_LOG(
445 				    "Context buffer size should be greater or equal to %d.\n",
446 				    minContextSize);
447 				return CPA_STATUS_INVALID_PARAM;
448 			}
449 		}
450 	}
451 
452 	/* Re-align the session structure to 64 byte alignment */
453 	physAddress =
454 	    LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info,
455 					 (Cpa8U *)pSessionHandle +
456 					     sizeof(void *));
457 
458 	if (physAddress == 0) {
459 		QAT_UTILS_LOG(
460 		    "Unable to get the physical address of the session.\n");
461 		return CPA_STATUS_FAIL;
462 	}
463 
464 	physAddressAligned =
465 	    (CpaPhysicalAddr)LAC_ALIGN_POW2_ROUNDUP(physAddress,
466 						    LAC_64BYTE_ALIGNMENT);
467 
468 	pSessionDesc = (dc_session_desc_t *)
469 	    /* Move the session pointer by the physical offset
470 	    between aligned and unaligned memory */
471 	    ((Cpa8U *)pSessionHandle + sizeof(void *) +
472 	     (physAddressAligned - physAddress));
473 
474 	/* Save the aligned pointer in the first bytes (size of LAC_ARCH_UINT)
475 	 * of the session memory */
476 	*((LAC_ARCH_UINT *)pSessionHandle) = (LAC_ARCH_UINT)pSessionDesc;
477 
478 	/* Zero the compression session */
479 	LAC_OS_BZERO(pSessionDesc, sizeof(dc_session_desc_t));
480 
481 	/* Write the buffer descriptor for context/history */
482 	if (0 != minContextSize) {
483 		status = LacBuffDesc_BufferListDescWrite(
484 		    pContextBuffer,
485 		    &contextAddrPhys,
486 		    CPA_FALSE,
487 		    &(pService->generic_service_info));
488 
489 		if (status != CPA_STATUS_SUCCESS) {
490 			return status;
491 		}
492 
493 		pSessionDesc->pContextBuffer = pContextBuffer;
494 		pSessionDesc->historyBuffSize = historySize;
495 	}
496 
497 	pSessionDesc->cumulativeConsumedBytes = 0;
498 
499 	/* Initialise pSessionDesc */
500 	pSessionDesc->requestType = DC_REQUEST_FIRST;
501 	pSessionDesc->huffType = pSessionData->huffType;
502 	pSessionDesc->compType = pSessionData->compType;
503 	pSessionDesc->checksumType = pSessionData->checksum;
504 	pSessionDesc->autoSelectBestHuffmanTree =
505 	    pSessionData->autoSelectBestHuffmanTree;
506 	pSessionDesc->sessDirection = pSessionData->sessDirection;
507 	pSessionDesc->sessState = pSessionData->sessState;
508 	pSessionDesc->compLevel = pSessionData->compLevel;
509 	pSessionDesc->isDcDp = CPA_FALSE;
510 	pSessionDesc->minContextSize = minContextSize;
511 	pSessionDesc->isSopForCompressionProcessed = CPA_FALSE;
512 	pSessionDesc->isSopForDecompressionProcessed = CPA_FALSE;
513 
514 	if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
515 		pSessionDesc->previousChecksum = 1;
516 	} else {
517 		pSessionDesc->previousChecksum = 0;
518 	}
519 
520 	if (CPA_DC_STATEFUL == pSessionData->sessState) {
521 		/* Init the spinlock used to lock the access to the number of
522 		 * stateful
523 		 * in-flight requests */
524 		status = LAC_SPINLOCK_INIT(&(pSessionDesc->sessionLock));
525 		if (CPA_STATUS_SUCCESS != status) {
526 			QAT_UTILS_LOG(
527 			    "Spinlock init failed for sessionLock.\n");
528 			return CPA_STATUS_RESOURCE;
529 		}
530 	}
531 
532 	/* For asynchronous - use the user supplied callback
533 	 * for synchronous - use the internal synchronous callback */
534 	pSessionDesc->pCompressionCb = ((void *)NULL != (void *)callbackFn) ?
535 	    callbackFn :
536 	    LacSync_GenWakeupSyncCaller;
537 
538 	/* Reset the pending callback counters */
539 	qatUtilsAtomicSet(0, &pSessionDesc->pendingStatelessCbCount);
540 	qatUtilsAtomicSet(0, &pSessionDesc->pendingStatefulCbCount);
541 	pSessionDesc->pendingDpStatelessCbCount = 0;
542 
543 	if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) {
544 		if (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) {
545 			/* Populate the compression section of the content
546 			 * descriptor */
547 			dcCompContentDescPopulate(pService,
548 						  pSessionDesc,
549 						  contextAddrPhys,
550 						  &(pSessionDesc->reqCacheComp),
551 						  ICP_QAT_FW_SLICE_XLAT,
552 						  DC_COMPRESSION_REQUEST);
553 
554 			/* Populate the translator section of the content
555 			 * descriptor */
556 			dcTransContentDescPopulate(
557 			    &(pSessionDesc->reqCacheComp),
558 			    ICP_QAT_FW_SLICE_DRAM_WR);
559 
560 			if (0 != pService->pInterBuffPtrsArrayPhyAddr) {
561 				pReqCache = &(pSessionDesc->reqCacheComp);
562 
563 				pReqCache->u1.xlt_pars.inter_buff_ptr =
564 				    pService->pInterBuffPtrsArrayPhyAddr;
565 			}
566 		} else {
567 			dcCompContentDescPopulate(pService,
568 						  pSessionDesc,
569 						  contextAddrPhys,
570 						  &(pSessionDesc->reqCacheComp),
571 						  ICP_QAT_FW_SLICE_DRAM_WR,
572 						  DC_COMPRESSION_REQUEST);
573 		}
574 	}
575 
576 	/* Populate the compression section of the content descriptor for
577 	 * the decompression case or combined */
578 	if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) {
579 		dcCompContentDescPopulate(pService,
580 					  pSessionDesc,
581 					  contextAddrPhys,
582 					  &(pSessionDesc->reqCacheDecomp),
583 					  ICP_QAT_FW_SLICE_DRAM_WR,
584 					  DC_DECOMPRESSION_REQUEST);
585 	}
586 
587 	if (CPA_DC_STATEFUL == pSessionData->sessState) {
588 		sessType = ICP_QAT_FW_COMP_STATEFUL_SESSION;
589 
590 		LAC_OS_BZERO(&pSessionDesc->stateRegistersComp,
591 			     sizeof(pSessionDesc->stateRegistersComp));
592 
593 		LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp,
594 			     sizeof(pSessionDesc->stateRegistersDecomp));
595 	}
596 
597 	/* Get physical address of E2E CRC buffer */
598 	pSessionDesc->physDataIntegrityCrcs = (icp_qat_addr_width_t)
599 	    LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info,
600 					 &pSessionDesc->dataIntegrityCrcs);
601 	if (0 == pSessionDesc->physDataIntegrityCrcs) {
602 		QAT_UTILS_LOG(
603 		    "Unable to get the physical address of Data Integrity buffer.\n");
604 		return CPA_STATUS_FAIL;
605 	}
606 	/* Initialize default CRC parameters */
607 	pDataIntegrityCrcs = &pSessionDesc->dataIntegrityCrcs;
608 	pDataIntegrityCrcs->crc32 = 0;
609 	pDataIntegrityCrcs->adler32 = 1;
610 	pDataIntegrityCrcs->oCrc32Cpr = DC_INVALID_CRC;
611 	pDataIntegrityCrcs->iCrc32Cpr = DC_INVALID_CRC;
612 	pDataIntegrityCrcs->oCrc32Xlt = DC_INVALID_CRC;
613 	pDataIntegrityCrcs->iCrc32Xlt = DC_INVALID_CRC;
614 	pDataIntegrityCrcs->xorFlags = DC_XOR_FLAGS_DEFAULT;
615 	pDataIntegrityCrcs->crcPoly = DC_CRC_POLY_DEFAULT;
616 	pDataIntegrityCrcs->xorOut = DC_XOR_OUT_DEFAULT;
617 
618 	/* Initialise seed checksums */
619 	pSessionDesc->seedSwCrc.swCrcI = 0;
620 	pSessionDesc->seedSwCrc.swCrcO = 0;
621 
622 	/* Populate the cmdFlags */
623 	switch (pSessionDesc->autoSelectBestHuffmanTree) {
624 	case CPA_DC_ASB_DISABLED:
625 		break;
626 	case CPA_DC_ASB_STATIC_DYNAMIC:
627 		autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST;
628 		break;
629 	case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS:
630 		autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST;
631 		enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST;
632 		break;
633 	case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS:
634 		autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST;
635 		enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST;
636 		disableType0EnhancedAutoSelectBest =
637 		    ICP_QAT_FW_COMP_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST;
638 		break;
639 	default:
640 		break;
641 	}
642 
643 	rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
644 	    ICP_QAT_FW_COMP_SOP,
645 	    ICP_QAT_FW_COMP_EOP,
646 	    ICP_QAT_FW_COMP_BFINAL,
647 	    ICP_QAT_FW_COMP_NO_CNV,
648 	    ICP_QAT_FW_COMP_NO_CNV_RECOVERY,
649 	    ICP_QAT_FW_COMP_CRC_MODE_LEGACY);
650 
651 	cmdFlags =
652 	    ICP_QAT_FW_COMP_FLAGS_BUILD(sessType,
653 					autoSelectBest,
654 					enhancedAutoSelectBest,
655 					disableType0EnhancedAutoSelectBest,
656 					secureRam);
657 
658 	if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) {
659 		if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) {
660 			dcCmdId = (icp_qat_fw_la_cmd_id_t)(
661 			    ICP_QAT_FW_COMP_CMD_DYNAMIC);
662 		}
663 
664 		pReqCache = &(pSessionDesc->reqCacheComp);
665 		pReqCache->comp_pars.req_par_flags = rpCmdFlags;
666 		pReqCache->comp_pars.crc.legacy.initial_adler = 1;
667 		pReqCache->comp_pars.crc.legacy.initial_crc32 = 0;
668 
669 		/* Populate header of the common request message */
670 		SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache,
671 				      ICP_QAT_FW_COMN_REQ_CPM_FW_COMP,
672 				      (uint8_t)dcCmdId,
673 				      cmnRequestFlags,
674 				      cmdFlags);
675 	}
676 
677 	if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) {
678 		dcCmdId =
679 		    (icp_qat_fw_la_cmd_id_t)(ICP_QAT_FW_COMP_CMD_DECOMPRESS);
680 		pReqCache = &(pSessionDesc->reqCacheDecomp);
681 		pReqCache->comp_pars.req_par_flags = rpCmdFlags;
682 		pReqCache->comp_pars.crc.legacy.initial_adler = 1;
683 		pReqCache->comp_pars.crc.legacy.initial_crc32 = 0;
684 
685 		/* Populate header of the common request message */
686 		SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache,
687 				      ICP_QAT_FW_COMN_REQ_CPM_FW_COMP,
688 				      (uint8_t)dcCmdId,
689 				      cmnRequestFlags,
690 				      cmdFlags);
691 	}
692 
693 	return status;
694 }
695 
696 CpaStatus
697 cpaDcInitSession(CpaInstanceHandle dcInstance,
698 		 CpaDcSessionHandle pSessionHandle,
699 		 CpaDcSessionSetupData *pSessionData,
700 		 CpaBufferList *pContextBuffer,
701 		 CpaDcCallbackFn callbackFn)
702 {
703 	CpaInstanceHandle insHandle = NULL;
704 	sal_compression_service_t *pService = NULL;
705 
706 	if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
707 		insHandle = dcGetFirstHandle();
708 	} else {
709 		insHandle = dcInstance;
710 	}
711 
712 	LAC_CHECK_INSTANCE_HANDLE(insHandle);
713 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
714 
715 	pService = (sal_compression_service_t *)insHandle;
716 
717 	/* Check if SAL is initialised otherwise return an error */
718 	SAL_RUNNING_CHECK(pService);
719 
720 	return dcInitSession(insHandle,
721 			     pSessionHandle,
722 			     pSessionData,
723 			     pContextBuffer,
724 			     callbackFn);
725 }
726 
727 CpaStatus
728 cpaDcResetSession(const CpaInstanceHandle dcInstance,
729 		  CpaDcSessionHandle pSessionHandle)
730 {
731 	CpaStatus status = CPA_STATUS_SUCCESS;
732 	CpaInstanceHandle insHandle = NULL;
733 	dc_session_desc_t *pSessionDesc = NULL;
734 	Cpa64U numPendingStateless = 0;
735 	Cpa64U numPendingStateful = 0;
736 	icp_comms_trans_handle trans_handle = NULL;
737 	LAC_CHECK_NULL_PARAM(pSessionHandle);
738 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
739 	LAC_CHECK_NULL_PARAM(pSessionDesc);
740 
741 	if (CPA_TRUE == pSessionDesc->isDcDp) {
742 		insHandle = dcInstance;
743 	} else {
744 		if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
745 			insHandle = dcGetFirstHandle();
746 		} else {
747 			insHandle = dcInstance;
748 		}
749 	}
750 	LAC_CHECK_NULL_PARAM(insHandle);
751 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
752 	/* Check if SAL is running otherwise return an error */
753 	SAL_RUNNING_CHECK(insHandle);
754 	if (CPA_TRUE == pSessionDesc->isDcDp) {
755 		trans_handle = ((sal_compression_service_t *)dcInstance)
756 				   ->trans_handle_compression_tx;
757 		if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) {
758 			/* Process the remaining messages on the ring */
759 			SalQatMsg_updateQueueTail(trans_handle);
760 			QAT_UTILS_LOG(
761 			    "There are remaining messages on the ring\n");
762 			return CPA_STATUS_RETRY;
763 		}
764 
765 		/* Check if there are stateless pending requests */
766 		if (0 != pSessionDesc->pendingDpStatelessCbCount) {
767 			QAT_UTILS_LOG(
768 			    "There are %llu stateless DP requests pending.\n",
769 			    (unsigned long long)
770 				pSessionDesc->pendingDpStatelessCbCount);
771 			return CPA_STATUS_RETRY;
772 		}
773 	} else {
774 		numPendingStateless =
775 		    qatUtilsAtomicGet(&(pSessionDesc->pendingStatelessCbCount));
776 		numPendingStateful =
777 		    qatUtilsAtomicGet(&(pSessionDesc->pendingStatefulCbCount));
778 		/* Check if there are stateless pending requests */
779 		if (0 != numPendingStateless) {
780 			QAT_UTILS_LOG(
781 			    "There are %llu stateless requests pending.\n",
782 			    (unsigned long long)numPendingStateless);
783 			return CPA_STATUS_RETRY;
784 		}
785 		/* Check if there are stateful pending requests */
786 		if (0 != numPendingStateful) {
787 			QAT_UTILS_LOG(
788 			    "There are %llu stateful requests pending.\n",
789 			    (unsigned long long)numPendingStateful);
790 			return CPA_STATUS_RETRY;
791 		}
792 
793 		/* Reset pSessionDesc */
794 		pSessionDesc->requestType = DC_REQUEST_FIRST;
795 		pSessionDesc->cumulativeConsumedBytes = 0;
796 		if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
797 			pSessionDesc->previousChecksum = 1;
798 		} else {
799 			pSessionDesc->previousChecksum = 0;
800 		}
801 	}
802 	/* Reset the pending callback counters */
803 	qatUtilsAtomicSet(0, &pSessionDesc->pendingStatelessCbCount);
804 	qatUtilsAtomicSet(0, &pSessionDesc->pendingStatefulCbCount);
805 	pSessionDesc->pendingDpStatelessCbCount = 0;
806 	if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
807 		LAC_OS_BZERO(&pSessionDesc->stateRegistersComp,
808 			     sizeof(pSessionDesc->stateRegistersComp));
809 		LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp,
810 			     sizeof(pSessionDesc->stateRegistersDecomp));
811 	}
812 	return status;
813 }
814 
815 CpaStatus
816 cpaDcRemoveSession(const CpaInstanceHandle dcInstance,
817 		   CpaDcSessionHandle pSessionHandle)
818 {
819 	CpaStatus status = CPA_STATUS_SUCCESS;
820 	CpaInstanceHandle insHandle = NULL;
821 	dc_session_desc_t *pSessionDesc = NULL;
822 	Cpa64U numPendingStateless = 0;
823 	Cpa64U numPendingStateful = 0;
824 	icp_comms_trans_handle trans_handle = NULL;
825 
826 	LAC_CHECK_NULL_PARAM(pSessionHandle);
827 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
828 	LAC_CHECK_NULL_PARAM(pSessionDesc);
829 
830 	if (CPA_TRUE == pSessionDesc->isDcDp) {
831 		insHandle = dcInstance;
832 	} else {
833 		if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
834 			insHandle = dcGetFirstHandle();
835 		} else {
836 			insHandle = dcInstance;
837 		}
838 	}
839 
840 	LAC_CHECK_NULL_PARAM(insHandle);
841 	SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
842 
843 	/* Check if SAL is running otherwise return an error */
844 	SAL_RUNNING_CHECK(insHandle);
845 
846 	if (CPA_TRUE == pSessionDesc->isDcDp) {
847 		trans_handle = ((sal_compression_service_t *)insHandle)
848 				   ->trans_handle_compression_tx;
849 
850 		if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) {
851 			/* Process the remaining messages on the ring */
852 			SalQatMsg_updateQueueTail(trans_handle);
853 			QAT_UTILS_LOG(
854 			    "There are remaining messages on the ring.\n");
855 			return CPA_STATUS_RETRY;
856 		}
857 
858 		/* Check if there are stateless pending requests */
859 		if (0 != pSessionDesc->pendingDpStatelessCbCount) {
860 			QAT_UTILS_LOG(
861 			    "There are %llu stateless DP requests pending.\n",
862 			    (unsigned long long)
863 				pSessionDesc->pendingDpStatelessCbCount);
864 			return CPA_STATUS_RETRY;
865 		}
866 	} else {
867 		numPendingStateless =
868 		    qatUtilsAtomicGet(&(pSessionDesc->pendingStatelessCbCount));
869 		numPendingStateful =
870 		    qatUtilsAtomicGet(&(pSessionDesc->pendingStatefulCbCount));
871 
872 		/* Check if there are stateless pending requests */
873 		if (0 != numPendingStateless) {
874 			QAT_UTILS_LOG(
875 			    "There are %llu stateless requests pending.\n",
876 			    (unsigned long long)numPendingStateless);
877 			status = CPA_STATUS_RETRY;
878 		}
879 
880 		/* Check if there are stateful pending requests */
881 		if (0 != numPendingStateful) {
882 			QAT_UTILS_LOG(
883 			    "There are %llu stateful requests pending.\n",
884 			    (unsigned long long)numPendingStateful);
885 			status = CPA_STATUS_RETRY;
886 		}
887 		if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
888 		    (CPA_STATUS_SUCCESS == status)) {
889 			if (CPA_STATUS_SUCCESS !=
890 			    LAC_SPINLOCK_DESTROY(
891 				&(pSessionDesc->sessionLock))) {
892 				QAT_UTILS_LOG(
893 				    "Failed to destory session lock.\n");
894 			}
895 		}
896 	}
897 
898 	return status;
899 }
900 
901 CpaStatus
902 dcGetSessionSize(CpaInstanceHandle dcInstance,
903 		 CpaDcSessionSetupData *pSessionData,
904 		 Cpa32U *pSessionSize,
905 		 Cpa32U *pContextSize)
906 {
907 
908 	CpaStatus status = CPA_STATUS_SUCCESS;
909 	CpaInstanceHandle insHandle = NULL;
910 
911 	if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
912 		insHandle = dcGetFirstHandle();
913 	} else {
914 		insHandle = dcInstance;
915 	}
916 
917 	/* Check parameters */
918 	LAC_CHECK_NULL_PARAM(insHandle);
919 	LAC_CHECK_NULL_PARAM(pSessionData);
920 	LAC_CHECK_NULL_PARAM(pSessionSize);
921 
922 	if (dcCheckSessionData(pSessionData, insHandle) != CPA_STATUS_SUCCESS) {
923 		return CPA_STATUS_INVALID_PARAM;
924 	}
925 
926 	/* Get session size for session data */
927 	*pSessionSize = sizeof(dc_session_desc_t) + LAC_64BYTE_ALIGNMENT +
928 	    sizeof(LAC_ARCH_UINT);
929 
930 	if (NULL != pContextSize) {
931 		status =
932 		    dcGetContextSize(insHandle, pSessionData, pContextSize);
933 
934 		if (CPA_STATUS_SUCCESS != status) {
935 			QAT_UTILS_LOG(
936 			    "Unable to get the context size of the session.\n");
937 			return CPA_STATUS_FAIL;
938 		}
939 	}
940 
941 	return CPA_STATUS_SUCCESS;
942 }
943 
944 CpaStatus
945 cpaDcGetSessionSize(CpaInstanceHandle dcInstance,
946 		    CpaDcSessionSetupData *pSessionData,
947 		    Cpa32U *pSessionSize,
948 		    Cpa32U *pContextSize)
949 {
950 
951 	LAC_CHECK_NULL_PARAM(pContextSize);
952 
953 	return dcGetSessionSize(dcInstance,
954 				pSessionData,
955 				pSessionSize,
956 				pContextSize);
957 }
958