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