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