qcacld-3.0: Add api's to handle MLO Roaming

- New api's added to handle mlo roaming scenarios.
- Read and store link addr from wmi.

Change-Id: I6a18802d27f72235dc69d2eedb05f3e563d1b0f4
CRs-Fixed: 2997105
This commit is contained in:
Amruta Kulkarni
2021-12-20 16:07:27 -08:00
committed by Madan Koyyalamudi
parent 5017adcd22
commit 24f04ca536
7 changed files with 393 additions and 6 deletions

View File

@@ -37,6 +37,7 @@
#include "connection_mgr/core/src/wlan_cm_sm.h"
#include "connection_mgr/core/src/wlan_cm_main_api.h"
#include "wlan_roam_debug.h"
#include "wlan_mlo_mgr_roam.h"
#define FW_ROAM_SYNC_TIMEOUT 7000
@@ -353,7 +354,7 @@ cm_roam_sync_event_handler(struct wlan_objmgr_psoc *psoc,
uint32_t len,
struct roam_offload_synch_ind *sync_ind)
{
return cm_fw_roam_sync_req(psoc, sync_ind->roamed_vdev_id,
return mlo_fw_roam_sync_req(psoc, sync_ind->roamed_vdev_id,
sync_ind, sizeof(sync_ind));
}

View File

@@ -1558,4 +1558,16 @@ wlan_cm_sta_mlme_vdev_roam_notify(struct vdev_mlme_obj *vdev_mlme,
*/
bool wlan_cm_same_band_sta_allowed(struct wlan_objmgr_psoc *psoc);
/**
* cm_cleanup_mlo_link() - Cleanup the MLO link
*
* @vdev: MLO link vdev
*
* This posts the event WLAN_CM_SM_EV_ROAM_LINK_DOWN to CM to cleanup the
* resources allocated for MLO link e.g. vdev, pe_session, etc..
* This gets called when MLO to non-MLO roaming happens
*
* Return: qdf_status
*/
QDF_STATUS cm_cleanup_mlo_link(struct wlan_objmgr_vdev *vdev);
#endif /* WLAN_CM_ROAM_API_H__ */

View File

@@ -2358,12 +2358,14 @@ struct cm_hw_mode_trans_ind {
* @link_id: link id of the link
* @channel: wmi channel
* @flags: link flags
* @link_addr: link mac addr
*/
struct ml_setup_link_param {
uint32_t vdev_id;
uint32_t link_id;
wmi_channel channel;
uint32_t flags;
struct qdf_mac_addr link_addr;
};
/*

View File

@@ -3272,3 +3272,9 @@ rel_ref:
return status;
}
#endif /* WLAN_FEATURE_FIPS */
QDF_STATUS
cm_cleanup_mlo_link(struct wlan_objmgr_vdev *vdev)
{
return QDF_STATUS_SUCCESS;
}

View File

@@ -23,6 +23,7 @@
#include <wlan_mlo_mgr_cmn.h>
#include <wlan_mlo_mgr_public_structs.h>
#include <wlan_cm_roam_public_struct.h>
#include <../../core/src/wlan_cm_roam_i.h>
#ifdef WLAN_FEATURE_11BE_MLO
/**
@@ -76,6 +77,34 @@ mlo_get_sta_link_mac_addr(uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind,
struct qdf_mac_addr *link_mac_addr);
/**
* mlo_roam_get_chan_freq - get channel frequency
*
* @vdev_id: vdev id
* @sync_ind: roam sync ind pointer
*
* This api will be called to get the link channel frequency.
*
* Return: channel frequency
*/
uint32_t
mlo_roam_get_chan_freq(uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind);
/**
* mlo_roam_get_link_id - get link id
*
* @vdev_id: vdev id
* @sync_ind: roam sync ind pointer
*
* This api will be called to get the link id information.
*
* Return: link id
*/
uint32_t
mlo_roam_get_link_id(uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind);
/**
* is_multi_link_roam - check if MLO roaming
*
@@ -101,7 +130,46 @@ is_multi_link_roam(struct roam_offload_synch_ind *sync_ind);
QDF_STATUS mlo_enable_rso(struct wlan_objmgr_pdev *pdev,
struct wlan_objmgr_vdev *vdev);
#else
/**
* mlo_roam_copy_partner_info - copy partner link info to connect response
*
* @sync_ind: roam sync ind pointer
* @connect_rsp: connect resp structure pointer
*
* This api will be called to copy partner link info to connect response.
*
* Return: none
*/
void mlo_roam_copy_partner_info(struct wlan_cm_connect_resp *connect_rsp,
struct roam_offload_synch_ind *sync_ind);
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
/**
* mlo_cm_roam_sync_cb - Callback function from CM to MLO mgr
*
* @vdev: vdev pointer
* @event: event ptr
* @event_data_len: event data len
*
* This api will be called from connection manger to mlo
* manager to start roam sync request on link vdev's.
*
* Return: qdf status
*/
void mlo_cm_roam_sync_cb(struct wlan_objmgr_vdev *vdev,
void *event, uint32_t event_data_len);
#endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */
#else /* WLAN_FEATURE_11BE_MLO */
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
static inline
QDF_STATUS mlo_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, void *event,
uint32_t event_data_len)
{
return cm_fw_roam_sync_req(psoc, vdev_id, event, event_data_len);
}
#endif
static inline QDF_STATUS
mlo_get_sta_link_mac_addr(uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind,
@@ -110,6 +178,25 @@ mlo_get_sta_link_mac_addr(uint8_t vdev_id,
return QDF_STATUS_E_NOSUPPORT;
}
static inline uint32_t
mlo_roam_get_chan_freq(uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind)
{
return 0;
}
static inline uint32_t
mlo_roam_get_link_id(uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind)
{
return 0;
}
static inline void
mlo_cm_roam_sync_cb(struct wlan_objmgr_vdev *vdev,
void *event, uint32_t event_data_len)
{}
static inline bool
is_multi_link_roam(struct roam_offload_synch_ind *sync_ind)
{
@@ -122,5 +209,10 @@ QDF_STATUS mlo_enable_rso(struct wlan_objmgr_pdev *pdev,
{
return QDF_STATUS_SUCCESS;
}
static inline void
mlo_roam_copy_partner_info(struct wlan_cm_connect_resp *connect_rsp,
struct roam_offload_synch_ind *sync_ind)
{}
#endif /* WLAN_FEATURE_11BE_MLO */
#endif

View File

@@ -28,22 +28,225 @@
#include <../../core/src/wlan_cm_roam_i.h>
#include "wlan_cm_roam_api.h"
static bool
mlo_check_connect_req_bmap(struct wlan_objmgr_vdev *vdev)
{
struct wlan_mlo_dev_context *mlo_dev_ctx = vdev->mlo_dev_ctx;
struct wlan_mlo_sta *sta_ctx;
uint8_t i = 0;
if (!mlo_dev_ctx)
return false;
sta_ctx = mlo_dev_ctx->sta_ctx;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
if (vdev == mlo_dev_ctx->wlan_vdev_list[i])
return qdf_test_bit(i, sta_ctx->wlan_connect_req_links);
}
mlo_err("vdev not found in ml dev ctx list");
return false;
}
static void
mlo_update_for_multi_link_roam(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id,
uint8_t ml_link_vdev_id)
{
struct wlan_objmgr_vdev *vdev;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
ml_link_vdev_id,
WLAN_MLME_SB_ID);
if (!vdev) {
mlo_err("VDEV is null");
return;
}
if (vdev_id == ml_link_vdev_id) {
wlan_vdev_mlme_feat_ext2_cap_set(vdev,
WLAN_VDEV_FEXT2_MLO);
goto end;
}
wlan_vdev_mlme_feat_ext2_cap_set(vdev,
WLAN_VDEV_FEXT2_MLO);
wlan_vdev_mlme_feat_ext2_cap_set(vdev,
WLAN_VDEV_FEXT2_MLO_STA_LINK);
mlo_update_connect_req_links(vdev, true);
end:
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
}
static void
mlo_cleanup_link(struct wlan_objmgr_vdev *tmp_vdev,
struct wlan_objmgr_vdev *vdev)
{
wlan_vdev_mlme_feat_ext2_cap_clear(vdev,
WLAN_VDEV_FEXT2_MLO);
if (wlan_vdev_mlme_is_mlo_link_vdev(tmp_vdev)) {
//cm_cleanup_mlo_link(tmp_vdev);
wlan_vdev_mlme_feat_ext2_cap_clear(tmp_vdev,
WLAN_VDEV_FEXT2_MLO_STA_LINK);
}
}
static void
mlo_update_for_legacy_roam(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id)
{
struct wlan_mlo_dev_context *mlo_dev_ctx;
uint8_t i;
struct wlan_objmgr_vdev *vdev, *tmp_vdev;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
vdev_id,
WLAN_MLME_SB_ID);
if (!vdev) {
mlo_err("VDEV is null");
return;
}
mlo_dev_ctx = vdev->mlo_dev_ctx;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i])
continue;
tmp_vdev = mlo_dev_ctx->wlan_vdev_list[i];
mlo_cleanup_link(tmp_vdev, vdev);
}
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
}
static void
mlo_clear_link_bmap(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
{
struct wlan_objmgr_vdev *vdev;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
vdev_id,
WLAN_MLME_SB_ID);
if (!vdev) {
mlo_err("VDEV is null");
return;
}
mlo_clear_connect_req_links_bmap(vdev);
wlan_vdev_mlme_feat_ext2_cap_clear(vdev,
WLAN_VDEV_FEXT2_MLO);
if (wlan_vdev_mlme_is_mlo_link_vdev(vdev))
wlan_vdev_mlme_feat_ext2_cap_clear(vdev,
WLAN_VDEV_FEXT2_MLO_STA_LINK);
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
}
QDF_STATUS mlo_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
void *event, uint32_t event_data_len)
{
struct roam_offload_synch_ind *sync_ind;
QDF_STATUS status;
uint8_t i;
sync_ind = (struct roam_offload_synch_ind *)event;
if (!sync_ind)
return QDF_STATUS_E_FAILURE;
return QDF_STATUS_SUCCESS;
for (i = 0; i < sync_ind->num_setup_links; i++)
mlo_update_for_multi_link_roam(psoc, vdev_id,
sync_ind->ml_link[i].vdev_id);
if (!sync_ind->num_setup_links)
mlo_debug("MLO_ROAM: Roamed to Legacy");
else
mlo_debug("MLO_ROAM: Roamed to MLO");
status = cm_fw_roam_sync_req(psoc, vdev_id, event, event_data_len);
if (QDF_IS_STATUS_ERROR(status))
mlo_clear_link_bmap(psoc, vdev_id);
return status;
}
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
void mlo_cm_roam_sync_cb(struct wlan_objmgr_vdev *vdev,
void *event, uint32_t event_data_len)
{
QDF_STATUS status;
struct roam_offload_synch_ind *sync_ind;
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_vdev *link_vdev;
uint8_t i;
uint8_t vdev_id;
sync_ind = (struct roam_offload_synch_ind *)event;
vdev_id = wlan_vdev_get_id(vdev);
psoc = wlan_vdev_get_psoc(vdev);
if (!sync_ind->num_setup_links)
mlo_update_for_legacy_roam(psoc, vdev_id);
for (i = 0; i < sync_ind->num_setup_links; i++) {
if (vdev_id == sync_ind->ml_link[i].vdev_id)
continue;
link_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
sync_ind->ml_link[i].vdev_id,
WLAN_MLME_SB_ID);
if (mlo_check_connect_req_bmap(link_vdev)) {
mlo_update_connect_req_links(link_vdev, false);
status = cm_fw_roam_sync_req(psoc,
sync_ind->ml_link[i].vdev_id,
event, event_data_len);
if (QDF_IS_STATUS_ERROR(status)) {
mlo_clear_connect_req_links_bmap(link_vdev);
wlan_objmgr_vdev_release_ref(link_vdev,
WLAN_MLME_SB_ID);
return;
}
}
wlan_objmgr_vdev_release_ref(link_vdev,
WLAN_MLME_SB_ID);
}
}
#endif
void
mlo_fw_ho_fail_req(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, struct qdf_mac_addr bssid)
{
struct wlan_objmgr_vdev *vdev;
struct wlan_mlo_dev_context *mlo_dev_ctx;
uint8_t i;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
vdev_id,
WLAN_MLME_SB_ID);
mlo_dev_ctx = vdev->mlo_dev_ctx;
for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
if (!mlo_dev_ctx->wlan_vdev_list[i] ||
mlo_dev_ctx->wlan_vdev_list[i] == vdev)
continue;
cm_fw_ho_fail_req(psoc,
wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]),
bssid);
}
cm_fw_ho_fail_req(psoc, vdev_id, bssid);
wlan_objmgr_vdev_release_ref(vdev,
WLAN_MLME_SB_ID);
}
QDF_STATUS
@@ -52,13 +255,61 @@ mlo_get_sta_link_mac_addr(uint8_t vdev_id,
struct qdf_mac_addr *link_mac_addr)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t i;
if (!sync_ind || !sync_ind->num_setup_links)
return QDF_STATUS_E_FAILURE;
for (i = 0; i < sync_ind->num_setup_links; i++) {
if (sync_ind->ml_link[i].vdev_id == vdev_id) {
qdf_copy_macaddr(link_mac_addr,
&sync_ind->ml_link[i].link_addr);
return status;
}
}
if (i == sync_ind->num_setup_links) {
mlo_err("Link mac addr not found");
status = QDF_STATUS_E_FAILURE;
}
return status;
}
uint32_t
mlo_roam_get_chan_freq(uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind)
{
uint8_t i;
if (!sync_ind || !sync_ind->num_setup_links)
return 0;
for (i = 0; i < sync_ind->num_setup_links; i++) {
if (sync_ind->ml_link[i].vdev_id == vdev_id)
return sync_ind->ml_link[i].channel.mhz;
}
return 0;
}
uint32_t
mlo_roam_get_link_id(uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind)
{
uint8_t i;
if (!sync_ind || !sync_ind->num_setup_links)
return 0;
for (i = 0; i < sync_ind->num_setup_links; i++) {
if (sync_ind->ml_link[i].vdev_id == vdev_id)
return sync_ind->ml_link[i].link_id;
}
return 0;
}
bool is_multi_link_roam(struct roam_offload_synch_ind *sync_ind)
{
if (!sync_ind)
@@ -89,3 +340,24 @@ QDF_STATUS mlo_enable_rso(struct wlan_objmgr_pdev *pdev,
return QDF_STATUS_SUCCESS;
}
void
mlo_roam_copy_partner_info(struct wlan_cm_connect_resp *connect_rsp,
struct roam_offload_synch_ind *sync_ind)
{
uint8_t i;
struct mlo_partner_info *partner_info;
if (!sync_ind)
return;
partner_info = &connect_rsp->ml_parnter_info;
for (i = 0; i < sync_ind->num_setup_links; i++) {
partner_info->partner_link_info[i].link_id =
sync_ind->ml_link[i].link_id;
qdf_copy_macaddr(
&partner_info->partner_link_info[i].link_addr,
&sync_ind->ml_link[i].link_addr);
}
}