Sfoglia il codice sorgente

qcacld-3.0: Use MAC addr derive logic for link adapters

Currently the link addresses of link adapters are static and
are allocated during adapter create.
To randomize the MAC address as part of connection Android
framework sends new MAC address, which will be set as MLD address
incase of ML interface, but the link addresses are not changed.

Use the MAC address from Android framework and generate new
link addresses from that for each link. Manage interface
change logic and redundant code.

Change-Id: I40c86cfd05b304c48ab048ea793cc34fb4d250f9
CRs-Fixed: 3485639
Vinod Kumar Pirla 1 anno fa
parent
commit
e99282ca0e

+ 16 - 15
core/hdd/inc/wlan_hdd_main.h

@@ -4850,17 +4850,19 @@ void hdd_check_for_net_dev_ref_leak(struct hdd_adapter *adapter);
 /**
  * hdd_dynamic_mac_address_set(): API to set MAC address, when interface
  *                                is up.
- * @hdd_ctx: Pointer to HDD context
  * @adapter: Pointer to hdd_adapter
  * @mac_addr: MAC address to set
+ * @mld_addr: MLD address to set
+ * @update_self_peer: Set to true to update self peer's address
  *
  * This API is used to update the current VDEV MAC address.
  *
  * Return: 0 for success. non zero valure for failure.
  */
-int hdd_dynamic_mac_address_set(struct hdd_context *hdd_ctx,
-				struct hdd_adapter *adapter,
-				struct qdf_mac_addr mac_addr);
+int hdd_dynamic_mac_address_set(struct hdd_adapter *adapter,
+				struct qdf_mac_addr mac_addr,
+				struct qdf_mac_addr mld_addr,
+				bool update_self_peer);
 
 /**
  * hdd_is_dynamic_set_mac_addr_allowed() - API to check dynamic MAC address
@@ -4874,7 +4876,6 @@ bool hdd_is_dynamic_set_mac_addr_allowed(struct hdd_adapter *adapter);
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
 /**
  * hdd_update_vdev_mac_address() - Update VDEV MAC address dynamically
- * @hdd_ctx: Pointer to HDD context
  * @adapter: Pointer to HDD adapter
  * @mac_addr: MAC address to be updated
  *
@@ -4882,28 +4883,28 @@ bool hdd_is_dynamic_set_mac_addr_allowed(struct hdd_adapter *adapter);
  *
  * Return: 0 for Success. Error code for failure
  */
