xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer_list.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <wlan_mlo_mgr_public_structs.h>
18 #include "wlan_mlo_mgr_main.h"
19 #include "qdf_types.h"
20 #include "wlan_cmn.h"
21 #include "wlan_mlo_mgr_peer.h"
22 
23 struct aid_search {
24 	struct wlan_mlo_peer_context *ml_peer;
25 	uint16_t aid;
26 };
27 
28 struct mlpeerid_search {
29 	struct wlan_mlo_peer_context *ml_peer;
30 	uint16_t ml_peerid;
31 };
32 
33 struct link_mac_search {
34 	struct wlan_mlo_peer_context *ml_peer;
35 	struct qdf_mac_addr mac_addr;
36 };
37 
38 static inline struct wlan_mlo_peer_context *wlan_mlo_peer_list_peek_head(
39 					qdf_list_t *peer_list)
40 {
41 	struct wlan_mlo_peer_context *ml_peer;
42 	qdf_list_node_t *peer_node = NULL;
43 
44 	/* This API is invoked with lock acquired, do not add log prints */
45 	if (qdf_list_peek_front(peer_list, &peer_node) != QDF_STATUS_SUCCESS)
46 		return NULL;
47 
48 	ml_peer = qdf_container_of(peer_node,
49 				   struct wlan_mlo_peer_context, peer_node);
50 	return ml_peer;
51 }
52 
53 static inline struct wlan_mlo_peer_context *wlan_mlo_peer_get_next_mlpeer(
54 					qdf_list_t *peer_list,
55 					struct wlan_mlo_peer_context *ml_peer)
56 {
57 	struct wlan_mlo_peer_context *next_peer;
58 	qdf_list_node_t *node = &ml_peer->peer_node;
59 	qdf_list_node_t *next_node = NULL;
60 
61 	/* This API is invoked with lock acquired, do not add log prints */
62 	if (!node)
63 		return NULL;
64 
65 	if (qdf_list_peek_next(peer_list, node, &next_node) !=
66 				QDF_STATUS_SUCCESS)
67 		return NULL;
68 
69 	next_peer = qdf_container_of(next_node,
70 				     struct wlan_mlo_peer_context, peer_node);
71 
72 	return next_peer;
73 }
74 
75 static inline struct wlan_mlo_peer_context *mlo_get_mlpeer(
76 				struct wlan_mlo_dev_context *ml_dev,
77 				struct qdf_mac_addr *ml_addr)
78 {
79 	uint8_t hash_index;
80 	struct wlan_mlo_peer_list *mlo_peer_list;
81 	struct wlan_mlo_peer_context *ml_peer;
82 	struct wlan_mlo_peer_context *next_ml_peer;
83 	qdf_list_t *peer_hash_list;
84 
85 	mlo_peer_list = &ml_dev->mlo_peer_list;
86 	hash_index = WLAN_PEER_HASH(ml_addr->bytes);
87 
88 	peer_hash_list = &mlo_peer_list->peer_hash[hash_index];
89 	/* Get first vdev */
90 	ml_peer = wlan_mlo_peer_list_peek_head(peer_hash_list);
91 	/**
92 	 * Iterate through pdev's vdev list, till vdev id matches with
93 	 * entry of vdev list
94 	 */
95 	while (ml_peer) {
96 		if (qdf_is_macaddr_equal(&ml_peer->peer_mld_addr, ml_addr))
97 			return ml_peer;
98 
99 		/* get next vdev */
100 		next_ml_peer = wlan_mlo_peer_get_next_mlpeer(peer_hash_list,
101 							     ml_peer);
102 		ml_peer = next_ml_peer;
103 	}
104 
105 	return NULL;
106 }
107 
108 QDF_STATUS wlan_mlo_iterate_ml_peerlist(struct wlan_mlo_dev_context *ml_dev,
109 					wlan_mlo_op_handler handler,
110 					void *arg)
111 {
112 	uint8_t hash_index;
113 	struct wlan_mlo_peer_list *peerlist;
114 	struct wlan_mlo_peer_context *ml_peer;
115 	struct wlan_mlo_peer_context *next;
116 	qdf_list_t *peer_hash_list;
117 	QDF_STATUS status;
118 
119 	peerlist = &ml_dev->mlo_peer_list;
120 	ml_peerlist_lock_acquire(peerlist);
121 
122 	for (hash_index = 0; hash_index < WLAN_PEER_HASHSIZE; hash_index++) {
123 		peer_hash_list = &peerlist->peer_hash[hash_index];
124 		/* Get first vdev */
125 		ml_peer = wlan_mlo_peer_list_peek_head(peer_hash_list);
126 		/**
127 		 * Iterate through pdev's vdev list, till vdev id matches with
128 		 * entry of vdev list
129 		 */
130 		while (ml_peer) {
131 			status = handler(ml_dev, ml_peer, arg);
132 			if (status == QDF_STATUS_SUCCESS) {
133 				ml_peerlist_lock_release(peerlist);
134 				return QDF_STATUS_SUCCESS;
135 			}
136 			/* get next ml peer */
137 			next = wlan_mlo_peer_get_next_mlpeer(peer_hash_list,
138 							     ml_peer);
139 			ml_peer = next;
140 		}
141 	}
142 	ml_peerlist_lock_release(peerlist);
143 
144 	return QDF_STATUS_E_NOENT;
145 }
146 
147 static QDF_STATUS
148 wlan_find_mlpeer_link_mac_addr(struct wlan_mlo_dev_context *ml_dev,
149 			       void *iter_ml_peer,
150 			       void *arg)
151 {
152 	struct link_mac_search *link_mac_arg = (struct link_mac_search *)arg;
153 	struct wlan_mlo_link_peer_entry *link_peer;
154 	struct wlan_mlo_peer_context *ml_peer;
155 	uint8_t i;
156 
157 	ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer;
158 	for (i = 0; i < MAX_MLO_PEER; i++) {
159 		link_peer = &ml_peer->peer_list[i];
160 		if (!link_peer)
161 			continue;
162 
163 		if (qdf_is_macaddr_equal(&link_mac_arg->mac_addr,
164 					 &link_peer->link_addr)) {
165 			link_mac_arg->ml_peer = ml_peer;
166 			return QDF_STATUS_SUCCESS;
167 		}
168 	}
169 	return QDF_STATUS_E_NOENT;
170 }
171 
172 static QDF_STATUS wlan_find_mlpeer_aid(struct wlan_mlo_dev_context *ml_dev,
173 				       void *iter_ml_peer,
174 				       void *arg)
175 {
176 	struct aid_search *aid_arg = (struct aid_search *)arg;
177 	struct wlan_mlo_peer_context *ml_peer;
178 
179 	ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer;
180 
181 	if (aid_arg->aid == ml_peer->assoc_id) {
182 		aid_arg->ml_peer = ml_peer;
183 		return QDF_STATUS_SUCCESS;
184 	}
185 
186 	return QDF_STATUS_E_NOENT;
187 }
188 
189 static QDF_STATUS
190 wlan_find_mlpeer_ml_peerid(struct wlan_mlo_dev_context *ml_dev,
191 			   void *iter_ml_peer,
192 			   void *arg)
193 {
194 	struct mlpeerid_search *mlpeer_id_arg = (struct mlpeerid_search *)arg;
195 	struct wlan_mlo_peer_context *ml_peer;
196 
197 	ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer;
198 
199 	if (mlpeer_id_arg->ml_peerid == ml_peer->mlo_peer_id) {
200 		mlpeer_id_arg->ml_peer = ml_peer;
201 		return QDF_STATUS_SUCCESS;
202 	}
203 
204 	return QDF_STATUS_E_NOENT;
205 }
206 
207 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_linkmac(
208 				struct wlan_mlo_dev_context *ml_dev,
209 				struct qdf_mac_addr *link_mac)
210 {
211 	struct link_mac_search link_mac_arg;
212 	QDF_STATUS status;
213 
214 	qdf_copy_macaddr(&link_mac_arg.mac_addr, link_mac);
215 	status = wlan_mlo_iterate_ml_peerlist(ml_dev,
216 					      wlan_find_mlpeer_link_mac_addr,
217 					      &link_mac_arg);
218 	if (status == QDF_STATUS_SUCCESS)
219 		return link_mac_arg.ml_peer;
220 
221 	/* TODO: Take ref */
222 
223 	return NULL;
224 }
225 
226 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_aid(
227 				struct wlan_mlo_dev_context *ml_dev,
228 				uint16_t assoc_id)
229 {
230 	struct aid_search aid_arg;
231 	QDF_STATUS status;
232 
233 	aid_arg.aid = assoc_id;
234 	status = wlan_mlo_iterate_ml_peerlist(ml_dev,
235 					      wlan_find_mlpeer_aid,
236 					      &aid_arg);
237 	if (status == QDF_STATUS_SUCCESS)
238 		return aid_arg.ml_peer;
239 
240 	/* TODO: Take ref */
241 
242 	return NULL;
243 }
244 
245 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_ml_peerid(
246 				struct wlan_mlo_dev_context *ml_dev,
247 				uint16_t ml_peerid)
248 {
249 	struct mlpeerid_search peerid_arg;
250 	QDF_STATUS status;
251 
252 	peerid_arg.ml_peerid = ml_peerid;
253 	status = wlan_mlo_iterate_ml_peerlist(ml_dev,
254 					      wlan_find_mlpeer_ml_peerid,
255 					      &peerid_arg);
256 	if (status == QDF_STATUS_SUCCESS)
257 		return peerid_arg.ml_peer;
258 
259 	/* TODO: Take ref */
260 
261 	return NULL;
262 }
263 
264 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer(
265 				struct wlan_mlo_dev_context *ml_dev,
266 				struct qdf_mac_addr *ml_addr)
267 {
268 	struct wlan_mlo_peer_context *ml_peer;
269 	struct wlan_mlo_peer_list *mlo_peer_list;
270 
271 	mlo_peer_list = &ml_dev->mlo_peer_list;
272 	ml_peerlist_lock_acquire(mlo_peer_list);
273 	ml_peer = mlo_get_mlpeer(ml_dev, ml_addr);
274 	if (!ml_peer) {
275 		ml_peerlist_lock_release(mlo_peer_list);
276 		return NULL;
277 	}
278 	/* TODO: Take ref */
279 
280 	ml_peerlist_lock_release(mlo_peer_list);
281 	return ml_peer;
282 }
283 
284 static void wlan_mlo_peerlist_add_tail(qdf_list_t *obj_list,
285 				       struct wlan_mlo_peer_context *obj)
286 {
287 	qdf_list_insert_back(obj_list, &obj->peer_node);
288 }
289 
290 static QDF_STATUS wlan_mlo_peerlist_remove_mlpeer(
291 				qdf_list_t *obj_list,
292 				struct wlan_mlo_peer_context *ml_peer)
293 {
294 	qdf_list_node_t *peer_node = NULL;
295 
296 	if (!ml_peer)
297 		return QDF_STATUS_E_FAILURE;
298 	/* get vdev list node element */
299 	peer_node = &ml_peer->peer_node;
300 	/* list is empty, return failure */
301 	if (qdf_list_remove_node(obj_list, peer_node) != QDF_STATUS_SUCCESS)
302 		return QDF_STATUS_E_FAILURE;
303 
304 	return QDF_STATUS_SUCCESS;
305 }
306 
307 QDF_STATUS mlo_dev_mlpeer_attach(struct wlan_mlo_dev_context *ml_dev,
308 				 struct wlan_mlo_peer_context *ml_peer)
309 {
310 	uint8_t hash_index;
311 	struct wlan_mlo_peer_list *mlo_peer_list;
312 
313 	mlo_peer_list = &ml_dev->mlo_peer_list;
314 	ml_peerlist_lock_acquire(mlo_peer_list);
315 	if (mlo_get_mlpeer(ml_dev, &ml_peer->peer_mld_addr)) {
316 		ml_peerlist_lock_release(mlo_peer_list);
317 		return QDF_STATUS_E_EXISTS;
318 	}
319 
320 	hash_index = WLAN_PEER_HASH(ml_peer->peer_mld_addr.bytes);
321 	wlan_mlo_peerlist_add_tail(&mlo_peer_list->peer_hash[hash_index],
322 				   ml_peer);
323 	ml_peerlist_lock_release(mlo_peer_list);
324 
325 	return QDF_STATUS_SUCCESS;
326 }
327 
328 QDF_STATUS mlo_dev_mlpeer_detach(struct wlan_mlo_dev_context *ml_dev,
329 				 struct wlan_mlo_peer_context *ml_peer)
330 {
331 	uint8_t hash_index;
332 	QDF_STATUS status;
333 	struct wlan_mlo_peer_list *mlo_peer_list;
334 
335 	mlo_peer_list = &ml_dev->mlo_peer_list;
336 	ml_peerlist_lock_acquire(mlo_peer_list);
337 	hash_index = WLAN_PEER_HASH(ml_peer->peer_mld_addr.bytes);
338 	status = wlan_mlo_peerlist_remove_mlpeer(
339 					&mlo_peer_list->peer_hash[hash_index],
340 					ml_peer);
341 	ml_peerlist_lock_release(mlo_peer_list);
342 
343 	return status;
344 }
345 
346 QDF_STATUS mlo_dev_mlpeer_list_init(struct wlan_mlo_dev_context *ml_dev)
347 {
348 	struct wlan_mlo_peer_list *mlo_peer_list;
349 	uint16_t i;
350 
351 	mlo_peer_list = &ml_dev->mlo_peer_list;
352 	ml_peerlist_lock_create(mlo_peer_list);
353 	for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
354 		qdf_list_create(&mlo_peer_list->peer_hash[i],
355 				WLAN_UMAC_PSOC_MAX_PEERS +
356 				WLAN_MAX_PSOC_TEMP_PEERS);
357 
358 	return QDF_STATUS_SUCCESS;
359 }
360 
361 QDF_STATUS mlo_dev_mlpeer_list_deinit(struct wlan_mlo_dev_context *ml_dev)
362 {
363 	uint16_t i;
364 	struct wlan_mlo_peer_list *mlo_peer_list;
365 
366 	/* deinit the lock */
367 	mlo_peer_list = &ml_dev->mlo_peer_list;
368 	ml_peerlist_lock_destroy(mlo_peer_list);
369 	for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
370 		qdf_list_destroy(&mlo_peer_list->peer_hash[i]);
371 
372 	return QDF_STATUS_SUCCESS;
373 }
374