1// SPDX-License-Identifier: GPL-2.0+
2/* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
3
4#include "util.h"
5#include "qtn_hw_ids.h"
6
7void qtnf_sta_list_init(struct qtnf_sta_list *list)
8{
9	if (unlikely(!list))
10		return;
11
12	INIT_LIST_HEAD(&list->head);
13	atomic_set(&list->size, 0);
14}
15
16struct qtnf_sta_node *qtnf_sta_list_lookup(struct qtnf_sta_list *list,
17					   const u8 *mac)
18{
19	struct qtnf_sta_node *node;
20
21	if (unlikely(!mac))
22		return NULL;
23
24	list_for_each_entry(node, &list->head, list) {
25		if (ether_addr_equal(node->mac_addr, mac))
26			return node;
27	}
28
29	return NULL;
30}
31
32struct qtnf_sta_node *qtnf_sta_list_lookup_index(struct qtnf_sta_list *list,
33						 size_t index)
34{
35	struct qtnf_sta_node *node;
36
37	if (qtnf_sta_list_size(list) <= index)
38		return NULL;
39
40	list_for_each_entry(node, &list->head, list) {
41		if (index-- == 0)
42			return node;
43	}
44
45	return NULL;
46}
47
48struct qtnf_sta_node *qtnf_sta_list_add(struct qtnf_vif *vif,
49					const u8 *mac)
50{
51	struct qtnf_sta_list *list = &vif->sta_list;
52	struct qtnf_sta_node *node;
53
54	if (unlikely(!mac))
55		return NULL;
56
57	node = qtnf_sta_list_lookup(list, mac);
58
59	if (node)
60		goto done;
61
62	node = kzalloc(sizeof(*node), GFP_KERNEL);
63	if (unlikely(!node))
64		goto done;
65
66	ether_addr_copy(node->mac_addr, mac);
67	list_add_tail(&node->list, &list->head);
68	atomic_inc(&list->size);
69	++vif->generation;
70
71done:
72	return node;
73}
74
75bool qtnf_sta_list_del(struct qtnf_vif *vif, const u8 *mac)
76{
77	struct qtnf_sta_list *list = &vif->sta_list;
78	struct qtnf_sta_node *node;
79	bool ret = false;
80
81	node = qtnf_sta_list_lookup(list, mac);
82
83	if (node) {
84		list_del(&node->list);
85		atomic_dec(&list->size);
86		kfree(node);
87		++vif->generation;
88		ret = true;
89	}
90
91	return ret;
92}
93
94void qtnf_sta_list_free(struct qtnf_sta_list *list)
95{
96	struct qtnf_sta_node *node, *tmp;
97
98	atomic_set(&list->size, 0);
99
100	list_for_each_entry_safe(node, tmp, &list->head, list) {
101		list_del(&node->list);
102		kfree(node);
103	}
104
105	INIT_LIST_HEAD(&list->head);
106}
107
108const char *qtnf_chipid_to_string(unsigned long chip_id)
109{
110	switch (chip_id) {
111	case QTN_CHIP_ID_TOPAZ:
112		return "Topaz";
113	case QTN_CHIP_ID_PEARL:
114		return "Pearl revA";
115	case QTN_CHIP_ID_PEARL_B:
116		return "Pearl revB";
117	case QTN_CHIP_ID_PEARL_C:
118		return "Pearl revC";
119	default:
120		return "unknown";
121	}
122}
123EXPORT_SYMBOL_GPL(qtnf_chipid_to_string);
124