xref: /openbmc/linux/drivers/net/wireless/quantenna/qtnfmac/util.c (revision 597473720f4dc69749542bfcfed4a927a43d935e)
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