1/* SPDX-License-Identifier: BSD-3-Clause */
2/* Copyright(c) 2007-2022 Intel Corporation */
3
4/**
5 ***************************************************************************
6 * @file lac_sym_queue.c     Functions for sending/queuing symmetric requests
7 *
8 * @ingroup LacSym
9 *
10 ***************************************************************************/
11
12/*
13*******************************************************************************
14* Include public/global header files
15*******************************************************************************
16*/
17#include "cpa.h"
18#include "cpa_cy_sym.h"
19
20/*
21*******************************************************************************
22* Include private header files
23*******************************************************************************
24*/
25#include "icp_accel_devices.h"
26#include "icp_adf_init.h"
27#include "icp_adf_debug.h"
28#include "icp_adf_transport.h"
29#include "lac_sym_queue.h"
30#include "lac_sym_qat.h"
31#include "lac_session.h"
32#include "lac_sym.h"
33#include "lac_log.h"
34#include "icp_qat_fw_la.h"
35#include "lac_sal_types_crypto.h"
36
37#define GetSingleBitFromByte(byte, bit) ((byte) & (1 << (bit)))
38
39/*
40*******************************************************************************
41* Define public/global function definitions
42*******************************************************************************
43*/
44
45CpaStatus
46LacSymQueue_RequestSend(const CpaInstanceHandle instanceHandle,
47			lac_sym_bulk_cookie_t *pRequest,
48			lac_session_desc_t *pSessionDesc)
49{
50	CpaStatus status = CPA_STATUS_SUCCESS;
51	CpaBoolean enqueued = CPA_FALSE;
52	sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle;
53	/* Enqueue the message instead of sending directly if:
54	 * (i) a blocking operation is in progress
55	 * (ii) there are previous requests already in the queue
56	 */
57	if ((CPA_FALSE == pSessionDesc->nonBlockingOpsInProgress) ||
58	    (NULL != pSessionDesc->pRequestQueueTail)) {
59		LAC_SPINLOCK(&pSessionDesc->requestQueueLock);
60
61		/* Re-check blockingOpsInProgress and pRequestQueueTail in case
62		 * either
63		 * changed before the lock was acquired.  The lock is shared
64		 * with
65		 * the callback context which drains this queue
66		 */
67		if ((CPA_FALSE == pSessionDesc->nonBlockingOpsInProgress) ||
68		    (NULL != pSessionDesc->pRequestQueueTail)) {
69			/* Enqueue the message and exit */
70			/* The FIFO queue is made up of a head and tail pointer.
71			 * The head pointer points to the first/oldest, entry
72			 * in the queue, and the tail pointer points to the
73			 * last/newest
74			 * entry in the queue
75			 */
76
77			if (NULL != pSessionDesc->pRequestQueueTail) {
78				/* Queue is non-empty. Add this request to the
79				 * list */
80				pSessionDesc->pRequestQueueTail->pNext =
81				    pRequest;
82			} else {
83				/* Queue is empty. Initialise the head pointer
84				 * as well */
85				pSessionDesc->pRequestQueueHead = pRequest;
86			}
87
88			pSessionDesc->pRequestQueueTail = pRequest;
89
90			/* request is queued, don't send to QAT here */
91			enqueued = CPA_TRUE;
92		}
93		LAC_SPINUNLOCK(&pSessionDesc->requestQueueLock);
94	}
95
96	if (CPA_FALSE == enqueued) {
97		/* If we send a partial packet request, set the
98		 * blockingOpsInProgress
99		 * flag for the session to indicate that subsequent requests
100		 * must be
101		 * queued up until this request completes
102		 *
103		 * @assumption
104		 * If we have got here it means that there were no previous
105		 * blocking
106		 * operations in progress and, since multiple partial packet
107		 * requests
108		 * on a given session cannot be issued concurrently, there
109		 * should be
110		 * no need for a critical section around the following code
111		 */
112		if (CPA_CY_SYM_PACKET_TYPE_FULL !=
113		    pRequest->pOpData->packetType) {
114			/* Select blocking operations which this reqest will
115			 * complete */
116			pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE;
117		}
118
119		/* At this point, we're clear to send the request.  For cipher
120		 * requests,
121		 * we need to check if the session IV needs to be updated.  This
122		 * can
123		 * only be done when no other partials are in flight for this
124		 * session,
125		 * to ensure the cipherPartialOpState buffer in the session
126		 * descriptor
127		 * is not currently in use
128		 */
129		if (CPA_TRUE == pRequest->updateSessionIvOnSend) {
130			if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) {
131				memcpy(pSessionDesc->cipherPartialOpState,
132				       pSessionDesc->cipherARC4InitialState,
133				       LAC_CIPHER_ARC4_STATE_LEN_BYTES);
134			} else {
135				memcpy(pSessionDesc->cipherPartialOpState,
136				       pRequest->pOpData->pIv,
137				       pRequest->pOpData->ivLenInBytes);
138			}
139		}
140
141		/* Send to QAT */
142		status = icp_adf_transPutMsg(pService->trans_handle_sym_tx,
143					     (void *)&(pRequest->qatMsg),
144					     LAC_QAT_SYM_REQ_SZ_LW);
145
146		/* if fail to send request, we need to change
147		 * nonBlockingOpsInProgress
148		 * to CPA_TRUE
149		 */
150		if ((CPA_STATUS_SUCCESS != status) &&
151		    (CPA_CY_SYM_PACKET_TYPE_FULL !=
152		     pRequest->pOpData->packetType)) {
153			pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE;
154		}
155	}
156	return status;
157}
158