/****************************************************************************** * function: * CpaStatus myPerformOp(const CpaInstanceHandle instanceHandle, * void * pCallbackTag, * const CpaCySymOpData *pOpData, * const CpaBufferList *pSrcBuffer, * CpaBufferList *pDstBuffer, * CpaBoolean *pVerifyResult) * * @param ih [IN] - Instance handle * @param instanceHandle [IN] - Instance handle * @param pCallbackTag [IN] - Pointer to op_done struct * @param pOpData [IN] - Operation parameters * @param pSrcBuffer [IN] - Source buffer list * @param pDstBuffer [OUT] - Destination buffer list * @param pVerifyResult [OUT] - Whether hash verified or not * * description: * Wrapper around cpaCySymPerformOp which handles retries for us. * ******************************************************************************/ CpaStatus myPerformOp(const CpaInstanceHandle instanceHandle, void *pCallbackTag, const CpaCySymOpData * pOpData, const CpaBufferList * pSrcBuffer, CpaBufferList * pDstBuffer, CpaBoolean * pVerifyResult) { CpaStatus status; struct op_done *opDone = (struct op_done *)pCallbackTag; unsigned int uiRetry = 0; do { status = cpaCySymPerformOp(instanceHandle, pCallbackTag, pOpData, pSrcBuffer, pDstBuffer, pVerifyResult); if (status == CPA_STATUS_RETRY) { if (opDone->job) { if ((qat_wake_job(opDone->job, 0) == 0) || (qat_pause_job(opDone->job, 0) == 0)) { status = CPA_STATUS_FAIL; break; } } else { qatPerformOpRetries++; if (uiRetry >= qat_max_retry_count && qat_max_retry_count != QAT_INFINITE_MAX_NUM_RETRIES) { break; } uiRetry++; usleep(qat_poll_interval + (uiRetry % QAT_RETRY_BACKOFF_MODULO_DIVISOR)); } } } while (status == CPA_STATUS_RETRY); return status; }
/* Name : icp_ocfDrvSymProcess * * Description : This function will map symmetric functionality calls from OCF * to the LAC API. It will also allocate memory to store the session context. * * Notes: If it is the first perform call for a given session, then a LAC * session is registered. After the session is registered, no checks as * to whether session paramaters have changed (e.g. alg chain order) are * done. */ int icp_ocfDrvSymProcess(icp_device_t dev, struct cryptop *crp, int hint) { struct icp_drvSessionData *sessionData = NULL; struct icp_drvOpData *drvOpData = NULL; CpaStatus lacStatus = CPA_STATUS_SUCCESS; Cpa32U sessionCtxSizeInBytes = 0; if (NULL == crp) { DPRINTK("%s(): Invalid input parameters, cryptop is NULL\n", __FUNCTION__); return EINVAL; } if (NULL == crp->crp_desc) { DPRINTK("%s(): Invalid input parameters, no crp_desc attached " "to crp\n", __FUNCTION__); crp->crp_etype = EINVAL; return EINVAL; } if (NULL == crp->crp_buf) { DPRINTK("%s(): Invalid input parameters, no buffer attached " "to crp\n", __FUNCTION__); crp->crp_etype = EINVAL; return EINVAL; } if (CPA_TRUE == icp_atomic_read(&icp_ocfDrvIsExiting)) { crp->crp_etype = EFAULT; return EFAULT; } sessionData = (struct icp_drvSessionData *) (CRYPTO_SESID2LID(crp->crp_sid)); if (NULL == sessionData) { DPRINTK("%s(): Invalid input parameters, Null Session ID \n", __FUNCTION__); crp->crp_etype = EINVAL; return EINVAL; } /*If we get a request against a deregisted session, cancel operation*/ if (ICP_SESSION_DEREGISTERED == sessionData->inUse) { DPRINTK("%s(): Session ID %d was deregistered \n", __FUNCTION__, (int)(CRYPTO_SESID2LID(crp->crp_sid))); crp->crp_etype = EFAULT; return EFAULT; } /*If none of the session states are set, then the session structure was either not initialised properly or we are reading from a freed memory area (possible due to OCF batch mode not removing queued requests against deregistered sessions*/ if (ICP_SESSION_INITIALISED != sessionData->inUse && ICP_SESSION_RUNNING != sessionData->inUse) { DPRINTK("%s(): Session - ID %d - not properly initialised or " "memory freed back to the kernel \n", __FUNCTION__, (int)(CRYPTO_SESID2LID(crp->crp_sid))); crp->crp_etype = EINVAL; return EINVAL; } /*For the below checks, remember error checking is already done in LAC. We're not validating inputs subsequent to registration */ if (sessionData->inUse == ICP_SESSION_INITIALISED) { DPRINTK("%s(): Initialising session\n", __FUNCTION__); if (NULL != crp->crp_desc->crd_next) { if (ICP_OCF_DRV_ALG_CIPHER == icp_ocfDrvAlgCheck(crp->crp_desc)) { sessionData->lacSessCtx.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; if (crp->crp_desc->crd_flags & CRD_F_ENCRYPT) { sessionData->lacSessCtx.cipherSetupData. cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; } else { sessionData->lacSessCtx.cipherSetupData. cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; } } else { sessionData->lacSessCtx.algChainOrder = CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; if (crp->crp_desc->crd_next->crd_flags & CRD_F_ENCRYPT) { sessionData->lacSessCtx.cipherSetupData. cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; } else { sessionData->lacSessCtx.cipherSetupData. cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; } } } else if (ICP_OCF_DRV_ALG_CIPHER == icp_ocfDrvAlgCheck(crp->crp_desc)) { if (crp->crp_desc->crd_flags & CRD_F_ENCRYPT) { sessionData->lacSessCtx.cipherSetupData. cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT; } else { sessionData->lacSessCtx.cipherSetupData. cipherDirection = CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT; } } /*No action required for standalone Auth here */ /* Allocate memory for SymSessionCtx before the Session Registration */ lacStatus = cpaCySymSessionCtxGetSize(CPA_INSTANCE_HANDLE_SINGLE, &(sessionData->lacSessCtx), &sessionCtxSizeInBytes); if (CPA_STATUS_SUCCESS != lacStatus) { EPRINTK("%s(): cpaCySymSessionCtxGetSize failed - %d\n", __FUNCTION__, lacStatus); crp->crp_etype = EINVAL; return EINVAL; } sessionData->sessHandle = icp_kmalloc(sessionCtxSizeInBytes, ICP_M_NOWAIT); if (NULL == sessionData->sessHandle) { EPRINTK ("%s(): Failed to get memory for SymSessionCtx\n", __FUNCTION__); crp->crp_etype = ENOMEM; return ENOMEM; } lacStatus = cpaCySymInitSession(CPA_INSTANCE_HANDLE_SINGLE, icp_ocfDrvSymCallBack, &(sessionData->lacSessCtx), sessionData->sessHandle); if (CPA_STATUS_SUCCESS != lacStatus) { EPRINTK("%s(): cpaCySymInitSession failed -%d \n", __FUNCTION__, lacStatus); crp->crp_etype = EFAULT; return EFAULT; } sessionData->inUse = ICP_SESSION_RUNNING; } drvOpData = icp_kmem_cache_zalloc(drvOpData_zone, ICP_M_NOWAIT); if (NULL == drvOpData) { EPRINTK("%s():Failed to get memory for drvOpData\n", __FUNCTION__); crp->crp_etype = ENOMEM; return ENOMEM; } drvOpData->lacOpData.pSessionCtx = sessionData->sessHandle; drvOpData->digestSizeInBytes = sessionData->lacSessCtx.hashSetupData. digestResultLenInBytes; drvOpData->crp = crp; /* Set the default buffer list array memory allocation */ drvOpData->srcBuffer.pBuffers = drvOpData->bufferListArray; drvOpData->numBufferListArray = ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS; if (ICP_OCF_DRV_STATUS_SUCCESS != icp_ocfDrvProcessDataSetup(drvOpData, drvOpData->crp->crp_desc)) { crp->crp_etype = EINVAL; goto err; } if (drvOpData->crp->crp_desc->crd_next != NULL) { if (icp_ocfDrvProcessDataSetup(drvOpData, drvOpData->crp-> crp_desc->crd_next)) { crp->crp_etype = EINVAL; goto err; } } /* * Allocate buffer list array memory if the data fragment is more than * the default number (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS) and not * calculated already */ if (crp->crp_flags & ICP_CRYPTO_F_PACKET_BUF) { if (NULL == drvOpData->lacOpData.pDigestResult) { drvOpData->numBufferListArray = icp_ocfDrvGetPacketBuffFrags((icp_packet_buffer_t *) crp->crp_buf); } if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS < drvOpData->numBufferListArray) { DPRINTK("%s() numBufferListArray more than default\n", __FUNCTION__); drvOpData->srcBuffer.pBuffers = NULL; drvOpData->srcBuffer.pBuffers = icp_kmalloc(drvOpData->numBufferListArray * sizeof(CpaFlatBuffer), ICP_M_NOWAIT); if (NULL == drvOpData->srcBuffer.pBuffers) { EPRINTK("%s() Failed to get memory for " "pBuffers\n", __FUNCTION__); ICP_CACHE_FREE(drvOpData_zone, drvOpData); crp->crp_etype = ENOMEM; return ENOMEM; } } } /* * Check the type of buffer structure we got and convert it into * CpaBufferList format. */ if (crp->crp_flags & ICP_CRYPTO_F_PACKET_BUF) { if (ICP_OCF_DRV_STATUS_SUCCESS != icp_ocfDrvPacketBuffToBufferList((icp_packet_buffer_t *) crp->crp_buf, &(drvOpData->srcBuffer))) { EPRINTK("%s():Failed to translate from packet buffer " "to bufferlist\n", __FUNCTION__); crp->crp_etype = EINVAL; goto err; } drvOpData->bufferType = ICP_CRYPTO_F_PACKET_BUF; } else if (crp->crp_flags & CRYPTO_F_IOV) { /* OCF only supports IOV of one entry. */ if (NUM_IOV_SUPPORTED == ((struct uio *)(crp->crp_buf))->uio_iovcnt) { icp_ocfDrvPtrAndLenToBufferList(((struct uio *)(crp-> crp_buf))-> uio_iov[0].iov_base, ((struct uio *)(crp-> crp_buf))-> uio_iov[0].iov_len, &(drvOpData-> srcBuffer)); drvOpData->bufferType = CRYPTO_F_IOV; } else { DPRINTK("%s():Unable to handle IOVs with lengths of " "greater than one!\n", __FUNCTION__); crp->crp_etype = EINVAL; goto err; } } else { icp_ocfDrvPtrAndLenToBufferList(crp->crp_buf, crp->crp_ilen, &(drvOpData->srcBuffer)); drvOpData->bufferType = CRYPTO_BUF_CONTIG; } /* Allocate srcBuffer's private meta data */ if (ICP_OCF_DRV_STATUS_SUCCESS != icp_ocfDrvAllocMetaData(&(drvOpData->srcBuffer), drvOpData)) { EPRINTK("%s() icp_ocfDrvAllocMetaData failed\n", __FUNCTION__); memset(&(drvOpData->lacOpData), 0, sizeof(CpaCySymOpData)); crp->crp_etype = EINVAL; goto err; } /* Perform "in-place" crypto operation */ lacStatus = cpaCySymPerformOp(CPA_INSTANCE_HANDLE_SINGLE, (void *)drvOpData, &(drvOpData->lacOpData), &(drvOpData->srcBuffer), &(drvOpData->srcBuffer), &(drvOpData->verifyResult)); if (CPA_STATUS_RETRY == lacStatus) { DPRINTK("%s(): cpaCySymPerformOp retry, lacStatus = %d\n", __FUNCTION__, lacStatus); memset(&(drvOpData->lacOpData), 0, sizeof(CpaCySymOpData)); crp->crp_etype = ERESTART; goto err; } if (CPA_STATUS_SUCCESS != lacStatus) { EPRINTK("%s(): cpaCySymPerformOp failed, lacStatus = %d\n", __FUNCTION__, lacStatus); memset(&(drvOpData->lacOpData), 0, sizeof(CpaCySymOpData)); crp->crp_etype = EINVAL; goto err; } return 0; //OCF success status value err: if (drvOpData->numBufferListArray > ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS) { icp_kfree(drvOpData->srcBuffer.pBuffers); } icp_ocfDrvFreeMetaData(&(drvOpData->srcBuffer)); ICP_CACHE_FREE(drvOpData_zone, drvOpData); return crp->crp_etype; }