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