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