1*ff233cb5SSergey Matyukevich // SPDX-License-Identifier: GPL-2.0+
2*ff233cb5SSergey Matyukevich /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
398f44cb0SIgor Mitsyanko
498f44cb0SIgor Mitsyanko #include "util.h"
5b7da53cdSIgor Mitsyanko #include "qtn_hw_ids.h"
698f44cb0SIgor Mitsyanko
qtnf_sta_list_init(struct qtnf_sta_list * list)798f44cb0SIgor Mitsyanko void qtnf_sta_list_init(struct qtnf_sta_list *list)
898f44cb0SIgor Mitsyanko {
998f44cb0SIgor Mitsyanko if (unlikely(!list))
1098f44cb0SIgor Mitsyanko return;
1198f44cb0SIgor Mitsyanko
1298f44cb0SIgor Mitsyanko INIT_LIST_HEAD(&list->head);
1398f44cb0SIgor Mitsyanko atomic_set(&list->size, 0);
1498f44cb0SIgor Mitsyanko }
1598f44cb0SIgor Mitsyanko
qtnf_sta_list_lookup(struct qtnf_sta_list * list,const u8 * mac)1698f44cb0SIgor Mitsyanko struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list,
1798f44cb0SIgor Mitsyanko const u8 *mac)
1898f44cb0SIgor Mitsyanko {
1998f44cb0SIgor Mitsyanko struct qtnf_sta_node *node;
2098f44cb0SIgor Mitsyanko
2198f44cb0SIgor Mitsyanko if (unlikely(!mac))
2298f44cb0SIgor Mitsyanko return NULL;
2398f44cb0SIgor Mitsyanko
2498f44cb0SIgor Mitsyanko list_for_each_entry(node, &list->head, list) {
2598f44cb0SIgor Mitsyanko if (ether_addr_equal(node->mac_addr, mac))
2698f44cb0SIgor Mitsyanko return node;
2798f44cb0SIgor Mitsyanko }
2898f44cb0SIgor Mitsyanko
2998f44cb0SIgor Mitsyanko return NULL;
3098f44cb0SIgor Mitsyanko }
3198f44cb0SIgor Mitsyanko
qtnf_sta_list_lookup_index(struct qtnf_sta_list * list,size_t index)3298f44cb0SIgor Mitsyanko struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list,
3398f44cb0SIgor Mitsyanko size_t index)
3498f44cb0SIgor Mitsyanko {
3598f44cb0SIgor Mitsyanko struct qtnf_sta_node *node;
3698f44cb0SIgor Mitsyanko
3798f44cb0SIgor Mitsyanko if (qtnf_sta_list_size(list) <= index)
3898f44cb0SIgor Mitsyanko return NULL;
3998f44cb0SIgor Mitsyanko
4098f44cb0SIgor Mitsyanko list_for_each_entry(node, &list->head, list) {
4198f44cb0SIgor Mitsyanko if (index-- == 0)
4298f44cb0SIgor Mitsyanko return node;
4398f44cb0SIgor Mitsyanko }
4498f44cb0SIgor Mitsyanko
4598f44cb0SIgor Mitsyanko return NULL;
4698f44cb0SIgor Mitsyanko }
4798f44cb0SIgor Mitsyanko
qtnf_sta_list_add(struct qtnf_vif * vif,const u8 * mac)487a4d3a3bSIgor Mitsyanko struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_vif *vif,
4998f44cb0SIgor Mitsyanko const u8 *mac)
5098f44cb0SIgor Mitsyanko {
517a4d3a3bSIgor Mitsyanko struct qtnf_sta_list *list = &vif->sta_list;
5298f44cb0SIgor Mitsyanko struct qtnf_sta_node *node;
5398f44cb0SIgor Mitsyanko
5498f44cb0SIgor Mitsyanko if (unlikely(!mac))
5598f44cb0SIgor Mitsyanko return NULL;
5698f44cb0SIgor Mitsyanko
5798f44cb0SIgor Mitsyanko node = qtnf_sta_list_lookup(list, mac);
5898f44cb0SIgor Mitsyanko
5998f44cb0SIgor Mitsyanko if (node)
6098f44cb0SIgor Mitsyanko goto done;
6198f44cb0SIgor Mitsyanko
6298f44cb0SIgor Mitsyanko node = kzalloc(sizeof(*node), GFP_KERNEL);
6398f44cb0SIgor Mitsyanko if (unlikely(!node))
6498f44cb0SIgor Mitsyanko goto done;
6598f44cb0SIgor Mitsyanko
6698f44cb0SIgor Mitsyanko ether_addr_copy(node->mac_addr, mac);
6798f44cb0SIgor Mitsyanko list_add_tail(&node->list, &list->head);
6898f44cb0SIgor Mitsyanko atomic_inc(&list->size);
697a4d3a3bSIgor Mitsyanko ++vif->generation;
7098f44cb0SIgor Mitsyanko
7198f44cb0SIgor Mitsyanko done:
7298f44cb0SIgor Mitsyanko return node;
7398f44cb0SIgor Mitsyanko }
7498f44cb0SIgor Mitsyanko
qtnf_sta_list_del(struct qtnf_vif * vif,const u8 * mac)757a4d3a3bSIgor Mitsyanko bool qtnf_sta_list_del(struct qtnf_vif *vif, const u8 *mac)
7698f44cb0SIgor Mitsyanko {
777a4d3a3bSIgor Mitsyanko struct qtnf_sta_list *list = &vif->sta_list;
7898f44cb0SIgor Mitsyanko struct qtnf_sta_node *node;
7998f44cb0SIgor Mitsyanko bool ret = false;
8098f44cb0SIgor Mitsyanko
8198f44cb0SIgor Mitsyanko node = qtnf_sta_list_lookup(list, mac);
8298f44cb0SIgor Mitsyanko
8398f44cb0SIgor Mitsyanko if (node) {
8498f44cb0SIgor Mitsyanko list_del(&node->list);
8598f44cb0SIgor Mitsyanko atomic_dec(&list->size);
8698f44cb0SIgor Mitsyanko kfree(node);
877a4d3a3bSIgor Mitsyanko ++vif->generation;
8898f44cb0SIgor Mitsyanko ret = true;
8998f44cb0SIgor Mitsyanko }
9098f44cb0SIgor Mitsyanko
9198f44cb0SIgor Mitsyanko return ret;
9298f44cb0SIgor Mitsyanko }
9398f44cb0SIgor Mitsyanko
qtnf_sta_list_free(struct qtnf_sta_list * list)9498f44cb0SIgor Mitsyanko void qtnf_sta_list_free(struct qtnf_sta_list *list)
9598f44cb0SIgor Mitsyanko {
9698f44cb0SIgor Mitsyanko struct qtnf_sta_node *node, *tmp;
9798f44cb0SIgor Mitsyanko
9898f44cb0SIgor Mitsyanko atomic_set(&list->size, 0);
9998f44cb0SIgor Mitsyanko
10098f44cb0SIgor Mitsyanko list_for_each_entry_safe(node, tmp, &list->head, list) {
10198f44cb0SIgor Mitsyanko list_del(&node->list);
10298f44cb0SIgor Mitsyanko kfree(node);
10398f44cb0SIgor Mitsyanko }
10498f44cb0SIgor Mitsyanko
10598f44cb0SIgor Mitsyanko INIT_LIST_HEAD(&list->head);
10698f44cb0SIgor Mitsyanko }
107b7da53cdSIgor Mitsyanko
qtnf_chipid_to_string(unsigned long chip_id)108b7da53cdSIgor Mitsyanko const char *qtnf_chipid_to_string(unsigned long chip_id)
109b7da53cdSIgor Mitsyanko {
110b7da53cdSIgor Mitsyanko switch (chip_id) {
111e401fa25SSergey Matyukevich case QTN_CHIP_ID_TOPAZ:
112e401fa25SSergey Matyukevich return "Topaz";
113b7da53cdSIgor Mitsyanko case QTN_CHIP_ID_PEARL:
114b7da53cdSIgor Mitsyanko return "Pearl revA";
115b7da53cdSIgor Mitsyanko case QTN_CHIP_ID_PEARL_B:
116b7da53cdSIgor Mitsyanko return "Pearl revB";
117b7da53cdSIgor Mitsyanko case QTN_CHIP_ID_PEARL_C:
118b7da53cdSIgor Mitsyanko return "Pearl revC";
119b7da53cdSIgor Mitsyanko default:
120b7da53cdSIgor Mitsyanko return "unknown";
121b7da53cdSIgor Mitsyanko }
122b7da53cdSIgor Mitsyanko }
123b7da53cdSIgor Mitsyanko EXPORT_SYMBOL_GPL(qtnf_chipid_to_string);
124