• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "devmgr_service.h"
10 #include "devhost_service_clnt.h"
11 #include "device_token_clnt.h"
12 #include "devsvc_manager.h"
13 #include "hdf_attribute_manager.h"
14 #include "hdf_base.h"
15 #include "hdf_driver_installer.h"
16 #include "hdf_host_info.h"
17 #include "hdf_log.h"
18 #include "hdf_object_manager.h"
19 #include "osal_time.h"
20 
21 #define HDF_LOG_TAG devmgr_service
22 #define INVALID_PID (-1)
23 
DevmgrServiceDynamicDevInfoFound(const char * svcName,struct DevHostServiceClnt ** targetHostClnt,struct HdfDeviceInfo ** targetDeviceInfo)24 static bool DevmgrServiceDynamicDevInfoFound(
25     const char *svcName, struct DevHostServiceClnt **targetHostClnt, struct HdfDeviceInfo **targetDeviceInfo)
26 {
27     struct HdfSListIterator itDeviceInfo;
28     struct HdfDeviceInfo *deviceInfo = NULL;
29     struct DevHostServiceClnt *hostClnt = NULL;
30     struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance();
31     if (devMgrSvc == NULL) {
32         return false;
33     }
34 
35     DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
36         HdfSListIteratorInit(&itDeviceInfo, &hostClnt->dynamicDevInfos);
37         while (HdfSListIteratorHasNext(&itDeviceInfo)) {
38             deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&itDeviceInfo);
39             if (strcmp(deviceInfo->svcName, svcName) == 0) {
40                 *targetDeviceInfo = deviceInfo;
41                 *targetHostClnt = hostClnt;
42                 return true;
43             }
44         }
45     }
46 
47     return false;
48 }
49 
50 #define WAIT_HOST_SLEEP_TIME    1 // ms
51 #define WAIT_HOST_SLEEP_CNT     1000
DevmgrServiceStartHostProcess(struct DevHostServiceClnt * hostClnt,bool sync,bool dynamic)52 static int DevmgrServiceStartHostProcess(struct DevHostServiceClnt *hostClnt, bool sync, bool dynamic)
53 {
54     int waitCount = WAIT_HOST_SLEEP_CNT;
55     struct IDriverInstaller *installer = DriverInstallerGetInstance();
56     if (installer == NULL || installer->StartDeviceHost == NULL) {
57         HDF_LOGE("invalid installer");
58         return HDF_FAILURE;
59     }
60 
61     hostClnt->hostPid = installer->StartDeviceHost(hostClnt->hostId, hostClnt->hostName, dynamic);
62     if (hostClnt->hostPid == HDF_FAILURE) {
63         HDF_LOGW("failed to start device host(%{public}s, %{public}u)", hostClnt->hostName, hostClnt->hostId);
64         return HDF_FAILURE;
65     }
66     hostClnt->stopFlag = false;
67     if (!sync) {
68         return HDF_SUCCESS;
69     }
70 
71     while (hostClnt->hostService == NULL && waitCount > 0) {
72         OsalMSleep(WAIT_HOST_SLEEP_TIME);
73         waitCount--;
74     }
75 
76     if (waitCount <= 0) {
77         HDF_LOGE("wait host(%{public}s, %{public}d) attach timeout", hostClnt->hostName, hostClnt->hostId);
78         hostClnt->hostPid = -1;
79         return HDF_ERR_TIMEOUT;
80     }
81 
82     return HDF_SUCCESS;
83 }
84 
DevmgrServiceLoadDevice(struct IDevmgrService * devMgrSvc,const char * serviceName)85 static int DevmgrServiceLoadDevice(struct IDevmgrService *devMgrSvc, const char *serviceName)
86 {
87     struct HdfDeviceInfo *deviceInfo = NULL;
88     struct DevHostServiceClnt *hostClnt = NULL;
89     bool dynamic = true;
90     int ret;
91     (void)devMgrSvc;
92 
93     if (serviceName == NULL) {
94         return HDF_ERR_INVALID_PARAM;
95     }
96 
97     if (!DevmgrServiceDynamicDevInfoFound(serviceName, &hostClnt, &deviceInfo)) {
98         HDF_LOGE("device %{public}s not in configed device list", serviceName);
99         return HDF_DEV_ERR_NO_DEVICE;
100     }
101 
102     if (deviceInfo->preload != DEVICE_PRELOAD_DISABLE) {
103         HDF_LOGE("device %{public}s not an dynamic load device", serviceName);
104         return HDF_DEV_ERR_NORANGE;
105     }
106 
107     dynamic = HdfSListIsEmpty(&hostClnt->unloadDevInfos) && !HdfSListIsEmpty(&hostClnt->dynamicDevInfos);
108     OsalMutexLock(&hostClnt->hostLock);
109     if (hostClnt->hostPid < 0) {
110         OsalMutexUnlock(&hostClnt->hostLock);
111         if (DevmgrServiceStartHostProcess(hostClnt, true, dynamic) != HDF_SUCCESS) {
112             HDF_LOGW("failed to start device host(%{public}s, %{public}u)", hostClnt->hostName, hostClnt->hostId);
113             return HDF_FAILURE;
114         }
115         OsalMutexLock(&hostClnt->hostLock);
116     }
117 
118     if (hostClnt->hostService == NULL || hostClnt->hostService->AddDevice == NULL) {
119         OsalMutexUnlock(&hostClnt->hostLock);
120         HDF_LOGE("%{public}s load %{public}s failed, hostService is null", __func__, serviceName);
121         return HDF_FAILURE;
122     }
123     ret = hostClnt->hostService->AddDevice(hostClnt->hostService, deviceInfo);
124     OsalMutexUnlock(&hostClnt->hostLock);
125     if (ret == HDF_SUCCESS) {
126         deviceInfo->status = HDF_SERVICE_USABLE;
127     }
128     return ret;
129 }
130 
DevmgrServiceStopHost(struct DevHostServiceClnt * hostClnt)131 static int DevmgrServiceStopHost(struct DevHostServiceClnt *hostClnt)
132 {
133     struct IDriverInstaller *installer = DriverInstallerGetInstance();
134     if (installer == NULL || installer->StopDeviceHost == NULL) {
135         HDF_LOGE("invalid installer");
136         return HDF_FAILURE;
137     }
138     installer->StopDeviceHost(hostClnt->hostId, hostClnt->hostName);
139     hostClnt->stopFlag = true;
140     return HDF_SUCCESS;
141 }
142 
DevmgrServiceUnloadDevice(struct IDevmgrService * devMgrSvc,const char * serviceName)143 static int DevmgrServiceUnloadDevice(struct IDevmgrService *devMgrSvc, const char *serviceName)
144 {
145     struct HdfDeviceInfo *deviceInfo = NULL;
146     struct DevHostServiceClnt *hostClnt = NULL;
147     int ret;
148     (void)devMgrSvc;
149 
150     if (serviceName == NULL) {
151         return HDF_ERR_INVALID_PARAM;
152     }
153 
154     if (!DevmgrServiceDynamicDevInfoFound(serviceName, &hostClnt, &deviceInfo) ||
155         deviceInfo->preload != DEVICE_PRELOAD_DISABLE) {
156         HDF_LOGE("device %{public}s not in configed dynamic device list", serviceName);
157         return HDF_DEV_ERR_NO_DEVICE;
158     }
159     OsalMutexLock(&hostClnt->hostLock);
160     if (hostClnt->hostService == NULL || hostClnt->hostService->DelDevice == NULL) {
161         OsalMutexUnlock(&hostClnt->hostLock);
162         HDF_LOGE("%{public}s unload %{public}s failed, hostService is null", __func__, serviceName);
163         return HDF_FAILURE;
164     }
165     ret = hostClnt->hostService->DelDevice(hostClnt->hostService, deviceInfo->deviceId);
166     if (ret != HDF_SUCCESS) {
167         OsalMutexUnlock(&hostClnt->hostLock);
168         HDF_LOGI("%{public}s:unload service %{public}s delDevice failed", __func__, serviceName);
169         return ret;
170     }
171     deviceInfo->status = HDF_SERVICE_UNUSABLE;
172     if (!HdfSListIsEmpty(&hostClnt->devices)) {
173         OsalMutexUnlock(&hostClnt->hostLock);
174         HDF_LOGD("%{public}s host %{public}s devices is not empty", __func__, hostClnt->hostName);
175         return HDF_SUCCESS;
176     }
177     hostClnt->hostPid = INVALID_PID;
178     hostClnt->hostService = NULL; // old hostService will be recycled in CleanupDiedHostResources
179     HdfSListFlush(&hostClnt->devices, DeviceTokenClntDelete);
180     OsalMutexUnlock(&hostClnt->hostLock);
181     ret = DevmgrServiceStopHost(hostClnt);
182 
183     return ret;
184 }
185 
DevmgrServiceLoadLeftDriver(struct DevmgrService * devMgrSvc)186 int32_t DevmgrServiceLoadLeftDriver(struct DevmgrService *devMgrSvc)
187 {
188     int32_t ret;
189     struct HdfSListIterator itDeviceInfo;
190     struct HdfDeviceInfo *deviceInfo = NULL;
191     struct DevHostServiceClnt *hostClnt = NULL;
192     if (devMgrSvc == NULL) {
193         return HDF_FAILURE;
194     }
195 
196     DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
197         HdfSListIteratorInit(&itDeviceInfo, &hostClnt->unloadDevInfos);
198         while (HdfSListIteratorHasNext(&itDeviceInfo)) {
199             deviceInfo = (struct HdfDeviceInfo *)HdfSListIteratorNext(&itDeviceInfo);
200             if (deviceInfo->preload == DEVICE_PRELOAD_ENABLE_STEP2) {
201                 ret = hostClnt->hostService->AddDevice(hostClnt->hostService, deviceInfo);
202                 if (ret != HDF_SUCCESS) {
203                     HDF_LOGE("%{public}s:failed to load driver %{public}s", __func__, deviceInfo->moduleName);
204                     continue;
205                 }
206                 deviceInfo->status = HDF_SERVICE_USABLE;
207                 HdfSListIteratorRemove(&itDeviceInfo);
208             }
209         }
210     }
211     return HDF_SUCCESS;
212 }
213 
DevmgrServiceFindDeviceHost(struct IDevmgrService * inst,uint16_t hostId)214 static struct DevHostServiceClnt *DevmgrServiceFindDeviceHost(struct IDevmgrService *inst, uint16_t hostId)
215 {
216     struct DevHostServiceClnt *hostClnt = NULL;
217     struct DevmgrService *dmService = (struct DevmgrService *)inst;
218     if (dmService == NULL) {
219         HDF_LOGE("failed to find device host, dmService is null");
220         return NULL;
221     }
222 
223     DLIST_FOR_EACH_ENTRY(hostClnt, &dmService->hosts, struct DevHostServiceClnt, node) {
224         if (hostClnt->hostId == hostId) {
225             return hostClnt;
226         }
227     }
228     HDF_LOGE("cannot find host %{public}u", hostId);
229     return NULL;
230 }
231 
DevmgrServiceAttachDevice(struct IDevmgrService * inst,struct IHdfDeviceToken * token)232 static int DevmgrServiceAttachDevice(struct IDevmgrService *inst, struct IHdfDeviceToken *token)
233 {
234     struct DevHostServiceClnt *hostClnt = NULL;
235     struct DeviceTokenClnt *tokenClnt = NULL;
236 
237     if (token == NULL) {
238         return HDF_FAILURE;
239     }
240     hostClnt = DevmgrServiceFindDeviceHost(inst, HOSTID(token->devid));
241     if (hostClnt == NULL) {
242         HDF_LOGE("failed to attach device, hostClnt is null");
243         return HDF_FAILURE;
244     }
245     tokenClnt = DeviceTokenClntNewInstance(token);
246     if (tokenClnt == NULL) {
247         HDF_LOGE("failed to attach device, tokenClnt is null");
248         return HDF_FAILURE;
249     }
250 
251     HdfSListAdd(&hostClnt->devices, &tokenClnt->node);
252     return HDF_SUCCESS;
253 }
254 
HdfSListHostSearchDeviceTokenComparer(struct HdfSListNode * tokenNode,uint32_t devid)255 static bool HdfSListHostSearchDeviceTokenComparer(struct HdfSListNode *tokenNode, uint32_t devid)
256 {
257     struct DeviceTokenClnt *tokenClnt = CONTAINER_OF(tokenNode, struct DeviceTokenClnt, node);
258     return tokenClnt->tokenIf->devid == devid;
259 }
260 
DevmgrServiceDetachDevice(struct IDevmgrService * inst,devid_t devid)261 static int DevmgrServiceDetachDevice(struct IDevmgrService *inst, devid_t devid)
262 {
263     struct DevHostServiceClnt *hostClnt = NULL;
264     struct DeviceTokenClnt *tokenClnt = NULL;
265     struct HdfSListNode *tokenClntNode = NULL;
266 
267     hostClnt = DevmgrServiceFindDeviceHost(inst, HOSTID(devid));
268     if (hostClnt == NULL) {
269         HDF_LOGE("failed to attach device, hostClnt is null");
270         return HDF_FAILURE;
271     }
272     tokenClntNode = HdfSListSearch(&hostClnt->devices, devid, HdfSListHostSearchDeviceTokenComparer);
273     if (tokenClntNode == NULL) {
274         HDF_LOGE("devmgr detach device %{public}x not found", devid);
275         return HDF_DEV_ERR_NO_DEVICE;
276     }
277     tokenClnt = CONTAINER_OF(tokenClntNode, struct DeviceTokenClnt, node);
278     HdfSListRemove(&hostClnt->devices, &tokenClnt->node);
279     return HDF_SUCCESS;
280 }
281 
DevmgrServiceAttachDeviceHost(struct IDevmgrService * inst,uint16_t hostId,struct IDevHostService * hostService)282 static int DevmgrServiceAttachDeviceHost(
283     struct IDevmgrService *inst, uint16_t hostId, struct IDevHostService *hostService)
284 {
285     struct DevHostServiceClnt *hostClnt = DevmgrServiceFindDeviceHost(inst, hostId);
286     if (hostClnt == NULL) {
287         HDF_LOGE("failed to attach device host, hostClnt is null");
288         return HDF_FAILURE;
289     }
290     if (hostService == NULL) {
291         HDF_LOGE("failed to attach device host, hostService is null");
292         return HDF_FAILURE;
293     }
294 
295     (void)OsalMutexLock(&hostClnt->hostLock);
296     hostClnt->hostService = hostService;
297     (void)OsalMutexUnlock(&hostClnt->hostLock);
298     return DevHostServiceClntInstallDriver(hostClnt);
299 }
300 
DevmgrServiceStartDeviceHost(struct DevmgrService * devmgr,struct HdfHostInfo * hostAttr)301 static int DevmgrServiceStartDeviceHost(struct DevmgrService *devmgr, struct HdfHostInfo *hostAttr)
302 {
303     struct DevHostServiceClnt *hostClnt = DevHostServiceClntNewInstance(hostAttr->hostId, hostAttr->hostName);
304     if (hostClnt == NULL) {
305         HDF_LOGW("failed to create new device host client");
306         return HDF_FAILURE;
307     }
308 
309     if (HdfAttributeManagerGetDeviceList(hostClnt) != HDF_SUCCESS) {
310         HDF_LOGW("failed to get device list for host %{public}s", hostClnt->hostName);
311         return HDF_FAILURE;
312     }
313 
314     DListInsertTail(&hostClnt->node, &devmgr->hosts);
315 
316     // not start the host which only have dynamic devices
317     if (HdfSListIsEmpty(&hostClnt->unloadDevInfos)) {
318         return HDF_SUCCESS;
319     }
320 
321     if (DevmgrServiceStartHostProcess(hostClnt, false, false) != HDF_SUCCESS) {
322         HDF_LOGW("failed to start device host, host id is %{public}u", hostAttr->hostId);
323         DListRemove(&hostClnt->node);
324         DevHostServiceClntFreeInstance(hostClnt);
325         return HDF_FAILURE;
326     }
327     return HDF_SUCCESS;
328 }
329 
DevmgrServiceStartDeviceHosts(struct DevmgrService * inst)330 static int DevmgrServiceStartDeviceHosts(struct DevmgrService *inst)
331 {
332     int ret;
333     struct HdfSList hostList;
334     struct HdfSListIterator it;
335     struct HdfHostInfo *hostAttr = NULL;
336 
337     HdfSListInit(&hostList);
338     if (!HdfAttributeManagerGetHostList(&hostList)) {
339         HDF_LOGW("%s: host list is null", __func__);
340         return HDF_SUCCESS;
341     }
342     HdfSListIteratorInit(&it, &hostList);
343     while (HdfSListIteratorHasNext(&it)) {
344         hostAttr = (struct HdfHostInfo *)HdfSListIteratorNext(&it);
345         ret = DevmgrServiceStartDeviceHost(inst, hostAttr);
346         if (ret != HDF_SUCCESS) {
347             HDF_LOGW("%{public}s failed to start device host, host id is %{public}u, host name is '%{public}s'",
348                 __func__, hostAttr->hostId, hostAttr->hostName);
349         }
350     }
351     HdfSListFlush(&hostList, HdfHostInfoDelete);
352     return HDF_SUCCESS;
353 }
354 
DevmgrServiceListAllDevice(struct IDevmgrService * inst,struct HdfSBuf * reply)355 static int32_t DevmgrServiceListAllDevice(struct IDevmgrService *inst, struct HdfSBuf *reply)
356 {
357     struct DevmgrService *devMgrSvc = (struct DevmgrService *)inst;
358     struct DevHostServiceClnt *hostClnt = NULL;
359     struct HdfSListIterator iterator;
360     struct HdfSListNode *node = NULL;
361     const char *name = NULL;
362 
363     if (devMgrSvc == NULL || reply == NULL) {
364         HDF_LOGE("%{public}s failed, parameter is null", __func__);
365         return HDF_FAILURE;
366     }
367 
368     DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
369         HdfSbufWriteString(reply, hostClnt->hostName);
370         HdfSbufWriteUint32(reply, hostClnt->hostId);
371         HdfSbufWriteUint32(reply, HdfSListCount(&hostClnt->devices));
372 
373         HdfSListIteratorInit(&iterator, &hostClnt->devices);
374         while (HdfSListIteratorHasNext(&iterator)) {
375             node = HdfSListIteratorNext(&iterator);
376             struct DeviceTokenClnt *tokenClnt = (struct DeviceTokenClnt *)node;
377             if (tokenClnt != NULL && tokenClnt->tokenIf != NULL) {
378                 name = (tokenClnt->tokenIf->deviceName == NULL) ? "" : tokenClnt->tokenIf->deviceName;
379                 HdfSbufWriteString(reply, name);
380                 HdfSbufWriteUint32(reply, tokenClnt->tokenIf->devid);
381                 name = (tokenClnt->tokenIf->servName == NULL) ? "" : tokenClnt->tokenIf->servName;
382                 HdfSbufWriteString(reply, name);
383             } else {
384                 HDF_LOGI("%{public}s host:%{public}s token null", __func__, hostClnt->hostName);
385             }
386         }
387     }
388     return HDF_SUCCESS;
389 }
390 
DevmgrServiceStartService(struct IDevmgrService * inst)391 int DevmgrServiceStartService(struct IDevmgrService *inst)
392 {
393     int ret;
394     struct DevmgrService *dmService = (struct DevmgrService *)inst;
395     if (dmService == NULL) {
396         HDF_LOGE("failed to start device manager service, dmService is null");
397         return HDF_FAILURE;
398     }
399 
400     ret = DevSvcManagerStartService();
401     HDF_LOGI("start svcmgr result %{public}d", ret);
402 
403     return DevmgrServiceStartDeviceHosts(dmService);
404 }
405 
DevmgrServicePowerStateChange(struct IDevmgrService * devmgrService,enum HdfPowerState powerState)406 int DevmgrServicePowerStateChange(struct IDevmgrService *devmgrService, enum HdfPowerState powerState)
407 {
408     struct DevHostServiceClnt *hostClient = NULL;
409     struct DevmgrService *devmgr = NULL;
410     int result = HDF_SUCCESS;
411 
412     if (devmgrService == NULL) {
413         return HDF_ERR_INVALID_OBJECT;
414     }
415 
416     if (!IsValidPowerState(powerState)) {
417         HDF_LOGE("%{public}s:invalid power event %{public}u", __func__, powerState);
418         return HDF_ERR_INVALID_PARAM;
419     }
420     devmgr = CONTAINER_OF(devmgrService, struct DevmgrService, super);
421 
422     if (IsPowerWakeState(powerState)) {
423         HDF_LOGI("%{public}s:wake state %{public}u", __func__, powerState);
424         DLIST_FOR_EACH_ENTRY(hostClient, &devmgr->hosts, struct DevHostServiceClnt, node) {
425             if (hostClient->hostService != NULL) {
426                 if (hostClient->hostService->PmNotify(hostClient->hostService, powerState) != HDF_SUCCESS) {
427                     result = HDF_FAILURE;
428                 }
429             }
430         }
431     } else {
432         HDF_LOGI("%{public}s:suspend state %{public}u", __func__, powerState);
433         DLIST_FOR_EACH_ENTRY_REVERSE(hostClient, &devmgr->hosts, struct DevHostServiceClnt, node) {
434             if (hostClient->hostService != NULL) {
435                 if (hostClient->hostService->PmNotify(hostClient->hostService, powerState) != HDF_SUCCESS) {
436                     result = HDF_FAILURE;
437                 }
438             }
439         }
440     }
441 
442     return result;
443 }
444 
DevmgrServiceConstruct(struct DevmgrService * inst)445 bool DevmgrServiceConstruct(struct DevmgrService *inst)
446 {
447     struct IDevmgrService *devMgrSvcIf = NULL;
448     if (OsalMutexInit(&inst->devMgrMutex) != HDF_SUCCESS) {
449         HDF_LOGE("%s:failed to mutex init ", __func__);
450         return false;
451     }
452     devMgrSvcIf = (struct IDevmgrService *)inst;
453     if (devMgrSvcIf != NULL) {
454         devMgrSvcIf->AttachDevice = DevmgrServiceAttachDevice;
455         devMgrSvcIf->DetachDevice = DevmgrServiceDetachDevice;
456         devMgrSvcIf->LoadDevice = DevmgrServiceLoadDevice;
457         devMgrSvcIf->UnloadDevice = DevmgrServiceUnloadDevice;
458         devMgrSvcIf->AttachDeviceHost = DevmgrServiceAttachDeviceHost;
459         devMgrSvcIf->StartService = DevmgrServiceStartService;
460         devMgrSvcIf->PowerStateChange = DevmgrServicePowerStateChange;
461         devMgrSvcIf->ListAllDevice = DevmgrServiceListAllDevice;
462         DListHeadInit(&inst->hosts);
463         return true;
464     } else {
465         return false;
466     }
467 }
468 
DevmgrServiceCreate(void)469 struct HdfObject *DevmgrServiceCreate(void)
470 {
471     static bool isDevMgrServiceInit = false;
472     static struct DevmgrService devmgrServiceInstance;
473     if (!isDevMgrServiceInit) {
474         if (!DevmgrServiceConstruct(&devmgrServiceInstance)) {
475             return NULL;
476         }
477         isDevMgrServiceInit = true;
478     }
479     return (struct HdfObject *)&devmgrServiceInstance;
480 }
481 
DevmgrServiceGetInstance(void)482 struct IDevmgrService *DevmgrServiceGetInstance(void)
483 {
484     static struct IDevmgrService *instance = NULL;
485     if (instance == NULL) {
486         instance = (struct IDevmgrService *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVMGR_SERVICE);
487     }
488     return instance;
489 }
490 
DevmgrServiceRelease(struct HdfObject * object)491 void DevmgrServiceRelease(struct HdfObject *object)
492 {
493     struct DevmgrService *devmgrService = (struct DevmgrService *)object;
494     struct DevHostServiceClnt *hostClnt = NULL;
495     struct DevHostServiceClnt *hostClntTmp = NULL;
496     if (devmgrService == NULL) {
497         return;
498     }
499     DLIST_FOR_EACH_ENTRY_SAFE(hostClnt, hostClntTmp, &devmgrService->hosts, struct DevHostServiceClnt, node) {
500         DListRemove(&hostClnt->node);
501         DevHostServiceClntDelete(hostClnt);
502     }
503 
504     OsalMutexDestroy(&devmgrService->devMgrMutex);
505 }
506