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 "power_state_token.h"
10 #include "devmgr_service_clnt.h"
11 #include "hdf_device_desc.h"
12 #include "hdf_slist.h"
13 #include "osal_mem.h"
14 #include "hdf_power_state.h"
15
PowerStateTokenOnFirstAcquire(struct HdfSRef * sref)16 static void PowerStateTokenOnFirstAcquire(struct HdfSRef *sref)
17 {
18 struct PowerStateToken *stateToken = NULL;
19 if (sref == NULL) {
20 return;
21 }
22 stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF(
23 struct HdfSRef, sref, struct PowerStateToken, wakeRef);
24
25 if (stateToken->psmState == PSM_STATE_ACTIVE) {
26 return;
27 }
28
29 if (stateToken->psmState == PSM_STATE_INACTIVE || stateToken->psmState == PSM_STATE_IDLE) {
30 const struct IPowerEventListener *listener = stateToken->listener;
31 if ((listener != NULL) && (listener->Resume != NULL)) {
32 listener->Resume(stateToken->deviceObject);
33 }
34 }
35 stateToken->psmState = PSM_STATE_ACTIVE;
36 }
37
PowerStateTokenOnLastRelease(struct HdfSRef * sref)38 static void PowerStateTokenOnLastRelease(struct HdfSRef *sref)
39 {
40 struct PowerStateToken *stateToken = NULL;
41 const struct IPowerEventListener *listener = NULL;
42 if (sref == NULL) {
43 return;
44 }
45 stateToken = (struct PowerStateToken *)HDF_SLIST_CONTAINER_OF(
46 struct HdfSRef, sref, struct PowerStateToken, wakeRef);
47
48 if (stateToken->psmState != PSM_STATE_ACTIVE && stateToken->psmState != PSM_STATE_IDLE) {
49 return;
50 }
51
52 listener = stateToken->listener;
53 if ((listener != NULL) && (listener->Suspend != NULL)) {
54 listener->Suspend(stateToken->deviceObject);
55 }
56 stateToken->psmState = PSM_STATE_INACTIVE;
57 }
58
PowerStateChange(struct PowerStateToken * stateToken,uint32_t pEvent)59 int PowerStateChange(struct PowerStateToken *stateToken, uint32_t pEvent)
60 {
61 if (stateToken == NULL || stateToken->listener == NULL || stateToken->mode != HDF_POWER_SYS_CTRL) {
62 return HDF_SUCCESS;
63 }
64
65 switch (pEvent) {
66 case POWER_STATE_SUSPEND:
67 if (stateToken->listener->Suspend != NULL) {
68 return stateToken->listener->Suspend(stateToken->deviceObject);
69 }
70 break;
71 case POWER_STATE_RESUME:
72 if (stateToken->listener->Resume != NULL) {
73 return stateToken->listener->Resume(stateToken->deviceObject);
74 }
75 break;
76 case POWER_STATE_DOZE_SUSPEND:
77 if (stateToken->listener->DozeSuspend != NULL) {
78 return stateToken->listener->DozeSuspend(stateToken->deviceObject);
79 }
80 break;
81 case POWER_STATE_DOZE_RESUME:
82 if (stateToken->listener->DozeResume != NULL) {
83 return stateToken->listener->DozeResume(stateToken->deviceObject);
84 }
85 break;
86 default:
87 break;
88 }
89
90 return HDF_SUCCESS;
91 }
92
PowerStateTokenAcquireWakeLock(struct IPowerStateToken * token)93 static void PowerStateTokenAcquireWakeLock(struct IPowerStateToken *token)
94 {
95 struct HdfSRef *sref = NULL;
96 struct PowerStateToken *stateToken = (struct PowerStateToken *)token;
97 if (stateToken == NULL || stateToken->mode != HDF_POWER_DYNAMIC_CTRL) {
98 return;
99 }
100 sref = (struct HdfSRef *)&stateToken->wakeRef;
101 if ((sref != NULL) && (sref->Acquire != NULL)) {
102 sref->Acquire(sref);
103 }
104 }
105
PowerStateTokenReleaseWakeLock(struct IPowerStateToken * token)106 static void PowerStateTokenReleaseWakeLock(struct IPowerStateToken *token)
107 {
108 struct HdfSRef *sref = NULL;
109 struct PowerStateToken *stateToken = (struct PowerStateToken *)token;
110 if (stateToken == NULL || stateToken->mode != HDF_POWER_DYNAMIC_CTRL) {
111 return;
112 }
113 sref = (struct HdfSRef *)&stateToken->wakeRef;
114 if ((sref == NULL) || (sref->Release == NULL)) {
115 return;
116 }
117
118 /* Not allowed to decrease the ref count to negative */
119 if (HdfSRefCount(sref) == 0) {
120 PowerStateTokenOnLastRelease(sref);
121 } else {
122 sref->Release(sref);
123 }
124 }
125
PowerStateTokenConstruct(struct PowerStateToken * powerStateToken,struct HdfDeviceObject * deviceObject,const struct IPowerEventListener * listener)126 static int32_t PowerStateTokenConstruct(struct PowerStateToken *powerStateToken,
127 struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener)
128 {
129 struct IPowerStateToken *tokenIf = &powerStateToken->super;
130 struct IHdfSRefListener *srefListener = (struct IHdfSRefListener *)OsalMemCalloc(sizeof(struct IHdfSRefListener));
131 if (srefListener == NULL) {
132 return HDF_ERR_MALLOC_FAIL;
133 }
134
135 tokenIf->AcquireWakeLock = PowerStateTokenAcquireWakeLock;
136 tokenIf->ReleaseWakeLock = PowerStateTokenReleaseWakeLock;
137
138 srefListener->OnFirstAcquire = PowerStateTokenOnFirstAcquire;
139 srefListener->OnLastRelease = PowerStateTokenOnLastRelease;
140
141 powerStateToken->psmState = PSM_STATE_IDLE;
142 powerStateToken->listener = listener;
143 powerStateToken->deviceObject = deviceObject;
144 HdfSRefConstruct(&powerStateToken->wakeRef, srefListener);
145
146 return HDF_SUCCESS;
147 }
148
PowerStateTokenNewInstance(struct HdfDeviceObject * deviceObject,const struct IPowerEventListener * listener)149 struct PowerStateToken *PowerStateTokenNewInstance(
150 struct HdfDeviceObject *deviceObject, const struct IPowerEventListener *listener)
151 {
152 struct PowerStateToken *stateToken =
153 (struct PowerStateToken *)OsalMemCalloc(sizeof(struct PowerStateToken));
154 if (stateToken == NULL) {
155 return NULL;
156 }
157
158 if (PowerStateTokenConstruct(stateToken, deviceObject, listener) != HDF_SUCCESS) {
159 OsalMemFree(stateToken);
160 return NULL;
161 }
162
163 return stateToken;
164 }
165
PowerStateTokenFreeInstance(struct PowerStateToken * stateToken)166 void PowerStateTokenFreeInstance(struct PowerStateToken *stateToken)
167 {
168 if (stateToken != NULL) {
169 if (stateToken->wakeRef.listener != NULL) {
170 OsalMemFree(stateToken->wakeRef.listener);
171 stateToken->wakeRef.listener = NULL;
172 }
173 OsalMemFree(stateToken);
174 }
175 }
176