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_LMEM_REG, RDMA_OP, RaHdcAsyncHandleLmemRegister, sizeof(union OpLmemRegInfoData)},
32 : {RA_RS_LMEM_UNREG, RDMA_OP, NULL, sizeof(union OpLmemUnregInfoData)},
33 : {RA_RS_CTX_QP_CREATE, RDMA_OP, RaHdcAsyncHandleQpCreate, sizeof(union OpCtxQpCreateData)},
34 : {RA_RS_CTX_QP_DESTROY, RDMA_OP, NULL, sizeof(union OpCtxQpDestroyData)},
35 : {RA_RS_CTX_QP_IMPORT, RDMA_OP, RaHdcAsyncHandleQpImport, sizeof(union OpCtxQpImportData)},
36 : {RA_RS_CTX_QP_UNIMPORT, RDMA_OP, NULL, sizeof(union OpCtxQpUnimportData)},
37 : {RA_RS_GET_TP_INFO_LIST, RDMA_OP, RaHdcAsyncHandleTpInfoList, sizeof(union OpGetTpInfoListData)},
38 : {RA_RS_GET_TP_ATTR, RDMA_OP, RaHdcAsyncHandleGetTpAttr, sizeof(union OpGetTpAttrData)},
39 : {RA_RS_SET_TP_ATTR, RDMA_OP, NULL, sizeof(union OpSetTpAttrData)},
40 : {RA_RS_CTX_QP_DESTROY_BATCH, RDMA_OP, RaHdcAsyncHandleQpDestroyBatch,
41 : 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,
45 : sizeof(union OpSocketListenData)},
46 : {RA_RS_SOCKET_LISTEN_STOP, SOCKET_OP, NULL, sizeof(union OpSocketListenData)},
47 : {RA_RS_SOCKET_CONN, SOCKET_OP, NULL, sizeof(union OpSocketConnectData)},
48 : {RA_RS_SOCKET_CLOSE, SOCKET_OP, RaHdcAsyncHandleSocketBatchClose, sizeof(union OpSocketCloseData)},
49 : {RA_RS_HDC_SESSION_CLOSE, OTHERS, NULL, sizeof(union OpHdcCloseData)},
50 : };
51 :
52 1 : STATIC struct RaAsyncOpHandle *RaHdcIsAsyncOp(unsigned int opcode)
53 : {
54 1 : int num = sizeof(gRaAsyncOpHandle) / sizeof(gRaAsyncOpHandle[0]);
55 : int i;
56 :
57 19 : for (i = 0; i < num; i++) {
58 18 : if (gRaAsyncOpHandle[i].opcode == (enum OpType)opcode) {
59 0 : return &gRaAsyncOpHandle[i];
60 : }
61 : }
62 1 : return NULL;
63 : }
64 :
65 0 : STATIC void HdcAsyncHandlePrivData(struct RaRequestHandle *reqHandle)
66 : {
67 0 : if (reqHandle->opHandle->privDataHandle == NULL) {
68 0 : return;
69 : }
70 :
71 0 : reqHandle->opHandle->privDataHandle(reqHandle);
72 : }
73 :
74 0 : STATIC void HdcAsyncSetRequest(struct RaRequestHandle *reqHandle, unsigned int reqId,
75 : struct RaAsyncOpHandle *opHandle, unsigned int phyId, unsigned int dataSize)
76 : {
77 0 : reqHandle->reqId = reqId;
78 0 : reqHandle->opHandle = opHandle;
79 0 : reqHandle->phyId = phyId;
80 0 : reqHandle->dataSize = dataSize;
81 0 : }
82 :
83 0 : STATIC int HdcAsyncGetRequest(struct HdcAsyncInfo *asyncInfo, unsigned int reqId,
84 : struct RaRequestHandle **reqHandle)
85 : {
86 0 : struct RaRequestHandle *reqTmp2 = NULL;
87 0 : struct RaRequestHandle *reqTmp = NULL;
88 :
89 : // no need to use lock: req_id always exist in current req_list(the data is always sent before it is received)
90 0 : RA_LIST_GET_HEAD_ENTRY(reqTmp, reqTmp2, &asyncInfo->reqList, list, struct RaRequestHandle);
91 0 : for (; (&reqTmp->list) != &asyncInfo->reqList;
92 0 : reqTmp = reqTmp2, reqTmp2 = list_entry(reqTmp2->list.next, struct RaRequestHandle, list)) {
93 0 : if (reqTmp->reqId == reqId) {
94 0 : *reqHandle = reqTmp;
95 0 : return 0;
96 : }
97 : }
98 0 : *reqHandle = NULL;
99 0 : return -ENODEV;
100 : }
101 :
102 0 : STATIC void HdcAsyncSetReqDone(struct RaRequestHandle *reqHandle, unsigned int phyId, int ret)
103 : {
104 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].rspMutex);
105 0 : RaListAddTail(&reqHandle->list, &gRaHdcAsync[phyId].rspList);
106 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].rspMutex);
107 0 : reqHandle->opRet = (ret != 0) ? ret : reqHandle->opRet;
108 0 : reqHandle->isDone = true;
109 0 : }
110 :
111 1 : STATIC void RaHwAsyncSetConnectStatus(unsigned int phyId, unsigned int connectStatus)
112 : {
113 1 : gRaHdcAsync[phyId].connectStatus = connectStatus;
114 1 : }
115 :
116 0 : STATIC bool HdcAsyncIsMsgValid(unsigned int phyId, struct MsgHead *recvMsgHead, unsigned int recvLen,
117 : struct RaRequestHandle **reqHandle)
118 : {
119 0 : struct RaRequestHandle *reqHandleTmp = NULL;
120 : int ret;
121 :
122 : // check recv_len and get req_handle
123 0 : CHK_PRT_RETURN(recvLen < sizeof(struct MsgHead),
124 : hccp_run_warn("[async][ra_hdc_recv]recv_len[%u] < [%lu] is invalid", recvLen, sizeof(struct MsgHead)), false);
125 0 : ret = HdcAsyncGetRequest(&gRaHdcAsync[phyId], recvMsgHead->asyncReqId, &reqHandleTmp);
126 0 : CHK_PRT_RETURN(reqHandleTmp == NULL, hccp_run_warn("[async][ra_hdc_recv]req_id[%u] invalid, ret[%d], opcode[%u]",
127 : recvMsgHead->asyncReqId, ret, recvMsgHead->opcode), 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, hccp_err("[async][ra_hdc_send]calloc send_buf failed. phyId(%u) opcode(%u)",
232 : 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, hccp_err("[init][ra_hdc_async]ra hdc message process failed ret[%d] phyId[%u]",
287 : 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,
307 : hccp_err("[deinit][ra_hdc_async]calloc req_handle failed, phyId[%u]", phyId), -ENOMEM);
308 0 : ret = RaHdcSendMsgAsync(RA_RS_HDC_SESSION_CLOSE, phyId, (char *)&opData, sizeof(union OpHdcCloseData),
309 : reqHandle);
310 0 : if (ret != 0) {
311 0 : hccp_err("[deinit][ra_hdc_async]hdc async send message failed ret[%d] phyId[%u]", ret, phyId);
312 0 : free(reqHandle);
313 0 : reqHandle = NULL;
314 0 : return ret;
315 : }
316 :
317 : // wait request done until time out: RA_THREAD_TRY_TIME * RA_THREAD_SLEEP_TIME us
318 0 : while (!reqHandle->isDone && timeout > 0) {
319 0 : usleep(RA_THREAD_SLEEP_TIME);
320 0 : timeout--;
321 : }
322 0 : if (timeout <= 0) {
323 0 : hccp_warn("[deinit][ra_hdc_async]hdc async session close timeout:%d phyId[%u]", timeout, phyId);
324 : }
325 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].reqMutex);
326 0 : HdcAsyncDelResponse(reqHandle);
327 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].reqMutex);
328 :
329 : // destroy async recv thread and work thread pool
330 0 : ret = RaHdcProcessMsg(RA_RS_ASYNC_HDC_SESSION_CLOSE, phyId, (char *)&asyncData,
331 : sizeof(union OpAsyncHdcCloseData));
332 0 : CHK_PRT_RETURN(ret != 0, hccp_err("[deinit][ra_hdc_async]ra hdc message process failed ret[%d] phyId[%u]",
333 : ret, phyId), ret);
334 0 : return ret;
335 : }
336 :
337 0 : STATIC void RaHwAsyncHdcServerInit(void *arg)
338 : {
339 0 : struct RaInitConfig cfg = {0};
340 : int ret;
341 :
342 0 : if (arg == NULL) {
343 0 : hccp_err("[init][ra_hdc_async]arg is NULL");
344 0 : return;
345 : }
346 :
347 0 : cfg = *(struct RaInitConfig *)arg;
348 0 : ret = pthread_detach(pthread_self());
349 0 : if (ret != 0) {
350 0 : hccp_err("[init][ra_hdc_async]pthread detach failed ret %d", ret);
351 0 : return;
352 : }
353 :
354 0 : (void)prctl(PR_SET_NAME, (unsigned long)"hccp_async_server");
355 :
356 : // trigger server to connect session
357 0 : ret = RaHdcAsyncSessionConnect(&cfg);
358 0 : if (ret != 0) {
359 0 : hccp_err("[init][ra_hdc_async]ra_hdc_async_session_connect failed ret[%d] phyId[%u]", ret, cfg.phyId);
360 0 : return;
361 : }
362 0 : return;
363 : }
364 :
365 0 : STATIC void RaHwAsyncHdcClientInit(void *arg)
366 : {
367 0 : struct RaInitConfig cfg = {0};
368 0 : unsigned int logicId = 0;
369 0 : unsigned int phyId = 0;
370 : int ret;
371 :
372 0 : if (arg == NULL) {
373 0 : hccp_err("[init][ra_hdc_async]arg is NULL");
374 0 : return;
375 : }
376 :
377 0 : cfg = *(struct RaInitConfig *)arg;
378 0 : ret = pthread_detach(pthread_self());
379 0 : if (ret != 0) {
380 0 : hccp_err("[init][ra_hdc_async]pthread detach failed ret %d", ret);
381 0 : return;
382 : }
383 :
384 0 : (void)prctl(PR_SET_NAME, (unsigned long)"hccp_async_client");
385 :
386 0 : phyId = cfg.phyId;
387 0 : ret = DlDrvDeviceGetIndexByPhyId(phyId, &logicId);
388 0 : if (ret != 0) {
389 0 : hccp_err("get logic id failed(%d), phyId(%u)", ret, phyId);
390 0 : return;
391 : }
392 :
393 0 : ret = RaHdcInitSession(0, (int)logicId, phyId, cfg.hdcType, &gRaHdcAsync[phyId].session);
394 0 : if (ret != 0) {
395 0 : hccp_err("hdc session_connect failed ret(%d) phyId(%u)", ret, phyId);
396 0 : return;
397 : }
398 :
399 0 : ret = RaHdcSetSessionReference(&gRaHdcAsync[phyId].session);
400 0 : if (ret != 0) {
401 0 : goto set_ref_err;
402 : }
403 :
404 0 : RaHwAsyncSetConnectStatus(phyId, HDC_CONNECTED);
405 0 : return;
406 :
407 0 : set_ref_err:
408 0 : RaHdcDeinitSession(&gRaHdcAsync[phyId].session);
409 0 : return;
410 : }
411 :
412 0 : STATIC void RaHwAsyncSetThreadStatus(unsigned int phyId, unsigned int threadStatus)
413 : {
414 0 : gRaHdcAsync[phyId].threadStatus = threadStatus;
415 0 : }
416 :
417 1 : STATIC void RaHwAsyncDelList(struct RaListHead *head, pthread_mutex_t *mutex)
418 : {
419 1 : struct RaRequestHandle *reqNext = NULL;
420 1 : struct RaRequestHandle *reqCur = NULL;
421 :
422 1 : RA_LIST_GET_HEAD_ENTRY(reqCur, reqNext, head, list, struct RaRequestHandle);
423 1 : for (; (&reqCur->list) != head;
424 0 : reqCur = reqNext, reqNext = list_entry(reqNext->list.next, struct RaRequestHandle, list)) {
425 0 : HdcAsyncDelReqHandle(reqCur, mutex);
426 : }
427 1 : }
428 :
429 0 : STATIC void RaHwAsyncHdcClientDeinit(unsigned int phyId)
430 : {
431 0 : int tryAgain = HDC_TRY_TIME;
432 :
433 : // destroy thread
434 0 : RaHwAsyncSetThreadStatus(phyId, THREAD_DESTROYING);
435 0 : while ((gRaHdcAsync[phyId].threadStatus != THREAD_HALT) && (tryAgain != 0)) {
436 0 : usleep(HDC_USLEEP_TIME);
437 0 : tryAgain--;
438 : }
439 0 : if (tryAgain <= 0) {
440 0 : hccp_warn("hdc async message thread quit timeout");
441 : }
442 :
443 : // close session
444 0 : RaHwAsyncSetConnectStatus(phyId, HDC_UNCONNECTED);
445 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].sendMutex);
446 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].recvMutex);
447 0 : RaHdcDeinitSession(&gRaHdcAsync[phyId].snapshotSession);
448 0 : RaHdcDeinitSession(&gRaHdcAsync[phyId].session);
449 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
450 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].sendMutex);
451 :
452 0 : RaHwAsyncDelList(&gRaHdcAsync[phyId].reqList, &gRaHdcAsync[phyId].reqMutex);
453 0 : RaHwAsyncDelList(&gRaHdcAsync[phyId].rspList, &gRaHdcAsync[phyId].rspMutex);
454 0 : }
455 :
456 0 : STATIC int RaHdcAsyncMutexInit(unsigned int phyId)
457 : {
458 0 : int ret = 0;
459 :
460 0 : ret = pthread_mutex_init(&gRaHdcAsync[phyId].sendMutex, NULL);
461 0 : if (ret != 0) {
462 0 : hccp_err("[init][ra_hdc_async]pthread_mutex_init send_mutex failed ret(%d) phyId(%u)", ret, phyId);
463 0 : return -ESYSFUNC;
464 : }
465 0 : ret = pthread_mutex_init(&gRaHdcAsync[phyId].recvMutex, NULL);
466 0 : if (ret != 0) {
467 0 : hccp_err("[init][ra_hdc_async]pthread_mutex_init recv_mutex failed ret(%d) phyId(%u)", ret, phyId);
468 0 : ret = -ESYSFUNC;
469 0 : goto recv_mutex_fail;
470 : }
471 0 : ret = pthread_mutex_init(&gRaHdcAsync[phyId].reqMutex, NULL);
472 0 : if (ret != 0) {
473 0 : hccp_err("[init][ra_hdc_async]pthread_mutex_init req_mutex failed ret(%d) phyId(%u)", ret, phyId);
474 0 : ret = -ESYSFUNC;
475 0 : goto req_mutex_fail;
476 : }
477 0 : ret = pthread_mutex_init(&gRaHdcAsync[phyId].rspMutex, NULL);
478 0 : if (ret != 0) {
479 0 : hccp_err("[init][ra_hdc_async]pthread_mutex_init rsp_mutex failed ret(%d) phyId(%u)", ret, phyId);
480 0 : ret = -ESYSFUNC;
481 0 : goto rsp_mutex_fail;
482 : }
483 :
484 0 : return 0;
485 :
486 0 : rsp_mutex_fail:
487 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].reqMutex);
488 0 : req_mutex_fail:
489 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].recvMutex);
490 0 : recv_mutex_fail:
491 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].sendMutex);
492 0 : return ret;
493 : }
494 :
495 0 : STATIC void RaHdcAsyncMutexDeinit(unsigned int phyId)
496 : {
497 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].rspMutex);
498 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].reqMutex);
499 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].recvMutex);
500 0 : (void)pthread_mutex_destroy(&gRaHdcAsync[phyId].sendMutex);
501 0 : }
502 :
503 1 : STATIC int RaHdcAsyncInitSession(struct RaInitConfig *cfg)
504 : {
505 1 : unsigned int phyId = cfg->phyId;
506 1 : int timeout = RA_THREAD_TRY_TIME;
507 : pthread_t serverTidp;
508 : pthread_t clientTidp;
509 1 : int ret = 0;
510 :
511 1 : CHK_PRT_RETURN(gRaHdcAsync[phyId].session != NULL, hccp_warn("hdc async session for phyId[%u] already existed",
512 : phyId), -EEXIST);
513 :
514 : // server will be blocked, use a thread to trigger server to accept
515 1 : ret = pthread_create(&serverTidp, NULL, (void *)RaHwAsyncHdcServerInit, cfg);
516 1 : CHK_PRT_RETURN(ret != 0, hccp_err("Create async_hdc_server_init pthread failed, ret(%d)", ret), -ESYSFUNC);
517 :
518 : // client will be blocked, use a thread to trigger client to connect
519 1 : ret = pthread_create(&clientTidp, NULL, (void *)RaHwAsyncHdcClientInit, cfg);
520 1 : CHK_PRT_RETURN(ret != 0, hccp_err("Create async_hdc_client_init pthread failed, ret(%d)", ret), -ESYSFUNC);
521 :
522 : // will block until time out: RA_CONNECT_TRY_TIME * RA_THREAD_SLEEP_TIME us
523 1 : timeout = RA_CONNECT_TRY_TIME;
524 1 : while (gRaHdcAsync[phyId].connectStatus != HDC_CONNECTED && timeout > 0) {
525 0 : usleep(RA_THREAD_SLEEP_TIME);
526 0 : timeout--;
527 : }
528 1 : if (gRaHdcAsync[phyId].connectStatus == HDC_UNCONNECTED || timeout <= 0) {
529 0 : hccp_err("HDC async connect timeout, connectStatus %d, timeout %d, total_timeout %d(us)",
530 : gRaHdcAsync[phyId].connectStatus, timeout, RA_CONNECT_TRY_TIME * RA_THREAD_SLEEP_TIME);
531 0 : return -ETIMEDOUT;
532 : }
533 :
534 1 : gRaHdcAsync[phyId].hostTgid = DlDrvDeviceGetBareTgid();
535 1 : ret = RaHdcAsyncMutexInit(phyId);
536 1 : CHK_PRT_RETURN(ret != 0, hccp_err("ra_hdc_async_mutex_init failed, ret(%d), phyId(%u)", ret, phyId), ret);
537 :
538 0 : RA_INIT_LIST_HEAD(&gRaHdcAsync[phyId].reqList);
539 0 : RA_INIT_LIST_HEAD(&gRaHdcAsync[phyId].rspList);
540 0 : return 0;
541 : }
542 :
543 2 : STATIC void HdcAsyncHandleRecvBroken(struct HdcAsyncInfo *asyncInfo)
544 : {
545 2 : struct RaRequestHandle *reqNext = NULL;
546 2 : struct RaRequestHandle *reqCurr = NULL;
547 :
548 2 : if (!RaHdcIsBroken(asyncInfo->lastRecvStatus)) {
549 0 : return;
550 : }
551 :
552 2 : RA_PTHREAD_MUTEX_LOCK(&asyncInfo->reqMutex);
553 2 : RA_LIST_GET_HEAD_ENTRY(reqCurr, reqNext, &asyncInfo->reqList, list, struct RaRequestHandle);
554 3 : for (; (&reqCurr->list) != &asyncInfo->reqList;
555 1 : reqCurr = reqNext, reqNext = list_entry(reqNext->list.next, struct RaRequestHandle, list)) {
556 1 : RaListDel(&reqCurr->list);
557 1 : HdcAsyncSetReqDone(reqCurr, reqCurr->phyId, asyncInfo->lastRecvStatus);
558 : }
559 2 : RA_PTHREAD_MUTEX_UNLOCK(&asyncInfo->reqMutex);
560 : }
561 :
562 0 : STATIC void *RaHdcRecvMsgAsync(void *arg)
563 : {
564 0 : unsigned int phyId = *(unsigned int *)arg;
565 0 : unsigned int recvLen = MAX_HDC_MSG_DATA;
566 0 : void *recvBuf = NULL;
567 : int ret;
568 :
569 : // free memory after using arg
570 0 : free(arg);
571 0 : arg = NULL;
572 :
573 0 : ret = pthread_detach(pthread_self());
574 0 : CHK_PRT_RETURN(ret, hccp_err("pthread detach failed ret %d, phyId %u", ret, phyId), NULL);
575 :
576 0 : (void)prctl(PR_SET_NAME, (unsigned long)"hccp_ra_async");
577 :
578 0 : hccp_info("[async][ra_hdc_recv]thread[%d] phyId[%u] enter", getpid(), phyId);
579 0 : RaHwAsyncSetThreadStatus(phyId, THREAD_RUNNING);
580 0 : recvBuf = (void *)calloc(recvLen, sizeof(char));
581 0 : CHK_PRT_RETURN(recvBuf == NULL, hccp_err("[async][ra_hdc_recv]calloc recv_buf failed. phyId(%u)", phyId), NULL);
582 :
583 : while (1) {
584 0 : if (gRaHdcAsync[phyId].threadStatus == THREAD_DESTROYING) {
585 0 : break;
586 : }
587 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].recvMutex);
588 0 : if (gRaHdcAsync[phyId].connectStatus != HDC_CONNECTED) {
589 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
590 0 : usleep(THREAD_SLEEP_TIME);
591 0 : continue;
592 : }
593 :
594 0 : if (RaListEmpty(&gRaHdcAsync[phyId].reqList)) {
595 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
596 0 : usleep(THREAD_SLEEP_TIME);
597 0 : continue;
598 : }
599 :
600 0 : recvLen = MAX_HDC_MSG_DATA;
601 0 : ret = HdcAsyncRecvPkt(&gRaHdcAsync[phyId], phyId, recvBuf, &recvLen);
602 0 : if (ret != 0) {
603 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
604 0 : HdcAsyncHandleRecvBroken(&gRaHdcAsync[phyId]);
605 0 : continue;
606 : }
607 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
608 :
609 0 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].reqMutex);
610 0 : (void)HdcAsyncAddResponse(phyId, recvBuf, recvLen);
611 0 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].reqMutex);
612 : }
613 :
614 0 : hccp_info("[async][ra_hdc_recv]thread[%d] phyId[%u] is out", getpid(), phyId);
615 0 : RaHwAsyncSetThreadStatus(phyId, THREAD_HALT);
616 0 : free(recvBuf);
617 0 : recvBuf = NULL;
618 0 : return NULL;
619 : }
620 :
621 0 : STATIC int RaHdcAsyncInitRecvThread(unsigned int phyId)
622 : {
623 0 : unsigned int *phyIdTmp = NULL;
624 0 : int ret = 0;
625 :
626 0 : phyIdTmp = (unsigned int *)calloc(1, sizeof(unsigned int));
627 0 : CHK_PRT_RETURN(phyIdTmp == NULL, hccp_err("calloc phy_id_tmp failed, errno(%d)", errno), -ENOMEM);
628 0 : *phyIdTmp = phyId;
629 :
630 : // create a thread to recv msg from server
631 0 : ret = pthread_create(&gRaHdcAsync[phyId].tid, NULL, RaHdcRecvMsgAsync, (void *)phyIdTmp);
632 0 : if (ret != 0) {
633 0 : hccp_err("Create ra_hdc_recv_msg_async pthread failed, ret(%d)", ret);
634 0 : goto err;
635 : }
636 :
637 0 : return 0;
638 :
639 0 : err:
640 0 : free(phyIdTmp);
641 0 : phyIdTmp = NULL;
642 0 : return ret;
643 : }
644 :
645 1 : int RaHdcInitAsync(struct RaInitConfig *cfg)
646 : {
647 1 : unsigned int interfaceVersion = 0;
648 1 : int ret = 0;
649 :
650 1 : CHK_PRT_RETURN(!cfg->enableHdcAsync, hccp_info("[init][ra_hdc_async]no need to init async hdc session"), 0);
651 :
652 0 : ret = RaHdcGetInterfaceVersion(cfg->phyId, RA_RS_ASYNC_HDC_SESSION_CONNECT, &interfaceVersion);
653 : // normal case: driver not support to or no need to init async hdc session
654 0 : CHK_PRT_RETURN(ret != 0 || interfaceVersion < RA_RS_OPCODE_BASE_VERSION,
655 : hccp_run_warn("[init][ra_hdc_async]not support to init async hdc session, ret(%d), interfaceVersion(%u)",
656 : ret, interfaceVersion), 0);
657 :
658 0 : ret = RaHdcAsyncInitSession(cfg);
659 0 : CHK_PRT_RETURN(ret != 0, hccp_err("[init][ra_hdc_async]ra_hdc_async_init_session failed, ret(%d) phyId(%u)",
660 : ret, cfg->phyId), ret);
661 :
662 0 : ret = RaHdcAsyncInitRecvThread(cfg->phyId);
663 0 : if (ret != 0) {
664 0 : hccp_err("[init][ra_hdc_async]ra_hdc_async_init_recv_thread failed, ret(%d) phyId(%u)", ret, cfg->phyId);
665 0 : goto err;
666 : }
667 :
668 0 : return 0;
669 :
670 0 : err:
671 0 : RaHdcAsyncMutexDeinit(cfg->phyId);
672 0 : return -ESRCH;
673 : }
674 :
675 2 : int RaHdcDeinitAsync(unsigned int phyId)
676 : {
677 : int ret;
678 :
679 2 : hccp_run_info("hdc deinit async start! phyId[%u] restore_flag[%u]", phyId, gRaHdcAsync[phyId].restoreFlag);
680 :
681 2 : CHK_PRT_RETURN(gRaHdcAsync[phyId].session == NULL && gRaHdcAsync[phyId].restoreFlag == 0,
682 : hccp_warn("hdc async session for phyId[%u] is NULL", phyId), -ENODEV);
683 :
684 : // close server session
685 0 : ret = RaHdcAsyncSessionClose(phyId);
686 0 : CHK_PRT_RETURN(ret != 0, hccp_err("[deinit][ra_hdc_async]ra_hdc_async_session_close failed ret[%d] phyId[%u]",
687 : ret, phyId), ret);
688 :
689 : // close client session & deinit client resources
690 0 : RaHwAsyncHdcClientDeinit(phyId);
691 :
692 0 : RaHdcAsyncMutexDeinit(phyId);
693 :
694 0 : (void)memset_s(&gRaHdcAsync[phyId], sizeof(gRaHdcAsync[phyId]), 0, sizeof(gRaHdcAsync[phyId]));
695 :
696 0 : return 0;
697 : }
698 :
699 0 : int RaHdcAsyncSaveSnapshot(unsigned int phyId, enum SaveSnapshotAction action)
700 : {
701 0 : int ret = 0;
702 :
703 0 : if (gRaHdcAsync[phyId].threadStatus == THREAD_HALT) {
704 0 : return 0;
705 : }
706 :
707 : #ifndef HNS_ROCE_LLT
708 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].sendMutex);
709 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].recvMutex);
710 : if (action == SAVE_SNAPSHOT_ACTION_PRE_PROCESSING && gRaHdcAsync[phyId].session != NULL) {
711 : RaHwAsyncSetConnectStatus(phyId, HDC_UNCONNECTED);
712 : gRaHdcAsync[phyId].snapshotSession = gRaHdcAsync[phyId].session;
713 : gRaHdcAsync[phyId].session = NULL;
714 : } else if (action == SAVE_SNAPSHOT_ACTION_POST_PROCESSING && gRaHdcAsync[phyId].session == NULL) {
715 : RaHwAsyncSetConnectStatus(phyId, HDC_CONNECTED);
716 : gRaHdcAsync[phyId].session = gRaHdcAsync[phyId].snapshotSession;
717 : gRaHdcAsync[phyId].snapshotSession = NULL;
718 : } else {
719 : hccp_err("duplicate or incorrect order calls are not allowed, phyId[%u] action[%d]", phyId, action);
720 : ret = -EPERM;
721 : }
722 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
723 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].sendMutex);
724 : #endif
725 0 : return ret;
726 : }
727 :
728 0 : int RaHdcAsyncRestoreSnapshot(unsigned int phyId)
729 : {
730 0 : int ret = 0;
731 :
732 0 : if (gRaHdcAsync[phyId].threadStatus == THREAD_HALT) {
733 0 : return 0;
734 : }
735 :
736 : #ifndef HNS_ROCE_LLT
737 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].sendMutex);
738 : RA_PTHREAD_MUTEX_LOCK(&gRaHdcAsync[phyId].recvMutex);
739 : if (gRaHdcAsync[phyId].connectStatus != HDC_UNCONNECTED) {
740 : hccp_err("incorrect order calls are not allowed, phyId[%u] connectStatus[%u]", phyId,
741 : gRaHdcAsync[phyId].connectStatus);
742 : ret = -EPERM;
743 : } else {
744 : gRaHdcAsync[phyId].restoreFlag = 1;
745 : }
746 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].recvMutex);
747 : RA_PTHREAD_MUTEX_UNLOCK(&gRaHdcAsync[phyId].sendMutex);
748 : #endif
749 0 : return ret;
750 : }
751 :
752 2 : void RaHdcDeinitAsyncAll(void)
753 : {
754 2 : unsigned int phyId = 0;
755 :
756 130 : for (phyId = 0; phyId < RA_MAX_PHY_ID_NUM; phyId++) {
757 128 : if (gRaHdcAsync[phyId].session == NULL || gRaHdcAsync[phyId].threadStatus != THREAD_RUNNING) {
758 128 : continue;
759 : }
760 :
761 0 : (void)RaHdcDeinitAsync(phyId);
762 : }
763 2 : }
|