diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h index b8983564b5..20f2fe21e0 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_vdev_obj.h +++ b/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_*/ diff --git a/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c b/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c index 55c66ec28c..e4ebb295a5 100644 --- a/umac/cmn_services/obj_mgr/src/wlan_objmgr_vdev_obj.c +++ b/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; diff --git a/umac/mlo_mgr/inc/wlan_mlo_mgr_cmn.h b/umac/mlo_mgr/inc/wlan_mlo_mgr_cmn.h index 6c738101f3..edfe7e4391 100644 --- a/umac/mlo_mgr/inc/wlan_mlo_mgr_cmn.h +++ b/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 diff --git a/umac/mlo_mgr/inc/wlan_mlo_mgr_peer.h b/umac/mlo_mgr/inc/wlan_mlo_mgr_peer.h index 3f40f40b24..acc96fef66 100644 --- a/umac/mlo_mgr/inc/wlan_mlo_mgr_peer.h +++ b/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 diff --git a/umac/mlo_mgr/src/wlan_mlo_mgr_primary_umac.c b/umac/mlo_mgr/src/wlan_mlo_mgr_primary_umac.c index 34d726d7b6..6d121f5a79 100644 --- a/umac/mlo_mgr/src/wlan_mlo_mgr_primary_umac.c +++ b/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));