• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 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 "platform_manager.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "osal_sem.h"
13 #include "platform_core.h"
14 
15 #define PLATFORM_MANAGER_NAME_DEFAULT "PlatformManagerDefault"
16 
PlatformManagerLock(struct PlatformManager * manager)17 static inline void PlatformManagerLock(struct PlatformManager *manager)
18 {
19     (void)OsalSpinLockIrqSave(&manager->device.spin, &manager->device.irqSave);
20 }
21 
PlatformManagerUnlock(struct PlatformManager * manager)22 static inline void PlatformManagerUnlock(struct PlatformManager *manager)
23 {
24     (void)OsalSpinUnlockIrqRestore(&manager->device.spin, &manager->device.irqSave);
25 }
26 
PlatformManagerInit(struct PlatformManager * manager)27 static int32_t PlatformManagerInit(struct PlatformManager *manager)
28 {
29     int32_t ret;
30 
31     DListHeadInit(&manager->devices);
32 
33     if ((ret = PlatformDeviceInit(&manager->device)) != HDF_SUCCESS) {
34         return ret;
35     }
36 
37     manager->add = NULL;
38     manager->del = NULL;
39     return HDF_SUCCESS;
40 }
41 
PlatformManagerClearDevice(struct PlatformManager * manager)42 static void PlatformManagerClearDevice(struct PlatformManager *manager)
43 {
44     struct PlatformDevice *tmp = NULL;
45     struct PlatformDevice *pos = NULL;
46 
47     if (manager == NULL) {
48         return;
49     }
50 
51     PlatformManagerLock(manager);
52     DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->devices, struct PlatformDevice, node) {
53         DListRemove(&pos->node);
54         PlatformDevicePut(pos);  // put the reference hold by manager
55     }
56     PlatformManagerUnlock(manager);
57 }
58 
PlatformManagerUninit(struct PlatformManager * manager)59 static void PlatformManagerUninit(struct PlatformManager *manager)
60 {
61     PlatformManagerClearDevice(manager);
62     PlatformDeviceUninit(&manager->device);
63     manager->add = NULL;
64     manager->del = NULL;
65 }
66 
PlatformManagerCreate(const char * name,struct PlatformManager ** manager)67 int32_t PlatformManagerCreate(const char *name, struct PlatformManager **manager)
68 {
69     int32_t ret;
70     struct PlatformManager *managerNew = NULL;
71 
72     managerNew = (struct PlatformManager *)OsalMemCalloc(sizeof(*managerNew));
73     if (managerNew == NULL) {
74         PLAT_LOGE("PlatformManagerCreate: malloc fail!");
75         return HDF_ERR_MALLOC_FAIL;
76     }
77     managerNew->device.name = name;
78     if ((ret = PlatformManagerInit(managerNew)) != HDF_SUCCESS) {
79         OsalMemFree(managerNew);
80         return ret;
81     }
82     *manager = managerNew;
83     return ret;
84 }
85 
PlatformManagerDestroy(struct PlatformManager * manager)86 void PlatformManagerDestroy(struct PlatformManager *manager)
87 {
88     if (manager == NULL) {
89         return;
90     }
91     PlatformManagerUninit(manager);
92     OsalMemFree(manager);
93 }
94 
PlatformManagerGet(int module)95 struct PlatformManager *PlatformManagerGet(int module)
96 {
97     int32_t ret;
98     struct PlatformManager *manager = NULL;
99     struct PlatformModuleInfo *info = NULL;
100 
101     info = PlatformModuleInfoGet(module);
102     if (info == NULL) {
103         PLAT_LOGE("PlatformManagerGet: get module(%d) info failed", module);
104         return NULL;
105     }
106 
107     PlatformGlobalLock();
108     if (info->priv == NULL) {
109         ret = PlatformManagerCreate(info->moduleName, &manager);
110         if (ret != HDF_SUCCESS) {
111             PLAT_LOGE("PlatformManagerGet: create manager failed:%d", ret);
112         } else {
113             info->priv = manager;
114         }
115     } else {
116         manager = (struct PlatformManager *)info->priv;
117     }
118     PlatformGlobalUnlock();
119 
120     return manager;
121 }
122 
PlatformManagerAddDeviceDefault(struct PlatformManager * manager,struct PlatformDevice * device)123 static int32_t PlatformManagerAddDeviceDefault(struct PlatformManager *manager, struct PlatformDevice *device)
124 {
125     struct PlatformDevice *tmp = NULL;
126     bool repeatId = false;
127     bool repeatName = false;
128 
129     DLIST_FOR_EACH_ENTRY(tmp, &manager->devices, struct PlatformDevice, node) {
130         if (device->number == tmp->number) {
131             repeatId = true;
132             PLAT_LOGE("%s: device:%s(%d) num repeated in manager:%s", __func__,
133                 device->name, device->number, manager->device.name);
134             break;
135         }
136         if (device->name != NULL && device->name == tmp->name) {
137             repeatName = true;
138             PLAT_LOGE("%s: device:%s(%d) name repeated in manager:%s", __func__,
139                 device->name, device->number, manager->device.name);
140             break;
141         }
142     }
143 
144     if (repeatId) {
145         return HDF_PLT_ERR_ID_REPEAT;
146     }
147     if (repeatName) {
148         return HDF_PLT_ERR_NAME_REPEAT;
149     }
150 
151     DListInsertTail(&device->node, &manager->devices);
152     return HDF_SUCCESS;
153 }
154 
PlatformManagerAddDevice(struct PlatformManager * manager,struct PlatformDevice * device)155 int32_t PlatformManagerAddDevice(struct PlatformManager *manager, struct PlatformDevice *device)
156 {
157     int32_t ret;
158     struct PlatformDevice *pos = NULL;
159 
160     if (manager == NULL || device == NULL) {
161         return HDF_ERR_INVALID_OBJECT;
162     }
163 
164     if (PlatformDeviceGet(device) != HDF_SUCCESS) { // keep a reference by manager
165         return HDF_PLT_ERR_DEV_GET;
166     }
167 
168     PlatformManagerLock(manager);
169     DLIST_FOR_EACH_ENTRY(pos, &manager->devices, struct PlatformDevice, node) {
170         if (pos == device) {
171             PlatformManagerUnlock(manager);
172             PLAT_LOGE("%s: device:%s(%d) already in manager:%s", __func__,
173                 device->name, device->number, manager->device.name);
174             PlatformDevicePut(device);
175             return HDF_PLT_ERR_OBJ_REPEAT;
176         }
177     }
178     if (manager->add != NULL) {
179         ret = manager->add(manager, device);
180     } else {
181         ret = PlatformManagerAddDeviceDefault(manager, device);
182     }
183     PlatformManagerUnlock(manager);
184 
185     if (ret == HDF_SUCCESS) {
186         PLAT_LOGD("%s: add dev:%s(%d) to %s success", __func__,
187             device->name, device->number, manager->device.name);
188     } else {
189         PlatformDevicePut(device);
190         PLAT_LOGE("%s: add dev:%s(%d) to %s failed:%d", __func__,
191             device->name, device->number, manager->device.name, ret);
192     }
193 
194     return ret;
195 }
196 
PlatformManagerDelDeviceDefault(const struct PlatformManager * manager,struct PlatformDevice * device)197 static int32_t PlatformManagerDelDeviceDefault(const struct PlatformManager *manager, struct PlatformDevice *device)
198 {
199     if (manager == NULL || device == NULL) {
200         return HDF_ERR_INVALID_OBJECT;
201     }
202     if (!DListIsEmpty(&device->node)) {
203         DListRemove(&device->node);
204     } else {
205         PLAT_LOGE("%s: device:%s already moved", __func__, device->name);
206         return HDF_ERR_INVALID_PARAM;
207     }
208 
209     return HDF_SUCCESS;
210 }
211 
PlatformManagerDelDevice(struct PlatformManager * manager,struct PlatformDevice * device)212 int32_t PlatformManagerDelDevice(struct PlatformManager *manager, struct PlatformDevice *device)
213 {
214     int32_t ret;
215     struct PlatformDevice *pos = NULL;
216 
217     if (manager == NULL || device == NULL) {
218         return HDF_ERR_INVALID_OBJECT;
219     }
220 
221     PlatformManagerLock(manager);
222     DLIST_FOR_EACH_ENTRY(pos, &manager->devices, struct PlatformDevice, node) {
223         if (pos == device) {
224             break;
225         }
226     }
227     if (pos != device) {
228         PLAT_LOGE("%s: device:%s(%d) not in manager:%s", __func__,
229             device->name, device->number, manager->device.name);
230         PlatformManagerUnlock(manager);
231         return HDF_PLT_ERR_NO_DEV;
232     }
233     if (manager->del != NULL) {
234         ret = manager->del(manager, device);
235     } else {
236         ret = PlatformManagerDelDeviceDefault(manager, device);
237     }
238     PlatformManagerUnlock(manager);
239 
240     if (ret == HDF_SUCCESS) {
241         PlatformDevicePut(device);  // put the reference hold by manager
242         PLAT_LOGD("%s: remove %s(%d) from %s success", __func__,
243             device->name, device->number, manager->device.name);
244     } else {
245         PLAT_LOGE("%s: remove %s(%d) from %s failed:%d", __func__,
246             device->name, device->number, manager->device.name, ret);
247     }
248     return ret;
249 }
250 
PlatformManagerFindDevice(struct PlatformManager * manager,void * data,bool (* match)(struct PlatformDevice * pdevice,void * data))251 struct PlatformDevice *PlatformManagerFindDevice(struct PlatformManager *manager, void *data,
252     bool (*match)(struct PlatformDevice *pdevice, void *data))
253 {
254     struct PlatformDevice *tmp = NULL;
255     struct PlatformDevice *pdevice = NULL;
256 
257     if (manager == NULL || match == NULL) {
258         return NULL;
259     }
260     if (manager->devices.prev == NULL || manager->devices.next == NULL) {
261         PLAT_LOGD("PlatformManagerFindDevice: devices not init.");
262         return NULL;
263     }
264 
265     PlatformManagerLock(manager);
266     DLIST_FOR_EACH_ENTRY(tmp, &manager->devices, struct PlatformDevice, node) {
267         if (tmp == NULL || !match(tmp, data)) {
268             continue;
269         }
270         if (PlatformDeviceGet(tmp) == HDF_SUCCESS) {
271             pdevice = tmp;
272         }
273         break;
274     }
275     PlatformManagerUnlock(manager);
276 
277     return pdevice;
278 }
279 
PlatformDeviceMatchByNumber(struct PlatformDevice * device,void * data)280 static bool PlatformDeviceMatchByNumber(struct PlatformDevice *device, void *data)
281 {
282     uint32_t number = (uint32_t)(uintptr_t)data;
283 
284     return (device != NULL && (uint32_t)device->number == number);
285 }
286 
PlatformManagerGetDeviceByNumber(struct PlatformManager * manager,uint32_t number)287 struct PlatformDevice *PlatformManagerGetDeviceByNumber(struct PlatformManager *manager, uint32_t number)
288 {
289     if (manager == NULL) {
290         return NULL;
291     }
292     return PlatformManagerFindDevice(manager, (void *)(uintptr_t)number, PlatformDeviceMatchByNumber);
293 }
294 
PlatformDeviceMatchByName(struct PlatformDevice * device,void * data)295 static bool PlatformDeviceMatchByName(struct PlatformDevice *device, void *data)
296 {
297     const char *name = (const char *)data;
298 
299     if (name == NULL || device->name == NULL) {
300         return false;
301     }
302 
303     return (strcmp(name, device->name) == 0);
304 }
305 
PlatformManagerGetDeviceByName(struct PlatformManager * manager,const char * name)306 struct PlatformDevice *PlatformManagerGetDeviceByName(struct PlatformManager *manager, const char *name)
307 {
308     if (manager == NULL) {
309         return NULL;
310     }
311     return PlatformManagerFindDevice(manager, (void *)name, PlatformDeviceMatchByName);
312 }
313