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