xref: /wlan-dirver/qcacld-3.0/core/hdd/src/wlan_hdd_mlo.c (revision 2b69562ed6480b642f0630f7cccca7ab5e47b699)
1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: wlan_hdd_mlo.c
20  *
21  * WLAN Host Device Driver file for 802.11be (Extremely High Throughput)
22  * support.
23  *
24  */
25 #include "wlan_hdd_main.h"
26 #include "wlan_hdd_mlo.h"
27 #include "osif_vdev_sync.h"
28 #include "wlan_osif_features.h"
29 #include "wlan_dp_ucfg_api.h"
30 #include "wlan_psoc_mlme_ucfg_api.h"
31 #include "wlan_osif_request_manager.h"
32 #include "wlan_hdd_object_manager.h"
33 #include <wlan_osif_priv.h>
34 
35 /*max time in ms, caller may wait for link state request get serviced */
36 #define WLAN_WAIT_TIME_LINK_STATE 3000
37 
38 #if defined(CFG80211_11BE_BASIC)
39 #ifndef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
40 #ifdef CFG80211_IFTYPE_MLO_LINK_SUPPORT
41 
42 static
43 void wlan_hdd_register_ml_link(struct hdd_adapter *sta_adapter,
44 			       struct hdd_adapter *link_adapter)
45 {
46 	int ret;
47 
48 	link_adapter->wdev.iftype = NL80211_IFTYPE_MLO_LINK;
49 	mutex_lock(&sta_adapter->wdev.mtx);
50 	ret = cfg80211_register_sta_mlo_link(&sta_adapter->wdev,
51 					     &link_adapter->wdev);
52 	mutex_unlock(&sta_adapter->wdev.mtx);
53 
54 	if (ret) {
55 		hdd_err("Failed to register ml link wdev %d", ret);
56 		return;
57 	}
58 }
59 
60 static
61 void wlan_hdd_unregister_ml_link(struct hdd_adapter *link_adapter,
62 				 bool rtnl_held)
63 {
64 	if (rtnl_held)
65 		rtnl_unlock();
66 
67 	cfg80211_unregister_wdev(&link_adapter->wdev);
68 
69 	if (rtnl_held)
70 		rtnl_lock();
71 }
72 #else
73 static
74 void wlan_hdd_register_ml_link(struct hdd_adapter *sta_adapter,
75 			       struct hdd_adapter *link_adapter)
76 {
77 }
78 
79 static
80 void wlan_hdd_unregister_ml_link(struct hdd_adapter *link_adapter,
81 				 bool rtnl_held)
82 {
83 }
84 #endif
85 
86 void hdd_register_wdev(struct hdd_adapter *sta_adapter,
87 		       struct hdd_adapter *link_adapter,
88 		       struct hdd_adapter_create_param *adapter_params)
89 {
90 	int  i;
91 
92 	hdd_enter_dev(sta_adapter->dev);
93 	/* Set the relation between adapters*/
94 	wlan_hdd_register_ml_link(sta_adapter, link_adapter);
95 	sta_adapter->mlo_adapter_info.is_ml_adapter = true;
96 	sta_adapter->mlo_adapter_info.is_link_adapter = false;
97 	link_adapter->mlo_adapter_info.is_link_adapter = true;
98 	link_adapter->mlo_adapter_info.is_ml_adapter = false;
99 	link_adapter->mlo_adapter_info.ml_adapter = sta_adapter;
100 	link_adapter->mlo_adapter_info.associate_with_ml_adapter =
101 				      adapter_params->associate_with_ml_adapter;
102 	qdf_set_bit(WDEV_ONLY_REGISTERED, &link_adapter->event_flags);
103 
104 	for (i = 0; i < WLAN_MAX_MLD; i++) {
105 		if (sta_adapter->mlo_adapter_info.link_adapter[i])
106 			continue;
107 		sta_adapter->mlo_adapter_info.link_adapter[i] = link_adapter;
108 		break;
109 	}
110 
111 	qdf_mem_copy(link_adapter->mld_addr.bytes, sta_adapter->mld_addr.bytes,
112 		     QDF_MAC_ADDR_SIZE);
113 	hdd_exit();
114 }
115 
116 static
117 void hdd_mlo_close_adapter(struct hdd_adapter *link_adapter, bool rtnl_held)
118 {
119 	struct osif_vdev_sync *vdev_sync;
120 
121 	vdev_sync = osif_vdev_sync_unregister(link_adapter->dev);
122 	if (vdev_sync)
123 		osif_vdev_sync_wait_for_ops(vdev_sync);
124 
125 	hdd_check_for_net_dev_ref_leak(link_adapter);
126 	policy_mgr_clear_concurrency_mode(link_adapter->hdd_ctx->psoc,
127 					  link_adapter->device_mode);
128 	link_adapter->wdev.netdev = NULL;
129 
130 	wlan_hdd_unregister_ml_link(link_adapter, rtnl_held);
131 	free_netdev(link_adapter->dev);
132 
133 	if (vdev_sync)
134 		osif_vdev_sync_destroy(vdev_sync);
135 }
136 
137 QDF_STATUS hdd_wlan_unregister_mlo_interfaces(struct hdd_adapter *adapter,
138 					      bool rtnl_held)
139 {
140 	int i;
141 	struct hdd_mlo_adapter_info *mlo_adapter_info;
142 	struct hdd_adapter *link_adapter;
143 
144 	mlo_adapter_info = &adapter->mlo_adapter_info;
145 
146 	if (mlo_adapter_info->is_link_adapter) {
147 		ucfg_dp_destroy_intf(adapter->hdd_ctx->psoc,
148 				     &adapter->mac_addr);
149 		hdd_remove_front_adapter(adapter->hdd_ctx, &adapter);
150 		return QDF_STATUS_E_AGAIN;
151 	}
152 
153 	for (i = 0; i < WLAN_MAX_MLD; i++) {
154 		link_adapter = mlo_adapter_info->link_adapter[i];
155 		if (!link_adapter)
156 			continue;
157 		hdd_cleanup_conn_info(link_adapter->deflink);
158 		ucfg_dp_destroy_intf(link_adapter->hdd_ctx->psoc,
159 				     &link_adapter->mac_addr);
160 		hdd_remove_adapter(link_adapter->hdd_ctx, link_adapter);
161 		hdd_mlo_close_adapter(link_adapter, rtnl_held);
162 	}
163 
164 	return QDF_STATUS_SUCCESS;
165 }
166 
167 void hdd_wlan_register_mlo_interfaces(struct hdd_context *hdd_ctx)
168 {
169 	int i = 0;
170 	QDF_STATUS status;
171 	struct hdd_adapter *ml_adapter;
172 	struct wlan_hdd_link_info *link_info;
173 	struct hdd_adapter_create_param params = {0};
174 	struct qdf_mac_addr link_addr[WLAN_MAX_ML_BSS_LINKS] = {0};
175 
176 	ml_adapter = hdd_get_ml_adapter(hdd_ctx);
177 	if (!ml_adapter)
178 		return;
179 
180 	status = hdd_derive_link_address_from_mld(hdd_ctx->psoc,
181 						  &ml_adapter->mld_addr,
182 						  &link_addr[0],
183 						  WLAN_MAX_ML_BSS_LINKS);
184 	if (QDF_IS_STATUS_ERROR(status))
185 		return;
186 
187 	/* if target supports MLO create a new dev */
188 	params.only_wdev_register = true;
189 	params.associate_with_ml_adapter = true;
190 	status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE, "null",
191 					   link_addr[0].bytes, &params);
192 	if (QDF_IS_STATUS_ERROR(status))
193 		hdd_err("Failed to register link adapter:%d", status);
194 
195 	qdf_mem_zero(&params, sizeof(params));
196 	params.only_wdev_register  = true;
197 	params.associate_with_ml_adapter = false;
198 	/* if target supports MLO create a new dev */
199 	status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE, "null",
200 					   link_addr[1].bytes, &params);
201 	if (QDF_IS_STATUS_ERROR(status)) {
202 		hdd_err("Failed to register link adapter:%d", status);
203 	} else {
204 		hdd_adapter_for_each_link_info(ml_adapter, link_info) {
205 			qdf_copy_macaddr(&link_info->link_addr,
206 					 &link_addr[i++]);
207 		}
208 	}
209 }
210 
211 void
212 hdd_adapter_set_sl_ml_adapter(struct hdd_adapter *adapter)
213 {
214 	adapter->mlo_adapter_info.is_single_link_ml = true;
215 }
216 
217 void
218 hdd_adapter_clear_sl_ml_adapter(struct hdd_adapter *adapter)
219 {
220 	adapter->mlo_adapter_info.is_single_link_ml = false;
221 }
222 
223 struct hdd_adapter *hdd_get_ml_adapter(struct hdd_context *hdd_ctx)
224 {
225 	struct hdd_adapter *adapter, *next_adapter = NULL;
226 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER_BY_VDEV;
227 
228 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
229 					   dbgid) {
230 		if (hdd_adapter_is_ml_adapter(adapter)) {
231 			hdd_adapter_dev_put_debug(adapter, dbgid);
232 			if (next_adapter)
233 				hdd_adapter_dev_put_debug(next_adapter,
234 							  dbgid);
235 			return adapter;
236 		}
237 		hdd_adapter_dev_put_debug(adapter, dbgid);
238 	}
239 
240 	return NULL;
241 }
242 #endif
243 
244 #ifndef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
245 void hdd_adapter_set_ml_adapter(struct hdd_adapter *adapter)
246 {
247 	adapter->mlo_adapter_info.is_ml_adapter = true;
248 	qdf_copy_macaddr(&adapter->mld_addr, &adapter->mac_addr);
249 }
250 #else
251 void hdd_adapter_set_ml_adapter(struct hdd_adapter *adapter)
252 {
253 	adapter->mlo_adapter_info.is_ml_adapter = true;
254 }
255 
256 static struct mlo_osif_ext_ops mlo_osif_ops = {
257 	.mlo_mgr_osif_update_bss_info = hdd_cm_save_connected_links_info,
258 	.mlo_mgr_osif_update_mac_addr = hdd_link_switch_vdev_mac_addr_update,
259 	.mlo_mgr_osif_link_switch_notification =
260 					hdd_adapter_link_switch_notification,
261 };
262 
263 QDF_STATUS hdd_mlo_mgr_register_osif_ops(void)
264 {
265 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
266 
267 	return wlan_mlo_mgr_register_osif_ext_ops(mlo_mgr_ctx, &mlo_osif_ops);
268 }
269 
270 QDF_STATUS hdd_mlo_mgr_unregister_osif_ops(void)
271 {
272 	struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx();
273 
274 	return wlan_mlo_mgr_unregister_osif_ext_ops(mlo_mgr_ctx);
275 }
276 
277 QDF_STATUS hdd_adapter_link_switch_notification(struct wlan_objmgr_vdev *vdev,
278 						uint8_t non_trans_vdev_id)
279 {
280 	bool found = false;
281 	struct hdd_adapter *adapter;
282 	struct vdev_osif_priv *osif_priv;
283 	struct wlan_hdd_link_info *link_info, *iter_link_info;
284 
285 	osif_priv = wlan_vdev_get_ospriv(vdev);
286 	if (!osif_priv) {
287 		hdd_err("Invalid osif priv");
288 		return QDF_STATUS_E_INVAL;
289 	}
290 
291 	link_info = osif_priv->legacy_osif_priv;
292 	adapter = link_info->adapter;
293 
294 	if (link_info->vdev_id != adapter->deflink->vdev_id) {
295 		hdd_err("Deflink VDEV %d not equals current VDEV %d",
296 			adapter->deflink->vdev_id, link_info->vdev_id);
297 		return QDF_STATUS_E_INVAL;
298 	}
299 
300 	hdd_adapter_for_each_link_info(adapter, iter_link_info) {
301 		if (non_trans_vdev_id == iter_link_info->vdev_id) {
302 			adapter->deflink = iter_link_info;
303 			found = true;
304 			break;
305 		}
306 	}
307 
308 	if (!found)
309 		return QDF_STATUS_E_FAILURE;
310 
311 	return QDF_STATUS_SUCCESS;
312 }
313 #endif
314 
315 void hdd_mlo_t2lm_register_callback(struct wlan_objmgr_vdev *vdev)
316 {
317 	if (!vdev || !vdev->mlo_dev_ctx)
318 		return;
319 
320 	wlan_register_t2lm_link_update_notify_handler(
321 			hdd_mlo_dev_t2lm_notify_link_update,
322 			vdev->mlo_dev_ctx);
323 }
324 
325 void hdd_mlo_t2lm_unregister_callback(struct wlan_objmgr_vdev *vdev)
326 {
327 	if (!vdev || !vdev->mlo_dev_ctx)
328 		return;
329 
330 	wlan_unregister_t2lm_link_update_notify_handler(vdev->mlo_dev_ctx, 0);
331 }
332 
333 QDF_STATUS hdd_derive_link_address_from_mld(struct wlan_objmgr_psoc *psoc,
334 					    struct qdf_mac_addr *mld_addr,
335 					    struct qdf_mac_addr *link_addr_list,
336 					    uint8_t max_idx)
337 {
338 	uint8_t last_byte, temp_byte, idx, start_idx = 0;
339 	struct qdf_mac_addr new_addr;
340 	struct qdf_mac_addr *link_addr;
341 
342 	if (!psoc || !mld_addr || !link_addr_list || !max_idx ||
343 	    max_idx > WLAN_MAX_ML_BSS_LINKS || qdf_is_macaddr_zero(mld_addr)) {
344 		hdd_err("Invalid values");
345 		return QDF_STATUS_E_INVAL;
346 	}
347 
348 	qdf_copy_macaddr(&new_addr, mld_addr);
349 	/* Set locally administered bit */
350 	new_addr.bytes[0] |= 0x02;
351 
352 	link_addr = link_addr_list;
353 	last_byte = mld_addr->bytes[5];
354 	hdd_debug("MLD addr: " QDF_MAC_ADDR_FMT,
355 		  QDF_MAC_ADDR_REF(mld_addr->bytes));
356 
357 	if (wlan_mlme_get_sta_same_link_mld_addr(psoc)) {
358 		qdf_copy_macaddr(link_addr, mld_addr);
359 		link_addr++;
360 		start_idx++;
361 	}
362 
363 	for (idx = start_idx; idx < max_idx; idx++) {
364 		temp_byte = ((last_byte >> 4 & INTF_MACADDR_MASK) + idx) &
365 			     INTF_MACADDR_MASK;
366 		new_addr.bytes[5] = last_byte + temp_byte;
367 		new_addr.bytes[5] ^= (1 << 7);
368 
369 		qdf_copy_macaddr(link_addr, &new_addr);
370 		link_addr++;
371 		hdd_debug("Derived link addr: " QDF_MAC_ADDR_FMT ", idx: %d",
372 			  QDF_MAC_ADDR_REF(new_addr.bytes), idx);
373 	}
374 
375 	return QDF_STATUS_SUCCESS;
376 }
377 
378 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
379 #ifdef WLAN_HDD_MULTI_VDEV_SINGLE_NDEV
380 static void hdd_adapter_restore_link_vdev_map(struct hdd_adapter *adapter)
381 {
382 	int i;
383 	unsigned long link_flags;
384 	uint8_t vdev_id, cur_link_idx, temp_link_idx;
385 	struct vdev_osif_priv *osif_priv;
386 	struct wlan_objmgr_vdev *vdev;
387 	struct wlan_hdd_link_info *temp_link_info, *link_info;
388 
389 	hdd_adapter_for_each_link_info(adapter, link_info) {
390 		cur_link_idx = hdd_adapter_get_index_of_link_info(link_info);
391 		/* If the current index matches the current pos in mapping
392 		 * then the link info is in same position
393 		 */
394 		if (adapter->curr_link_info_map[cur_link_idx] == cur_link_idx)
395 			continue;
396 
397 		/* Find the index where current link info is moved to perform
398 		 * VDEV info swap.
399 		 */
400 		for (i = cur_link_idx + 1; i < WLAN_MAX_ML_BSS_LINKS; i++) {
401 			if (adapter->curr_link_info_map[i] == cur_link_idx) {
402 				temp_link_idx = i;
403 				break;
404 			}
405 		}
406 
407 		if (i == WLAN_MAX_ML_BSS_LINKS)
408 			continue;
409 
410 		temp_link_info = &adapter->link_info[temp_link_idx];
411 
412 		/* Move VDEV info from current link info */
413 		qdf_spin_lock_bh(&temp_link_info->vdev_lock);
414 		vdev = temp_link_info->vdev;
415 		vdev_id = temp_link_info->vdev_id;
416 		temp_link_info->vdev = link_info->vdev;
417 		temp_link_info->vdev_id = link_info->vdev_id;
418 		qdf_spin_unlock_bh(&temp_link_info->vdev_lock);
419 
420 		/* Update VDEV-OSIF priv pointer to new link info. */
421 		if (temp_link_info->vdev) {
422 			osif_priv = wlan_vdev_get_ospriv(temp_link_info->vdev);
423 			if (osif_priv)
424 				osif_priv->legacy_osif_priv = temp_link_info;
425 		}
426 
427 		/* Fill current link info's actual VDEV info */
428 		qdf_spin_lock_bh(&link_info->vdev_lock);
429 		link_info->vdev = vdev;
430 		link_info->vdev_id = vdev_id;
431 		qdf_spin_unlock_bh(&link_info->vdev_lock);
432 
433 		/* Update VDEV-OSIF priv pointer to new link info. */
434 		if (link_info->vdev) {
435 			osif_priv = wlan_vdev_get_ospriv(link_info->vdev);
436 			if (osif_priv)
437 				osif_priv->legacy_osif_priv = link_info;
438 		}
439 
440 		/* Swap link flags */
441 		link_flags = temp_link_info->link_flags;
442 		temp_link_info->link_flags = link_info->link_flags;
443 		link_info->link_flags = link_flags;
444 
445 		/* Update the mapping, current link info's mapping will be
446 		 * set to be proper.
447 		 */
448 		adapter->curr_link_info_map[temp_link_idx] =
449 				adapter->curr_link_info_map[cur_link_idx];
450 		adapter->curr_link_info_map[cur_link_idx] = cur_link_idx;
451 	}
452 	hdd_adapter_disable_all_links(adapter);
453 }
454 
455 int hdd_update_vdev_mac_address(struct hdd_adapter *adapter,
456 				struct qdf_mac_addr mac_addr)
457 {
458 	int idx, i, ret = 0;
459 	bool update_self_peer;
460 	QDF_STATUS status;
461 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
462 	struct wlan_hdd_link_info *link_info;
463 	uint8_t *addr_list[WLAN_MAX_ML_BSS_LINKS + 1] = {0};
464 	struct qdf_mac_addr link_addrs[WLAN_MAX_ML_BSS_LINKS] = {0};
465 
466 	/* This API is only called with is ml adapter set for STA mode adapter.
467 	 * For SAP mode, hdd_hostapd_set_mac_address() is the entry point for
468 	 * MAC address update.
469 	 */
470 
471 	if (!hdd_adapter_is_ml_adapter(adapter)) {
472 		struct qdf_mac_addr mld_addr = QDF_MAC_ADDR_ZERO_INIT;
473 
474 		ret = hdd_dynamic_mac_address_set(adapter->deflink, mac_addr,
475 						  mld_addr, true);
476 		return ret;
477 	}
478 
479 	status = hdd_derive_link_address_from_mld(hdd_ctx->psoc,
480 						  &mac_addr, &link_addrs[0],
481 						  WLAN_MAX_ML_BSS_LINKS);
482 
483 	if (QDF_IS_STATUS_ERROR(status))
484 		return qdf_status_to_os_return(status);
485 
486 	hdd_adapter_restore_link_vdev_map(adapter);
487 
488 	i = 0;
489 	hdd_adapter_for_each_active_link_info(adapter, link_info) {
490 		idx = hdd_adapter_get_index_of_link_info(link_info);
491 		addr_list[i++] = &link_addrs[idx].bytes[0];
492 	}
493 
494 	status = sme_check_for_duplicate_session(hdd_ctx->mac_handle,
495 						 &addr_list[0]);
496 	if (QDF_IS_STATUS_ERROR(status))
497 		return qdf_status_to_os_return(status);
498 
499 	i = 0;
500 	hdd_adapter_for_each_link_info(adapter, link_info)
501 		qdf_copy_macaddr(&link_info->link_addr, &link_addrs[i++]);
502 
503 	hdd_adapter_for_each_active_link_info(adapter, link_info) {
504 		idx = hdd_adapter_get_index_of_link_info(link_info);
505 		update_self_peer =
506 			(link_info == adapter->deflink) ? true : false;
507 		ret = hdd_dynamic_mac_address_set(link_info, link_addrs[idx],
508 						  mac_addr, update_self_peer);
509 		if (ret)
510 			return ret;
511 
512 		qdf_copy_macaddr(&link_info->link_addr, &link_addrs[idx]);
513 	}
514 
515 	hdd_adapter_update_mlo_mgr_mac_addr(adapter);
516 	return ret;
517 }
518 #else
519 int hdd_update_vdev_mac_address(struct hdd_adapter *adapter,
520 				struct qdf_mac_addr mac_addr)
521 {
522 	int i, ret = 0;
523 	QDF_STATUS status;
524 	bool eht_capab, update_self_peer;
525 	struct hdd_adapter *link_adapter;
526 	struct hdd_mlo_adapter_info *mlo_adapter_info;
527 	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
528 	uint8_t *addr_list[WLAN_MAX_MLD + 1] = {0};
529 	struct qdf_mac_addr link_addrs[WLAN_MAX_ML_BSS_LINKS] = {0};
530 
531 	/* This API is only called with is ml adapter set for STA mode adapter.
532 	 * For SAP mode, hdd_hostapd_set_mac_address() is the entry point for
533 	 * MAC address update.
534 	 */
535 	ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
536 	if (!(eht_capab && hdd_adapter_is_ml_adapter(adapter))) {
537 		struct qdf_mac_addr mld_addr = QDF_MAC_ADDR_ZERO_INIT;
538 
539 		ret = hdd_dynamic_mac_address_set(adapter->deflink, mac_addr,
540 						  mld_addr, true);
541 		return ret;
542 	}
543 
544 	status = hdd_derive_link_address_from_mld(hdd_ctx->psoc,
545 						  &mac_addr, &link_addrs[0],
546 						  WLAN_MAX_ML_BSS_LINKS);
547 
548 	if (QDF_IS_STATUS_ERROR(status))
549 		return qdf_status_to_os_return(status);
550 
551 	for (i = 0; i < WLAN_MAX_MLD; i++)
552 		addr_list[i] = &link_addrs[i].bytes[0];
553 
554 	status = sme_check_for_duplicate_session(hdd_ctx->mac_handle,
555 						 &addr_list[0]);
556 	if (QDF_IS_STATUS_ERROR(status))
557 		return qdf_status_to_os_return(status);
558 
559 	mlo_adapter_info = &adapter->mlo_adapter_info;
560 	for (i = 0; i < WLAN_MAX_MLD; i++) {
561 		link_adapter = mlo_adapter_info->link_adapter[i];
562 		if (!link_adapter)
563 			continue;
564 
565 		if (hdd_adapter_is_associated_with_ml_adapter(link_adapter))
566 			update_self_peer = true;
567 		else
568 			update_self_peer = false;
569 
570 		ret = hdd_dynamic_mac_address_set(link_adapter->deflink,
571 						  link_addrs[i], mac_addr,
572 						  update_self_peer);
573 		if (ret)
574 			return ret;
575 
576 		/* Update DP intf and new link address in link adapter
577 		 */
578 		ucfg_dp_update_intf_mac(hdd_ctx->psoc, &link_adapter->mac_addr,
579 					&link_addrs[i],
580 					link_adapter->deflink->vdev);
581 		qdf_copy_macaddr(&link_adapter->mac_addr, &link_addrs[i]);
582 		qdf_copy_macaddr(&adapter->link_info[i].link_addr,
583 				 &link_addrs[i]);
584 	}
585 
586 	qdf_copy_macaddr(&adapter->link_info[i].link_addr, &link_addrs[i]);
587 	hdd_adapter_update_mlo_mgr_mac_addr(adapter);
588 
589 	return ret;
590 }
591 #endif
592 #endif /* WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE */
593 
594 const struct nla_policy
595 ml_link_state_config_policy [QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_MAX + 1] = {
596 	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID] =  {.type = NLA_U8},
597 	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE] =    {.type = NLA_U32},
598 };
599 
600 const struct nla_policy
601 ml_link_state_request_policy[QCA_WLAN_VENDOR_ATTR_LINK_STATE_MAX + 1] = {
602 	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_OP_TYPE] = {.type = NLA_U32},
603 	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE] = {.type = NLA_U32},
604 	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG] = {.type = NLA_NESTED},
605 	[QCA_WLAN_VENDOR_ATTR_LINK_STATE_MIXED_MODE_ACTIVE_NUM_LINKS] = {
606 							.type = NLA_U8},
607 };
608 
609 static int
610 __wlan_hdd_cfg80211_process_ml_link_state(struct wiphy *wiphy,
611 					  struct wireless_dev *wdev,
612 					  const void *data, int data_len)
613 {
614 	int ret = 0;
615 	struct net_device *dev = wdev->netdev;
616 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
617 	struct wlan_objmgr_vdev *vdev;
618 	struct hdd_context *hdd_ctx = NULL;
619 
620 	hdd_enter_dev(wdev->netdev);
621 
622 	if (hdd_validate_adapter(adapter))
623 		return -EINVAL;
624 
625 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
626 	if (!hdd_ctx)
627 		return -EINVAL;
628 
629 	if (adapter->device_mode != QDF_STA_MODE)
630 		return -EINVAL;
631 
632 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
633 
634 	if (!vdev)
635 		return -EINVAL;
636 
637 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
638 		goto release_ref;
639 
640 	ret = wlan_handle_mlo_link_state_operation(adapter, wiphy, vdev,
641 						   hdd_ctx, data, data_len);
642 
643 release_ref:
644 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
645 
646 	return ret;
647 }
648 
649 int wlan_hdd_cfg80211_process_ml_link_state(struct wiphy *wiphy,
650 					    struct wireless_dev *wdev,
651 					    const void *data, int data_len)
652 {
653 	int errno;
654 	struct osif_vdev_sync *vdev_sync;
655 
656 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
657 	if (errno)
658 		return errno;
659 
660 	errno = __wlan_hdd_cfg80211_process_ml_link_state(wiphy, wdev, data,
661 							  data_len);
662 
663 	osif_vdev_sync_op_stop(vdev_sync);
664 
665 	return errno;
666 }
667 
668 static inline void ml_link_state_resp_cb(struct ml_link_state_info_event *ev,
669 					 void *cookie)
670 {
671 	struct ml_link_state_info_event *priv;
672 	struct osif_request *request;
673 
674 	request = osif_request_get(cookie);
675 
676 	if (!request) {
677 		hdd_err("Obsolete request");
678 		return;
679 	}
680 
681 	priv = osif_request_priv(request);
682 
683 	qdf_mem_copy(priv, ev, sizeof(*priv));
684 	osif_request_complete(request);
685 	osif_request_put(request);
686 }
687 
688 static uint32_t
689 hdd_get_ml_link_state_response_len(const struct ml_link_state_info_event *event)
690 {
691 	uint32_t len = 0;
692 	uint32_t info_len = 0;
693 
694 	len = NLMSG_HDRLEN;
695 	/* QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE */
696 	len += NLA_HDRLEN + sizeof(u32);
697 
698 	/* QCA_WLAN_VENDOR_ATTR_LINK_STATE_OPERATION_MODE */
699 	len += NLA_HDRLEN + sizeof(u32);
700 
701 	/* nest */
702 	info_len = NLA_HDRLEN;
703 	/* QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID */
704 	info_len += NLA_HDRLEN + sizeof(u8);
705 	/* QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE */
706 	info_len += NLA_HDRLEN + sizeof(u32);
707 
708 	/* QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG */
709 	len += NLA_HDRLEN + (info_len * event->num_mlo_vdev_link_info);
710 
711 	return len;
712 }
713 
714 static int
715 hdd_ml_generate_link_state_resp_nlmsg(struct sk_buff *skb,
716 				      struct wlan_objmgr_psoc *psoc,
717 				      struct ml_link_state_info_event *params,
718 				      uint32_t num_link_info)
719 {
720 	struct nlattr *nla_config_attr, *nla_config_params;
721 	uint32_t i = 0, attr;
722 	int errno;
723 	uint32_t value;
724 
725 	attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE;
726 	value = ucfg_mlme_get_ml_link_control_mode(psoc, params->vdev_id);
727 	errno = nla_put_u32(skb, attr, value);
728 	if (errno)
729 		return errno;
730 
731 	attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_OPERATION_MODE;
732 
733 	/* Default link state operation mode is only supported */
734 	value = QCA_WLAN_VENDOR_LINK_STATE_OPERATION_MODE_DEFAULT;
735 	errno = nla_put_u32(skb, attr, value);
736 	if (errno)
737 		return errno;
738 
739 	attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG;
740 	nla_config_attr = nla_nest_start(skb, attr);
741 
742 	if (!nla_config_attr)
743 		return -EINVAL;
744 
745 	for (i = 0; i < num_link_info; i++) {
746 		nla_config_params = nla_nest_start(skb, attr);
747 		if (!nla_config_params)
748 			return -EINVAL;
749 
750 		attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID;
751 		value = params->link_info[i].link_id;
752 		errno = nla_put_u8(skb, attr, value);
753 		if (errno)
754 			return errno;
755 
756 		attr = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE;
757 		value = params->link_info[i].link_status;
758 		errno = nla_put_u32(skb, attr, value);
759 
760 		if (errno)
761 			return errno;
762 
763 		nla_nest_end(skb, nla_config_params);
764 	}
765 
766 	nla_nest_end(skb, nla_config_attr);
767 
768 	return 0;
769 }
770 
771 static char *link_state_status_id_to_str(uint32_t status)
772 {
773 	switch (status) {
774 	case WLAN_LINK_INFO_EVENT_SUCCESS:
775 		return "LINK_INFO_EVENT_SUCCESS";
776 	case WLAN_LINK_INFO_EVENT_REJECT_FAILURE:
777 		return "LINK_INFO_EVENT_REJECT_FAILURE";
778 	case WLAN_LINK_INFO_EVENT_REJECT_VDEV_NOT_UP:
779 		return "LINK_INFO_EVENT_REJECT_VDEV_NOT_UP";
780 	case WLAN_LINK_INFO_EVENT_REJECT_ROAMING_IN_PROGRESS:
781 		return "LINK_INFO_EVENT_REJECT_ROAMING_IN_PROGRESS";
782 	case WLAN_LINK_INFO_EVENT_REJECT_NON_MLO_CONNECTION:
783 		return "LINK_INFO_EVENT_REJECT_NON_MLO_CONNECTION";
784 	}
785 	return "Undefined link state status ID";
786 }
787 
788 static bool
789 wlan_hdd_link_state_request_needed(struct hdd_adapter *adapter)
790 {
791 	qdf_time_t link_state_cached_duration = 0;
792 
793 	link_state_cached_duration =
794 				qdf_system_ticks_to_msecs(qdf_system_ticks()) -
795 				adapter->link_state_cached_timestamp;
796 	if (link_state_cached_duration <=
797 		adapter->hdd_ctx->config->link_state_cache_expiry_time)
798 		return false;
799 
800 	return true;
801 }
802 
803 #ifdef WLAN_FEATURE_11BE_MLO
804 
805 void hdd_update_link_state_cached_timestamp(struct hdd_adapter *adapter)
806 {
807 	adapter->link_state_cached_timestamp =
808 		qdf_system_ticks_to_msecs(qdf_system_ticks());
809 }
810 #endif /* WLAN_FEATURE_11BE_MLO */
811 
812 static QDF_STATUS
813 wlan_hdd_cached_link_state_request(struct hdd_adapter *adapter,
814 				   struct wiphy *wiphy,
815 				   struct wlan_objmgr_psoc *psoc,
816 				   struct wlan_objmgr_vdev *vdev)
817 {
818 	QDF_STATUS status = QDF_STATUS_E_INVAL;
819 	struct ml_link_state_info_event link_state_event = {0};
820 	struct wlan_hdd_link_info *link_info;
821 	struct hdd_station_ctx *sta_ctx;
822 	int skb_len;
823 	struct sk_buff *reply_skb = NULL;
824 	int errno;
825 	struct qdf_mac_addr *mld_addr;
826 	uint8_t link_iter = 0;
827 	struct mlo_link_info *ml_link_info;
828 	struct wlan_mlo_dev_context *mlo_ctx;
829 
830 	mlo_ctx = vdev->mlo_dev_ctx;
831 	if (!mlo_ctx) {
832 		hdd_err("null mlo_dev_ctx");
833 		return -EINVAL;
834 	}
835 
836 	hdd_adapter_for_each_link_info(adapter, link_info) {
837 
838 		if (link_iter >= WLAN_MAX_ML_BSS_LINKS) {
839 			hdd_err("Invalid number of link info");
840 			return -EINVAL;
841 		}
842 
843 		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
844 		link_state_event.link_info[link_iter].link_id =
845 				sta_ctx->conn_info.ieee_link_id;
846 		link_state_event.link_info[link_iter].vdev_id =
847 				link_info->vdev_id;
848 		link_state_event.link_info[link_iter].chan_freq =
849 				sta_ctx->ch_info.freq;
850 
851 		if (sta_ctx->conn_info.ieee_link_id == WLAN_INVALID_LINK_ID)
852 			continue;
853 
854 		ml_link_info = mlo_mgr_get_ap_link_by_link_id(
855 				mlo_ctx,
856 				sta_ctx->conn_info.ieee_link_id);
857 		if (!ml_link_info) {
858 			hdd_debug("link: %d info does not exist",
859 				  sta_ctx->conn_info.ieee_link_id);
860 			return -EINVAL;
861 		}
862 
863 		link_state_event.link_info[link_iter].link_status =
864 			ml_link_info->is_link_active;
865 
866 		link_iter++;
867 
868 		hdd_debug_rl("vdev id %d sta_ctx->conn_info.ieee_link_id %d is_mlo_vdev_active %d ",
869 			     link_info->vdev_id, sta_ctx->conn_info.ieee_link_id,
870 			     ml_link_info->is_link_active);
871 	}
872 
873 	link_state_event.num_mlo_vdev_link_info = link_iter;
874 	link_state_event.vdev_id = wlan_vdev_get_id(vdev);
875 	link_state_event.status = 0;
876 	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
877 	link_state_event.mldaddr = *mld_addr;
878 
879 	hdd_debug_rl("cached link_state_resp: vdev id %d status %d num %d MAC addr " QDF_MAC_ADDR_FMT,
880 		     link_state_event.vdev_id, link_state_event.status,
881 		     link_state_event.num_mlo_vdev_link_info,
882 		     QDF_MAC_ADDR_REF(link_state_event.mldaddr.bytes));
883 
884 	skb_len = hdd_get_ml_link_state_response_len(&link_state_event);
885 
886 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
887 	if (!reply_skb) {
888 		hdd_err("Get stats - alloc reply_skb failed");
889 		status = QDF_STATUS_E_NOMEM;
890 		return status;
891 	}
892 
893 	status = hdd_ml_generate_link_state_resp_nlmsg(
894 			reply_skb, psoc, &link_state_event,
895 			link_state_event.num_mlo_vdev_link_info);
896 	if (QDF_IS_STATUS_ERROR(status)) {
897 		hdd_err("Failed to pack nl response");
898 		goto free_skb;
899 	}
900 
901 	errno = wlan_cfg80211_vendor_cmd_reply(reply_skb);
902 
903 	return qdf_status_from_os_return(errno);
904 
905 free_skb:
906 	wlan_cfg80211_vendor_free_skb(reply_skb);
907 	return QDF_STATUS_SUCCESS;
908 }
909 
910 static QDF_STATUS wlan_hdd_link_state_request(struct hdd_adapter *adapter,
911 					      struct wiphy *wiphy,
912 					      struct wlan_objmgr_psoc *psoc,
913 					      struct wlan_objmgr_vdev *vdev)
914 {
915 	int errno;
916 	int skb_len;
917 	struct sk_buff *reply_skb = NULL;
918 	QDF_STATUS status = QDF_STATUS_E_INVAL;
919 	void *cookie;
920 	struct ml_link_state_info_event *link_state_event = NULL;
921 	struct osif_request *request;
922 	struct ml_link_state_cmd_info info = {0};
923 	int num_info = 0;
924 	static const struct osif_request_params params = {
925 		.priv_size = sizeof(*link_state_event),
926 		.timeout_ms = WLAN_WAIT_TIME_LINK_STATE,
927 		.dealloc = NULL,
928 	};
929 
930 	if (!wiphy || !vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev))
931 		return status;
932 
933 	if (adapter->device_mode != QDF_STA_MODE)
934 		return QDF_STATUS_SUCCESS;
935 
936 	if (!wlan_hdd_link_state_request_needed(adapter)) {
937 		hdd_debug_rl("sending cached link state request");
938 		status = wlan_hdd_cached_link_state_request(adapter, wiphy,
939 							    psoc, vdev);
940 		return status;
941 	}
942 
943 	request = osif_request_alloc(&params);
944 	if (!request)
945 		return QDF_STATUS_E_NOMEM;
946 
947 	cookie = osif_request_cookie(request);
948 	link_state_event = osif_request_priv(request);
949 
950 	info.request_cookie = cookie;
951 	info.ml_link_state_resp_cb = ml_link_state_resp_cb;
952 
953 	status = mlo_get_link_state_register_resp_cb(vdev,
954 						     &info);
955 	if (QDF_IS_STATUS_ERROR(status)) {
956 		hdd_err("Failed to register resp callback: %d", status);
957 		status = qdf_status_to_os_return(status);
958 		goto free_event;
959 	}
960 
961 	status = ml_post_get_link_state_msg(vdev);
962 	if (QDF_IS_STATUS_ERROR(status)) {
963 		hdd_err("Failed to post scheduler msg");
964 		goto free_event;
965 	}
966 
967 	status = osif_request_wait_for_response(request);
968 	if (status) {
969 		hdd_err("wait failed or timed out ret: %d", status);
970 		goto free_event;
971 	}
972 
973 	hdd_debug("ml_link_state_resp: vdev id %d status %d num %d MAC addr " QDF_MAC_ADDR_FMT,
974 		  link_state_event->vdev_id, link_state_event->status,
975 		  link_state_event->num_mlo_vdev_link_info,
976 		  QDF_MAC_ADDR_REF(link_state_event->mldaddr.bytes));
977 
978 	if (QDF_IS_STATUS_ERROR(link_state_event->status)) {
979 		hdd_debug("ml_link_state_status failed %s",
980 			  link_state_status_id_to_str(link_state_event->status));
981 		goto free_event;
982 	}
983 
984 	for (num_info = 0; num_info < link_state_event->num_mlo_vdev_link_info;
985 	     num_info++) {
986 		hdd_debug("ml_link_state_resp: chan_freq %d vdev_id %d link_id %d link_status %d",
987 			  link_state_event->link_info[num_info].chan_freq,
988 			  link_state_event->link_info[num_info].vdev_id,
989 			  link_state_event->link_info[num_info].link_id,
990 			  link_state_event->link_info[num_info].link_status);
991 	}
992 
993 	hdd_update_link_state_cached_timestamp(adapter);
994 
995 	skb_len = hdd_get_ml_link_state_response_len(link_state_event);
996 
997 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(
998 						wiphy,
999 						skb_len);
1000 	if (!reply_skb) {
1001 		hdd_err("Get stats - alloc reply_skb failed");
1002 		status = QDF_STATUS_E_NOMEM;
1003 		goto free_event;
1004 	}
1005 
1006 	status = hdd_ml_generate_link_state_resp_nlmsg(
1007 			reply_skb, psoc, link_state_event,
1008 			link_state_event->num_mlo_vdev_link_info);
1009 	if (QDF_IS_STATUS_ERROR(status)) {
1010 		hdd_err("Failed to pack nl response");
1011 		goto free_skb;
1012 	}
1013 
1014 	osif_request_put(request);
1015 
1016 	errno = wlan_cfg80211_vendor_cmd_reply(reply_skb);
1017 
1018 	return qdf_status_from_os_return(errno);
1019 
1020 free_skb:
1021 	wlan_cfg80211_vendor_free_skb(reply_skb);
1022 free_event:
1023 	osif_request_put(request);
1024 
1025 	return status;
1026 }
1027 
1028 #define MLD_MAX_SUPPORTED_LINKS 2
1029 
1030 int wlan_handle_mlo_link_state_operation(struct hdd_adapter *adapter,
1031 					 struct wiphy *wiphy,
1032 					 struct wlan_objmgr_vdev *vdev,
1033 					 struct hdd_context *hdd_ctx,
1034 					 const void *data, int data_len)
1035 {
1036 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_LINK_STATE_MAX + 1];
1037 	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_MAX + 1];
1038 	enum qca_wlan_vendor_link_state_op_types ml_link_op;
1039 	struct nlattr *link_oper_attr, *mode_attr, *curr_attr, *num_link_attr;
1040 	int rem_len = 0, rc;
1041 	uint32_t attr_id, ml_config_state;
1042 	uint8_t ml_active_num_links, ml_link_control_mode;
1043 	uint8_t ml_config_link_id, num_links = 0;
1044 	uint8_t vdev_id = vdev->vdev_objmgr.vdev_id;
1045 	uint8_t link_id_list[MLD_MAX_SUPPORTED_LINKS] = {0};
1046 	uint32_t config_state_list[MLD_MAX_SUPPORTED_LINKS] = {0};
1047 	QDF_STATUS status;
1048 
1049 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_LINK_STATE_MAX,
1050 				    data, data_len,
1051 				    ml_link_state_request_policy)) {
1052 		hdd_debug("vdev %d: invalid mlo link state attr", vdev_id);
1053 		return -EINVAL;
1054 	}
1055 
1056 	attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_OP_TYPE;
1057 	link_oper_attr = tb[attr_id];
1058 	if (!link_oper_attr) {
1059 		hdd_debug("vdev %d: link state op not specified", vdev_id);
1060 		return -EINVAL;
1061 	}
1062 	ml_link_op = nla_get_u8(link_oper_attr);
1063 	switch (ml_link_op) {
1064 	case QCA_WLAN_VENDOR_LINK_STATE_OP_GET:
1065 		status = wlan_hdd_link_state_request(adapter, wiphy,
1066 						     hdd_ctx->psoc, vdev);
1067 		return qdf_status_to_os_return(status);
1068 	case QCA_WLAN_VENDOR_LINK_STATE_OP_SET:
1069 		if (policy_mgr_is_set_link_in_progress(hdd_ctx->psoc)) {
1070 			hdd_debug("vdev %d: change link already in progress",
1071 				  vdev_id);
1072 			return -EBUSY;
1073 		}
1074 
1075 		break;
1076 	default:
1077 		hdd_debug("vdev %d: Invalid op type:%d", vdev_id, ml_link_op);
1078 		return -EINVAL;
1079 	}
1080 
1081 	attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONTROL_MODE;
1082 	mode_attr = tb[attr_id];
1083 	if (!mode_attr) {
1084 		hdd_debug("vdev %d: ml links control mode attr not present",
1085 			  vdev_id);
1086 		return -EINVAL;
1087 	}
1088 	ml_link_control_mode = nla_get_u8(mode_attr);
1089 
1090 	switch (ml_link_control_mode) {
1091 	case QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_DEFAULT:
1092 		/* clear mlo link(s) settings in fw as per driver */
1093 		status = policy_mgr_clear_ml_links_settings_in_fw(hdd_ctx->psoc,
1094 								  vdev_id);
1095 		if (QDF_IS_STATUS_ERROR(status))
1096 			return -EINVAL;
1097 		break;
1098 	case QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_USER:
1099 		attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG;
1100 		if (!tb[attr_id]) {
1101 			hdd_debug("vdev %d: state config attr not present",
1102 				  vdev_id);
1103 			return -EINVAL;
1104 		}
1105 
1106 		nla_for_each_nested(curr_attr, tb[attr_id], rem_len) {
1107 			rc = wlan_cfg80211_nla_parse_nested(
1108 				tb2, QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_MAX,
1109 				curr_attr,
1110 				ml_link_state_config_policy);
1111 			if (rc) {
1112 				hdd_debug("vdev %d: nested attr not present",
1113 					     vdev_id);
1114 				return -EINVAL;
1115 			}
1116 
1117 			attr_id =
1118 				QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_LINK_ID;
1119 			if (!tb2[attr_id]) {
1120 				hdd_debug("vdev %d: link id attr not present",
1121 					  vdev_id);
1122 				return -EINVAL;
1123 			}
1124 
1125 			ml_config_link_id = nla_get_u8(tb2[attr_id]);
1126 
1127 			attr_id = QCA_WLAN_VENDOR_ATTR_LINK_STATE_CONFIG_STATE;
1128 			if (!tb2[attr_id]) {
1129 				hdd_debug("vdev %d: config attr not present",
1130 					  vdev_id);
1131 				return -EINVAL;
1132 			}
1133 
1134 			ml_config_state = nla_get_u32(tb2[attr_id]);
1135 			hdd_debug("vdev %d: ml_link_id %d, ml_link_state:%d",
1136 				  vdev_id, ml_config_link_id, ml_config_state);
1137 			link_id_list[num_links] = ml_config_link_id;
1138 			config_state_list[num_links] = ml_config_state;
1139 			num_links++;
1140 
1141 			if (num_links >= MLD_MAX_SUPPORTED_LINKS)
1142 				break;
1143 		}
1144 
1145 		status = policy_mgr_update_mlo_links_based_on_linkid(
1146 						hdd_ctx->psoc,
1147 						vdev_id, num_links,
1148 						link_id_list,
1149 						config_state_list);
1150 		if (QDF_IS_STATUS_ERROR(status))
1151 			return -EINVAL;
1152 		break;
1153 	case QCA_WLAN_VENDOR_LINK_STATE_CONTROL_MODE_MIXED:
1154 		attr_id =
1155 		   QCA_WLAN_VENDOR_ATTR_LINK_STATE_MIXED_MODE_ACTIVE_NUM_LINKS;
1156 		num_link_attr = tb[attr_id];
1157 		if (!num_link_attr) {
1158 			hdd_debug("number of active state links not specified");
1159 			return -EINVAL;
1160 		}
1161 		ml_active_num_links = nla_get_u8(num_link_attr);
1162 		hdd_debug("vdev %d: ml_active_num_links: %d", vdev_id,
1163 			  ml_active_num_links);
1164 		if (ml_active_num_links > MLD_MAX_SUPPORTED_LINKS)
1165 			return -EINVAL;
1166 		status = policy_mgr_update_active_mlo_num_links(hdd_ctx->psoc,
1167 						vdev_id, ml_active_num_links);
1168 		if (QDF_IS_STATUS_ERROR(status))
1169 			return -EINVAL;
1170 		break;
1171 	default:
1172 		hdd_debug("vdev %d: invalid ml_link_control_mode: %d", vdev_id,
1173 			  ml_link_control_mode);
1174 		return -EINVAL;
1175 	}
1176 
1177 	ucfg_mlme_set_ml_link_control_mode(hdd_ctx->psoc, vdev_id,
1178 					   ml_link_control_mode);
1179 
1180 	hdd_debug("vdev: %d, processed link state command successfully",
1181 		  vdev_id);
1182 	return 0;
1183 }
1184 
1185 static uint32_t
1186 hdd_get_t2lm_setup_event_len(void)
1187 {
1188 	uint32_t len = 0;
1189 	uint32_t info_len = 0;
1190 
1191 	len = NLMSG_HDRLEN;
1192 
1193 	/* QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AP_MLD_ADDR */
1194 	len += nla_total_size(QDF_MAC_ADDR_SIZE);
1195 
1196 	/* nest */
1197 	info_len = NLA_HDRLEN;
1198 	/* QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK */
1199 	info_len += NLA_HDRLEN + sizeof(u16);
1200 	/* QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK */
1201 	info_len += NLA_HDRLEN + sizeof(u16);
1202 
1203 	/* QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS */
1204 	len += NLA_HDRLEN + (info_len * T2LM_MAX_NUM_TIDS);
1205 
1206 	return len;
1207 }
1208 
1209 static QDF_STATUS
1210 hdd_t2lm_pack_nl_response(struct sk_buff *skb,
1211 			  struct wlan_objmgr_vdev *vdev,
1212 			  struct wlan_t2lm_info *t2lm,
1213 			  struct qdf_mac_addr mld_addr)
1214 {
1215 	struct nlattr *config_attr, *config_params;
1216 	uint32_t i = 0, attr, attr1;
1217 	int errno;
1218 	uint32_t value;
1219 	uint8_t tid_num;
1220 
1221 	attr = QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_AP_MLD_ADDR;
1222 	if (nla_put(skb, attr, QDF_MAC_ADDR_SIZE, mld_addr.bytes)) {
1223 		hdd_err("Failed to put mac_addr");
1224 		return QDF_STATUS_E_INVAL;
1225 	}
1226 
1227 	if (t2lm->default_link_mapping) {
1228 		hdd_debug("update mld addr for default mapping");
1229 		return QDF_STATUS_SUCCESS;
1230 	}
1231 
1232 	attr = QCA_WLAN_VENDOR_ATTR_TID_TO_LINK_MAP_STATUS;
1233 	config_attr = nla_nest_start(skb, attr);
1234 	if (!config_attr) {
1235 		hdd_err("nla_nest_start error");
1236 		return QDF_STATUS_E_INVAL;
1237 	}
1238 
1239 	switch (t2lm->direction) {
1240 	case WLAN_T2LM_UL_DIRECTION:
1241 		for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
1242 			config_params = nla_nest_start(skb, tid_num + 1);
1243 			if (!config_params)
1244 				return -EINVAL;
1245 
1246 			attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK;
1247 			value = t2lm->ieee_link_map_tid[i];
1248 			errno = nla_put_u16(skb, attr1, value);
1249 			if (errno)
1250 				return errno;
1251 
1252 			attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK;
1253 			value = 0;
1254 			errno = nla_put_u16(skb, attr1, value);
1255 			if (errno)
1256 				return errno;
1257 			nla_nest_end(skb, config_params);
1258 		}
1259 		break;
1260 	case WLAN_T2LM_DL_DIRECTION:
1261 		for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
1262 			config_params = nla_nest_start(skb, tid_num + 1);
1263 			if (!config_params)
1264 				return -EINVAL;
1265 			attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK;
1266 			value = t2lm->ieee_link_map_tid[i];
1267 			errno = nla_put_u16(skb, attr1, value);
1268 			if (errno)
1269 				return errno;
1270 
1271 			attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK;
1272 			value = 0;
1273 			errno = nla_put_u16(skb, attr1, value);
1274 			if (errno)
1275 				return errno;
1276 			nla_nest_end(skb, config_params);
1277 		}
1278 		break;
1279 	case WLAN_T2LM_BIDI_DIRECTION:
1280 		for (tid_num = 0; tid_num < T2LM_MAX_NUM_TIDS; tid_num++) {
1281 			config_params = nla_nest_start(skb, tid_num + 1);
1282 			if (!config_params)
1283 				return -EINVAL;
1284 
1285 			attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_UPLINK;
1286 			value = t2lm->ieee_link_map_tid[i];
1287 			errno = nla_put_u16(skb, attr1, value);
1288 			if (errno)
1289 				return errno;
1290 
1291 			attr1 = QCA_WLAN_VENDOR_ATTR_LINK_TID_MAP_STATUS_DOWNLINK;
1292 			value = t2lm->ieee_link_map_tid[i];
1293 			errno = nla_put_u16(skb, attr1, value);
1294 			if (errno)
1295 				return errno;
1296 			nla_nest_end(skb, config_params);
1297 		}
1298 		break;
1299 	default:
1300 		return -EINVAL;
1301 	}
1302 	nla_nest_end(skb, config_attr);
1303 	return QDF_STATUS_SUCCESS;
1304 }
1305 
1306 QDF_STATUS wlan_hdd_send_t2lm_event(struct wlan_objmgr_vdev *vdev,
1307 				    struct wlan_t2lm_info *t2lm)
1308 {
1309 	struct sk_buff *skb;
1310 	size_t data_len;
1311 	QDF_STATUS status;
1312 	struct qdf_mac_addr mld_addr;
1313 	struct hdd_adapter *adapter;
1314 	struct wlan_hdd_link_info *link_info;
1315 
1316 	enum qca_nl80211_vendor_subcmds_index index =
1317 		QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP_INDEX;
1318 
1319 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
1320 	if (!link_info) {
1321 		hdd_err("Invalid VDEV");
1322 		return QDF_STATUS_E_FAILURE;
1323 	}
1324 
1325 	adapter = link_info->adapter;
1326 	data_len = hdd_get_t2lm_setup_event_len();
1327 	skb = wlan_cfg80211_vendor_event_alloc(adapter->hdd_ctx->wiphy,
1328 					       NULL,
1329 					       data_len,
1330 					       index, GFP_KERNEL);
1331 	if (!skb) {
1332 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1333 		return -EINVAL;
1334 	}
1335 
1336 	/* get mld addr */
1337 	status = wlan_vdev_get_bss_peer_mld_mac(vdev, &mld_addr);
1338 	if (QDF_IS_STATUS_ERROR(status)) {
1339 		hdd_err("Failed to get mld address");
1340 		goto free_skb;
1341 	}
1342 
1343 	status = hdd_t2lm_pack_nl_response(skb, vdev, t2lm, mld_addr);
1344 	if (QDF_IS_STATUS_ERROR(status)) {
1345 		hdd_err("Failed to pack nl response");
1346 		goto free_skb;
1347 	}
1348 
1349 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
1350 
1351 	return status;
1352 free_skb:
1353 	wlan_cfg80211_vendor_free_skb(skb);
1354 
1355 	return status;
1356 }
1357 #endif
1358