xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_aid.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_main.h"
18 #include "qdf_types.h"
19 #include "wlan_cmn.h"
20 #include <include/wlan_vdev_mlme.h>
21 #include "wlan_mlo_mgr_ap.h"
22 #include "wlan_mlo_mgr_cmn.h"
23 
24 static void mlo_peer_set_aid_bit(struct wlan_ml_vdev_aid_mgr *ml_aid_mgr,
25 				 uint16_t assoc_id_ix)
26 {
27 	uint16_t ix;
28 	struct wlan_vdev_aid_mgr *vdev_aid_mgr;
29 
30 	/* Mark this bit as AID assigned */
31 	for (ix = 0; ix < WLAN_UMAC_MLO_MAX_VDEVS; ix++) {
32 		vdev_aid_mgr = ml_aid_mgr->aid_mgr[ix];
33 		if (vdev_aid_mgr)
34 			qdf_set_bit(assoc_id_ix, vdev_aid_mgr->aid_bitmap);
35 	}
36 }
37 
38 static uint16_t wlan_mlo_peer_alloc_aid(
39 		struct wlan_ml_vdev_aid_mgr *ml_aid_mgr,
40 		bool is_mlo_peer,
41 		uint8_t link_ix)
42 {
43 	uint16_t assoc_id = (uint16_t)-1;
44 	uint16_t i, j;
45 	struct wlan_vdev_aid_mgr *vdev_aid_mgr;
46 	uint16_t first_aid = 0;
47 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
48 
49 	if (!mlo_mgr_ctx)
50 		return assoc_id;
51 
52 	if (!is_mlo_peer && link_ix == MLO_INVALID_LINK_IDX)
53 		return assoc_id;
54 	/* TODO check locking strategy */
55 	ml_aid_lock_acquire(mlo_mgr_ctx);
56 
57 	for (i = 0; i < ml_aid_mgr->max_aid; i++) {
58 		if (qdf_test_bit(i, ml_aid_mgr->aid_bitmap))
59 			continue;
60 
61 		if (is_mlo_peer) {
62 			for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) {
63 				vdev_aid_mgr = ml_aid_mgr->aid_mgr[j];
64 				if (vdev_aid_mgr &&
65 				    qdf_test_bit(i, vdev_aid_mgr->aid_bitmap))
66 					break;
67 				/* AID is free */
68 				if (j == WLAN_UMAC_MLO_MAX_VDEVS - 1) {
69 					assoc_id = i + 1;
70 					mlo_peer_set_aid_bit(ml_aid_mgr, i);
71 				}
72 			}
73 
74 			if (assoc_id == i + 1) {
75 				qdf_set_bit(i, ml_aid_mgr->aid_bitmap);
76 				break;
77 			}
78 		} else {
79 			vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix];
80 			if (vdev_aid_mgr)
81 				break;
82 
83 			if (qdf_test_bit(i, vdev_aid_mgr->aid_bitmap))
84 				continue;
85 
86 			if (!first_aid)
87 				first_aid = i + 1;
88 
89 			for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) {
90 				if (j == link_ix)
91 					continue;
92 
93 				vdev_aid_mgr = ml_aid_mgr->aid_mgr[j];
94 				if (vdev_aid_mgr &&
95 				    qdf_test_bit(i, vdev_aid_mgr->aid_bitmap)) {
96 					assoc_id = i + 1;
97 					break;
98 				}
99 			}
100 			if (assoc_id == i + 1) {
101 				vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix];
102 				qdf_set_bit(i, vdev_aid_mgr->aid_bitmap);
103 				first_aid = 0;
104 				break;
105 			}
106 		}
107 	}
108 
109 	if ((!is_mlo_peer) && first_aid) {
110 		vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix];
111 		qdf_set_bit(first_aid, vdev_aid_mgr->aid_bitmap);
112 		assoc_id = first_aid;
113 	}
114 
115 	ml_aid_lock_release(mlo_mgr_ctx);
116 
117 	return assoc_id;
118 }
119 
120 static uint16_t wlan_mlme_peer_alloc_aid(
121 		struct wlan_vdev_aid_mgr *vdev_aid_mgr,
122 		bool no_lock)
123 {
124 	uint16_t assoc_id = (uint16_t)-1;
125 	uint16_t i;
126 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
127 
128 	if (!mlo_mgr_ctx)
129 		return assoc_id;
130 
131 	if (!no_lock)
132 		ml_aid_lock_acquire(mlo_mgr_ctx);
133 
134 	for (i = 0; i < vdev_aid_mgr->max_aid; i++) {
135 		if (qdf_test_bit(i, vdev_aid_mgr->aid_bitmap))
136 			continue;
137 
138 		assoc_id = i + 1;
139 		qdf_set_bit(i, vdev_aid_mgr->aid_bitmap);
140 	}
141 
142 	if (!no_lock)
143 		ml_aid_lock_release(mlo_mgr_ctx);
144 
145 	return assoc_id;
146 }
147 
148 QDF_STATUS wlan_mlo_peer_free_aid(
149 		struct wlan_ml_vdev_aid_mgr *ml_aid_mgr,
150 		uint8_t link_ix,
151 		uint16_t assoc_id)
152 {
153 	uint16_t  j;
154 	struct wlan_vdev_aid_mgr *vdev_aid_mgr;
155 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
156 	uint16_t assoc_id_ix;
157 
158 	if (!mlo_mgr_ctx)
159 		return QDF_STATUS_E_FAILURE;
160 
161 	/* TODO check locking strategy */
162 	ml_aid_lock_acquire(mlo_mgr_ctx);
163 	assoc_id_ix = assoc_id - 1;
164 	if (qdf_test_bit(assoc_id_ix, ml_aid_mgr->aid_bitmap)) {
165 		qdf_clear_bit(assoc_id_ix, ml_aid_mgr->aid_bitmap);
166 		for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) {
167 			vdev_aid_mgr = ml_aid_mgr->aid_mgr[j];
168 			if (vdev_aid_mgr &&
169 			    qdf_test_bit(assoc_id_ix,
170 					 vdev_aid_mgr->aid_bitmap)) {
171 				qdf_clear_bit(assoc_id_ix,
172 					      vdev_aid_mgr->aid_bitmap);
173 			}
174 		}
175 	} else {
176 		vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix];
177 		if (vdev_aid_mgr)
178 			qdf_clear_bit(assoc_id_ix, vdev_aid_mgr->aid_bitmap);
179 	}
180 
181 	ml_aid_lock_release(mlo_mgr_ctx);
182 
183 	return QDF_STATUS_SUCCESS;
184 }
185 
186 void wlan_mlme_peer_free_aid(
187 		struct wlan_vdev_aid_mgr *vdev_aid_mgr,
188 		bool no_lock, uint16_t assoc_id)
189 {
190 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
191 
192 	if (!mlo_mgr_ctx)
193 		return;
194 
195 	if (!no_lock)
196 		ml_aid_lock_acquire(mlo_mgr_ctx);
197 
198 	qdf_clear_bit(assoc_id - 1, vdev_aid_mgr->aid_bitmap);
199 
200 	if (!no_lock)
201 		ml_aid_lock_release(mlo_mgr_ctx);
202 }
203 
204 QDF_STATUS mlo_peer_allocate_aid(
205 		struct wlan_mlo_dev_context *ml_dev,
206 		struct wlan_mlo_peer_context *ml_peer)
207 {
208 	uint16_t assoc_id = (uint16_t)-1;
209 	struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
210 
211 	ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
212 	if (!ml_aid_mgr)
213 		return QDF_STATUS_E_INVAL;
214 
215 	assoc_id = wlan_mlo_peer_alloc_aid(ml_aid_mgr, true, 0xff);
216 	if (assoc_id == (uint16_t)-1)
217 		return QDF_STATUS_E_NOENT;
218 
219 	ml_peer->assoc_id = assoc_id;
220 
221 	return QDF_STATUS_SUCCESS;
222 }
223 
224 QDF_STATUS mlo_peer_free_aid(struct wlan_mlo_dev_context *ml_dev,
225 			     struct wlan_mlo_peer_context *ml_peer)
226 {
227 	struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
228 	QDF_STATUS status = QDF_STATUS_SUCCESS;
229 
230 	ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
231 	if (!ml_aid_mgr)
232 		return QDF_STATUS_E_INVAL;
233 
234 	wlan_mlo_peer_free_aid(ml_aid_mgr, 0xff, ml_peer->assoc_id);
235 
236 	return status;
237 }
238 
239 uint16_t mlo_get_aid(struct wlan_objmgr_vdev *vdev)
240 {
241 	struct wlan_mlo_dev_context *ml_dev;
242 	uint16_t assoc_id = (uint16_t)-1;
243 	struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
244 
245 	ml_dev = vdev->mlo_dev_ctx;
246 
247 	if (!ml_dev)
248 		return assoc_id;
249 
250 	ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
251 	if (!ml_aid_mgr)
252 		return assoc_id;
253 
254 	return wlan_mlo_peer_alloc_aid(ml_aid_mgr, true, 0xff);
255 }
256 
257 QDF_STATUS mlo_free_aid(struct wlan_objmgr_vdev *vdev, uint16_t assoc_id)
258 {
259 	struct wlan_mlo_dev_context *ml_dev;
260 	struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
261 
262 	ml_dev = vdev->mlo_dev_ctx;
263 
264 	if (!ml_dev)
265 		return QDF_STATUS_E_INVAL;
266 
267 	ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
268 	if (!ml_aid_mgr)
269 		return QDF_STATUS_E_INVAL;
270 
271 	return wlan_mlo_peer_free_aid(ml_aid_mgr, true, assoc_id);
272 }
273 
274 uint16_t mlme_get_aid(struct wlan_objmgr_vdev *vdev)
275 {
276 	struct wlan_mlo_dev_context *ml_dev;
277 	uint16_t assoc_id = (uint16_t)-1;
278 	struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
279 	struct wlan_vdev_aid_mgr *vdev_aid_mgr;
280 	bool no_lock = true;
281 	uint8_t link_id;
282 
283 	ml_dev = vdev->mlo_dev_ctx;
284 
285 	if (!ml_dev) {
286 		vdev_aid_mgr = wlan_vdev_mlme_get_aid_mgr(vdev);
287 		if (vdev_aid_mgr) {
288 			if (qdf_atomic_read(&vdev_aid_mgr->ref_cnt) > 1)
289 				no_lock = false;
290 			return wlan_mlme_peer_alloc_aid(vdev_aid_mgr, no_lock);
291 		}
292 		return assoc_id;
293 	}
294 
295 	ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
296 	if (!ml_aid_mgr)
297 		return assoc_id;
298 
299 	link_id = mlo_get_link_vdev_ix(ml_dev, vdev);
300 
301 	assoc_id = wlan_mlo_peer_alloc_aid(ml_aid_mgr, false, link_id);
302 
303 	return assoc_id;
304 }
305 
306 void mlme_free_aid(struct wlan_objmgr_vdev *vdev, uint16_t assoc_id)
307 {
308 	struct wlan_mlo_dev_context *ml_dev;
309 	struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
310 	struct wlan_vdev_aid_mgr *vdev_aid_mgr;
311 	bool no_lock = true;
312 	uint8_t link_id;
313 
314 	ml_dev = vdev->mlo_dev_ctx;
315 
316 	if (!ml_dev) {
317 		vdev_aid_mgr = wlan_vdev_mlme_get_aid_mgr(vdev);
318 		if (vdev_aid_mgr) {
319 			if (qdf_atomic_read(&vdev_aid_mgr->ref_cnt) > 1)
320 				no_lock = false;
321 
322 			wlan_mlme_peer_free_aid(vdev_aid_mgr, no_lock,
323 						assoc_id);
324 		}
325 		return;
326 	}
327 
328 	ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
329 	if (!ml_aid_mgr)
330 		return;
331 
332 	link_id = mlo_get_link_vdev_ix(ml_dev, vdev);
333 
334 	wlan_mlo_peer_free_aid(ml_aid_mgr, link_id, assoc_id);
335 }
336 
337 struct wlan_vdev_aid_mgr *wlan_vdev_aid_mgr_init(uint16_t max_aid)
338 {
339 	struct wlan_vdev_aid_mgr *aid_mgr;
340 
341 	aid_mgr = qdf_mem_malloc(sizeof(struct wlan_vdev_aid_mgr));
342 	if (!aid_mgr)
343 		return NULL;
344 
345 	aid_mgr->max_aid = max_aid;
346 	qdf_atomic_init(&aid_mgr->ref_cnt);
347 	/* Take reference before returning */
348 	qdf_atomic_inc(&aid_mgr->ref_cnt);
349 
350 	return aid_mgr;
351 }
352 
353 void wlan_vdev_aid_mgr_free(struct wlan_vdev_aid_mgr *aid_mgr)
354 {
355 	if (!aid_mgr)
356 		return;
357 
358 	if (!qdf_atomic_dec_and_test(&aid_mgr->ref_cnt))
359 		return;
360 
361 	aid_mgr->max_aid = 0;
362 	qdf_mem_free(aid_mgr);
363 }
364 
365 QDF_STATUS wlan_mlo_vdev_alloc_aid_mgr(struct wlan_mlo_dev_context *ml_dev,
366 				       struct wlan_objmgr_vdev *vdev)
367 {
368 	uint8_t i;
369 	uint8_t is_mbss_enabled = 0;
370 	struct wlan_objmgr_vdev *vdev_iter;
371 	struct wlan_objmgr_vdev *tx_vdev = NULL;
372 	struct wlan_vdev_aid_mgr *aid_mgr;
373 	struct wlan_ml_vdev_aid_mgr *ml_aidmgr;
374 	uint16_t max_aid = WLAN_UMAC_MAX_AID;
375 
376 	if (!ml_dev->ap_ctx) {
377 		mlo_err(" ML AP context is not initialized");
378 		QDF_BUG(0);
379 		return QDF_STATUS_E_NOMEM;
380 	}
381 	ml_aidmgr = ml_dev->ap_ctx->ml_aid_mgr;
382 	if (!ml_aidmgr) {
383 		mlo_err(" ML AID mgr allocation failed");
384 		return QDF_STATUS_E_NOMEM;
385 	}
386 
387 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
388 		vdev_iter = ml_dev->wlan_vdev_list[i];
389 		if (!vdev_iter)
390 			continue;
391 
392 		if (vdev != vdev_iter)
393 			continue;
394 
395 		/* TODO */
396 		/* Get Tx VDEV, if VDEV is MBSSID */
397 		if (is_mbss_enabled) {
398 			aid_mgr = wlan_vdev_mlme_get_aid_mgr(tx_vdev);
399 			if (!aid_mgr) {
400 				mlo_err("AID bitmap allocation failed for Tx VDEV%d",
401 					wlan_vdev_get_id(tx_vdev));
402 				return QDF_STATUS_E_NOMEM;
403 			}
404 			qdf_atomic_inc(&aid_mgr->ref_cnt);
405 			ml_aidmgr->aid_mgr[i] = aid_mgr;
406 			wlan_vdev_mlme_set_aid_mgr(vdev,
407 						   ml_aidmgr->aid_mgr[i]);
408 			break;
409 		} else {
410 			ml_aidmgr->aid_mgr[i] = wlan_vdev_aid_mgr_init(max_aid);
411 			if (!ml_aidmgr->aid_mgr[i]) {
412 				mlo_err("AID bitmap allocation failed for VDEV%d",
413 					wlan_vdev_get_id(vdev));
414 				return QDF_STATUS_E_NOMEM;
415 			}
416 			wlan_vdev_mlme_set_aid_mgr(vdev, ml_aidmgr->aid_mgr[i]);
417 			break;
418 		}
419 	}
420 
421 	return QDF_STATUS_SUCCESS;
422 }
423 
424 QDF_STATUS wlan_mlo_vdev_free_aid_mgr(struct wlan_mlo_dev_context *ml_dev,
425 				      struct wlan_objmgr_vdev *vdev)
426 {
427 	uint8_t i;
428 	struct wlan_objmgr_vdev *vdev_iter;
429 	struct wlan_ml_vdev_aid_mgr *ml_aidmgr;
430 
431 	if (!ml_dev->ap_ctx) {
432 		mlo_err(" ML AP context is not initialized");
433 		QDF_BUG(0);
434 		return QDF_STATUS_E_NOMEM;
435 	}
436 	ml_aidmgr = ml_dev->ap_ctx->ml_aid_mgr;
437 	if (!ml_aidmgr) {
438 		mlo_err(" ML AID mgr allocation failed");
439 		return QDF_STATUS_E_NOMEM;
440 	}
441 
442 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
443 		vdev_iter = ml_dev->wlan_vdev_list[i];
444 		if (!vdev_iter)
445 			continue;
446 
447 		if (vdev != vdev_iter)
448 			continue;
449 
450 		wlan_vdev_aid_mgr_free(ml_aidmgr->aid_mgr[i]);
451 		ml_aidmgr->aid_mgr[i] = NULL;
452 		break;
453 	}
454 
455 	return QDF_STATUS_SUCCESS;
456 }
457 
458 QDF_STATUS wlan_mlo_vdev_aid_mgr_init(struct wlan_mlo_dev_context *ml_dev)
459 {
460 	uint8_t i;
461 	uint8_t is_mbss_enabled = 0;
462 	struct wlan_objmgr_vdev *vdev;
463 	struct wlan_objmgr_vdev *tx_vdev = NULL;
464 	struct wlan_vdev_aid_mgr *aid_mgr;
465 	struct wlan_ml_vdev_aid_mgr *ml_aidmgr;
466 	uint16_t max_aid = WLAN_UMAC_MAX_AID;
467 
468 	ml_aidmgr = qdf_mem_malloc(sizeof(struct wlan_ml_vdev_aid_mgr));
469 	if (!ml_aidmgr) {
470 		ml_dev->ap_ctx->ml_aid_mgr = NULL;
471 		mlo_err(" ML AID mgr allocation failed");
472 		return QDF_STATUS_E_NOMEM;
473 	}
474 
475 	ml_aidmgr->max_aid = max_aid;
476 	ml_dev->ap_ctx->ml_aid_mgr = ml_aidmgr;
477 
478 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
479 		vdev = ml_dev->wlan_vdev_list[i];
480 		if (!vdev)
481 			continue;
482 		/* TODO */
483 		/* Get Tx VDEV, if VDEV is MBSSID */
484 		if (is_mbss_enabled) {
485 			aid_mgr = wlan_vdev_mlme_get_aid_mgr(tx_vdev);
486 			if (!aid_mgr) {
487 				mlo_err("AID bitmap allocation failed for Tx VDEV%d",
488 					wlan_vdev_get_id(tx_vdev));
489 				goto free_ml_aid_mgr;
490 			}
491 
492 			qdf_atomic_inc(&aid_mgr->ref_cnt);
493 			ml_aidmgr->aid_mgr[i] = aid_mgr;
494 		} else {
495 			ml_aidmgr->aid_mgr[i] = wlan_vdev_aid_mgr_init(max_aid);
496 			if (!ml_aidmgr->aid_mgr[i]) {
497 				mlo_err("AID bitmap allocation failed for VDEV%d",
498 					wlan_vdev_get_id(vdev));
499 				goto free_ml_aid_mgr;
500 			}
501 			wlan_vdev_mlme_set_aid_mgr(vdev,
502 						   ml_aidmgr->aid_mgr[i]);
503 		}
504 	}
505 
506 	return QDF_STATUS_SUCCESS;
507 
508 free_ml_aid_mgr:
509 	wlan_mlo_vdev_aid_mgr_deinit(ml_dev);
510 
511 	return QDF_STATUS_E_NOMEM;
512 }
513 
514 void wlan_mlo_vdev_aid_mgr_deinit(struct wlan_mlo_dev_context *ml_dev)
515 {
516 	uint8_t i;
517 	struct wlan_ml_vdev_aid_mgr *ml_aid_mgr;
518 	int32_t n;
519 
520 	ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr;
521 	if (!ml_aid_mgr)
522 		return;
523 
524 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
525 		if (!ml_dev->wlan_vdev_list[i])
526 			continue;
527 
528 		if (ml_aid_mgr->aid_mgr[i]) {
529 			n = qdf_atomic_read(&ml_aid_mgr->aid_mgr[i]->ref_cnt);
530 			mlo_info("Vdev ID %d, AID mgr ref cnt %d",
531 				 wlan_vdev_get_id(ml_dev->wlan_vdev_list[i]),
532 				 n);
533 		} else {
534 			mlo_err("Vdev ID %d, doesn't have associated AID mgr",
535 				wlan_vdev_get_id(ml_dev->wlan_vdev_list[i]));
536 			continue;
537 		}
538 		wlan_vdev_aid_mgr_free(ml_aid_mgr->aid_mgr[i]);
539 		ml_aid_mgr->aid_mgr[i] = NULL;
540 	}
541 
542 	qdf_mem_free(ml_aid_mgr);
543 	ml_dev->ap_ctx->ml_aid_mgr = NULL;
544 }
545