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 "watchdog_core.h"
10 #include "hdf_log.h"
11 #include "watchdog_if.h"
12
13 #define HDF_LOG_TAG watchdog_core
14
15 static int32_t WatchdogIoDispatch(struct HdfDeviceIoClient *client, int cmd,
16 struct HdfSBuf *data, struct HdfSBuf *reply);
WatchdogCntlrAdd(struct WatchdogCntlr * cntlr)17 int32_t WatchdogCntlrAdd(struct WatchdogCntlr *cntlr)
18 {
19 int32_t ret;
20
21 if (cntlr == NULL) {
22 return HDF_ERR_INVALID_OBJECT;
23 }
24
25 if (cntlr->device == NULL) {
26 HDF_LOGE("WatchdogCntlrAdd: no device associated!");
27 return HDF_ERR_INVALID_OBJECT;
28 }
29
30 if (cntlr->ops == NULL) {
31 HDF_LOGE("WatchdogCntlrAdd: no ops supplied!");
32 return HDF_ERR_INVALID_OBJECT;
33 }
34
35 ret = OsalSpinInit(&cntlr->lock);
36 if (ret != HDF_SUCCESS) {
37 HDF_LOGE("WatchdogCntlrAdd: spinlock init fail!");
38 return ret;
39 }
40
41 cntlr->device->service = &cntlr->service;
42 cntlr->device->service->Dispatch = WatchdogIoDispatch;
43 return HDF_SUCCESS;
44 }
45
WatchdogCntlrRemove(struct WatchdogCntlr * cntlr)46 void WatchdogCntlrRemove(struct WatchdogCntlr *cntlr)
47 {
48 if (cntlr == NULL) {
49 return;
50 }
51
52 if (cntlr->device == NULL) {
53 HDF_LOGE("WatchdogCntlrRemove: no device associated!");
54 return;
55 }
56
57 cntlr->device->service = NULL;
58 (void)OsalSpinDestroy(&cntlr->lock);
59 }
60
WatchdogGetPrivData(struct WatchdogCntlr * cntlr)61 int32_t WatchdogGetPrivData(struct WatchdogCntlr *cntlr)
62 {
63 if (cntlr == NULL || cntlr->ops == NULL) {
64 return HDF_ERR_INVALID_OBJECT;
65 }
66 if (cntlr->ops->getPriv != NULL) {
67 return cntlr->ops->getPriv(cntlr);
68 }
69 return HDF_SUCCESS;
70 }
71
WatchdogReleasePriv(struct WatchdogCntlr * cntlr)72 int32_t WatchdogReleasePriv(struct WatchdogCntlr *cntlr)
73 {
74 if (cntlr == NULL || cntlr->ops == NULL) {
75 HDF_LOGE("cntlr or cntlr->ops is null");
76 return HDF_SUCCESS;
77 }
78 if (cntlr->ops->releasePriv != NULL) {
79 cntlr->ops->releasePriv(cntlr);
80 }
81 return HDF_SUCCESS;
82 }
83
WatchdogCntlrGetStatus(struct WatchdogCntlr * cntlr,int32_t * status)84 int32_t WatchdogCntlrGetStatus(struct WatchdogCntlr *cntlr, int32_t *status)
85 {
86 int32_t ret;
87 uint32_t flags;
88
89 if (cntlr == NULL) {
90 return HDF_ERR_INVALID_OBJECT;
91 }
92 if (cntlr->ops == NULL || cntlr->ops->getStatus == NULL) {
93 return HDF_ERR_NOT_SUPPORT;
94 }
95 if (status == NULL) {
96 return HDF_ERR_INVALID_PARAM;
97 }
98
99 if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
100 return HDF_ERR_DEVICE_BUSY;
101 }
102 ret = cntlr->ops->getStatus(cntlr, status);
103 if (ret != HDF_SUCCESS) {
104 HDF_LOGE("%s:getStatus fail", __func__);
105 return ret;
106 }
107 (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
108 return ret;
109 }
110
WatchdogCntlrStart(struct WatchdogCntlr * cntlr)111 int32_t WatchdogCntlrStart(struct WatchdogCntlr *cntlr)
112 {
113 int32_t ret;
114 uint32_t flags;
115
116 if (cntlr == NULL) {
117 return HDF_ERR_INVALID_OBJECT;
118 }
119 if (cntlr->ops == NULL || cntlr->ops->start == NULL) {
120 return HDF_ERR_NOT_SUPPORT;
121 }
122
123 if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
124 return HDF_ERR_DEVICE_BUSY;
125 }
126 ret = cntlr->ops->start(cntlr);
127 (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
128 return ret;
129 }
130
WatchdogCntlrStop(struct WatchdogCntlr * cntlr)131 int32_t WatchdogCntlrStop(struct WatchdogCntlr *cntlr)
132 {
133 int32_t ret;
134 uint32_t flags;
135
136 if (cntlr == NULL) {
137 return HDF_ERR_INVALID_OBJECT;
138 }
139 if (cntlr->ops == NULL || cntlr->ops->stop == NULL) {
140 return HDF_ERR_NOT_SUPPORT;
141 }
142
143 if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
144 return HDF_ERR_DEVICE_BUSY;
145 }
146 ret = cntlr->ops->stop(cntlr);
147 (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
148 return ret;
149 }
150
WatchdogCntlrSetTimeout(struct WatchdogCntlr * cntlr,uint32_t seconds)151 int32_t WatchdogCntlrSetTimeout(struct WatchdogCntlr *cntlr, uint32_t seconds)
152 {
153 int32_t ret;
154 uint32_t flags;
155
156 if (cntlr == NULL) {
157 return HDF_ERR_INVALID_OBJECT;
158 }
159 if (cntlr->ops == NULL || cntlr->ops->setTimeout == NULL) {
160 return HDF_ERR_NOT_SUPPORT;
161 }
162
163 if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
164 return HDF_ERR_DEVICE_BUSY;
165 }
166 ret = cntlr->ops->setTimeout(cntlr, seconds);
167 (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
168 return ret;
169 }
170
WatchdogCntlrGetTimeout(struct WatchdogCntlr * cntlr,uint32_t * seconds)171 int32_t WatchdogCntlrGetTimeout(struct WatchdogCntlr *cntlr, uint32_t *seconds)
172 {
173 int32_t ret;
174 uint32_t flags;
175
176 if (cntlr == NULL) {
177 return HDF_ERR_INVALID_OBJECT;
178 }
179 if (cntlr->ops == NULL || cntlr->ops->getTimeout == NULL) {
180 return HDF_ERR_NOT_SUPPORT;
181 }
182 if (seconds == NULL) {
183 return HDF_ERR_INVALID_PARAM;
184 }
185
186 if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
187 return HDF_ERR_DEVICE_BUSY;
188 }
189 ret = cntlr->ops->getTimeout(cntlr, seconds);
190 (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
191 return ret;
192 }
193
WatchdogCntlrFeed(struct WatchdogCntlr * cntlr)194 int32_t WatchdogCntlrFeed(struct WatchdogCntlr *cntlr)
195 {
196 int32_t ret;
197 uint32_t flags;
198
199 if (cntlr == NULL) {
200 return HDF_ERR_INVALID_OBJECT;
201 }
202 if (cntlr->ops == NULL || cntlr->ops->feed == NULL) {
203 return HDF_ERR_NOT_SUPPORT;
204 }
205
206 if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
207 return HDF_ERR_DEVICE_BUSY;
208 }
209 ret = cntlr->ops->feed(cntlr);
210 (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
211 return ret;
212 }
213
WatchdogUserGetPrivData(struct WatchdogCntlr * cntlr,struct HdfSBuf * reply)214 static int32_t WatchdogUserGetPrivData(struct WatchdogCntlr *cntlr, struct HdfSBuf *reply)
215 {
216 int32_t ret;
217 if (reply == NULL) {
218 HDF_LOGE("%s: invalid param", __func__);
219 return HDF_ERR_INVALID_OBJECT;
220 }
221 ret = WatchdogGetPrivData(cntlr);
222 if (!HdfSbufWriteInt32(reply, ret)) {
223 HDF_LOGE("%s: sbuf write buffer failed", __func__);
224 return HDF_ERR_IO;
225 }
226 return HDF_SUCCESS;
227 }
228
WatchdogUserGetStatus(struct WatchdogCntlr * cntlr,struct HdfSBuf * reply)229 static int32_t WatchdogUserGetStatus(struct WatchdogCntlr *cntlr, struct HdfSBuf *reply)
230 {
231 int32_t ret;
232 int32_t status;
233
234 if (reply == NULL) {
235 HDF_LOGE("%s: invalid param", __func__);
236 return HDF_ERR_INVALID_OBJECT;
237 }
238 ret = WatchdogCntlrGetStatus(cntlr, &status);
239 if (ret != HDF_SUCCESS) {
240 HDF_LOGE("%s: WatchdogCntlrGetStatus failed, ret: %d", __func__, ret);
241 return ret;
242 }
243 if (!HdfSbufWriteInt32(reply, status)) {
244 HDF_LOGE("%s: sbuf write status failed", __func__);
245 return HDF_ERR_IO;
246 }
247 return HDF_SUCCESS;
248 }
249
WatchdogUserSetTimeout(struct WatchdogCntlr * cntlr,struct HdfSBuf * data)250 static int32_t WatchdogUserSetTimeout(struct WatchdogCntlr *cntlr, struct HdfSBuf *data)
251 {
252 uint32_t seconds;
253
254 if (data == NULL) {
255 HDF_LOGE("%s: invalid param", __func__);
256 return HDF_ERR_INVALID_OBJECT;
257 }
258
259 if (!HdfSbufReadUint32(data, &seconds)) {
260 HDF_LOGE("%s: sbuf read seconds failed", __func__);
261 return HDF_ERR_IO;
262 }
263
264 return WatchdogCntlrSetTimeout(cntlr, seconds);
265 }
266
WatchdogUserGetTimeout(struct WatchdogCntlr * cntlr,struct HdfSBuf * reply)267 static int32_t WatchdogUserGetTimeout(struct WatchdogCntlr *cntlr, struct HdfSBuf *reply)
268 {
269 int32_t ret;
270 uint32_t seconds;
271 if (reply == NULL) {
272 HDF_LOGE("%s: invalid param", __func__);
273 return HDF_ERR_INVALID_OBJECT;
274 }
275 ret = WatchdogCntlrGetTimeout(cntlr, &seconds);
276 if (ret != HDF_SUCCESS) {
277 HDF_LOGE("%s: WatchdogCntlrGetTimeout failed, ret: %d", __func__, ret);
278 return ret;
279 }
280
281 if (!HdfSbufWriteUint32(reply, seconds)) {
282 HDF_LOGE("%s: sbuf write buffer failed", __func__);
283 return HDF_ERR_IO;
284 }
285 return HDF_SUCCESS;
286 }
287
WatchdogIoDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)288 static int32_t WatchdogIoDispatch(struct HdfDeviceIoClient *client, int cmd,
289 struct HdfSBuf *data, struct HdfSBuf *reply)
290 {
291 struct WatchdogCntlr *cntlr = NULL;
292
293 if (client == NULL) {
294 HDF_LOGE("%s: client is NULL", __func__);
295 return HDF_ERR_INVALID_OBJECT;
296 }
297 if (client->device == NULL) {
298 HDF_LOGE("%s: client->device is NULL", __func__);
299 return HDF_ERR_INVALID_OBJECT;
300 }
301 if (client->device->service == NULL) {
302 HDF_LOGE("%s: client->device->service is NULL", __func__);
303 return HDF_ERR_INVALID_OBJECT;
304 }
305
306 cntlr = (struct WatchdogCntlr *)client->device->service;
307 switch (cmd) {
308 case WATCHDOG_IO_GET_PRIV:
309 return WatchdogUserGetPrivData(cntlr, reply);
310 case WATCHDOG_IO_RELEASE_PRIV:
311 return WatchdogReleasePriv(cntlr);
312 case WATCHDOG_IO_GET_STATUS:
313 return WatchdogUserGetStatus(cntlr, reply);
314 case WATCHDOG_IO_START:
315 return WatchdogCntlrStart(cntlr);
316 case WATCHDOG_IO_STOP:
317 return WatchdogCntlrStop(cntlr);
318 case WATCHDOG_IO_SET_TIMEOUT:
319 return WatchdogUserSetTimeout(cntlr, data);
320 case WATCHDOG_IO_GET_TIMEOUT:
321 return WatchdogUserGetTimeout(cntlr, reply);
322 case WATCHDOG_IO_FEED:
323 return WatchdogCntlrFeed(cntlr);
324 default:
325 HDF_LOGE("%s: cmd %d not support", __func__, cmd);
326 return HDF_ERR_NOT_SUPPORT;
327 }
328 }
329