فهرست منبع

qcacmn: Add force flag support for PTQM migration

Add force flag support for PTQM migration.
This flag will be used to allow migration to vdevs which are not
allowed to be selected as primary by using the ini config.
This will be helpful in scenarios where if the current primary link is
going down and peer ptqm needs to be migrated but the partner links of
that mld are the user disabled links for ptqm.
Also add skip_pumac_cnt to mark a link to be skipped from being selected
as new primary

Change-Id: Ia8c7881f37d32211a732c5c7394c4a608099b62a
CRs-Fixed: 3548552
Himanshu Batra 2 سال پیش
والد
کامیت
444fa57930

+ 80 - 0
umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h

@@ -349,6 +349,7 @@ struct wlan_channel {
  * @mlo_link_id: link id for mlo connection
  * @mlo_external_sae_auth: MLO external SAE auth
  * @wlan_vdev_mlo_lock: lock to protect the set/clear of
+ * @skip_pumac_cnt: Counter to skip vdev to be selected as pumac
  * WLAN_VDEV_FEXT2_MLO feature flag in vdev MLME
  */
 struct wlan_objmgr_vdev_mlme {
@@ -375,6 +376,9 @@ struct wlan_objmgr_vdev_mlme {
 #else
 	qdf_mutex_t wlan_vdev_mlo_lock;
 #endif
+#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
+	qdf_atomic_t skip_pumac_cnt;
+#endif
 #endif
 };
 
@@ -2254,4 +2258,80 @@ static inline bool wlan_mlo_peer_delete_is_not_allowed(
 				WLAN_VDEV_OP_MLME_LEGACY_PEER_DISCON_TRIG);
 }
 
+#ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
+/**
+ * wlan_vdev_init_skip_pumac_cnt() - init skip_pumac_cnt
+ * @vdev: VDEV object
+ *
+ * API to initialize skip_pumac_cnt
+ *
+ * Return: void
+ */
+static inline void
+wlan_vdev_init_skip_pumac_cnt(struct wlan_objmgr_vdev *vdev)
+{
+	qdf_atomic_init(&vdev->vdev_mlme.skip_pumac_cnt);
+}
+
+/**
+ * wlan_vdev_inc_skip_pumac_cnt() - inc skip_pumac_cnt
+ * @vdev: VDEV object
+ *
+ * API to increment skip_pumac_cnt
+ *
+ * Return: void
+ */
+static inline void
+wlan_vdev_inc_skip_pumac_cnt(struct wlan_objmgr_vdev *vdev)
+{
+	qdf_atomic_inc(&vdev->vdev_mlme.skip_pumac_cnt);
+}
+
+/**
+ * wlan_vdev_dec_skip_pumac_cnt() - dec skip_pumac_cnt
+ * @vdev: VDEV object
+ *
+ * API to decrement skip_pumac_cnt
+ *
+ * Return: void
+ */
+static inline void
+wlan_vdev_dec_skip_pumac_cnt(struct wlan_objmgr_vdev *vdev)
+{
+	qdf_atomic_dec(&vdev->vdev_mlme.skip_pumac_cnt);
+}
+
+/**
+ * wlan_vdev_read_skip_pumac_cnt() - read skip_pumac_cnt
+ * @vdev: VDEV object
+ *
+ * API to read skip_pumac_cnt value
+ *
+ * Return: skip_pumac_cnt value
+ */
+static inline int32_t
+wlan_vdev_read_skip_pumac_cnt(struct wlan_objmgr_vdev *vdev)
+{
+	return qdf_atomic_read(&vdev->vdev_mlme.skip_pumac_cnt);
+}
+#else
+static inline void
+wlan_vdev_init_skip_pumac_cnt(struct wlan_objmgr_vdev *vdev)
+{ }
+
+static inline void
+wlan_vdev_inc_skip_pumac_cnt(struct wlan_objmgr_vdev *vdev)
+{ }
+
+static inline void
+wlan_vdev_dec_skip_pumac_cnt(struct wlan_objmgr_vdev *vdev)
+{ }
+
+static inline int32_t
+wlan_vdev_read_skip_pumac_cnt(struct wlan_objmgr_vdev *vdev)
+{
+	return 0;
+}
+#endif
+
 #endif /* _WLAN_OBJMGR_VDEV_OBJ_H_*/

+ 1 - 0
umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c

@@ -236,6 +236,7 @@ struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create(
 		vdev->vdev_objmgr.max_peer_count =
 				wlan_pdev_get_max_peer_count(pdev);
 
+	wlan_vdev_init_skip_pumac_cnt(vdev);
 	if (params->legacy_osif)
 		vdev->vdev_nif.osdev->legacy_osif_priv = params->legacy_osif;
 

+ 4 - 1
umac/mlo_mgr/inc/wlan_mlo_mgr_cmn.h

@@ -642,11 +642,14 @@ void mlo_mlme_ptqm_migrate_timer_cb(void *arg);
  * @link_migration: flag to indicate if all peers of vdev need migration
  * or individual peer migration
  * @link_id: link id for new ptqm
+ * @force_mig: allow migration to vdevs which are disabled to be pumac
+ * using primary_umac_skip ini
  *
  * Return: Success if migration is triggered, else failure
  */
 QDF_STATUS wlan_mlo_set_ptqm_migration(struct wlan_objmgr_vdev *vdev,
 				       struct wlan_mlo_peer_context *ml_peer,
 				       bool link_migration,
-				       uint32_t link_id);
+				       uint32_t link_id,
+				       bool force_mig);
 #endif

+ 4 - 1
umac/mlo_mgr/inc/wlan_mlo_mgr_peer.h

@@ -766,6 +766,8 @@ void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer);
  * wlan_mld_get_best_primary_umac_w_rssi() - API to get primary umac using rssi
  * @ml_peer: ml peer object
  * @link_vdevs: list of vdevs from which new primary link is to be selected
