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
This commit is contained in:
Amruta Kulkarni
2022-11-29 23:28:28 +05:30
committed by Madan Koyyalamudi
parent 6e78070bc6
commit 87f1a94226
13 changed files with 929 additions and 53 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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))
if (num_setup_links >= 2 &&
wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
cm_cleanup_mlo_link(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;
}

View File

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

View File

@@ -2620,6 +2620,7 @@ struct osif_cm_ops osif_ops = {
.vendor_handoff_params_cb = hdd_cm_get_vendor_handoff_params,
#endif
.send_vdev_keys_cb = hdd_cm_send_vdev_keys,
.get_scan_ie_params_cb = hdd_cm_get_scan_ie_params,
};
QDF_STATUS hdd_cm_register_cb(void)

View File

@@ -199,6 +199,7 @@
#include "wlan_hdd_tdls.h"
#include "wlan_psoc_mlme_api.h"
#include <utils_mlo.h>
#include "wlan_mlo_mgr_roam.h"
/*
* A value of 100 (milliseconds) can be sent to FW.
@@ -20792,6 +20793,20 @@ static int wlan_hdd_add_key_sta(struct wlan_objmgr_pdev *pdev,
}
#ifdef WLAN_FEATURE_11BE_MLO
static void
wlan_hdd_mlo_link_free_keys(struct hdd_adapter *adapter,
struct wlan_objmgr_vdev *vdev,
bool pairwise)
{
if (adapter->device_mode != QDF_STA_MODE)
return;
if (pairwise &&
wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
wlan_vdev_get_id(vdev)))
wlan_crypto_free_vdev_key(vdev);
}
static bool
wlan_hdd_mlo_set_keys_saved(struct hdd_adapter *adapter,
struct wlan_objmgr_vdev *vdev,
@@ -20804,7 +20819,10 @@ wlan_hdd_mlo_set_keys_saved(struct hdd_adapter *adapter,
return false;
if ((adapter->device_mode == QDF_STA_MODE) &&
(!wlan_cm_is_vdev_connected(vdev))) {
((!wlan_cm_is_vdev_connected(vdev)) ||
(wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
wlan_vdev_get_id(vdev))))) {
hdd_debug("MLO:Save keys for vdev %d", wlan_vdev_get_id(vdev));
mlo_set_keys_saved(vdev, mac_address, true);
return true;
@@ -20820,6 +20838,13 @@ wlan_hdd_mlo_set_keys_saved(struct hdd_adapter *adapter,
{
return false;
}
static void
wlan_hdd_mlo_link_free_keys(struct hdd_adapter *adapter,
struct wlan_objmgr_vdev *vdev,
bool pairwise)
{
}
#endif
#ifdef WLAN_FEATURE_11BE_MLO
@@ -20948,6 +20973,20 @@ static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
hdd_err("Peer is null return");
return -EINVAL;
}
status = mlo_get_link_mac_addr_from_reassoc_rsp(vdev,
&mac_address);
if (QDF_IS_STATUS_ERROR(status)) {
peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
WLAN_OSIF_ID);
if (!peer) {
hdd_err("Peer is null return");
return -EINVAL;
}
qdf_mem_copy(mac_address.bytes,
wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
}
} else {
if (mac_addr)
qdf_mem_copy(mac_address.bytes,
@@ -20955,6 +20994,8 @@ static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
QDF_MAC_ADDR_SIZE);
}
wlan_hdd_mlo_link_free_keys(adapter, vdev, pairwise);
errno = wlan_cfg80211_store_key(vdev, key_index,
(pairwise ?
WLAN_CRYPTO_KEY_TYPE_UNICAST :
@@ -21155,7 +21196,6 @@ static int wlan_hdd_add_key_all_mlo_vdev(mac_handle_t mac_handle,
int errno = 0;
uint16_t link, vdev_count = 0;
/* if vdev mlme is mlo & pairwaise is set to true set same info for
* both the links.
*/
@@ -21182,6 +21222,9 @@ static int wlan_hdd_add_key_all_mlo_vdev(mac_handle_t mac_handle,
break;
case QDF_STA_MODE:
default:
status = mlo_get_link_mac_addr_from_reassoc_rsp(link_vdev,
&peer_mac);
if (QDF_IS_STATUS_ERROR(status))
peer = wlan_objmgr_vdev_try_get_bsspeer(link_vdev,
WLAN_OSIF_ID);
break;
@@ -21207,7 +21250,6 @@ static int wlan_hdd_add_key_all_mlo_vdev(mac_handle_t mac_handle,
mlo_release_vdev_ref(link_vdev);
continue;
}
errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
pairwise, peer_mac.bytes,
params, link_id, link_adapter);
@@ -21228,10 +21270,24 @@ static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
struct wlan_objmgr_vdev *link_vdev;
struct hdd_adapter *link_adapter = NULL;
struct hdd_context *hdd_ctx;
uint8_t vdev_id;
QDF_STATUS status;
if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
return errno;
vdev_id = wlan_vdev_get_id(vdev);
if (pairwise &&
mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
vdev_id)) {
status = mlo_roam_link_connect_notify(adapter->hdd_ctx->psoc,
vdev_id);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Posting of link connect request failed");
return -EINVAL;
}
}
if (pairwise && link_id == -1)
return wlan_hdd_add_key_all_mlo_vdev(mac_handle, vdev,
key_index, pairwise,

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2022-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
@@ -355,4 +355,16 @@ bool hdd_cm_is_disconnected(struct hdd_adapter *adapter);
*/
bool hdd_cm_is_vdev_roaming(struct hdd_adapter *adapter);
/**
* hdd_cm_get_scan_ie_params() - to get scan ie params
* @vdev: Pointer to vdev object
* @scan_ie: pointer to scan ie element struct
* @dot11mode_filter: Pointer to dot11mode_filter enum
*
* Return: QDF_STATUS
*/
QDF_STATUS
hdd_cm_get_scan_ie_params(struct wlan_objmgr_vdev *vdev,
struct element_info *scan_ie,
enum dot11_mode_filter *dot11mode_filter);
#endif /* __WLAN_HDD_CM_API_H */

View File

@@ -1567,7 +1567,6 @@ QDF_STATUS hdd_cm_send_vdev_keys(struct wlan_objmgr_vdev *vdev,
#ifdef WLAN_VENDOR_HANDOFF_CONTROL
#define WLAN_WAIT_TIME_HANDOFF_PARAMS 1000
QDF_STATUS hdd_cm_get_handoff_param(struct wlan_objmgr_psoc *psoc,
struct hdd_adapter *adapter,
uint8_t vdev_id, uint32_t param_id)
@@ -1634,6 +1633,42 @@ hdd_cm_get_vendor_handoff_params(struct wlan_objmgr_psoc *psoc,
}
#endif
QDF_STATUS
hdd_cm_get_scan_ie_params(struct wlan_objmgr_vdev *vdev,
struct element_info *scan_ie,
enum dot11_mode_filter *dot11mode_filter)
{
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
struct hdd_adapter *adapter;
if (!hdd_ctx) {
hdd_err("hdd_ctx is NULL");
return QDF_STATUS_E_INVAL;
}
adapter = hdd_get_adapter_by_vdev(hdd_ctx, wlan_vdev_get_id(vdev));
if (!adapter) {
hdd_err("adapter is NULL for vdev %d", wlan_vdev_get_id(vdev));
return QDF_STATUS_E_INVAL;
}
if (adapter->device_mode == QDF_P2P_CLIENT_MODE) {
scan_ie->ptr =
&adapter->scan_info.scan_add_ie.addIEdata[0];
scan_ie->len = adapter->scan_info.scan_add_ie.length;
} else if (adapter->scan_info.default_scan_ies) {
scan_ie->ptr = adapter->scan_info.default_scan_ies;
scan_ie->len = adapter->scan_info.default_scan_ies_len;
} else if (adapter->scan_info.scan_add_ie.length) {
scan_ie->ptr = adapter->scan_info.scan_add_ie.addIEdata;
scan_ie->len = adapter->scan_info.scan_add_ie.length;
}
*dot11mode_filter = hdd_get_dot11mode_filter(hdd_ctx);
return QDF_STATUS_SUCCESS;
}
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
#ifdef WLAN_FEATURE_FILS_SK
QDF_STATUS hdd_cm_save_gtk(struct wlan_objmgr_vdev *vdev,

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
* 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
@@ -49,6 +49,7 @@
#include <lim_mlo.h>
#include "parser_api.h"
#include "wlan_twt_cfg_ext_api.h"
#include "wlan_mlo_mgr_roam.h"
/**
* lim_update_stads_htcap() - Updates station Descriptor HT capability
@@ -1407,9 +1408,12 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
goto assocReject;
}
}
if (!mlo_roam_is_auth_status_connected(mac_ctx->psoc,
wlan_vdev_get_id(session_entry->vdev))) {
qdf_mem_free(beacon);
return;
}
}
pe_debug("Successfully Associated with BSS " QDF_MAC_ADDR_FMT,
QDF_MAC_ADDR_REF(hdr->sa));
@@ -1432,6 +1436,12 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
(uint32_t *) &assoc_cnf);
clean_up_ft_sha384(assoc_rsp, sha384_akm);
/*
* Don't free the assoc rsp if it's cached in pe_session.
* It would be reused in link connect in cases like OWE
* roaming
*/
if (session_entry->limAssocResponseData != assoc_rsp)
qdf_mem_free(assoc_rsp);
qdf_mem_free(beacon);
return;
@@ -1532,6 +1542,7 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
&session_entry->lim_join_req->bssDescription, true,
session_entry)) {
clean_up_ft_sha384(assoc_rsp, sha384_akm);
if (session_entry->limAssocResponseData != assoc_rsp)
qdf_mem_free(assoc_rsp);
qdf_mem_free(beacon);
return;

View File

@@ -47,6 +47,7 @@
#include <lim_mlo.h>
#include "wlan_mlo_mgr_sta.h"
#include "../../../../qca-wifi-host-cmn/umac/mlo_mgr/inc/utils_mlo.h"
#include "wlan_mlo_mgr_roam.h"
#define MAX_SUPPORTED_PEERS_WEP 16
@@ -2849,6 +2850,95 @@ lim_process_switch_channel_join_mlo(struct pe_session *session_entry,
}
#endif /* WLAN_FEATURE_11BE_MLO */
#if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(WLAN_FEATURE_11BE_MLO)
static QDF_STATUS
lim_process_switch_channel_join_mlo_roam(struct pe_session *session_entry,
struct mac_context *mac_ctx)
{
QDF_STATUS status;
struct element_info assoc_rsp = {};
struct qdf_mac_addr sta_link_addr;
assoc_rsp.len = 0;
mlo_get_assoc_rsp(session_entry->vdev, &assoc_rsp);
if (!session_entry->lim_join_req->partner_info.num_partner_links) {
pe_debug("MLO_ROAM: num_partner_links is 0");
return QDF_STATUS_E_INVAL;
}
/* Todo: update the sta addr by matching link id */
qdf_mem_copy(&sta_link_addr, session_entry->self_mac_addr,
QDF_MAC_ADDR_SIZE);
pe_err("sta_link_addr" QDF_MAC_ADDR_FMT,
QDF_MAC_ADDR_REF(&sta_link_addr));
if (assoc_rsp.len) {
struct element_info link_assoc_rsp;
tLimMlmJoinCnf mlm_join_cnf;
tLimMlmAssocCnf assoc_cnf;
struct qdf_mac_addr bssid;
mlm_join_cnf.resultCode = eSIR_SME_SUCCESS;
mlm_join_cnf.protStatusCode = STATUS_SUCCESS;
/* Update PE sessionId */
mlm_join_cnf.sessionId = session_entry->peSessionId;
lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF,
(uint32_t *)&mlm_join_cnf);
session_entry->limSmeState = eLIM_SME_WT_ASSOC_STATE;
pe_debug("MLO_ROAM: reassoc rsp len %d ", assoc_rsp.len);
link_assoc_rsp.ptr = qdf_mem_malloc(assoc_rsp.len);
if (!link_assoc_rsp.ptr)
return QDF_STATUS_E_NOMEM;
link_assoc_rsp.len = assoc_rsp.len;
session_entry->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE;
mlo_get_link_mac_addr_from_reassoc_rsp(session_entry->vdev, &bssid);
sir_copy_mac_addr(session_entry->limReAssocbssId, bssid.bytes);
pe_debug("MLO_ROAM: Generate and process reassoc rsp for link vdev");
status = util_gen_link_assoc_rsp(assoc_rsp.ptr,
assoc_rsp.len,
true, sta_link_addr,
link_assoc_rsp.ptr,
assoc_rsp.len,
(qdf_size_t *)&link_assoc_rsp.len);
if (QDF_IS_STATUS_SUCCESS(status)) {
pe_debug("MLO_ROAM: process reassoc rsp for link vdev");
lim_process_assoc_rsp_frame(mac_ctx,
link_assoc_rsp.ptr,
(link_assoc_rsp.len - WLAN_MAC_HDR_LEN_3A),
LIM_REASSOC,
session_entry);
qdf_mem_free(link_assoc_rsp.ptr);
} else {
pe_debug("MLO_ROAM: link vdev assoc rsp generation failed");
assoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
/* Update PE sessionId */
assoc_cnf.sessionId = session_entry->peSessionId;
lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
(uint32_t *)&assoc_cnf);
session_entry->limMlmState = eLIM_MLM_IDLE_STATE;
qdf_mem_free(link_assoc_rsp.ptr);
}
}
return QDF_STATUS_SUCCESS;
}
#else /* (WLAN_FEATURE_ROAM_OFFLOAD) && (WLAN_FEATURE_11BE_MLO) */
static QDF_STATUS
lim_process_switch_channel_join_mlo_roam(struct pe_session *session_entry,
struct mac_context *mac_ctx)
{
return QDF_STATUS_SUCCESS;
}
#endif /* (WLAN_FEATURE_ROAM_OFFLOAD) && (WLAN_FEATURE_11BE_MLO) */
/**
* lim_process_switch_channel_join_req() -Initiates probe request
*
@@ -2896,6 +2986,11 @@ static void lim_process_switch_channel_join_req(
lim_apply_configuration(mac_ctx, session_entry);
if (wlan_vdev_mlme_is_mlo_link_vdev(session_entry->vdev)) {
if (mlo_roam_is_auth_status_connected(mac_ctx->psoc,
session_entry->vdev_id))
mlo_status = lim_process_switch_channel_join_mlo_roam(session_entry,
mac_ctx);
else
mlo_status = lim_process_switch_channel_join_mlo(session_entry,
mac_ctx);
@@ -2904,7 +2999,6 @@ static void lim_process_switch_channel_join_req(
else
return;
}
/*
* If deauth_before_connection is enabled, Send Deauth first to AP if
* last disconnection was caused by HB failure.

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
* 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
@@ -3426,7 +3426,6 @@ csr_roam_send_rso_enable(struct mac_context *mac_ctx, uint8_t vdev_id)
}
wlan_objmgr_vdev_release_ref(vdev,
WLAN_MLME_OBJMGR_ID);
return QDF_STATUS_SUCCESS;
}
#else