• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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