Browse Source

qcacld-3.0: Add changes to handle self roaming

For mlo roaming, roam sync will be handled on
link vdev/s first and then assoc link vdev.
In case of mlo self roaming, an issue is observed
during peer creation as one already exists on other link.

To solve this all link peers will be deleted
while handling roam synch on first link.

Change-Id: I4d3ff71dd7c8b54f3f06b0147ce23ac8bfe5f49b
CRs-Fixed: 3421698
Amruta Kulkarni 2 years ago
parent
commit
91d49f075a

+ 37 - 0
components/umac/mlme/mlo_mgr/inc/wlan_mlo_mgr_roam.h

@@ -131,6 +131,17 @@ mlo_roam_get_link_id(uint8_t vdev_id,
 bool
 is_multi_link_roam(struct roam_offload_synch_ind *sync_ind);
 
+/**
+ * mlo_roam_get_num_of_setup_links - get number of setup links
+ * @sync_ind: roam sync ind pointer
+ *
+ * This api will be called to get number of setup links after roaming
+ *
+ * Return: true/false
+ */
+uint8_t
+mlo_roam_get_num_of_setup_links(struct roam_offload_synch_ind *sync_ind);
+
 /**
  * mlo_enable_rso - Enable rso on assoc vdev
  *
@@ -371,6 +382,19 @@ void
 mlo_roam_set_link_id(struct wlan_objmgr_vdev *vdev,
 		     struct roam_offload_synch_ind *sync_ind);
 
+/**
+ * mlo_is_roaming_in_progress - check if roaming is in progress
+ * @psoc: psoc pointer
+ * @vdev_id: vdev id
+ *
+ * This api will be called to check if roaming in progress on any
+ * of the mlo links.
+ *
+ * Return: boolean (true or false)
+ */
+bool
+mlo_is_roaming_in_progress(struct wlan_objmgr_psoc *psoc,
+			   uint8_t vdev_id);
 #else /* WLAN_FEATURE_11BE_MLO */
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 static inline
@@ -421,6 +445,12 @@ is_multi_link_roam(struct roam_offload_synch_ind *sync_ind)
 	return false;
 }
 
+static inline uint8_t
+mlo_roam_get_num_of_setup_links(struct roam_offload_synch_ind *sync_ind)
+{
+	return 0;
+}
+
 static inline
 QDF_STATUS mlo_enable_rso(struct wlan_objmgr_pdev *pdev,
 			  struct wlan_objmgr_vdev *vdev,
@@ -526,5 +556,12 @@ mlo_roam_get_link_freq_from_mac_addr(struct roam_offload_synch_ind *sync_ind,
 {
 	return 0;
 }
+
+static inline bool
+mlo_is_roaming_in_progress(struct wlan_objmgr_psoc *psoc,
+			   uint8_t vdev_id)
+{
+	return false;
+}
 #endif /* WLAN_FEATURE_11BE_MLO */
 #endif

+ 55 - 0
components/umac/mlme/mlo_mgr/src/wlan_mlo_mgr_roam.c

@@ -448,6 +448,17 @@ bool is_multi_link_roam(struct roam_offload_synch_ind *sync_ind)
 	return false;
 }
 
+uint8_t
+mlo_roam_get_num_of_setup_links(struct roam_offload_synch_ind *sync_ind)
+{
+	if (!sync_ind) {
+		mlo_err("Roam Sync ind is null");
+		return WLAN_INVALID_VDEV_ID;
+	}
+
+	return sync_ind->num_setup_links;
+}
+
 uint32_t
 mlo_roam_get_link_freq_from_mac_addr(struct roam_offload_synch_ind *sync_ind,
 				     uint8_t *link_mac_addr)
@@ -1273,3 +1284,47 @@ end:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
 	return status;
 }