-int hdd_update_vdev_mac_address(struct hdd_context *hdd_ctx,
-				struct hdd_adapter *adapter,
+int hdd_update_vdev_mac_address(struct hdd_adapter *adapter,
 				struct qdf_mac_addr mac_addr);
 #else
-static inline int hdd_update_vdev_mac_address(struct hdd_context *hdd_ctx,
-					      struct hdd_adapter *adapter,
+static inline int hdd_update_vdev_mac_address(struct hdd_adapter *adapter,
 					      struct qdf_mac_addr mac_addr)
 {
-	return hdd_dynamic_mac_address_set(hdd_ctx, adapter, mac_addr);
+	struct qdf_mac_addr mld_addr = QDF_MAC_ADDR_ZERO_INIT;
+
+	return hdd_dynamic_mac_address_set(adapter, mac_addr, mld_addr, true);
 }
 #endif /* WLAN_FEATURE_11BE_MLO */
 #else
-static inline int hdd_update_vdev_mac_address(struct hdd_context *hdd_ctx,
-					      struct hdd_adapter *adapter,
+static inline int hdd_update_vdev_mac_address(struct hdd_adapter *adapter,
 					      struct qdf_mac_addr mac_addr)
 {
 	return 0;
 }
 
-static inline int hdd_dynamic_mac_address_set(struct hdd_context *hdd_ctx,
-					      struct hdd_adapter *adapter,
-					      struct qdf_mac_addr mac_addr)
+static inline int hdd_dynamic_mac_address_set(struct hdd_adapter *adapter,
+					      struct qdf_mac_addr mac_addr,
+					      struct qdf_mac_addr mld_addr,
+					      bool update_self_peer)
 {
 	return 0;
 }

+ 14 - 0
core/hdd/inc/wlan_hdd_mlo.h

@@ -150,6 +150,15 @@ void hdd_adapter_set_ml_adapter(struct hdd_adapter *adapter);
  */
 void hdd_adapter_set_sl_ml_adapter(struct hdd_adapter *adapter);
 
+/**
+ * hdd_adapter_clear_sl_ml_adapter() - Set adapter as sl ml adapter
+ * @adapter: HDD adapter
+ *
+ * This function clears adapter single link ML adapter flag
+ * Return: None
+ */
+void hdd_adapter_clear_sl_ml_adapter(struct hdd_adapter *adapter);
+
 /**
  * hdd_get_ml_adapter() - get an ml adapter
  * @hdd_ctx: HDD context
@@ -266,6 +275,11 @@ hdd_adapter_set_sl_ml_adapter(struct hdd_adapter *adapter)
 {
 }
 
+static inline void
+hdd_adapter_clear_sl_ml_adapter(struct hdd_adapter *adapter)
+{
+}
+
 static inline
 struct hdd_adapter *hdd_get_ml_adapter(struct hdd_context *hdd_ctx)
 {

+ 50 - 72
core/hdd/src/wlan_hdd_cfg80211.c

@@ -202,6 +202,7 @@
 #include <utils_mlo.h>
 #include "wlan_mlo_mgr_roam.h"
 #include "wlan_hdd_mlo.h"
+#include <wlan_psoc_mlme_ucfg_api.h>
 
 /*
  * A value of 100 (milliseconds) can be sent to FW.
@@ -20729,79 +20730,43 @@ static bool hdd_is_ap_mode(enum QDF_OPMODE mode)
 	}
 }
 
-/**
- * hdd_adapter_update_mac_on_mode_change() - Update mac address on mode change
- * @adapter: HDD adapter
- * @get_new_addr: Get new address or release existing address
- *
- * If @get_new_addr is false, the function will release the MAC address
- * in the adapter's mac_addr member and copy the MLD address into it.
- *
- * If @get_new_addr is true, the function will override MAC address
- * in the adapter's mac_addr member and copy the new MAc address
- * fetched from the MAC address pool.
- *
- * The MLD address is not changed in this function.
- *
- * Return: void
- */
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
 static QDF_STATUS
-hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter,
-				      bool get_new_addr)
+hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter)
 {
-	uint8_t *new_mac;
-	bool is_mac_equal;
-	struct hdd_adapter *assoc_adapter;
-	struct qdf_mac_addr *assoc_mac;
+	int i;
 	QDF_STATUS status;
+	struct hdd_adapter *link_adapter;
+	struct hdd_mlo_adapter_info *mlo_adapter_info;
+	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
+	struct qdf_mac_addr link_addr[WLAN_MAX_MLD] = {0};
 
-	if (!adapter || !hdd_adapter_is_ml_adapter(adapter))
-		return QDF_STATUS_SUCCESS;
-
-	assoc_adapter = hdd_get_assoc_link_adapter(adapter);
-	if (!assoc_adapter || qdf_is_macaddr_zero(&assoc_adapter->mld_addr))
-		return QDF_STATUS_E_INVAL;
-
-	assoc_mac = &assoc_adapter->mac_addr;
-
-	is_mac_equal = qdf_is_macaddr_equal(&assoc_adapter->mld_addr,
-					    assoc_mac);
-
-	if (get_new_addr) {
-		/* If both address are already different
-		 * don't get new address
-		 */
-		if (!is_mac_equal)
-			goto out;
+	status = hdd_derive_link_address_from_mld(&adapter->mld_addr,
+						  &link_addr[0],
+						  WLAN_MAX_MLD);
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
 
-		new_mac = wlan_hdd_get_intf_addr(adapter->hdd_ctx,
-						 QDF_STA_MODE);
-		if (new_mac) {
-			memcpy(assoc_mac->bytes, new_mac, QDF_MAC_ADDR_SIZE);
-			status = ucfg_dp_create_intf(
-					assoc_adapter->hdd_ctx->psoc,
-					assoc_mac,
-					(qdf_netdev_t)assoc_adapter->dev);
-			if (QDF_IS_STATUS_ERROR(status))
-				return status;
-		}
-	} else {
-		/* If both address are already equal
-		 * don't release the address
-		 */
-		if (is_mac_equal)
-			goto out;
+	mlo_adapter_info = &adapter->mlo_adapter_info;
+	for (i = 0; i < WLAN_MAX_MLD; i++) {
+		link_adapter = mlo_adapter_info->link_adapter[i];
+		if (!link_adapter)
+			continue;
 
-		wlan_hdd_release_intf_addr(adapter->hdd_ctx, assoc_mac->bytes);
-		ucfg_dp_destroy_intf(adapter->hdd_ctx->psoc, assoc_mac);
-		qdf_copy_macaddr(assoc_mac, &adapter->mld_addr);
+		ucfg_dp_update_inf_mac(hdd_ctx->psoc, &link_adapter->mac_addr,
+				       &link_addr[i]);
+		qdf_copy_macaddr(&link_adapter->mac_addr, &link_addr[i]);
 	}
-out:
-	qdf_net_update_net_device_dev_addr(adapter->dev,
-					   adapter->mld_addr.bytes,
-					   QDF_MAC_ADDR_SIZE);
+
 	return QDF_STATUS_SUCCESS;
 }
+#else
+static inline QDF_STATUS
+hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 
 /**
  * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
@@ -20827,6 +20792,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 	QDF_STATUS status;
 	int errno;
 	uint8_t mac_addr[QDF_MAC_ADDR_SIZE];
+	bool eht_capab;
 
 	hdd_enter();
 
@@ -20928,10 +20894,6 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 					QDF_MAC_ADDR_FMT "\n",
 					QDF_MAC_ADDR_REF(ndev->dev_addr));
 			}
-			status = hdd_adapter_update_mac_on_mode_change(adapter,
-								       false);
-			if (QDF_IS_STATUS_ERROR(status))
-				goto err;
 			hdd_set_ap_ops(adapter->dev);
 		} else {
 			hdd_err("Changing to device mode '%s' is not supported",
@@ -20946,10 +20908,6 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 				hdd_err("change mode fail %d", errno);
 				goto err;
 			}
-			status = hdd_adapter_update_mac_on_mode_change(adapter,
-								       true);
-			if (QDF_IS_STATUS_ERROR(status))
-				goto err;
 		} else if (hdd_is_ap_mode(new_mode)) {
 			adapter->device_mode = new_mode;
 
@@ -20968,6 +20926,26 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 		goto err;
 	}
 
+	ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
+	if (eht_capab && hdd_adapter_is_ml_adapter(adapter)) {
+		switch (adapter->device_mode) {
+		case QDF_SAP_MODE:
+			hdd_adapter_set_sl_ml_adapter(adapter);
+			break;
+		case QDF_STA_MODE:
+			hdd_adapter_clear_sl_ml_adapter(adapter);
+
+			status = hdd_adapter_update_mac_on_mode_change(adapter);
+			if (QDF_IS_STATUS_ERROR(status))
+				goto err;
+
+			break;
+		default:
+			hdd_adapter_clear_sl_ml_adapter(adapter);
+			break;
+		}
+	}
+
 	/* restart the adapter if it was up before the change iface request */
 	if (iff_up) {
 		errno = hdd_start_adapter(adapter);

+ 11 - 2
core/hdd/src/wlan_hdd_hostapd.c

@@ -118,6 +118,7 @@
 #include "wlan_twt_ucfg_ext_api.h"
 #include "wlan_twt_ucfg_api.h"
 #include "wlan_vdev_mgr_ucfg_api.h"
+#include <wlan_psoc_mlme_ucfg_api.h>
 
 #define ACS_SCAN_EXPIRY_TIMEOUT_S 4
 
@@ -747,7 +748,8 @@ static int __hdd_hostapd_set_mac_address(struct net_device *dev, void *addr)
 	struct hdd_adapter *adapter, *adapter_temp;
 	struct hdd_context *hdd_ctx;
 	int ret = 0;
-	struct qdf_mac_addr mac_addr;
+	bool eht_capab;
+	struct qdf_mac_addr mac_addr, mld_addr;
 
 	hdd_enter_dev(dev);
 
@@ -791,7 +793,14 @@ static int __hdd_hostapd_set_mac_address(struct net_device *dev, void *addr)
 		if (!hdd_is_dynamic_set_mac_addr_allowed(adapter))
 			return -ENOTSUPP;
 
-		ret = hdd_dynamic_mac_address_set(hdd_ctx, adapter, mac_addr);
+		ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
+		if (eht_capab && hdd_adapter_is_ml_adapter(adapter))
+			qdf_copy_macaddr(&mld_addr, &mac_addr);
+		else
+			qdf_zero_macaddr(&mld_addr);
+
+		ret = hdd_dynamic_mac_address_set(adapter, mac_addr, mld_addr,
+						  false);
 		if (ret)
 			return ret;
 	}

+ 45 - 47
core/hdd/src/wlan_hdd_main.c

@@ -5408,26 +5408,33 @@ bool hdd_is_dynamic_set_mac_addr_allowed(struct hdd_adapter *adapter)
 	}
 }
 
