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:
committed by
Madan Koyyalamudi
parent
6e78070bc6
commit
87f1a94226
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,8 +21222,11 @@ static int wlan_hdd_add_key_all_mlo_vdev(mac_handle_t mac_handle,
|
||||
break;
|
||||
case QDF_STA_MODE:
|
||||
default:
|
||||
peer = wlan_objmgr_vdev_try_get_bsspeer(link_vdev,
|
||||
WLAN_OSIF_ID);
|
||||
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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,8 +1408,11 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
|
||||
goto assocReject;
|
||||
}
|
||||
}
|
||||
qdf_mem_free(beacon);
|
||||
return;
|
||||
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,7 +1436,13 @@ 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);
|
||||
qdf_mem_free(assoc_rsp);
|
||||
/*
|
||||
* 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,7 +1542,8 @@ 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);
|
||||
qdf_mem_free(assoc_rsp);
|
||||
if (session_entry->limAssocResponseData != assoc_rsp)
|
||||
qdf_mem_free(assoc_rsp);
|
||||
qdf_mem_free(beacon);
|
||||
return;
|
||||
} else {
|
||||
|
||||
@@ -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,15 +2986,19 @@ 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)) {
|
||||
mlo_status = lim_process_switch_channel_join_mlo(session_entry,
|
||||
mac_ctx);
|
||||
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);
|
||||
|
||||
if (mlo_status == QDF_STATUS_E_INVAL)
|
||||
goto error;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If deauth_before_connection is enabled, Send Deauth first to AP if
|
||||
* last disconnection was caused by HB failure.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user