1 /*
2 * Copyright (c) 2021-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 "regulator_tree_mgr.h"
10 #include "osal_mem.h"
11 #include "securec.h"
12
13 static struct RegulatorTreeManager *g_regulatorTreeManager = NULL;
RegulatorChildNodeAdd(struct RegulatorTreeInfo * pRegulator,struct RegulatorNode * child)14 static int RegulatorChildNodeAdd(struct RegulatorTreeInfo *pRegulator, struct RegulatorNode *child)
15 {
16 CHECK_NULL_PTR_RETURN_VALUE(pRegulator, HDF_ERR_INVALID_PARAM);
17 CHECK_NULL_PTR_RETURN_VALUE(child, HDF_ERR_INVALID_PARAM);
18
19 struct RegulatorChildNode *nodeInfo = NULL;
20
21 nodeInfo = (struct RegulatorChildNode *)OsalMemCalloc(sizeof(*nodeInfo));
22 if (nodeInfo == NULL) {
23 HDF_LOGE("RegulatorChildNodeAdd: OsalMemCalloc fail!");
24 return HDF_FAILURE;
25 }
26 nodeInfo->child = child;
27
28 DListInsertTail(&nodeInfo->node, &pRegulator->childHead);
29 HDF_LOGI("RegulatorChildNodeAdd: add %s child node success!", pRegulator->name);
30 return HDF_SUCCESS;
31 }
32
RegulatorChildListDestroy(struct RegulatorTreeInfo * pRegulator)33 static void RegulatorChildListDestroy(struct RegulatorTreeInfo *pRegulator)
34 {
35 CHECK_NULL_PTR_RETURN(pRegulator);
36 struct RegulatorChildNode *nodeInfo = NULL;
37 struct RegulatorChildNode *tmp = NULL;
38
39 DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, &pRegulator->childHead, struct RegulatorChildNode, node) {
40 DListRemove(&nodeInfo->node);
41 OsalMemFree(nodeInfo);
42 }
43 }
44
45 // name:the regulator node name; fun :get the node parent struct RegulatorNode
RegulatorTreeGetParent(const char * name)46 struct RegulatorNode *RegulatorTreeGetParent(const char *name)
47 {
48 CHECK_NULL_PTR_RETURN_VALUE(name, NULL);
49
50 struct RegulatorTreeInfo *pos = NULL;
51 struct RegulatorTreeInfo *tmp = NULL;
52 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
53 CHECK_NULL_PTR_RETURN_VALUE(manager, NULL);
54
55 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
56 HDF_LOGE("RegulatorTreeGetParent: lock regulator manager fail!");
57 return NULL;
58 }
59
60 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) {
61 if (strcmp(pos->name, name) == 0) {
62 if (pos->parent == NULL) {
63 (void)OsalMutexUnlock(&manager->lock);
64 HDF_LOGI("RegulatorTreeGetParent: %s no parent", name);
65 return NULL;
66 }
67 (void)OsalMutexUnlock(&manager->lock);
68 HDF_LOGI("RegulatorTreeGetParent: get %s parent %s success!",
69 name, pos->parent->regulatorInfo.name);
70 return pos->parent;
71 }
72 }
73
74 (void)OsalMutexUnlock(&manager->lock);
75 HDF_LOGI("RegulatorTreeGetParent: no %s Tree node", name);
76 return NULL;
77 }
78
79 // next level child
RegulatorTreeGetChild(const char * name)80 static struct DListHead *RegulatorTreeGetChild(const char *name)
81 {
82 CHECK_NULL_PTR_RETURN_VALUE(name, NULL);
83
84 struct RegulatorTreeInfo *pos = NULL;
85 struct RegulatorTreeInfo *tmp = NULL;
86 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
87 CHECK_NULL_PTR_RETURN_VALUE(manager, NULL);
88
89 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
90 HDF_LOGE("RegulatorTreeGetChild: lock regulator manager fail!");
91 return NULL;
92 }
93
94 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) {
95 if (strcmp(pos->name, name) == 0) {
96 (void)OsalMutexUnlock(&manager->lock);
97 HDF_LOGI("RegulatorTreeGetChild: get %s child success!", name);
98 return (&pos->childHead);
99 }
100 }
101
102 (void)OsalMutexUnlock(&manager->lock);
103 HDF_LOGE("RegulatorTreeGetChild: get %s child fail!", name);
104 return NULL;
105 }
106
107 // name:the regulator node name
RegulatorTreeIsUpNodeComplete(const char * name)108 bool RegulatorTreeIsUpNodeComplete(const char *name)
109 {
110 CHECK_NULL_PTR_RETURN_VALUE(name, false);
111
112 struct RegulatorNode *node = RegulatorTreeGetParent(name);
113 CHECK_NULL_PTR_RETURN_VALUE(node, false);
114
115 if ((node->regulatorInfo.parentName == NULL) || (strlen(node->regulatorInfo.parentName) == 0)) {
116 return true;
117 } else {
118 return RegulatorTreeIsUpNodeComplete(node->regulatorInfo.name);
119 }
120 }
121
RegulatorTreeIsChildAlwayson(const char * name)122 bool RegulatorTreeIsChildAlwayson(const char *name)
123 {
124 CHECK_NULL_PTR_RETURN_VALUE(name, false);
125 struct DListHead *pList = RegulatorTreeGetChild(name);
126 CHECK_NULL_PTR_RETURN_VALUE(pList, false);
127
128 struct RegulatorChildNode *nodeInfo = NULL;
129 struct RegulatorChildNode *tmp = NULL;
130 DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, pList, struct RegulatorChildNode, node) {
131 if (nodeInfo->child->regulatorInfo.constraints.alwaysOn) {
132 HDF_LOGD("RegulatorTreeIsChildAlwayson: %s's child %s alwaysOn true!",
133 name, nodeInfo->child->regulatorInfo.name);
134 return true;
135 }
136 }
137
138 HDF_LOGD("RegulatorTreeIsChildAlwayson: %s's all child alwaysOn false!", name);
139 return false;
140 }
141
RegulatorTreeIsChildStatusOn(const char * name)142 bool RegulatorTreeIsChildStatusOn(const char *name)
143 {
144 CHECK_NULL_PTR_RETURN_VALUE(name, false);
145 struct DListHead *pList = RegulatorTreeGetChild(name);
146 CHECK_NULL_PTR_RETURN_VALUE(pList, false);
147
148 struct RegulatorChildNode *nodeInfo = NULL;
149 struct RegulatorChildNode *tmp = NULL;
150 DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, pList, struct RegulatorChildNode, node) {
151 if (nodeInfo->child->regulatorInfo.status == REGULATOR_STATUS_ON) {
152 HDF_LOGD("RegulatorTreeIsChildStatusOn: %s's child %s status on!",
153 name, nodeInfo->child->regulatorInfo.name);
154 return true;
155 }
156 }
157
158 HDF_LOGD("RegulatorTreeIsChildStatusOn: %s's all child status off!", name);
159 return false;
160 }
161
RegulatorTreeIsAllChildDisable(const char * name)162 bool RegulatorTreeIsAllChildDisable(const char *name)
163 {
164 CHECK_NULL_PTR_RETURN_VALUE(name, true);
165 struct DListHead *pList = RegulatorTreeGetChild(name);
166 CHECK_NULL_PTR_RETURN_VALUE(pList, true);
167
168 struct RegulatorChildNode *nodeInfo = NULL;
169 struct RegulatorChildNode *tmp = NULL;
170 DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, pList, struct RegulatorChildNode, node) {
171 if (nodeInfo->child->regulatorInfo.status == REGULATOR_STATUS_ON) {
172 HDF_LOGI("RegulatorTreeIsAllChildDisable: %s's child %s on!", name, nodeInfo->child->regulatorInfo.name);
173 return false;
174 }
175 }
176
177 HDF_LOGI("RegulatorTreeIsAllChildDisable: %s's all child off!", name);
178 return true;
179 }
180
RegulatorTreeChildForceDisable(struct RegulatorNode * node)181 int32_t RegulatorTreeChildForceDisable(struct RegulatorNode *node)
182 {
183 CHECK_NULL_PTR_RETURN_VALUE(node, HDF_ERR_INVALID_PARAM);
184 struct DListHead *pList = RegulatorTreeGetChild(node->regulatorInfo.name);
185 CHECK_NULL_PTR_RETURN_VALUE(pList, HDF_SUCCESS);
186
187 struct RegulatorChildNode *nodeInfo = NULL;
188 struct RegulatorChildNode *tmp = NULL;
189 DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, pList, struct RegulatorChildNode, node) {
190 if (RegulatorTreeChildForceDisable(nodeInfo->child) != HDF_SUCCESS) {
191 HDF_LOGE("RegulatorTreeChildForceDisable: %s fail!", nodeInfo->child->regulatorInfo.name);
192 return HDF_FAILURE;
193 }
194
195 if (OsalMutexLock(&nodeInfo->child->lock) != HDF_SUCCESS) {
196 HDF_LOGE("RegulatorTreeChildForceDisable: lock regulator %s fail!", node->regulatorInfo.name);
197 return HDF_ERR_DEVICE_BUSY;
198 }
199 if (nodeInfo->child->regulatorInfo.status == REGULATOR_STATUS_ON) {
200 nodeInfo->child->ops->disable(nodeInfo->child);
201 nodeInfo->child->regulatorInfo.status = REGULATOR_STATUS_OFF;
202 RegulatorNodeStatusCb(nodeInfo->child);
203 }
204 (void)OsalMutexUnlock(&nodeInfo->child->lock);
205 HDF_LOGI("RegulatorTreeChildForceDisable: child %s ForceDisable success!", nodeInfo->child->regulatorInfo.name);
206 }
207
208 return HDF_SUCCESS;
209 }
210
211 // if Tree regulator node not exist, then add
RegulatorTreeManagerNodeInit(const char * name)212 static int32_t RegulatorTreeManagerNodeInit(const char *name)
213 {
214 CHECK_NULL_PTR_RETURN_VALUE(name, HDF_FAILURE);
215
216 struct RegulatorTreeInfo *nodeInfo = NULL;
217 struct RegulatorTreeInfo *pos = NULL;
218 struct RegulatorTreeInfo *tmp = NULL;
219 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
220 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
221
222 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
223 HDF_LOGE("RegulatorTreeManagerNodeInit: lock regulator manager fail!");
224 return HDF_ERR_DEVICE_BUSY;
225 }
226
227 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) {
228 if (strcmp(pos->name, name) == 0) {
229 HDF_LOGI("RegulatorTreeManagerNodeInit: node %s has exists!", name);
230 (void)OsalMutexUnlock(&manager->lock);
231 return HDF_SUCCESS;
232 }
233 }
234
235 nodeInfo = (struct RegulatorTreeInfo *)OsalMemCalloc(sizeof(*nodeInfo));
236 CHECK_NULL_PTR_RETURN_VALUE(nodeInfo, HDF_FAILURE);
237
238 DListHeadInit(&nodeInfo->childHead);
239 nodeInfo->name = name;
240
241 DListInsertTail(&nodeInfo->node, &manager->treeMgrHead);
242 (void)OsalMutexUnlock(&manager->lock);
243
244 HDF_LOGI("RegulatorTreeManagerNodeInit: init %s node success!", name);
245 return HDF_SUCCESS;
246 }
247
248 // set regulator (name)'s (parent) info
RegulatorTreeSetParent(const char * name,struct RegulatorNode * parent)249 static int RegulatorTreeSetParent(const char *name, struct RegulatorNode *parent)
250 {
251 CHECK_NULL_PTR_RETURN_VALUE(name, HDF_ERR_INVALID_PARAM);
252 CHECK_NULL_PTR_RETURN_VALUE(parent, HDF_ERR_INVALID_PARAM);
253
254 struct RegulatorTreeInfo *pos = NULL;
255 struct RegulatorTreeInfo *tmp = NULL;
256 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
257 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
258
259 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
260 HDF_LOGE("RegulatorTreeSetParent: lock regulator manager fail!");
261 return HDF_ERR_DEVICE_BUSY;
262 }
263
264 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) {
265 if (strcmp(pos->name, name) == 0) {
266 pos->parent = parent;
267 (void)OsalMutexUnlock(&manager->lock);
268 HDF_LOGI("RegulatorTreeSetParent: set %s parent success!", name);
269 return HDF_SUCCESS;
270 }
271 }
272
273 (void)OsalMutexUnlock(&manager->lock);
274 HDF_LOGI("RegulatorTreeSetParent:%s does not exist!", name);
275 return HDF_FAILURE;
276 }
277
278 // add (child) to regulator (name)'s childHead
RegulatorTreeSetChild(const char * name,struct RegulatorNode * child)279 static int RegulatorTreeSetChild(const char *name, struct RegulatorNode *child)
280 {
281 CHECK_NULL_PTR_RETURN_VALUE(name, HDF_ERR_INVALID_PARAM);
282 CHECK_NULL_PTR_RETURN_VALUE(child, HDF_ERR_INVALID_PARAM);
283
284 struct RegulatorTreeInfo *pos = NULL;
285 struct RegulatorTreeInfo *tmp = NULL;
286 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
287 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
288
289 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
290 HDF_LOGE("RegulatorTreeSetChild: lock regulator manager fail!");
291 return HDF_ERR_DEVICE_BUSY;
292 }
293
294 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) {
295 if (strcmp(pos->name, name) == 0) {
296 if (RegulatorChildNodeAdd(pos, child) != HDF_SUCCESS) {
297 HDF_LOGE("RegulatorTreeSetChild: RegulatorChildNodeAdd fail!");
298 (void)OsalMutexUnlock(&manager->lock);
299 return HDF_FAILURE;
300 }
301 (void)OsalMutexUnlock(&manager->lock);
302 HDF_LOGI("RegulatorTreeSetChild: set %s child success!", name);
303 return HDF_SUCCESS;
304 }
305 }
306
307 (void)OsalMutexUnlock(&manager->lock);
308 HDF_LOGI("RegulatorTreeSetChild:%s does not exist!", name);
309 return HDF_FAILURE;
310 }
311
312 /*
313 * name: child regulator node name
314 * child: child regulator node info
315 * parent: parent regulator node info
316 * process: set regultor (name)'s RegulatorTreeInfo:parent,and add (name) to (parent)'s RegulatorTreeInfo:childHead
317 */
RegulatorTreeSet(const char * name,struct RegulatorNode * child,struct RegulatorNode * parent)318 int RegulatorTreeSet(const char *name, struct RegulatorNode *child, struct RegulatorNode *parent)
319 {
320 CHECK_NULL_PTR_RETURN_VALUE(name, HDF_ERR_INVALID_PARAM);
321 CHECK_NULL_PTR_RETURN_VALUE(child, HDF_ERR_INVALID_PARAM);
322 CHECK_NULL_PTR_RETURN_VALUE(parent, HDF_ERR_INVALID_PARAM);
323
324 if (RegulatorTreeManagerNodeInit(name) != HDF_SUCCESS) {
325 HDF_LOGE("RegulatorTreeSet: RegulatorTreeManagerNodeInit %s fail!", name);
326 return HDF_FAILURE;
327 }
328 if (RegulatorTreeSetParent(name, parent) != HDF_SUCCESS) {
329 HDF_LOGE("RegulatorTreeSet: RegulatorTreeSetParent %s fail!", name);
330 return HDF_FAILURE;
331 }
332
333 if (RegulatorTreeManagerNodeInit(parent->regulatorInfo.name) != HDF_SUCCESS) {
334 HDF_LOGE("RegulatorTreeSet: RegulatorTreeManagerNodeInit %s fail!", parent->regulatorInfo.name);
335 return HDF_FAILURE;
336 }
337 if (RegulatorTreeSetChild(parent->regulatorInfo.name, child) != HDF_SUCCESS) {
338 HDF_LOGE("RegulatorTreeSet: RegulatorTreeSetChild %s fail!", name);
339 return HDF_FAILURE;
340 }
341
342 HDF_LOGI("RegulatorTreeSet: set [%s], parent[%s] and child info success!",
343 name, parent->regulatorInfo.name);
344 return HDF_SUCCESS;
345 }
346
RegulatorTreePrintChild(const char * name,struct DListHead * childHead)347 static void RegulatorTreePrintChild(const char *name, struct DListHead *childHead)
348 {
349 CHECK_NULL_PTR_RETURN(childHead);
350 CHECK_NULL_PTR_RETURN(name);
351
352 struct RegulatorChildNode *nodeInfo = NULL;
353 struct RegulatorChildNode *tmp = NULL;
354
355 DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, childHead, struct RegulatorChildNode, node) {
356 HDF_LOGI("RegulatorTreePrintChild: %s's child %s !",
357 name, nodeInfo->child->regulatorInfo.name);
358 }
359 }
360
RegulatorTreePrint(void)361 void RegulatorTreePrint(void)
362 {
363 struct RegulatorTreeInfo *pos = NULL;
364 struct RegulatorTreeInfo *tmp = NULL;
365 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
366 CHECK_NULL_PTR_RETURN(manager);
367
368 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
369 HDF_LOGE("RegulatorTreePrint: lock regulator manager fail!");
370 return;
371 }
372
373 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) {
374 HDF_LOGI("RegulatorTreePrint %s info IN ---->", pos->name);
375 if (pos->parent != NULL) {
376 HDF_LOGI("RegulatorTreePrint %s info, parent name[%s]",
377 pos->name, pos->parent->regulatorInfo.name);
378 }
379
380 RegulatorTreePrintChild(pos->name, &pos->childHead);
381 HDF_LOGI("RegulatorTreePrint %s info out---->", pos->name);
382 }
383 (void)OsalMutexUnlock(&manager->lock);
384 }
385
RegulatorTreeNodeRemoveAll(void)386 int RegulatorTreeNodeRemoveAll(void)
387 {
388 struct RegulatorTreeInfo *nodeInfo = NULL;
389 struct RegulatorTreeInfo *tmp = NULL;
390 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
391 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
392
393 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
394 HDF_LOGE("RegulatorTreeNodeRemoveAll: lock regulator manager fail!");
395 return HDF_ERR_DEVICE_BUSY;
396 }
397
398 DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) {
399 RegulatorChildListDestroy(nodeInfo);
400 DListRemove(&nodeInfo->node);
401 OsalMemFree(nodeInfo);
402 }
403
404 (void)OsalMutexUnlock(&manager->lock);
405 return HDF_SUCCESS;
406 }
407
RegulatorTreeManagerDestory(void)408 int RegulatorTreeManagerDestory(void)
409 {
410 if (RegulatorTreeNodeRemoveAll() != HDF_SUCCESS) {
411 HDF_LOGE("RegulatorTreeManagerDestory: RegulatorTreeNodeRemoveAll fail!");
412 }
413
414 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
415 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
416 OsalMutexDestroy(&manager->lock);
417 OsalMemFree(manager);
418 g_regulatorTreeManager = NULL;
419 return HDF_SUCCESS;
420 }
421
RegulatorTreeManagerInit(void)422 int RegulatorTreeManagerInit(void)
423 {
424 struct RegulatorTreeManager *manager =
425 (struct RegulatorTreeManager *)OsalMemCalloc(sizeof(struct RegulatorTreeManager));
426 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
427
428 if (OsalMutexInit(&manager->lock) != HDF_SUCCESS) {
429 HDF_LOGE("RegulatorTreeManagerInit: mutex init fail!");
430 OsalMemFree(manager);
431 return HDF_FAILURE;
432 }
433
434 DListHeadInit(&manager->treeMgrHead);
435 g_regulatorTreeManager = manager;
436 return HDF_SUCCESS;
437 }
438