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