Beispiel #1
0
/******************************************************************************
* 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;
}
Beispiel #2
0
/* 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;
}