1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 #include "adf_transport_access_macros.h"
4 #include "adf_transport_internal.h"
5
6 #include "cpa.h"
7 #include "icp_adf_init.h"
8 #include "icp_adf_transport.h"
9 #include "icp_adf_poll.h"
10 #include "icp_adf_transport_dp.h"
11 #include "icp_sal_poll.h"
12
13 /*
14 * adf_modulo
15 * result = data % ( 2 ^ shift )
16 */
17 static inline Cpa32U
adf_modulo(Cpa32U data,Cpa32U shift)18 adf_modulo(Cpa32U data, Cpa32U shift)
19 {
20 Cpa32U div = data >> shift;
21 Cpa32U mult = div << shift;
22
23 return data - mult;
24 }
25
26 /*
27 * icp_adf_transCreateHandle
28 * crete transport handle for a service
29 * call adf_create_ring from adf driver directly with same parameters
30 */
31 CpaStatus
icp_adf_transCreateHandle(icp_accel_dev_t * adf,icp_transport_type trans_type,const char * section,const uint32_t accel_nr,const uint32_t bank_nr,const char * service_name,const icp_adf_ringInfoService_t info,icp_trans_callback callback,icp_resp_deliv_method resp,const uint32_t num_msgs,const uint32_t msg_size,icp_comms_trans_handle * trans_handle)32 icp_adf_transCreateHandle(icp_accel_dev_t *adf,
33 icp_transport_type trans_type,
34 const char *section,
35 const uint32_t accel_nr,
36 const uint32_t bank_nr,
37 const char *service_name,
38 const icp_adf_ringInfoService_t info,
39 icp_trans_callback callback,
40 icp_resp_deliv_method resp,
41 const uint32_t num_msgs,
42 const uint32_t msg_size,
43 icp_comms_trans_handle *trans_handle)
44 {
45 CpaStatus status;
46 int error;
47
48 ICP_CHECK_FOR_NULL_PARAM(trans_handle);
49 ICP_CHECK_FOR_NULL_PARAM(adf);
50
51 error = adf_create_ring(adf->accel_dev,
52 section,
53 bank_nr,
54 num_msgs,
55 msg_size,
56 service_name,
57 callback,
58 ((resp == ICP_RESP_TYPE_IRQ) ? 0 : 1),
59 (struct adf_etr_ring_data **)trans_handle);
60 if (!error)
61 status = CPA_STATUS_SUCCESS;
62 else
63 status = CPA_STATUS_FAIL;
64
65 return status;
66 }
67
68 /*
69 * icp_adf_transReinitHandle
70 * Reinitialize transport handle for a service
71 */
72 CpaStatus
icp_adf_transReinitHandle(icp_accel_dev_t * adf,icp_transport_type trans_type,const char * section,const uint32_t accel_nr,const uint32_t bank_nr,const char * service_name,const icp_adf_ringInfoService_t info,icp_trans_callback callback,icp_resp_deliv_method resp,const uint32_t num_msgs,const uint32_t msg_size,icp_comms_trans_handle * trans_handle)73 icp_adf_transReinitHandle(icp_accel_dev_t *adf,
74 icp_transport_type trans_type,
75 const char *section,
76 const uint32_t accel_nr,
77 const uint32_t bank_nr,
78 const char *service_name,
79 const icp_adf_ringInfoService_t info,
80 icp_trans_callback callback,
81 icp_resp_deliv_method resp,
82 const uint32_t num_msgs,
83 const uint32_t msg_size,
84 icp_comms_trans_handle *trans_handle)
85 {
86 return CPA_STATUS_SUCCESS;
87 }
88 /*
89 * icp_adf_transReleaseHandle
90 * destroy a transport handle, call adf_remove_ring from adf driver directly
91 */
92 CpaStatus
icp_adf_transReleaseHandle(icp_comms_trans_handle trans_handle)93 icp_adf_transReleaseHandle(icp_comms_trans_handle trans_handle)
94 {
95 struct adf_etr_ring_data *ring = trans_handle;
96
97 ICP_CHECK_FOR_NULL_PARAM(ring);
98 adf_remove_ring(ring);
99
100 return CPA_STATUS_SUCCESS;
101 }
102
103 /*
104 * icp_adf_transResetHandle
105 * clean a transport handle, call adf_remove_ring from adf driver directly
106 */
107 CpaStatus
icp_adf_transResetHandle(icp_comms_trans_handle trans_handle)108 icp_adf_transResetHandle(icp_comms_trans_handle trans_handle)
109 {
110 return CPA_STATUS_SUCCESS;
111 }
112
113 /*
114 * icp_adf_transGetRingNum
115 * get ring number from a transport handle
116 */
117 CpaStatus
icp_adf_transGetRingNum(icp_comms_trans_handle trans_handle,uint32_t * ringNum)118 icp_adf_transGetRingNum(icp_comms_trans_handle trans_handle, uint32_t *ringNum)
119 {
120 struct adf_etr_ring_data *ring = trans_handle;
121
122 ICP_CHECK_FOR_NULL_PARAM(ring);
123 ICP_CHECK_FOR_NULL_PARAM(ringNum);
124 *ringNum = (uint32_t)(ring->ring_number);
125
126 return CPA_STATUS_SUCCESS;
127 }
128
129 /*
130 * icp_adf_transPutMsg
131 * send a request to transport handle
132 * call adf_send_message from adf driver directly
133 */
134 CpaStatus
icp_adf_transPutMsg(icp_comms_trans_handle trans_handle,uint32_t * inBuf,uint32_t bufLen)135 icp_adf_transPutMsg(icp_comms_trans_handle trans_handle,
136 uint32_t *inBuf,
137 uint32_t bufLen)
138 {
139 struct adf_etr_ring_data *ring = trans_handle;
140 CpaStatus status = CPA_STATUS_FAIL;
141 int error = EFAULT;
142
143 ICP_CHECK_FOR_NULL_PARAM(ring);
144
145 error = adf_send_message(ring, inBuf);
146 if (EAGAIN == error)
147 status = CPA_STATUS_RETRY;
148 else if (0 == error)
149 status = CPA_STATUS_SUCCESS;
150 else
151 status = CPA_STATUS_FAIL;
152
153 return status;
154 }
155
156 CpaStatus
icp_adf_getInflightRequests(icp_comms_trans_handle trans_handle,Cpa32U * maxInflightRequests,Cpa32U * numInflightRequests)157 icp_adf_getInflightRequests(icp_comms_trans_handle trans_handle,
158 Cpa32U *maxInflightRequests,
159 Cpa32U *numInflightRequests)
160 {
161 struct adf_etr_ring_data *ring = trans_handle;
162 ICP_CHECK_FOR_NULL_PARAM(ring);
163 ICP_CHECK_FOR_NULL_PARAM(maxInflightRequests);
164 ICP_CHECK_FOR_NULL_PARAM(numInflightRequests);
165 /*
166 * XXX: The qat_direct version of this routine returns max - 1, not
167 * the absolute max.
168 */
169 *numInflightRequests = (*(uint32_t *)ring->inflights);
170 *maxInflightRequests =
171 ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size);
172 return CPA_STATUS_SUCCESS;
173 }
174
175 CpaStatus
icp_adf_dp_getInflightRequests(icp_comms_trans_handle trans_handle,Cpa32U * maxInflightRequests,Cpa32U * numInflightRequests)176 icp_adf_dp_getInflightRequests(icp_comms_trans_handle trans_handle,
177 Cpa32U *maxInflightRequests,
178 Cpa32U *numInflightRequests)
179 {
180 ICP_CHECK_FOR_NULL_PARAM(trans_handle);
181 ICP_CHECK_FOR_NULL_PARAM(maxInflightRequests);
182 ICP_CHECK_FOR_NULL_PARAM(numInflightRequests);
183
184 return icp_adf_getInflightRequests(trans_handle,
185 maxInflightRequests,
186 numInflightRequests);
187 }
188
189 /*
190 * This function allows the user to poll the response ring. The
191 * ring number to be polled is supplied by the user via the
192 * trans handle for that ring. The trans_hnd is a pointer
193 * to an array of trans handles. This ring is
194 * only polled if it contains data.
195 * This method is used as an alternative to the reading messages
196 * via the ISR method.
197 * This function will return RETRY if the ring is empty.
198 */
199 CpaStatus
icp_adf_pollInstance(icp_comms_trans_handle * trans_hnd,Cpa32U num_transHandles,Cpa32U response_quota)200 icp_adf_pollInstance(icp_comms_trans_handle *trans_hnd,
201 Cpa32U num_transHandles,
202 Cpa32U response_quota)
203 {
204 Cpa32U resp_total = 0;
205 Cpa32U num_resp;
206 struct adf_etr_ring_data *ring = NULL;
207 struct adf_etr_bank_data *bank = NULL;
208 Cpa32U i;
209
210 ICP_CHECK_FOR_NULL_PARAM(trans_hnd);
211
212 for (i = 0; i < num_transHandles; i++) {
213 ring = trans_hnd[i];
214 if (!ring)
215 continue;
216 bank = ring->bank;
217
218 /* If the ring in question is empty try the next ring.*/
219 if (!bank || !bank->ring_mask) {
220 continue;
221 }
222
223 num_resp = adf_handle_response(ring, response_quota);
224 resp_total += num_resp;
225 }
226
227 /* If any of the rings in the instance had data and was polled
228 * return SUCCESS. */
229 if (resp_total)
230 return CPA_STATUS_SUCCESS;
231 else
232 return CPA_STATUS_RETRY;
233 }
234
235 /*
236 * This function allows the user to check the response ring. The
237 * ring number to be polled is supplied by the user via the
238 * trans handle for that ring. The trans_hnd is a pointer
239 * to an array of trans handles.
240 * This function now is a empty function.
241 */
242 CpaStatus
icp_adf_check_RespInstance(icp_comms_trans_handle * trans_hnd,Cpa32U num_transHandles)243 icp_adf_check_RespInstance(icp_comms_trans_handle *trans_hnd,
244 Cpa32U num_transHandles)
245 {
246 return CPA_STATUS_SUCCESS;
247 }
248
249 /*
250 * icp_sal_pollBank
251 * poll bank with id bank_number inside acceleration device with id @accelId
252 */
253 CpaStatus
icp_sal_pollBank(Cpa32U accelId,Cpa32U bank_number,Cpa32U response_quota)254 icp_sal_pollBank(Cpa32U accelId, Cpa32U bank_number, Cpa32U response_quota)
255 {
256 int ret;
257
258 ret = adf_poll_bank(accelId, bank_number, response_quota);
259 if (!ret)
260 return CPA_STATUS_SUCCESS;
261 else if (EAGAIN == ret)
262 return CPA_STATUS_RETRY;
263
264 return CPA_STATUS_FAIL;
265 }
266
267 /*
268 * icp_sal_pollAllBanks
269 * poll all banks inside acceleration device with id @accelId
270 */
271 CpaStatus
icp_sal_pollAllBanks(Cpa32U accelId,Cpa32U response_quota)272 icp_sal_pollAllBanks(Cpa32U accelId, Cpa32U response_quota)
273 {
274 int ret = 0;
275
276 ret = adf_poll_all_banks(accelId, response_quota);
277 if (!ret)
278 return CPA_STATUS_SUCCESS;
279 else if (ret == EAGAIN)
280 return CPA_STATUS_RETRY;
281
282 return CPA_STATUS_FAIL;
283 }
284
285 /*
286 * icp_adf_getQueueMemory
287 * Data plane support function - returns the pointer to next message on the ring
288 * or NULL if there is not enough space.
289 */
290 void
icp_adf_getQueueMemory(icp_comms_trans_handle trans_handle,Cpa32U numberRequests,void ** pCurrentQatMsg)291 icp_adf_getQueueMemory(icp_comms_trans_handle trans_handle,
292 Cpa32U numberRequests,
293 void **pCurrentQatMsg)
294 {
295 struct adf_etr_ring_data *ring = trans_handle;
296 Cpa64U flight;
297
298 ICP_CHECK_FOR_NULL_PARAM_VOID(ring);
299
300 /* Check if there is enough space in the ring */
301 flight = atomic_add_return(numberRequests, ring->inflights);
302 if (flight > ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size)) {
303 atomic_sub(numberRequests, ring->inflights);
304 *pCurrentQatMsg = NULL;
305 return;
306 }
307
308 /* We have enough space - get the address of next message */
309 *pCurrentQatMsg = (void *)((uintptr_t)ring->base_addr + ring->tail);
310 }
311
312 /*
313 * icp_adf_getSingleQueueAddr
314 * Data plane support function - returns the pointer to next message on the ring
315 * or NULL if there is not enough space - it also updates the shadow tail copy.
316 */
317 void
icp_adf_getSingleQueueAddr(icp_comms_trans_handle trans_handle,void ** pCurrentQatMsg)318 icp_adf_getSingleQueueAddr(icp_comms_trans_handle trans_handle,
319 void **pCurrentQatMsg)
320 {
321 struct adf_etr_ring_data *ring = trans_handle;
322 Cpa64U flight;
323
324 ICP_CHECK_FOR_NULL_PARAM_VOID(ring);
325 ICP_CHECK_FOR_NULL_PARAM_VOID(pCurrentQatMsg);
326
327 /* Check if there is enough space in the ring */
328 flight = atomic_add_return(1, ring->inflights);
329 if (flight > ADF_MAX_INFLIGHTS(ring->ring_size, ring->msg_size)) {
330 atomic_dec(ring->inflights);
331 *pCurrentQatMsg = NULL;
332 return;
333 }
334
335 /* We have enough space - get the address of next message */
336 *pCurrentQatMsg = (void *)((uintptr_t)ring->base_addr + ring->tail);
337
338 /* Update the shadow tail */
339 ring->tail =
340 adf_modulo(ring->tail + ADF_MSG_SIZE_TO_BYTES(ring->msg_size),
341 ADF_RING_SIZE_MODULO(ring->ring_size));
342 }
343
344 /*
345 * icp_adf_getQueueNext
346 * Data plane support function - increments the tail pointer and returns
347 * the pointer to next message on the ring.
348 */
349 void
icp_adf_getQueueNext(icp_comms_trans_handle trans_handle,void ** pCurrentQatMsg)350 icp_adf_getQueueNext(icp_comms_trans_handle trans_handle, void **pCurrentQatMsg)
351 {
352 struct adf_etr_ring_data *ring = trans_handle;
353
354 ICP_CHECK_FOR_NULL_PARAM_VOID(ring);
355 ICP_CHECK_FOR_NULL_PARAM_VOID(pCurrentQatMsg);
356
357 /* Increment tail to next message */
358 ring->tail =
359 adf_modulo(ring->tail + ADF_MSG_SIZE_TO_BYTES(ring->msg_size),
360 ADF_RING_SIZE_MODULO(ring->ring_size));
361
362 /* Get the address of next message */
363 *pCurrentQatMsg = (void *)((uintptr_t)ring->base_addr + ring->tail);
364 }
365
366 /*
367 * icp_adf_updateQueueTail
368 * Data plane support function - Writes the tail shadow copy to the device.
369 */
370 void
icp_adf_updateQueueTail(icp_comms_trans_handle trans_handle)371 icp_adf_updateQueueTail(icp_comms_trans_handle trans_handle)
372 {
373 struct adf_etr_ring_data *ring = trans_handle;
374 struct adf_hw_csr_ops *csr_ops;
375
376 ICP_CHECK_FOR_NULL_PARAM_VOID(ring);
377 ICP_CHECK_FOR_NULL_PARAM_VOID(ring->bank);
378 ICP_CHECK_FOR_NULL_PARAM_VOID(ring->bank->accel_dev);
379
380 csr_ops = GET_CSR_OPS(ring->bank->accel_dev);
381
382 ICP_CHECK_FOR_NULL_PARAM_VOID(csr_ops);
383
384 csr_ops->write_csr_ring_tail(ring->bank->csr_addr,
385 ring->bank->bank_number,
386 ring->ring_number,
387 ring->tail);
388 ring->csr_tail_offset = ring->tail;
389 }
390
391 /*
392 * icp_adf_pollQueue
393 * Data plane support function - Poll messages from the queue.
394 */
395 CpaStatus
icp_adf_pollQueue(icp_comms_trans_handle trans_handle,Cpa32U response_quota)396 icp_adf_pollQueue(icp_comms_trans_handle trans_handle, Cpa32U response_quota)
397 {
398 Cpa32U num_resp;
399 struct adf_etr_ring_data *ring = trans_handle;
400
401 ICP_CHECK_FOR_NULL_PARAM(ring);
402
403 num_resp = adf_handle_response(ring, response_quota);
404
405 if (num_resp)
406 return CPA_STATUS_SUCCESS;
407 else
408 return CPA_STATUS_RETRY;
409 }
410
411 /*
412 * icp_adf_queueDataToSend
413 * Data-plane support function - Indicates if there is data on the ring to be
414 * sent. This should only be called on request rings. If the function returns
415 * true then it is ok to call icp_adf_updateQueueTail() function on this ring.
416 */
417 CpaBoolean
icp_adf_queueDataToSend(icp_comms_trans_handle trans_handle)418 icp_adf_queueDataToSend(icp_comms_trans_handle trans_handle)
419 {
420 struct adf_etr_ring_data *ring = trans_handle;
421
422 if (ring->tail != ring->csr_tail_offset)
423 return CPA_TRUE;
424 else
425 return CPA_FALSE;
426 }
427
428 /*
429 * This icp API won't be supported in kernel space currently
430 */
431 CpaStatus
icp_adf_transGetFdForHandle(icp_comms_trans_handle trans_hnd,int * fd)432 icp_adf_transGetFdForHandle(icp_comms_trans_handle trans_hnd, int *fd)
433 {
434 return CPA_STATUS_UNSUPPORTED;
435 }
436