1 /*
2 * Copyright (c) 2011-2016, 2018-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 *
22 * This file lim_aid_mgmt.c contains the functions related to
23 * AID pool management like initialization, assignment etc.
24 * Author: Chandra Modumudi
25 * Date: 03/20/02
26 * History:-
27 * Date Modified by Modification Information
28 * --------------------------------------------------------------------
29 */
30
31 #include "cds_api.h"
32 #include "wni_cfg.h"
33 #include "ani_global.h"
34 #include "sir_params.h"
35 #include "lim_utils.h"
36 #include "lim_timer_utils.h"
37 #include "lim_ft_defs.h"
38 #include "lim_session.h"
39 #include "lim_session_utils.h"
40 #include <wlan_mlo_mgr_ap.h>
41 #include <wlan_mlo_mgr_peer.h>
42
43 #define LIM_START_PEER_IDX 1
44
45 /**
46 * lim_init_peer_idxpool_legacy() - init aid pool for non MLO SAP
47 * @mac: Pointer to Global MAC structure
48 * @pe_session: pe session
49 *
50 * Return: Void
51 */
lim_init_peer_idxpool_legacy(struct mac_context * mac,struct pe_session * pe_session)52 static void lim_init_peer_idxpool_legacy(struct mac_context *mac,
53 struct pe_session *pe_session)
54 {
55 uint8_t i;
56 uint8_t max_assoc_sta = mac->lim.max_sta_of_pe_session;
57
58 pe_session->gpLimPeerIdxpool[0] = 0;
59
60 #ifdef FEATURE_WLAN_TDLS
61 /*
62 * In station role, DPH_STA_HASH_INDEX_PEER (index 1) is reserved
63 * for peer station index corresponding to AP. Avoid choosing that index
64 * and get index starting from (DPH_STA_HASH_INDEX_PEER + 1)
65 * (index 2) for TDLS stations;
66 */
67 if (LIM_IS_STA_ROLE(pe_session)) {
68 pe_session->freePeerIdxHead = DPH_STA_HASH_INDEX_PEER + 1;
69 } else
70 #endif
71 {
72 pe_session->freePeerIdxHead = LIM_START_PEER_IDX;
73 }
74
75 for (i = pe_session->freePeerIdxHead; i < max_assoc_sta; i++)
76 pe_session->gpLimPeerIdxpool[i] = i + 1;
77
78 pe_session->gpLimPeerIdxpool[i] = 0;
79
80 pe_session->freePeerIdxTail = i;
81 }
82
lim_init_peer_idxpool(struct mac_context * mac,struct pe_session * pe_session)83 void lim_init_peer_idxpool(struct mac_context *mac,
84 struct pe_session *pe_session)
85 {
86 if (!wlan_vdev_mlme_is_mlo_ap(pe_session->vdev))
87 lim_init_peer_idxpool_legacy(mac, pe_session);
88 }
89
90 /**
91 * lim_create_peer_idxpool_legacy() - AID pool creation for non-MLO AP
92 * @pe_session: pe session
93 * @idx_pool_size: aid pool size
94 *
95 * Return: true if pool is created successfully
96 */
lim_create_peer_idxpool_legacy(struct pe_session * pe_session,uint8_t idx_pool_size)97 static bool lim_create_peer_idxpool_legacy(struct pe_session *pe_session,
98 uint8_t idx_pool_size)
99 {
100 pe_session->gpLimPeerIdxpool = qdf_mem_malloc(
101 sizeof(*pe_session->gpLimPeerIdxpool) * idx_pool_size);
102 if (!pe_session->gpLimPeerIdxpool)
103 return false;
104
105 pe_session->freePeerIdxHead = 0;
106 pe_session->freePeerIdxTail = 0;
107
108 return true;
109 }
110
lim_create_peer_idxpool(struct pe_session * pe_session,uint8_t idx_pool_size)111 bool lim_create_peer_idxpool(struct pe_session *pe_session,
112 uint8_t idx_pool_size)
113 {
114 pe_session->gLimNumOfCurrentSTAs = 0;
115 if (!wlan_vdev_mlme_is_mlo_ap(pe_session->vdev))
116 return lim_create_peer_idxpool_legacy(pe_session,
117 idx_pool_size);
118
119 return true;
120 }
121
122 /**
123 * lim_free_peer_idxpool_legacy() - Free the non-MLO AP aid pool
124 * @pe_session: pe session
125 *
126 * Return: Void
127 */
lim_free_peer_idxpool_legacy(struct pe_session * pe_session)128 static void lim_free_peer_idxpool_legacy(struct pe_session *pe_session)
129 {
130 if (pe_session->gpLimPeerIdxpool) {
131 qdf_mem_free(pe_session->gpLimPeerIdxpool);
132 pe_session->gpLimPeerIdxpool = NULL;
133 }
134 }
135
lim_free_peer_idxpool(struct pe_session * pe_session)136 void lim_free_peer_idxpool(struct pe_session *pe_session)
137 {
138 if (!pe_session->vdev) {
139 pe_debug("vdev is null");
140 return;
141 }
142 if (!wlan_vdev_mlme_is_mlo_ap(pe_session->vdev))
143 lim_free_peer_idxpool_legacy(pe_session);
144 }
145
146 /**
147 * lim_assign_peer_idx_mlo() - trigger mlo api to allocate an AID for a STA
148 * @pe_session: pe session
149 *
150 * Return: peer_idx - assigned AID for STA
151 */
152 #ifdef WLAN_FEATURE_11BE_MLO
lim_assign_peer_idx_mlo(struct pe_session * pe_session)153 static uint16_t lim_assign_peer_idx_mlo(struct pe_session *pe_session)
154 {
155 return mlme_get_aid(pe_session->vdev);
156 }
157 #else
lim_assign_peer_idx_mlo(struct pe_session * pe_session)158 static uint16_t lim_assign_peer_idx_mlo(struct pe_session *pe_session)
159 {
160 return 0; /* no more free peer index */
161 }
162 #endif
163
164 /**
165 * lim_assign_peer_idx_legacy() - non-MLO AP allocates an AID for a STA
166 * @mac: Pointer to Global MAC structure
167 * @pe_session: pe session
168 *
169 * Return: peer_idx - assigned AID for STA
170 */
lim_assign_peer_idx_legacy(struct mac_context * mac,struct pe_session * pe_session)171 static uint16_t lim_assign_peer_idx_legacy(struct mac_context *mac,
172 struct pe_session *pe_session)
173 {
174 uint16_t peer_id;
175
176 /* return head of free list */
177
178 if (pe_session->freePeerIdxHead) {
179 peer_id = pe_session->freePeerIdxHead;
180 pe_session->freePeerIdxHead =
181 pe_session->gpLimPeerIdxpool[pe_session->freePeerIdxHead];
182 if (pe_session->freePeerIdxHead == 0)
183 pe_session->freePeerIdxTail = 0;
184 return peer_id;
185 }
186
187 return 0; /* no more free peer index */
188 }
189
190 /**
191 * lim_assign_peer_idx()
192 *
193 ***FUNCTION:
194 * This function is called to get a peer station index. This index is
195 * used during Association/Reassociation
196 * frame handling to assign association ID (aid) to a STA.
197 * In case of TDLS, this is used to assign a index into the Dph hash entry.
198 *
199 ***LOGIC:
200 *
201 ***ASSUMPTIONS:
202 * NA
203 *
204 ***NOTE:
205 *
206 * @param mac - Pointer to Global MAC structure
207 * @return peerIdx - assigned peer Station IDx for STA
208 */
209
lim_assign_peer_idx(struct mac_context * mac,struct pe_session * pe_session)210 uint16_t lim_assign_peer_idx(struct mac_context *mac,
211 struct pe_session *pe_session)
212 {
213 uint16_t peer_id;
214
215 /* make sure we haven't exceeded the configurable limit on associations */
216 /* This count is global to ensure that it doesn't exceed the hardware limits. */
217 if (pe_get_current_stas_count(mac) >=
218 mac->mlme_cfg->sap_cfg.assoc_sta_limit) {
219 /* too many associations already active */
220 return 0;
221 }
222
223 if (wlan_vdev_mlme_is_mlo_ap(pe_session->vdev))
224 peer_id = lim_assign_peer_idx_mlo(pe_session);
225 else
226 peer_id = lim_assign_peer_idx_legacy(mac, pe_session);
227
228 if (peer_id)
229 pe_session->gLimNumOfCurrentSTAs++;
230
231 return peer_id;
232 }
233
234 #ifdef WLAN_FEATURE_11BE_MLO
lim_assign_mlo_conn_idx(struct mac_context * mac,struct pe_session * pe_session,uint16_t partner_peer_idx)235 uint16_t lim_assign_mlo_conn_idx(struct mac_context *mac,
236 struct pe_session *pe_session,
237 uint16_t partner_peer_idx)
238 {
239 uint16_t peer_id;
240
241 if (pe_get_current_stas_count(mac) >=
242 mac->mlme_cfg->sap_cfg.assoc_sta_limit) {
243 /* too many associations already active */
244 return 0;
245 }
246
247 if (partner_peer_idx)
248 peer_id = partner_peer_idx;
249 else
250 peer_id = mlo_get_aid(pe_session->vdev);
251
252 if (peer_id)
253 pe_session->gLimNumOfCurrentSTAs++;
254
255 return peer_id;
256 }
257
258 /**
259 * lim_release_peer_idx_mlo() - trigger mlo api to release aid
260 * @peer_idx: aid to free
261 * @pe_session: pe session
262 *
263 * Return: Void
264 */
lim_release_peer_idx_mlo(uint16_t peer_idx,struct pe_session * pe_session)265 static void lim_release_peer_idx_mlo(uint16_t peer_idx,
266 struct pe_session *pe_session)
267 {
268 return mlme_free_aid(pe_session->vdev, peer_idx);
269 }
270 #else
lim_release_peer_idx_mlo(uint16_t peer_idx,struct pe_session * pe_session)271 static void lim_release_peer_idx_mlo(uint16_t peer_idx,
272 struct pe_session *pe_session)
273 {
274 }
275 #endif
276
277 /**
278 * lim_release_peer_idx_legacy() - non-MLO AP releases an AID
279 * @mac: Pointer to Global MAC structure
280 * @peer_idx: aid to free
281 * @pe_session: pe session
282 *
283 * Return: Void
284 */
lim_release_peer_idx_legacy(struct mac_context * mac,uint16_t peer_idx,struct pe_session * pe_session)285 static void lim_release_peer_idx_legacy(struct mac_context *mac,
286 uint16_t peer_idx,
287 struct pe_session *pe_session)
288 {
289 /* insert at tail of free list */
290 if (pe_session->freePeerIdxTail) {
291 pe_session->gpLimPeerIdxpool[pe_session->freePeerIdxTail] =
292 (uint8_t)peer_idx;
293 pe_session->freePeerIdxTail = (uint8_t)peer_idx;
294 } else {
295 pe_session->freePeerIdxTail =
296 pe_session->freePeerIdxHead = (uint8_t)peer_idx;
297 }
298 pe_session->gpLimPeerIdxpool[(uint8_t)peer_idx] = 0;
299 }
300
301 /**
302 * lim_release_peer_idx()
303 *
304 ***FUNCTION:
305 * This function is called when a STA context is removed
306 * at AP (or TDLS) to return peer Index
307 * to free pool.
308 *
309 ***LOGIC:
310 *
311 ***ASSUMPTIONS:
312 * NA
313 *
314 ***NOTE:
315 *
316 * @param mac - Pointer to Global MAC structure
317 * @param peerIdx - peer station index that need to return to free pool
318 *
319 * @return None
320 */
321
322 void
lim_release_peer_idx(struct mac_context * mac,uint16_t peer_idx,struct pe_session * pe_session)323 lim_release_peer_idx(struct mac_context *mac, uint16_t peer_idx,
324 struct pe_session *pe_session)
325 {
326 pe_session->gLimNumOfCurrentSTAs--;
327
328 if (wlan_vdev_mlme_is_mlo_ap(pe_session->vdev))
329 lim_release_peer_idx_mlo(peer_idx, pe_session);
330 else
331 lim_release_peer_idx_legacy(mac, peer_idx, pe_session);
332 }
333
334 #ifdef WLAN_FEATURE_11BE_MLO
335 void
lim_release_mlo_conn_idx(struct mac_context * mac,uint16_t peer_idx,struct pe_session * session,bool free_aid)336 lim_release_mlo_conn_idx(struct mac_context *mac, uint16_t peer_idx,
337 struct pe_session *session, bool free_aid)
338 {
339 session->gLimNumOfCurrentSTAs--;
340 if (free_aid &&
341 wlan_mlo_get_mlpeer_by_aid(session->vdev->mlo_dev_ctx, peer_idx))
342 mlo_free_aid(session->vdev, peer_idx);
343 }
344 #endif
345