qcacld-3.0: Handle 1x roaming case

In case of 1x MLO roaming, 4 way handshake is offloaded to supplicant
and link vdev is down in FW. Host has to bring up link vdev post
set key installation.

Add handling in host for following:
- During roam sync indication handle only assoc link.
- Save reassoc response and link information.
- After keys are installed bring up link vdev by
queueing connect req on link vdev.
- Enable roaming after all links are up.

Change-Id: I9c0722f88e950ba05ec3dd7f44883bedf568f97d
CRs-Fixed: 3287316
此提交包含在:
Amruta Kulkarni
2022-11-29 23:28:28 +05:30
提交者 Madan Koyyalamudi
父節點 6e78070bc6
當前提交 87f1a94226
共有 13 個檔案被更改,包括 929 行新增53 行删除

查看文件

@@ -996,7 +996,7 @@ cm_fw_roam_sync_propagation(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
wlan_cm_tgt_send_roam_sync_complete_cmd(psoc, vdev_id);
mlo_roam_update_connected_links(vdev, connect_rsp);
mlo_set_single_link_ml_roaming(psoc, vdev_id,
roam_synch_data, false);
false);
}
cm_connect_info(vdev, true, &connect_rsp->bssid, &connect_rsp->ssid,
connect_rsp->freq);
@@ -1011,6 +1011,10 @@ cm_fw_roam_sync_propagation(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
}
mlme_cm_osif_connect_complete(vdev, connect_rsp);
mlme_cm_osif_roam_complete(vdev);
if (wlan_vdev_mlme_is_mlo_vdev(vdev) &&
roam_synch_data->auth_status == ROAM_AUTH_STATUS_CONNECTED)
mlo_roam_copy_reassoc_rsp(vdev, connect_rsp);
mlme_debug(CM_PREFIX_FMT, CM_PREFIX_REF(vdev_id, cm_id));
cm_remove_cmd(cm_ctx, &cm_id);
status = QDF_STATUS_SUCCESS;

查看文件

@@ -1645,6 +1645,8 @@ cm_connect_complete_ind(struct wlan_objmgr_vdev *vdev,
cm_update_tid_mapping(vdev);
}
mlo_roam_connect_complete(psoc, pdev, vdev, rsp);
if (op_mode == QDF_STA_MODE &&
(wlan_vdev_mlme_is_mlo_link_vdev(vdev) ||
!wlan_vdev_mlme_is_mlo_vdev(vdev)))

查看文件