-int hdd_dynamic_mac_address_set(struct hdd_context *hdd_ctx,
-				struct hdd_adapter *adapter,
-				struct qdf_mac_addr mac_addr)
+int hdd_dynamic_mac_address_set(struct hdd_adapter *adapter,
+				struct qdf_mac_addr mac_addr,
+				struct qdf_mac_addr mld_addr,
+				bool update_self_peer)
 {
-	uint32_t *fw_resp_status;
+	int ret;
 	void *cookie;
+	bool update_mld_addr;
+	uint32_t *fw_resp_status;
+	QDF_STATUS status;
 	struct osif_request *request;
+	struct wlan_objmgr_vdev *vdev;
+	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
 	static const struct osif_request_params params = {
 		.priv_size = sizeof(*fw_resp_status),
 		.timeout_ms = WLAN_SET_MAC_ADDR_TIMEOUT
 	};
-	int ret;
-	QDF_STATUS qdf_ret_status;
-	struct qdf_mac_addr mld_addr;
-	bool update_self_peer, update_mld_addr;
 
-	qdf_ret_status = ucfg_vdev_mgr_cdp_vdev_detach(adapter->deflink->vdev);
-	if (QDF_IS_STATUS_ERROR(qdf_ret_status)) {
-		hdd_err("Failed to detach CDP vdev. Status:%d", qdf_ret_status);
-		return qdf_status_to_os_return(qdf_ret_status);
+	vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_ID);
+	if (!vdev)
+		return -EINVAL;
+
+	status = ucfg_vdev_mgr_cdp_vdev_detach(vdev);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to detach CDP vdev. Status:%d", status);
+		ret = qdf_status_to_os_return(status);
+		goto vdev_ref;
 	}
 
 	request = osif_request_alloc(&params);
