1 /*
2 * Copyright (c) 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 "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("%s: OsalMemCalloc failed", __func__);
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 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 failed!", 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("RegulatorTreeIsChildAlwayson:%s's child %s status on!",
153 name, nodeInfo->child->regulatorInfo.name);
154 return true;
155 }
156 }
157
158 HDF_LOGD("RegulatorTreeIsChildAlwayson:%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 }
RegulatorTreePrintChild(const char * name,struct DListHead * childHead)346 static void RegulatorTreePrintChild(const char *name, struct DListHead *childHead)
347 {
348 CHECK_NULL_PTR_RETURN(childHead);
349 CHECK_NULL_PTR_RETURN(name);
350
351 struct RegulatorChildNode *nodeInfo = NULL;
352 struct RegulatorChildNode *tmp = NULL;
353
354 DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, childHead, struct RegulatorChildNode, node) {
355 HDF_LOGI("RegulatorTreePrintChild: %s's child %s !",
356 name, nodeInfo->child->regulatorInfo.name);
357 }
358 }
359
RegulatorTreePrint(void)360 void RegulatorTreePrint(void)
361 {
362 struct RegulatorTreeInfo *pos = NULL;
363 struct RegulatorTreeInfo *tmp = NULL;
364 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
365 CHECK_NULL_PTR_RETURN(manager);
366
367 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
368 HDF_LOGE("RegulatorTreePrint: lock regulator manager fail!");
369 return;
370 }
371
372 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) {
373 HDF_LOGI("RegulatorTreePrint %s info IN ---->", pos->name);
374 if (pos->parent != NULL) {
375 HDF_LOGI("RegulatorTreePrint %s info, parent name[%s]",
376 pos->name, pos->parent->regulatorInfo.name);
377 }
378
379 RegulatorTreePrintChild(pos->name, &pos->childHead);
380 HDF_LOGI("RegulatorTreePrint %s info out---->", pos->name);
381 }
382 (void)OsalMutexUnlock(&manager->lock);
383 }
384
RegulatorTreeNodeRemoveAll(void)385 int RegulatorTreeNodeRemoveAll(void)
386 {
387 struct RegulatorTreeInfo *nodeInfo = NULL;
388 struct RegulatorTreeInfo *tmp = NULL;
389 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
390 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
391
392 if (OsalMutexLock(&manager->lock) != HDF_SUCCESS) {
393 HDF_LOGE("RegulatorTreeNodeRemoveAll: lock regulator manager fail!");
394 return HDF_ERR_DEVICE_BUSY;
395 }
396
397 DLIST_FOR_EACH_ENTRY_SAFE(nodeInfo, tmp, &manager->treeMgrHead, struct RegulatorTreeInfo, node) {
398 RegulatorChildListDestroy(nodeInfo);
399 DListRemove(&nodeInfo->node);
400 OsalMemFree(nodeInfo);
401 }
402
403 (void)OsalMutexUnlock(&manager->lock);
404 return HDF_SUCCESS;
405 }
406
RegulatorTreeManagerDestory(void)407 int RegulatorTreeManagerDestory(void)
408 {
409 if (RegulatorTreeNodeRemoveAll() != HDF_SUCCESS) {
410 HDF_LOGE("func:%s RegulatorTreeNodeRemoveAll failed", __func__);
411 }
412
413 struct RegulatorTreeManager *manager = g_regulatorTreeManager;
414 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
415 OsalMutexDestroy(&manager->lock);
416 OsalMemFree(manager);
417 g_regulatorTreeManager = NULL;
418 return HDF_SUCCESS;
419 }
420
RegulatorTreeManagerInit(void)421 int RegulatorTreeManagerInit(void)
422 {
423 struct RegulatorTreeManager *manager =
424 (struct RegulatorTreeManager *)OsalMemCalloc(sizeof(struct RegulatorTreeManager));
425 CHECK_NULL_PTR_RETURN_VALUE(manager, HDF_FAILURE);
426
427 if (OsalMutexInit(&manager->lock) != HDF_SUCCESS) {
428 HDF_LOGE("RegulatorTreeManagerInit: mutex init fail");
429 OsalMemFree(manager);
430 return HDF_FAILURE;
431 }
432
433 DListHeadInit(&manager->treeMgrHead);
434 g_regulatorTreeManager = manager;
435 return HDF_SUCCESS;
436 }
437