1 /*
2 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. 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 /*
18 * DOC: contains TID to Link mapping related functionality
19 */
20 #include <wlan_cmn.h>
21 #include <wlan_cm_public_struct.h>
22 #include "wlan_t2lm_api.h"
23 #include <wlan_mlo_t2lm.h>
24 #include "wlan_cm_api.h"
25 #include "wlan_mlo_mgr_roam.h"
26 #include "wlan_connectivity_logging.h"
27
28 #define T2LM_MIN_DIALOG_TOKEN 1
29 #define T2LM_MAX_DIALOG_TOKEN 0xFF
30
31 static
t2lm_get_event_str(enum wlan_t2lm_evt event)32 const char *t2lm_get_event_str(enum wlan_t2lm_evt event)
33 {
34 if (event > WLAN_T2LM_EV_ACTION_FRAME_MAX)
35 return "";
36
37 switch (event) {
38 CASE_RETURN_STRING(WLAN_T2LM_EV_ACTION_FRAME_RX_REQ);
39 CASE_RETURN_STRING(WLAN_T2LM_EV_ACTION_FRAME_TX_RESP);
40 CASE_RETURN_STRING(WLAN_T2LM_EV_ACTION_FRAME_TX_REQ);
41 CASE_RETURN_STRING(WLAN_T2LM_EV_ACTION_FRAME_RX_RESP);
42 CASE_RETURN_STRING(WLAN_T2LM_EV_ACTION_FRAME_RX_TEARDOWN);
43 CASE_RETURN_STRING(WLAN_T2LM_EV_ACTION_FRAME_TX_TEARDOWN);
44 default:
45 return "Unknown";
46 }
47 }
48
49 static
t2lm_get_connected_link_id(struct wlan_objmgr_vdev * vdev)50 uint16_t t2lm_get_connected_link_id(struct wlan_objmgr_vdev *vdev)
51 {
52 uint16_t ieee_link_mask = 0;
53 uint8_t i, link_id;
54 struct mlo_link_info *link_info = NULL;
55
56 if (!vdev->mlo_dev_ctx) {
57 t2lm_err("MLO dev context failed");
58 return false;
59 }
60
61 link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[0];
62
63 for (i = 0; i < WLAN_MAX_ML_BSS_LINKS; i++) {
64 link_id = link_info[i].link_id;
65 if (link_id == WLAN_INVALID_LINK_ID)
66 continue;
67
68 ieee_link_mask |= BIT(link_id);
69 }
70
71 return ieee_link_mask;
72 }
73
74 static
t2lm_is_valid_t2lm_link_map(struct wlan_objmgr_vdev * vdev,struct wlan_t2lm_onging_negotiation_info * t2lm,enum wlan_t2lm_direction * valid_dir)75 bool t2lm_is_valid_t2lm_link_map(struct wlan_objmgr_vdev *vdev,
76 struct wlan_t2lm_onging_negotiation_info *t2lm,
77 enum wlan_t2lm_direction *valid_dir)
78 {
79 uint8_t i, tid = 0;
80 enum wlan_t2lm_direction dir = WLAN_T2LM_INVALID_DIRECTION;
81 uint16_t ieee_link_mask = 0;
82 uint16_t provisioned_links = 0;
83 bool is_valid_link_mask = false;
84
85 ieee_link_mask = t2lm_get_connected_link_id(vdev);
86
87 /* Check if the configured hw_link_id map is valid */
88 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) {
89 if (t2lm->t2lm_info[dir].direction ==
90 WLAN_T2LM_INVALID_DIRECTION)
91 continue;
92
93 if (t2lm->t2lm_info[dir].default_link_mapping &&
94 t2lm->t2lm_info[dir].direction == WLAN_T2LM_BIDI_DIRECTION) {
95 is_valid_link_mask = true;
96 *valid_dir = dir;
97 continue;
98 }
99
100 for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
101 provisioned_links =
102 t2lm->t2lm_info[dir].ieee_link_map_tid[tid];
103
104 for (i = 0; i < WLAN_T2LM_MAX_NUM_LINKS; i++) {
105 if (!(provisioned_links & BIT(i)))
106 continue;
107
108 if (ieee_link_mask & BIT(i)) {
109 is_valid_link_mask = true;
110 *valid_dir = dir;
111 continue;
112 } else {
113 return false;
114 }
115 }
116 }
117 }
118
119 return is_valid_link_mask;
120 }
121
122 static uint8_t
t2lm_gen_dialog_token(struct wlan_mlo_peer_t2lm_policy * t2lm_policy)123 t2lm_gen_dialog_token(struct wlan_mlo_peer_t2lm_policy *t2lm_policy)
124 {
125 if (!t2lm_policy)
126 return 0;
127
128 if (t2lm_policy->self_gen_dialog_token == T2LM_MAX_DIALOG_TOKEN)
129 /* wrap is ok */
130 t2lm_policy->self_gen_dialog_token = T2LM_MIN_DIALOG_TOKEN;
131 else
132 t2lm_policy->self_gen_dialog_token += 1;
133
134 t2lm_debug("gen dialog token %d", t2lm_policy->self_gen_dialog_token);
135 return t2lm_policy->self_gen_dialog_token;
136 }
137
t2lm_handle_rx_req(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,void * event_data,uint32_t frame_len,uint8_t * token)138 QDF_STATUS t2lm_handle_rx_req(struct wlan_objmgr_vdev *vdev,
139 struct wlan_objmgr_peer *peer,
140 void *event_data, uint32_t frame_len,
141 uint8_t *token)
142 {
143 struct wlan_t2lm_onging_negotiation_info t2lm_req = {0};
144 struct wlan_t2lm_info *t2lm_info;
145 enum wlan_t2lm_direction dir = WLAN_T2LM_MAX_DIRECTION;
146 bool valid_map = false;
147 QDF_STATUS status;
148 struct wlan_mlo_peer_context *ml_peer;
149 struct wlan_objmgr_psoc *psoc;
150
151 if (!vdev)
152 return QDF_STATUS_E_NULL_VALUE;
153
154 psoc = wlan_vdev_get_psoc(vdev);
155 if (!psoc)
156 return QDF_STATUS_E_NULL_VALUE;
157
158 if (!wlan_mlme_get_t2lm_negotiation_supported(psoc)) {
159 mlme_rl_debug("T2LM negotiation not supported");
160 return QDF_STATUS_E_NOSUPPORT;
161 }
162
163 ml_peer = peer->mlo_peer_ctx;
164 if (!ml_peer)
165 return QDF_STATUS_E_FAILURE;
166
167 status = wlan_mlo_parse_t2lm_action_frame(&t2lm_req, event_data,
168 frame_len,
169 WLAN_T2LM_CATEGORY_REQUEST);
170 if (status != QDF_STATUS_SUCCESS) {
171 mlme_err("Unable to parse T2LM request action frame");
172 return QDF_STATUS_E_FAILURE;
173 }
174
175 /*
176 * Check if ML vdevs are connected and link id matches with T2LM
177 * negotiation action request link id
178 */
179 valid_map = t2lm_is_valid_t2lm_link_map(vdev, &t2lm_req, &dir);
180 if (valid_map) {
181 mlme_debug("Link match found,accept t2lm conf");
182 status = QDF_STATUS_SUCCESS;
183 } else {
184 status = QDF_STATUS_E_FAILURE;
185 mlme_err("reject t2lm conf");
186 }
187
188 if (dir >= WLAN_T2LM_MAX_DIRECTION) {
189 mlme_err("Received T2LM IE has invalid direction");
190 status = QDF_STATUS_E_INVAL;
191 }
192
193 if (QDF_IS_STATUS_SUCCESS(status) &&
194 t2lm_req.t2lm_info[dir].direction != WLAN_T2LM_INVALID_DIRECTION) {
195 wlan_t2lm_clear_peer_negotiation(peer);
196 /* Apply T2LM config to peer T2LM ctx */
197 t2lm_info = &ml_peer->t2lm_policy.t2lm_negotiated_info.t2lm_info[dir];
198 qdf_mem_copy(t2lm_info, &t2lm_req.t2lm_info[dir],
199 sizeof(struct wlan_t2lm_info));
200 }
201
202 *token = t2lm_req.dialog_token;
203 wlan_connectivity_t2lm_req_resp_event(
204 vdev, *token, 0, 0,
205 wlan_vdev_mlme_get_bss_chan(vdev)->ch_freq,
206 true, WLAN_CONN_DIAG_MLO_T2LM_REQ_EVENT);
207
208 return status;
209 }
210
t2lm_handle_tx_resp(struct wlan_objmgr_vdev * vdev,void * event_data,uint8_t * token)211 QDF_STATUS t2lm_handle_tx_resp(struct wlan_objmgr_vdev *vdev,
212 void *event_data, uint8_t *token)
213 {
214 return QDF_STATUS_SUCCESS;
215 }
216
t2lm_handle_tx_req(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,void * event_data,uint8_t * token)217 QDF_STATUS t2lm_handle_tx_req(struct wlan_objmgr_vdev *vdev,
218 struct wlan_objmgr_peer *peer,
219 void *event_data, uint8_t *token)
220 {
221 struct wlan_t2lm_onging_negotiation_info *t2lm_neg;
222 struct wlan_action_frame_args args;
223 QDF_STATUS status;
224
225 if (!vdev)
226 return QDF_STATUS_E_NULL_VALUE;
227
228 if (!event_data) {
229 t2lm_err("Null event data ptr");
230 return QDF_STATUS_E_NULL_VALUE;
231 }
232
233 t2lm_neg = (struct wlan_t2lm_onging_negotiation_info *)event_data;
234 args.category = ACTION_CATEGORY_PROTECTED_EHT;
235 args.action = EHT_T2LM_REQUEST;
236 args.arg1 = *token;
237
238 status = lim_send_t2lm_action_req_frame(vdev,
239 wlan_peer_get_macaddr(peer),
240 &args, t2lm_neg,
241 *token);
242
243 if (QDF_IS_STATUS_ERROR(status)) {
244 t2lm_err("Failed to send T2LM action request frame");
245 } else {
246 t2lm_debug("Copy the ongoing neg to peer");
247 qdf_mem_copy(&peer->mlo_peer_ctx->t2lm_policy.ongoing_tid_to_link_mapping,
248 t2lm_neg, sizeof(struct wlan_t2lm_onging_negotiation_info));
249 }
250
251 return status;
252 }
253
t2lm_handle_rx_resp(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,void * event_data,uint32_t frame_len,uint8_t * token)254 QDF_STATUS t2lm_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
255 struct wlan_objmgr_peer *peer,
256 void *event_data, uint32_t frame_len,
257 uint8_t *token)
258 {
259 struct wlan_t2lm_onging_negotiation_info t2lm_rsp = {0};
260 struct wlan_t2lm_onging_negotiation_info *t2lm_req;
261 QDF_STATUS status;
262 struct wlan_mlo_peer_context *ml_peer;
263 struct wlan_t2lm_info *t2lm_info;
264 uint8_t dir;
265 struct wlan_channel *channel;
266
267 if (!peer) {
268 t2lm_err("peer is null");
269 return QDF_STATUS_E_NULL_VALUE;
270 }
271
272 ml_peer = peer->mlo_peer_ctx;
273 if (!ml_peer) {
274 t2lm_err("ml peer is null");
275 return QDF_STATUS_E_NULL_VALUE;
276 }
277
278 /* ignore the frame if all links are not connected */
279 if (!mlo_check_if_all_links_up(vdev))
280 return QDF_STATUS_SUCCESS;
281
282 status = wlan_mlo_parse_t2lm_action_frame(&t2lm_rsp, event_data,
283 frame_len,
284 WLAN_T2LM_CATEGORY_RESPONSE);
285 if (status != QDF_STATUS_SUCCESS) {
286 mlme_err("Unable to parse T2LM request action frame");
287 return QDF_STATUS_E_FAILURE;
288 }
289
290 mlme_debug("t2lm rsp dialog token %d", t2lm_rsp.dialog_token);
291 mlme_debug("t2lm rsp is %d", t2lm_rsp.t2lm_resp_type);
292 t2lm_req = &ml_peer->t2lm_policy.ongoing_tid_to_link_mapping;
293 if (!t2lm_req) {
294 t2lm_err("Ongoing tid neg is null");
295 return QDF_STATUS_E_FAILURE;
296 }
297
298 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) {
299 t2lm_info = &t2lm_req->t2lm_info[dir];
300 if (t2lm_info &&
301 t2lm_info->direction != WLAN_T2LM_INVALID_DIRECTION) {
302 if (t2lm_rsp.dialog_token == t2lm_req->dialog_token &&
303 t2lm_rsp.t2lm_resp_type == WLAN_T2LM_RESP_TYPE_SUCCESS) {
304 status = wlan_send_tid_to_link_mapping(vdev,
305 t2lm_info);
306 if (QDF_IS_STATUS_ERROR(status)) {
307 t2lm_err("sending t2lm wmi failed");
308 break;
309 }
310 } else if (t2lm_rsp.dialog_token == t2lm_req->dialog_token &&
311 t2lm_rsp.t2lm_resp_type != WLAN_T2LM_RESP_TYPE_PREFERRED_TID_TO_LINK_MAPPING) {
312 t2lm_debug("T2LM rsp status denied, clear ongoing tid mapping");
313 wlan_t2lm_clear_ongoing_negotiation(peer);
314 }
315 }
316 }
317
318 channel = wlan_vdev_mlme_get_bss_chan(vdev);
319 if (!channel) {
320 t2lm_err("vdev: %d channel infio not found",
321 wlan_vdev_get_id(vdev));
322 return QDF_STATUS_E_FAILURE;
323 }
324
325 wlan_connectivity_t2lm_req_resp_event(vdev, t2lm_rsp.dialog_token, 0,
326 false,
327 channel->ch_freq,
328 true,
329 WLAN_CONN_DIAG_MLO_T2LM_RESP_EVENT);
330
331 return status;
332 }
333
t2lm_handle_rx_teardown(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,void * event_data)334 QDF_STATUS t2lm_handle_rx_teardown(struct wlan_objmgr_vdev *vdev,
335 struct wlan_objmgr_peer *peer,
336 void *event_data)
337 {
338 struct wlan_mlo_dev_context *mlo_dev_ctx;
339 struct wlan_t2lm_context *t2lm_ctx;
340
341 if (!peer) {
342 t2lm_err("peer is null");
343 return QDF_STATUS_E_NULL_VALUE;
344 }
345
346 if (!vdev) {
347 t2lm_err("vdev is null");
348 return QDF_STATUS_E_NULL_VALUE;
349 }
350
351 mlo_dev_ctx = vdev->mlo_dev_ctx;
352 if (!mlo_dev_ctx) {
353 t2lm_err("mlo dev ctx is null");
354 return QDF_STATUS_E_NULL_VALUE;
355 }
356
357 t2lm_ctx = &mlo_dev_ctx->t2lm_ctx;
358 if (!t2lm_ctx) {
359 t2lm_err("t2lm ctx is null");
360 return QDF_STATUS_E_NULL_VALUE;
361 }
362
363 wlan_t2lm_clear_peer_negotiation(peer);
364
365 /* Notify the registered caller about the link update*/
366 wlan_mlo_dev_t2lm_notify_link_update(vdev,
367 &t2lm_ctx->established_t2lm.t2lm);
368 wlan_send_tid_to_link_mapping(vdev,
369 &t2lm_ctx->established_t2lm.t2lm);
370
371 return QDF_STATUS_SUCCESS;
372 }
373
t2lm_handle_tx_teardown(struct wlan_objmgr_vdev * vdev,void * event_data)374 QDF_STATUS t2lm_handle_tx_teardown(struct wlan_objmgr_vdev *vdev,
375 void *event_data)
376 {
377 return QDF_STATUS_SUCCESS;
378 }
379
t2lm_deliver_event(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,enum wlan_t2lm_evt event,void * event_data,uint32_t frame_len,uint8_t * token)380 QDF_STATUS t2lm_deliver_event(struct wlan_objmgr_vdev *vdev,
381 struct wlan_objmgr_peer *peer,
382 enum wlan_t2lm_evt event,
383 void *event_data, uint32_t frame_len,
384 uint8_t *token)
385 {
386 struct wlan_objmgr_psoc *psoc;
387 QDF_STATUS status;
388
389 psoc = wlan_vdev_get_psoc(vdev);
390 if (!psoc)
391 return QDF_STATUS_E_FAILURE;
392
393 mlme_debug("T2LM event received: %s(%d)",
394 t2lm_get_event_str(event), event);
395
396 switch (event) {
397 case WLAN_T2LM_EV_ACTION_FRAME_RX_REQ:
398 status = t2lm_handle_rx_req(vdev, peer, event_data,
399 frame_len, token);
400 break;
401 case WLAN_T2LM_EV_ACTION_FRAME_TX_RESP:
402 status = t2lm_handle_tx_resp(vdev, event_data, token);
403 break;
404 case WLAN_T2LM_EV_ACTION_FRAME_TX_REQ:
405 status = t2lm_handle_tx_req(vdev, peer, event_data, token);
406 break;
407 case WLAN_T2LM_EV_ACTION_FRAME_RX_RESP:
408 status = t2lm_handle_rx_resp(vdev, peer, event_data,
409 frame_len, token);
410 break;
411 case WLAN_T2LM_EV_ACTION_FRAME_RX_TEARDOWN:
412 status = t2lm_handle_rx_teardown(vdev, peer, event_data);
413 break;
414 case WLAN_T2LM_EV_ACTION_FRAME_TX_TEARDOWN:
415 status = t2lm_handle_tx_teardown(vdev, event_data);
416 break;
417 default:
418 status = QDF_STATUS_E_FAILURE;
419 mlme_err("Unhandled T2LM event");
420 }
421
422 return status;
423 }
424
425 static uint16_t
t2lm_get_tids_mapped_link_id(uint16_t link_map_tid)426 t2lm_get_tids_mapped_link_id(uint16_t link_map_tid)
427 {
428 uint16_t all_tids_mapped_link_id = 0;
429 uint8_t i;
430 uint8_t bit_mask = 1;
431
432 for (i = 0; i < WLAN_T2LM_MAX_NUM_LINKS; i++) {
433 if (link_map_tid & bit_mask)
434 all_tids_mapped_link_id = i;
435 bit_mask = bit_mask << 1;
436 }
437
438 return all_tids_mapped_link_id;
439 }
440
441 static QDF_STATUS
t2lm_find_tid_mapped_link_id(struct wlan_t2lm_info * t2lm_info,uint16_t * tid_mapped_link_id)442 t2lm_find_tid_mapped_link_id(struct wlan_t2lm_info *t2lm_info,
443 uint16_t *tid_mapped_link_id)
444 {
445 uint16_t link_map_tid;
446 uint8_t tid;
447
448 if (!t2lm_info)
449 return QDF_STATUS_E_NULL_VALUE;
450
451 if (t2lm_info->default_link_mapping) {
452 t2lm_debug("T2LM ie has default link mapping");
453 *tid_mapped_link_id = 0xFFFF;
454 return QDF_STATUS_SUCCESS;
455 }
456
457 link_map_tid = t2lm_info->ieee_link_map_tid[0];
458 for (tid = 1; tid < T2LM_MAX_NUM_TIDS; tid++) {
459 if (link_map_tid != t2lm_info->ieee_link_map_tid[tid]) {
460 mlme_debug("all tids are not mapped to same link set");
461 return QDF_STATUS_E_FAILURE;
462 }
463 }
464
465 *tid_mapped_link_id = t2lm_get_tids_mapped_link_id(link_map_tid);
466 return QDF_STATUS_SUCCESS;
467 }
468
469 QDF_STATUS
wlan_t2lm_validate_candidate(struct cnx_mgr * cm_ctx,struct scan_cache_entry * scan_entry)470 wlan_t2lm_validate_candidate(struct cnx_mgr *cm_ctx,
471 struct scan_cache_entry *scan_entry)
472 {
473 QDF_STATUS status = QDF_STATUS_SUCCESS;
474 struct wlan_objmgr_vdev *vdev;
475 struct wlan_t2lm_context t2lm_ctx;
476 uint16_t tid_map_link_id;
477 uint16_t established_tid_mapped_link_id = 0;
478 uint16_t upcoming_tid_mapped_link_id = 0;
479 struct wlan_objmgr_psoc *psoc;
480
481 if (!scan_entry || !cm_ctx || !cm_ctx->vdev)
482 return QDF_STATUS_E_NULL_VALUE;
483
484 vdev = cm_ctx->vdev;
485 psoc = wlan_vdev_get_psoc(vdev);
486 if (!psoc)
487 return QDF_STATUS_E_NULL_VALUE;
488
489 if (!wlan_mlme_get_t2lm_negotiation_supported(psoc)) {
490 mlme_rl_debug("T2LM negotiation not supported");
491 return QDF_STATUS_SUCCESS;
492 }
493
494 /*
495 * Skip T2LM validation for following cases:
496 * - Is link VDEV
497 * - Is not STA VDEV
498 * - T2LM IE not present in scan entry
499 */
500 if (wlan_vdev_mlme_is_mlo_link_vdev(vdev) ||
501 wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE ||
502 !scan_entry->ie_list.t2lm[0]) {
503 return QDF_STATUS_SUCCESS;
504 }
505
506 status = wlan_mlo_parse_bcn_prbresp_t2lm_ie(&t2lm_ctx,
507 util_scan_entry_t2lm(scan_entry),
508 util_scan_entry_t2lm_len(scan_entry));
509 if (QDF_IS_STATUS_ERROR(status))
510 goto end;
511
512 status = t2lm_find_tid_mapped_link_id(&t2lm_ctx.established_t2lm.t2lm,
513 &established_tid_mapped_link_id);
514 if (QDF_IS_STATUS_ERROR(status))
515 goto end;
516
517 status = t2lm_find_tid_mapped_link_id(&t2lm_ctx.upcoming_t2lm.t2lm,
518 &upcoming_tid_mapped_link_id);
519 if (QDF_IS_STATUS_ERROR(status))
520 goto end;
521
522 t2lm_debug("self link id %d established_tid_mapped_link_id %x upcoming_tid_mapped_link_id %x",
523 scan_entry->ml_info.self_link_id,
524 established_tid_mapped_link_id, upcoming_tid_mapped_link_id);
525
526 tid_map_link_id =
527 established_tid_mapped_link_id & upcoming_tid_mapped_link_id;
528
529 if (!tid_map_link_id)
530 tid_map_link_id = established_tid_mapped_link_id;
531
532 if (tid_map_link_id == scan_entry->ml_info.self_link_id)
533 status = QDF_STATUS_SUCCESS;
534 else
535 status = QDF_STATUS_E_FAILURE;
536
537 end:
538 return status;
539 }
540
541 void
wlan_t2lm_clear_ongoing_negotiation(struct wlan_objmgr_peer * peer)542 wlan_t2lm_clear_ongoing_negotiation(struct wlan_objmgr_peer *peer)
543 {
544 struct wlan_mlo_peer_context *ml_peer;
545 struct wlan_t2lm_onging_negotiation_info *ongoing_tid_to_link_mapping;
546 uint8_t i;
547
548 ml_peer = peer->mlo_peer_ctx;
549 if (!ml_peer) {
550 t2lm_err("ml peer is null");
551 return;
552 }
553
554 ongoing_tid_to_link_mapping = &ml_peer->t2lm_policy.ongoing_tid_to_link_mapping;
555 if (!ongoing_tid_to_link_mapping) {
556 t2lm_err("ongoing tid mapping is null");
557 return;
558 }
559
560 qdf_mem_zero(&ongoing_tid_to_link_mapping->t2lm_info,
561 sizeof(struct wlan_t2lm_info) * WLAN_T2LM_MAX_DIRECTION);
562
563 ongoing_tid_to_link_mapping->dialog_token = 0;
564 ongoing_tid_to_link_mapping->category = WLAN_T2LM_CATEGORY_NONE;
565 ongoing_tid_to_link_mapping->t2lm_resp_type = WLAN_T2LM_RESP_TYPE_INVALID;
566 ongoing_tid_to_link_mapping->t2lm_tx_status = WLAN_T2LM_TX_STATUS_NONE;
567
568 for (i = 0; i < WLAN_T2LM_MAX_DIRECTION; i++)
569 ongoing_tid_to_link_mapping->t2lm_info[i].direction =
570 WLAN_T2LM_INVALID_DIRECTION;
571 }
572
573 void
wlan_t2lm_clear_peer_negotiation(struct wlan_objmgr_peer * peer)574 wlan_t2lm_clear_peer_negotiation(struct wlan_objmgr_peer *peer)
575 {
576 struct wlan_mlo_peer_context *ml_peer;
577 struct wlan_prev_t2lm_negotiated_info *t2lm_negotiated_info;
578 uint8_t i;
579
580 ml_peer = peer->mlo_peer_ctx;
581 if (!ml_peer) {
582 t2lm_err("ml peer is null");
583 return;
584 }
585
586 qdf_mem_zero(&ml_peer->t2lm_policy.t2lm_negotiated_info.t2lm_info,
587 sizeof(struct wlan_t2lm_info) * WLAN_T2LM_MAX_DIRECTION);
588
589 ml_peer->t2lm_policy.t2lm_negotiated_info.dialog_token = 0;
590 t2lm_negotiated_info = &ml_peer->t2lm_policy.t2lm_negotiated_info;
591 for (i = 0; i < WLAN_T2LM_MAX_DIRECTION; i++)
592 t2lm_negotiated_info->t2lm_info[i].direction =
593 WLAN_T2LM_INVALID_DIRECTION;
594 }
595
596 void
wlan_t2lm_clear_all_tid_mapping(struct wlan_objmgr_vdev * vdev)597 wlan_t2lm_clear_all_tid_mapping(struct wlan_objmgr_vdev *vdev)
598 {
599 struct wlan_objmgr_peer *peer;
600 struct wlan_t2lm_context *t2lm_ctx;
601
602 if (!vdev) {
603 t2lm_err("Vdev is null");
604 return;
605 }
606
607 if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
608 return;
609
610 if (!vdev->mlo_dev_ctx) {
611 t2lm_err("mlo dev ctx is null");
612 return;
613 }
614
615 t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
616 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
617 WLAN_MLO_MGR_ID);
618 if (!peer) {
619 t2lm_err("peer is null");
620 return;
621 }
622 qdf_mem_zero(&t2lm_ctx->established_t2lm,
623 sizeof(struct wlan_mlo_t2lm_ie));
624 t2lm_ctx->established_t2lm.t2lm.direction = WLAN_T2LM_BIDI_DIRECTION;
625 t2lm_ctx->established_t2lm.t2lm.default_link_mapping = 1;
626 t2lm_ctx->established_t2lm.t2lm.link_mapping_size = 0;
627
628 qdf_mem_zero(&t2lm_ctx->upcoming_t2lm,
629 sizeof(struct wlan_mlo_t2lm_ie));
630 t2lm_ctx->upcoming_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
631
632 t2lm_debug("Clear the T2LM info received in assoc rsp");
633 t2lm_ctx = &vdev->mlo_dev_ctx->sta_ctx->copied_t2lm_ie_assoc_rsp;
634
635 qdf_mem_zero(&t2lm_ctx->established_t2lm,
636 sizeof(struct wlan_mlo_t2lm_ie));
637 t2lm_ctx->established_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
638 qdf_mem_zero(&t2lm_ctx->upcoming_t2lm,
639 sizeof(struct wlan_mlo_t2lm_ie));
640 t2lm_ctx->upcoming_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
641
642 wlan_t2lm_clear_peer_negotiation(peer);
643 wlan_t2lm_clear_ongoing_negotiation(peer);
644 wlan_mlo_t2lm_timer_stop(vdev);
645 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
646 }
647
648 static bool
wlan_is_ml_link_disabled(uint32_t link_id_bitmap,uint8_t ml_link_id)649 wlan_is_ml_link_disabled(uint32_t link_id_bitmap,
650 uint8_t ml_link_id)
651 {
652 uint8_t link;
653
654 if (!link_id_bitmap) {
655 t2lm_err("Link id bitmap is 0");
656 return false;
657 }
658
659 for (link = 0; link < WLAN_T2LM_MAX_NUM_LINKS; link++) {
660 if ((link == ml_link_id) &&
661 (link_id_bitmap & BIT(link))) {
662 return true;
663 }
664 }
665
666 return false;
667 }
668
669 static void
wlan_t2lm_set_link_mapping_of_tids(uint8_t link_id,struct wlan_t2lm_info * t2lm_info,bool set)670 wlan_t2lm_set_link_mapping_of_tids(uint8_t link_id,
671 struct wlan_t2lm_info *t2lm_info,
672 bool set)
673 {
674 uint8_t tid_num;
675
676 if (link_id >= WLAN_T2LM_MAX_NUM_LINKS) {
677 t2lm_err("Max 16 t2lm links are supported");
678 return;
679 }
680
681 for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
682 if (set)
683 t2lm_info->ieee_link_map_tid[tid_num] |= BIT(link_id);
684 else
685 t2lm_info->ieee_link_map_tid[tid_num] &= ~BIT(link_id);
686 }
687 }
688
689 QDF_STATUS
wlan_populate_link_disable_t2lm_frame(struct wlan_objmgr_vdev * vdev,struct mlo_link_disable_request_evt_params * params)690 wlan_populate_link_disable_t2lm_frame(struct wlan_objmgr_vdev *vdev,
691 struct mlo_link_disable_request_evt_params *params)
692 {
693 struct wlan_objmgr_peer *peer;
694 struct wlan_mlo_dev_context *ml_dev_ctx;
695 struct wlan_mlo_peer_t2lm_policy *t2lm_policy;
696 struct wlan_objmgr_vdev *tmp_vdev;
697 struct wlan_t2lm_onging_negotiation_info t2lm_neg = {0};
698 uint8_t dir = WLAN_T2LM_BIDI_DIRECTION;
699 uint8_t i = 0;
700 QDF_STATUS status;
701 uint8_t link_id;
702
703 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
704 WLAN_MLO_MGR_ID);
705
706 if (!peer) {
707 t2lm_err("peer is null");
708 return QDF_STATUS_E_NULL_VALUE;
709 }
710
711 if (!vdev->mlo_dev_ctx)
712 return QDF_STATUS_E_NULL_VALUE;
713
714 t2lm_policy = &peer->mlo_peer_ctx->t2lm_policy;
715 t2lm_neg = t2lm_policy->ongoing_tid_to_link_mapping;
716
717 t2lm_neg.category = WLAN_T2LM_CATEGORY_REQUEST;
718 t2lm_neg.dialog_token = t2lm_gen_dialog_token(t2lm_policy);
719 qdf_mem_zero(&t2lm_neg.t2lm_info,
720 sizeof(struct wlan_t2lm_info) * WLAN_T2LM_MAX_DIRECTION);
721 for (i = 0; i < WLAN_T2LM_MAX_DIRECTION; i++)
722 t2lm_neg.t2lm_info[i].direction = WLAN_T2LM_INVALID_DIRECTION;
723
724 t2lm_neg.t2lm_info[dir].default_link_mapping = 0;
725 t2lm_neg.t2lm_info[dir].direction = WLAN_T2LM_BIDI_DIRECTION;
726 t2lm_neg.t2lm_info[dir].mapping_switch_time_present = 0;
727 t2lm_neg.t2lm_info[dir].expected_duration_present = 0;
728 t2lm_neg.t2lm_info[dir].link_mapping_size = 1;
729
730 t2lm_debug("dir %d", t2lm_neg.t2lm_info[dir].direction);
731 ml_dev_ctx = vdev->mlo_dev_ctx;
732
733 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
734 if (!ml_dev_ctx->wlan_vdev_list[i])
735 continue;
736
737 tmp_vdev = ml_dev_ctx->wlan_vdev_list[i];
738 link_id = wlan_vdev_get_link_id(tmp_vdev);
739
740 /* if link id matches disabled link id bitmap
741 * set that bit as 0.
742 */
743 if (wlan_is_ml_link_disabled(params->link_id_bitmap,
744 link_id)) {
745 wlan_t2lm_set_link_mapping_of_tids(link_id,
746 &t2lm_neg.t2lm_info[dir],
747 0);
748 t2lm_debug("Disabled link id %d", link_id);
749 } else {
750 wlan_t2lm_set_link_mapping_of_tids(link_id,
751 &t2lm_neg.t2lm_info[dir],
752 1);
753 t2lm_debug("Enabled link id %d", link_id);
754 }
755 }
756
757 status = t2lm_deliver_event(vdev, peer,
758 WLAN_T2LM_EV_ACTION_FRAME_TX_REQ,
759 &t2lm_neg,
760 0,
761 &t2lm_neg.dialog_token);
762
763 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
764 return status;
765 }
766
wlan_t2lm_deliver_event(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_peer * peer,enum wlan_t2lm_evt event,void * event_data,uint32_t frame_len,uint8_t * dialog_token)767 QDF_STATUS wlan_t2lm_deliver_event(struct wlan_objmgr_vdev *vdev,
768 struct wlan_objmgr_peer *peer,
769 enum wlan_t2lm_evt event,
770 void *event_data,
771 uint32_t frame_len,
772 uint8_t *dialog_token)
773 {
774 return t2lm_deliver_event(vdev, peer, event, event_data,
775 frame_len, dialog_token);
776 }
777
778 QDF_STATUS
wlan_t2lm_init_default_mapping(struct wlan_t2lm_context * t2lm_ctx)779 wlan_t2lm_init_default_mapping(struct wlan_t2lm_context *t2lm_ctx)
780 {
781 if (!t2lm_ctx)
782 return QDF_STATUS_E_NULL_VALUE;
783
784 qdf_mem_zero(t2lm_ctx, sizeof(struct wlan_t2lm_context));
785
786 t2lm_ctx->established_t2lm.t2lm.default_link_mapping = 1;
787 t2lm_ctx->established_t2lm.t2lm.direction = WLAN_T2LM_BIDI_DIRECTION;
788 t2lm_ctx->established_t2lm.t2lm.link_mapping_size = 0;
789
790 return QDF_STATUS_SUCCESS;
791 }
792
793 QDF_STATUS
wlan_update_t2lm_mapping(struct wlan_objmgr_vdev * vdev,struct wlan_t2lm_context * rx_t2lm,uint64_t tsf)794 wlan_update_t2lm_mapping(struct wlan_objmgr_vdev *vdev,
795 struct wlan_t2lm_context *rx_t2lm, uint64_t tsf)
796 {
797 struct wlan_t2lm_context *t2lm_ctx;
798 struct wlan_mlo_dev_context *mlo_dev_ctx;
799 uint64_t mst_start_tsf;
800 uint64_t mst_end_tsf;
801 uint64_t rx_bcn_tsf_exp_dur;
802 uint64_t mst_end_tsf_low;
803 uint64_t mst_end_tsf_high;
804 uint16_t mst;
805 uint32_t exp_dur;
806
807 if (!vdev)
808 return QDF_STATUS_E_NULL_VALUE;
809
810 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
811 if (!mlo_dev_ctx)
812 return QDF_STATUS_E_NULL_VALUE;
813
814 t2lm_ctx = &mlo_dev_ctx->t2lm_ctx;
815 if (rx_t2lm->upcoming_t2lm.t2lm.direction == WLAN_T2LM_INVALID_DIRECTION &&
816 rx_t2lm->established_t2lm.t2lm.direction == WLAN_T2LM_INVALID_DIRECTION) {
817 if (!t2lm_ctx->established_t2lm.t2lm.default_link_mapping) {
818 wlan_t2lm_init_default_mapping(t2lm_ctx);
819 t2lm_debug("initialize to default T2LM mapping");
820 }
821 return QDF_STATUS_SUCCESS;
822 }
823
824 if (rx_t2lm->established_t2lm.t2lm.expected_duration &&
825 !rx_t2lm->established_t2lm.t2lm.mapping_switch_time_present &&
826 rx_t2lm->upcoming_t2lm.t2lm.expected_duration &&
827 rx_t2lm->upcoming_t2lm.t2lm.mapping_switch_time_present) {
828 if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid,
829 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid,
830 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
831 t2lm_debug("T2LM mapping is already configured");
832 return QDF_STATUS_E_ALREADY;
833 }
834
835 qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm,
836 &rx_t2lm->established_t2lm.t2lm,
837 sizeof(struct wlan_t2lm_info));
838
839 t2lm_ctx->established_t2lm.t2lm.expected_duration = 0;
840 t2lm_ctx->established_t2lm.t2lm.expected_duration_present = 0;
841 t2lm_ctx->established_t2lm.t2lm.mapping_switch_time = 0;
842 t2lm_ctx->established_t2lm.t2lm.mapping_switch_time_present = 0;
843
844 wlan_mlo_dev_t2lm_notify_link_update(vdev,
845 &t2lm_ctx->established_t2lm.t2lm);
846 wlan_clear_peer_level_tid_to_link_mapping(vdev);
847 t2lm_debug("Update T2LM established mapping to FW");
848 wlan_send_tid_to_link_mapping(
849 vdev, &t2lm_ctx->established_t2lm.t2lm);
850
851 if (!qdf_mem_cmp(t2lm_ctx->upcoming_t2lm.t2lm.ieee_link_map_tid,
852 rx_t2lm->upcoming_t2lm.t2lm.ieee_link_map_tid,
853 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
854 t2lm_debug("Ongoing mapping is already established");
855 return QDF_STATUS_E_ALREADY;
856 }
857 qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm,
858 &rx_t2lm->upcoming_t2lm.t2lm,
859 sizeof(struct wlan_t2lm_info));
860 t2lm_debug("Update T2LM upcoming mapping to FW");
861 wlan_send_tid_to_link_mapping(
862 vdev, &t2lm_ctx->upcoming_t2lm.t2lm);
863 }
864
865 if (t2lm_ctx->established_t2lm.t2lm.expected_duration_present &&
866 rx_t2lm->established_t2lm.t2lm.expected_duration_present) {
867 /* Established T2LM is already saved in the T2LM context.
868 * T2LM IE in the beacon/probe response frame has the updated
869 * expected duration.
870 */
871 if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid,
872 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid,
873 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
874 if (!t2lm_ctx->mst_start_tsf) {
875 t2lm_ctx->mst_end_tsf = tsf + (rx_t2lm->established_t2lm.t2lm.expected_duration << 10);
876 t2lm_ctx->mst_start_tsf = tsf;
877 }
878
879 /* Check if AP has updated expected duration value
880 * more than expected delta between 2 beacons,
881 * calculation as following:
882 * 1.when receive a beacon with mapping switch
883 * time set, calculate the mapping switch start TSF
884 * by replacing bit25~bit10 in the bcn TSF
885 * mst_start_tsf = (bcn_tsf & (~mst_mask)) | (mst << 10);
886 * 2.based on the expected duration,
887 * calculate the mapping end time tsf
888 * mst_end_tsf = mst_start_tsf + expected_duration;
889 * 3.then after the TSF become established mapping,
890 * whenever host receive a beacon,
891 * check if the new expected duration based
892 * on current beacon TSF has a big drift to the old one.
893 * mst_end_tsf - (200 << 10) < rx_bcn_tsf_exp_dur +
894 * rx_bcn_tsf_exp_dur < mst_end_tsf + (200 << 10)
895 */
896 rx_bcn_tsf_exp_dur = tsf + (rx_t2lm->established_t2lm.t2lm.expected_duration << 10);
897 mst_end_tsf_low = t2lm_ctx->mst_end_tsf - (200 << 10);
898 mst_end_tsf_high = t2lm_ctx->mst_end_tsf + (200 << 10);
899 if (t2lm_ctx->mst_end_tsf && (rx_bcn_tsf_exp_dur < mst_end_tsf_low) &&
900 (rx_bcn_tsf_exp_dur > mst_end_tsf_high)) {
901 t2lm_ctx->established_t2lm.t2lm.expected_duration =
902 rx_t2lm->established_t2lm.t2lm.expected_duration;
903 wlan_send_tid_to_link_mapping(
904 vdev, &t2lm_ctx->established_t2lm.t2lm);
905 } else {
906 t2lm_debug("T2LM exp duration in range");
907 }
908 }
909 } else if (rx_t2lm->established_t2lm.t2lm.expected_duration_present &&
910 !rx_t2lm->established_t2lm.t2lm.mapping_switch_time_present) {
911 if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid,
912 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid,
913 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
914 t2lm_debug("T2LM mapping is already configured");
915 return QDF_STATUS_E_ALREADY;
916 }
917
918 mst_start_tsf = tsf;
919 t2lm_ctx->mst_start_tsf = mst_start_tsf;
920 mst_end_tsf = mst_start_tsf + (rx_t2lm->established_t2lm.t2lm.expected_duration << 10);
921 t2lm_ctx->mst_end_tsf = mst_end_tsf;
922
923 /* Mapping switch time is already expired when STA receives the
924 * T2LM IE from beacon/probe response frame.
925 */
926 qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm,
927 &rx_t2lm->established_t2lm.t2lm,
928 sizeof(struct wlan_t2lm_info));
929
930 /* Notify the registered caller about the link update*/
931 wlan_mlo_dev_t2lm_notify_link_update(vdev,
932 &t2lm_ctx->established_t2lm.t2lm);
933 wlan_clear_peer_level_tid_to_link_mapping(vdev);
934 t2lm_debug("MST expired, update established T2LM mapping to FW");
935 wlan_send_tid_to_link_mapping(
936 vdev, &t2lm_ctx->established_t2lm.t2lm);
937 }
938
939 if (rx_t2lm->upcoming_t2lm.t2lm.mapping_switch_time_present) {
940 if (!qdf_mem_cmp(t2lm_ctx->upcoming_t2lm.t2lm.ieee_link_map_tid,
941 rx_t2lm->upcoming_t2lm.t2lm.ieee_link_map_tid,
942 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
943 t2lm_debug("Ongoing mapping is already established");
944 return QDF_STATUS_E_ALREADY;
945 }
946
947 mst = rx_t2lm->upcoming_t2lm.t2lm.mapping_switch_time;
948 exp_dur = rx_t2lm->upcoming_t2lm.t2lm.expected_duration;
949 if (mst) {
950 mst_start_tsf = (tsf & (~WLAN_T2LM_MAPPING_SWITCH_TSF_BITS)) | (mst << 10);
951 mst_end_tsf = mst_start_tsf + exp_dur;
952 t2lm_ctx->mst_start_tsf = mst_start_tsf;
953 t2lm_ctx->mst_end_tsf = mst_end_tsf;
954 }
955
956 qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm,
957 &rx_t2lm->upcoming_t2lm.t2lm,
958 sizeof(struct wlan_t2lm_info));
959 t2lm_debug("Update T2LM upcoming mapping to FW");
960 wlan_send_tid_to_link_mapping(
961 vdev, &t2lm_ctx->upcoming_t2lm.t2lm);
962 } else {
963 if (t2lm_ctx->established_t2lm.t2lm.direction == WLAN_T2LM_INVALID_DIRECTION &&
964 t2lm_ctx->upcoming_t2lm.t2lm.direction != WLAN_T2LM_INVALID_DIRECTION) {
965 t2lm_debug("Copy upcoming T2LM mapping to expected T2LM");
966 qdf_mem_copy(&t2lm_ctx->established_t2lm,
967 &t2lm_ctx->upcoming_t2lm,
968 sizeof(struct wlan_mlo_t2lm_ie));
969 }
970 /* Upcoming mapping should be cleared as mapping switch time has expired */
971 qdf_mem_zero(&t2lm_ctx->upcoming_t2lm,
972 sizeof(struct wlan_mlo_t2lm_ie));
973 t2lm_ctx->upcoming_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
974 }
975
976 return QDF_STATUS_SUCCESS;
977 }
978
979