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