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