[IE][VPU][XLink]: XLink semaphore wrappers impl (#3079)
[platform/upstream/dldt.git] / inference-engine / thirdparty / movidius / XLink / shared / src / XLinkDevice.c
1 // Copyright (C) 2018-2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include "stdio.h"
6 #include "stdint.h"
7 #include "string.h"
8 #include "stdlib.h"
9
10 #include "XLink.h"
11 #include "XLinkErrorUtils.h"
12
13 #include "XLinkPlatform.h"
14 #include "XLinkPrivateFields.h"
15 #include "XLinkDispatcherImpl.h"
16
17 #ifdef MVLOG_UNIT_NAME
18 #undef MVLOG_UNIT_NAME
19 #define MVLOG_UNIT_NAME xLink
20 #endif
21 #include "XLinkLog.h"
22 #include "XLinkStringUtils.h"
23
24 #define MAX_PATH_LENGTH (255)
25
26 // ------------------------------------
27 // Global fields. Begin.
28 // ------------------------------------
29
30 XLinkGlobalHandler_t* glHandler; //TODO need to either protect this with semaphor
31                                  //or make profiling data per device
32
33 xLinkDesc_t availableXLinks[MAX_LINKS];
34 sem_t  pingSem; //to b used by myriad
35 DispatcherControlFunctions controlFunctionTbl;
36 linkId_t nextUniqueLinkId = 0; //incremental number, doesn't get decremented.
37
38 // ------------------------------------
39 // Global fields. End.
40 // ------------------------------------
41
42
43
44 // ------------------------------------
45 // Helpers declaration. Begin.
46 // ------------------------------------
47
48 static linkId_t getNextAvailableLinkUniqueId();
49 static xLinkDesc_t* getNextAvailableLink();
50
51 #ifdef __PC__
52
53 static XLinkError_t parsePlatformError(xLinkPlatformErrorCode_t rc);
54
55 #endif // __PC__
56
57 // ------------------------------------
58 // Helpers declaration. End.
59 // ------------------------------------
60
61
62
63 // ------------------------------------
64 // API implementation. Begin.
65 // ------------------------------------
66
67 XLinkError_t XLinkInitialize(XLinkGlobalHandler_t* globalHandler)
68 {
69 #ifndef __PC__
70     mvLogLevelSet(MVLOG_FATAL);
71     mvLogDefaultLevelSet(MVLOG_FATAL);
72 #endif
73
74     XLINK_RET_IF(globalHandler == NULL);
75     ASSERT_XLINK(XLINK_MAX_STREAMS <= MAX_POOLS_ALLOC);
76     glHandler = globalHandler;
77     if (sem_init(&pingSem,0,0)) {
78         mvLog(MVLOG_ERROR, "Can't create semaphore\n");
79     }
80     int i;
81
82     XLinkPlatformInit();
83
84     //Using deprecated fields. Begin.
85     int loglevel = globalHandler->loglevel;
86     int protocol = globalHandler->protocol;
87     //Using deprecated fields. End.
88
89     memset((void*)globalHandler, 0, sizeof(XLinkGlobalHandler_t));
90
91     //Using deprecated fields. Begin.
92     globalHandler->loglevel = loglevel;
93     globalHandler->protocol = protocol;
94     //Using deprecated fields. End.
95
96     controlFunctionTbl.eventReceive      = &dispatcherEventReceive;
97     controlFunctionTbl.eventSend         = &dispatcherEventSend;
98     controlFunctionTbl.localGetResponse  = &dispatcherLocalEventGetResponse;
99     controlFunctionTbl.remoteGetResponse = &dispatcherRemoteEventGetResponse;
100     controlFunctionTbl.closeLink         = &dispatcherCloseLink;
101     controlFunctionTbl.closeDeviceFd     = &dispatcherCloseDeviceFd;
102
103     XLINK_RET_IF(DispatcherInitialize(&controlFunctionTbl));
104
105     //initialize availableStreams
106     memset(availableXLinks, 0, sizeof(availableXLinks));
107
108     xLinkDesc_t* link;
109     for (i = 0; i < MAX_LINKS; i++) {
110         link = &availableXLinks[i];
111
112         link->id = INVALID_LINK_ID;
113         link->deviceHandle.xLinkFD = NULL;
114         link->peerState = XLINK_NOT_INIT;
115         int stream;
116         for (stream = 0; stream < XLINK_MAX_STREAMS; stream++)
117             link->availableStreams[stream].id = INVALID_STREAM_ID;
118     }
119
120 #ifndef __PC__
121     link = getNextAvailableLink();
122     if (link == NULL)
123         return X_LINK_COMMUNICATION_NOT_OPEN;
124
125     link->id = getNextAvailableLinkUniqueId();
126     link->peerState = XLINK_UP;
127     link->deviceHandle.xLinkFD = NULL;
128
129     xLinkDeviceHandle_t temp = {0};
130     temp.protocol = X_LINK_ANY_PROTOCOL;
131     XLINK_RET_IF_FAIL(DispatcherStart(&temp)); //myriad has one
132
133     sem_wait(&pingSem);
134 #endif
135
136     return X_LINK_SUCCESS;
137 }
138
139 #ifdef __PC__
140
141 int XLinkIsDescriptionValid(const deviceDesc_t *in_deviceDesc, const XLinkDeviceState_t state) {
142     return XLinkPlatformIsDescriptionValid(in_deviceDesc, state);
143 }
144
145 XLinkError_t XLinkFindFirstSuitableDevice(XLinkDeviceState_t state,
146                                           const deviceDesc_t in_deviceRequirements,
147                                           deviceDesc_t *out_foundDevice)
148 {
149     XLINK_RET_IF(out_foundDevice == NULL);
150
151     xLinkPlatformErrorCode_t rc;
152     rc = XLinkPlatformFindDeviceName(state, in_deviceRequirements, out_foundDevice);
153     return parsePlatformError(rc);
154 }
155
156 XLinkError_t XLinkFindAllSuitableDevices(XLinkDeviceState_t state,
157                                          const deviceDesc_t in_deviceRequirements,
158                                          deviceDesc_t *out_foundDevicesPtr,
159                                          const unsigned int devicesArraySize,
160                                          unsigned int* out_foundDevicesCount) {
161     XLINK_RET_IF(out_foundDevicesPtr == NULL);
162     XLINK_RET_IF(devicesArraySize <= 0);
163     XLINK_RET_IF(out_foundDevicesCount == NULL);
164
165     xLinkPlatformErrorCode_t rc;
166     rc = XLinkPlatformFindArrayOfDevicesNames(
167         state, in_deviceRequirements,
168         out_foundDevicesPtr, devicesArraySize, out_foundDevicesCount);
169
170     return parsePlatformError(rc);
171 }
172
173 //Called only from app - per device
174 XLinkError_t XLinkConnect(XLinkHandler_t* handler)
175 {
176     XLINK_RET_IF(handler == NULL);
177     if (strnlen(handler->devicePath, MAX_PATH_LENGTH) < 2) {
178         mvLog(MVLOG_ERROR, "Device path is incorrect");
179         return X_LINK_ERROR;
180     }
181
182     xLinkDesc_t* link = getNextAvailableLink();
183     XLINK_RET_IF(link == NULL);
184     mvLog(MVLOG_DEBUG,"%s() device name %s glHandler %p protocol %d\n", __func__, handler->devicePath, glHandler, handler->protocol);
185
186     link->deviceHandle.protocol = handler->protocol;
187     int connectStatus = XLinkPlatformConnect(handler->devicePath2, handler->devicePath,
188                                              link->deviceHandle.protocol, &link->deviceHandle.xLinkFD);
189
190     if (connectStatus < 0) {
191         /**
192          * Connection may be unsuccessful at some amount of first tries.
193          * In this case, asserting the status provides enormous amount of logs in tests.
194          */
195         return X_LINK_COMMUNICATION_NOT_OPEN;
196     }
197
198     XLINK_RET_ERR_IF(
199         DispatcherStart(&link->deviceHandle) != X_LINK_SUCCESS, X_LINK_TIMEOUT);
200
201     xLinkEvent_t event = {0};
202
203     event.header.type = XLINK_PING_REQ;
204     event.deviceHandle = link->deviceHandle;
205     DispatcherAddEvent(EVENT_LOCAL, &event);
206
207     if (DispatcherWaitEventComplete(&link->deviceHandle)) {
208         DispatcherClean(&link->deviceHandle);
209         return X_LINK_TIMEOUT;
210     }
211
212     link->id = getNextAvailableLinkUniqueId();
213     link->peerState = XLINK_UP;
214     link->hostClosedFD = 0;
215     handler->linkId = link->id;
216     return X_LINK_SUCCESS;
217 }
218
219 XLinkError_t XLinkBoot(deviceDesc_t* deviceDesc, const char* binaryPath)
220 {
221     if (XLinkPlatformBootRemote(deviceDesc, binaryPath) == 0) {
222         return X_LINK_SUCCESS;
223     }
224
225     return X_LINK_COMMUNICATION_FAIL;
226 }
227
228 XLinkError_t XLinkBootFirmware(deviceDesc_t* deviceDesc, const char* firmware, unsigned long length) {
229     if (!XLinkPlatformBootFirmware(deviceDesc, firmware, length)) {
230         return X_LINK_SUCCESS;
231     }
232
233     return X_LINK_COMMUNICATION_FAIL;
234 }
235
236 XLinkError_t XLinkResetRemote(linkId_t id)
237 {
238     xLinkDesc_t* link = getLinkById(id);
239     XLINK_RET_IF(link == NULL);
240
241     if (getXLinkState(link) != XLINK_UP) {
242         mvLog(MVLOG_WARN, "Link is down, close connection to device without reset");
243         XLinkPlatformCloseRemote(&link->deviceHandle);
244         return X_LINK_COMMUNICATION_NOT_OPEN;
245     }
246
247     // Add event to reset device. After sending it, dispatcher will close fd link
248     xLinkEvent_t event = {0};
249     event.header.type = XLINK_RESET_REQ;
250     event.deviceHandle = link->deviceHandle;
251     mvLog(MVLOG_DEBUG, "sending reset remote event\n");
252     DispatcherAddEvent(EVENT_LOCAL, &event);
253     XLINK_RET_ERR_IF(DispatcherWaitEventComplete(&link->deviceHandle),
254         X_LINK_TIMEOUT);
255
256     if(XLink_sem_wait(&link->dispatcherClosedSem)) {
257         mvLog(MVLOG_ERROR,"can't wait dispatcherClosedSem\n");
258         return X_LINK_ERROR;
259     }
260
261     return X_LINK_SUCCESS;
262 }
263
264 XLinkError_t XLinkResetAll()
265 {
266 #if defined(NO_BOOT)
267     mvLog(MVLOG_INFO, "Devices will not be restarted for this configuration (NO_BOOT)");
268 #else
269     int i;
270     for (i = 0; i < MAX_LINKS; i++) {
271         if (availableXLinks[i].id != INVALID_LINK_ID) {
272             xLinkDesc_t* link = &availableXLinks[i];
273             int stream;
274             for (stream = 0; stream < XLINK_MAX_STREAMS; stream++) {
275                 if (link->availableStreams[stream].id != INVALID_STREAM_ID) {
276                     streamId_t streamId = link->availableStreams[stream].id;
277                     mvLog(MVLOG_DEBUG,"%s() Closing stream (stream = %d) %d on link %d\n",
278                           __func__, stream, (int) streamId, (int) link->id);
279                     COMBINE_IDS(streamId, link->id);
280                     if (XLinkCloseStream(streamId) != X_LINK_SUCCESS) {
281                         mvLog(MVLOG_WARN,"Failed to close stream");
282                     }
283                 }
284             }
285             if (XLinkResetRemote(link->id) != X_LINK_SUCCESS) {
286                 mvLog(MVLOG_WARN,"Failed to reset");
287             }
288         }
289     }
290 #endif
291     return X_LINK_SUCCESS;
292 }
293
294 #endif // __PC__
295
296 XLinkError_t XLinkProfStart()
297 {
298     glHandler->profEnable = 1;
299     glHandler->profilingData.totalReadBytes = 0;
300     glHandler->profilingData.totalWriteBytes = 0;
301     glHandler->profilingData.totalWriteTime = 0;
302     glHandler->profilingData.totalReadTime = 0;
303     glHandler->profilingData.totalBootCount = 0;
304     glHandler->profilingData.totalBootTime = 0;
305
306     return X_LINK_SUCCESS;
307 }
308
309 XLinkError_t XLinkProfStop()
310 {
311     glHandler->profEnable = 0;
312     return X_LINK_SUCCESS;
313 }
314
315 XLinkError_t XLinkProfPrint()
316 {
317     printf("XLink profiling results:\n");
318     if (glHandler->profilingData.totalWriteTime)
319     {
320         printf("Average write speed: %f MB/Sec\n",
321                glHandler->profilingData.totalWriteBytes /
322                glHandler->profilingData.totalWriteTime /
323                1024.0 /
324                1024.0 );
325     }
326     if (glHandler->profilingData.totalReadTime)
327     {
328         printf("Average read speed: %f MB/Sec\n",
329                glHandler->profilingData.totalReadBytes /
330                glHandler->profilingData.totalReadTime /
331                1024.0 /
332                1024.0);
333     }
334     if (glHandler->profilingData.totalBootCount)
335     {
336         printf("Average boot speed: %f sec\n",
337                glHandler->profilingData.totalBootTime /
338                glHandler->profilingData.totalBootCount);
339     }
340     return X_LINK_SUCCESS;
341 }
342
343 // ------------------------------------
344 // API implementation. End.
345 // ------------------------------------
346
347
348 // ------------------------------------
349 // Helpers implementation. Begin.
350 // ------------------------------------
351
352 static linkId_t getNextAvailableLinkUniqueId()
353 {
354     linkId_t start = nextUniqueLinkId;
355     do
356     {
357         int i;
358         for (i = 0; i < MAX_LINKS; i++)
359         {
360             if (availableXLinks[i].id != INVALID_LINK_ID &&
361                 availableXLinks[i].id == nextUniqueLinkId)
362                 break;
363         }
364         if (i >= MAX_LINKS)
365         {
366             return nextUniqueLinkId;
367         }
368         nextUniqueLinkId++;
369         if (nextUniqueLinkId == INVALID_LINK_ID)
370         {
371             nextUniqueLinkId = 0;
372         }
373     } while (start != nextUniqueLinkId);
374     mvLog(MVLOG_ERROR, "%s():- no next available unique link id!\n", __func__);
375     return INVALID_LINK_ID;
376 }
377
378 static xLinkDesc_t* getNextAvailableLink() {
379     int i;
380     for (i = 0; i < MAX_LINKS; i++) {
381         if (availableXLinks[i].id == INVALID_LINK_ID) {
382             break;
383         }
384     }
385
386     if(i >= MAX_LINKS) {
387         mvLog(MVLOG_ERROR,"%s():- no next available link!\n", __func__);
388         return NULL;
389     }
390
391     xLinkDesc_t* link = &availableXLinks[i];
392
393     if (XLink_sem_init(&link->dispatcherClosedSem, 0 ,0)) {
394         mvLog(MVLOG_ERROR, "Cannot initialize semaphore\n");
395         return NULL;
396     }
397
398     return link;
399 }
400
401 #ifdef __PC__
402
403 static XLinkError_t parsePlatformError(xLinkPlatformErrorCode_t rc) {
404     switch (rc) {
405         case X_LINK_PLATFORM_SUCCESS:
406             return X_LINK_SUCCESS;
407         case X_LINK_PLATFORM_DEVICE_NOT_FOUND:
408             return X_LINK_DEVICE_NOT_FOUND;
409         case X_LINK_PLATFORM_TIMEOUT:
410             return X_LINK_TIMEOUT;
411         default:
412             return X_LINK_ERROR;
413     }
414 }
415
416 #endif // __PC__
417
418 // ------------------------------------
419 // Helpers implementation. End.
420 // ------------------------------------