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