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