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