+ * @allow_all_links: Flag to allow all links to be able to get selected as
+ * primary. This flag will be used to override primary_umac_skip ini
  *
  * API to get primary umac using rssi
  *
@@ -773,5 +775,6 @@ void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer);
  */
 uint8_t
 wlan_mld_get_best_primary_umac_w_rssi(struct wlan_mlo_peer_context *ml_peer,
-				      struct wlan_objmgr_vdev *link_vdevs[]);
+				      struct wlan_objmgr_vdev *link_vdevs[],
+				      bool allow_all_links);
 #endif

+ 121 - 40
umac/mlo_mgr/src/wlan_mlo_mgr_primary_umac.c

@@ -134,7 +134,8 @@ static QDF_STATUS mld_get_link_rssi(struct mlo_all_link_rssi *rssi_data)
 
 uint8_t
 wlan_mld_get_best_primary_umac_w_rssi(struct wlan_mlo_peer_context *ml_peer,
-				      struct wlan_objmgr_vdev *link_vdevs[])
+				      struct wlan_objmgr_vdev *link_vdevs[],
+				      bool allow_all_links)
 {
 	struct mlo_all_link_rssi rssi_data;
 	uint8_t i;
@@ -187,7 +188,7 @@ wlan_mld_get_best_primary_umac_w_rssi(struct wlan_mlo_peer_context *ml_peer,
 		if (id >= WLAN_OBJMGR_MAX_DEVICES)
 			continue;
 
-		if (wlan_vdev_skip_pumac(link_vdevs[i])) {
+		if (!allow_all_links && wlan_vdev_skip_pumac(link_vdevs[i])) {
 			mlo_err("Skip Radio for Primary MLO umac");
 			mld_sta_links[id] = false;
 			continue;
@@ -338,7 +339,7 @@ wlan_mld_get_best_primary_umac_w_rssi(struct wlan_mlo_peer_context *ml_peer,
 		if (!link_vdevs[i])
 			continue;
 
-		if (wlan_vdev_skip_pumac(link_vdevs[i])) {
+		if (!allow_all_links && wlan_vdev_skip_pumac(link_vdevs[i])) {
 			mlo_debug("Skip Radio for Primary MLO umac");
 			continue;
 		}
@@ -686,7 +687,7 @@ QDF_STATUS mlo_peer_allocate_primary_umac(
 				    wlan_peer_get_vdev(assoc_peer));
 
 	ml_peer->primary_umac_psoc_id =
-		wlan_mld_get_best_primary_umac_w_rssi(ml_peer, link_vdevs);
+		wlan_mld_get_best_primary_umac_w_rssi(ml_peer, link_vdevs, false);
 
 	mlo_peer_assign_primary_umac(ml_peer, peer_entry);
 
@@ -909,6 +910,8 @@ wlan_mlo_send_ptqm_migrate_cmd(struct wlan_objmgr_vdev *vdev,
  * @ml_peer: ml peer object
  * @new_primary_link_id: new primary link id
  * @new_hw_link_id: hw link id for new primary TQM
+ * @force_mig: allow migration to vdevs which are disabled to be pumac
+ * using primary_umac_skip ini
  *
  * API to get new ptqm ID
  *
@@ -918,15 +921,18 @@ static QDF_STATUS
 wlan_mlo_get_new_ptqm_id(struct wlan_objmgr_vdev *curr_vdev,
 			 struct wlan_mlo_peer_context *ml_peer,
 			 uint8_t new_primary_link_id,
-			 uint16_t *new_hw_link_id)
+			 uint16_t *new_hw_link_id,
+			 bool force_mig)
 {
 	uint8_t current_primary_link_id = WLAN_LINK_ID_INVALID;
 	struct wlan_objmgr_vdev *tmp_vdev = NULL;
 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
+	struct wlan_objmgr_vdev *tmp_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
 	struct wlan_mlo_link_peer_entry *peer_entry;
 	uint8_t psoc_ids[WLAN_UMAC_MLO_MAX_VDEVS];
+	struct wlan_objmgr_vdev *link_vdev = NULL;
 	QDF_STATUS status;
-	uint8_t i = 0, idx = 0, j = 0;
+	uint8_t i = 0, idx = 0, j = 0, tmp_cnt = 0;
 
 	if (wlan_vdev_mlme_get_opmode(curr_vdev) == QDF_SAP_MODE &&
 	    QDF_IS_STATUS_ERROR(wlan_mlo_peer_is_assoc_done(ml_peer))) {
@@ -949,6 +955,23 @@ wlan_mlo_get_new_ptqm_id(struct wlan_objmgr_vdev *curr_vdev,
 		return QDF_STATUS_E_INVAL;
 	}
 
+	if (new_primary_link_id != WLAN_LINK_ID_INVALID) {
+		link_vdev = mlo_get_vdev_by_link_id(curr_vdev,
+						    new_primary_link_id);
+		if (!link_vdev) {
+			mlo_err("links vdev not found for link id %d",
+				new_primary_link_id);
+			return QDF_STATUS_E_INVAL;
+		}
+
+		if (wlan_vdev_read_skip_pumac_cnt(link_vdev) > 0) {
+			mlo_err("Selected new ptqm link not allowed for migration");
+			mlo_release_vdev_ref(link_vdev);
+			return QDF_STATUS_E_PERM;
+		}
+		mlo_release_vdev_ref(link_vdev);
+	}
+
 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
 		peer_entry = &ml_peer->peer_list[i];
 		if (!peer_entry || !peer_entry->link_peer)
@@ -986,37 +1009,90 @@ wlan_mlo_get_new_ptqm_id(struct wlan_objmgr_vdev *curr_vdev,
 			mlo_err("failed to get vdev ref");
 			continue;
 		}
+
+		if (wlan_vdev_read_skip_pumac_cnt(tmp_vdev) > 0) {
+			mlo_debug("Vdev not allowed for migration, skip this vdev");
+			wlan_objmgr_vdev_release_ref(tmp_vdev,
+						     WLAN_MLME_SB_ID);
+			continue;
+		}
+
+		/* Store vdevs which cannot be selected as primary in a temp
+		 * list. force_mig flag will be used to allow migration to vdevs
+		 * which are not allowed to be selected as primary by using the
+		 * primary_umac_skip ini config. This will be helpful in scenarios
+		 * where if the current primary link is going down and peer ptqm
+		 * needs to be migrated but the partner links ofthat mld are
+		 * the user disabled links for ptqm.
+		 */
+		if (wlan_vdev_skip_pumac(tmp_vdev)) {
+			mlo_debug("Vdev cannot be selected as primary");
+			tmp_vdev_list[tmp_cnt++] = tmp_vdev;
+			continue;
+		}
 		wlan_vdev_list[idx++] = tmp_vdev;
 	}
 
 	if (new_primary_link_id == WLAN_LINK_ID_INVALID) {
 		mlo_debug("Invalid link id provided, select new link id");
-		ml_peer->migrate_primary_umac_psoc_id =
-			wlan_mld_get_best_primary_umac_w_rssi(ml_peer, wlan_vdev_list);
-		if (ml_peer->migrate_primary_umac_psoc_id ==
-					ML_PRIMARY_UMAC_ID_INVAL) {
-			mlo_err("Unable to fetch new primary link id for ml peer " QDF_MAC_ADDR_FMT,
-				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
-			goto exit;
-		}
-		for (i = 0; i < idx; i++) {
+		/* If there are no vdevs present in wlan_vdev_list, means none
+		 * of the partner vdevs of current MLD are eligible to become
+		 * primary umac. In that case if user has requested force
+		 * migration and there are some vdevs present in temp_vdev_list,
+		 * select new primary umac from those vdev. If no vdevs are
+		 * prenset in any of the list, return failure.
+		 */
+		if (idx == 0) {
+			if (!force_mig || tmp_cnt == 0) {
+				mlo_err("No link available to be selected as primary");
+				goto exit;
+			} else {
+				ml_peer->migrate_primary_umac_psoc_id =
+					wlan_mld_get_best_primary_umac_w_rssi(
+							ml_peer,
+							tmp_vdev_list,
+							true);
+				if (ml_peer->migrate_primary_umac_psoc_id ==
+						ML_PRIMARY_UMAC_ID_INVAL) {
+					mlo_err("Unable to fetch new primary link id for ml peer " QDF_MAC_ADDR_FMT,
+						QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
+					goto exit;
+				}
+
+				for (i = 0; i < tmp_cnt; i++) {
+					if (ml_peer->migrate_primary_umac_psoc_id ==
+							wlan_vdev_get_psoc_id(tmp_vdev_list[i])) {
+						*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
+								wlan_vdev_get_pdev(tmp_vdev_list[i]));
+						break;
+					}
+				}
+			}
+		} else {
+			ml_peer->migrate_primary_umac_psoc_id =
+				wlan_mld_get_best_primary_umac_w_rssi(
+							ml_peer,
+							wlan_vdev_list,
+							false);
 			if (ml_peer->migrate_primary_umac_psoc_id ==
-				wlan_vdev_get_psoc_id(wlan_vdev_list[i])) {
-				*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
+					ML_PRIMARY_UMAC_ID_INVAL) {
+				mlo_err("Unable to fetch new primary link id for ml peer " QDF_MAC_ADDR_FMT,
+					QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
+				goto exit;
+			}
+			for (i = 0; i < idx; i++) {
+				if (ml_peer->migrate_primary_umac_psoc_id ==
+						wlan_vdev_get_psoc_id(wlan_vdev_list[i])) {
+					*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
 							wlan_vdev_get_pdev(wlan_vdev_list[i]));
-				break;
+					break;
+				}
 			}
 		}
 	} else {
 		/* check if provided link id is part of current ml peer links */
 		for (i = 0; i < idx; i++) {
 			if (new_primary_link_id == wlan_vdev_get_link_id(wlan_vdev_list[i])) {
-				/* Check if the soc is enabled to be pumac or not */
-				if (wlan_vdev_skip_pumac(wlan_vdev_list[i])) {
-					mlo_err("Given link %d cannot be selected as primary",
-						new_primary_link_id);
-					goto exit;
-				}
 				*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
 							wlan_vdev_get_pdev(wlan_vdev_list[i]));
 				ml_peer->migrate_primary_umac_psoc_id =
@@ -1024,6 +1100,18 @@ wlan_mlo_get_new_ptqm_id(struct wlan_objmgr_vdev *curr_vdev,
 				break;
 			}
 		}
+		if (*new_hw_link_id == INVALID_HW_LINK_ID && force_mig) {
+			for (i = 0; i < tmp_cnt; i++) {
+				if (new_primary_link_id ==
+				    wlan_vdev_get_link_id(tmp_vdev_list[i])) {
+					*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
+								wlan_vdev_get_pdev(tmp_vdev_list[i]));
+					ml_peer->migrate_primary_umac_psoc_id =
+							wlan_vdev_get_psoc_id(tmp_vdev_list[i]);
+					break;
+				}
+			}
+		}
 	}
 
 	if (*new_hw_link_id == INVALID_HW_LINK_ID) {
@@ -1032,18 +1120,13 @@ wlan_mlo_get_new_ptqm_id(struct wlan_objmgr_vdev *curr_vdev,
 		goto exit;
 	}
 
-	if (i < idx) {
-		if (wlan_vdev_mlme_op_flags_get(wlan_vdev_list[i],
-						WLAN_VDEV_OP_MLO_LINK_REMOVAL_IN_PROGRESS)) {
-			mlo_err("New selected primary link is going for removal, skip migration");
-			goto exit;
-		}
-	}
-
 	for (i = 0; i < idx; i++)
 		wlan_objmgr_vdev_release_ref(wlan_vdev_list[i],
 					     WLAN_MLME_SB_ID);
 
+	for (i = 0; i < tmp_cnt; i++)
+		wlan_objmgr_vdev_release_ref(tmp_vdev_list[i],
+					     WLAN_MLME_SB_ID);
 	return QDF_STATUS_SUCCESS;
 
 exit:
@@ -1053,6 +1136,9 @@ exit:
 		wlan_objmgr_vdev_release_ref(wlan_vdev_list[i],
 					     WLAN_MLME_SB_ID);
 
+	for (i = 0; i < tmp_cnt; i++)
+		wlan_objmgr_vdev_release_ref(tmp_vdev_list[i],
+					     WLAN_MLME_SB_ID);
 	return QDF_STATUS_E_FAILURE;
 }
 
@@ -1175,7 +1261,7 @@ static void wlan_mlo_build_ptqm_migrate_list(struct wlan_objmgr_vdev *vdev,
 
 	status = wlan_mlo_get_new_ptqm_id(vdev, ml_peer,
 					  WLAN_LINK_ID_INVALID,
-					  &new_hw_link_id);
+					  &new_hw_link_id, true);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		mlo_err("peer " QDF_MAC_ADDR_FMT " unable to get new ptqm id",
 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
@@ -1239,7 +1325,7 @@ static QDF_STATUS wlan_mlo_trigger_link_ptqm_migration(
 QDF_STATUS wlan_mlo_set_ptqm_migration(struct wlan_objmgr_vdev *vdev,
 				       struct wlan_mlo_peer_context *ml_peer,
 				       bool link_migration,
-				       uint32_t link_id)
+				       uint32_t link_id, bool force_mig)
 {
 	uint16_t new_hw_link_id = INVALID_HW_LINK_ID;
 	struct peer_migrate_ptqm_multi_entries migrate_list = {0};
@@ -1260,11 +1346,6 @@ QDF_STATUS wlan_mlo_set_ptqm_migration(struct wlan_objmgr_vdev *vdev,
 	}
 
 	if (link_migration) {
-		if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_LINK_REMOVAL_IN_PROGRESS)) {
-			mlo_err("Link removal in progress, skip umac migration for vdev:%d",
-				wlan_vdev_get_id(vdev));
-			return QDF_STATUS_E_INVAL;
-		}
 		mlo_err("Trigger migration for full link");
 		// trigger full link migration
 		status = wlan_mlo_trigger_link_ptqm_migration(vdev);
@@ -1298,7 +1379,7 @@ QDF_STATUS wlan_mlo_set_ptqm_migration(struct wlan_objmgr_vdev *vdev,
 	}
 
 	status = wlan_mlo_get_new_ptqm_id(curr_vdev, ml_peer,
-					  link_id, &new_hw_link_id);
+					  link_id, &new_hw_link_id, force_mig);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		mlo_err("peer " QDF_MAC_ADDR_FMT " unable to get new ptqm id",
 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));