xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/phl/phl_util.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 }