qcacld-3.0: Add host roam preauth handling code for connection manager
Add host roam preauth handling code for connection manager. Change-Id: Id97d716a6c47ba08b2e8ef5e3ed675c5dcf88ed8 CRs-Fixed: 2954515
This commit is contained in:

کامیت شده توسط
Madan Koyyalamudi

والد
c55cae0628
کامیت
1557129851
@@ -0,0 +1,678 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The Linux Foundation. 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
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: wlan_cm_host_roam_preauth.c
|
||||
*
|
||||
* Implements general roam pre-auth functionality for connection manager
|
||||
*/
|
||||
|
||||
#include "wlan_cm_vdev_api.h"
|
||||
#include "wni_api.h"
|
||||
#include <wlan_cm_api.h>
|
||||
#include "wlan_cm_roam_api.h"
|
||||
#include "wlan_cm_roam_public_struct.h"
|
||||
#include "wlan_cm_public_struct.h"
|
||||
#include "connection_mgr/core/src/wlan_cm_roam.h"
|
||||
#include "connection_mgr/core/src/wlan_cm_sm.h"
|
||||
#include "connection_mgr/core/src/wlan_cm_main_api.h"
|
||||
|
||||
#define MAX_NUM_PREAUTH_RETRIES 3
|
||||
#define CM_PREAUTH_TIMEOUT 10000
|
||||
#define REASSOC_TIMER_DURATION 60
|
||||
|
||||
static QDF_STATUS cm_get_valid_preauth_candidate(struct cm_roam_req *cm_req)
|
||||
{
|
||||
qdf_list_t *candidate_list;
|
||||
qdf_list_node_t *cur_node = NULL;
|
||||
struct scan_cache_node *prev_candidate;
|
||||
bool new_candidate = false;
|
||||
uint8_t vdev_id = cm_req->req.vdev_id;
|
||||
|
||||
candidate_list = cm_req->candidate_list;
|
||||
if (!candidate_list || !qdf_list_size(candidate_list)) {
|
||||
mlme_info(CM_PREFIX_FMT "no valid candidate found",
|
||||
CM_PREFIX_REF(vdev_id, cm_req->cm_id));
|
||||
return QDF_STATUS_E_EMPTY;
|
||||
}
|
||||
|
||||
prev_candidate = cm_req->cur_candidate;
|
||||
if (!prev_candidate) {
|
||||
qdf_list_peek_front(candidate_list, &cur_node);
|
||||
new_candidate = true;
|
||||
} else if (cm_req->num_preauth_retry >= MAX_NUM_PREAUTH_RETRIES) {
|
||||
qdf_list_peek_next(candidate_list, &prev_candidate->node,
|
||||
&cur_node);
|
||||
new_candidate = true;
|
||||
}
|
||||
|
||||
if (new_candidate) {
|
||||
if (!cur_node) {
|
||||
mlme_debug(CM_PREFIX_FMT "All canidate tried",
|
||||
CM_PREFIX_REF(vdev_id, cm_req->cm_id));
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
cm_req->num_preauth_retry = 0;
|
||||
cm_req->cur_candidate = qdf_container_of(cur_node,
|
||||
struct scan_cache_node,
|
||||
node);
|
||||
}
|
||||
|
||||
cm_req->num_preauth_retry++;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void cm_preauth_fail(struct cnx_mgr *cm_ctx,
|
||||
struct wlan_cm_preauth_fail *preauth_fail_rsp)
|
||||
{
|
||||
struct cm_req *cm_req;
|
||||
wlan_cm_id cm_id;
|
||||
|
||||
cm_id = preauth_fail_rsp->cm_id;
|
||||
cm_req = cm_get_req_by_cm_id(cm_ctx, cm_id);
|
||||
/*
|
||||
* If the entry is not present in the list, it must have been cleared
|
||||
* already.
|
||||
*/
|
||||
if (!cm_req)
|
||||
return;
|
||||
|
||||
if (cm_get_state(cm_ctx) == WLAN_CM_S_CONNECTED)
|
||||
cm_mlme_roam_preauth_fail(cm_ctx->vdev, &cm_req->roam_req.req,
|
||||
preauth_fail_rsp->reason);
|
||||
|
||||
mlme_debug(CM_PREFIX_FMT,
|
||||
CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id));
|
||||
|
||||
if (cm_req->roam_req.req.source == CM_ROAMING_HOST &&
|
||||
cm_get_state(cm_ctx) == WLAN_CM_S_CONNECTED)
|
||||
wlan_cm_disconnect(cm_ctx->vdev, CM_ROAM_DISCONNECT,
|
||||
REASON_USER_TRIGGERED_ROAM_FAILURE, NULL);
|
||||
|
||||
cm_remove_cmd(cm_ctx, &cm_id);
|
||||
}
|
||||
|
||||
static void
|
||||
cm_preauth_handle_event_post_fail(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
|
||||
{
|
||||
struct wlan_cm_preauth_fail preauth_fail_rsp;
|
||||
|
||||
preauth_fail_rsp.cm_id = cm_id;
|
||||
preauth_fail_rsp.reason = CM_ABORT_DUE_TO_NEW_REQ_RECVD;
|
||||
|
||||
cm_preauth_fail(cm_ctx, &preauth_fail_rsp);
|
||||
}
|
||||
|
||||
static QDF_STATUS
|
||||
cm_preauth_cmd_timeout(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct wlan_cm_preauth_fail preauth_fail_rsp;
|
||||
|
||||
preauth_fail_rsp.cm_id = cm_id;
|
||||
preauth_fail_rsp.reason = CM_SER_TIMEOUT;
|
||||
|
||||
status = cm_sm_deliver_event(
|
||||
cm_ctx->vdev, WLAN_CM_SM_EV_PREAUTH_FAIL,
|
||||
sizeof(struct wlan_cm_preauth_fail), &preauth_fail_rsp);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cm_preauth_handle_event_post_fail(cm_ctx, cm_id);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static QDF_STATUS
|
||||
cm_ser_preauth_cb(struct wlan_serialization_command *cmd,
|
||||
enum wlan_serialization_cb_reason reason)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
struct cnx_mgr *cm_ctx;
|
||||
|
||||
if (!cmd) {
|
||||
mlme_err("cmd is NULL, reason: %d", reason);
|
||||
QDF_ASSERT(0);
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
}
|
||||
|
||||
vdev = cmd->vdev;
|
||||
cm_ctx = cm_get_cm_ctx(vdev);
|
||||
if (!cm_ctx)
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
|
||||
switch (reason) {
|
||||
case WLAN_SER_CB_ACTIVATE_CMD:
|
||||
if (cmd->activation_reason == SER_PENDING_TO_ACTIVE)
|
||||
status = cm_sm_deliver_event(
|
||||
vdev, WLAN_CM_SM_EV_PREAUTH_ACTIVE,
|
||||
sizeof(wlan_cm_id), &cmd->cmd_id);
|
||||
else
|
||||
status = cm_sm_deliver_event_sync(
|
||||
cm_ctx, WLAN_CM_SM_EV_PREAUTH_ACTIVE,
|
||||
sizeof(wlan_cm_id), &cmd->cmd_id);
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
break;
|
||||
/*
|
||||
* Handle failure if posting fails, i.e. the SM state has
|
||||
* changed or head cm_id doesn't match the active cm_id.
|
||||
* connect active should be handled only in JOIN_PENDING. If
|
||||
* new command has been received connect activation should be
|
||||
* aborted from here with connect req cleanup.
|
||||
*/
|
||||
cm_preauth_handle_event_post_fail(cm_ctx, cmd->cmd_id);
|
||||
break;
|
||||
case WLAN_SER_CB_CANCEL_CMD:
|
||||
/* command removed from pending list. */
|
||||
break;
|
||||
case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
|
||||
mlme_err(CM_PREFIX_FMT "Active command timeout",
|
||||
CM_PREFIX_REF(wlan_vdev_get_id(vdev), cmd->cmd_id));
|
||||
QDF_ASSERT(0);
|
||||
|
||||
cm_preauth_cmd_timeout(cm_ctx, cmd->cmd_id);
|
||||
break;
|
||||
case WLAN_SER_CB_RELEASE_MEM_CMD:
|
||||
cm_reset_active_cm_id(vdev, cmd->cmd_id);
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
|
||||
break;
|
||||
default:
|
||||
QDF_ASSERT(0);
|
||||
status = QDF_STATUS_E_INVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static QDF_STATUS cm_ser_preauth_req(struct cnx_mgr *cm_ctx,
|
||||
struct cm_req *cm_req)
|
||||
{
|
||||
struct wlan_serialization_command cmd = {0, };
|
||||
enum wlan_serialization_status ser_cmd_status;
|
||||
QDF_STATUS status;
|
||||
uint8_t vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
|
||||
|
||||
status = wlan_objmgr_vdev_try_get_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
mlme_err(CM_PREFIX_FMT "unable to get reference",
|
||||
CM_PREFIX_REF(vdev_id, cm_req->cm_id));
|
||||
return status;
|
||||
}
|
||||
|
||||
cmd.cmd_type = WLAN_SER_CMD_PERFORM_PRE_AUTH;
|
||||
cmd.cmd_id = cm_req->cm_id;
|
||||
cmd.cmd_cb = cm_ser_preauth_cb;
|
||||
cmd.source = WLAN_UMAC_COMP_MLME;
|
||||
cmd.is_high_priority = false;
|
||||
cmd.cmd_timeout_duration = CM_PREAUTH_TIMEOUT;
|
||||
cmd.vdev = cm_ctx->vdev;
|
||||
cmd.is_blocking = true;
|
||||
|
||||
ser_cmd_status = wlan_serialization_request(&cmd);
|
||||
switch (ser_cmd_status) {
|
||||
case WLAN_SER_CMD_PENDING:
|
||||
/* command moved to pending list.Do nothing */
|
||||
break;
|
||||
case WLAN_SER_CMD_ACTIVE:
|
||||
/* command moved to active list. Do nothing */
|
||||
break;
|
||||
default:
|
||||
mlme_err(CM_PREFIX_FMT "ser cmd status %d",
|
||||
CM_PREFIX_REF(vdev_id, cm_req->cm_id), ser_cmd_status);
|
||||
wlan_objmgr_vdev_release_ref(cm_ctx->vdev, WLAN_MLME_CM_ID);
|
||||
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
cm_send_preauth_start_fail(struct cnx_mgr *cm_ctx,
|
||||
wlan_cm_id cm_id,
|
||||
enum wlan_cm_connect_fail_reason reason)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct wlan_cm_preauth_fail preauth_fail_rsp;
|
||||
|
||||
preauth_fail_rsp.cm_id = cm_id;
|
||||
preauth_fail_rsp.reason = reason;
|
||||
|
||||
status = cm_sm_deliver_event_sync(
|
||||
cm_ctx, WLAN_CM_SM_EV_PREAUTH_FAIL,
|
||||
sizeof(struct wlan_cm_preauth_fail), &preauth_fail_rsp);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cm_preauth_handle_event_post_fail(cm_ctx, cm_id);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS cm_host_roam_preauth_start(struct cnx_mgr *cm_ctx,
|
||||
struct cm_req *cm_req)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status = cm_get_valid_preauth_candidate(&cm_req->roam_req);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
return status;
|
||||
|
||||
return cm_ser_preauth_req(cm_ctx, cm_req);
|
||||
}
|
||||
|
||||
void cm_free_preauth_req(struct wlan_preauth_req *preauth_req)
|
||||
{
|
||||
if (!preauth_req)
|
||||
return;
|
||||
|
||||
util_scan_free_cache_entry(preauth_req->entry);
|
||||
preauth_req->entry = NULL;
|
||||
qdf_mem_free(preauth_req);
|
||||
}
|
||||
|
||||
static QDF_STATUS cm_flush_preauth_req(struct scheduler_msg *msg)
|
||||
{
|
||||
struct wlan_preauth_req *preauth_req;
|
||||
|
||||
if (!msg || !msg->bodyptr) {
|
||||
mlme_err("msg or msg->bodyptr is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
preauth_req = msg->bodyptr;
|
||||
cm_free_preauth_req(preauth_req);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static QDF_STATUS
|
||||
cm_issue_preauth_req(struct cnx_mgr *cm_ctx, struct cm_roam_req *roam_req)
|
||||
{
|
||||
struct wlan_preauth_req *preauth_req;
|
||||
struct scheduler_msg msg;
|
||||
QDF_STATUS status;
|
||||
|
||||
qdf_mem_zero(&msg, sizeof(msg));
|
||||
preauth_req = qdf_mem_malloc(sizeof(*preauth_req));
|
||||
if (!preauth_req)
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
|
||||
preauth_req->vdev_id = wlan_vdev_get_id(cm_ctx->vdev);
|
||||
preauth_req->entry =
|
||||
util_scan_copy_cache_entry(roam_req->cur_candidate->entry);
|
||||
|
||||
if (!preauth_req->entry) {
|
||||
qdf_mem_free(preauth_req);
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
msg.bodyptr = preauth_req;
|
||||
msg.type = CM_PREAUTH_REQ;
|
||||
msg.flush_callback = cm_flush_preauth_req;
|
||||
|
||||
status = scheduler_post_message(QDF_MODULE_ID_MLME,
|
||||
QDF_MODULE_ID_PE,
|
||||
QDF_MODULE_ID_PE, &msg);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
mlme_err(CM_PREFIX_FMT "msg post fail",
|
||||
CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev),
|
||||
roam_req->cm_id));
|
||||
cm_free_preauth_req(preauth_req);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS cm_preauth_active(struct cnx_mgr *cm_ctx, wlan_cm_id *cm_id)
|
||||
{
|
||||
struct cm_req *cm_req;
|
||||
struct cm_roam_req *roam_req;
|
||||
QDF_STATUS status;
|
||||
|
||||
cm_req = cm_get_req_by_cm_id(cm_ctx, *cm_id);
|
||||
if (!cm_req)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
cm_ctx->active_cm_id = *cm_id;
|
||||
roam_req = &cm_req->roam_req;
|
||||
|
||||
status = cm_issue_preauth_req(cm_ctx, roam_req);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cm_send_preauth_start_fail(cm_ctx, *cm_id, CM_GENERIC_FAILURE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
static void cm_update_cckmtsf(uint32_t *timestamp0, uint32_t *timestamp1,
|
||||
uint64_t *incr)
|
||||
{
|
||||
uint64_t timestamp64 = ((uint64_t)*timestamp1 << 32) | (*timestamp0);
|
||||
|
||||
timestamp64 = (uint64_t)(timestamp64 + (*incr));
|
||||
*timestamp0 = (uint32_t)(timestamp64 & 0xffffffff);
|
||||
*timestamp1 = (uint32_t)((timestamp64 >> 32) & 0xffffffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* cm_roam_read_tsf() - read TSF
|
||||
* @cm_ctx: connection manager context
|
||||
* @rsp: preauth response
|
||||
*
|
||||
* This function reads the TSF and also add the time elapsed since last
|
||||
* beacon or probe response reception from the hand off AP to arrive at
|
||||
* the latest TSF value.
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
static void cm_roam_read_tsf(struct cnx_mgr *cm_ctx,
|
||||
struct wlan_preauth_rsp *rsp)
|
||||
{
|
||||
struct cm_req *cm_req;
|
||||
struct scan_cache_entry *scan_entry;
|
||||
uint64_t timer_diff = 0;
|
||||
|
||||
cm_req = cm_get_req_by_cm_id(cm_ctx, rsp->cm_id);
|
||||
if (!cm_req)
|
||||
return;
|
||||
if (!cm_req->roam_req.cur_candidate ||
|
||||
!cm_req->roam_req.cur_candidate->entry)
|
||||
return;
|
||||
|
||||
scan_entry = cm_req->roam_req.cur_candidate->entry;
|
||||
qdf_mem_copy(rsp->timestamp, scan_entry->tsf_info.data, 8);
|
||||
|
||||
/* Get the time diff in nano seconds */
|
||||
timer_diff = qdf_get_monotonic_boottime_ns() - scan_entry->boottime_ns;
|
||||
/* Convert msec to micro sec timer */
|
||||
timer_diff = do_div(timer_diff, SYSTEM_TIME_NSEC_TO_USEC);
|
||||
/* Update the TSF with the difference in system time */
|
||||
cm_update_cckmtsf(&rsp->timestamp[0], &rsp->timestamp[1],
|
||||
&timer_diff);
|
||||
}
|
||||
#else
|
||||
static inline void cm_roam_read_tsf(struct cnx_mgr *cm_ctx,
|
||||
struct wlan_preauth_rsp *rsp)
|
||||
{}
|
||||
#endif
|
||||
|
||||
#define MD_IE_ID 54
|
||||
|
||||
void cm_reassoc_timer_callback(void *context)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct reassoc_timer_ctx *ctx = context;
|
||||
struct cnx_mgr *cm_ctx;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
wlan_cm_id cm_id = ctx->cm_id;
|
||||
uint8_t vdev_id = ctx->vdev_id;
|
||||
|
||||
vdev = wlan_objmgr_get_vdev_by_id_from_pdev(ctx->pdev, vdev_id,
|
||||
WLAN_MLME_CM_ID);
|
||||
if (!vdev) {
|
||||
mlme_err(CM_PREFIX_FMT "vdev object is NULL",
|
||||
CM_PREFIX_REF(vdev_id, cm_id));
|
||||
return;
|
||||
}
|
||||
|
||||
cm_ctx = cm_get_cm_ctx(vdev);
|
||||
if (!cm_ctx)
|
||||
goto rel_ref;
|
||||
|
||||
status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_REASSOC_TIMER,
|
||||
sizeof(wlan_cm_id), &cm_id);
|
||||
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cm_preauth_handle_event_post_fail(cm_ctx, cm_id);
|
||||
|
||||
rel_ref:
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
|
||||
}
|
||||
|
||||
void cm_preauth_success(struct cnx_mgr *cm_ctx, struct wlan_preauth_rsp *rsp)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct mlme_legacy_priv *mlme_priv;
|
||||
struct rso_config *rso_cfg;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
uint8_t vdev_id = rsp->vdev_id;
|
||||
wlan_cm_id cm_id = rsp->cm_id;
|
||||
struct cm_roam_values_copy config;
|
||||
bool is_11r;
|
||||
|
||||
vdev = cm_ctx->vdev;
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
if (!pdev || !rsp->psoc) {
|
||||
mlme_err(CM_PREFIX_FMT "pdev or psoc is NULL",
|
||||
CM_PREFIX_REF(vdev_id, cm_id));
|
||||
goto err;
|
||||
}
|
||||
|
||||
mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
|
||||
if (!mlme_priv) {
|
||||
mlme_err(CM_PREFIX_FMT "vdev ext priv is NULL",
|
||||
CM_PREFIX_REF(vdev_id, cm_id));
|
||||
goto err;
|
||||
}
|
||||
|
||||
rso_cfg = wlan_cm_get_rso_config(vdev);
|
||||
if (!rso_cfg) {
|
||||
mlme_err(CM_PREFIX_FMT "rso_cfg is NULL",
|
||||
CM_PREFIX_REF(vdev_id, cm_id));
|
||||
goto err;
|
||||
}
|
||||
|
||||
mlme_err(CM_PREFIX_FMT "Preauth success with " QDF_MAC_ADDR_FMT,
|
||||
CM_PREFIX_REF(vdev_id, rsp->cm_id),
|
||||
QDF_MAC_ADDR_REF(rsp->pre_auth_bssid.bytes));
|
||||
|
||||
cm_csr_preauth_done(vdev);
|
||||
|
||||
qdf_mem_copy(rsp->ric_ies,
|
||||
mlme_priv->connect_info.ft_info.ric_ies,
|
||||
mlme_priv->connect_info.ft_info.ric_ies_length);
|
||||
rsp->ric_ies_length = mlme_priv->connect_info.ft_info.ric_ies_length;
|
||||
|
||||
mlme_priv->connect_info.ft_info.ft_state = FT_REASSOC_REQ_WAIT;
|
||||
|
||||
/* start reassoc timer */
|
||||
rso_cfg->ctx.pdev = pdev;
|
||||
rso_cfg->ctx.vdev_id = vdev_id;
|
||||
rso_cfg->ctx.cm_id = cm_id;
|
||||
|
||||
status = qdf_mc_timer_start(&rso_cfg->reassoc_timer,
|
||||
REASSOC_TIMER_DURATION);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
mlme_err(CM_PREFIX_FMT "start reassoc timer failed, status %d",
|
||||
CM_PREFIX_REF(vdev_id, cm_id), status);
|
||||
goto err;
|
||||
}
|
||||
|
||||
wlan_cm_roam_cfg_get_value(rsp->psoc, vdev_id, IS_11R_CONNECTION,
|
||||
&config);
|
||||
is_11r = config.bool_value;
|
||||
if (is_11r)
|
||||
mlme_cm_osif_ft_preauth_complete(vdev, rsp);
|
||||
|
||||
if (wlan_cm_get_ese_assoc(pdev, vdev_id)) {
|
||||
cm_roam_read_tsf(cm_ctx, rsp);
|
||||
mlme_cm_osif_cckm_preauth_complete(vdev, rsp);
|
||||
}
|
||||
|
||||
if (cm_is_fast_roam_enabled(rsp->psoc) &&
|
||||
cm_is_rsn_or_8021x_sha256_auth_type(vdev))
|
||||
mlme_cm_osif_pmksa_candidate_notify(vdev, &rsp->pre_auth_bssid,
|
||||
1, false);
|
||||
|
||||
mlme_priv->connect_info.ft_info.add_mdie = false;
|
||||
if (!is_11r && !cm_is_open_mode(vdev))
|
||||
return;
|
||||
|
||||
qdf_mem_zero(mlme_priv->connect_info.ft_info.reassoc_ft_ie,
|
||||
MAX_FTIE_SIZE);
|
||||
mlme_priv->connect_info.ft_info.reassoc_ie_len = 0;
|
||||
|
||||
if (wlan_get_ie_ptr_from_eid(MD_IE_ID, rsp->ft_ie, rsp->ft_ie_length))
|
||||
mlme_priv->connect_info.ft_info.add_mdie = true;
|
||||
|
||||
if (!mlme_priv->connect_info.ft_info.ric_ies_length)
|
||||
return;
|
||||
|
||||
/* Copy the RIC IEs to reassoc IEs */
|
||||
qdf_mem_copy(mlme_priv->connect_info.ft_info.reassoc_ft_ie,
|
||||
mlme_priv->connect_info.ft_info.ric_ies,
|
||||
mlme_priv->connect_info.ft_info.ric_ies_length);
|
||||
mlme_priv->connect_info.ft_info.reassoc_ie_len =
|
||||
mlme_priv->connect_info.ft_info.ric_ies_length;
|
||||
mlme_priv->connect_info.ft_info.add_mdie = true;
|
||||
return;
|
||||
|
||||
err:
|
||||
rsp->status = QDF_STATUS_E_ABORTED;
|
||||
status = cm_sm_deliver_event_sync(cm_ctx, WLAN_CM_SM_EV_PREAUTH_RESP,
|
||||
sizeof(*rsp), rsp);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cm_preauth_handle_event_post_fail(cm_ctx, cm_id);
|
||||
}
|
||||
|
||||
static QDF_STATUS
|
||||
cm_hanlde_preauth_failure(struct cnx_mgr *cm_ctx, wlan_cm_id cm_id)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct wlan_cm_preauth_fail preauth_fail_rsp;
|
||||
|
||||
preauth_fail_rsp.cm_id = cm_id;
|
||||
preauth_fail_rsp.reason = CM_GENERIC_FAILURE;
|
||||
|
||||
status = cm_sm_deliver_event_sync(
|
||||
cm_ctx, WLAN_CM_SM_EV_PREAUTH_FAIL,
|
||||
sizeof(struct wlan_cm_preauth_fail), &preauth_fail_rsp);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cm_preauth_handle_event_post_fail(cm_ctx, cm_id);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void cm_preauth_done_resp(struct cnx_mgr *cm_ctx, struct wlan_preauth_rsp *rsp)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct cm_req *cm_req;
|
||||
wlan_cm_id cm_id = rsp->cm_id;
|
||||
|
||||
if (QDF_IS_STATUS_ERROR(rsp->status)) {
|
||||
cm_req = cm_get_req_by_cm_id(cm_ctx, cm_id);
|
||||
if (!cm_req)
|
||||
return;
|
||||
|
||||
/* retry again with same or new candidate */
|
||||
status = cm_host_roam_preauth_start(cm_ctx, cm_req);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cm_hanlde_preauth_failure(cm_ctx, cm_id);
|
||||
} else {
|
||||
status = cm_sm_deliver_event_sync(cm_ctx,
|
||||
WLAN_CM_SM_EV_PREAUTH_DONE,
|
||||
sizeof(*rsp), rsp);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cm_preauth_handle_event_post_fail(cm_ctx, cm_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cm_remove_preauth_cmd_from_serialization() - Remove preauth cmd
|
||||
* from serialization
|
||||
* @cm_ctx: connection manager context
|
||||
* @cm_id: cm id of roam req
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void cm_remove_preauth_cmd_from_serialization(struct cnx_mgr *cm_ctx,
|
||||
wlan_cm_id cm_id)
|
||||
{
|
||||
struct wlan_serialization_queued_cmd_info cmd_info;
|
||||
|
||||
qdf_mem_zero(&cmd_info, sizeof(cmd_info));
|
||||
cmd_info.cmd_id = cm_id;
|
||||
cmd_info.req_type = WLAN_SER_CANCEL_NON_SCAN_CMD;
|
||||
cmd_info.cmd_type = WLAN_SER_CMD_PERFORM_PRE_AUTH;
|
||||
|
||||
mlme_debug(CM_PREFIX_FMT "Remove cmd type %d from active",
|
||||
CM_PREFIX_REF(wlan_vdev_get_id(cm_ctx->vdev), cm_id),
|
||||
cmd_info.cmd_type);
|
||||
cmd_info.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE;
|
||||
wlan_serialization_remove_cmd(&cmd_info);
|
||||
}
|
||||
|
||||
static QDF_STATUS cm_preauth_rsp(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_preauth_rsp *rsp)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct cnx_mgr *cm_ctx;
|
||||
wlan_cm_id cm_id;
|
||||
uint32_t prefix;
|
||||
|
||||
cm_ctx = cm_get_cm_ctx(vdev);
|
||||
if (!cm_ctx)
|
||||
return QDF_STATUS_E_NULL_VALUE;
|
||||
|
||||
cm_id = cm_ctx->active_cm_id;
|
||||
prefix = CM_ID_GET_PREFIX(cm_id);
|
||||
|
||||
if (prefix != ROAM_REQ_PREFIX) {
|
||||
mlme_err(CM_PREFIX_FMT "active req is not roam req",
|
||||
CM_PREFIX_REF(wlan_vdev_get_id(vdev), cm_id));
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
rsp->cm_id = cm_id;
|
||||
|
||||
cm_remove_preauth_cmd_from_serialization(cm_ctx, cm_id);
|
||||
|
||||
status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_PREAUTH_RESP,
|
||||
sizeof(*rsp), rsp);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cm_preauth_handle_event_post_fail(cm_ctx, cm_id);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS cm_handle_preauth_rsp(struct scheduler_msg *msg)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
struct wlan_preauth_rsp *rsp = NULL;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
|
||||
if (!msg || !msg->bodyptr) {
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
rsp = (struct wlan_preauth_rsp *)msg->bodyptr;
|
||||
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(rsp->psoc, rsp->vdev_id,
|
||||
WLAN_MLME_CM_ID);
|
||||
if (!vdev) {
|
||||
mlme_err("vdev_id: %d : vdev not found", rsp->vdev_id);
|
||||
status = QDF_STATUS_E_INVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = cm_preauth_rsp(vdev, rsp);
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_CM_ID);
|
||||
end:
|
||||
if (rsp)
|
||||
qdf_mem_free(rsp);
|
||||
|
||||
return status;
|
||||
}
|
122
components/umac/mlme/connection_mgr/core/src/wlan_cm_host_util.c
Normal file
122
components/umac/mlme/connection_mgr/core/src/wlan_cm_host_util.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2021 The Linux Foundation. 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
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: wlan_cm_host_util.c
|
||||
*
|
||||
* Implements Host roam (LFR2) utils for connection manager
|
||||
*/
|
||||
|
||||
#include "wlan_cm_roam_api.h"
|
||||
#include "connection_mgr/core/src/wlan_cm_roam.h"
|
||||
|
||||
/*
|
||||
* cm_copy_ssids_from_rso_config_params() - copy SSID from rso_config_params
|
||||
* to scan filter
|
||||
* @rso_usr_cfg: rso user config
|
||||
* @filter: scan filter
|
||||
*
|
||||
* Return void
|
||||
*/
|
||||
static void
|
||||
cm_copy_ssids_from_rso_config_params(struct rso_config_params *rso_usr_cfg,
|
||||
struct scan_filter *filter)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t max_ssid;
|
||||
|
||||
if (!rso_usr_cfg->num_ssid_allowed_list)
|
||||
return;
|
||||
max_ssid = QDF_MIN(WLAN_SCAN_FILTER_NUM_SSID, MAX_SSID_ALLOWED_LIST);
|
||||
|
||||
filter->num_of_ssid = rso_usr_cfg->num_ssid_allowed_list;
|
||||
if (filter->num_of_ssid > max_ssid)
|
||||
filter->num_of_ssid = max_ssid;
|
||||
for (i = 0; i < filter->num_of_ssid; i++)
|
||||
qdf_mem_copy(&filter->ssid_list[i],
|
||||
&rso_usr_cfg->ssid_allowed_list[i],
|
||||
sizeof(struct wlan_ssid));
|
||||
}
|
||||
|
||||
QDF_STATUS cm_update_advance_roam_scan_filter(
|
||||
struct wlan_objmgr_vdev *vdev, struct scan_filter *filter)
|
||||
{
|
||||
uint8_t num_ch = 0;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct rso_config *rso_cfg;
|
||||
struct rso_chan_info *chan_lst;
|
||||
struct wlan_mlme_psoc_ext_obj *mlme_obj;
|
||||
struct rso_config_params *rso_usr_cfg;
|
||||
|
||||
psoc = wlan_vdev_get_psoc(vdev);
|
||||
if (!psoc) {
|
||||
mlme_debug("psoc is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
mlme_obj = mlme_get_psoc_ext_obj(psoc);
|
||||
if (!mlme_obj)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
rso_usr_cfg = &mlme_obj->cfg.lfr.rso_user_config;
|
||||
|
||||
mlme_debug("No of Allowed SSID List:%d",
|
||||
rso_usr_cfg->num_ssid_allowed_list);
|
||||
|
||||
if (rso_usr_cfg->num_ssid_allowed_list) {
|
||||
cm_copy_ssids_from_rso_config_params(rso_usr_cfg, filter);
|
||||
} else {
|
||||
filter->num_of_ssid = 1;
|
||||
wlan_vdev_mlme_get_ssid(vdev, filter->ssid_list[0].ssid,
|
||||
&filter->ssid_list[0].length);
|
||||
|
||||
mlme_debug("Filtering for SSID %.*s,length of SSID = %u",
|
||||
filter->ssid_list[0].length,
|
||||
filter->ssid_list[0].ssid,
|
||||
filter->ssid_list[0].length);
|
||||
}
|
||||
|
||||
rso_cfg = wlan_cm_get_rso_config(vdev);
|
||||
if (!rso_cfg)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
chan_lst = &rso_cfg->roam_scan_freq_lst;
|
||||
num_ch = chan_lst->num_chan;
|
||||
if (num_ch) {
|
||||
filter->num_of_channels = num_ch;
|
||||
if (filter->num_of_channels > NUM_CHANNELS)
|
||||
filter->num_of_channels = NUM_CHANNELS;
|
||||
qdf_mem_copy(filter->chan_freq_list, chan_lst->freq_list,
|
||||
filter->num_of_channels *
|
||||
sizeof(filter->chan_freq_list[0]));
|
||||
}
|
||||
|
||||
if (rso_cfg->is_11r_assoc)
|
||||
/*
|
||||
* MDIE should be added as a part of profile. This should be
|
||||
* added as a part of filter as well
|
||||
*/
|
||||
filter->mobility_domain = rso_cfg->mdid.mobility_domain;
|
||||
filter->enable_adaptive_11r =
|
||||
wlan_mlme_adaptive_11r_enabled(psoc);
|
||||
|
||||
if (rso_cfg->rsn_cap & WLAN_CRYPTO_RSN_CAP_MFP_REQUIRED)
|
||||
filter->pmf_cap = WLAN_PMF_REQUIRED;
|
||||
else if (rso_cfg->rsn_cap & WLAN_CRYPTO_RSN_CAP_MFP_ENABLED)
|
||||
filter->pmf_cap = WLAN_PMF_CAPABLE;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
@@ -526,6 +526,16 @@ void cm_free_join_req(struct cm_vdev_join_req *join_req);
|
||||
QDF_STATUS cm_process_join_req(struct scheduler_msg *msg);
|
||||
|
||||
#ifdef WLAN_FEATURE_HOST_ROAM
|
||||
/**
|
||||
* cm_process_preauth_req() - Process preauth request
|
||||
* @msg: scheduler message
|
||||
*
|
||||
* Process preauth request in LIM.
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS cm_process_preauth_req(struct scheduler_msg *msg);
|
||||
|
||||
/**
|
||||
* cm_process_reassoc_req() - Process vdev reassoc req
|
||||
* @msg: scheduler message
|
||||
@@ -547,11 +557,25 @@ QDF_STATUS cm_process_reassoc_req(struct scheduler_msg *msg);
|
||||
QDF_STATUS
|
||||
cm_handle_reassoc_req(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_vdev_reassoc_req *req);
|
||||
|
||||
/**
|
||||
* cm_csr_preauth_done() - Process preauth done from csr part
|
||||
* @vdev: vdev object pointer
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void cm_csr_preauth_done(struct wlan_objmgr_vdev *vdev);
|
||||
#else
|
||||
static inline QDF_STATUS cm_process_preauth_req(struct scheduler_msg *msg)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS cm_process_reassoc_req(struct scheduler_msg *msg)
|
||||
{
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline QDF_STATUS
|
||||
cm_handle_reassoc_req(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_vdev_reassoc_req *req)
|
||||
@@ -637,6 +661,5 @@ QDF_STATUS wlan_cm_send_connect_rsp(struct scheduler_msg *msg);
|
||||
* Return: void
|
||||
*/
|
||||
void wlan_cm_free_connect_rsp(struct cm_vdev_join_rsp *rsp);
|
||||
|
||||
#endif /* FEATURE_CM_ENABLE */
|
||||
#endif /* __WLAN_CM_VDEV_API_H__ */
|
||||
|
@@ -636,6 +636,7 @@ void cm_roam_start_init_on_connect(struct wlan_objmgr_pdev *pdev,
|
||||
void cm_update_session_assoc_ie(struct wlan_objmgr_psoc *psoc,
|
||||
uint8_t vdev_id,
|
||||
struct element_info *assoc_ie);
|
||||
|
||||
#ifdef FEATURE_CM_ENABLE
|
||||
/**
|
||||
* wlan_cm_roam_invoke() - Validate and send Roam invoke req to CM
|
||||
@@ -652,6 +653,23 @@ wlan_cm_roam_invoke(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
|
||||
struct qdf_mac_addr *bssid, qdf_freq_t chan_freq,
|
||||
enum wlan_cm_source source);
|
||||
|
||||
/**
|
||||
* cm_is_fast_roam_enabled() - check fast roam enabled or not
|
||||
* @psoc: psoc pointer
|
||||
*
|
||||
* Return: true or false
|
||||
*/
|
||||
bool cm_is_fast_roam_enabled(struct wlan_objmgr_psoc *psoc);
|
||||
|
||||
/**
|
||||
* cm_is_rsn_or_8021x_sha256_auth_type() - check whether auth type is rsn
|
||||
* or 8021x_sha256 or not
|
||||
* @vdev: vdev object pointer
|
||||
*
|
||||
* Return: true, if auth type is rsn/8021x_sha256, false otherwise
|
||||
*/
|
||||
bool cm_is_rsn_or_8021x_sha256_auth_type(struct wlan_objmgr_vdev *vdev);
|
||||
|
||||
#ifdef WLAN_FEATURE_HOST_ROAM
|
||||
/**
|
||||
* wlan_cm_host_roam_start() - fw host roam start handler
|
||||
@@ -660,6 +678,61 @@ wlan_cm_roam_invoke(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS wlan_cm_host_roam_start(struct scheduler_msg *msg);
|
||||
|
||||
/**
|
||||
* cm_handle_roam_start() - roam start indication
|
||||
* @vdev: VDEV object
|
||||
* @req: Connection manager roam request
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS
|
||||
cm_handle_roam_start(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_roam_req *req);
|
||||
|
||||
/**
|
||||
* cm_mlme_roam_preauth_fail() - roam preauth fail
|
||||
* @vdev: VDEV object
|
||||
* @req: Connection manager roam request
|
||||
* @reason: connection manager connect fail reason
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS
|
||||
cm_mlme_roam_preauth_fail(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_roam_req *req,
|
||||
enum wlan_cm_connect_fail_reason reason);
|
||||
|
||||
/**
|
||||
* cm_free_preauth_req() - free preauth request related memory
|
||||
* @preauth_req: preauth request
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void cm_free_preauth_req(struct wlan_preauth_req *preauth_req);
|
||||
|
||||
/**
|
||||
* cm_handle_preauth_rsp() - Process vdev preauth rsp and send to CM
|
||||
* @msg: scheduler message
|
||||
*
|
||||
* Process preauth rsp and send it to CM SM.
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS cm_handle_preauth_rsp(struct scheduler_msg *msg);
|
||||
|
||||
/**
|
||||
* cm_reassoc_timer_callback() - reassoc timer callback, gets called at time out
|
||||
* @context: context
|
||||
*
|
||||
* Timer callback for the timer that is started between the preauth completion
|
||||
* and reassoc request. In this interval, it is expected that the
|
||||
* pre-auth response and RIC IEs are passed up to the WPA supplicant and
|
||||
* received back the necessary FTIEs required to be sent in the reassoc request
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
void cm_reassoc_timer_callback(void *context);
|
||||
#else
|
||||
static inline QDF_STATUS wlan_cm_host_roam_start(struct scheduler_msg *msg)
|
||||
{
|
||||
|
@@ -113,7 +113,12 @@
|
||||
#define MAX_BSSID_AVOID_LIST 16
|
||||
#define MAX_BSSID_FAVORED 16
|
||||
|
||||
#if defined(FEATURE_CM_ENABLE) && defined(WLAN_FEATURE_HOST_ROAM)
|
||||
#define MAX_FTIE_SIZE CM_MAX_FTIE_SIZE
|
||||
#else
|
||||
#define MAX_FTIE_SIZE 384
|
||||
#endif
|
||||
|
||||
#define ESE_MAX_TSPEC_IES 4
|
||||
|
||||
/*
|
||||
@@ -262,9 +267,25 @@ enum roam_fail_params {
|
||||
ROAM_FAIL_REASON,
|
||||
};
|
||||
|
||||
#if defined(FEATURE_CM_ENABLE) && defined(WLAN_FEATURE_HOST_ROAM)
|
||||
/**
|
||||
* srtuct reassoc_timer_ctx - reassoc timer context
|
||||
* @pdev: pdev object pointer
|
||||
* @vdev_id: vdev id
|
||||
* @cm_id: cm id to find cm_roam_req
|
||||
*/
|
||||
struct reassoc_timer_ctx {
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
uint8_t vdev_id;
|
||||
wlan_cm_id cm_id;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct rso_config - connect config to be used to send info in
|
||||
* RSO. This is the info we dont have in VDEV or CM ctx
|
||||
* @reassoc_timer: reassoc timer
|
||||
* @ctx: reassoc timer context
|
||||
* @cm_rso_lock: RSO lock
|
||||
* @rsn_cap: original rsn caps from the connect req from supplicant
|
||||
* @disable_hi_rssi: disable high rssi
|
||||
@@ -309,6 +330,10 @@ enum roam_fail_params {
|
||||
* @lost_link_rssi: lost link RSSI
|
||||
*/
|
||||
struct rso_config {
|
||||
#if defined(FEATURE_CM_ENABLE) && defined(WLAN_FEATURE_HOST_ROAM)
|
||||
qdf_mc_timer_t reassoc_timer;
|
||||
struct reassoc_timer_ctx ctx;
|
||||
#endif
|
||||
qdf_mutex_t cm_rso_lock;
|
||||
uint8_t rsn_cap;
|
||||
bool disable_hi_rssi;
|
||||
|
@@ -1220,9 +1220,35 @@ static void cm_rso_chan_to_freq_list(struct wlan_objmgr_pdev *pdev,
|
||||
wlan_reg_legacy_chan_to_freq(pdev, chan_list[count]);
|
||||
}
|
||||
|
||||
#if defined(FEATURE_CM_ENABLE) && defined(WLAN_FEATURE_HOST_ROAM)
|
||||
static QDF_STATUS wlan_cm_init_reassoc_timer(struct rso_config *rso_cfg)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status = qdf_mc_timer_init(&rso_cfg->reassoc_timer, QDF_TIMER_TYPE_SW,
|
||||
cm_reassoc_timer_callback, &rso_cfg->ctx);
|
||||
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
mlme_err("Preauth Reassoc interval Timer allocation failed");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void wlan_cm_deinit_reassoc_timer(struct rso_config *rso_cfg)
|
||||
{
|
||||
/* check if the timer is running */
|
||||
if (QDF_TIMER_STATE_RUNNING ==
|
||||
qdf_mc_timer_get_current_state(&rso_cfg->reassoc_timer))
|
||||
qdf_mc_timer_stop(&rso_cfg->reassoc_timer);
|
||||
|
||||
qdf_mc_timer_destroy(&rso_cfg->reassoc_timer);
|
||||
}
|
||||
#endif
|
||||
|
||||
QDF_STATUS wlan_cm_rso_config_init(struct wlan_objmgr_vdev *vdev,
|
||||
struct rso_config *rso_cfg)
|
||||
{
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
struct rso_chan_info *chan_info;
|
||||
struct rso_cfg_params *cfg_params;
|
||||
struct wlan_mlme_psoc_ext_obj *mlme_obj;
|
||||
@@ -1241,6 +1267,14 @@ QDF_STATUS wlan_cm_rso_config_init(struct wlan_objmgr_vdev *vdev,
|
||||
if (!mlme_obj)
|
||||
return QDF_STATUS_E_INVAL;
|
||||
|
||||
#ifdef FEATURE_CM_ENABLE
|
||||
#ifdef WLAN_FEATURE_HOST_ROAM
|
||||
status = wlan_cm_init_reassoc_timer(rso_cfg);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
return status;
|
||||
#endif
|
||||
qdf_mutex_create(&rso_cfg->cm_rso_lock);
|
||||
#endif
|
||||
cfg_params = &rso_cfg->cfg_param;
|
||||
cfg_params->max_chan_scan_time =
|
||||
mlme_obj->cfg.lfr.neighbor_scan_max_chan_time;
|
||||
@@ -1317,10 +1351,8 @@ QDF_STATUS wlan_cm_rso_config_init(struct wlan_objmgr_vdev *vdev,
|
||||
mlme_obj->cfg.lfr.roam_rssi_diff;
|
||||
cfg_params->bg_rssi_threshold =
|
||||
mlme_obj->cfg.lfr.bg_rssi_threshold;
|
||||
#ifdef FEATURE_CM_ENABLE
|
||||
qdf_mutex_create(&rso_cfg->cm_rso_lock);
|
||||
#endif
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void wlan_cm_rso_config_deinit(struct wlan_objmgr_vdev *vdev,
|
||||
@@ -1328,9 +1360,6 @@ void wlan_cm_rso_config_deinit(struct wlan_objmgr_vdev *vdev,
|
||||
{
|
||||
struct rso_cfg_params *cfg_params;
|
||||
|
||||
#ifdef FEATURE_CM_ENABLE
|
||||
qdf_mutex_destroy(&rso_cfg->cm_rso_lock);
|
||||
#endif
|
||||
cfg_params = &rso_cfg->cfg_param;
|
||||
if (rso_cfg->assoc_ie.ptr) {
|
||||
qdf_mem_free(rso_cfg->assoc_ie.ptr);
|
||||
@@ -1349,6 +1378,14 @@ void wlan_cm_rso_config_deinit(struct wlan_objmgr_vdev *vdev,
|
||||
|
||||
cm_flush_roam_channel_list(&cfg_params->specific_chan_info);
|
||||
cm_flush_roam_channel_list(&cfg_params->pref_chan_info);
|
||||
|
||||
#ifdef FEATURE_CM_ENABLE
|
||||
qdf_mutex_destroy(&rso_cfg->cm_rso_lock);
|
||||
#ifdef WLAN_FEATURE_HOST_ROAM
|
||||
wlan_cm_deinit_reassoc_timer(rso_cfg);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef FEATURE_CM_ENABLE
|
||||
@@ -1420,6 +1457,38 @@ wlan_cm_roam_invoke(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id,
|
||||
return status;
|
||||
}
|
||||
|
||||
bool cm_is_fast_roam_enabled(struct wlan_objmgr_psoc *psoc)
|
||||
{
|
||||
struct wlan_mlme_psoc_ext_obj *mlme_obj;
|
||||
|
||||
mlme_obj = mlme_get_psoc_ext_obj(psoc);
|
||||
if (!mlme_obj)
|
||||
return false;
|
||||
|
||||
if (!mlme_obj->cfg.lfr.lfr_enabled)
|
||||
return false;
|
||||
|
||||
if (mlme_obj->cfg.lfr.enable_fast_roam_in_concurrency)
|
||||
return true;
|
||||
/* return true if no concurency */
|
||||
if (policy_mgr_get_connection_count(psoc) < 2)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cm_is_rsn_or_8021x_sha256_auth_type(struct wlan_objmgr_vdev *vdev)
|
||||
{
|
||||
int32_t akm;
|
||||
|
||||
akm = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_KEY_MGMT);
|
||||
if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256) ||
|
||||
QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_IEEE8021X))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_HOST_ROAM
|
||||
QDF_STATUS wlan_cm_host_roam_start(struct scheduler_msg *msg)
|
||||
{
|
||||
@@ -1433,6 +1502,53 @@ QDF_STATUS wlan_cm_host_roam_start(struct scheduler_msg *msg)
|
||||
return wlan_cm_roam_invoke(req->pdev, req->vdev_id, &bssid, 0,
|
||||
CM_ROAMING_FW);
|
||||
}
|
||||
|
||||
QDF_STATUS cm_handle_roam_start(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_roam_req *req)
|
||||
{
|
||||
if (!vdev || !req) {
|
||||
mlme_err("vdev or req is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (req->source == CM_ROAMING_HOST)
|
||||
cm_roam_state_change(wlan_vdev_get_pdev(vdev),
|
||||
wlan_vdev_get_id(vdev),
|
||||
WLAN_ROAM_RSO_STOPPED,
|
||||
REASON_OS_REQUESTED_ROAMING_NOW);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS cm_mlme_roam_preauth_fail(struct wlan_objmgr_vdev *vdev,
|
||||
struct wlan_cm_roam_req *req,
|
||||
enum wlan_cm_connect_fail_reason reason)
|
||||
{
|
||||
uint8_t vdev_id, roam_reason;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
|
||||
if (!vdev || !req) {
|
||||
mlme_err("vdev or req is NULL");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
if (reason == CM_NO_CANDIDATE_FOUND)
|
||||
roam_reason = REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW;
|
||||
else
|
||||
roam_reason = REASON_PREAUTH_FAILED_FOR_ALL;
|
||||
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
vdev_id = wlan_vdev_get_id(vdev);
|
||||
|
||||
if (req->source == CM_ROAMING_FW)
|
||||
cm_roam_state_change(pdev, vdev_id,
|
||||
ROAM_SCAN_OFFLOAD_RESTART,
|
||||
roam_reason);
|
||||
else
|
||||
cm_roam_state_change(pdev, vdev_id,
|
||||
ROAM_SCAN_OFFLOAD_START,
|
||||
roam_reason);
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
مرجع در شماره جدید
Block a user