+
+bool
+mlo_is_roaming_in_progress(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	bool is_roaming_in_progress = false;
+	uint8_t link_vdev_id;
+	uint8_t i;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_MLME_OBJMGR_ID);
+	if (!vdev) {
+		mlme_err("vdev object is NULL for vdev %d", vdev_id);
+		return false;
+	}
+
+	mlo_dev_ctx = vdev->mlo_dev_ctx;
+	if (!mlo_dev_ctx) {
+		mlme_err("mlo_dev_ctx object is NULL for vdev %d", vdev_id);
+		goto end;
+	}
+
+	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
+		if (!mlo_dev_ctx->wlan_vdev_list[i])
+			continue;
+
+		link_vdev_id = wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]);
+		if (link_vdev_id == WLAN_INVALID_VDEV_ID) {
+			mlme_err("invalid vdev id");
+			goto end;
+		}
+
+		if (wlan_cm_is_roam_sync_in_progress(psoc, link_vdev_id)) {
+			is_roaming_in_progress = true;
+			goto end;
+		}
+	}
+
+end:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
+	return is_roaming_in_progress;
+}
+

+ 42 - 0
core/mac/src/pe/lim/lim_mlo.c

@@ -436,6 +436,48 @@ void lim_mlo_sta_notify_peer_disconn(struct pe_session *pe_session)
 	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
 }
 