@@ -3766,12 +3766,12 @@ cm_cleanup_mlo_link(struct wlan_objmgr_vdev *vdev)
{
QDF_STATUS status;
/* Use internal disconnect as this is for cleanup and no need
* to inform OSIF, and REASON_FW_TRIGGERED_ROAM_FAILURE will
/* Use MLO roam internal disconnect as this is for cleanup and
* no need to inform OSIF, and REASON_FW_TRIGGERED_ROAM_FAILURE will
* cleanup host without informing the FW
*/
status = wlan_cm_disconnect(vdev,
CM_INTERNAL_DISCONNECT,
CM_MLO_ROAM_INTERNAL_DISCONNECT,
REASON_FW_TRIGGERED_ROAM_FAILURE,
NULL);
if (QDF_IS_STATUS_ERROR(status))

查看文件

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -26,6 +26,7 @@
#include <../../core/src/wlan_cm_roam_i.h>
#ifdef WLAN_FEATURE_11BE_MLO
/**
* mlo_fw_roam_sync_req - Handler for roam sync event handling
*
@@ -176,7 +177,6 @@ void mlo_roam_update_connected_links(struct wlan_objmgr_vdev *vdev,
*
* @psoc: psoc pointer
* @vdev_id: vdev id
* @sync_ind: roam synch indication
* @is_single_link_ml_roaming: boolean flag
*
* This api will be called to set single link mlo roaming flag.
@@ -186,7 +186,6 @@ void mlo_roam_update_connected_links(struct wlan_objmgr_vdev *vdev,
void
mlo_set_single_link_ml_roaming(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind,
bool is_single_link_ml_roaming);
/**
@@ -221,6 +220,79 @@ mlo_roam_get_bssid_chan_for_link(uint8_t vdev_id,
struct qdf_mac_addr *bssid,
wmi_channel *chan);
/**
* mlo_get_link_mac_addr_from_reassoc_rsp - get link mac addr from reassoc rsp
* @vdev: vdev pointer
* @link_mac_addr: link mac address
*
* This api will be called to get link mac addr from stored reassoc rsp
* after roaming and vdev id.
*
* Return: qdf status
*/
QDF_STATUS
mlo_get_link_mac_addr_from_reassoc_rsp(struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *link_mac_addr);
/**
* mlo_roam_copy_reassoc_rsp - Copy cm vdev join rsp
*
* @vdev: vdev pointer
* @reassoc_rsp: cm vdev reassoc rsp pointer
*
* This api will be called to copy cm vdev reassoc rsp which will
* be used to later bring up link vdev/s.
*
* Return: qdf_status success or fail
*/
QDF_STATUS
mlo_roam_copy_reassoc_rsp(struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_resp *reassoc_rsp);
/**
* mlo_roam_link_connect_notify - Send connect req
* on link
* @psoc: psoc pointer
* @vdev_id: vdev id
*
* This api will be called to send connect req for link vdev.
*
* Return: qdf_status success or fail
*/
QDF_STATUS
mlo_roam_link_connect_notify(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id);
/**
* mlo_roam_is_auth_status_connected - api to check roam auth status
* on link
* @psoc: psoc pointer
* @vdev_id: vdev id
*
* This api will be called to check if roam auth status is connected
*
* Return: boolean true or false
*/
bool
mlo_roam_is_auth_status_connected(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id);
/**
* mlo_roam_connect_complete - roam connect complete api
* @psoc: psoc pointer
* @pdev: pdev pointer
* @vdev: vdev pointer
* @rsp: connect rsp pointer
*
* This api will be called after connect complete for roam 1x case.
*
* Return: none
*/
void mlo_roam_connect_complete(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_pdev *pdev,
struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_resp *rsp);
#ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
/**
* mlo_cm_roam_sync_cb - Callback function from CM to MLO mgr
@@ -356,7 +428,6 @@ wlan_mlo_roam_abort_on_link(struct wlan_objmgr_psoc *psoc,
static inline void
mlo_set_single_link_ml_roaming(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind,
bool is_single_link_ml_roaming)
{}
@@ -386,5 +457,40 @@ static inline void
mlo_roam_set_link_id(struct wlan_objmgr_vdev *vdev,
struct roam_offload_synch_ind *sync_ind)
{}
static inline QDF_STATUS
mlo_roam_copy_reassoc_rsp(struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_resp *reassoc_rsp)
{
return QDF_STATUS_E_NOSUPPORT;
}
static inline QDF_STATUS
mlo_roam_link_connect_notify(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
{
return QDF_STATUS_E_NOSUPPORT;
}
static inline bool
mlo_roam_is_auth_status_connected(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id)
{
return false;
}
static inline void
mlo_roam_connect_complete(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_pdev *pdev,
struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_resp *rsp)
{}
static inline QDF_STATUS
mlo_get_link_mac_addr_from_reassoc_rsp(struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *link_mac_addr)
{
return QDF_STATUS_E_NOSUPPORT;
}
#endif /* WLAN_FEATURE_11BE_MLO */
#endif

查看文件

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -28,6 +28,8 @@
#include <../../core/src/wlan_cm_roam_i.h>
#include "wlan_cm_roam_api.h"
#include "wlan_mlme_vdev_mgr_interface.h"
#include <include/wlan_mlme_cmn.h>
#include <wlan_cm_api.h>
#ifdef WLAN_FEATURE_11BE_MLO
static bool
@@ -84,20 +86,23 @@ end:
}
static void
mlo_cleanup_link(struct wlan_objmgr_vdev *vdev, bool is_legacy)
mlo_cleanup_link(struct wlan_objmgr_vdev *vdev, uint8_t num_setup_links)
{
if (is_legacy || wlan_vdev_mlme_is_mlo_link_vdev(vdev))
wlan_vdev_mlme_clear_mlo_vdev(vdev);
if (wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
if (num_setup_links >= 2 &&
wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
cm_cleanup_mlo_link(vdev);
wlan_vdev_mlme_clear_mlo_link_vdev(vdev);
} else if (!num_setup_links || wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
wlan_vdev_mlme_clear_mlo_vdev(vdev);
if (wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
cm_cleanup_mlo_link(vdev);
wlan_vdev_mlme_clear_mlo_link_vdev(vdev);
}
}
}
static void
mlo_update_for_single_link_roam(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, bool is_legacy)
mlo_update_vdev_after_roam(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, uint8_t num_setup_links)
{
struct wlan_mlo_dev_context *mlo_dev_ctx;
uint8_t i;
@@ -120,7 +125,7 @@ mlo_update_for_single_link_roam(struct wlan_objmgr_psoc *psoc,
continue;
tmp_vdev = mlo_dev_ctx->wlan_vdev_list[i];
mlo_cleanup_link(tmp_vdev, is_legacy);
mlo_cleanup_link(tmp_vdev, num_setup_links);
}
end:
@@ -174,12 +179,12 @@ mlo_clear_link_bmap(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
{}
static inline void
mlo_update_for_single_link_roam(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, bool is_legacy)
mlo_update_vdev_after_roam(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id, uint8_t num_setup_links)
{}
static inline void
mlo_cleanup_link(struct wlan_objmgr_vdev *vdev, bool is_legacy)
mlo_cleanup_link(struct wlan_objmgr_vdev *vdev, uint8_t num_setup_links)
{}
static inline void
@@ -251,9 +256,10 @@ QDF_STATUS mlo_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
if (!sync_ind->num_setup_links) {
mlo_debug("MLO_ROAM: Roamed to Legacy");
is_non_mlo_ap = true;
} else if (sync_ind->num_setup_links == 1) {
} else if (sync_ind->num_setup_links == 1 ||
sync_ind->auth_status == ROAM_AUTH_STATUS_CONNECTED) {
mlo_debug("MLO_ROAM: Roamed to single link MLO");
mlo_set_single_link_ml_roaming(psoc, vdev_id, sync_ind, true);
mlo_set_single_link_ml_roaming(psoc, vdev_id, true);
} else {
mlo_debug("MLO_ROAM: Roamed to MLO");
}
@@ -282,10 +288,22 @@ void mlo_cm_roam_sync_cb(struct wlan_objmgr_vdev *vdev,
vdev_id = wlan_vdev_get_id(vdev);
psoc = wlan_vdev_get_psoc(vdev);
if (!sync_ind->num_setup_links)
mlo_update_for_single_link_roam(psoc, vdev_id, true);
else if (sync_ind->num_setup_links == 1)
mlo_update_for_single_link_roam(psoc, vdev_id, false);
/* Clean up link vdev in following cases
* 1. When roamed to legacy, num_setup_links = 0
* 2. When roamed to single link, num_setup_links = 1
* 3. Roamed to AP with auth_status = ROAMED_AUTH_STATUS_CONNECTED
*/
if (sync_ind->num_setup_links < 2 ||
sync_ind->auth_status == ROAM_AUTH_STATUS_CONNECTED)
mlo_update_vdev_after_roam(psoc, vdev_id,
sync_ind->num_setup_links);
/* If EAPOL is offloaded to supplicant, link vdev/s are not up
* at FW, in that case complete roam sync on assoc vdev
* link vdev will be initialized after set key is complete.
*/
if (sync_ind->auth_status == ROAM_AUTH_STATUS_CONNECTED)
return;
for (i = 0; i < sync_ind->num_setup_links; i++) {
if (vdev_id == sync_ind->ml_link[i].vdev_id)
@@ -551,7 +569,6 @@ wlan_mlo_roam_abort_on_link(struct wlan_objmgr_psoc *psoc,
void
mlo_set_single_link_ml_roaming(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id,
struct roam_offload_synch_ind *sync_ind,
bool is_single_link_ml_roaming)
{
struct wlan_objmgr_vdev *vdev;
@@ -564,17 +581,10 @@ mlo_set_single_link_ml_roaming(struct wlan_objmgr_psoc *psoc,
return;
}
if (!sync_ind) {
mlo_err("Roam sync ind is null");
goto end;
}
if (sync_ind->num_setup_links == 1 &&
!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
mlme_set_single_link_mlo_roaming(vdev,
is_single_link_ml_roaming);
end:
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
}
@@ -681,3 +691,548 @@ mlo_roam_set_link_id(struct wlan_objmgr_vdev *vdev,
}
}
}
QDF_STATUS
mlo_get_link_mac_addr_from_reassoc_rsp(struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *link_mac_addr)
{
uint8_t i;
struct wlan_mlo_sta *sta_ctx;
struct wlan_cm_connect_resp *rsp;
struct mlo_partner_info parnter_info;
uint8_t vdev_id;
if (!vdev)
return QDF_STATUS_E_NULL_VALUE;
vdev_id = wlan_vdev_get_id(vdev);
if (!vdev->mlo_dev_ctx) {
mlo_err("mlo dev ctx is null, vdev id %d", vdev_id);
return QDF_STATUS_E_NULL_VALUE;
}
sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
if (!sta_ctx || !sta_ctx->copied_reassoc_rsp ||
!sta_ctx->copied_reassoc_rsp->roaming_info) {
mlo_debug("sta ctx or copied reassoc rsp is null for vdev id %d", vdev_id);
return QDF_STATUS_E_NULL_VALUE;
}
rsp = sta_ctx->copied_reassoc_rsp;
if (rsp->roaming_info->auth_status != ROAM_AUTH_STATUS_CONNECTED) {
mlo_debug("Roam auth status is not connected");
return QDF_STATUS_E_FAILURE;
}
parnter_info = rsp->ml_parnter_info;
for (i = 0; i < parnter_info.num_partner_links; i++) {
if (parnter_info.partner_link_info[i].vdev_id == vdev_id) {
qdf_copy_macaddr(link_mac_addr,
&parnter_info.partner_link_info[i].link_addr);
return QDF_STATUS_SUCCESS;
}
}
if (i == parnter_info.num_partner_links) {
mlo_debug("Link mac addr not found");
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
mlo_roam_copy_reassoc_rsp(struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_resp *reassoc_rsp)
{
struct wlan_mlo_dev_context *mlo_dev_ctx;
struct wlan_mlo_sta *sta_ctx;
struct wlan_connect_rsp_ies *connect_ies;
if (!vdev)
return QDF_STATUS_E_NULL_VALUE;
if (!reassoc_rsp)
return QDF_STATUS_E_NULL_VALUE;
/* Store reassoc rsp only if roamed to 2 link AP */
if (reassoc_rsp->ml_parnter_info.num_partner_links < 2)
return QDF_STATUS_E_INVAL;
mlo_dev_ctx = vdev->mlo_dev_ctx;
if (!mlo_dev_ctx)
return QDF_STATUS_E_NULL_VALUE;
sta_ctx = mlo_dev_ctx->sta_ctx;
if (!sta_ctx)
return QDF_STATUS_E_NULL_VALUE;
if (sta_ctx) {
sta_ctx->copied_reassoc_rsp = qdf_mem_malloc(
sizeof(struct wlan_cm_connect_resp));
if (!sta_ctx->copied_reassoc_rsp)
return QDF_STATUS_E_NOMEM;
qdf_mem_copy(sta_ctx->copied_reassoc_rsp, reassoc_rsp,
sizeof(struct wlan_cm_connect_resp));
sta_ctx->copied_reassoc_rsp->roaming_info = qdf_mem_malloc(
sizeof(struct wlan_roam_sync_info));
if (!sta_ctx->copied_reassoc_rsp->roaming_info)
return QDF_STATUS_E_NOMEM;
qdf_mem_copy(sta_ctx->copied_reassoc_rsp->roaming_info,
reassoc_rsp->roaming_info,
sizeof(struct wlan_roam_sync_info));
connect_ies = &sta_ctx->copied_reassoc_rsp->connect_ies;
connect_ies->assoc_rsp.len =
reassoc_rsp->connect_ies.assoc_rsp.len;
connect_ies->assoc_rsp.ptr = qdf_mem_malloc(
connect_ies->assoc_rsp.len);
if (!connect_ies->assoc_rsp.ptr)
return QDF_STATUS_E_NOMEM;
qdf_mem_copy(connect_ies->assoc_rsp.ptr,
reassoc_rsp->connect_ies.assoc_rsp.ptr,
reassoc_rsp->connect_ies.assoc_rsp.len);
connect_ies->assoc_req.len = 0;
connect_ies->assoc_req.ptr = NULL;
connect_ies->bcn_probe_rsp.len = 0;
connect_ies->bcn_probe_rsp.ptr = NULL;
connect_ies->link_bcn_probe_rsp.len = 0;
connect_ies->link_bcn_probe_rsp.ptr = NULL;
connect_ies->fils_ie = NULL;
mlo_debug("Copied reassoc response");
}
return QDF_STATUS_SUCCESS;
}
static void
mlo_roam_free_connect_rsp(struct wlan_cm_connect_resp *rsp)
{
struct wlan_connect_rsp_ies *connect_ie =
&rsp->connect_ies;
if (connect_ie->assoc_req.ptr) {
qdf_mem_free(connect_ie->assoc_req.ptr);
connect_ie->assoc_req.ptr = NULL;
}
if (connect_ie->bcn_probe_rsp.ptr) {
qdf_mem_free(connect_ie->bcn_probe_rsp.ptr);
connect_ie->bcn_probe_rsp.ptr = NULL;
}
if (connect_ie->link_bcn_probe_rsp.ptr) {
qdf_mem_free(connect_ie->link_bcn_probe_rsp.ptr);
connect_ie->link_bcn_probe_rsp.ptr = NULL;
}
if (connect_ie->assoc_rsp.ptr) {
qdf_mem_free(connect_ie->assoc_rsp.ptr);
connect_ie->assoc_rsp.ptr = NULL;
}
if (connect_ie->fils_ie && connect_ie->fils_ie->fils_pmk) {
qdf_mem_zero(connect_ie->fils_ie->fils_pmk,
connect_ie->fils_ie->fils_pmk_len);
qdf_mem_free(connect_ie->fils_ie->fils_pmk);
}
if (connect_ie->fils_ie) {
qdf_mem_zero(connect_ie->fils_ie, sizeof(*connect_ie->fils_ie));
qdf_mem_free(connect_ie->fils_ie);
}
if (rsp->roaming_info) {
qdf_mem_free(rsp->roaming_info);
rsp->roaming_info = NULL;
}
qdf_mem_zero(rsp, sizeof(*rsp));
qdf_mem_free(rsp);
}
static bool
mlo_roam_is_internal_disconnect(struct wlan_objmgr_vdev *link_vdev)
{
struct wlan_cm_vdev_discon_req *disconn_req;
if (wlan_vdev_mlme_is_mlo_link_vdev(link_vdev) &&
wlan_cm_is_vdev_disconnecting(link_vdev)) {
mlo_debug("Disconnect is ongoing on vdev %d",
wlan_vdev_get_id(link_vdev));
disconn_req = qdf_mem_malloc(sizeof(*disconn_req));
if (!disconn_req) {
mlme_err("Malloc failed for disconnect req");
return false;
}
if (!wlan_cm_get_active_disconnect_req(link_vdev,
disconn_req)) {
mlme_err("vdev: %d: Active disconnect not found",
wlan_vdev_get_id(link_vdev));
qdf_mem_free(disconn_req);
return false;
}
mlo_debug("Disconnect source %d", disconn_req->req.source);
if (disconn_req->req.source == CM_MLO_ROAM_INTERNAL_DISCONNECT) {
qdf_mem_free(disconn_req);
return true;
}
qdf_mem_free(disconn_req);
}
/* Disconnect is not ongoing */
return true;
}
static QDF_STATUS
mlo_roam_validate_req(struct wlan_objmgr_vdev *vdev,
struct wlan_objmgr_vdev *link_vdev,
struct wlan_cm_connect_resp *rsp)
{
struct wlan_mlo_dev_context *mlo_dev_ctx;
struct wlan_mlo_sta *sta_ctx;
if (!vdev) {
mlo_debug_rl("vdev is NULL");
return QDF_STATUS_E_NULL_VALUE;
}
mlo_dev_ctx = vdev->mlo_dev_ctx;
if (!mlo_dev_ctx) {
mlo_debug_rl("mlo_dev_ctx is NULL");
return QDF_STATUS_E_NULL_VALUE;
}
sta_ctx = mlo_dev_ctx->sta_ctx;
if (sta_ctx && sta_ctx->disconn_req) {
mlo_debug("Handle pending disconnect for vdev %d",
wlan_vdev_get_id(vdev));
mlo_handle_pending_disconnect(vdev);
return QDF_STATUS_E_FAILURE;
}
if (wlan_cm_is_vdev_disconnected(vdev) ||
(wlan_vdev_mlme_is_mlo_link_vdev(link_vdev) &&
(wlan_cm_is_vdev_connecting(link_vdev) ||
!mlo_roam_is_internal_disconnect(link_vdev)))) {
if (sta_ctx) {
if (sta_ctx->copied_reassoc_rsp) {
mlo_roam_free_connect_rsp(sta_ctx->copied_reassoc_rsp);
sta_ctx->copied_reassoc_rsp = NULL;
}
copied_conn_req_lock_acquire(sta_ctx);
if (sta_ctx->copied_conn_req) {
mlo_free_connect_ies(sta_ctx->copied_conn_req);
qdf_mem_free(sta_ctx->copied_conn_req);
sta_ctx->copied_conn_req = NULL;
}
copied_conn_req_lock_release(sta_ctx);
}
}
if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
mlo_debug("Vdev: %d", wlan_vdev_get_id(vdev));
if (wlan_cm_is_vdev_disconnected(vdev)) {
mlo_handle_sta_link_connect_failure(vdev, rsp);
return QDF_STATUS_E_FAILURE;
} else if (!wlan_cm_is_vdev_connected(vdev)) {
/* If vdev is not in disconnected or connected state,
* then the event is received due to connect req being
* flushed. Hence, ignore this event
*/
if (sta_ctx && sta_ctx->copied_reassoc_rsp) {
mlo_roam_free_connect_rsp(sta_ctx->copied_reassoc_rsp);
sta_ctx->copied_reassoc_rsp = NULL;
}
return QDF_STATUS_E_FAILURE;
}
}
if (wlan_vdev_mlme_is_mlo_link_vdev(link_vdev) &&
(wlan_cm_is_vdev_connecting(link_vdev) ||
!mlo_roam_is_internal_disconnect(link_vdev))) {
return QDF_STATUS_E_FAILURE;
}
if (sta_ctx && !wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
if (sta_ctx->assoc_rsp.ptr) {
qdf_mem_free(sta_ctx->assoc_rsp.ptr);
sta_ctx->assoc_rsp.ptr = NULL;
}
sta_ctx->assoc_rsp.len = rsp->connect_ies.assoc_rsp.len;
sta_ctx->assoc_rsp.ptr =
qdf_mem_malloc(rsp->connect_ies.assoc_rsp.len);
if (!sta_ctx->assoc_rsp.ptr)
return QDF_STATUS_E_FAILURE;
if (rsp->connect_ies.assoc_rsp.ptr)
qdf_mem_copy(sta_ctx->assoc_rsp.ptr,
rsp->connect_ies.assoc_rsp.ptr,
rsp->connect_ies.assoc_rsp.len);
/* Update connected_links_bmap for all vdev taking
* part in association
*/
mlo_update_connected_links(vdev, 1);
mlo_update_connected_links_bmap(mlo_dev_ctx,
rsp->ml_parnter_info);
}
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS
mlo_roam_prepare_and_send_link_connect_req(struct wlan_objmgr_vdev *assoc_vdev,
struct wlan_objmgr_vdev *link_vdev,
struct wlan_cm_connect_resp *rsp,
struct qdf_mac_addr *link_addr,
uint16_t chan_freq)
{
struct wlan_mlo_sta *sta_ctx;
struct wlan_cm_connect_req req = {0};
struct wlan_ssid ssid = {0};
struct rso_config *rso_cfg;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!assoc_vdev || !link_vdev || !rsp)
return QDF_STATUS_E_FAILURE;
if (!assoc_vdev->mlo_dev_ctx || !assoc_vdev->mlo_dev_ctx->sta_ctx)
return QDF_STATUS_E_FAILURE;
sta_ctx = assoc_vdev->mlo_dev_ctx->sta_ctx;
wlan_vdev_mlme_get_ssid(assoc_vdev, ssid.ssid,
&ssid.length);
rso_cfg = wlan_cm_get_rso_config(assoc_vdev);
req.vdev_id = wlan_vdev_get_id(link_vdev);
req.source = CM_MLO_LINK_VDEV_CONNECT;
qdf_mem_copy(&req.bssid.bytes,
link_addr->bytes,
QDF_MAC_ADDR_SIZE);
req.ssid.length = ssid.length;
qdf_mem_copy(&req.ssid.ssid, &ssid.ssid, ssid.length);
req.chan_freq = chan_freq;
req.ml_parnter_info = rsp->ml_parnter_info;
if (rso_cfg) {
req.crypto.rsn_caps = rso_cfg->orig_sec_info.rsn_caps;
req.crypto.auth_type = rso_cfg->orig_sec_info.authmodeset;
req.crypto.ciphers_pairwise = rso_cfg->orig_sec_info.ucastcipherset;
req.crypto.group_cipher = rso_cfg->orig_sec_info.mcastcipherset;
req.crypto.akm_suites = rso_cfg->orig_sec_info.key_mgmt;
req.assoc_ie.len = rso_cfg->assoc_ie.len;
if (rso_cfg->assoc_ie.len)
qdf_mem_copy(&req.assoc_ie.ptr, &rso_cfg->assoc_ie.ptr,
rso_cfg->assoc_ie.len);
}
mlo_debug("vdev_id %d, chan_freq %d, mac_addr " QDF_MAC_ADDR_FMT,
req.vdev_id, req.chan_freq,
QDF_MAC_ADDR_REF(link_addr->bytes));
mlme_cm_osif_roam_get_scan_params(assoc_vdev, &req.scan_ie,
&req.dot11mode_filter);
copied_conn_req_lock_acquire(sta_ctx);
if (!sta_ctx->copied_conn_req)
sta_ctx->copied_conn_req = qdf_mem_malloc(
sizeof(struct wlan_cm_connect_req));
else
mlo_free_connect_ies(sta_ctx->copied_conn_req);
mlo_debug("MLO_ROAM: storing from roam connect rsp to connect req");
if (sta_ctx->copied_conn_req) {
qdf_mem_copy(sta_ctx->copied_conn_req, &req,
sizeof(struct wlan_cm_connect_req));
mlo_allocate_and_copy_ies(sta_ctx->copied_conn_req,
&req);
copied_conn_req_lock_release(sta_ctx);
} else {
mlo_err("MLO_ROAM: Failed to allocate connect req");
copied_conn_req_lock_release(sta_ctx);
return QDF_STATUS_E_NOMEM;
}
status = mlo_roam_validate_req(assoc_vdev, link_vdev, rsp);
if (QDF_IS_STATUS_ERROR(status))
return status;
mlo_debug("MLO_ROAM: Partner link connect mac:" QDF_MAC_ADDR_FMT " vdev_id:%d",
QDF_MAC_ADDR_REF(req.bssid.bytes),
req.vdev_id);
status = wlan_cm_start_connect(link_vdev, &req);
if (QDF_IS_STATUS_ERROR(status))
return status;
mlo_update_connected_links(link_vdev, 1);
return status;
}
void mlo_roam_connect_complete(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_pdev *pdev,
struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_resp *rsp)
{
struct wlan_mlo_sta *sta_ctx;
uint8_t auth_status;
if (!vdev)
return;
if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev))
return;
if (!vdev->mlo_dev_ctx)
return;
sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
if (!sta_ctx || !sta_ctx->copied_reassoc_rsp ||
!sta_ctx->copied_reassoc_rsp->roaming_info)
return;
auth_status = sta_ctx->copied_reassoc_rsp->roaming_info->auth_status;
if (!mlo_check_connect_req_bmap(vdev) &&
auth_status == ROAM_AUTH_STATUS_CONNECTED) {
mlo_roam_free_connect_rsp(sta_ctx->copied_reassoc_rsp);
sta_ctx->copied_reassoc_rsp = NULL;
}
}
bool
mlo_roam_is_auth_status_connected(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
{
bool status = false;
struct wlan_mlo_sta *sta_ctx;
struct wlan_cm_connect_resp *rsp;
struct wlan_objmgr_vdev *vdev;
if (!psoc)
return status;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
WLAN_MLME_SB_ID);
if (!vdev)
return status;
if (!vdev->mlo_dev_ctx)
goto end;
sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
if (!sta_ctx || !sta_ctx->copied_reassoc_rsp ||
!sta_ctx->copied_reassoc_rsp->roaming_info)
goto end;
rsp = sta_ctx->copied_reassoc_rsp;
if (rsp->roaming_info->auth_status == ROAM_AUTH_STATUS_CONNECTED)
status = true;
end:
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
return status;
}
QDF_STATUS
mlo_roam_link_connect_notify(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
{
struct wlan_mlo_sta *sta_ctx = NULL;
struct wlan_cm_connect_resp *rsp;
struct wlan_objmgr_vdev *assoc_vdev;
struct wlan_objmgr_vdev *link_vdev = NULL;
struct wlan_objmgr_vdev *vdev;
struct mlo_partner_info partner_info;
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t i;
uint8_t assoc_vdev_id;
uint8_t link_vdev_id;
if (!psoc)
return QDF_STATUS_E_NULL_VALUE;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
WLAN_MLME_SB_ID);
if (!vdev)
return QDF_STATUS_E_NULL_VALUE;
if (!vdev->mlo_dev_ctx) {
mlo_err("mlo dev ctx is null");
status = QDF_STATUS_E_FAILURE;
goto err;
}
sta_ctx = vdev->mlo_dev_ctx->sta_ctx;
if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
mlo_debug("MLO_ROAM: Ignore if not mlo vdev");
status = QDF_STATUS_E_FAILURE;
goto err;
}
assoc_vdev = wlan_mlo_get_assoc_link_vdev(vdev);
if (!assoc_vdev) {
status = QDF_STATUS_E_NULL_VALUE;
goto err;
}
assoc_vdev_id = wlan_vdev_get_id(assoc_vdev);
if (!sta_ctx || !sta_ctx->copied_reassoc_rsp) {
status = QDF_STATUS_E_NULL_VALUE;
goto err;
}
rsp = sta_ctx->copied_reassoc_rsp;
partner_info = rsp->ml_parnter_info;
mlo_debug("partner links %d", partner_info.num_partner_links);
for (i = 0; i < partner_info.num_partner_links; i++) {
link_vdev_id = partner_info.partner_link_info[i].vdev_id;
if (assoc_vdev_id == link_vdev_id)
continue;
link_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
link_vdev_id,
WLAN_MLME_SB_ID);
if (!link_vdev) {
mlo_err("Link vdev is null");
status = QDF_STATUS_E_NULL_VALUE;
goto err;
}
if (mlo_check_connect_req_bmap(link_vdev)) {
mlo_update_connect_req_links(link_vdev, false);
status = mlo_roam_prepare_and_send_link_connect_req(assoc_vdev,
link_vdev,
rsp,
&partner_info.partner_link_info[i].link_addr,
partner_info.partner_link_info[i].chan_freq);
if (QDF_IS_STATUS_ERROR(status))
goto err;
else
goto end;
}
}
err:
if (link_vdev)
mlo_clear_connect_req_links_bmap(link_vdev);
if (sta_ctx && sta_ctx->copied_reassoc_rsp) {
mlo_roam_free_connect_rsp(sta_ctx->copied_reassoc_rsp);
sta_ctx->copied_reassoc_rsp = NULL;
}
end:
if (link_vdev)
wlan_objmgr_vdev_release_ref(link_vdev, WLAN_MLME_SB_ID);
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
return status;
}

查看文件

@@ -2324,6 +2324,7 @@ wmi_fill_roam_sync_buffer(wmi_unified_t wmi_handle,
roam_sync_ind->auth_status = synch_event->auth_status;
roam_sync_ind->roam_reason = synch_event->roam_reason;
roam_sync_ind->rssi = synch_event->rssi;
roam_sync_ind->isBeacon = synch_event->is_beacon;
WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid,
roam_sync_ind->bssid.bytes);