1 /* 2 * Copyright (c) 2015-2016 Quantenna Communications, Inc. 3 * All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 */ 16 17 #include "util.h" 18 #include "qtn_hw_ids.h" 19 20 void qtnf_sta_list_init(struct qtnf_sta_list *list) 21 { 22 if (unlikely(!list)) 23 return; 24 25 INIT_LIST_HEAD(&list->head); 26 atomic_set(&list->size, 0); 27 } 28 29 struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list, 30 const u8 *mac) 31 { 32 struct qtnf_sta_node *node; 33 34 if (unlikely(!mac)) 35 return NULL; 36 37 list_for_each_entry(node, &list->head, list) { 38 if (ether_addr_equal(node->mac_addr, mac)) 39 return node; 40 } 41 42 return NULL; 43 } 44 45 struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list, 46 size_t index) 47 { 48 struct qtnf_sta_node *node; 49 50 if (qtnf_sta_list_size(list) <= index) 51 return NULL; 52 53 list_for_each_entry(node, &list->head, list) { 54 if (index-- == 0) 55 return node; 56 } 57 58 return NULL; 59 } 60 61 struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_vif *vif, 62 const u8 *mac) 63 { 64 struct qtnf_sta_list *list = &vif->sta_list; 65 struct qtnf_sta_node *node; 66 67 if (unlikely(!mac)) 68 return NULL; 69 70 node = qtnf_sta_list_lookup(list, mac); 71 72 if (node) 73 goto done; 74 75 node = kzalloc(sizeof(*node), GFP_KERNEL); 76 if (unlikely(!node)) 77 goto done; 78 79 ether_addr_copy(node->mac_addr, mac); 80 list_add_tail(&node->list, &list->head); 81 atomic_inc(&list->size); 82 ++vif->generation; 83 84 done: 85 return node; 86 } 87 88 bool qtnf_sta_list_del(struct qtnf_vif *vif, const u8 *mac) 89 { 90 struct qtnf_sta_list *list = &vif->sta_list; 91 struct qtnf_sta_node *node; 92 bool ret = false; 93 94 node = qtnf_sta_list_lookup(list, mac); 95 96 if (node) { 97 list_del(&node->list); 98 atomic_dec(&list->size); 99 kfree(node); 100 ++vif->generation; 101 ret = true; 102 } 103 104 return ret; 105 } 106 107 void qtnf_sta_list_free(struct qtnf_sta_list *list) 108 { 109 struct qtnf_sta_node *node, *tmp; 110 111 atomic_set(&list->size, 0); 112 113 list_for_each_entry_safe(node, tmp, &list->head, list) { 114 list_del(&node->list); 115 kfree(node); 116 } 117 118 INIT_LIST_HEAD(&list->head); 119 } 120 121 const char *qtnf_chipid_to_string(unsigned long chip_id) 122 { 123 switch (chip_id) { 124 case QTN_CHIP_ID_TOPAZ: 125 return "Topaz"; 126 case QTN_CHIP_ID_PEARL: 127 return "Pearl revA"; 128 case QTN_CHIP_ID_PEARL_B: 129 return "Pearl revB"; 130 case QTN_CHIP_ID_PEARL_C: 131 return "Pearl revC"; 132 default: 133 return "unknown"; 134 } 135 } 136 EXPORT_SYMBOL_GPL(qtnf_chipid_to_string); 137