Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include <stdlib.h>
12 : #include <sys/prctl.h>
13 : #include "securec.h"
14 : #include "user_log.h"
15 : #include "dl_hal_function.h"
16 : #include "ra.h"
17 : #include "ra_async.h"
18 : #include "ra_rs_comm.h"
19 : #include "ra_rs_err.h"
20 : #include "ra_hdc.h"
21 : #include "ra_hdc_socket.h"
22 : #include "ra_hdc_async_socket.h"
23 : #include "ra_hdc_ctx.h"
24 : #include "ra_hdc_async_ctx.h"
25 : #include "ra_hdc_async.h"
26 :
27 : struct HdcAsyncInfo gRaHdcAsync[RA_MAX_PHY_ID_NUM] = {0};
28 :
29 : struct RaAsyncOpHandle gRaAsyncOpHandle[] = {
30 : {RA_RS_GET_EID_BY_IP, RDMA_OP, RaHdcAsyncHandleGetEidByIp, sizeof(union OpGetEidByIpData)},
31 : {RA_RS_GET_IP_BY_EID, RDMA_OP, RaHdcAsyncHandleGetIpByEid, sizeof(union OpGetIpByEidData)},
32 : {RA_RS_LMEM_REG, RDMA_OP, RaHdcAsyncHandleLmemRegister, sizeof(union OpLmemRegInfoData)},
33 : {RA_RS_LMEM_UNREG, RDMA_OP, NULL, sizeof(union OpLmemUnregInfoData)},
34 : {RA_RS_CTX_QP_CREATE, RDMA_OP, RaHdcAsyncHandleQpCreate, sizeof(union OpCtxQpCreateData)},
35 : {RA_RS_CTX_QP_DESTROY, RDMA_OP, NULL, sizeof(union OpCtxQpDestroyData)},
36 : {RA_RS_CTX_QP_IMPORT, RDMA_OP, RaHdcAsyncHandleQpImport, sizeof(union OpCtxQpImportData)},
37 : {RA_RS_CTX_QP_UNIMPORT, RDMA_OP, NULL, sizeof(union OpCtxQpUnimportData)},
38 : {RA_RS_GET_TP_INFO_LIST, RDMA_OP, RaHdcAsyncHandleTpInfoList, sizeof(union OpGetTpInfoListData)},
39 : {RA_RS_GET_TP_ATTR, RDMA_OP, RaHdcAsyncHandleGetTpAttr, sizeof(union OpGetTpAttrData)},
40 : {RA_RS_SET_TP_ATTR, RDMA_OP, NULL, sizeof(union OpSetTpAttrData)},
41 : {RA_RS_CTX_QP_DESTROY_BATCH, RDMA_OP, RaHdcAsyncHandleQpDestroyBatch, sizeof(union OpCtxQpDestroyBatchData)},
42 : {RA_RS_SOCKET_SEND, SOCKET_OP, RaHdcAsyncHandleSocketSend, sizeof(union OpSocketSendData)},
43 : {RA_RS_SOCKET_RECV, SOCKET_OP, RaHdcAsyncHandleSocketRecv, sizeof(union OpSocketRecvData)},
44 : {RA_RS_SOCKET_LISTEN_START, SOCKET_OP, RaHdcAsyncHandleSocketListenStart, sizeof(union OpSocketListenData)},
45 : {RA_RS_SOCKET_LISTEN_STOP, SOCKET_OP, NULL, sizeof(union OpSocketListenData)},
46 : {RA_RS_SOCKET_CONN, SOCKET_OP, NULL, sizeof(union OpSocketConnectData)},
47 : {RA_RS_SOCKET_CLOSE, SOCKET_OP, RaHdcAsyncHandleSocketBatchClose, sizeof(union OpSocketCloseData)},
48 : {RA_RS_HDC_SESSION_CLOSE, OTHERS, NULL, sizeof(union OpHdcCloseData)},
49 : };
50 :
51 1 : STATIC struct RaAsyncOpHandle *RaHdcIsAsyncOp(unsigned int opcode)
52 : {
53 1 : int num = sizeof(gRaAsyncOpHandle) / sizeof(gRaAsyncOpHandle[0]);
54 : int i;
55 :
56 20 : for (i = 0; i < num; i++) {
57 19 : if (gRaAsyncOpHandle[i].opcode == (enum OpType)opcode) {
58 0 : return &gRaAsyncOpHandle[i];
59 : }
60 : }
61 1 : return NULL;
62 : }
63 :
64 0 : STATIC void HdcAsyncHandlePrivData(struct RaRequestHandle *reqHandle)
65 : {
66 0 : if (reqHandle->opHandle->privDataHandle == NULL) {
67 0 : return;
68 : }
69 :
70 0 : reqHandle->opHandle->privDataHandle(reqHandle);
71 : }
72 :
73 0 : STATIC void HdcAsyncSetRequest(struct RaRequestHandle *reqHandle, unsigned int reqId, struct RaAsyncOpHandle *opHandle,
74 : unsigned int phyId, unsigned int dataSize)
75 : {
76 0 : reqHandle->reqId = reqId;
77 0 : reqHandle->opHandle = opHandle;
78 0 : reqHandle->phyId = phyId;
79 0 : reqHandle->dataSize = dataSize;
80 0 : }
81 :
82 0 : STATIC int HdcAsyncGetRequest(struct HdcAsyncInfo *asyncInfo, unsigned int reqId, struct RaRequestHandle **reqHandle)
83 : {
84 0 : struct RaRequestHandle *reqTmp2 = NULL;
85 0 : struct RaRequestHandle *reqTmp = NULL;
86 :
87 : // no need to use lock: req_id always exist in current req_list(the data is always sent before it is received)
88 0 : RA_LIST_GET_HEAD_ENTRY(reqTmp, reqTmp2, &asyncInfo->reqList, list, struct RaRequestHandle);
89 0 : for (; (&reqTmp->list) != &asyncInfo->reqList;
90 0 : reqTmp = reqTmp2, reqTmp2 = list_entry(reqTmp2->list.next, struct RaRequestHandle, list)) {
91 0 : if (reqTmp->reqId == reqId) {
92 0 : *reqHandle = reqTmp;
93 0 : return 0;
94 : }
95 : }
96 0 : *reqHandle = NULL;
97 0 : return -ENODEV;
98 : }
99 :
100 0 : STATIC void HdcAsyncSetReqDone(struct RaRequestHandle *reqHandle, unsigned int phyId, int ret)
101 : {
102 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].rspMutex);
103 0 : RaListAddTail(&reqHandle->list, &gRaHdcAsync[phyId].rspList);
104 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].rspMutex);
105 0 : reqHandle->opRet = (ret != 0) ? ret : reqHandle->opRet;
106 0 : reqHandle->isDone = true;
107 0 : }
108 :
109 1 : STATIC void RaHwAsyncSetConnectStatus(unsigned int phyId, unsigned int connectStatus)
110 : {
111 1 : gRaHdcAsync[phyId].connectStatus = connectStatus;
112 1 : }
113 :
114 0 : STATIC bool HdcAsyncIsMsgValid(unsigned int phyId, struct MsgHead *recvMsgHead, unsigned int recvLen,
115 : struct RaRequestHandle **reqHandle)
116 : {
117 0 : struct RaRequestHandle *reqHandleTmp = NULL;
118 : int ret;
119 :
120 : // check recv_len and get req_handle
121 0 : CHK_PRT_RETURN(recvLen < sizeof(struct MsgHead),
122 : hccp_run_warn("[async][ra_hdc_recv]recv_len[%u] < [%lu] is invalid", recvLen, sizeof(struct MsgHead)), false);
123 0 : ret = HdcAsyncGetRequest(&gRaHdcAsync[phyId], recvMsgHead->asyncReqId, &reqHandleTmp);
124 0 : CHK_PRT_RETURN(reqHandleTmp == NULL,
125 : hccp_run_warn("[async][ra_hdc_recv]req_id[%u] invalid, ret[%d], opcode[%u]", recvMsgHead->asyncReqId, ret,
126 : recvMsgHead->opcode),
127 : false);
128 :
129 : // del req_handle from req_list
130 0 : RaListDel(&reqHandleTmp->list);
131 :
132 : // opcode RA_RS_HDC_SESSION_CLOSE
133 0 : if (recvMsgHead->opcode == RA_RS_HDC_SESSION_CLOSE) {
134 0 : RaHwAsyncSetConnectStatus(phyId, HDC_UNCONNECTED);
135 0 : hccp_dbg("opcode[%u] req_id[%u] phyId[%u]", recvMsgHead->opcode, reqHandleTmp->reqId, phyId);
136 0 : reqHandleTmp->isDone = true;
137 0 : return false;
138 : }
139 :
140 : // need to check op_data size and recv data size
141 0 : if ((reqHandleTmp->dataSize != recvMsgHead->msgDataLen) ||
142 0 : (recvMsgHead->msgDataLen + (unsigned int)sizeof(struct MsgHead)) != recvLen) {
143 0 : hccp_run_warn("[async][ra_hdc_recv]opcode[%u] data_size[%u] msg_data_len[%u] mismatch or recv_len[%u] mismatch",
144 : recvMsgHead->opcode, reqHandleTmp->dataSize, recvMsgHead->msgDataLen, recvLen);
145 0 : HdcAsyncSetReqDone(reqHandleTmp, phyId, -EINVAL);
146 0 : return false;
147 : }
148 :
149 0 : *reqHandle = reqHandleTmp;
150 0 : return true;
151 : }
152 :
153 0 : STATIC int HdcAsyncAddResponse(unsigned int phyId, void *recvBuf, unsigned int recvLen)
154 : {
155 0 : struct RaRequestHandle *reqHandleTmp = NULL;
156 0 : struct MsgHead *recvMsgHead = NULL;
157 0 : int ret = 0;
158 :
159 0 : recvMsgHead = (struct MsgHead *)recvBuf;
160 : // check recv msg: req_id, opcode, msg_data_len and get req_handle
161 0 : if (!HdcAsyncIsMsgValid(phyId, recvMsgHead, recvLen, &reqHandleTmp)) {
162 0 : return -EINVAL;
163 : }
164 :
165 : // handle recv msg
166 0 : reqHandleTmp->recvBuf = (void *)calloc(recvMsgHead->msgDataLen, sizeof(char));
167 0 : if (reqHandleTmp->recvBuf == NULL) {
168 0 : hccp_err("[async][ra_hdc_recv]calloc recv_buf failed, msgDataLen[%u] reqId[%u] opcode[%u]",
169 : recvMsgHead->msgDataLen, recvMsgHead->asyncReqId, recvMsgHead->opcode);
170 0 : ret = -ENOMEM;
171 0 : goto out;
172 : }
173 0 : (void)memcpy_s(reqHandleTmp->recvBuf, recvMsgHead->msgDataLen, recvBuf + sizeof(struct MsgHead),
174 0 : recvMsgHead->msgDataLen);
175 0 : reqHandleTmp->recvLen = recvMsgHead->msgDataLen;
176 0 : reqHandleTmp->opRet = recvMsgHead->ret;
177 0 : HdcAsyncHandlePrivData(reqHandleTmp);
178 :
179 0 : out:
180 0 : HdcAsyncSetReqDone(reqHandleTmp, phyId, ret);
181 0 : return ret;
182 : }
183 :
184 1 : static void HdcAsyncDelReqHandle(struct RaRequestHandle *reqHandle, pthread_mutex_t *mutex)
185 : {
186 1 : RA_PTHREAD_MUTEX_LOCK(mutex);
187 1 : RaListDel(&reqHandle->list);
188 1 : RA_PTHREAD_MUTEX_UNLOCK(mutex);
189 1 : if (reqHandle->recvBuf != NULL && reqHandle->recvLen != 0) {
190 1 : free(reqHandle->recvBuf);
191 1 : reqHandle->recvBuf = NULL;
192 1 : reqHandle->recvLen = 0;
193 : }
194 : // async api return failed, free corresponding handle
195 1 : if (reqHandle->opRet != 0 && reqHandle->privHandle != NULL) {
196 0 : free(reqHandle->privHandle);
197 0 : reqHandle->privHandle = NULL;
198 : }
199 1 : free(reqHandle);
200 1 : reqHandle = NULL;
201 1 : return;
202 : }
203 :
204 1 : void HdcAsyncDelResponse(struct RaRequestHandle *reqHandle)
205 : {
206 1 : HdcAsyncDelReqHandle(reqHandle, &gRaHdcAsync[reqHandle->phyId].rspMutex);
207 1 : }
208 :
209 1 : int RaHdcSendMsgAsync(unsigned int opcode, unsigned int phyId, char *data, unsigned int dataSize,
210 : struct RaRequestHandle *reqHandle)
211 : {
212 1 : struct RaAsyncOpHandle *opHandleTmp = NULL;
213 1 : unsigned int asyncReqId = 0;
214 1 : void *sendBuf = NULL;
215 : unsigned int sendLen;
216 : pid_t hostTgid;
217 : int ret;
218 :
219 1 : if (gRaHdcAsync[phyId].restoreFlag != 0) {
220 0 : return 0;
221 : }
222 :
223 1 : CHK_PRT_RETURN(RaHdcIsBroken(gRaHdcAsync[phyId].lastRecvStatus),
224 : hccp_err("[async][ra_hdc_send]HDC broken, phyId(%u)", phyId), gRaHdcAsync[phyId].lastRecvStatus);
225 1 : opHandleTmp = RaHdcIsAsyncOp(opcode);
226 1 : CHK_PRT_RETURN(opHandleTmp == NULL, hccp_err("[async][ra_hdc_send]opcode[%u] invalid", opcode), -EINVAL);
227 :
228 0 : hostTgid = gRaHdcAsync[phyId].hostTgid;
229 0 : sendLen = (unsigned int)sizeof(struct MsgHead) + dataSize;
230 0 : sendBuf = (void *)calloc(sendLen, sizeof(char));
231 0 : CHK_PRT_RETURN(sendBuf == NULL,
232 : hccp_err("[async][ra_hdc_send]calloc send_buf failed. phyId(%u) opcode(%u)", phyId, opcode), -ENOMEM);
233 :
234 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].reqMutex);
235 0 : asyncReqId = gRaHdcAsync[phyId].reqId;
236 0 : gRaHdcAsync[phyId].reqId++;
237 0 : HdcAsyncSetRequest(reqHandle, asyncReqId, opHandleTmp, phyId, dataSize);
238 : // make sure request has been added to req_list
239 0 : RaListAddTail(&reqHandle->list, &gRaHdcAsync[phyId].reqList);
240 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].reqMutex);
241 :
242 0 : MsgHeadBuildUp(sendBuf, opcode, asyncReqId, dataSize, hostTgid);
243 0 : ret = memcpy_s(sendBuf + sizeof(struct MsgHead), sendLen - sizeof(struct MsgHead), data, dataSize);
244 0 : if (ret != 0) {
245 0 : hccp_err("[async][ra_hdc_send]memcpy_s failed, ret(%d) phyId(%u) opcode(%u)", ret, phyId, opcode);
246 0 : ret = -ESAFEFUNC;
247 0 : goto out;
248 : }
249 :
250 0 : ret = HdcAsyncSendPkt(&gRaHdcAsync[phyId], phyId, sendBuf, sendLen);
251 0 : if (ret != 0) {
252 0 : hccp_err("[async][ra_hdc_send]hdc_async_send_pkt opcode(%u) failed ret(%d) phyId(%u)", opcode, ret, phyId);
253 0 : goto out;
254 : }
255 :
256 0 : free(sendBuf);
257 0 : sendBuf = NULL;
258 0 : return 0;
259 :
260 0 : out:
261 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].reqMutex);
262 0 : RaListDel(&reqHandle->list);
263 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].reqMutex);
264 0 : free(sendBuf);
265 0 : sendBuf = NULL;
266 0 : return ret;
267 : }
268 :
269 0 : STATIC int RaHdcAsyncSessionConnect(struct RaInitConfig *cfg)
270 : {
271 0 : union OpAsyncHdcConnectData asyncData = {0};
272 0 : unsigned int interfaceVersion = 0;
273 : int ret;
274 :
275 0 : ret = RaHdcGetInterfaceVersion(cfg->phyId, RA_RS_ASYNC_HDC_SESSION_CONNECT, &interfaceVersion);
276 : // compatibility issue: ignore return value and set base version queue size to MAX_POOL_QUEUE_SIZE_V1
277 0 : if (ret != 0 || interfaceVersion <= RA_RS_OPCODE_BASE_VERSION) {
278 0 : asyncData.txData.queueSize = MAX_POOL_QUEUE_SIZE_V1;
279 : } else {
280 0 : asyncData.txData.queueSize = MAX_POOL_QUEUE_SIZE;
281 : }
282 0 : asyncData.txData.phyId = cfg->phyId;
283 0 : asyncData.txData.threadNum = RA_POOL_THREAD_NUM;
284 0 : ret = RaHdcProcessMsg(RA_RS_ASYNC_HDC_SESSION_CONNECT, cfg->phyId, (char *)&asyncData,
285 : sizeof(union OpAsyncHdcConnectData));
286 0 : CHK_PRT_RETURN(ret != 0,
287 : hccp_err("[init][ra_hdc_async]ra hdc message process failed ret[%d] phyId[%u]", ret, cfg->phyId), ret);
288 0 : return ret;
289 : }
290 :
291 0 : STATIC int RaHdcAsyncSessionClose(unsigned int phyId)
292 : {
293 0 : union OpAsyncHdcCloseData asyncData = {0};
294 0 : struct RaRequestHandle *reqHandle = NULL;
295 0 : union OpHdcCloseData opData = {0};
296 0 : int timeout = RA_THREAD_TRY_TIME;
297 : int ret;
298 :
299 0 : if (gRaHdcAsync[phyId].restoreFlag != 0) {
300 0 : return 0;
301 : }
302 :
303 : // close async session
304 0 : opData.txData.phyId = phyId;
305 0 : reqHandle = (struct RaRequestHandle *)calloc(1, sizeof(struct RaRequestHandle));
306 0 : CHK_PRT_RETURN(reqHandle == NULL, hccp_err("[deinit][ra_hdc_async]calloc req_handle failed, phyId[%u]", phyId),
307 : -ENOMEM);
308 0 : ret = RaHdcSendMsgAsync(RA_RS_HDC_SESSION_CLOSE, phyId, (char *)&opData, sizeof(union OpHdcCloseData), reqHandle);
309 0 : if (ret != 0) {
310 0 : hccp_err("[deinit][ra_hdc_async]hdc async send message failed ret[%d] phyId[%u]", ret, phyId);
311 0 : free(reqHandle);
312 0 : reqHandle = NULL;
313 0 : return ret;
314 : }
315 :
316 : // wait request done until time out: RA_THREAD_TRY_TIME * RA_THREAD_SLEEP_TIME us
317 0 : while (!reqHandle->isDone && timeout > 0) {
318 0 : usleep(RA_THREAD_SLEEP_TIME);
319 0 : timeout--;
320 : }
321 0 : if (timeout <= 0) {
322 0 : hccp_warn("[deinit][ra_hdc_async]hdc async session close timeout:%d phyId[%u]", timeout, phyId);
323 : }
324 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].reqMutex);
325 0 : HdcAsyncDelResponse(reqHandle);
326 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].reqMutex);
327 :
328 : // destroy async recv thread and work thread pool
329 0 : ret = RaHdcProcessMsg(RA_RS_ASYNC_HDC_SESSION_CLOSE, phyId, (char *)&asyncData, sizeof(union OpAsyncHdcCloseData));
330 0 : CHK_PRT_RETURN(ret != 0,
331 : hccp_err("[deinit][ra_hdc_async]ra hdc message process failed ret[%d] phyId[%u]", ret, phyId), ret);
332 0 : return ret;
333 : }
334 :
335 0 : STATIC void RaHwAsyncHdcServerInit(void *arg)
336 : {
337 0 : struct RaInitConfig cfg = {0};
338 : int ret;
339 :
340 0 : if (arg == NULL) {
341 0 : hccp_err("[init][ra_hdc_async]arg is NULL");
342 0 : return;
343 : }
344 :
345 0 : cfg = *(struct RaInitConfig *)arg;
346 0 : ret = pthread_detach(pthread_self());
347 0 : if (ret != 0) {
348 0 : hccp_err("[init][ra_hdc_async]pthread detach failed ret %d", ret);
349 0 : return;
350 : }
351 :
352 0 : (void)prctl(PR_SET_NAME, (uintptr_t) "hccp_async_server", 0, 0, 0);
353 :
354 : // trigger server to connect session
355 0 : ret = RaHdcAsyncSessionConnect(&cfg);
356 0 : if (ret != 0) {
357 0 : hccp_err("[init][ra_hdc_async]ra_hdc_async_session_connect failed ret[%d] phyId[%u]", ret, cfg.phyId);
358 0 : return;
359 : }
360 0 : return;
361 : }
362 :
363 0 : STATIC void RaHwAsyncHdcClientInit(void *arg)
364 : {
365 0 : struct RaInitConfig cfg = {0};
366 0 : unsigned int logicId = 0;
367 0 : unsigned int phyId = 0;
368 : int ret;
369 :
370 0 : if (arg == NULL) {
371 0 : hccp_err("[init][ra_hdc_async]arg is NULL");
372 0 : return;
373 : }
374 :
375 0 : cfg = *(struct RaInitConfig *)arg;
376 0 : ret = pthread_detach(pthread_self());
377 0 : if (ret != 0) {
378 0 : hccp_err("[init][ra_hdc_async]pthread detach failed ret %d", ret);
379 0 : return;
380 : }
381 :
382 0 : (void)prctl(PR_SET_NAME, (uintptr_t) "hccp_async_client", 0, 0, 0);
383 :
384 0 : phyId = cfg.phyId;
385 0 : ret = DlDrvDeviceGetIndexByPhyId(phyId, &logicId);
386 0 : if (ret != 0) {
387 0 : hccp_err("get logic id failed(%d), phyId(%u)", ret, phyId);
388 0 : return;
389 : }
390 :
391 0 : ret = RaHdcInitSession(0, (int)logicId, phyId, cfg.hdcType, &gRaHdcAsync[phyId].session);
392 0 : if (ret != 0) {
393 0 : hccp_err("hdc session_connect failed ret(%d) phyId(%u)", ret, phyId);
394 0 : return;
395 : }
396 :
397 0 : ret = RaHdcSetSessionReference(&gRaHdcAsync[phyId].session);
398 0 : if (ret != 0) {
399 0 : goto set_ref_err;
400 : }
401 :
402 0 : RaHwAsyncSetConnectStatus(phyId, HDC_CONNECTED);
403 0 : return;
404 :
405 0 : set_ref_err:
406 0 : RaHdcDeinitSession(&gRaHdcAsync[phyId].session);
407 0 : return;
408 : }
409 :
410 0 : STATIC void RaHwAsyncSetThreadStatus(unsigned int phyId, unsigned int threadStatus)
411 : {
412 0 : gRaHdcAsync[phyId].threadStatus = threadStatus;
413 0 : }
414 :
415 1 : STATIC void RaHwAsyncDelList(struct RaListHead *head, pthread_mutex_t *mutex)
416 : {
417 1 : struct RaRequestHandle *reqNext = NULL;
418 1 : struct RaRequestHandle *reqCur = NULL;
419 :
420 1 : RA_LIST_GET_HEAD_ENTRY(reqCur, reqNext, head, list, struct RaRequestHandle);
421 1 : for (; (&reqCur->list) != head;
422 0 : reqCur = reqNext, reqNext = list_entry(reqNext->list.next, struct RaRequestHandle, list)) {
423 0 : HdcAsyncDelReqHandle(reqCur, mutex);
424 : }
425 1 : }
426 :
427 0 : STATIC void RaHwAsyncHdcClientDeinit(unsigned int phyId)
428 : {
429 0 : int tryAgain = HDC_TRY_TIME;
430 :
431 : // destroy thread
432 0 : RaHwAsyncSetThreadStatus(phyId, THREAD_DESTROYING);
433 0 : while ((gRaHdcAsync[phyId].threadStatus != THREAD_HALT) && (tryAgain != 0)) {
434 0 : usleep(HDC_USLEEP_TIME);
435 0 : tryAgain--;
436 : }
437 0 : if (tryAgain <= 0) {
438 0 : hccp_warn("hdc async message thread quit timeout");
439 : }
440 :
441 : // close session
442 0 : RaHwAsyncSetConnectStatus(phyId, HDC_UNCONNECTED);
443 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].sendMutex);
444 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].recvMutex);
445 0 : RaHdcDeinitSession(&gRaHdcAsync[phyId].snapshotSession);
446 0 : RaHdcDeinitSession(&gRaHdcAsync[phyId].session);
447 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
448 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].sendMutex);
449 :
450 0 : RaHwAsyncDelList(&gRaHdcAsync[phyId].reqList, &gRaHdcAsync[phyId].reqMutex);
451 0 : RaHwAsyncDelList(&gRaHdcAsync[phyId].rspList, &gRaHdcAsync[phyId].rspMutex);
452 0 : }
453 :
454 0 : STATIC int RaHdcAsyncMutexInit(unsigned int phyId)
455 : {
456 0 : int ret = 0;
457 :
458 0 : ret = pthread_mutex_init(&gRaHdcAsync[phyId].sendMutex, NULL);
459 0 : if (ret != 0) {
460 0 : hccp_err("[init][ra_hdc_async]pthread_mutex_init send_mutex failed ret(%d) phyId(%u)", ret, phyId);
461 0 : return -ESYSFUNC;
462 : }
463 0 : ret = pthread_mutex_init(&gRaHdcAsync[phyId].recvMutex, NULL);
464 0 : if (ret != 0) {
465 0 : hccp_err("[init][ra_hdc_async]pthread_mutex_init recv_mutex failed ret(%d) phyId(%u)", ret, phyId);
466 0 : ret = -ESYSFUNC;
467 0 : goto recv_mutex_fail;
468 : }
469 0 : ret = pthread_mutex_init(&gRaHdcAsync[phyId].reqMutex, NULL);
470 0 : if (ret != 0) {
471 0 : hccp_err("[init][ra_hdc_async]pthread_mutex_init req_mutex failed ret(%d) phyId(%u)", ret, phyId);
472 0 : ret = -ESYSFUNC;
473 0 : goto req_mutex_fail;
474 : }
475 0 : ret = pthread_mutex_init(&gRaHdcAsync[phyId].rspMutex, NULL);
476 0 : if (ret != 0) {
477 0 : hccp_err("[init][ra_hdc_async]pthread_mutex_init rsp_mutex failed ret(%d) phyId(%u)", ret, phyId);
478 0 : ret = -ESYSFUNC;
479 0 : goto rsp_mutex_fail;
480 : }
481 :
482 0 : return 0;
483 :
484 0 : rsp_mutex_fail:
485 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].reqMutex);
486 0 : req_mutex_fail:
487 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].recvMutex);
488 0 : recv_mutex_fail:
489 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].sendMutex);
490 0 : return ret;
491 : }
492 :
493 0 : STATIC void RaHdcAsyncMutexDeinit(unsigned int phyId)
494 : {
495 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].rspMutex);
496 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].reqMutex);
497 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].recvMutex);
498 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].sendMutex);
499 0 : }
500 :
501 1 : STATIC int RaHdcAsyncInitSession(struct RaInitConfig *cfg)
502 : {
503 1 : unsigned int phyId = cfg->phyId;
504 1 : int timeout = RA_THREAD_TRY_TIME;
505 : pthread_t serverTidp;
506 : pthread_t clientTidp;
507 1 : int ret = 0;
508 :
509 1 : CHK_PRT_RETURN(gRaHdcAsync[phyId].session != NULL,
510 : hccp_warn("hdc async session for phyId[%u] already existed", phyId), -EEXIST);
511 :
512 : // server will be blocked, use a thread to trigger server to accept
513 1 : ret = pthread_create(&serverTidp, NULL, (void *)RaHwAsyncHdcServerInit, cfg);
514 1 : CHK_PRT_RETURN(ret != 0, hccp_err("Create async_hdc_server_init pthread failed, ret(%d)", ret), -ESYSFUNC);
515 :
516 : // client will be blocked, use a thread to trigger client to connect
517 1 : ret = pthread_create(&clientTidp, NULL, (void *)RaHwAsyncHdcClientInit, cfg);
518 1 : CHK_PRT_RETURN(ret != 0, hccp_err("Create async_hdc_client_init pthread failed, ret(%d)", ret), -ESYSFUNC);
519 :
520 : // will block until time out: RA_CONNECT_TRY_TIME * RA_THREAD_SLEEP_TIME us
521 1 : timeout = RA_CONNECT_TRY_TIME;
522 1 : while (gRaHdcAsync[phyId].connectStatus != HDC_CONNECTED && timeout > 0) {
523 0 : usleep(RA_THREAD_SLEEP_TIME);
524 0 : timeout--;
525 : }
526 1 : if (gRaHdcAsync[phyId].connectStatus == HDC_UNCONNECTED || timeout <= 0) {
527 0 : hccp_err("HDC async connect timeout, connectStatus %d, timeout %d, total_timeout %d(us)",
528 : gRaHdcAsync[phyId].connectStatus, timeout, RA_CONNECT_TRY_TIME * RA_THREAD_SLEEP_TIME);
529 0 : return -ETIMEDOUT;
530 : }
531 :
532 1 : gRaHdcAsync[phyId].hostTgid = DlDrvDeviceGetBareTgid();
533 1 : ret = RaHdcAsyncMutexInit(phyId);
534 1 : CHK_PRT_RETURN(ret != 0, hccp_err("ra_hdc_async_mutex_init failed, ret(%d), phyId(%u)", ret, phyId), ret);
535 :
536 0 : RA_INIT_LIST_HEAD(&gRaHdcAsync[phyId].reqList);
537 0 : RA_INIT_LIST_HEAD(&gRaHdcAsync[phyId].rspList);
538 0 : return 0;
539 : }
540 :
541 2 : STATIC void HdcAsyncHandleRecvBroken(struct HdcAsyncInfo *asyncInfo)
542 : {
543 2 : struct RaRequestHandle *reqNext = NULL;
544 2 : struct RaRequestHandle *reqCurr = NULL;
545 :
546 2 : if (!RaHdcIsBroken(asyncInfo->lastRecvStatus)) {
547 0 : return;
548 : }
549 :
550 2 : RA_PTHREAD_MUTEX_LOCK(&asyncInfo->reqMutex);
551 2 : RA_LIST_GET_HEAD_ENTRY(reqCurr, reqNext, &asyncInfo->reqList, list, struct RaRequestHandle);
552 3 : for (; (&reqCurr->list) != &asyncInfo->reqList;
553 1 : reqCurr = reqNext, reqNext = list_entry(reqNext->list.next, struct RaRequestHandle, list)) {
554 1 : RaListDel(&reqCurr->list);
555 1 : HdcAsyncSetReqDone(reqCurr, reqCurr->phyId, asyncInfo->lastRecvStatus);
556 : }
557 2 : RA_PTHREAD_MUTEX_UNLOCK(&asyncInfo->reqMutex);
558 : }
559 :
560 0 : STATIC void *RaHdcRecvMsgAsync(void *arg)
561 : {
562 0 : unsigned int phyId = *(unsigned int *)arg;
563 0 : unsigned int recvLen = MAX_HDC_MSG_DATA;
564 0 : void *recvBuf = NULL;
565 : int ret;
566 :
567 : // free memory after using arg
568 0 : free(arg);
569 0 : arg = NULL;
570 :
571 0 : ret = pthread_detach(pthread_self());
572 0 : CHK_PRT_RETURN(ret, hccp_err("pthread detach failed ret %d, phyId %u", ret, phyId), NULL);
573 :
574 0 : (void)prctl(PR_SET_NAME, (uintptr_t) "hccp_ra_async", 0, 0, 0);
575 :
576 0 : hccp_info("[async][ra_hdc_recv]thread[%d] phyId[%u] enter", getpid(), phyId);
577 0 : RaHwAsyncSetThreadStatus(phyId, THREAD_RUNNING);
578 0 : recvBuf = (void *)calloc(recvLen, sizeof(char));
579 0 : CHK_PRT_RETURN(recvBuf == NULL, hccp_err("[async][ra_hdc_recv]calloc recv_buf failed. phyId(%u)", phyId), NULL);
580 :
581 : while (1) {
582 0 : if (gRaHdcAsync[phyId].threadStatus == THREAD_DESTROYING) {
583 0 : break;
584 : }
585 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].recvMutex);
586 0 : if (gRaHdcAsync[phyId].connectStatus != HDC_CONNECTED) {
587 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
588 0 : usleep(THREAD_SLEEP_TIME);
589 0 : continue;
590 : }
591 :
592 0 : if (RaListEmpty(&gRaHdcAsync[phyId].reqList)) {
593 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
594 0 : usleep(THREAD_SLEEP_TIME);
595 0 : continue;
596 : }
597 :
598 0 : recvLen = MAX_HDC_MSG_DATA;
599 0 : ret = HdcAsyncRecvPkt(&gRaHdcAsync[phyId], phyId, recvBuf, &recvLen);
600 0 : if (ret != 0) {
601 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
602 0 : HdcAsyncHandleRecvBroken(&gRaHdcAsync[phyId]);
603 0 : continue;
604 : }
605 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
606 :
607 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].reqMutex);
608 0 : (void)HdcAsyncAddResponse(phyId, recvBuf, recvLen);
609 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].reqMutex);
610 : }
611 :
612 0 : hccp_info("[async][ra_hdc_recv]thread[%d] phyId[%u] is out", getpid(), phyId);
613 0 : RaHwAsyncSetThreadStatus(phyId, THREAD_HALT);
614 0 : free(recvBuf);
615 0 : recvBuf = NULL;
616 0 : return NULL;
617 : }
618 :
619 0 : STATIC int RaHdcAsyncInitRecvThread(unsigned int phyId)
620 : {
621 0 : unsigned int *phyIdTmp = NULL;
622 0 : int ret = 0;
623 :
624 0 : phyIdTmp = (unsigned int *)calloc(1, sizeof(unsigned int));
625 0 : CHK_PRT_RETURN(phyIdTmp == NULL, hccp_err("calloc phy_id_tmp failed, errno(%d)", errno), -ENOMEM);
626 0 : *phyIdTmp = phyId;
627 :
628 : // create a thread to recv msg from server
629 0 : ret = pthread_create(&gRaHdcAsync[phyId].tid, NULL, RaHdcRecvMsgAsync, (void *)phyIdTmp);
630 0 : if (ret != 0) {
631 0 : hccp_err("Create ra_hdc_recv_msg_async pthread failed, ret(%d)", ret);
632 0 : goto err;
633 : }
634 :
635 0 : return 0;
636 :
637 0 : err:
638 0 : free(phyIdTmp);
639 0 : phyIdTmp = NULL;
640 0 : return ret;
641 : }
642 :
643 1 : int RaHdcInitAsync(struct RaInitConfig *cfg)
644 : {
645 1 : unsigned int interfaceVersion = 0;
646 1 : int ret = 0;
647 :
648 1 : CHK_PRT_RETURN(!cfg->enableHdcAsync, hccp_info("[init][ra_hdc_async]no need to init async hdc session"), 0);
649 :
650 0 : ret = RaHdcGetInterfaceVersion(cfg->phyId, RA_RS_ASYNC_HDC_SESSION_CONNECT, &interfaceVersion);
651 : // normal case: driver not support to or no need to init async hdc session
652 0 : CHK_PRT_RETURN(ret != 0 || interfaceVersion < RA_RS_OPCODE_BASE_VERSION,
653 : hccp_run_warn("[init][ra_hdc_async]not support to init async hdc session, ret(%d), interfaceVersion(%u)", ret,
654 : interfaceVersion),
655 : 0);
656 :
657 0 : ret = RaHdcAsyncInitSession(cfg);
658 0 : CHK_PRT_RETURN(ret != 0,
659 : hccp_err("[init][ra_hdc_async]ra_hdc_async_init_session failed, ret(%d) phyId(%u)", ret, cfg->phyId), ret);
660 :
661 0 : ret = RaHdcAsyncInitRecvThread(cfg->phyId);
662 0 : if (ret != 0) {
663 0 : hccp_err("[init][ra_hdc_async]ra_hdc_async_init_recv_thread failed, ret(%d) phyId(%u)", ret, cfg->phyId);
664 0 : goto err;
665 : }
666 :
667 0 : return 0;
668 :
669 0 : err:
670 0 : RaHdcAsyncMutexDeinit(cfg->phyId);
671 0 : return -ESRCH;
672 : }
673 :
674 2 : int RaHdcDeinitAsync(unsigned int phyId)
675 : {
676 : int ret;
677 :
678 2 : hccp_run_info("hdc deinit async start! phyId[%u] restore_flag[%u]", phyId, gRaHdcAsync[phyId].restoreFlag);
679 :
680 2 : CHK_PRT_RETURN(gRaHdcAsync[phyId].session == NULL && gRaHdcAsync[phyId].restoreFlag == 0,
681 : hccp_warn("hdc async session for phyId[%u] is NULL", phyId), -ENODEV);
682 :
683 : // close server session
684 0 : ret = RaHdcAsyncSessionClose(phyId);
685 0 : CHK_PRT_RETURN(ret != 0,
686 : hccp_err("[deinit][ra_hdc_async]ra_hdc_async_session_close failed ret[%d] phyId[%u]", ret, phyId), ret);
687 :
688 : // close client session & deinit client resources
689 0 : RaHwAsyncHdcClientDeinit(phyId);
690 :
691 0 : RaHdcAsyncMutexDeinit(phyId);
692 :
693 0 : (void)memset_s(&gRaHdcAsync[phyId], sizeof(gRaHdcAsync[phyId]), 0, sizeof(gRaHdcAsync[phyId]));
694 :
695 0 : return 0;
696 : }
697 :
698 0 : int RaHdcAsyncSaveSnapshot(unsigned int phyId, enum SaveSnapshotAction action)
699 : {
700 0 : int ret = 0;
701 :
702 0 : if (gRaHdcAsync[phyId].threadStatus == THREAD_HALT) {
703 0 : return 0;
704 : }
705 :
706 : #ifndef HNS_ROCE_LLT
707 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].sendMutex);
708 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].recvMutex);
709 : if (action == SAVE_SNAPSHOT_ACTION_PRE_PROCESSING && gRaHdcAsync[phyId].session != NULL) {
710 : RaHwAsyncSetConnectStatus(phyId, HDC_UNCONNECTED);
711 : gRaHdcAsync[phyId].snapshotSession = gRaHdcAsync[phyId].session;
712 : gRaHdcAsync[phyId].session = NULL;
713 : } else if (action == SAVE_SNAPSHOT_ACTION_POST_PROCESSING && gRaHdcAsync[phyId].session == NULL) {
714 : RaHwAsyncSetConnectStatus(phyId, HDC_CONNECTED);
715 : gRaHdcAsync[phyId].session = gRaHdcAsync[phyId].snapshotSession;
716 : gRaHdcAsync[phyId].snapshotSession = NULL;
717 : } else {
718 : hccp_err("duplicate or incorrect order calls are not allowed, phyId[%u] action[%d]", phyId, action);
719 : ret = -EPERM;
720 : }
721 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
722 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].sendMutex);
723 : #endif
724 0 : return ret;
725 : }
726 :
727 0 : int RaHdcAsyncRestoreSnapshot(unsigned int phyId)
728 : {
729 0 : int ret = 0;
730 :
731 0 : if (gRaHdcAsync[phyId].threadStatus == THREAD_HALT) {
732 0 : return 0;
733 : }
734 :
735 : #ifndef HNS_ROCE_LLT
736 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].sendMutex);
737 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].recvMutex);
738 : if (gRaHdcAsync[phyId].connectStatus != HDC_UNCONNECTED) {
739 : hccp_err("incorrect order calls are not allowed, phyId[%u] connectStatus[%u]", phyId,
740 : gRaHdcAsync[phyId].connectStatus);
741 : ret = -EPERM;
742 : } else {
743 : gRaHdcAsync[phyId].restoreFlag = 1;
744 : }
745 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
746 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].sendMutex);
747 : #endif
748 0 : return ret;
749 : }
750 :
751 2 : void RaHdcDeinitAsyncAll(void)
752 : {
753 2 : unsigned int phyId = 0;
754 :
755 130 : for (phyId = 0; phyId < RA_MAX_PHY_ID_NUM; phyId++) {
756 128 : if (gRaHdcAsync[phyId].session == NULL || gRaHdcAsync[phyId].threadStatus != THREAD_RUNNING) {
757 128 : continue;
758 : }
759 :
760 0 : (void)RaHdcDeinitAsync(phyId);
761 : }
762 2 : }
|