xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_t2lm.c (revision 54ab05a36f58e470e5b322a774385b90ea47f785)
1 /*
2  * Copyright (c) 2022-2023 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 T2LM APIs
19  */
20 
21 #include <wlan_objmgr_pdev_obj.h>
22 #include <wlan_objmgr_vdev_obj.h>
23 #include <wlan_objmgr_peer_obj.h>
24 #include <wlan_mlo_mgr_public_structs.h>
25 #include <wlan_mlo_mgr_cmn.h>
26 #include <qdf_util.h>
27 #include <wlan_cm_api.h>
28 #include "wlan_utility.h"
29 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE)
30 #include <wlan_t2lm_api.h>
31 #endif
32 
33 QDF_STATUS wlan_mlo_parse_t2lm_info(uint8_t *ie,
34 				    struct wlan_t2lm_info *t2lm)
35 {
36 	struct wlan_ie_tid_to_link_mapping *t2lm_ie;
37 	enum wlan_t2lm_direction dir;
38 	uint8_t *t2lm_control_field;
39 	uint16_t t2lm_control;
40 	uint8_t link_mapping_presence_ind;
41 	uint8_t *link_mapping_of_tids;
42 	uint8_t tid_num;
43 	uint8_t *ie_ptr = NULL;
44 
45 	t2lm_ie = (struct wlan_ie_tid_to_link_mapping *)ie;
46 
47 	t2lm_control_field = t2lm_ie->data;
48 	if (!t2lm_control_field) {
49 		t2lm_err("t2lm_control_field is null");
50 		return QDF_STATUS_E_NULL_VALUE;
51 	}
52 
53 	t2lm_control = qdf_le16_to_cpu(*(uint16_t *)t2lm_control_field);
54 
55 	dir = QDF_GET_BITS(t2lm_control, WLAN_T2LM_CONTROL_DIRECTION_IDX,
56 			   WLAN_T2LM_CONTROL_DIRECTION_BITS);
57 	if (dir > WLAN_T2LM_BIDI_DIRECTION) {
58 		t2lm_err("Invalid direction");
59 		return QDF_STATUS_E_NULL_VALUE;
60 	}
61 
62 	t2lm->direction = dir;
63 	t2lm->default_link_mapping =
64 		QDF_GET_BITS(t2lm_control,
65 			     WLAN_T2LM_CONTROL_DEFAULT_LINK_MAPPING_IDX,
66 			     WLAN_T2LM_CONTROL_DEFAULT_LINK_MAPPING_BITS);
67 
68 	t2lm->mapping_switch_time_present =
69 		QDF_GET_BITS(t2lm_control,
70 			     WLAN_T2LM_CONTROL_MAPPING_SWITCH_TIME_PRESENT_IDX,
71 			     WLAN_T2LM_CONTROL_MAPPING_SWITCH_TIME_PRESENT_BITS);
72 
73 	t2lm->expected_duration_present =
74 		QDF_GET_BITS(t2lm_control,
75 			     WLAN_T2LM_CONTROL_EXPECTED_DURATION_PRESENT_IDX,
76 			     WLAN_T2LM_CONTROL_EXPECTED_DURATION_PRESENT_BITS);
77 
78 	t2lm->link_mapping_size =
79 		QDF_GET_BITS(t2lm_control,
80 			     WLAN_T2LM_CONTROL_LINK_MAPPING_SIZE_IDX,
81 			     WLAN_T2LM_CONTROL_LINK_MAPPING_SIZE_BITS);
82 
83 	t2lm_debug("direction:%d default_link_mapping:%d mapping_switch_time_present:%d expected_duration_present:%d link_mapping_size:%d",
84 		   t2lm->direction, t2lm->default_link_mapping,
85 		    t2lm->mapping_switch_time_present,
86 		    t2lm->expected_duration_present,
87 		    t2lm->link_mapping_size);
88 
89 	if (t2lm->default_link_mapping) {
90 		ie_ptr = t2lm_control_field + sizeof(uint8_t);
91 	} else {
92 		link_mapping_presence_ind =
93 			QDF_GET_BITS(t2lm_control,
94 				     WLAN_T2LM_CONTROL_LINK_MAPPING_PRESENCE_INDICATOR_IDX,
95 				     WLAN_T2LM_CONTROL_LINK_MAPPING_PRESENCE_INDICATOR_BITS);
96 		ie_ptr = t2lm_control_field + sizeof(t2lm_control);
97 	}
98 
99 	if (t2lm->mapping_switch_time_present) {
100 		t2lm->mapping_switch_time =
101 			qdf_le16_to_cpu(*(uint16_t *)ie_ptr);
102 		ie_ptr += sizeof(uint16_t);
103 	}
104 
105 	if (t2lm->expected_duration_present) {
106 		qdf_mem_copy(&t2lm->expected_duration, ie_ptr,
107 			     WLAN_T2LM_EXPECTED_DURATION_SIZE *
108 			     (sizeof(uint8_t)));
109 		ie_ptr += WLAN_T2LM_EXPECTED_DURATION_SIZE * (sizeof(uint8_t));
110 	}
111 
112 	t2lm_debug("mapping_switch_time:%d expected_duration:%d",
113 		   t2lm->mapping_switch_time, t2lm->expected_duration);
114 
115 	if (t2lm->default_link_mapping)
116 		return QDF_STATUS_SUCCESS;
117 
118 	link_mapping_of_tids = ie_ptr;
119 
120 	for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
121 		if (!(link_mapping_presence_ind & BIT(tid_num)))
122 			continue;
123 
124 		if (!t2lm->link_mapping_size) {
125 			t2lm->ieee_link_map_tid[tid_num] =
126 				qdf_le16_to_cpu(*(uint16_t *)link_mapping_of_tids);
127 			link_mapping_of_tids += sizeof(uint16_t);
128 		} else {
129 			t2lm->ieee_link_map_tid[tid_num] =
130 				*(uint8_t *)link_mapping_of_tids;
131 			link_mapping_of_tids += sizeof(uint8_t);
132 		}
133 
134 		t2lm_rl_debug("link mapping of TID%d is %x", tid_num,
135 			      t2lm->ieee_link_map_tid[tid_num]);
136 	}
137 
138 	return QDF_STATUS_SUCCESS;
139 }
140 
141 QDF_STATUS wlan_mlo_parse_bcn_prbresp_t2lm_ie(
142 		struct wlan_t2lm_context *t2lm_ctx, uint8_t *ie)
143 {
144 	struct wlan_t2lm_info t2lm = {0};
145 	struct extn_ie_header *ext_ie_hdr;
146 	QDF_STATUS retval;
147 	int i = 0;
148 
149 	qdf_mem_zero(&t2lm_ctx->established_t2lm,
150 		     sizeof(struct wlan_mlo_t2lm_ie));
151 	qdf_mem_zero(&t2lm_ctx->upcoming_t2lm, sizeof(struct wlan_mlo_t2lm_ie));
152 
153 	t2lm_ctx->established_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
154 	t2lm_ctx->upcoming_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
155 
156 	for (i = 0; i < WLAN_MAX_T2LM_IE; i++) {
157 		if (!ie) {
158 			t2lm_err("ie is null");
159 			return QDF_STATUS_E_NULL_VALUE;
160 		}
161 
162 		ext_ie_hdr = (struct extn_ie_header *)ie;
163 
164 		if (!(ext_ie_hdr->ie_id == WLAN_ELEMID_EXTN_ELEM &&
165 		      ext_ie_hdr->ie_extn_id == WLAN_EXTN_ELEMID_T2LM))
166 			continue;
167 
168 		t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
169 		retval = wlan_mlo_parse_t2lm_info(ie, &t2lm);
170 		if (retval) {
171 			t2lm_err("Failed to parse the T2LM IE");
172 			return retval;
173 		}
174 
175 		if (!t2lm.mapping_switch_time_present &&
176 		    t2lm.expected_duration_present) {
177 			qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm, &t2lm,
178 				     sizeof(struct wlan_t2lm_info));
179 		} else if (t2lm.mapping_switch_time_present) {
180 			qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm, &t2lm,
181 				     sizeof(struct wlan_t2lm_info));
182 		}
183 
184 		ie += ext_ie_hdr->ie_len + sizeof(struct ie_header);
185 	}
186 
187 	return QDF_STATUS_SUCCESS;
188 }
189 
190 QDF_STATUS wlan_mlo_parse_t2lm_ie(
191 		struct wlan_t2lm_onging_negotiation_info *t2lm, uint8_t *ie)
192 {
193 	struct extn_ie_header *ext_ie_hdr = NULL;
194 	QDF_STATUS retval;
195 	enum wlan_t2lm_direction dir;
196 	struct wlan_t2lm_info t2lm_info;
197 
198 	for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++)
199 		t2lm->t2lm_info[dir].direction = WLAN_T2LM_INVALID_DIRECTION;
200 
201 	for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) {
202 		if (!ie) {
203 			t2lm_err("ie is null");
204 			return QDF_STATUS_E_NULL_VALUE;
205 		}
206 
207 		ext_ie_hdr = (struct extn_ie_header *)ie;
208 
209 		if (ext_ie_hdr->ie_id == WLAN_ELEMID_EXTN_ELEM &&
210 		    ext_ie_hdr->ie_extn_id == WLAN_EXTN_ELEMID_T2LM) {
211 			qdf_mem_zero(&t2lm_info, sizeof(t2lm_info));
212 			retval = wlan_mlo_parse_t2lm_info(ie, &t2lm_info);
213 			if (!retval &&
214 			    t2lm_info.direction < WLAN_T2LM_MAX_DIRECTION) {
215 				qdf_mem_copy(&t2lm->t2lm_info[t2lm_info.direction],
216 					     &t2lm_info,
217 					     sizeof(struct wlan_t2lm_info));
218 			} else {
219 				t2lm_err("Failed to parse the T2LM IE");
220 				return retval;
221 			}
222 			ie += ext_ie_hdr->ie_len + sizeof(struct ie_header);
223 		}
224 	}
225 
226 	if ((t2lm->t2lm_info[WLAN_T2LM_DL_DIRECTION].direction ==
227 			WLAN_T2LM_DL_DIRECTION ||
228 	     t2lm->t2lm_info[WLAN_T2LM_UL_DIRECTION].direction ==
229 			WLAN_T2LM_UL_DIRECTION) &&
230 	    t2lm->t2lm_info[WLAN_T2LM_BIDI_DIRECTION].direction ==
231 			WLAN_T2LM_BIDI_DIRECTION) {
232 		t2lm_err("Both DL/UL and BIDI T2LM IEs should not be present at the same time");
233 
234 		qdf_mem_zero(t2lm, sizeof(*t2lm));
235 		for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) {
236 			t2lm->t2lm_info[dir].direction =
237 			    WLAN_T2LM_INVALID_DIRECTION;
238 		}
239 
240 		return QDF_STATUS_E_FAILURE;
241 	}
242 
243 	return QDF_STATUS_SUCCESS;
244 }
245 
246 uint8_t *wlan_mlo_add_t2lm_info_ie(uint8_t *frm, struct wlan_t2lm_info *t2lm,
247 				   struct wlan_objmgr_vdev *vdev)
248 {
249 	struct wlan_ie_tid_to_link_mapping *t2lm_ie;
250 	uint16_t t2lm_control = 0;
251 	uint8_t *t2lm_control_field;
252 	uint8_t *link_mapping_of_tids;
253 	uint8_t tid_num;
254 	uint8_t num_tids = 0;
255 	uint8_t link_mapping_presence_indicator = 0;
256 	struct vdev_mlme_obj *vdev_mlme;
257 
258 	t2lm_ie = (struct wlan_ie_tid_to_link_mapping *)frm;
259 	t2lm_ie->elem_id = WLAN_ELEMID_EXTN_ELEM;
260 	t2lm_ie->elem_id_extn = WLAN_EXTN_ELEMID_T2LM;
261 
262 	t2lm_ie->elem_len = sizeof(*t2lm_ie) - sizeof(struct ie_header);
263 
264 	t2lm_control_field = t2lm_ie->data;
265 
266 	QDF_SET_BITS(t2lm_control, WLAN_T2LM_CONTROL_DIRECTION_IDX,
267 		     WLAN_T2LM_CONTROL_DIRECTION_BITS, t2lm->direction);
268 
269 	QDF_SET_BITS(t2lm_control, WLAN_T2LM_CONTROL_DEFAULT_LINK_MAPPING_IDX,
270 		     WLAN_T2LM_CONTROL_DEFAULT_LINK_MAPPING_BITS,
271 		     t2lm->default_link_mapping);
272 
273 	QDF_SET_BITS(t2lm_control,
274 		     WLAN_T2LM_CONTROL_MAPPING_SWITCH_TIME_PRESENT_IDX,
275 		     WLAN_T2LM_CONTROL_MAPPING_SWITCH_TIME_PRESENT_BITS,
276 		     t2lm->mapping_switch_time_present);
277 
278 	QDF_SET_BITS(t2lm_control,
279 		     WLAN_T2LM_CONTROL_EXPECTED_DURATION_PRESENT_IDX,
280 		     WLAN_T2LM_CONTROL_EXPECTED_DURATION_PRESENT_BITS,
281 		     t2lm->expected_duration_present);
282 
283 	QDF_SET_BITS(t2lm_control,
284 		     WLAN_T2LM_CONTROL_LINK_MAPPING_SIZE_IDX,
285 		     WLAN_T2LM_CONTROL_LINK_MAPPING_SIZE_BITS,
286 		     t2lm->link_mapping_size);
287 
288 	if (t2lm->default_link_mapping) {
289 		/* Link mapping of TIDs are not present when default mapping is
290 		 * set. Hence, the size of TID-To-Link mapping control is one
291 		 * octet.
292 		 */
293 		*t2lm_control_field = (uint8_t)t2lm_control;
294 
295 		t2lm_ie->elem_len += sizeof(uint8_t);
296 
297 		t2lm_rl_debug("T2LM IE added, default_link_mapping: %d dir:%d",
298 			      t2lm->default_link_mapping, t2lm->direction);
299 
300 		frm += sizeof(*t2lm_ie) + sizeof(uint8_t);
301 	} else {
302 		for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++)
303 			if (t2lm->hw_link_map_tid[tid_num] ||
304 			    t2lm->ieee_link_map_tid[tid_num])
305 				link_mapping_presence_indicator |= BIT(tid_num);
306 
307 		QDF_SET_BITS(t2lm_control,
308 			     WLAN_T2LM_CONTROL_LINK_MAPPING_PRESENCE_INDICATOR_IDX,
309 			     WLAN_T2LM_CONTROL_LINK_MAPPING_PRESENCE_INDICATOR_BITS,
310 			     link_mapping_presence_indicator);
311 		t2lm_rl_debug("T2LM IE added, direction:%d link_mapping_presence_indicator:%x",
312 			      t2lm->direction, link_mapping_presence_indicator);
313 
314 		/* The size of TID-To-Link mapping control is two octets when
315 		 * default link mapping is not set.
316 		 */
317 		*(uint16_t *)t2lm_control_field = htole16(t2lm_control);
318 		frm += sizeof(*t2lm_ie) + sizeof(uint16_t);
319 		t2lm_ie->elem_len += sizeof(uint16_t);
320 	}
321 
322 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
323 	if (vdev_mlme && t2lm->mapping_switch_time_present) {
324 		/* Mapping switch time is different for each vdevs. Hence,
325 		 * populate the mapping switch time from vdev_mlme_obj.
326 		 */
327 		*(uint16_t *)frm =
328 			htole16(vdev_mlme->proto.ap.mapping_switch_time);
329 		frm += sizeof(uint16_t);
330 		t2lm_ie->elem_len += sizeof(uint16_t);
331 	}
332 
333 	if (t2lm->expected_duration_present) {
334 		qdf_mem_copy(frm, &t2lm->expected_duration,
335 			     WLAN_T2LM_EXPECTED_DURATION_SIZE *
336 			     sizeof(uint8_t));
337 		frm += WLAN_T2LM_EXPECTED_DURATION_SIZE * sizeof(uint8_t);
338 		t2lm_ie->elem_len +=
339 			WLAN_T2LM_EXPECTED_DURATION_SIZE * sizeof(uint8_t);
340 	}
341 
342 	t2lm_rl_debug("mapping_switch_time:%d expected_duration:%u",
343 		      t2lm->mapping_switch_time, t2lm->expected_duration);
344 
345 	if (t2lm->default_link_mapping)
346 		return frm;
347 
348 	link_mapping_of_tids = frm;
349 
350 	for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
351 		if (!t2lm->ieee_link_map_tid[tid_num])
352 			continue;
353 
354 		if (!t2lm->link_mapping_size) {
355 			*(uint16_t *)link_mapping_of_tids =
356 				htole16(t2lm->ieee_link_map_tid[tid_num]);
357 			t2lm_rl_debug("link mapping of TID%d is %x",
358 				      tid_num,
359 				      htole16(t2lm->ieee_link_map_tid[tid_num]));
360 			link_mapping_of_tids += sizeof(uint16_t);
361 		} else {
362 			*(uint8_t *)link_mapping_of_tids =
363 				t2lm->ieee_link_map_tid[tid_num];
364 			t2lm_rl_debug("link mapping of TID%d is %x",
365 				      tid_num,
366 				      t2lm->ieee_link_map_tid[tid_num]);
367 			link_mapping_of_tids += sizeof(uint8_t);
368 		}
369 		num_tids++;
370 	}
371 
372 	if (!t2lm->link_mapping_size) {
373 		frm += num_tids * sizeof(uint16_t);
374 		t2lm_ie->elem_len += (num_tids * sizeof(uint16_t));
375 	} else {
376 		frm += num_tids * sizeof(uint8_t);
377 		t2lm_ie->elem_len += (num_tids * sizeof(uint8_t));
378 	}
379 
380 	return frm;
381 }
382 
383 uint8_t *wlan_mlo_add_t2lm_ie(uint8_t *frm,
384 			      struct wlan_t2lm_onging_negotiation_info *t2lm,
385 			      struct wlan_objmgr_vdev *vdev)
386 {
387 	uint8_t dir;
388 
389 	if (!frm) {
390 		t2lm_err("frm is null");
391 		return NULL;
392 	}
393 
394 	if (!t2lm) {
395 		t2lm_err("t2lm is null");
396 		return NULL;
397 	}
398 
399 	/* As per spec, the frame should include one or two T2LM IEs. When it is
400 	 * two, then direction should DL and UL.
401 	 */
402 	if ((t2lm->t2lm_info[WLAN_T2LM_DL_DIRECTION].direction ==
403 			WLAN_T2LM_DL_DIRECTION ||
404 	     t2lm->t2lm_info[WLAN_T2LM_UL_DIRECTION].direction ==
405 			WLAN_T2LM_UL_DIRECTION) &&
406 	    t2lm->t2lm_info[WLAN_T2LM_BIDI_DIRECTION].direction ==
407 			WLAN_T2LM_BIDI_DIRECTION) {
408 		t2lm_err("Both DL/UL and BIDI T2LM IEs should not be present at the same time");
409 		return NULL;
410 	}
411 
412 	for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) {
413 		if (t2lm->t2lm_info[dir].direction !=
414 			WLAN_T2LM_INVALID_DIRECTION)
415 			frm = wlan_mlo_add_t2lm_info_ie(frm,
416 							&t2lm->t2lm_info[dir],
417 							vdev);
418 	}
419 
420 	return frm;
421 }
422 
423 /**
424  * wlan_mlo_parse_t2lm_request_action_frame() - API to parse T2LM request action
425  * frame.
426  * @t2lm: Pointer to T2LM structure
427  * @action_frm: Pointer to action frame
428  * @category: T2LM action frame category
429  *
430  * Return: QDF_STATUS
431  */
432 static QDF_STATUS wlan_mlo_parse_t2lm_request_action_frame(
433 		struct wlan_t2lm_onging_negotiation_info *t2lm,
434 		struct wlan_action_frame *action_frm,
435 		enum wlan_t2lm_category category)
436 {
437 	uint8_t *t2lm_action_frm;
438 
439 	t2lm->category = category;
440 
441 	/*
442 	 * T2LM request action frame
443 	 *
444 	 *   1-byte     1-byte     1-byte   variable
445 	 *-------------------------------------------
446 	 * |         |           |        |         |
447 	 * | Category| Protected | Dialog | T2LM IE |
448 	 * |         |    EHT    | token  |         |
449 	 * |         |  Action   |        |         |
450 	 *-------------------------------------------
451 	 */
452 
453 	t2lm_action_frm = (uint8_t *)action_frm + sizeof(*action_frm);
454 
455 	t2lm->dialog_token = *t2lm_action_frm;
456 
457 	return wlan_mlo_parse_t2lm_ie(t2lm,
458 				      t2lm_action_frm + sizeof(uint8_t));
459 }
460 
461 /**
462  * wlan_mlo_parse_t2lm_response_action_frame() - API to parse T2LM response
463  * action frame.
464  * @t2lm: Pointer to T2LM structure
465  * @action_frm: Pointer to action frame
466  * @category: T2LM action frame category
467  *
468  * Return: QDF_STATUS
469  */
470 static QDF_STATUS wlan_mlo_parse_t2lm_response_action_frame(
471 		struct wlan_t2lm_onging_negotiation_info *t2lm,
472 		struct wlan_action_frame *action_frm,
473 		enum wlan_t2lm_category category)
474 {
475 	uint8_t *t2lm_action_frm;
476 	QDF_STATUS ret_val = QDF_STATUS_SUCCESS;
477 
478 	t2lm->category = WLAN_T2LM_CATEGORY_RESPONSE;
479 	/*
480 	 * T2LM response action frame
481 	 *
482 	 *   1-byte     1-byte     1-byte   2-byte   variable
483 	 *----------------------------------------------------
484 	 * |         |           |        |        |         |
485 	 * | Category| Protected | Dialog | Status | T2LM IE |
486 	 * |         |    EHT    | token  |  code  |         |
487 	 * |         |  Action   |        |        |         |
488 	 *----------------------------------------------------
489 	 */
490 
491 	t2lm_action_frm = (uint8_t *)action_frm + sizeof(*action_frm);
492 
493 	t2lm->dialog_token = *t2lm_action_frm;
494 	t2lm->t2lm_resp_type =
495 	      qdf_le16_to_cpu(*(uint16_t *)(t2lm_action_frm + sizeof(uint8_t)));
496 
497 	if (t2lm->t2lm_resp_type ==
498 			WLAN_T2LM_RESP_TYPE_PREFERRED_TID_TO_LINK_MAPPING) {
499 		t2lm_action_frm += sizeof(uint8_t) + sizeof(uint16_t);
500 		ret_val = wlan_mlo_parse_t2lm_ie(t2lm, t2lm_action_frm);
501 	}
502 
503 	return ret_val;
504 }
505 
506 int wlan_mlo_parse_t2lm_action_frame(
507 		struct wlan_t2lm_onging_negotiation_info *t2lm,
508 		struct wlan_action_frame *action_frm,
509 		enum wlan_t2lm_category category)
510 {
511 	QDF_STATUS ret_val = QDF_STATUS_SUCCESS;
512 
513 	switch (category) {
514 	case WLAN_T2LM_CATEGORY_REQUEST:
515 		{
516 			ret_val = wlan_mlo_parse_t2lm_request_action_frame(
517 					t2lm, action_frm, category);
518 			return qdf_status_to_os_return(ret_val);
519 		}
520 	case WLAN_T2LM_CATEGORY_RESPONSE:
521 		{
522 			ret_val = wlan_mlo_parse_t2lm_response_action_frame(
523 					t2lm, action_frm, category);
524 
525 			return qdf_status_to_os_return(ret_val);
526 		}
527 	case WLAN_T2LM_CATEGORY_TEARDOWN:
528 			/* Nothing to parse from T2LM teardown frame, just reset
529 			 * the mapping to default mapping.
530 			 *
531 			 * T2LM teardown action frame
532 			 *
533 			 *   1-byte     1-byte
534 			 *------------------------
535 			 * |         |           |
536 			 * | Category| Protected |
537 			 * |         |    EHT    |
538 			 * |         |  Action   |
539 			 *------------------------
540 			 */
541 			break;
542 	default:
543 			t2lm_err("Invalid category:%d", category);
544 	}
545 
546 	return ret_val;
547 }
548 
549 static uint8_t *wlan_mlo_add_t2lm_request_action_frame(
550 		uint8_t *frm,
551 		struct wlan_action_frame_args *args, uint8_t *buf,
552 		enum wlan_t2lm_category category)
553 {
554 	*frm++ = args->category;
555 	*frm++ = args->action;
556 	/* Dialog token*/
557 	*frm++ = args->arg1;
558 
559 	t2lm_info("T2LM request frame: category:%d action:%d dialog_token:%d",
560 		  args->category, args->action, args->arg1);
561 	return wlan_mlo_add_t2lm_ie(frm, (void *)buf, NULL);
562 }
563 
564 static uint8_t *wlan_mlo_add_t2lm_response_action_frame(
565 		uint8_t *frm,
566 		struct wlan_action_frame_args *args, uint8_t *buf,
567 		enum wlan_t2lm_category category)
568 {
569 	*frm++ = args->category;
570 	*frm++ = args->action;
571 	/* Dialog token*/
572 	*frm++ = args->arg1;
573 	/* Status code (2 bytes)*/
574 	*(uint16_t *)frm = htole16(args->arg2);
575 	frm += sizeof(uint16_t);
576 
577 	t2lm_info("T2LM response frame: category:%d action:%d dialog_token:%d status_code:%d",
578 		  args->category, args->action, args->arg1, args->arg2);
579 
580 	if (args->arg2 == WLAN_T2LM_RESP_TYPE_PREFERRED_TID_TO_LINK_MAPPING)
581 		frm = wlan_mlo_add_t2lm_ie(frm, (void *)buf, NULL);
582 
583 	return frm;
584 }
585 
586 uint8_t *wlan_mlo_add_t2lm_action_frame(
587 		uint8_t *frm,
588 		struct wlan_action_frame_args *args, uint8_t *buf,
589 		enum wlan_t2lm_category category)
590 {
591 
592 	switch (category) {
593 	case WLAN_T2LM_CATEGORY_REQUEST:
594 		return wlan_mlo_add_t2lm_request_action_frame(frm, args,
595 							      buf, category);
596 	case WLAN_T2LM_CATEGORY_RESPONSE:
597 		return wlan_mlo_add_t2lm_response_action_frame(frm, args,
598 							      buf, category);
599 	case WLAN_T2LM_CATEGORY_TEARDOWN:
600 		*frm++ = args->category;
601 		*frm++ = args->action;
602 		return frm;
603 	default:
604 		t2lm_err("Invalid category:%d", category);
605 	}
606 
607 	return frm;
608 }
609 
610 /**
611  * wlan_mlo_t2lm_handle_mapping_switch_time_expiry() - API to handle the mapping
612  * switch timer expiry.
613  * @t2lm_ctx: Pointer to T2LM context
614  * @vdev: Pointer to vdev structure
615  *
616  * Return: None
617  */
618 static void wlan_mlo_t2lm_handle_mapping_switch_time_expiry(
619 		struct wlan_t2lm_context *t2lm_ctx,
620 		struct wlan_objmgr_vdev *vdev)
621 {
622 	struct wlan_t2lm_info *t2lm;
623 
624 	t2lm_debug("Mapping switch time expired for vdev_id:%d ",
625 		   wlan_vdev_get_id(vdev));
626 
627 	qdf_mem_copy(&t2lm_ctx->established_t2lm, &t2lm_ctx->upcoming_t2lm,
628 		     sizeof(struct wlan_mlo_t2lm_ie));
629 
630 	t2lm_ctx->established_t2lm.t2lm.mapping_switch_time_present = false;
631 	t2lm_ctx->established_t2lm.t2lm.mapping_switch_time = 0;
632 
633 	t2lm = &t2lm_ctx->established_t2lm.t2lm;
634 	t2lm_debug("Established mapping: disabled_link_bitmap:%x dir:%d default_map:%d MSTP:%d EDP:%d MST:%d ED:%d ieee_link_map:%x hw_link_map:%x",
635 		   t2lm_ctx->established_t2lm.disabled_link_bitmap,
636 		   t2lm->direction, t2lm->default_link_mapping,
637 		   t2lm->mapping_switch_time_present,
638 		   t2lm->expected_duration_present,
639 		   t2lm->mapping_switch_time, t2lm->expected_duration,
640 		   t2lm->ieee_link_map_tid[0], t2lm->hw_link_map_tid[0]);
641 
642 	qdf_mem_zero(&t2lm_ctx->upcoming_t2lm, sizeof(struct wlan_mlo_t2lm_ie));
643 	t2lm_ctx->upcoming_t2lm.t2lm.direction = WLAN_T2LM_INVALID_DIRECTION;
644 }
645 
646 /**
647  * wlan_mlo_t2lm_handle_expected_duration_expiry() - API to handle the expected
648  * duration timer expiry.
649  * @t2lm_ctx: Pointer to T2LM context
650  * @vdev: Pointer to vdev structure
651  *
652  * Return: none
653  */
654 static void wlan_mlo_t2lm_handle_expected_duration_expiry(
655 		struct wlan_t2lm_context *t2lm_ctx,
656 		struct wlan_objmgr_vdev *vdev)
657 {
658 	t2lm_debug("Expected duration expired for vdev_id:%d ",
659 		   wlan_vdev_get_id(vdev));
660 
661 	if (t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present) {
662 		/* Copy the new non-default ongoing mapping to established
663 		 * mapping if expected duration expires for the established
664 		 * mapping.
665 		 */
666 		wlan_mlo_t2lm_handle_mapping_switch_time_expiry(t2lm_ctx,
667 								vdev);
668 		return;
669 	}
670 
671 	/* Use the default mapping when expected duration expires for the
672 	 * established mapping and no new non-default T2LM announcement is
673 	 * ongoing.
674 	 */
675 	qdf_mem_zero(&t2lm_ctx->established_t2lm,
676 		     sizeof(struct wlan_mlo_t2lm_ie));
677 
678 	t2lm_ctx->established_t2lm.t2lm.direction = WLAN_T2LM_BIDI_DIRECTION;
679 	t2lm_ctx->established_t2lm.t2lm.default_link_mapping = 1;
680 	t2lm_ctx->established_t2lm.disabled_link_bitmap = 0;
681 	t2lm_ctx->established_t2lm.t2lm.link_mapping_size = 0;
682 	t2lm_debug("Set established mapping to default mapping");
683 
684 	wlan_clear_peer_level_tid_to_link_mapping(vdev);
685 }
686 
687 QDF_STATUS wlan_mlo_vdev_tid_to_link_map_event(
688 		struct wlan_objmgr_psoc *psoc,
689 		struct mlo_vdev_host_tid_to_link_map_resp *event)
690 {
691 	struct wlan_objmgr_vdev *vdev;
692 	struct wlan_t2lm_context *t2lm_ctx;
693 	struct vdev_mlme_obj *vdev_mlme;
694 
695 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, event->vdev_id,
696 						    WLAN_MLO_MGR_ID);
697 	if (!vdev) {
698 		t2lm_err("null vdev");
699 		return QDF_STATUS_E_NULL_VALUE;
700 	}
701 
702 	if (!vdev->mlo_dev_ctx) {
703 		t2lm_err("null mlo_dev_ctx");
704 		return QDF_STATUS_E_NULL_VALUE;
705 	}
706 
707 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
708 	if (!vdev_mlme) {
709 		t2lm_err("null vdev_mlme");
710 		return QDF_STATUS_E_FAILURE;
711 	}
712 
713 	t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
714 
715 	t2lm_debug("psoc_id:%d vdev_id:%d status:%d",
716 		   wlan_psoc_get_id(psoc), event->vdev_id, event->status);
717 
718 	t2lm_dev_lock_acquire(t2lm_ctx);
719 	switch (event->status) {
720 	case WLAN_MAP_SWITCH_TIMER_TSF:
721 
722 		/* Mapping switch time is different for each AP vdev of a given
723 		 * MLD as these vdevs can have separate beacon TDF value.
724 		 */
725 		if (t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present)
726 			vdev_mlme->proto.ap.mapping_switch_time =
727 				(event->mapping_switch_tsf &
728 				 WLAN_T2LM_MAPPING_SWITCH_TSF_BITS) >> 10;
729 
730 		t2lm_debug("vdev_id:%d updated mapping switch time:%d",
731 			   event->vdev_id,
732 			   vdev_mlme->proto.ap.mapping_switch_time);
733 		break;
734 	case WLAN_MAP_SWITCH_TIMER_EXPIRED:
735 		vdev_mlme->proto.ap.mapping_switch_time = 0;
736 		wlan_mlo_t2lm_handle_mapping_switch_time_expiry(t2lm_ctx, vdev);
737 
738 		/* Notify the registered caller about the link update*/
739 		wlan_mlo_dev_t2lm_notify_link_update(vdev,
740 					&t2lm_ctx->established_t2lm.t2lm);
741 		break;
742 	case WLAN_EXPECTED_DUR_EXPIRED:
743 		wlan_mlo_t2lm_handle_expected_duration_expiry(t2lm_ctx, vdev);
744 
745 		/* Notify the registered caller about the link update*/
746 		wlan_mlo_dev_t2lm_notify_link_update(vdev,
747 					&t2lm_ctx->established_t2lm.t2lm);
748 		break;
749 	default:
750 		t2lm_err("Invalid status");
751 	}
752 
753 	t2lm_dev_lock_release(t2lm_ctx);
754 	mlo_release_vdev_ref(vdev);
755 
756 	return QDF_STATUS_SUCCESS;
757 }
758 
759 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
760 static
761 QDF_STATUS wlan_send_t2lm_info(struct wlan_objmgr_vdev *vdev,
762 			       struct wlan_t2lm_info *t2lm,
763 			       struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
764 {
765 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
766 
767 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
768 		t2lm_err("vdev is not MLO vdev");
769 		return status;
770 	}
771 
772 	status = mlo_tx_ops->send_tid_to_link_mapping(vdev, t2lm);
773 	if (QDF_IS_STATUS_ERROR(status))
774 		t2lm_err("Failed to send T2LM command to FW");
775 
776 	return status;
777 }
778 #else
779 static
780 QDF_STATUS wlan_send_t2lm_info(struct wlan_objmgr_vdev *vdev,
781 			       struct wlan_t2lm_info *t2lm,
782 			       struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops)
783 {
784 	struct wlan_objmgr_vdev *co_mld_vdev;
785 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
786 	uint16_t vdev_count = 0;
787 	int i = 0;
788 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
789 
790 	mlo_get_ml_vdev_list(vdev, &vdev_count, wlan_vdev_list);
791 	if (!vdev_count) {
792 		t2lm_err("Number of VDEVs under MLD is reported as 0");
793 		return QDF_STATUS_E_NULL_VALUE;
794 	}
795 
796 	for (i = 0; i < vdev_count; i++) {
797 		co_mld_vdev = wlan_vdev_list[i];
798 		if (!co_mld_vdev) {
799 			t2lm_err("co_mld_vdev is null");
800 			mlo_release_vdev_ref(co_mld_vdev);
801 			continue;
802 		}
803 
804 		status = mlo_tx_ops->send_tid_to_link_mapping(co_mld_vdev,
805 							      t2lm);
806 		if (QDF_IS_STATUS_ERROR(status))
807 			t2lm_err("Failed to send T2LM command to FW");
808 		mlo_release_vdev_ref(co_mld_vdev);
809 	}
810 
811 	return status;
812 }
813 #endif
814 
815 QDF_STATUS wlan_send_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev,
816 					 struct wlan_t2lm_info *t2lm)
817 {
818 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
819 	struct wlan_objmgr_psoc *psoc;
820 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
821 
822 	psoc = wlan_vdev_get_psoc(vdev);
823 	if (!psoc) {
824 		t2lm_err("null psoc");
825 		return QDF_STATUS_E_NULL_VALUE;
826 	}
827 
828 	mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
829 	if (!mlo_tx_ops) {
830 		t2lm_err("tx_ops is null!");
831 		return QDF_STATUS_E_NULL_VALUE;
832 	}
833 
834 	if (!mlo_tx_ops->send_tid_to_link_mapping) {
835 		t2lm_err("send_tid_to_link_mapping is null");
836 		return QDF_STATUS_E_NULL_VALUE;
837 	}
838 
839 	status = wlan_send_t2lm_info(vdev, t2lm, mlo_tx_ops);
840 
841 	return status;
842 }
843 
844 /**
845  * wlan_get_vdev_t2lm_mapping_status() - API to get vdev level T2LM info
846  * @vdev: vdev object
847  * @t2lm: T2LM info
848  *
849  * Return: QDF_STATUS
850  */
851 static
852 QDF_STATUS wlan_get_vdev_t2lm_mapping_status(struct wlan_objmgr_vdev *vdev,
853 					     struct wlan_t2lm_info *t2lm)
854 {
855 	struct wlan_t2lm_context *t2lm_ctx;
856 	int i = 0;
857 
858 	t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
859 
860 	t2lm_dev_lock_acquire(t2lm_ctx);
861 	qdf_mem_copy(&t2lm[i++], &t2lm_ctx->established_t2lm.t2lm,
862 		     sizeof(struct wlan_t2lm_info));
863 	t2lm_dev_lock_release(t2lm_ctx);
864 
865 	return QDF_STATUS_SUCCESS;
866 }
867 
868 /**
869  * wlan_get_peer_t2lm_mapping_status() - API to get peer level T2LM info
870  * @peer: peer object
871  * @t2lm: T2LM info
872  *
873  * Return: QDF_STATUS
874  */
875 static
876 QDF_STATUS wlan_get_peer_t2lm_mapping_status(struct wlan_objmgr_peer *peer,
877 					     struct wlan_t2lm_info *t2lm)
878 {
879 	enum wlan_t2lm_direction dir = WLAN_T2LM_INVALID_DIRECTION;
880 	struct wlan_mlo_peer_context *ml_peer;
881 	struct wlan_prev_t2lm_negotiated_info *t2lm_req;
882 	int i = 0;
883 
884 	ml_peer = peer->mlo_peer_ctx;
885 	if (!ml_peer)
886 		return QDF_STATUS_E_FAILURE;
887 
888 	t2lm_req = &ml_peer->t2lm_policy.t2lm_negotiated_info;
889 	if ((t2lm_req->t2lm_info[WLAN_T2LM_DL_DIRECTION].direction ==
890 			WLAN_T2LM_DL_DIRECTION ||
891 	     t2lm_req->t2lm_info[WLAN_T2LM_UL_DIRECTION].direction ==
892 			WLAN_T2LM_UL_DIRECTION) &&
893 	     t2lm_req->t2lm_info[WLAN_T2LM_BIDI_DIRECTION].direction ==
894 			WLAN_T2LM_BIDI_DIRECTION) {
895 		t2lm_err("Both DL/UL and BIDI T2LM IEs should not be present at the same time");
896 		return QDF_STATUS_E_FAILURE;
897 	}
898 
899 	for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) {
900 		if (t2lm_req->t2lm_info[dir].direction !=
901 			WLAN_T2LM_INVALID_DIRECTION)
902 			qdf_mem_copy(&t2lm[i++], &t2lm_req->t2lm_info[dir],
903 				     sizeof(struct wlan_t2lm_info));
904 	}
905 
906 	if (i == 0)
907 		return QDF_STATUS_E_EMPTY;
908 
909 	return QDF_STATUS_SUCCESS;
910 }
911 
912 QDF_STATUS wlan_get_t2lm_mapping_status(struct wlan_objmgr_vdev *vdev,
913 					struct wlan_t2lm_info *t2lm)
914 {
915 	struct wlan_objmgr_peer *peer;
916 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
917 
918 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
919 	if (!peer) {
920 		t2lm_err("peer not found");
921 		return QDF_STATUS_E_NULL_VALUE;
922 	}
923 
924 	status = wlan_get_peer_t2lm_mapping_status(peer, t2lm);
925 	if (QDF_IS_STATUS_SUCCESS(status)) {
926 		t2lm_debug("peer level T2LM info");
927 		goto peer_release;
928 	}
929 
930 	t2lm_debug("vdev level T2LM info");
931 	status = wlan_get_vdev_t2lm_mapping_status(vdev, t2lm);
932 
933 peer_release:
934 	wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
935 
936 	return status;
937 }
938 
939 QDF_STATUS
940 wlan_send_peer_level_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev,
941 					 struct wlan_objmgr_peer *peer)
942 {
943 	uint8_t dir, idx = 0;
944 	struct wlan_mlo_peer_context *ml_peer;
945 	struct wlan_t2lm_info *t2lm_info;
946 	QDF_STATUS status = QDF_STATUS_E_NULL_VALUE;
947 
948 	if (!peer) {
949 		t2lm_err("peer is null");
950 		return status;
951 	}
952 
953 	ml_peer = peer->mlo_peer_ctx;
954 	if (!ml_peer) {
955 		t2lm_err("ml peer is null");
956 		return status;
957 	}
958 
959 	for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) {
960 		t2lm_info = &ml_peer->t2lm_policy.t2lm_negotiated_info.t2lm_info[dir];
961 		if (t2lm_info && t2lm_info->direction !=
962 		    WLAN_T2LM_INVALID_DIRECTION) {
963 			t2lm_debug("send peer-level mapping to FW for dir: %d", dir);
964 
965 			/* Notify the registered caller about the link update*/
966 			wlan_mlo_dev_t2lm_notify_link_update(vdev, t2lm_info);
967 			status = wlan_send_tid_to_link_mapping(vdev, t2lm_info);
968 			idx++;
969 		}
970 	}
971 
972 	if (!idx)
973 		t2lm_debug("No peer-level mapping present");
974 
975 	return status;
976 }
977 
978 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE)
979 void
980 wlan_clear_peer_level_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev)
981 {
982 	struct wlan_objmgr_peer *peer;
983 
984 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID);
985 	if (!peer) {
986 		t2lm_err("Peer not found");
987 		return;
988 	}
989 
990 	wlan_t2lm_clear_peer_negotiation(peer);
991 
992 	wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID);
993 }
994 #endif
995 
996 void wlan_mlo_t2lm_timer_expiry_handler(void *vdev)
997 {
998 	struct wlan_objmgr_vdev *vdev_ctx = (struct wlan_objmgr_vdev *)vdev;
999 
1000 	struct wlan_t2lm_timer *t2lm_timer;
1001 	struct wlan_t2lm_context *t2lm_ctx;
1002 
1003 	if (!vdev_ctx || !vdev_ctx->mlo_dev_ctx)
1004 		return;
1005 
1006 	t2lm_ctx = &vdev_ctx->mlo_dev_ctx->t2lm_ctx;
1007 	t2lm_timer = &vdev_ctx->mlo_dev_ctx->t2lm_ctx.t2lm_timer;
1008 
1009 	wlan_mlo_t2lm_timer_stop(vdev_ctx);
1010 
1011 	/* Since qdf_mutex_acquire cannot be called from interrupt context,
1012 	 * change needed to create a workqueue and offload the timer expiry
1013 	 * handling to workqueue.
1014 	 */
1015 	if (t2lm_ctx->established_t2lm.t2lm.expected_duration_present) {
1016 		wlan_mlo_t2lm_handle_expected_duration_expiry(t2lm_ctx, vdev);
1017 
1018 		/* Notify the registered caller about the link update*/
1019 		wlan_mlo_dev_t2lm_notify_link_update(vdev_ctx,
1020 					&t2lm_ctx->established_t2lm.t2lm);
1021 		wlan_send_tid_to_link_mapping(
1022 				vdev, &t2lm_ctx->established_t2lm.t2lm);
1023 
1024 		wlan_handle_t2lm_timer(vdev_ctx);
1025 	} else if (t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present) {
1026 		wlan_mlo_t2lm_handle_mapping_switch_time_expiry(t2lm_ctx, vdev);
1027 
1028 		/* Notify the registered caller about the link update*/
1029 		wlan_mlo_dev_t2lm_notify_link_update(vdev_ctx,
1030 					&t2lm_ctx->established_t2lm.t2lm);
1031 		wlan_send_tid_to_link_mapping(
1032 				vdev, &t2lm_ctx->established_t2lm.t2lm);
1033 		wlan_handle_t2lm_timer(vdev_ctx);
1034 	}
1035 
1036 }
1037 
1038 QDF_STATUS
1039 wlan_mlo_t2lm_timer_init(struct wlan_objmgr_vdev *vdev)
1040 {
1041 	struct wlan_t2lm_timer *t2lm_timer = NULL;
1042 
1043 	if (!vdev || !vdev->mlo_dev_ctx)
1044 		return QDF_STATUS_E_FAILURE;
1045 
1046 	t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer;
1047 	if (!t2lm_timer) {
1048 		t2lm_err("t2lm timer ctx is null");
1049 		return QDF_STATUS_E_NULL_VALUE;
1050 	}
1051 
1052 	t2lm_dev_lock_create(&vdev->mlo_dev_ctx->t2lm_ctx);
1053 	t2lm_dev_lock_acquire(&vdev->mlo_dev_ctx->t2lm_ctx);
1054 	qdf_timer_init(NULL, &t2lm_timer->t2lm_timer,
1055 		       wlan_mlo_t2lm_timer_expiry_handler,
1056 		       vdev, QDF_TIMER_TYPE_WAKE_APPS);
1057 
1058 	t2lm_timer->timer_started = false;
1059 	t2lm_timer->timer_interval = 0;
1060 	t2lm_timer->timer_out_time = 0;
1061 	t2lm_dev_lock_release(&vdev->mlo_dev_ctx->t2lm_ctx);
1062 	return QDF_STATUS_SUCCESS;
1063 }
1064 
1065 QDF_STATUS
1066 wlan_mlo_t2lm_timer_start(struct wlan_objmgr_vdev *vdev,
1067 			  uint32_t interval)
1068 {
1069 	struct wlan_t2lm_timer *t2lm_timer;
1070 	struct wlan_t2lm_context *t2lm_ctx;
1071 	uint32_t target_out_time;
1072 	struct wlan_mlo_dev_context *mlo_dev_ctx;
1073 
1074 	if (!interval) {
1075 		t2lm_debug("Timer interval is 0");
1076 		return QDF_STATUS_E_NULL_VALUE;
1077 	}
1078 
1079 	if (!vdev)
1080 		return QDF_STATUS_E_NULL_VALUE;
1081 
1082 	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
1083 	if (!mlo_dev_ctx)
1084 		return QDF_STATUS_E_NULL_VALUE;
1085 
1086 	t2lm_ctx = &mlo_dev_ctx->t2lm_ctx;
1087 	t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer;
1088 	if (!t2lm_timer) {
1089 		t2lm_err("t2lm timer ctx is null");
1090 		return QDF_STATUS_E_NULL_VALUE;
1091 	}
1092 
1093 	interval = (interval * 1024) / 1000;
1094 	target_out_time = qdf_system_ticks_to_msecs(qdf_system_ticks());
1095 	target_out_time += interval;
1096 	t2lm_debug("earlier timer @%u ms out, new @%u ms out",
1097 		   t2lm_timer->timer_out_time, target_out_time);
1098 
1099 	/* sometimes the host process the beacon maybe delay, it may help for
1100 	 * update the new expected time.
1101 	 */
1102 	if (t2lm_timer->timer_out_time &&
1103 	    (target_out_time > t2lm_timer->timer_out_time ||
1104 	     (t2lm_timer->timer_out_time - target_out_time) <
1105 	      WLAN_T2LM_MAPPING_SWITCH_TIME_DELAY))
1106 		return QDF_STATUS_E_NULL_VALUE;
1107 
1108 	if (t2lm_timer->timer_started)
1109 		qdf_timer_stop(&t2lm_timer->t2lm_timer);
1110 
1111 	t2lm_debug("t2lm timer started with interval %d ms", interval);
1112 	t2lm_timer->timer_interval = interval;
1113 	t2lm_timer->timer_started = true;
1114 	t2lm_timer->timer_out_time = target_out_time;
1115 	qdf_timer_start(&t2lm_timer->t2lm_timer, t2lm_timer->timer_interval);
1116 
1117 	return QDF_STATUS_SUCCESS;
1118 }
1119 
1120 QDF_STATUS
1121 wlan_mlo_t2lm_timer_stop(struct wlan_objmgr_vdev *vdev)
1122 {
1123 	struct wlan_t2lm_timer *t2lm_timer;
1124 
1125 	if (!vdev || !vdev->mlo_dev_ctx)
1126 		return QDF_STATUS_E_NULL_VALUE;
1127 
1128 	t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer;
1129 	if (!t2lm_timer) {
1130 		t2lm_err("t2lm timer ctx is null");
1131 		return QDF_STATUS_E_NULL_VALUE;
1132 	}
1133 
1134 	if (t2lm_timer->timer_started) {
1135 		qdf_timer_stop(&t2lm_timer->t2lm_timer);
1136 		t2lm_timer->timer_started = false;
1137 		t2lm_timer->timer_interval = 0;
1138 		t2lm_timer->timer_out_time = 0;
1139 	}
1140 	return QDF_STATUS_SUCCESS;
1141 }
1142 
1143 QDF_STATUS wlan_handle_t2lm_timer(struct wlan_objmgr_vdev *vdev)
1144 {
1145 	struct wlan_t2lm_context *t2lm_ctx;
1146 	struct vdev_mlme_obj *vdev_mlme;
1147 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1148 
1149 	if (!vdev || !vdev->mlo_dev_ctx)
1150 		return QDF_STATUS_E_NULL_VALUE;
1151 
1152 	t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
1153 
1154 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
1155 	if (!vdev_mlme)
1156 		return QDF_STATUS_E_FAILURE;
1157 
1158 	if (t2lm_ctx->established_t2lm.t2lm.expected_duration_present) {
1159 		if (t2lm_ctx->established_t2lm.t2lm.expected_duration ==
1160 		    T2LM_EXPECTED_DURATION_MAX_VALUE) {
1161 			return status;
1162 		}
1163 
1164 		status = wlan_mlo_t2lm_timer_start(
1165 				vdev,
1166 				t2lm_ctx->established_t2lm.t2lm.expected_duration);
1167 	} else if (t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present) {
1168 		status = wlan_mlo_t2lm_timer_start(
1169 				vdev,
1170 				t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time);
1171 	}
1172 
1173 	return status;
1174 }
1175 
1176 /**
1177  * wlan_update_mapping_switch_time_expected_dur() - API to update the mapping
1178  * switch time and expected duration.
1179  * @vdev:Pointer to vdev
1180  * @rx_t2lm: Pointer to received T2LM IE
1181  * @tsf: TSF value of beacon/probe response
1182  *
1183  * Return: None
1184  */
1185 static QDF_STATUS wlan_update_mapping_switch_time_expected_dur(
1186 		struct wlan_objmgr_vdev *vdev,
1187 		struct wlan_t2lm_context *rx_t2lm, uint64_t tsf)
1188 {
1189 	struct wlan_t2lm_context *t2lm_ctx;
1190 	uint16_t tsf_bit25_10, ms_time;
1191 	struct wlan_mlo_dev_context *mlo_dev_ctx;
1192 
1193 	if (!vdev)
1194 		return QDF_STATUS_E_NULL_VALUE;
1195 
1196 	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
1197 	if (!mlo_dev_ctx)
1198 		return QDF_STATUS_E_NULL_VALUE;
1199 
1200 	tsf_bit25_10 = (tsf & WLAN_T2LM_MAPPING_SWITCH_TSF_BITS) >> 10;
1201 	t2lm_ctx = &mlo_dev_ctx->t2lm_ctx;
1202 
1203 	t2lm_dev_lock_acquire(t2lm_ctx);
1204 
1205 	if ((t2lm_ctx->established_t2lm.t2lm.expected_duration_present &&
1206 	    rx_t2lm->established_t2lm.t2lm.expected_duration_present) &&
1207 	    (rx_t2lm->established_t2lm.t2lm.expected_duration <
1208 	     t2lm_ctx->established_t2lm.t2lm.expected_duration)) {
1209 		/* Established T2LM is already saved in the T2LM context.
1210 		 * T2LM IE in the beacon/probe response frame has the updated
1211 		 * expected duration.
1212 		 */
1213 		if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid,
1214 				 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid,
1215 				 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
1216 			t2lm_ctx->established_t2lm.t2lm.expected_duration =
1217 				rx_t2lm->established_t2lm.t2lm.expected_duration;
1218 		}
1219 	} else if (rx_t2lm->established_t2lm.t2lm.expected_duration_present &&
1220 		   !rx_t2lm->established_t2lm.t2lm.mapping_switch_time_present) {
1221 		if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid,
1222 				 rx_t2lm->established_t2lm.t2lm.ieee_link_map_tid,
1223 				 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
1224 			t2lm_debug("T2LM mapping is already configured");
1225 			t2lm_dev_lock_release(t2lm_ctx);
1226 			return QDF_STATUS_E_ALREADY;
1227 		}
1228 
1229 		/* Mapping switch time is already expired when STA receives the
1230 		 * T2LM IE from beacon/probe response frame.
1231 		 */
1232 		qdf_mem_copy(&t2lm_ctx->established_t2lm.t2lm,
1233 			     &rx_t2lm->established_t2lm.t2lm,
1234 			     sizeof(struct wlan_t2lm_info));
1235 
1236 		/* Notify the registered caller about the link update*/
1237 		wlan_mlo_dev_t2lm_notify_link_update(vdev,
1238 					&t2lm_ctx->established_t2lm.t2lm);
1239 		wlan_clear_peer_level_tid_to_link_mapping(vdev);
1240 		wlan_send_tid_to_link_mapping(
1241 				vdev, &t2lm_ctx->established_t2lm.t2lm);
1242 	}
1243 
1244 	if (rx_t2lm->upcoming_t2lm.t2lm.mapping_switch_time_present) {
1245 		if (!qdf_mem_cmp(t2lm_ctx->established_t2lm.t2lm.ieee_link_map_tid,
1246 				 rx_t2lm->upcoming_t2lm.t2lm.ieee_link_map_tid,
1247 				 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS)) {
1248 			t2lm_debug("Ongoing mapping is already established");
1249 			t2lm_dev_lock_release(t2lm_ctx);
1250 			return QDF_STATUS_E_ALREADY;
1251 		}
1252 
1253 		qdf_mem_copy(&t2lm_ctx->upcoming_t2lm.t2lm,
1254 			     &rx_t2lm->upcoming_t2lm.t2lm,
1255 			     sizeof(struct wlan_t2lm_info));
1256 
1257 		ms_time = t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time;
1258 		/* Per test, -300ms is fine */
1259 		if (ms_time > tsf_bit25_10) {
1260 			t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time =
1261 				(ms_time - tsf_bit25_10 - (3 * WLAN_T2LM_MAPPING_SWITCH_TIME_DELAY));
1262 		} else {
1263 			t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time =
1264 				0xFFFF - (tsf_bit25_10 - ms_time) - (3 * WLAN_T2LM_MAPPING_SWITCH_TIME_DELAY);
1265 		}
1266 	}
1267 
1268 	t2lm_dev_lock_release(t2lm_ctx);
1269 
1270 	return QDF_STATUS_SUCCESS;
1271 }
1272 
1273 QDF_STATUS wlan_process_bcn_prbrsp_t2lm_ie(
1274 		struct wlan_objmgr_vdev *vdev,
1275 		struct wlan_t2lm_context *rx_t2lm_ie, uint64_t tsf)
1276 {
1277 	struct wlan_t2lm_context *t2lm_ctx;
1278 	QDF_STATUS status;
1279 	struct wlan_mlo_dev_context *mlo_dev_ctx;
1280 
1281 	/* Do not parse the T2LM IE if STA is not in connected state */
1282 	if (!wlan_cm_is_vdev_connected(vdev))
1283 		return QDF_STATUS_SUCCESS;
1284 
1285 	if (!vdev)
1286 		return QDF_STATUS_E_NULL_VALUE;
1287 
1288 	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
1289 	if (!mlo_dev_ctx)
1290 		return QDF_STATUS_E_NULL_VALUE;
1291 
1292 	t2lm_ctx = &mlo_dev_ctx->t2lm_ctx;
1293 
1294 	status = wlan_update_mapping_switch_time_expected_dur(
1295 			vdev, rx_t2lm_ie, tsf);
1296 	if (QDF_IS_STATUS_ERROR(status))
1297 		return status;
1298 
1299 	t2lm_dev_lock_acquire(t2lm_ctx);
1300 	if (t2lm_ctx->established_t2lm.t2lm.expected_duration_present ||
1301 	    t2lm_ctx->upcoming_t2lm.t2lm.mapping_switch_time_present) {
1302 		wlan_handle_t2lm_timer(vdev);
1303 	}
1304 	t2lm_dev_lock_release(t2lm_ctx);
1305 
1306 	return QDF_STATUS_SUCCESS;
1307 }
1308 
1309 int wlan_register_t2lm_link_update_notify_handler(
1310 		wlan_mlo_t2lm_link_update_handler handler,
1311 		struct wlan_mlo_dev_context *mldev)
1312 {
1313 	struct wlan_t2lm_context *t2lm_ctx = &mldev->t2lm_ctx;
1314 	int i;
1315 
1316 	for (i = 0; i < MAX_T2LM_HANDLERS; i++) {
1317 		if (t2lm_ctx->is_valid_handler[i])
1318 			continue;
1319 
1320 		t2lm_ctx->link_update_handler[i] = handler;
1321 		t2lm_ctx->is_valid_handler[i] = true;
1322 		break;
1323 	}
1324 
1325 	if (i == MAX_T2LM_HANDLERS) {
1326 		t2lm_err("Failed to register the link disablement callback");
1327 		return -EINVAL;
1328 	}
1329 
1330 	return i;
1331 }
1332 
1333 void wlan_unregister_t2lm_link_update_notify_handler(
1334 		struct wlan_mlo_dev_context *mldev,
1335 		uint8_t index)
1336 {
1337 	if (index >= MAX_T2LM_HANDLERS)
1338 		return;
1339 
1340 	mldev->t2lm_ctx.link_update_handler[index] = NULL;
1341 	mldev->t2lm_ctx.is_valid_handler[index] = false;
1342 }
1343 
1344 QDF_STATUS wlan_mlo_dev_t2lm_notify_link_update(
1345 		struct wlan_objmgr_vdev *vdev,
1346 		struct wlan_t2lm_info *t2lm)
1347 {
1348 	struct wlan_t2lm_context *t2lm_ctx;
1349 	wlan_mlo_t2lm_link_update_handler handler;
1350 	int i;
1351 
1352 	if (!vdev || !vdev->mlo_dev_ctx)
1353 		return QDF_STATUS_E_FAILURE;
1354 
1355 	if (!wlan_cm_is_vdev_connected(vdev)) {
1356 		t2lm_err("Not associated!");
1357 		return QDF_STATUS_E_AGAIN;
1358 	}
1359 
1360 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
1361 		t2lm_err("failed due to non-ML connection");
1362 		return QDF_STATUS_E_INVAL;
1363 	}
1364 
1365 	t2lm_ctx = &vdev->mlo_dev_ctx->t2lm_ctx;
1366 	for (i = 0; i < MAX_T2LM_HANDLERS; i++) {
1367 		if (!t2lm_ctx->is_valid_handler[i])
1368 			continue;
1369 
1370 		handler = t2lm_ctx->link_update_handler[i];
1371 		if (!handler)
1372 			continue;
1373 
1374 		handler(vdev, t2lm);
1375 	}
1376 	return QDF_STATUS_SUCCESS;
1377 }
1378 
1379 QDF_STATUS
1380 wlan_mlo_t2lm_timer_deinit(struct wlan_objmgr_vdev *vdev)
1381 {
1382 	struct wlan_t2lm_timer *t2lm_timer = NULL;
1383 
1384 	if (!vdev || !vdev->mlo_dev_ctx)
1385 		return QDF_STATUS_E_FAILURE;
1386 
1387 	t2lm_timer = &vdev->mlo_dev_ctx->t2lm_ctx.t2lm_timer;
1388 	if (!t2lm_timer) {
1389 		t2lm_err("t2lm timer ctx is null");
1390 		return QDF_STATUS_E_NULL_VALUE;
1391 	}
1392 
1393 	t2lm_dev_lock_acquire(&vdev->mlo_dev_ctx->t2lm_ctx);
1394 	t2lm_timer->timer_started = false;
1395 	t2lm_timer->timer_interval = 0;
1396 	t2lm_dev_lock_release(&vdev->mlo_dev_ctx->t2lm_ctx);
1397 	qdf_timer_free(&t2lm_timer->t2lm_timer);
1398 	t2lm_dev_lock_destroy(&vdev->mlo_dev_ctx->t2lm_ctx);
1399 	return QDF_STATUS_SUCCESS;
1400 }
1401 
1402 #if defined(WLAN_FEATURE_11BE_MLO_ADV_FEATURE) && defined(WLAN_FEATURE_11BE)
1403 QDF_STATUS
1404 wlan_mlo_link_disable_request_handler(struct wlan_objmgr_psoc *psoc,
1405 				      void *evt_params)
1406 {
1407 	struct wlan_objmgr_vdev *vdev;
1408 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1409 	uint8_t vdev_id;
1410 	bool is_connected = false;
1411 	struct mlo_link_disable_request_evt_params *params;
1412 
1413 	if (!psoc)
1414 		return QDF_STATUS_E_NULL_VALUE;
1415 
1416 	if (!evt_params) {
1417 		t2lm_err("event params is null");
1418 		return QDF_STATUS_E_NULL_VALUE;
1419 	}
1420 
1421 	params = (struct mlo_link_disable_request_evt_params *)evt_params;
1422 	if (qdf_is_macaddr_zero(&params->mld_addr)) {
1423 		t2lm_err("mld mac addr in event params is null");
1424 		return QDF_STATUS_E_NULL_VALUE;
1425 	}
1426 
1427 	if (!params->link_id_bitmap) {
1428 		t2lm_debug("Link id bitmap is 0, no action frame to be sent");
1429 		return QDF_STATUS_SUCCESS;
1430 	}
1431 
1432 	is_connected = wlan_get_connected_vdev_by_mld_addr(psoc,
1433 							   params->mld_addr.bytes,
1434 							   &vdev_id);
1435 	if (!is_connected) {
1436 		t2lm_err("Not connected to peer MLD " QDF_MAC_ADDR_FMT,
1437 			 params->mld_addr.bytes);
1438 		return QDF_STATUS_E_FAILURE;
1439 	}
1440 
1441 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
1442 						    WLAN_MLO_MGR_ID);
1443 	if (!vdev) {
1444 		t2lm_err("vdev is null");
1445 		return QDF_STATUS_E_NULL_VALUE;
1446 	}
1447 
1448 	status = wlan_populate_link_disable_t2lm_frame(vdev, params);
1449 
1450 	if (QDF_IS_STATUS_ERROR(status))
1451 		t2lm_err("Failed to handle link disable");
1452 
1453 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
1454 	return status;
1455 }
1456 #endif
1457 
1458