1 /*
2 * osal_timer.c
3 *
4 * osal driver
5 *
6 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19 #include "osal_timer.h"
20 #include <linux/errno.h>
21 #include <linux/export.h>
22 #include <linux/signal.h>
23 #include <linux/timer.h>
24 #include "hdf_log.h"
25 #include "osal_mem.h"
26 #include "osal_mutex.h"
27
28 #define HDF_LOG_TAG osal_timer
29
30 typedef enum {
31 OSAL_TIMER_ONCE,
32 OSAL_TIMER_LOOP,
33 } OsalTimerMode;
34
35 struct osal_ktimer {
36 uintptr_t arg;
37 struct timer_list timer;
38 OsalTimerFunc func;
39 uint32_t msec;
40 struct OsalMutex mutex;
41 OsalTimerMode mode;
42 bool stop_flag;
43 };
44
osal_timer_callback(struct timer_list * arg)45 static void osal_timer_callback(struct timer_list *arg)
46 {
47 struct osal_ktimer *ktimer = NULL;
48 uint32_t msec;
49 OsalTimerMode mode;
50 bool stop_flag = false;
51
52 if (arg == NULL) {
53 HDF_LOGI("%s timer is stopped", __func__);
54 return;
55 }
56
57 ktimer = from_timer(ktimer, arg, timer);
58
59 OsalMutexTimedLock(&ktimer->mutex, HDF_WAIT_FOREVER);
60 mode = ktimer->mode;
61 stop_flag = ktimer->stop_flag;
62 OsalMutexUnlock(&ktimer->mutex);
63
64 if (!stop_flag) {
65 ktimer->func(ktimer->arg);
66 OsalMutexTimedLock(&ktimer->mutex, HDF_WAIT_FOREVER);
67 msec = ktimer->msec;
68 OsalMutexUnlock(&ktimer->mutex);
69 if (mode == OSAL_TIMER_LOOP) {
70 ktimer->timer.expires = jiffies + msecs_to_jiffies(msec);
71 mod_timer(&ktimer->timer, ktimer->timer.expires);
72 }
73 } else {
74 del_timer(&ktimer->timer);
75 OsalMutexDestroy(&ktimer->mutex);
76 OsalMemFree(ktimer);
77 HDF_LOGI("%s timer is stop", __func__);
78 }
79 }
80
OsalTimerCreate(OsalTimer * timer,uint32_t interval,OsalTimerFunc func,uintptr_t arg)81 int32_t OsalTimerCreate(OsalTimer *timer, uint32_t interval, OsalTimerFunc func, uintptr_t arg)
82 {
83 struct osal_ktimer *ktimer = NULL;
84
85 if (func == NULL || timer == NULL || interval == 0) {
86 HDF_LOGE("%s invalid para", __func__);
87 return HDF_ERR_INVALID_PARAM;
88 }
89
90 ktimer = (struct osal_ktimer *)OsalMemCalloc(sizeof(*ktimer));
91 if (ktimer == NULL) {
92 HDF_LOGE("%s malloc fail", __func__);
93 timer->realTimer = NULL;
94 return HDF_ERR_MALLOC_FAIL;
95 }
96
97 ktimer->arg = arg;
98 ktimer->func = func;
99 ktimer->msec = interval;
100 ktimer->stop_flag = false;
101 OsalMutexInit(&ktimer->mutex);
102 timer->realTimer = (void *)ktimer;
103
104 return HDF_SUCCESS;
105 }
106 EXPORT_SYMBOL(OsalTimerCreate);
107
OsalTimerStart(OsalTimer * timer,OsalTimerMode mode)108 static int32_t OsalTimerStart(OsalTimer *timer, OsalTimerMode mode)
109 {
110 struct osal_ktimer *ktimer = NULL;
111 struct timer_list *timer_id = NULL;
112
113 if (timer == NULL || timer->realTimer == NULL) {
114 HDF_LOGE("%s invalid para", __func__);
115 return HDF_ERR_INVALID_PARAM;
116 }
117
118 ktimer = (struct osal_ktimer *)timer->realTimer;
119 timer_id = &ktimer->timer;
120 timer_setup(timer_id, osal_timer_callback, 0);
121 ktimer->mode = mode;
122 timer_id->expires = jiffies + msecs_to_jiffies(ktimer->msec);
123 add_timer(timer_id);
124
125 return HDF_SUCCESS;
126 }
127
OsalTimerStartOnce(OsalTimer * timer)128 int32_t OsalTimerStartOnce(OsalTimer *timer)
129 {
130 return OsalTimerStart(timer, OSAL_TIMER_ONCE);
131 }
132 EXPORT_SYMBOL(OsalTimerStartOnce);
133
OsalTimerStartLoop(OsalTimer * timer)134 int32_t OsalTimerStartLoop(OsalTimer *timer)
135 {
136 return OsalTimerStart(timer, OSAL_TIMER_LOOP);
137 }
138
139 EXPORT_SYMBOL(OsalTimerStartLoop);
140
OsalTimerSetTimeout(OsalTimer * timer,uint32_t interval)141 int32_t OsalTimerSetTimeout(OsalTimer *timer, uint32_t interval)
142 {
143 struct osal_ktimer *ktimer = NULL;
144
145 if (timer == NULL || timer->realTimer == NULL || interval == 0) {
146 HDF_LOGE("%s invalid para", __func__);
147 return HDF_ERR_INVALID_PARAM;
148 }
149
150 ktimer = (struct osal_ktimer *)timer->realTimer;
151 if (ktimer->msec == interval)
152 return HDF_SUCCESS;
153
154 OsalMutexTimedLock(&ktimer->mutex, HDF_WAIT_FOREVER);
155 ktimer->msec = interval;
156 OsalMutexUnlock(&ktimer->mutex);
157
158 return HDF_SUCCESS;
159 }
160 EXPORT_SYMBOL(OsalTimerSetTimeout);
161
OsalTimerDelete(OsalTimer * timer)162 int32_t OsalTimerDelete(OsalTimer *timer)
163 {
164 struct osal_ktimer *ktimer = NULL;
165
166 if (timer == NULL || timer->realTimer == NULL) {
167 HDF_LOGE("%s invalid para", __func__);
168 return HDF_ERR_INVALID_PARAM;
169 }
170
171 ktimer = (struct osal_ktimer *)timer->realTimer;
172 OsalMutexTimedLock(&ktimer->mutex, HDF_WAIT_FOREVER);
173 ktimer->stop_flag = true;
174 OsalMutexUnlock(&ktimer->mutex);
175
176 if (ktimer->mode == OSAL_TIMER_ONCE)
177 mod_timer(&ktimer->timer, ktimer->timer.expires);
178
179 timer->realTimer = NULL;
180
181 return HDF_SUCCESS;
182 }
183 EXPORT_SYMBOL(OsalTimerDelete);
184
185