1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /**
4  *****************************************************************************
5  * @file dc_dp.c
6  *
7  * @defgroup cpaDcDp Data Compression Data Plane API
8  *
9  * @ingroup cpaDcDp
10  *
11  * @description
12  *      Implementation of the Data Compression DP operations.
13  *
14  *****************************************************************************/
15 
16 /*
17 *******************************************************************************
18 * Include public/global header files
19 *******************************************************************************
20 */
21 #include "cpa.h"
22 #include "cpa_dc.h"
23 #include "cpa_dc_dp.h"
24 
25 #include "icp_qat_fw_comp.h"
26 
27 /*
28 *******************************************************************************
29 * Include private header files
30 *******************************************************************************
31 */
32 #include "dc_session.h"
33 #include "dc_datapath.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 "lac_sal.h"
39 #include "lac_sync.h"
40 #include "sal_service_state.h"
41 #include "sal_qat_cmn_msg.h"
42 #include "icp_sal_poll.h"
43 #include "sal_hw_gen.h"
44 
45 /**
46  *****************************************************************************
47  * @ingroup cpaDcDp
48  *      Check that pOpData is valid
49  *
50  * @description
51  *      Check that all the parameters defined in the pOpData are valid
52  *
53  * @param[in]       pOpData          Pointer to a structure containing the
54  *                                   request parameters
55  *
56  * @retval CPA_STATUS_SUCCESS        Function executed successfully
57  * @retval CPA_STATUS_INVALID_PARAM  Invalid parameter passed in
58  *
59  *****************************************************************************/
60 static CpaStatus
61 dcDataPlaneParamCheck(const CpaDcDpOpData *pOpData)
62 {
63 	sal_compression_service_t *pService = NULL;
64 	dc_session_desc_t *pSessionDesc = NULL;
65 
66 	LAC_CHECK_NULL_PARAM(pOpData);
67 	LAC_CHECK_NULL_PARAM(pOpData->dcInstance);
68 	LAC_CHECK_NULL_PARAM(pOpData->pSessionHandle);
69 
70 	/* Ensure this is a compression instance */
71 	SAL_CHECK_INSTANCE_TYPE(pOpData->dcInstance,
72 				SAL_SERVICE_TYPE_COMPRESSION);
73 
74 	pService = (sal_compression_service_t *)(pOpData->dcInstance);
75 
76 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle);
77 	if (NULL == pSessionDesc) {
78 		QAT_UTILS_LOG("Session handle not as expected.\n");
79 		return CPA_STATUS_INVALID_PARAM;
80 	}
81 
82 	if (CPA_FALSE == pSessionDesc->isDcDp) {
83 		QAT_UTILS_LOG("The session type should be data plane.\n");
84 		return CPA_STATUS_INVALID_PARAM;
85 	}
86 
87 	/* Compressing zero byte is not supported */
88 	if ((CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) &&
89 	    (0 == pOpData->bufferLenToCompress)) {
90 		QAT_UTILS_LOG("The source buffer length to compress needs to "
91 			      "be greater than zero byte.\n");
92 		return CPA_STATUS_INVALID_PARAM;
93 	}
94 
95 	if (pOpData->sessDirection > CPA_DC_DIR_DECOMPRESS) {
96 		QAT_UTILS_LOG("Invalid direction of operation.\n");
97 		return CPA_STATUS_INVALID_PARAM;
98 	}
99 
100 	if (0 == pOpData->srcBuffer) {
101 		QAT_UTILS_LOG("Invalid srcBuffer\n");
102 		return CPA_STATUS_INVALID_PARAM;
103 	}
104 	if (0 == pOpData->destBuffer) {
105 		QAT_UTILS_LOG("Invalid destBuffer\n");
106 		return CPA_STATUS_INVALID_PARAM;
107 	}
108 	if (pOpData->srcBuffer == pOpData->destBuffer) {
109 		QAT_UTILS_LOG("In place operation is not supported.\n");
110 		return CPA_STATUS_INVALID_PARAM;
111 	}
112 	if (0 == pOpData->thisPhys) {
113 		QAT_UTILS_LOG("Invalid thisPhys\n");
114 		return CPA_STATUS_INVALID_PARAM;
115 	}
116 
117 	if ((CPA_TRUE != pOpData->compressAndVerify) &&
118 	    (CPA_FALSE != pOpData->compressAndVerify)) {
119 		QAT_UTILS_LOG("Invalid compressAndVerify\n");
120 		return CPA_STATUS_INVALID_PARAM;
121 	}
122 	if ((CPA_TRUE == pOpData->compressAndVerify) &&
123 	    !(pService->generic_service_info.dcExtendedFeatures &
124 	      DC_CNV_EXTENDED_CAPABILITY)) {
125 		QAT_UTILS_LOG("Invalid compressAndVerify, no CNV capability\n");
126 		return CPA_STATUS_UNSUPPORTED;
127 	}
128 	if ((CPA_TRUE != pOpData->compressAndVerifyAndRecover) &&
129 	    (CPA_FALSE != pOpData->compressAndVerifyAndRecover)) {
130 		QAT_UTILS_LOG("Invalid compressAndVerifyAndRecover\n");
131 		return CPA_STATUS_INVALID_PARAM;
132 	}
133 	if ((CPA_TRUE == pOpData->compressAndVerifyAndRecover) &&
134 	    (CPA_FALSE == pOpData->compressAndVerify)) {
135 		QAT_UTILS_LOG("CnVnR option set without setting CnV\n");
136 		return CPA_STATUS_INVALID_PARAM;
137 	}
138 	if ((CPA_TRUE == pOpData->compressAndVerifyAndRecover) &&
139 	    !(pService->generic_service_info.dcExtendedFeatures &
140 	      DC_CNVNR_EXTENDED_CAPABILITY)) {
141 		QAT_UTILS_LOG(
142 		    "Invalid CnVnR option set and no CnVnR capability.\n");
143 		return CPA_STATUS_UNSUPPORTED;
144 	}
145 
146 	if ((CPA_DP_BUFLIST == pOpData->srcBufferLen) &&
147 	    (CPA_DP_BUFLIST != pOpData->destBufferLen)) {
148 		QAT_UTILS_LOG(
149 		    "The source and destination buffers need to be of the same type (both flat buffers or buffer lists).\n");
150 		return CPA_STATUS_INVALID_PARAM;
151 	}
152 	if ((CPA_DP_BUFLIST != pOpData->srcBufferLen) &&
153 	    (CPA_DP_BUFLIST == pOpData->destBufferLen)) {
154 		QAT_UTILS_LOG(
155 		    "The source and destination buffers need to be of the same type (both flat buffers or buffer lists).\n");
156 		return CPA_STATUS_INVALID_PARAM;
157 	}
158 
159 	if (CPA_DP_BUFLIST != pOpData->srcBufferLen) {
160 		if (pOpData->srcBufferLen < pOpData->bufferLenToCompress) {
161 			QAT_UTILS_LOG(
162 			    "srcBufferLen is smaller than bufferLenToCompress.\n");
163 			return CPA_STATUS_INVALID_PARAM;
164 		}
165 
166 		if (pOpData->destBufferLen < pOpData->bufferLenForData) {
167 			QAT_UTILS_LOG(
168 			    "destBufferLen is smaller than bufferLenForData.\n");
169 			return CPA_STATUS_INVALID_PARAM;
170 		}
171 	} else {
172 		/* We are assuming that there is enough memory in the source and
173 		 * destination buffer lists. We only receive physical addresses
174 		 * of the buffers so we are unable to test it here */
175 		LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->srcBuffer);
176 		LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->destBuffer);
177 	}
178 
179 	LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->thisPhys);
180 
181 	if ((CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) ||
182 	    (CPA_DC_DIR_COMBINED == pSessionDesc->sessDirection)) {
183 		if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) {
184 			/* Check if Intermediate Buffer Array pointer is NULL */
185 			if (isDcGen2x(pService) &&
186 			    ((0 == pService->pInterBuffPtrsArrayPhyAddr) ||
187 			     (NULL == pService->pInterBuffPtrsArray))) {
188 				QAT_UTILS_LOG(
189 				    "No intermediate buffer defined for this instance - see cpaDcStartInstance.\n");
190 				return CPA_STATUS_INVALID_PARAM;
191 			}
192 
193 			/* Ensure that the destination buffer length for data is
194 			 * greater
195 			 * or equal to 128B */
196 			if (pOpData->bufferLenForData <
197 			    DC_DEST_BUFFER_DYN_MIN_SIZE) {
198 				QAT_UTILS_LOG(
199 				    "Destination buffer length for data should be greater or equal to 128B.\n");
200 				return CPA_STATUS_INVALID_PARAM;
201 			}
202 		} else {
203 			/* Ensure that the destination buffer length for data is
204 			 * greater
205 			 * or equal to min output buffsize */
206 			if (pOpData->bufferLenForData <
207 			    pService->comp_device_data.minOutputBuffSize) {
208 				QAT_UTILS_LOG(
209 				    "Destination buffer size should be greater or equal to %d bytes.\n",
210 				    pService->comp_device_data
211 					.minOutputBuffSize);
212 				return CPA_STATUS_INVALID_PARAM;
213 			}
214 		}
215 	}
216 
217 	return CPA_STATUS_SUCCESS;
218 }
219 
220 /**
221  *****************************************************************************
222  * @ingroup cpaDcDp
223  *      Partial-read parameters validation utility.
224  *
225  * @description
226  *      Basic check that all partial-read related parameters provided by
227  *      caller are valid.
228  *
229  * @param[in]       pOpData          Pointer to a structure containing the
230  *                                   request parameters
231  * @param[in]       pPartReadData    Pointer to a structure containing the
232  *                                   partial-read request parameters.
233  *
234  * @retval CPA_STATUS_SUCCESS        Function executed successfully
235  * @retval CPA_STATUS_INVALID_PARAM  Invalid parameter passed in
236  *
237  *****************************************************************************/
238 static CpaStatus
239 dcDataPlanePartReadCheck(CpaDcDpOpData *pOpData,
240 			 CpaDcDpPartialReadData *pPartReadData)
241 {
242 	sal_compression_service_t *pService = NULL;
243 
244 	LAC_CHECK_NULL_PARAM(pPartReadData);
245 
246 	pService = (sal_compression_service_t *)(pOpData->dcInstance);
247 
248 	if (!isDcGen4x(pService)) {
249 		/* Extended features are not supported prior Gen4 */
250 		return CPA_STATUS_UNSUPPORTED;
251 	}
252 
253 	if (pOpData->sessDirection == CPA_DC_DIR_COMPRESS) {
254 		/* Decompression specific feature */
255 		return CPA_STATUS_INVALID_PARAM;
256 	}
257 
258 	if (pPartReadData->length > pOpData->bufferLenForData) {
259 		QAT_UTILS_LOG(
260 		    "Partial read data length can not be greater than the destination buffer size\n");
261 		return CPA_STATUS_INVALID_PARAM;
262 	}
263 
264 	return CPA_STATUS_SUCCESS;
265 }
266 
267 /**
268  *****************************************************************************
269  * @ingroup cpaDcDp
270  *      Zero-padding parameters validation utility.
271  *
272  * @description
273  *      Basic check that all zero-padding related parameters provided by
274  *      caller are valid.
275  *
276  * @param[in]       pOpData          Pointer to a structure containing the
277  *                                   request parameters.
278  *
279  * @retval CPA_STATUS_SUCCESS        Function executed successfully
280  * @retval CPA_STATUS_INVALID_PARAM  Invalid parameter passed in
281  * @retval CPA_STATUS_NOT_SUPPORTED  Feature not supported
282  *
283  *****************************************************************************/
284 static CpaStatus
285 dcDataPlaneZeroPadCheck(CpaDcDpOpData *pOpData)
286 {
287 	sal_compression_service_t *pService = NULL;
288 
289 	pService = (sal_compression_service_t *)(pOpData->dcInstance);
290 
291 	if (!isDcGen4x(pService)) {
292 		/* Extended features are not supported prior Gen4 */
293 		return CPA_STATUS_UNSUPPORTED;
294 	}
295 
296 	if (pOpData->sessDirection == CPA_DC_DIR_DECOMPRESS) {
297 		/* Compression specific feature */
298 		return CPA_STATUS_INVALID_PARAM;
299 	}
300 
301 	return CPA_STATUS_SUCCESS;
302 }
303 CpaStatus
304 cpaDcDpGetSessionSize(CpaInstanceHandle dcInstance,
305 		      CpaDcSessionSetupData *pSessionData,
306 		      Cpa32U *pSessionSize)
307 {
308 	return dcGetSessionSize(dcInstance, pSessionData, pSessionSize, NULL);
309 }
310 
311 CpaStatus
312 cpaDcDpInitSession(CpaInstanceHandle dcInstance,
313 		   CpaDcSessionHandle pSessionHandle,
314 		   CpaDcSessionSetupData *pSessionData)
315 {
316 	CpaStatus status = CPA_STATUS_SUCCESS;
317 	dc_session_desc_t *pSessionDesc = NULL;
318 	sal_compression_service_t *pService = NULL;
319 
320 	LAC_CHECK_INSTANCE_HANDLE(dcInstance);
321 	SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION);
322 
323 	pService = (sal_compression_service_t *)dcInstance;
324 
325 	/* Check if SAL is initialised otherwise return an error */
326 	SAL_RUNNING_CHECK(pService);
327 
328 	/* Stateful is not supported */
329 	if (CPA_DC_STATELESS != pSessionData->sessState) {
330 		QAT_UTILS_LOG("Invalid sessState value\n");
331 		return CPA_STATUS_INVALID_PARAM;
332 	}
333 
334 	status =
335 	    dcInitSession(dcInstance, pSessionHandle, pSessionData, NULL, NULL);
336 	if (CPA_STATUS_SUCCESS == status) {
337 		pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
338 		pSessionDesc->isDcDp = CPA_TRUE;
339 
340 		ICP_QAT_FW_COMN_PTR_TYPE_SET(
341 		    pSessionDesc->reqCacheDecomp.comn_hdr.comn_req_flags,
342 		    DC_DP_QAT_PTR_TYPE);
343 		ICP_QAT_FW_COMN_PTR_TYPE_SET(
344 		    pSessionDesc->reqCacheComp.comn_hdr.comn_req_flags,
345 		    DC_DP_QAT_PTR_TYPE);
346 	}
347 
348 	return status;
349 }
350 
351 CpaStatus
352 cpaDcDpRemoveSession(const CpaInstanceHandle dcInstance,
353 		     CpaDcSessionHandle pSessionHandle)
354 {
355 	return cpaDcRemoveSession(dcInstance, pSessionHandle);
356 }
357 
358 CpaStatus
359 cpaDcDpUpdateSession(const CpaInstanceHandle dcInstance,
360 		     CpaDcSessionHandle pSessionHandle,
361 		     CpaDcSessionUpdateData *pUpdateSessionData)
362 {
363 	return CPA_STATUS_UNSUPPORTED;
364 }
365 
366 CpaStatus
367 cpaDcDpRegCbFunc(const CpaInstanceHandle dcInstance,
368 		 const CpaDcDpCallbackFn pNewCb)
369 {
370 	sal_compression_service_t *pService = NULL;
371 
372 	LAC_CHECK_NULL_PARAM(dcInstance);
373 	SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION);
374 	LAC_CHECK_NULL_PARAM(pNewCb);
375 
376 	/* Check if SAL is initialised otherwise return an error */
377 	SAL_RUNNING_CHECK(dcInstance);
378 
379 	pService = (sal_compression_service_t *)dcInstance;
380 	pService->pDcDpCb = pNewCb;
381 
382 	return CPA_STATUS_SUCCESS;
383 }
384 
385 /**
386  *****************************************************************************
387  * @ingroup cpaDcDp
388  *
389  * @description
390  *      Writes the message to the ring
391  *
392  * @param[in]       pOpData          Pointer to a structure containing the
393  *                                   request parameters
394  * @param[in]       pCurrentQatMsg   Pointer to current QAT message on the ring
395  *
396  *****************************************************************************/
397 static void
398 dcDpWriteRingMsg(CpaDcDpOpData *pOpData, icp_qat_fw_comp_req_t *pCurrentQatMsg)
399 {
400 	icp_qat_fw_comp_req_t *pReqCache = NULL;
401 	dc_session_desc_t *pSessionDesc = NULL;
402 	Cpa8U bufferFormat;
403 
404 	Cpa8U cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV;
405 	Cpa8U cnvnrCompReq = ICP_QAT_FW_COMP_NO_CNV_RECOVERY;
406 	CpaBoolean cnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX;
407 	sal_compression_service_t *pService = NULL;
408 
409 	pService = (sal_compression_service_t *)(pOpData->dcInstance);
410 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle);
411 
412 	if (CPA_DC_DIR_COMPRESS == pOpData->sessDirection) {
413 		pReqCache = &(pSessionDesc->reqCacheComp);
414 		/* CNV check */
415 		if (CPA_TRUE == pOpData->compressAndVerify) {
416 			cnvDecompReq = ICP_QAT_FW_COMP_CNV;
417 			if (isDcGen4x(pService)) {
418 				cnvErrorInjection =
419 				    pSessionDesc->cnvErrorInjection;
420 			}
421 
422 			/* CNVNR check */
423 			if (CPA_TRUE == pOpData->compressAndVerifyAndRecover) {
424 				cnvnrCompReq = ICP_QAT_FW_COMP_CNV_RECOVERY;
425 			}
426 		}
427 	} else {
428 		pReqCache = &(pSessionDesc->reqCacheDecomp);
429 	}
430 
431 	/* Fills in the template DC ET ring message - cached from the
432 	 * session descriptor */
433 	memcpy((void *)pCurrentQatMsg,
434 	       (void *)(pReqCache),
435 	       (LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES));
436 
437 	if (CPA_DP_BUFLIST == pOpData->srcBufferLen) {
438 		bufferFormat = QAT_COMN_PTR_TYPE_SGL;
439 	} else {
440 		bufferFormat = QAT_COMN_PTR_TYPE_FLAT;
441 	}
442 
443 	pCurrentQatMsg->comp_pars.req_par_flags |=
444 	    ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
445 		ICP_QAT_FW_COMP_NOT_SOP,
446 		ICP_QAT_FW_COMP_NOT_EOP,
447 		ICP_QAT_FW_COMP_NOT_BFINAL,
448 		cnvDecompReq,
449 		cnvnrCompReq,
450 		cnvErrorInjection,
451 		ICP_QAT_FW_COMP_CRC_MODE_LEGACY);
452 
453 	SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pCurrentQatMsg,
454 			      pOpData,
455 			      bufferFormat,
456 			      pOpData->srcBuffer,
457 			      pOpData->destBuffer,
458 			      pOpData->srcBufferLen,
459 			      pOpData->destBufferLen);
460 
461 	pCurrentQatMsg->comp_pars.comp_len = pOpData->bufferLenToCompress;
462 	pCurrentQatMsg->comp_pars.out_buffer_sz = pOpData->bufferLenForData;
463 }
464 
465 /**
466  *****************************************************************************
467  * @ingroup cpaDcDp
468  *
469  * @description
470  *      Updates the request decryptor with optional parameters:
471  *      - partial read specific fields
472  *      - zero-padding specific field
473  *
474  * @param[in]       pOpData          Pointer to a structure containing the
475  *                                   request parameters.
476  * @param[in]       pPartReadData    Pointer to a structure containing the
477  *                                   partial-read request parameters.
478  * @param[in]       zeroPadFlag      Boolean indicator containing the
479  *                                   zero-padding enablement flag.
480  * @param[in]       pCurrentQatMsg   Pointer to current QAT message on the ring.
481  *
482  *****************************************************************************/
483 static void
484 dcDpUpdateRingMsg(CpaDcDpOpData *pOpData,
485 		  CpaDcDpPartialReadData *pPartReadData,
486 		  CpaBoolean zeroPadFlag,
487 		  icp_qat_fw_comp_req_t *pCurrentQatMsg)
488 {
489 	sal_compression_service_t *pService = NULL;
490 
491 	pService = (sal_compression_service_t *)(pOpData->dcInstance);
492 	if (!isDcGen4x(pService)) {
493 		return;
494 	}
495 
496 	/* Partial read settings */
497 	if (NULL != pPartReadData) {
498 		pCurrentQatMsg->u1.partial_decompress
499 		    .partial_decompress_offset = pPartReadData->dataOffset;
500 		pCurrentQatMsg->u1.partial_decompress
501 		    .partial_decompress_length = pPartReadData->length;
502 		ICP_QAT_FW_COMP_PART_DECOMP_SET(
503 		    pCurrentQatMsg->comp_pars.req_par_flags,
504 		    ICP_QAT_FW_COMP_PART_DECOMP);
505 	}
506 	/* Zero padding settings */
507 	if (CPA_TRUE == zeroPadFlag) {
508 		ICP_QAT_FW_COMP_ZEROPAD_SET(
509 		    pCurrentQatMsg->comp_pars.req_par_flags,
510 		    ICP_QAT_FW_COMP_ZEROPAD);
511 	}
512 }
513 
514 static CpaStatus
515 dcDpEnqueueOpBase(CpaDcDpOpData *pOpData,
516 		  CpaDcDpPartialReadData *pPartReadData,
517 		  CpaBoolean zeroPadFlag,
518 		  const CpaBoolean performOpNow)
519 {
520 	icp_qat_fw_comp_req_t *pCurrentQatMsg = NULL;
521 	icp_comms_trans_handle trans_handle = NULL;
522 	dc_session_desc_t *pSessionDesc = NULL;
523 	CpaStatus status = CPA_STATUS_SUCCESS;
524 
525 	status = dcDataPlaneParamCheck(pOpData);
526 	if (CPA_STATUS_SUCCESS != status) {
527 		return status;
528 	}
529 
530 	if (NULL != pPartReadData) {
531 		status = dcDataPlanePartReadCheck(pOpData, pPartReadData);
532 		if (CPA_STATUS_SUCCESS != status) {
533 			return status;
534 		}
535 	}
536 
537 	if (CPA_TRUE == zeroPadFlag) {
538 		status = dcDataPlaneZeroPadCheck(pOpData);
539 		if (CPA_STATUS_SUCCESS != status) {
540 			return status;
541 		}
542 	}
543 
544 	if ((CPA_FALSE == pOpData->compressAndVerify) &&
545 	    (CPA_DC_DIR_COMPRESS == pOpData->sessDirection)) {
546 		return CPA_STATUS_UNSUPPORTED;
547 	}
548 
549 	/* Check if SAL is initialised otherwise return an error */
550 	SAL_RUNNING_CHECK(pOpData->dcInstance);
551 
552 	trans_handle = ((sal_compression_service_t *)pOpData->dcInstance)
553 			   ->trans_handle_compression_tx;
554 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle);
555 
556 	if ((CPA_DC_DIR_COMPRESS == pOpData->sessDirection) &&
557 	    (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection)) {
558 		QAT_UTILS_LOG(
559 		    "The session does not support this direction of operation.\n");
560 		return CPA_STATUS_INVALID_PARAM;
561 	} else if ((CPA_DC_DIR_DECOMPRESS == pOpData->sessDirection) &&
562 		   (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection)) {
563 		QAT_UTILS_LOG(
564 		    "The session does not support this direction of operation.\n");
565 		return CPA_STATUS_INVALID_PARAM;
566 	}
567 
568 	icp_adf_getSingleQueueAddr(trans_handle, (void **)&pCurrentQatMsg);
569 	if (NULL == pCurrentQatMsg) {
570 		return CPA_STATUS_RETRY;
571 	}
572 
573 	dcDpWriteRingMsg(pOpData, pCurrentQatMsg);
574 	if (NULL != pPartReadData || CPA_TRUE == zeroPadFlag) {
575 		dcDpUpdateRingMsg(pOpData,
576 				  pPartReadData,
577 				  zeroPadFlag,
578 				  pCurrentQatMsg);
579 	}
580 
581 	pSessionDesc->pendingDpStatelessCbCount++;
582 
583 	if (CPA_TRUE == performOpNow) {
584 		SalQatMsg_updateQueueTail(trans_handle);
585 	}
586 
587 	return CPA_STATUS_SUCCESS;
588 }
589 
590 CpaStatus
591 cpaDcDpEnqueueOp(CpaDcDpOpData *pOpData, const CpaBoolean performOpNow)
592 {
593 
594 	return dcDpEnqueueOpBase(pOpData, NULL, CPA_FALSE, performOpNow);
595 }
596 
597 CpaStatus
598 cpaDcDpEnqueueOpWithPartRead(CpaDcDpOpData *pOpData,
599 			     CpaDcDpPartialReadData *pPartReadData,
600 			     const CpaBoolean performOpNow)
601 {
602 	return dcDpEnqueueOpBase(pOpData,
603 				 pPartReadData,
604 				 CPA_FALSE,
605 				 performOpNow);
606 }
607 
608 CpaStatus
609 cpaDcDpEnqueueOpWithZeroPad(CpaDcDpOpData *pOpData,
610 			    const CpaBoolean performOpNow)
611 {
612 	return dcDpEnqueueOpBase(pOpData, NULL, CPA_TRUE, performOpNow);
613 }
614 
615 static CpaStatus
616 dcDpEnqueueOpBatchBase(const Cpa32U numberRequests,
617 		       CpaDcDpOpData *pOpData[],
618 		       CpaDcDpPartialReadData *pPartData[],
619 		       CpaBoolean zeroPadFlag,
620 		       const CpaBoolean performOpNow)
621 {
622 	icp_qat_fw_comp_req_t *pCurrentQatMsg = NULL;
623 	icp_comms_trans_handle trans_handle = NULL;
624 	dc_session_desc_t *pSessionDesc = NULL;
625 	Cpa32U i = 0;
626 	CpaStatus status = CPA_STATUS_SUCCESS;
627 	sal_compression_service_t *pService = NULL;
628 
629 	LAC_CHECK_NULL_PARAM(pOpData);
630 	LAC_CHECK_NULL_PARAM(pOpData[0]);
631 	LAC_CHECK_NULL_PARAM(pOpData[0]->dcInstance);
632 
633 	pService = (sal_compression_service_t *)(pOpData[0]->dcInstance);
634 	if ((numberRequests == 0) ||
635 	    (numberRequests > pService->maxNumCompConcurrentReq)) {
636 		QAT_UTILS_LOG(
637 		    "The number of requests needs to be between 1 and %d.\n",
638 		    pService->maxNumCompConcurrentReq);
639 		return CPA_STATUS_INVALID_PARAM;
640 	}
641 
642 	for (i = 0; i < numberRequests; i++) {
643 		status = dcDataPlaneParamCheck(pOpData[i]);
644 		if (CPA_STATUS_SUCCESS != status) {
645 			return status;
646 		}
647 
648 		if (NULL != pPartData) {
649 			status =
650 			    dcDataPlanePartReadCheck(pOpData[i], pPartData[i]);
651 			if (CPA_STATUS_SUCCESS != status) {
652 				return status;
653 			}
654 		}
655 
656 		if (CPA_TRUE == zeroPadFlag) {
657 			status = dcDataPlaneZeroPadCheck(pOpData[i]);
658 			if (CPA_STATUS_SUCCESS != status) {
659 				return status;
660 			}
661 		}
662 
663 		/* Check that all instance handles and session handles are the
664 		 * same */
665 		if (pOpData[i]->dcInstance != pOpData[0]->dcInstance) {
666 			QAT_UTILS_LOG(
667 			    "All instance handles should be the same in the pOpData.\n");
668 			return CPA_STATUS_INVALID_PARAM;
669 		}
670 
671 		if (pOpData[i]->pSessionHandle != pOpData[0]->pSessionHandle) {
672 			QAT_UTILS_LOG(
673 			    "All session handles should be the same in the pOpData.\n");
674 			return CPA_STATUS_INVALID_PARAM;
675 		}
676 	}
677 
678 	for (i = 0; i < numberRequests; i++) {
679 		if ((CPA_FALSE == pOpData[i]->compressAndVerify) &&
680 		    (CPA_DC_DIR_COMPRESS == pOpData[i]->sessDirection)) {
681 			return CPA_STATUS_UNSUPPORTED;
682 		}
683 	}
684 
685 	/* Check if SAL is initialised otherwise return an error */
686 	SAL_RUNNING_CHECK(pOpData[0]->dcInstance);
687 
688 	trans_handle = ((sal_compression_service_t *)pOpData[0]->dcInstance)
689 			   ->trans_handle_compression_tx;
690 	pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData[0]->pSessionHandle);
691 
692 	for (i = 0; i < numberRequests; i++) {
693 		if ((CPA_DC_DIR_COMPRESS == pOpData[i]->sessDirection) &&
694 		    (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection)) {
695 			QAT_UTILS_LOG(
696 			    "The session does not support this direction of operation.\n");
697 			return CPA_STATUS_INVALID_PARAM;
698 		} else if ((CPA_DC_DIR_DECOMPRESS ==
699 			    pOpData[i]->sessDirection) &&
700 			   (CPA_DC_DIR_COMPRESS ==
701 			    pSessionDesc->sessDirection)) {
702 			QAT_UTILS_LOG(
703 			    "The session does not support this direction of operation.\n");
704 			return CPA_STATUS_INVALID_PARAM;
705 		}
706 	}
707 
708 	icp_adf_getQueueMemory(trans_handle,
709 			       numberRequests,
710 			       (void **)&pCurrentQatMsg);
711 	if (NULL == pCurrentQatMsg) {
712 		return CPA_STATUS_RETRY;
713 	}
714 
715 	for (i = 0; i < numberRequests; i++) {
716 		dcDpWriteRingMsg(pOpData[i], pCurrentQatMsg);
717 		if (pPartData) {
718 			dcDpUpdateRingMsg(pOpData[i],
719 					  pPartData[i],
720 					  CPA_FALSE,
721 					  pCurrentQatMsg);
722 		}
723 		if (CPA_TRUE == zeroPadFlag) {
724 			dcDpUpdateRingMsg(pOpData[i],
725 					  NULL,
726 					  CPA_TRUE,
727 					  pCurrentQatMsg);
728 		}
729 		icp_adf_getQueueNext(trans_handle, (void **)&pCurrentQatMsg);
730 	}
731 
732 	pSessionDesc->pendingDpStatelessCbCount += numberRequests;
733 
734 	if (CPA_TRUE == performOpNow) {
735 		SalQatMsg_updateQueueTail(trans_handle);
736 	}
737 
738 	return CPA_STATUS_SUCCESS;
739 }
740 
741 CpaStatus
742 cpaDcDpEnqueueOpBatch(const Cpa32U numberRequests,
743 		      CpaDcDpOpData *pOpData[],
744 		      const CpaBoolean performOpNow)
745 {
746 	return dcDpEnqueueOpBatchBase(
747 	    numberRequests, pOpData, NULL, CPA_FALSE, performOpNow);
748 }
749 
750 CpaStatus
751 cpaDcDpEnqueueOpWithPartReadBatch(const Cpa32U numberRequests,
752 				  CpaDcDpOpData *pOpData[],
753 				  CpaDcDpPartialReadData *pPartReadData[],
754 				  const CpaBoolean performOpNow)
755 {
756 	return dcDpEnqueueOpBatchBase(
757 	    numberRequests, pOpData, pPartReadData, CPA_FALSE, performOpNow);
758 }
759 
760 CpaStatus
761 cpaDcDpEnqueueOpWithZeroPadBatch(const Cpa32U numberRequests,
762 				 CpaDcDpOpData *pOpData[],
763 				 const CpaBoolean performOpNow)
764 {
765 	return dcDpEnqueueOpBatchBase(
766 	    numberRequests, pOpData, NULL, CPA_TRUE, performOpNow);
767 }
768 
769 CpaStatus
770 icp_sal_DcPollDpInstance(CpaInstanceHandle dcInstance, Cpa32U responseQuota)
771 {
772 	icp_comms_trans_handle trans_handle = NULL;
773 
774 	LAC_CHECK_INSTANCE_HANDLE(dcInstance);
775 	SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION);
776 
777 	/* Check if SAL is initialised otherwise return an error */
778 	SAL_RUNNING_CHECK(dcInstance);
779 
780 	trans_handle = ((sal_compression_service_t *)dcInstance)
781 			   ->trans_handle_compression_rx;
782 
783 	return icp_adf_pollQueue(trans_handle, responseQuota);
784 }
785 
786 CpaStatus
787 cpaDcDpPerformOpNow(CpaInstanceHandle dcInstance)
788 {
789 	icp_comms_trans_handle trans_handle = NULL;
790 
791 	LAC_CHECK_NULL_PARAM(dcInstance);
792 	SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION);
793 
794 	/* Check if SAL is initialised otherwise return an error */
795 	SAL_RUNNING_CHECK(dcInstance);
796 
797 	trans_handle = ((sal_compression_service_t *)dcInstance)
798 			   ->trans_handle_compression_tx;
799 
800 	if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) {
801 		SalQatMsg_updateQueueTail(trans_handle);
802 	}
803 
804 	return CPA_STATUS_SUCCESS;
805 }
806 
807 CpaStatus
808 cpaDcDpIsPartReadSupported(const CpaInstanceHandle instanceHandle,
809 			   CpaBoolean *flag)
810 {
811 	sal_compression_service_t *pService = NULL;
812 	dc_extd_ftrs_t *pExtendedFtrs = NULL;
813 
814 	LAC_CHECK_NULL_PARAM(instanceHandle);
815 	SAL_CHECK_INSTANCE_TYPE(instanceHandle, SAL_SERVICE_TYPE_COMPRESSION);
816 
817 	pService = (sal_compression_service_t *)instanceHandle;
818 	if (!isDcGen4x(pService)) {
819 		*flag = CPA_FALSE;
820 		return CPA_STATUS_SUCCESS;
821 	}
822 
823 	pExtendedFtrs = (dc_extd_ftrs_t *)&(
824 	    ((sal_service_t *)instanceHandle)->dcExtendedFeatures);
825 
826 	*flag = (CpaBoolean)pExtendedFtrs->is_part_read;
827 
828 	return CPA_STATUS_SUCCESS;
829 }
830 
831 CpaStatus
832 cpaDcDpIsZeroPadSupported(const CpaInstanceHandle instanceHandle,
833 			  CpaBoolean *flag)
834 {
835 	sal_compression_service_t *pService = NULL;
836 	dc_extd_ftrs_t *pExtendedFtrs = NULL;
837 
838 	LAC_CHECK_NULL_PARAM(instanceHandle);
839 	SAL_CHECK_INSTANCE_TYPE(instanceHandle, SAL_SERVICE_TYPE_COMPRESSION);
840 
841 	pService = (sal_compression_service_t *)instanceHandle;
842 	if (!isDcGen4x(pService)) {
843 		*flag = CPA_FALSE;
844 		return CPA_STATUS_SUCCESS;
845 	}
846 
847 	pExtendedFtrs = (dc_extd_ftrs_t *)&(
848 	    ((sal_service_t *)instanceHandle)->dcExtendedFeatures);
849 
850 	*flag = (CpaBoolean)pExtendedFtrs->is_zero_pad;
851 
852 	return CPA_STATUS_SUCCESS;
853 }
854