1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "hi_osal.h"
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/printk.h>
23 #include <linux/wait.h>
24 #include <linux/sched.h>
25 #include <linux/sched/signal.h>
26 #include <linux/slab.h>
27
osal_msecs_to_jiffies(const unsigned int m)28 unsigned long osal_msecs_to_jiffies(const unsigned int m)
29 {
30 return msecs_to_jiffies(m);
31 }
32 EXPORT_SYMBOL(osal_msecs_to_jiffies);
33
osal_wait_init(osal_wait_t * wait)34 int osal_wait_init(osal_wait_t *wait)
35 {
36 wait_queue_head_t *wq = NULL;
37 if (wait == NULL) {
38 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
39 return -1;
40 }
41 wq = (wait_queue_head_t *)kmalloc(sizeof(wait_queue_head_t), GFP_ATOMIC);
42 if (wq == NULL) {
43 osal_trace("%s - kmalloc error!\n", __FUNCTION__);
44 return -1;
45 }
46 init_waitqueue_head(wq);
47 wait->wait = wq;
48 return 0;
49 }
50 EXPORT_SYMBOL(osal_wait_init);
osal_wait_interruptible(osal_wait_t * wait,osal_wait_cond_func_t func,const void * param)51 int osal_wait_interruptible(osal_wait_t *wait, osal_wait_cond_func_t func, const void *param)
52 {
53 wait_queue_head_t *wq = NULL;
54 DEFINE_WAIT(__wait);
55 long ret = 0;
56 int condition = 0;
57
58 if (wait == NULL) {
59 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
60 return -1;
61 }
62
63 wq = (wait_queue_head_t *)(wait->wait);
64 if (wq == NULL) {
65 osal_trace("%s - wait->wait is NULL!\n", __FUNCTION__);
66 return -1;
67 }
68 prepare_to_wait(wq, &__wait, TASK_INTERRUPTIBLE);
69 /* if wakeup the queue before prepare_to_wait, the func will return true. And will not go to schedule */
70 if (func != NULL) {
71 condition = func(param);
72 }
73
74 if (!condition) {
75 if (!signal_pending(current)) {
76 schedule();
77 }
78 if (signal_pending(current)) {
79 ret = -ERESTARTSYS;
80 }
81 }
82
83 finish_wait(wq, &__wait);
84 return ret;
85 }
86 EXPORT_SYMBOL(osal_wait_interruptible);
87
osal_wait_uninterruptible(osal_wait_t * wait,osal_wait_cond_func_t func,const void * param)88 int osal_wait_uninterruptible(osal_wait_t *wait, osal_wait_cond_func_t func, const void *param)
89 {
90 wait_queue_head_t *wq = NULL;
91 DEFINE_WAIT(__wait);
92 long ret = 0;
93 int condition = 0;
94
95 if (wait == NULL) {
96 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
97 return -1;
98 }
99
100 wq = (wait_queue_head_t *)(wait->wait);
101 if (wq == NULL) {
102 osal_trace("%s - wait->wait is NULL!\n", __FUNCTION__);
103 return -1;
104 }
105 prepare_to_wait(wq, &__wait, TASK_UNINTERRUPTIBLE);
106 /* if wakeup the queue before prepare_to_wait, the func will return true. And will not go to schedule */
107 if (func != NULL) {
108 condition = func(param);
109 }
110
111 if (!condition) {
112 schedule();
113 }
114
115 finish_wait(wq, &__wait);
116 return ret;
117 }
118 EXPORT_SYMBOL(osal_wait_uninterruptible);
119
osal_wait_timeout_interruptible(osal_wait_t * wait,osal_wait_cond_func_t func,const void * param,unsigned long ms)120 int osal_wait_timeout_interruptible(osal_wait_t *wait, osal_wait_cond_func_t func, const void *param,
121 unsigned long ms)
122 {
123 wait_queue_head_t *wq = NULL;
124 DEFINE_WAIT(__wait);
125 long ret = ms;
126 int condition = 0;
127
128 if (wait == NULL) {
129 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
130 return -1;
131 }
132
133 wq = (wait_queue_head_t *)(wait->wait);
134 if (wq == NULL) {
135 osal_trace("%s - wait->wait is NULL!\n", __FUNCTION__);
136 return -1;
137 }
138 prepare_to_wait(wq, &__wait, TASK_INTERRUPTIBLE);
139 /* if wakeup the queue before prepare_to_wait, the func will return true. And will not go to schedule */
140 if (func != NULL) {
141 condition = func(param);
142 }
143
144 if (!condition) {
145 if (!signal_pending(current)) {
146 ret = schedule_timeout(msecs_to_jiffies(ret));
147 ret = jiffies_to_msecs(ret);
148 }
149 if (signal_pending(current)) {
150 ret = -ERESTARTSYS;
151 }
152 }
153
154 finish_wait(wq, &__wait);
155
156 return ret;
157 }
158
159 EXPORT_SYMBOL(osal_wait_timeout_interruptible);
160
osal_wait_timeout_uninterruptible(osal_wait_t * wait,osal_wait_cond_func_t func,const void * param,unsigned long ms)161 int osal_wait_timeout_uninterruptible(osal_wait_t *wait, osal_wait_cond_func_t func,
162 const void *param, unsigned long ms)
163 {
164 wait_queue_head_t *wq = NULL;
165 DEFINE_WAIT(__wait);
166 long ret = ms;
167 int condition = 0;
168
169 if (wait == NULL) {
170 osal_trace("%s - parameter invalid!\n", __FUNCTION__);
171 return -1;
172 }
173
174 wq = (wait_queue_head_t *)(wait->wait);
175 if (wq == NULL) {
176 osal_trace("%s - wait->wait is NULL!\n", __FUNCTION__);
177 return -1;
178 }
179 prepare_to_wait(wq, &__wait, TASK_UNINTERRUPTIBLE);
180 /* if wakeup the queue before prepare_to_wait, the func will return true. And will not go to schedule */
181 if (func != NULL) {
182 condition = func(param);
183 }
184
185 if (!condition) {
186 ret = schedule_timeout(msecs_to_jiffies(ret));
187 ret = jiffies_to_msecs(ret);
188 }
189
190 finish_wait(wq, &__wait);
191
192 return ret;
193 }
194 EXPORT_SYMBOL(osal_wait_timeout_uninterruptible);
195
osal_wakeup(osal_wait_t * wait)196 void osal_wakeup(osal_wait_t *wait)
197 {
198 wait_queue_head_t *wq = NULL;
199
200 wq = (wait_queue_head_t *)(wait->wait);
201 if (wq == NULL) {
202 osal_trace("%s - wait->wait is NULL!\n", __FUNCTION__);
203 return;
204 }
205 wake_up_all(wq);
206 }
207 EXPORT_SYMBOL(osal_wakeup);
osal_wait_destroy(osal_wait_t * wait)208 void osal_wait_destroy(osal_wait_t *wait)
209 {
210 wait_queue_head_t *wq = NULL;
211
212 wq = (wait_queue_head_t *)(wait->wait);
213 if (wq == NULL) {
214 osal_trace("%s - wait->wait is NULL!\n", __FUNCTION__);
215 return;
216 }
217 kfree(wq);
218 wait->wait = NULL;
219 }
220 EXPORT_SYMBOL(osal_wait_destroy);
221