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