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