@@ -5436,20 +5443,6 @@ int hdd_dynamic_mac_address_set(struct hdd_context *hdd_ctx,
 		goto status_ret;
 	}
 
-	if (hdd_adapter_is_link_adapter(adapter)) {
-		update_self_peer =
-			hdd_adapter_is_associated_with_ml_adapter(adapter);
-		update_mld_addr = true;
-	} else if (hdd_adapter_is_sl_ml_adapter(adapter)) {
-		update_mld_addr = true;
-		if (adapter->device_mode == QDF_SAP_MODE)
-			update_self_peer = false;
-		else
-			update_self_peer = true;
-	} else {
-		update_self_peer = true;
-		update_mld_addr = false;
-	}
 	/* Host should hold a wake lock until the FW event response is received
 	 * the WMI event would not be a wake up event.
 	 */
@@ -5460,14 +5453,11 @@ int hdd_dynamic_mac_address_set(struct hdd_context *hdd_ctx,
 	cookie = osif_request_cookie(request);
 	hdd_update_set_mac_addr_req_ctx(adapter, cookie);
 
-	qdf_mem_copy(&mld_addr, adapter->mld_addr.bytes, sizeof(mld_addr));
-	qdf_ret_status = sme_send_set_mac_addr(mac_addr, mld_addr,
-					       adapter->deflink->vdev,
-					       update_mld_addr);
-	ret = qdf_status_to_os_return(qdf_ret_status);
-	if (QDF_STATUS_SUCCESS != qdf_ret_status) {
+	status = sme_send_set_mac_addr(mac_addr, mld_addr, vdev);
+	ret = qdf_status_to_os_return(status);
+	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_nofl_err("Failed to send set MAC address command. Status:%d",
-			     qdf_ret_status);
+			     status);
 		osif_request_put(request);
 		goto status_ret;
 	} else {
@@ -5486,34 +5476,42 @@ int hdd_dynamic_mac_address_set(struct hdd_context *hdd_ctx,
 
 	osif_request_put(request);
 
-	qdf_ret_status = sme_update_vdev_mac_addr(
-			   hdd_ctx->psoc, mac_addr, adapter->deflink->vdev,
-			   update_self_peer, update_mld_addr,
-			   ret);
+	if (qdf_is_macaddr_zero(&mld_addr))
+		update_mld_addr = false;
+	else
+		update_mld_addr = true;
 
-	if (QDF_IS_STATUS_ERROR(qdf_ret_status))
-		ret = qdf_status_to_os_return(qdf_ret_status);
+	status = sme_update_vdev_mac_addr(vdev, mac_addr, mld_addr,
+					  update_self_peer, update_mld_addr,
+					  ret);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		ret = qdf_status_to_os_return(status);
 
 status_ret:
-	qdf_ret_status = ucfg_vdev_mgr_cdp_vdev_attach(adapter->deflink->vdev);
-	if (QDF_IS_STATUS_ERROR(qdf_ret_status)) {
+	status = ucfg_vdev_mgr_cdp_vdev_attach(vdev);
+	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_allow_suspend(
 			WIFI_POWER_EVENT_WAKELOCK_DYN_MAC_ADDR_UPDATE);
 		qdf_runtime_pm_allow_suspend(
 				&hdd_ctx->runtime_context.dyn_mac_addr_update);
-		hdd_err("Failed to attach CDP vdev. status:%d", qdf_ret_status);
-		return qdf_status_to_os_return(qdf_ret_status);
+		hdd_err("Failed to attach CDP vdev. status:%d", status);
+		ret = qdf_status_to_os_return(status);
+		goto vdev_ref;
 	}
-	sme_vdev_set_data_tx_callback(adapter->deflink->vdev);
+	sme_vdev_set_data_tx_callback(vdev);
 
 	/* Update FW WoW pattern with new MAC address */
-	ucfg_pmo_del_wow_pattern(adapter->deflink->vdev);
-	ucfg_pmo_register_wow_default_patterns(adapter->deflink->vdev);
+	ucfg_pmo_del_wow_pattern(vdev);
+	ucfg_pmo_register_wow_default_patterns(vdev);
 
 	hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_DYN_MAC_ADDR_UPDATE);
 	qdf_runtime_pm_allow_suspend(
 			&hdd_ctx->runtime_context.dyn_mac_addr_update);
 
+vdev_ref:
+	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
+
 	return ret;
 }
 
