xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_peer_list.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021 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 link_mac_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 				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 link_mac_search *link_mac_arg = (struct link_mac_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 wlan_find_mlpeer_aid(struct wlan_mlo_dev_context *ml_dev,
180 				       void *iter_ml_peer,
181 				       void *arg)
182 {
183 	struct aid_search *aid_arg = (struct aid_search *)arg;
184 	struct wlan_mlo_peer_context *ml_peer;
185 
186 	ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer;
187 
188 	if (aid_arg->aid == ml_peer->assoc_id) {
189 		aid_arg->ml_peer = ml_peer;
190 		return QDF_STATUS_SUCCESS;
191 	}
192 
193 	return QDF_STATUS_E_NOENT;
194 }
195 
196 static QDF_STATUS
197 wlan_find_mlpeer_ml_peerid(struct wlan_mlo_dev_context *ml_dev,
198 			   void *iter_ml_peer,
199 			   void *arg)
200 {
201 	struct mlpeerid_search *mlpeer_id_arg = (struct mlpeerid_search *)arg;
202 	struct wlan_mlo_peer_context *ml_peer;
203 
204 	ml_peer = (struct wlan_mlo_peer_context *)iter_ml_peer;
205 
206 	if (mlpeer_id_arg->ml_peerid == ml_peer->mlo_peer_id) {
207 		mlpeer_id_arg->ml_peer = ml_peer;
208 		return QDF_STATUS_SUCCESS;
209 	}
210 
211 	return QDF_STATUS_E_NOENT;
212 }
213 
214 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_linkmac(
215 				struct wlan_mlo_dev_context *ml_dev,
216 				struct qdf_mac_addr *link_mac)
217 {
218 	struct link_mac_search link_mac_arg;
219 	QDF_STATUS status;
220 
221 	mlo_debug("MLD ID %d ML Peer search with link mac " QDF_MAC_ADDR_FMT,
222 		  ml_dev->mld_id, QDF_MAC_ADDR_REF(link_mac->bytes));
223 	qdf_copy_macaddr(&link_mac_arg.mac_addr, link_mac);
224 	status = wlan_mlo_iterate_ml_peerlist(ml_dev,
225 					      wlan_find_mlpeer_link_mac_addr,
226 					      &link_mac_arg);
227 	if (status == QDF_STATUS_SUCCESS)
228 		return link_mac_arg.ml_peer;
229 
230 	/* TODO: Take ref */
231 
232 	return NULL;
233 }
234 
235 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_aid(
236 				struct wlan_mlo_dev_context *ml_dev,
237 				uint16_t assoc_id)
238 {
239 	struct aid_search aid_arg;
240 	QDF_STATUS status;
241 
242 	aid_arg.aid = assoc_id;
243 	status = wlan_mlo_iterate_ml_peerlist(ml_dev,
244 					      wlan_find_mlpeer_aid,
245 					      &aid_arg);
246 	if (status == QDF_STATUS_SUCCESS)
247 		return aid_arg.ml_peer;
248 
249 	/* TODO: Take ref */
250 
251 	return NULL;
252 }
253 
254 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer_by_ml_peerid(
255 				struct wlan_mlo_dev_context *ml_dev,
256 				uint16_t ml_peerid)
257 {
258 	struct mlpeerid_search peerid_arg;
259 	QDF_STATUS status;
260 
261 	peerid_arg.ml_peerid = ml_peerid;
262 	status = wlan_mlo_iterate_ml_peerlist(ml_dev,
263 					      wlan_find_mlpeer_ml_peerid,
264 					      &peerid_arg);
265 	if (status == QDF_STATUS_SUCCESS)
266 		return peerid_arg.ml_peer;
267 
268 	/* TODO: Take ref */
269 
270 	return NULL;
271 }
272 
273 struct wlan_mlo_peer_context *wlan_mlo_get_mlpeer(
274 				struct wlan_mlo_dev_context *ml_dev,
275 				struct qdf_mac_addr *ml_addr)
276 {
277 	struct wlan_mlo_peer_context *ml_peer;
278 	struct wlan_mlo_peer_list *mlo_peer_list;
279 
280 	mlo_debug("MLD ID %d ML Peer search mac " QDF_MAC_ADDR_FMT,
281 		  ml_dev->mld_id, QDF_MAC_ADDR_REF(ml_addr->bytes));
282 	mlo_peer_list = &ml_dev->mlo_peer_list;
283 	ml_peerlist_lock_acquire(mlo_peer_list);
284 	ml_peer = mlo_get_mlpeer(ml_dev, ml_addr);
285 	if (!ml_peer) {
286 		ml_peerlist_lock_release(mlo_peer_list);
287 		return NULL;
288 	}
289 	/* TODO: Take ref */
290 
291 	ml_peerlist_lock_release(mlo_peer_list);
292 	return ml_peer;
293 }
294 
295 static void wlan_mlo_peerlist_add_tail(qdf_list_t *obj_list,
296 				       struct wlan_mlo_peer_context *obj)
297 {
298 	qdf_list_insert_back(obj_list, &obj->peer_node);
299 }
300 
301 static QDF_STATUS wlan_mlo_peerlist_remove_mlpeer(
302 				qdf_list_t *obj_list,
303 				struct wlan_mlo_peer_context *ml_peer)
304 {
305 	qdf_list_node_t *peer_node = NULL;
306 
307 	if (!ml_peer)
308 		return QDF_STATUS_E_FAILURE;
309 	/* get vdev list node element */
310 	peer_node = &ml_peer->peer_node;
311 	/* list is empty, return failure */
312 	if (qdf_list_remove_node(obj_list, peer_node) != QDF_STATUS_SUCCESS)
313 		return QDF_STATUS_E_FAILURE;
314 
315 	return QDF_STATUS_SUCCESS;
316 }
317 
318 QDF_STATUS mlo_dev_mlpeer_attach(struct wlan_mlo_dev_context *ml_dev,
319 				 struct wlan_mlo_peer_context *ml_peer)
320 {
321 	uint8_t hash_index;
322 	struct wlan_mlo_peer_list *mlo_peer_list;
323 
324 	mlo_peer_list = &ml_dev->mlo_peer_list;
325 	ml_peerlist_lock_acquire(mlo_peer_list);
326 	if (mlo_get_mlpeer(ml_dev, &ml_peer->peer_mld_addr)) {
327 		ml_peerlist_lock_release(mlo_peer_list);
328 		mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT,
329 			ml_dev->mld_id,
330 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
331 		return QDF_STATUS_E_EXISTS;
332 	}
333 
334 	hash_index = WLAN_PEER_HASH(ml_peer->peer_mld_addr.bytes);
335 	wlan_mlo_peerlist_add_tail(&mlo_peer_list->peer_hash[hash_index],
336 				   ml_peer);
337 	ml_peerlist_lock_release(mlo_peer_list);
338 
339 	mlo_debug("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is attached",
340 		  ml_dev->mld_id,
341 		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
342 
343 	return QDF_STATUS_SUCCESS;
344 }
345 
346 QDF_STATUS mlo_dev_mlpeer_detach(struct wlan_mlo_dev_context *ml_dev,
347 				 struct wlan_mlo_peer_context *ml_peer)
348 {
349 	uint8_t hash_index;
350 	QDF_STATUS status;
351 	struct wlan_mlo_peer_list *mlo_peer_list;
352 
353 	mlo_peer_list = &ml_dev->mlo_peer_list;
354 	ml_peerlist_lock_acquire(mlo_peer_list);
355 	hash_index = WLAN_PEER_HASH(ml_peer->peer_mld_addr.bytes);
356 	status = wlan_mlo_peerlist_remove_mlpeer(
357 					&mlo_peer_list->peer_hash[hash_index],
358 					ml_peer);
359 	ml_peerlist_lock_release(mlo_peer_list);
360 
361 	mlo_debug("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is detached",
362 		  ml_dev->mld_id,
363 		  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
364 
365 	return status;
366 }
367 
368 QDF_STATUS mlo_dev_mlpeer_list_init(struct wlan_mlo_dev_context *ml_dev)
369 {
370 	struct wlan_mlo_peer_list *mlo_peer_list;
371 	uint16_t i;
372 
373 	mlo_peer_list = &ml_dev->mlo_peer_list;
374 	ml_peerlist_lock_create(mlo_peer_list);
375 	for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
376 		qdf_list_create(&mlo_peer_list->peer_hash[i],
377 				WLAN_UMAC_PSOC_MAX_PEERS +
378 				WLAN_MAX_PSOC_TEMP_PEERS);
379 
380 	return QDF_STATUS_SUCCESS;
381 }
382 
383 QDF_STATUS mlo_dev_mlpeer_list_deinit(struct wlan_mlo_dev_context *ml_dev)
384 {
385 	uint16_t i;
386 	struct wlan_mlo_peer_list *mlo_peer_list;
387 
388 	/* deinit the lock */
389 	mlo_peer_list = &ml_dev->mlo_peer_list;
390 	ml_peerlist_lock_destroy(mlo_peer_list);
391 	for (i = 0; i < WLAN_PEER_HASHSIZE; i++)
392 		qdf_list_destroy(&mlo_peer_list->peer_hash[i]);
393 
394 	return QDF_STATUS_SUCCESS;
395 }
396