diff options
Diffstat (limited to 'drivers/net/wireless/quantenna/qtnfmac/util.c')
-rw-r--r-- | drivers/net/wireless/quantenna/qtnfmac/util.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/drivers/net/wireless/quantenna/qtnfmac/util.c b/drivers/net/wireless/quantenna/qtnfmac/util.c new file mode 100644 index 000000000000..ed38e87471bf --- /dev/null +++ b/drivers/net/wireless/quantenna/qtnfmac/util.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015-2016 Quantenna Communications, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "util.h" + +void qtnf_sta_list_init(struct qtnf_sta_list *list) +{ + if (unlikely(!list)) + return; + + INIT_LIST_HEAD(&list->head); + atomic_set(&list->size, 0); +} + +struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list, + const u8 *mac) +{ + struct qtnf_sta_node *node; + + if (unlikely(!mac)) + return NULL; + + list_for_each_entry(node, &list->head, list) { + if (ether_addr_equal(node->mac_addr, mac)) + return node; + } + + return NULL; +} + +struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list, + size_t index) +{ + struct qtnf_sta_node *node; + + if (qtnf_sta_list_size(list) <= index) + return NULL; + + list_for_each_entry(node, &list->head, list) { + if (index-- == 0) + return node; + } + + return NULL; +} + +struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_sta_list *list, + const u8 *mac) +{ + struct qtnf_sta_node *node; + + if (unlikely(!mac)) + return NULL; + + node = qtnf_sta_list_lookup(list, mac); + + if (node) + goto done; + + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (unlikely(!node)) + goto done; + + ether_addr_copy(node->mac_addr, mac); + list_add_tail(&node->list, &list->head); + atomic_inc(&list->size); + +done: + return node; +} + +bool qtnf_sta_list_del(struct qtnf_sta_list *list, const u8 *mac) +{ + struct qtnf_sta_node *node; + bool ret = false; + + node = qtnf_sta_list_lookup(list, mac); + + if (node) { + list_del(&node->list); + atomic_dec(&list->size); + kfree(node); + ret = true; + } + + return ret; +} + +void qtnf_sta_list_free(struct qtnf_sta_list *list) +{ + struct qtnf_sta_node *node, *tmp; + + atomic_set(&list->size, 0); + + list_for_each_entry_safe(node, tmp, &list->head, list) { + list_del(&node->list); + kfree(node); + } + + INIT_LIST_HEAD(&list->head); +} |