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
This commit is contained in:
Amruta Kulkarni
2023-01-27 15:56:51 -08:00
committed by Madan Koyyalamudi
parent dc452f6fbb
commit 91d49f075a
6 changed files with 248 additions and 13 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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);
}