xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_list.c (revision 4865edfd190c086bbe2c69aae12a8226f877b91e)
1 /*
2  * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: qdf_list.c
21  *
22  * QCA driver framework list manipulation APIs. QDF linked list
23  * APIs are NOT thread safe so make sure to use appropriate locking mechanisms
24  * to assure operations on the list are thread safe.
25  */
26 
27 /* Include files */
28 #include <qdf_list.h>
29 #include <qdf_module.h>
30 
31 /* Function declarations and documenation */
32 
33 QDF_STATUS qdf_list_insert_before(qdf_list_t *list,
34 	qdf_list_node_t *new_node, qdf_list_node_t *node)
35 {
36 	list_add_tail(new_node, node);
37 	list->count++;
38 
39 	return QDF_STATUS_SUCCESS;
40 }
41 qdf_export_symbol(qdf_list_insert_before);
42 
43 QDF_STATUS qdf_list_insert_after(qdf_list_t *list,
44 	qdf_list_node_t *new_node, qdf_list_node_t *node)
45 {
46 	list_add(new_node, node);
47 	list->count++;
48 
49 	return QDF_STATUS_SUCCESS;
50 }
51 qdf_export_symbol(qdf_list_insert_after);
52 
53 /**
54  * qdf_list_insert_front() - insert input node at front of the list
55  * @list: Pointer to list
56  * @node: Pointer to input node
57  *
58  * Return: QDF status
59  */
60 QDF_STATUS qdf_list_insert_front(qdf_list_t *list, qdf_list_node_t *node)
61 {
62 	list_add(node, &list->anchor);
63 	list->count++;
64 	return QDF_STATUS_SUCCESS;
65 }
66 qdf_export_symbol(qdf_list_insert_front);
67 
68 /**
69  * qdf_list_insert_back() - insert input node at back of the list
70  * @list: Pointer to list
71  * @node: Pointer to input node
72  *
73  * Return: QDF status
74  */
75 QDF_STATUS qdf_list_insert_back(qdf_list_t *list, qdf_list_node_t *node)
76 {
77 	list_add_tail(node, &list->anchor);
78 	list->count++;
79 	return QDF_STATUS_SUCCESS;
80 }
81 qdf_export_symbol(qdf_list_insert_back);
82 
83 /**
84  * qdf_list_insert_back_size() - insert input node at back of list and save
85  * list size
86  * @list: Pointer to list
87  * @node: Pointer to input node
88  * @p_size: Pointer to store list size
89  *
90  * Return: QDF status
91  */
92 QDF_STATUS qdf_list_insert_back_size(qdf_list_t *list,
93 				     qdf_list_node_t *node, uint32_t *p_size)
94 {
95 	list_add_tail(node, &list->anchor);
96 	list->count++;
97 	*p_size = list->count;
98 	return QDF_STATUS_SUCCESS;
99 }
100 qdf_export_symbol(qdf_list_insert_back_size);
101 
102 /**
103  * qdf_list_remove_front() - remove node from front of the list
104  * @list: Pointer to list
105  * @node2: Double pointer to store the node which is removed from list
106  *
107  * Return: QDF status
108  */
109 QDF_STATUS qdf_list_remove_front(qdf_list_t *list, qdf_list_node_t **node2)
110 {
111 	struct list_head *listptr;
112 
113 	if (list_empty(&list->anchor))
114 		return QDF_STATUS_E_EMPTY;
115 
116 	listptr = list->anchor.next;
117 	*node2 = listptr;
118 	list_del(list->anchor.next);
119 	list->count--;
120 
121 	return QDF_STATUS_SUCCESS;
122 }
123 qdf_export_symbol(qdf_list_remove_front);
124 
125 /**
126  * qdf_list_remove_back() - remove node from end of the list
127  * @list: Pointer to list
128  * @node2: Double pointer to store node which is removed from list
129  *
130  * Return: QDF status
131  */
132 QDF_STATUS qdf_list_remove_back(qdf_list_t *list, qdf_list_node_t **node2)
133 {
134 	struct list_head *listptr;
135 
136 	if (list_empty(&list->anchor))
137 		return QDF_STATUS_E_EMPTY;
138 
139 	listptr = list->anchor.prev;
140 	*node2 = listptr;
141 	list_del(list->anchor.prev);
142 	list->count--;
143 
144 	return QDF_STATUS_SUCCESS;
145 }
146 qdf_export_symbol(qdf_list_remove_back);
147 
148 /**
149  * qdf_list_has_node() - check if a node is in a list
150  * @list: pointer to the list being searched
151  * @node: pointer to the node to search for
152  *
153  * It is expected that the list being checked is locked
154  * when this function is being called.
155  *
156  * Return: true if the node is in the list
157  */
158 bool qdf_list_has_node(qdf_list_t *list, qdf_list_node_t *node)
159 {
160 	qdf_list_node_t *tmp;
161 
162 	list_for_each(tmp, &list->anchor) {
163 		if (tmp == node)
164 			return true;
165 	}
166 	return false;
167 }
168 
169 /**
170  * qdf_list_remove_node() - remove input node from list
171  * @list: Pointer to list
172  * @node_to_remove: Pointer to node which needs to be removed
173  *
174  * verifies that the node is in the list before removing it.
175  * It is expected that the list being removed from is locked
176  * when this function is being called.
177  *
178  * Return: QDF status
179  */
180 QDF_STATUS qdf_list_remove_node(qdf_list_t *list,
181 				qdf_list_node_t *node_to_remove)
182 {
183 	if (list_empty(&list->anchor))
184 		return QDF_STATUS_E_EMPTY;
185 
186 	list_del(node_to_remove);
187 	list->count--;
188 
189 	return QDF_STATUS_SUCCESS;
190 }
191 qdf_export_symbol(qdf_list_remove_node);
192 
193 /**
194  * qdf_list_peek_front() - peek front node from list
195  * @list: Pointer to list
196  * @node2: Double pointer to store peeked node pointer
197  *
198  * Return: QDF status
199  */
200 QDF_STATUS qdf_list_peek_front(qdf_list_t *list, qdf_list_node_t **node2)
201 {
202 	struct list_head *listptr;
203 
204 	if (list_empty(&list->anchor))
205 		return QDF_STATUS_E_EMPTY;
206 
207 	listptr = list->anchor.next;
208 	*node2 = listptr;
209 	return QDF_STATUS_SUCCESS;
210 }
211 qdf_export_symbol(qdf_list_peek_front);
212 
213 /**
214  * qdf_list_peek_next() - peek next node of input node in the list
215  * @list: Pointer to list
216  * @node: Pointer to input node
217  * @node2: Double pointer to store peeked node pointer
218  *
219  * Return: QDF status
220  */
221 QDF_STATUS qdf_list_peek_next(qdf_list_t *list,
222 			      qdf_list_node_t *node,
223 			      qdf_list_node_t **node2)
224 {
225 	if (!list || !node || !node2)
226 		return QDF_STATUS_E_FAULT;
227 
228 	if (list_empty(&list->anchor))
229 		return QDF_STATUS_E_EMPTY;
230 
231 	if (node->next == &list->anchor)
232 		return QDF_STATUS_E_EMPTY;
233 
234 	*node2 = node->next;
235 
236 	return QDF_STATUS_SUCCESS;
237 }
238 qdf_export_symbol(qdf_list_peek_next);
239 
240 /**
241  * qdf_list_empty() - check if the list is empty
242  * @list: pointer to the list
243  *
244  * Return: true if the list is empty and false otherwise.
245  */
246 bool qdf_list_empty(qdf_list_t *list)
247 {
248 	return list_empty(&list->anchor);
249 }
250 qdf_export_symbol(qdf_list_empty);
251