1 /******************************************************************************
2 *
3 * Copyright(c) 2019 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #include "phl_headers.h"
16 #define _PHL_UTIL_C_
17
18
19 /* phl queue general API */
pq_init(void * d,struct phl_queue * q)20 void pq_init(void *d, struct phl_queue *q)
21 {
22 INIT_LIST_HEAD(&q->queue);
23 _os_spinlock_init(d, &q->lock);
24 q->cnt = 0;
25 }
26
pq_deinit(void * d,struct phl_queue * q)27 void pq_deinit(void *d, struct phl_queue *q)
28 {
29 _os_spinlock_free(d, &q->lock);
30 }
31
pq_reset(void * d,struct phl_queue * q,enum lock_type type)32 void pq_reset(void *d, struct phl_queue *q, enum lock_type type)
33 {
34 _os_spinlockfg sp_flags;
35
36 _os_spinlock(d, &q->lock, type, &sp_flags);
37 INIT_LIST_HEAD(&q->queue);
38 q->cnt = 0;
39 _os_spinunlock(d, &q->lock, type, &sp_flags);
40 }
41
pq_push(void * d,struct phl_queue * q,_os_list * obj,u8 pos,enum lock_type type)42 u8 pq_push(void *d, struct phl_queue *q, _os_list *obj, u8 pos, enum lock_type type)
43 {
44 _os_spinlockfg sp_flags;
45
46 _os_spinlock(d, &q->lock, type, &sp_flags);
47 if(pos == _first)
48 list_add(obj, &q->queue);
49 else
50 list_add_tail(obj, &q->queue);
51 q->cnt++;
52 _os_spinunlock(d, &q->lock, type, &sp_flags);
53 return true;
54 }
55
pq_pop(void * d,struct phl_queue * q,_os_list ** obj,u8 pos,enum lock_type type)56 u8 pq_pop(void *d, struct phl_queue *q, _os_list **obj, u8 pos, enum lock_type type)
57 {
58 _os_spinlockfg sp_flags = 0;
59
60 (*obj) = NULL;
61 _os_spinlock(d, &q->lock, type, &sp_flags);
62 if(!list_empty(&q->queue) && (q->cnt > 0)) {
63 if(pos == _first)
64 (*obj) = _get_next(&q->queue);
65 else
66 (*obj) = _get_prev(&q->queue);
67 list_del(*obj);
68 q->cnt--;
69 }
70 _os_spinunlock(d, &q->lock, type, &sp_flags);
71
72 return ((*obj) == NULL || (*obj) == &q->queue) ? (false) : (true);
73 }
74
pq_get_front(void * d,struct phl_queue * q,_os_list ** obj,enum lock_type type)75 u8 pq_get_front(void *d, struct phl_queue *q, _os_list **obj, enum lock_type type)
76 {
77 _os_spinlockfg sp_flags = 0;
78
79 (*obj) = NULL;
80
81 _os_spinlock(d, &q->lock, type, &sp_flags);
82 if(!list_empty(&q->queue) && (q->cnt > 0))
83 (*obj) = q->queue.next;
84 _os_spinunlock(d, &q->lock, type, &sp_flags);
85 return ((*obj) == NULL || (*obj) == &q->queue) ? (false) : (true);
86 }
87
pq_get_next(void * d,struct phl_queue * queue,_os_list * cur_obj,_os_list ** obj,enum lock_type type)88 u8 pq_get_next(void *d, struct phl_queue *queue, _os_list *cur_obj,
89 _os_list **obj, enum lock_type type)
90 {
91 _os_spinlockfg sp_flags;
92
93 (*obj) = NULL;
94 if(cur_obj == NULL)
95 return false;
96 _os_spinlock(d, &queue->lock, type, &sp_flags);
97 (*obj) = cur_obj->next;
98 _os_spinunlock(d, &queue->lock, type, &sp_flags);
99 return ((*obj) == NULL || (*obj) == &(queue->queue)) ? (false) : (true);
100 }
101
pq_get_tail(void * d,struct phl_queue * q,_os_list ** obj,enum lock_type type)102 u8 pq_get_tail(void *d, struct phl_queue *q, _os_list **obj, enum lock_type type)
103 {
104 _os_spinlockfg sp_flags = 0;
105
106 (*obj) = NULL;
107
108 _os_spinlock(d, &q->lock, type, &sp_flags);
109 if(!list_empty(&q->queue) && (q->cnt > 0))
110 (*obj) = q->queue.prev;
111 _os_spinunlock(d, &q->lock, type, &sp_flags);
112 return ((*obj) == NULL || (*obj) == &q->queue) ? (false) : (true);
113 }
114
pq_get_prev(void * d,struct phl_queue * queue,_os_list * cur_obj,_os_list ** obj,enum lock_type type)115 u8 pq_get_prev(void *d, struct phl_queue *queue, _os_list *cur_obj,
116 _os_list **obj, enum lock_type type)
117 {
118 _os_spinlockfg sp_flags;
119
120 (*obj) = NULL;
121 if(cur_obj == NULL)
122 return false;
123 _os_spinlock(d, &queue->lock, type, &sp_flags);
124 (*obj) = cur_obj->prev;
125 _os_spinunlock(d, &queue->lock, type, &sp_flags);
126 return ((*obj) == NULL || (*obj) == &(queue->queue)) ? (false) : (true);
127 }
128
pq_search_node(void * d,struct phl_queue * q,_os_list ** obj,enum lock_type type,bool bdel,void * priv,u8 (* search_fun)(void * d,void * obj,void * priv))129 u8 pq_search_node(void *d, struct phl_queue *q, _os_list **obj,
130 enum lock_type type, bool bdel, void *priv,
131 u8 (*search_fun)(void *d, void *obj, void *priv))
132 {
133 _os_spinlockfg sp_flags = 0;
134 _os_list *newobj = NULL;
135 bool bhit = false;
136
137 (*obj) = NULL;
138 _os_spinlock(d, &q->lock, type, &sp_flags);
139
140 if(!list_empty(&q->queue) && (q->cnt > 0))
141 newobj = _get_next(&q->queue);
142
143 while(newobj && (newobj != &(q->queue))) {
144
145 if(search_fun)
146 bhit = search_fun(d, newobj, priv);
147
148 if(bhit && bdel) {
149 list_del(newobj);
150 q->cnt--;
151 }
152
153 if(bhit) {
154 (*obj) = newobj;
155 break;
156 }
157
158 newobj = newobj->next;
159 };
160 _os_spinunlock(d, &q->lock, type, &sp_flags);
161
162 return ((*obj) == NULL || (*obj) == &(q->queue)) ? (false) : (true);
163 }
164
pq_del_node(void * d,struct phl_queue * q,_os_list * obj,enum lock_type type)165 void pq_del_node(void *d, struct phl_queue *q, _os_list *obj, enum lock_type type)
166 {
167 _os_spinlockfg sp_flags;
168
169 if(obj == NULL)
170 return;
171 _os_spinlock(d, &q->lock, type, &sp_flags);
172 list_del(obj);
173 q->cnt--;
174 _os_spinunlock(d, &q->lock, type, &sp_flags);
175 }
176
pq_insert(void * d,struct phl_queue * q,enum lock_type type,void * priv,_os_list * input,u8 (* pq_predicate)(void * d,void * priv,_os_list * input,_os_list * obj))177 u8 pq_insert(void *d, struct phl_queue *q, enum lock_type type, void *priv, _os_list *input,
178 u8 (*pq_predicate)(void *d, void *priv,_os_list *input, _os_list *obj))
179 {
180 _os_spinlockfg sp_flags;
181 _os_list *obj = NULL;
182
183 _os_spinlock(d, &q->lock, type, &sp_flags);
184 obj = q->queue.next;
185 while (obj != &(q->queue)) {
186 if (pq_predicate && (pq_predicate(d, priv, input, obj) == true))
187 break;
188 obj = obj->next;
189 }
190 list_add_tail(input, obj);
191 q->cnt++;
192 _os_spinunlock(d, &q->lock, type, &sp_flags);
193 return true;
194 }
phl_get_passing_time_us(u32 start)195 u32 phl_get_passing_time_us(u32 start)
196 {
197 u32 now = _os_get_cur_time_us();
198 u32 pass = 0;
199
200 if (now == start)
201 pass = 0;
202 else if (now > start)
203 /* -- start -- now -- */
204 pass = now - start;
205 else
206 /* -- now -- start -- */
207 pass = 0xffffffff - start + now;
208
209 return pass;
210 }
211
phl_get_passing_time_ms(u32 start)212 u32 phl_get_passing_time_ms(u32 start)
213 {
214 u32 now = _os_get_cur_time_ms();
215 u32 pass = 0;
216
217 if (now == start)
218 pass = 0;
219 else if (now > start)
220 /* -- start -- now -- */
221 pass = now - start;
222 else
223 /* -- now -- start -- */
224 pass = 0xffffffff - start + now;
225
226 return pass;
227 }