• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         return ret;
115     }
116     (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
117     return ret;
118 }
119 
WatchdogCntlrStart(struct WatchdogCntlr * cntlr)120 int32_t WatchdogCntlrStart(struct WatchdogCntlr *cntlr)
121 {
122     int32_t ret;
123     uint32_t flags;
124 
125     if (cntlr == NULL) {
126         HDF_LOGE("WatchdogCntlrStart: cntlr is null!");
127         return HDF_ERR_INVALID_OBJECT;
128     }
129     if (cntlr->ops == NULL || cntlr->ops->start == NULL) {
130         HDF_LOGE("WatchdogCntlrStart: ops or start is null!");
131         return HDF_ERR_NOT_SUPPORT;
132     }
133 
134     if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
135         HDF_LOGE("WatchdogCntlrStart: osal spin lock irq save fail!");
136         return HDF_ERR_DEVICE_BUSY;
137     }
138     ret = cntlr->ops->start(cntlr);
139     if (PlatformTraceStart() == HDF_SUCCESS) {
140         unsigned int infos[WATCHDOG_TRACE_BASIC_PARAM_NUM];
141         infos[PLATFORM_TRACE_UINT_PARAM_SIZE_1 - 1] = cntlr->wdtId;
142         PlatformTraceAddUintMsg(PLATFORM_TRACE_MODULE_WATCHDOG, PLATFORM_TRACE_MODULE_WATCHDOG_FUN_START,
143             infos, WATCHDOG_TRACE_BASIC_PARAM_NUM);
144         PlatformTraceStop();
145     }
146     (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
147     return ret;
148 }
149 
WatchdogCntlrStop(struct WatchdogCntlr * cntlr)150 int32_t WatchdogCntlrStop(struct WatchdogCntlr *cntlr)
151 {
152     int32_t ret;
153     uint32_t flags;
154 
155     if (cntlr == NULL) {
156         HDF_LOGE("WatchdogCntlrStop: cntlr is null!");
157         return HDF_ERR_INVALID_OBJECT;
158     }
159     if (cntlr->ops == NULL || cntlr->ops->stop == NULL) {
160         HDF_LOGE("WatchdogCntlrStop: ops or stop is null!");
161         return HDF_ERR_NOT_SUPPORT;
162     }
163 
164     if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
165         HDF_LOGE("WatchdogCntlrStop: osal spin lock irq save fail!");
166         return HDF_ERR_DEVICE_BUSY;
167     }
168     ret = cntlr->ops->stop(cntlr);
169     if (PlatformTraceStart() == HDF_SUCCESS) {
170         unsigned int infos[WATCHDOG_TRACE_PARAM_STOP_NUM];
171         infos[PLATFORM_TRACE_UINT_PARAM_SIZE_1 - 1] = cntlr->wdtId;
172         PlatformTraceAddUintMsg(PLATFORM_TRACE_MODULE_WATCHDOG, PLATFORM_TRACE_MODULE_WATCHDOG_FUN_STOP,
173             infos, WATCHDOG_TRACE_PARAM_STOP_NUM);
174         PlatformTraceStop();
175         PlatformTraceInfoDump();
176     }
177     (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
178     return ret;
179 }
180 
WatchdogCntlrSetTimeout(struct WatchdogCntlr * cntlr,uint32_t seconds)181 int32_t WatchdogCntlrSetTimeout(struct WatchdogCntlr *cntlr, uint32_t seconds)
182 {
183     int32_t ret;
184     uint32_t flags;
185 
186     if (cntlr == NULL) {
187         HDF_LOGE("WatchdogCntlrSetTimeout: cntlr is null!");
188         return HDF_ERR_INVALID_OBJECT;
189     }
190     if (cntlr->ops == NULL || cntlr->ops->setTimeout == NULL) {
191         HDF_LOGE("WatchdogCntlrSetTimeout: ops or setTimeout is null!");
192         return HDF_ERR_NOT_SUPPORT;
193     }
194 
195     if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
196         HDF_LOGE("WatchdogCntlrSetTimeout: osal spin lock irq save fail!");
197         return HDF_ERR_DEVICE_BUSY;
198     }
199     ret = cntlr->ops->setTimeout(cntlr, seconds);
200     (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
201     return ret;
202 }
203 
WatchdogCntlrGetTimeout(struct WatchdogCntlr * cntlr,uint32_t * seconds)204 int32_t WatchdogCntlrGetTimeout(struct WatchdogCntlr *cntlr, uint32_t *seconds)
205 {
206     int32_t ret;
207     uint32_t flags;
208 
209     if (cntlr == NULL) {
210         HDF_LOGE("WatchdogCntlrGetTimeout: cntlr is null!");
211         return HDF_ERR_INVALID_OBJECT;
212     }
213     if (cntlr->ops == NULL || cntlr->ops->getTimeout == NULL) {
214         HDF_LOGE("WatchdogCntlrGetTimeout: ops or getTimeout is null!");
215         return HDF_ERR_NOT_SUPPORT;
216     }
217     if (seconds == NULL) {
218         HDF_LOGE("WatchdogCntlrGetTimeout: seconds is null!");
219         return HDF_ERR_INVALID_PARAM;
220     }
221 
222     if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
223         HDF_LOGE("WatchdogCntlrGetTimeout: osal spin lock irq save fail!");
224         return HDF_ERR_DEVICE_BUSY;
225     }
226     ret = cntlr->ops->getTimeout(cntlr, seconds);
227     (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
228     return ret;
229 }
230 
WatchdogCntlrFeed(struct WatchdogCntlr * cntlr)231 int32_t WatchdogCntlrFeed(struct WatchdogCntlr *cntlr)
232 {
233     int32_t ret;
234     uint32_t flags;
235 
236     if (cntlr == NULL) {
237         HDF_LOGE("WatchdogCntlrFeed: cntlr is null!");
238         return HDF_ERR_INVALID_OBJECT;
239     }
240     if (cntlr->ops == NULL || cntlr->ops->feed == NULL) {
241         HDF_LOGE("WatchdogCntlrFeed: ops or feed is null!");
242         return HDF_ERR_NOT_SUPPORT;
243     }
244 
245     if (OsalSpinLockIrqSave(&cntlr->lock, &flags) != HDF_SUCCESS) {
246         HDF_LOGE("OsalSpinLockIrqSave: osal spin lock irq save fail!");
247         return HDF_ERR_DEVICE_BUSY;
248     }
249     ret = cntlr->ops->feed(cntlr);
250     (void)OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
251     return ret;
252 }
253 
WatchdogUserGetPrivData(struct WatchdogCntlr * cntlr,struct HdfSBuf * reply)254 static int32_t WatchdogUserGetPrivData(struct WatchdogCntlr *cntlr, struct HdfSBuf *reply)
255 {
256     int32_t ret;
257 
258     if (reply == NULL) {
259         HDF_LOGE("WatchdogUserGetPrivData: reply is null!");
260         return HDF_ERR_INVALID_OBJECT;
261     }
262     ret = WatchdogGetPrivData(cntlr);
263     if (!HdfSbufWriteInt32(reply, ret)) {
264         HDF_LOGE("WatchdogUserGetPrivData: sbuf write buffer fail!");
265         return HDF_ERR_IO;
266     }
267     return HDF_SUCCESS;
268 }
269 
WatchdogUserGetStatus(struct WatchdogCntlr * cntlr,struct HdfSBuf * reply)270 static int32_t WatchdogUserGetStatus(struct WatchdogCntlr *cntlr, struct HdfSBuf *reply)
271 {
272     int32_t ret;
273     int32_t status;
274 
275     if (reply == NULL) {
276         HDF_LOGE("WatchdogUserGetStatus:reply is null!");
277         return HDF_ERR_INVALID_OBJECT;
278     }
279     ret = WatchdogCntlrGetStatus(cntlr, &status);
280     if (ret != HDF_SUCCESS) {
281         HDF_LOGE("WatchdogUserGetStatus: watchdog cntlr get status fail, ret: %d!", ret);
282         return ret;
283     }
284     if (!HdfSbufWriteInt32(reply, status)) {
285         HDF_LOGE("WatchdogUserGetStatus: sbuf write status fail!");
286         return HDF_ERR_IO;
287     }
288     return HDF_SUCCESS;
289 }
290 
WatchdogUserSetTimeout(struct WatchdogCntlr * cntlr,struct HdfSBuf * data)291 static int32_t WatchdogUserSetTimeout(struct WatchdogCntlr *cntlr, struct HdfSBuf *data)
292 {
293     uint32_t seconds;
294 
295     if (data == NULL) {
296         HDF_LOGE("WatchdogUserSetTimeout: data is null!");
297         return HDF_ERR_INVALID_OBJECT;
298     }
299 
300     if (!HdfSbufReadUint32(data, &seconds)) {
301         HDF_LOGE("WatchdogUserSetTimeout: sbuf read seconds fail!");
302         return HDF_ERR_IO;
303     }
304 
305     return WatchdogCntlrSetTimeout(cntlr, seconds);
306 }
307 
WatchdogUserGetTimeout(struct WatchdogCntlr * cntlr,struct HdfSBuf * reply)308 static int32_t WatchdogUserGetTimeout(struct WatchdogCntlr *cntlr, struct HdfSBuf *reply)
309 {
310     int32_t ret;
311     uint32_t seconds;
312 
313     if (reply == NULL) {
314         HDF_LOGE("WatchdogUserGetTimeout: reply is null!");
315         return HDF_ERR_INVALID_OBJECT;
316     }
317     ret = WatchdogCntlrGetTimeout(cntlr, &seconds);
318     if (ret != HDF_SUCCESS) {
319         HDF_LOGE("WatchdogUserGetTimeout: watchdog cntlr get timeout fail, ret: %d!", ret);
320         return ret;
321     }
322 
323     if (!HdfSbufWriteUint32(reply, seconds)) {
324         HDF_LOGE("WatchdogUserGetTimeout: sbuf write buffer fail!");
325         return HDF_ERR_IO;
326     }
327     return HDF_SUCCESS;
328 }
329 
WatchdogIoDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)330 static int32_t WatchdogIoDispatch(struct HdfDeviceIoClient *client, int cmd,
331     struct HdfSBuf *data, struct HdfSBuf *reply)
332 {
333     struct WatchdogCntlr *cntlr = NULL;
334 
335     if (client == NULL) {
336         HDF_LOGE("WatchdogIoDispatch: client is null!");
337         return HDF_ERR_INVALID_OBJECT;
338     }
339     if (client->device == NULL) {
340         HDF_LOGE("WatchdogIoDispatch: client->device is null!");
341         return HDF_ERR_INVALID_OBJECT;
342     }
343     if (client->device->service == NULL) {
344         HDF_LOGE("WatchdogIoDispatch: client->device->service is null!");
345         return HDF_ERR_INVALID_OBJECT;
346     }
347 
348     cntlr = (struct WatchdogCntlr *)client->device->service;
349     switch (cmd) {
350         case WATCHDOG_IO_GET_PRIV:
351             return WatchdogUserGetPrivData(cntlr, reply);
352         case WATCHDOG_IO_RELEASE_PRIV:
353             return WatchdogReleasePriv(cntlr);
354         case WATCHDOG_IO_GET_STATUS:
355             return WatchdogUserGetStatus(cntlr, reply);
356         case WATCHDOG_IO_START:
357             return WatchdogCntlrStart(cntlr);
358         case WATCHDOG_IO_STOP:
359             return WatchdogCntlrStop(cntlr);
360         case WATCHDOG_IO_SET_TIMEOUT:
361             return WatchdogUserSetTimeout(cntlr, data);
362         case WATCHDOG_IO_GET_TIMEOUT:
363             return WatchdogUserGetTimeout(cntlr, reply);
364         case WATCHDOG_IO_FEED:
365             return WatchdogCntlrFeed(cntlr);
366         default:
367             HDF_LOGE("WatchdogIoDispatch: cmd %d is not support!", cmd);
368             return HDF_ERR_NOT_SUPPORT;
369     }
370 }
371