@@ -5608,7 +5606,7 @@ static int __hdd_set_mac_address(struct net_device *dev, void *addr)
 		       QDF_MAC_ADDR_REF(mac_addr.bytes), dev->name);
 
 	if (net_if_running && adapter->deflink->vdev) {
-		ret = hdd_update_vdev_mac_address(hdd_ctx, adapter, mac_addr);
+		ret = hdd_update_vdev_mac_address(adapter, mac_addr);
 		if (ret)
 			return ret;
 	}

+ 85 - 57
core/hdd/src/wlan_hdd_mlo.c

@@ -121,8 +121,6 @@ void hdd_mlo_close_adapter(struct hdd_adapter *link_adapter, bool rtnl_held)
 		osif_vdev_sync_wait_for_ops(vdev_sync);
 
 	hdd_check_for_net_dev_ref_leak(link_adapter);
-	wlan_hdd_release_intf_addr(link_adapter->hdd_ctx,
-				   link_adapter->mac_addr.bytes);
 	policy_mgr_clear_concurrency_mode(link_adapter->hdd_ctx->psoc,
 					  link_adapter->device_mode);
 	link_adapter->wdev.netdev = NULL;
@@ -144,11 +142,8 @@ QDF_STATUS hdd_wlan_unregister_mlo_interfaces(struct hdd_adapter *adapter,
 	mlo_adapter_info = &adapter->mlo_adapter_info;
 
 	if (mlo_adapter_info->is_link_adapter) {
-		if (!qdf_is_macaddr_equal(&adapter->mac_addr,
-					  &adapter->mld_addr)) {
-			ucfg_dp_destroy_intf(adapter->hdd_ctx->psoc,
-					     &adapter->mac_addr);
-		}
+		ucfg_dp_destroy_intf(adapter->hdd_ctx->psoc,
+				     &adapter->mac_addr);
 		hdd_remove_front_adapter(adapter->hdd_ctx, &adapter);
 		return QDF_STATUS_E_AGAIN;
 	}
@@ -157,11 +152,8 @@ QDF_STATUS hdd_wlan_unregister_mlo_interfaces(struct hdd_adapter *adapter,
 		link_adapter = mlo_adapter_info->link_adapter[i];
 		if (!link_adapter)
 			continue;
-		if (!qdf_is_macaddr_equal(&link_adapter->mac_addr,
-					  &link_adapter->mld_addr)) {
-			ucfg_dp_destroy_intf(link_adapter->hdd_ctx->psoc,
-					     &link_adapter->mac_addr);
-		}
+		ucfg_dp_destroy_intf(link_adapter->hdd_ctx->psoc,
+				     &link_adapter->mac_addr);
 		hdd_remove_adapter(link_adapter->hdd_ctx, link_adapter);
 		hdd_mlo_close_adapter(link_adapter, rtnl_held);
 	}
@@ -171,34 +163,36 @@ QDF_STATUS hdd_wlan_unregister_mlo_interfaces(struct hdd_adapter *adapter,
 
 void hdd_wlan_register_mlo_interfaces(struct hdd_context *hdd_ctx)
 {
-	uint8_t *mac_addr;
-	struct hdd_adapter_create_param params = {0};
 	QDF_STATUS status;
+	struct hdd_adapter *ml_adapter;
+	struct hdd_adapter_create_param params = {0};
+	struct qdf_mac_addr link_addr[WLAN_MAX_MLD] = {0};
 
-	mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_STA_MODE);
-	if (mac_addr) {
-		/* if target supports MLO create a new dev */
-		params.only_wdev_register = true;
-		params.associate_with_ml_adapter = false;
-		status = hdd_open_adapter_no_trans(hdd_ctx,
-						   QDF_STA_MODE,
-						   "null", mac_addr,
-						   &params);
-		if (QDF_IS_STATUS_ERROR(status))
-			hdd_err("Failed to register link adapter:%d", status);
-	}
+	ml_adapter = hdd_get_ml_adapter(hdd_ctx);
+	if (!ml_adapter)
+		return;
+
+	status = hdd_derive_link_address_from_mld(&ml_adapter->mld_addr,
+						  &link_addr[0], WLAN_MAX_MLD);
+	if (QDF_IS_STATUS_ERROR(status))
+		return;
+
+	/* if target supports MLO create a new dev */
+	params.only_wdev_register = true;
+	params.associate_with_ml_adapter = true;
+	status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE, "null",
+					   link_addr[0].bytes, &params);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Failed to register link adapter:%d", status);
 
 	qdf_mem_zero(&params, sizeof(params));
 	params.only_wdev_register  = true;
-	params.associate_with_ml_adapter = true;
-	mac_addr = wlan_hdd_get_intf_addr(hdd_ctx, QDF_STA_MODE);
-	if (mac_addr) {
-		/* if target supports MLO create a new dev */
-		status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE,
-						   "null", mac_addr, &params);
-		if (QDF_IS_STATUS_ERROR(status))
-			hdd_err("Failed to register link adapter:%d", status);
-	}
+	params.associate_with_ml_adapter = false;
+	/* if target supports MLO create a new dev */
+	status = hdd_open_adapter_no_trans(hdd_ctx, QDF_STA_MODE, "null",
+					   link_addr[1].bytes, &params);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Failed to register link adapter:%d", status);
 }
 
 #ifdef CFG80211_MLD_MAC_IN_WDEV
