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 
45 CpaStatus
46 LacSymQueue_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