+void lim_mlo_roam_peer_disconn_del(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_objmgr_peer *peer;
+	struct wlan_objmgr_psoc *psoc;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct qdf_mac_addr bssid;
+
+	if (!vdev) {
+		pe_err("vdev is null");
+		return;
+	}
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		pe_err("psoc is null");
+		return;
+	}
+
+	status = wlan_vdev_get_bss_peer_mac(vdev, &bssid);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		pe_err("vdev id %d : failed to get bssid",
+		       wlan_vdev_get_id(vdev));
+		return;
+	}
+
+	peer = wlan_objmgr_get_peer_by_mac(psoc,
+					   bssid.bytes,
+					   WLAN_LEGACY_MAC_ID);
+	if (!peer) {
+		pe_err("peer is null");
+		return;
+	}
+
+	if (wlan_peer_mlme_flag_ext_get(peer, WLAN_PEER_FEXT_MLO)) {
+		pe_debug("vdev id %d disconn del peer", wlan_vdev_get_id(vdev));
+		wlan_mlo_partner_peer_disconnect_notify(peer);
+		wlan_mlo_link_peer_delete(peer);
+	}
+
+	wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
+}
+
 void lim_mlo_cleanup_partner_peer(struct wlan_objmgr_peer *peer)
 {
 	struct mac_context *mac_ctx;

+ 12 - 0
core/mac/src/pe/lim/lim_mlo.h

@@ -72,6 +72,15 @@ struct pe_session *pe_find_partner_session_by_link_id(
 void lim_get_mlo_vdev_list(struct pe_session *session, uint16_t *vdev_count,
 			   struct wlan_objmgr_vdev **wlan_vdev_list);
 
+/**
+ * lim_mlo_roam_peer_disconn_del - trigger mlo to delete partner peer
+ *                                 This API is only for MLO STA roam.
+ * @vdev: vdev pointer
+ *
+ * Return: void
+ */
+void lim_mlo_roam_peer_disconn_del(struct wlan_objmgr_vdev *vdev);
+
 /**
  * lim_mlo_notify_peer_disconn - trigger mlo to delete partner peer
  * @pe_session: pe session
@@ -382,6 +391,9 @@ QDF_STATUS lim_get_bpcc_from_mlo_ie(tSchBeaconStruct *bcn,
 bool lim_check_cu_happens(struct wlan_objmgr_vdev *vdev, uint8_t new_bpcc);
 
 #else
+static inline void lim_mlo_roam_peer_disconn_del(struct wlan_objmgr_vdev *vdev)
+{
+}
 static inline void lim_mlo_notify_peer_disconn(struct pe_session *pe_session,
 					       tpDphHashNode sta_ds)
 {

+ 4 - 2
core/wma/src/wma_dev_if.c

@@ -5597,7 +5597,8 @@ void wma_delete_sta(tp_wma_handle wma, tpDeleteStaParams del_sta)
 	switch (oper_mode) {
 	case BSS_OPERATIONAL_MODE_STA:
 		if (wlan_cm_is_roam_sync_in_progress(wma->psoc, vdev_id) ||
-		    MLME_IS_MLO_ROAM_SYNCH_IN_PROGRESS(wma->psoc, vdev_id)) {
+		    MLME_IS_MLO_ROAM_SYNCH_IN_PROGRESS(wma->psoc, vdev_id) ||
+		    mlo_is_roaming_in_progress(wma->psoc, vdev_id)) {
 			wma_debug("LFR3: Del STA on vdev_id %d", vdev_id);
 			qdf_mem_free(del_sta);
 			return;
@@ -5876,7 +5877,8 @@ void wma_delete_bss(tp_wma_handle wma, uint8_t vdev_id)
 	}
 
 	if (wlan_cm_is_roam_sync_in_progress(wma->psoc, vdev_id) ||
-	    MLME_IS_MLO_ROAM_SYNCH_IN_PROGRESS(wma->psoc, vdev_id)) {
+	    MLME_IS_MLO_ROAM_SYNCH_IN_PROGRESS(wma->psoc, vdev_id) ||
+	    mlo_is_roaming_in_progress(wma->psoc, vdev_id)) {
 		roam_synch_in_progress = true;
 		wma_debug("LFR3: Setting vdev_up to FALSE for vdev:%d",
 			  vdev_id);

+ 98 - 11
core/wma/src/wma_scan_roam.c

@@ -90,6 +90,7 @@
 #include <../../core/src/wlan_cm_roam_i.h>
 #include "wlan_cm_roam_api.h"
 #include "wlan_mlo_mgr_roam.h"
+#include "lim_mlo.h"
 #ifdef FEATURE_WLAN_EXTSCAN
 #define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION WAKELOCK_DURATION_RECOMMENDED
 
@@ -547,6 +548,77 @@ wma_send_roam_preauth_status(tp_wma_handle wma_handle,
 #endif
 
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * wma_delete_all_peers() - Delete all bss peer/s
+ * @wma: Global WMA Handle
+ * @vdev_id: vdev id
+ * @del_sta_params: parameters required for del sta request
+ *
+ * This function will perform deleting of all the link peers
+ * after self roaming.
+ *
+ * Return: None
+ */
+static QDF_STATUS
+wma_delete_all_peers(tp_wma_handle wma,
+		     uint8_t vdev_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	uint8_t i;
+	uint8_t link_vdev_id;
+	tDeleteStaParams *del_sta_params;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
+						    WLAN_MLME_OBJMGR_ID);
+	if (!vdev) {
+		mlme_err("vdev object is NULL for vdev %d", vdev_id);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	mlo_dev_ctx = vdev->mlo_dev_ctx;
+	if (!mlo_dev_ctx) {
+		mlme_err("mlo_dev_ctx object is NULL for vdev %d", vdev_id);
+		status = QDF_STATUS_E_NULL_VALUE;
+		goto end;
+	}
+
+	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
+		if (!mlo_dev_ctx->wlan_vdev_list[i])
+			continue;
+
+		del_sta_params = qdf_mem_malloc(sizeof(*del_sta_params));
+		if (!del_sta_params) {
+			status = QDF_STATUS_E_NOMEM;
+			goto end;
+		}
+		lim_mlo_roam_peer_disconn_del(mlo_dev_ctx->wlan_vdev_list[i]);
+		qdf_mem_zero(del_sta_params, sizeof(*del_sta_params));
+		link_vdev_id = wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]);
+		if (link_vdev_id == WLAN_INVALID_VDEV_ID) {
+			mlme_err("invalid vdev id");
+			status = QDF_STATUS_E_INVAL;
+			goto end;
+		}
+		del_sta_params->smesessionId = link_vdev_id;
+		wma_delete_sta(wma, del_sta_params);
+		wma_delete_bss(wma, link_vdev_id);
+	}
+
+end:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
+	return status;
+}
+#else
+static inline  QDF_STATUS
+wma_delete_all_peers(tp_wma_handle wma,
+		     uint8_t vdev_id)
+{
+	return QDF_STATUS_E_FAILURE;
+}
+#endif
 /**
  * wma_roam_update_vdev() - Update the STA and BSS
  * @wma: Global WMA Handle
@@ -569,6 +641,7 @@ wma_roam_update_vdev(tp_wma_handle wma,
 	int32_t uc_cipher, cipher_cap;
 	bool is_assoc_peer = false;
 	struct qdf_mac_addr mac_addr;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	vdev_id = roamed_vdev_id;
 	wma->interfaces[vdev_id].nss = roam_synch_ind_ptr->nss;
@@ -584,14 +657,8 @@ wma_roam_update_vdev(tp_wma_handle wma,
 		wma->interfaces[vdev_id].ch_freq =
 			roam_synch_ind_ptr->chan_freq;
 
-	del_sta_params = qdf_mem_malloc(sizeof(*del_sta_params));
-	if (!del_sta_params) {
-		return;
-	}
-
 	add_sta_params = qdf_mem_malloc(sizeof(*add_sta_params));
 	if (!add_sta_params) {
-		qdf_mem_free(del_sta_params);
 		return;
 	}
 
@@ -601,14 +668,35 @@ wma_roam_update_vdev(tp_wma_handle wma,
 	else
 		mac_addr = roam_synch_ind_ptr->bssid;
 
-	qdf_mem_zero(del_sta_params, sizeof(*del_sta_params));
 	qdf_mem_zero(add_sta_params, sizeof(*add_sta_params));
 
-	del_sta_params->smesessionId = vdev_id;
+	/* With self roaming on multi link AP, as the same
+	 * peer already exists, new peer creation fails
+	 * To handle this delete all link peers,
+	 * while doing roam sync on first link.
+	 */
+	if (is_multi_link_roam(roam_synch_ind_ptr)) {
+		if (wlan_vdev_mlme_get_is_mlo_link(wma->psoc, vdev_id) ||
+		    mlo_roam_get_num_of_setup_links(roam_synch_ind_ptr) == 1) {
+			status = wma_delete_all_peers(wma, vdev_id);
+			if (QDF_IS_STATUS_ERROR(status))
+				goto end;
+		}
+	} else {
+		del_sta_params = qdf_mem_malloc(sizeof(*del_sta_params));
+		if (!del_sta_params)
+			goto end;
+
+		qdf_mem_zero(del_sta_params, sizeof(*del_sta_params));
+		del_sta_params->smesessionId = vdev_id;
+		wma_delete_sta(wma, del_sta_params);
+		wma_delete_bss(wma, vdev_id);
+	}
+
 	add_sta_params->staType = STA_ENTRY_SELF;
 	add_sta_params->smesessionId = vdev_id;
 	qdf_mem_copy(&add_sta_params->bssId, &mac_addr,
-		     QDF_MAC_ADDR_SIZE);
+			 QDF_MAC_ADDR_SIZE);
 	add_sta_params->assocId = roam_synch_ind_ptr->aid;
 
 	bssid = wma_get_vdev_bssid(wma->interfaces[vdev_id].vdev);
@@ -617,8 +705,6 @@ wma_roam_update_vdev(tp_wma_handle wma,
 		return;
 	}
 
-	wma_delete_sta(wma, del_sta_params);
-	wma_delete_bss(wma, vdev_id);
 	is_assoc_peer = wlan_vdev_mlme_get_is_mlo_vdev(wma->psoc, vdev_id);
 	if (is_multi_link_roam(roam_synch_ind_ptr)) {
 		wma_create_peer(wma, mac_addr.bytes,
@@ -652,6 +738,7 @@ wma_roam_update_vdev(tp_wma_handle wma,
 		     QDF_MAC_ADDR_SIZE);
 	lim_fill_roamed_peer_twt_caps(wma->mac_context, vdev_id,
 				      roam_synch_ind_ptr);
+end:
 	qdf_mem_free(add_sta_params);
 }