@@ -228,6 +222,12 @@ hdd_adapter_set_sl_ml_adapter(struct hdd_adapter *adapter)
 	adapter->mlo_adapter_info.is_single_link_ml = true;
 }
 
+void
+hdd_adapter_clear_sl_ml_adapter(struct hdd_adapter *adapter)
+{
+	adapter->mlo_adapter_info.is_single_link_ml = false;
+}
+
 struct hdd_adapter *hdd_get_ml_adapter(struct hdd_context *hdd_ctx)
 {
 	struct hdd_adapter *adapter, *next_adapter = NULL;
@@ -303,35 +303,63 @@ QDF_STATUS hdd_derive_link_address_from_mld(struct qdf_mac_addr *mld_addr,
 }
 
 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
-int hdd_update_vdev_mac_address(struct hdd_context *hdd_ctx,
-				struct hdd_adapter *adapter,
+int hdd_update_vdev_mac_address(struct hdd_adapter *adapter,
 				struct qdf_mac_addr mac_addr)
 {
 	int i, ret = 0;
-	struct hdd_mlo_adapter_info *mlo_adapter_info;
+	QDF_STATUS status;
+	bool eht_capab, update_self_peer;
 	struct hdd_adapter *link_adapter;
-	bool eht_capab;
+	struct hdd_mlo_adapter_info *mlo_adapter_info;
+	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
+	struct qdf_mac_addr link_addrs[WLAN_MAX_MLD] = {0};
 
+	/* This API is only called with is ml adapter set for STA mode adapter.
+	 * For SAP mode, hdd_hostapd_set_mac_address() is the entry point for
+	 * MAC address update.
+	 */
 	ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
-	if (hdd_adapter_is_ml_adapter(adapter) && eht_capab) {
-		if (hdd_adapter_is_sl_ml_adapter(adapter)) {
-			ret = hdd_dynamic_mac_address_set(hdd_ctx, adapter,
-							  mac_addr);
+	if (!(eht_capab && hdd_adapter_is_ml_adapter(adapter))) {
+		struct qdf_mac_addr mld_addr = QDF_MAC_ADDR_ZERO_INIT;
+
+		ret = hdd_dynamic_mac_address_set(adapter, mac_addr,
+						  mld_addr, true);
+		return ret;
+	}
+
+	status = hdd_derive_link_address_from_mld(&mac_addr, &link_addrs[0],
+						  WLAN_MAX_MLD);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		return qdf_status_to_os_return(status);
+
+	mlo_adapter_info = &adapter->mlo_adapter_info;
+	for (i = 0; i < WLAN_MAX_MLD; i++) {
+		link_adapter = mlo_adapter_info->link_adapter[i];
+		if (!link_adapter)
+			continue;
+
+		status = sme_check_for_duplicate_session(hdd_ctx->mac_handle,
+							 link_addrs[i].bytes);
+
+		if (QDF_IS_STATUS_ERROR(status))
+			return qdf_status_to_os_return(status);
+
+		if (hdd_adapter_is_associated_with_ml_adapter(link_adapter))
+			update_self_peer = true;
+		else
+			update_self_peer = false;
+
+		ret = hdd_dynamic_mac_address_set(link_adapter, link_addrs[i],
+						  mac_addr, update_self_peer);
+		if (ret)
 			return ret;
-		}
-		mlo_adapter_info = &adapter->mlo_adapter_info;
-
-		for (i = 0; i < WLAN_MAX_MLD; i++) {
-			link_adapter = mlo_adapter_info->link_adapter[i];
-			if (!link_adapter)
-				continue;
-			ret = hdd_dynamic_mac_address_set(hdd_ctx, link_adapter,
-							  mac_addr);
-			if (ret)
-				return ret;
-		}
-	} else {
-		ret = hdd_dynamic_mac_address_set(hdd_ctx, adapter, mac_addr);
+
+		/* Update DP intf and new link address in link adapter
+		 */
+		ucfg_dp_update_inf_mac(hdd_ctx->psoc, &link_adapter->mac_addr,
+				       &link_addrs[i]);
+		qdf_copy_macaddr(&link_adapter->mac_addr, &link_addrs[i]);
 	}
 
 	return ret;

+ 5 - 7
core/sme/inc/sme_api.h

@@ -4619,7 +4619,6 @@ QDF_STATUS sme_switch_channel(mac_handle_t mac_handle,
  * @mac_addr: VDEV MAC address
  * @mld_addr: VDEV MLD address
  * @vdev: Pointer to object manager VDEV
- * @update_mld_addr: Flag to check whether to update MLD addr or not
  *
  * API to send set MAC address request command to FW
  *
@@ -4627,14 +4626,13 @@ QDF_STATUS sme_switch_channel(mac_handle_t mac_handle,
  */
 QDF_STATUS sme_send_set_mac_addr(struct qdf_mac_addr mac_addr,
 				 struct qdf_mac_addr mld_addr,
-				 struct wlan_objmgr_vdev *vdev,
-				 bool update_mld_addr);
+				 struct wlan_objmgr_vdev *vdev);
 
 /**
  * sme_update_vdev_mac_addr() - Update VDEV MAC address
- * @psoc: Pointer to PSOC structure
+ * @vdev: Objmgr VDEV pointer
  * @mac_addr: VDEV MAC address
- * @vdev: Pointer to object manager VDEV
+ * @mld_addr: VDEV MLD address
  * @update_sta_self_peer: Flag to check self peer MAC address or not.
  * @update_mld_addr: Flag to check if MLD address update needed or not.
  * @req_status: Status of the set MAC address request to the FW
@@ -4645,9 +4643,9 @@ QDF_STATUS sme_send_set_mac_addr(struct qdf_mac_addr mac_addr,
  *
  * Return: QDF_STATUS
  */
-QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_psoc *psoc,
+QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_vdev *vdev,
 				    struct qdf_mac_addr mac_addr,
-				    struct wlan_objmgr_vdev *vdev,
+				    struct qdf_mac_addr mld_addr,
 				    bool update_sta_self_peer,
 				    bool update_mld_addr, int req_status);
 #endif

+ 31 - 52
core/sme/src/common/sme_api.c

@@ -16339,12 +16339,10 @@ bool sme_is_11be_capable(void)
 
 QDF_STATUS sme_send_set_mac_addr(struct qdf_mac_addr mac_addr,
 				 struct qdf_mac_addr mld_addr,
-				 struct wlan_objmgr_vdev *vdev,
-				 bool update_mld_addr)
+				 struct wlan_objmgr_vdev *vdev)
 {
 	enum QDF_OPMODE vdev_opmode;
-	struct qdf_mac_addr vdev_mac_addr = mac_addr;
-	QDF_STATUS qdf_ret_status;
+	QDF_STATUS status;
 	struct vdev_mlme_obj *vdev_mlme;
 
 	if (!vdev) {
@@ -16355,26 +16353,14 @@ QDF_STATUS sme_send_set_mac_addr(struct qdf_mac_addr mac_addr,
 	vdev_opmode = wlan_vdev_mlme_get_opmode(vdev);
 
 	if (vdev_opmode == QDF_P2P_DEVICE_MODE) {
-		qdf_ret_status = wma_p2p_self_peer_remove(vdev);
-		if (QDF_IS_STATUS_ERROR(qdf_ret_status))
-			return qdf_ret_status;
-	}
-
-	if (sme_is_11be_capable() && update_mld_addr) {
-		/* Set new MAC addr as MLD address incase of MLO */
-		mld_addr = mac_addr;
-		if (vdev_opmode == QDF_STA_MODE) {
-			qdf_mem_copy(&vdev_mac_addr,
-				     wlan_vdev_mlme_get_linkaddr(vdev),
-				     sizeof(struct qdf_mac_addr));
-		}
+		status = wma_p2p_self_peer_remove(vdev);
+		if (QDF_IS_STATUS_ERROR(status))
+			return status;
 	}
 
-	qdf_ret_status = wlan_vdev_mlme_send_set_mac_addr(vdev_mac_addr,
-							  mld_addr, vdev);
-
-	if (QDF_IS_STATUS_SUCCESS(qdf_ret_status))
-		return qdf_ret_status;
+	status = wlan_vdev_mlme_send_set_mac_addr(mac_addr, mld_addr, vdev);
+	if (QDF_IS_STATUS_SUCCESS(status))
+		return status;
 
 	/**
 	 * Failed to send set MAC address command to FW. Create P2P self peer
@@ -16387,10 +16373,10 @@ QDF_STATUS sme_send_set_mac_addr(struct qdf_mac_addr mac_addr,
 			return QDF_STATUS_E_INVAL;
 		}
 
-		qdf_ret_status = wma_vdev_self_peer_create(vdev_mlme);
-		if (QDF_IS_STATUS_ERROR(qdf_ret_status)) {
+		status = wma_vdev_self_peer_create(vdev_mlme);
+		if (QDF_IS_STATUS_ERROR(status)) {
 			sme_nofl_err("Failed to create self peer for P2P device mode. Status:%d",
-				     qdf_ret_status);
+				     status);
 			return QDF_STATUS_E_INVAL;
 		}
 	}
@@ -16398,22 +16384,20 @@ QDF_STATUS sme_send_set_mac_addr(struct qdf_mac_addr mac_addr,
 	return QDF_STATUS_E_INVAL;
 }
 
-QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_psoc *psoc,
+QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_vdev *vdev,
 				    struct qdf_mac_addr mac_addr,
-				    struct wlan_objmgr_vdev *vdev,
+				    struct qdf_mac_addr mld_addr,
 				    bool update_sta_self_peer,
 				    bool update_mld_addr, int req_status)
 {
 	enum QDF_OPMODE vdev_opmode;
-	uint8_t *old_mac_addr_bytes;
+	uint8_t *old_macaddr, *new_macaddr;
 	QDF_STATUS qdf_ret_status;
 	struct wlan_objmgr_peer *peer;
 	struct vdev_mlme_obj *vdev_mlme;
+	struct wlan_objmgr_psoc *psoc;
 
-	if (!vdev) {
-		sme_err("Invalid VDEV");
-		return QDF_STATUS_E_INVAL;
-	}
+	psoc = wlan_vdev_get_psoc(vdev);
 
 	vdev_opmode = wlan_vdev_mlme_get_opmode(vdev);
 
@@ -16421,17 +16405,20 @@ QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_psoc *psoc,
 		goto p2p_self_peer_create;
 
 	if (vdev_opmode == QDF_STA_MODE && update_sta_self_peer) {
-		if (sme_is_11be_capable() && update_mld_addr)
-			old_mac_addr_bytes = wlan_vdev_mlme_get_mldaddr(vdev);
-		else
-			old_mac_addr_bytes = wlan_vdev_mlme_get_macaddr(vdev);
+		if (sme_is_11be_capable() && update_mld_addr) {
+			old_macaddr = wlan_vdev_mlme_get_mldaddr(vdev);
+			new_macaddr = mld_addr.bytes;
+		} else {
+			old_macaddr = wlan_vdev_mlme_get_macaddr(vdev);
+			new_macaddr = mac_addr.bytes;
+		}
 
 		/* Update self peer MAC address */
-		peer = wlan_objmgr_get_peer_by_mac(psoc, old_mac_addr_bytes,
+		peer = wlan_objmgr_get_peer_by_mac(psoc, old_macaddr,
 						   WLAN_MLME_NB_ID);
 		if (peer) {
-			qdf_ret_status = wlan_peer_update_macaddr(
-							peer, mac_addr.bytes);
+			qdf_ret_status = wlan_peer_update_macaddr(peer,
+								  new_macaddr);
 			wlan_objmgr_peer_release_ref(peer, WLAN_MLME_NB_ID);
 			if (QDF_IS_STATUS_ERROR(qdf_ret_status)) {
 				sme_nofl_err("Failed to update self peer MAC address. Status:%d",
@@ -16441,7 +16428,7 @@ QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_psoc *psoc,
 		} else {
 			sme_err("Self peer not found with MAC addr:"
 				QDF_MAC_ADDR_FMT,
-				QDF_MAC_ADDR_REF(old_mac_addr_bytes));
+				QDF_MAC_ADDR_REF(old_macaddr));
 				return QDF_STATUS_E_INVAL;
 		}
 	}
@@ -16452,22 +16439,14 @@ QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_psoc *psoc,
 			qdf_ret_status = wlan_mlo_mgr_update_mld_addr(
 					    (struct qdf_mac_addr *)
 					       wlan_vdev_mlme_get_mldaddr(vdev),
-					    &mac_addr);
+					    &mld_addr);
 			if (QDF_IS_STATUS_ERROR(qdf_ret_status))
 				return qdf_ret_status;
 		}
-		wlan_vdev_mlme_set_mldaddr(vdev, mac_addr.bytes);
-		/* Currently the design is to use same MAC for
-		 * MLD and Link for SAP so update link and MAC addr.
-		 */
-		if (vdev_opmode == QDF_SAP_MODE) {
-			wlan_vdev_mlme_set_macaddr(vdev, mac_addr.bytes);
-			wlan_vdev_mlme_set_linkaddr(vdev, mac_addr.bytes);
-		}
-	} else {
-		wlan_vdev_mlme_set_macaddr(vdev, mac_addr.bytes);
-		wlan_vdev_mlme_set_linkaddr(vdev, mac_addr.bytes);
+		wlan_vdev_mlme_set_mldaddr(vdev, mld_addr.bytes);
 	}
+	wlan_vdev_mlme_set_macaddr(vdev, mac_addr.bytes);
+	wlan_vdev_mlme_set_linkaddr(vdev, mac_addr.bytes);
 
 p2p_self_peer_create:
 	if (vdev_opmode == QDF_P2P_DEVICE_MODE) {