blob: 4ea65dcec7ed4689f89fc3ad582158f5c3d834c0 [file] [log] [blame]
/*
* Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* 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.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*===========================================================================
s a p A p i L i n k C n t l . C
OVERVIEW:
This software unit holds the implementation of the WLAN SAP modules
Link Control functions.
The functions externalized by this module are to be called ONLY by other
WLAN modules (HDD)
DEPENDENCIES:
Are listed for each API below.
===========================================================================*/
/*----------------------------------------------------------------------------
* Include Files
* -------------------------------------------------------------------------*/
#include "cdf_trace.h"
/* Pick up the CSR callback definition */
#include "csr_api.h"
#include "sme_api.h"
/* SAP Internal API header file */
#include "sap_internal.h"
/*----------------------------------------------------------------------------
* Preprocessor Definitions and Constants
* -------------------------------------------------------------------------*/
#define SAP_DEBUG
/*----------------------------------------------------------------------------
* Type Declarations
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Global Data Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Static Variable Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Static Function Declarations and Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Externalized Function Definitions
* -------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Function Declarations and Documentation
* -------------------------------------------------------------------------*/
/*
* wlansap_scan_callback() - Callback for Scan (scan results) Events
*
* @hal_handle : tHalHandle passed in with the scan request
* @ctx : The second context pass in for the caller (sapContext)
* @scanID : scanID got after the scan
*
* Callback for Scan (scan results) Events
*
* Return: Status
*/
CDF_STATUS wlansap_scan_callback(tHalHandle hal_handle,
void *ctx, /* Opaque SAP handle */
uint8_t session_id,
uint32_t scan_id, eCsrScanStatus scan_status) {
tScanResultHandle result = NULL;
CDF_STATUS get_result_status = CDF_STATUS_E_FAILURE;
ptSapContext sap_ctx = (ptSapContext) ctx;
tWLAN_SAPEvent sapEvent; /* State machine event */
uint8_t operChannel = 0;
CDF_STATUS sap_sm_status;
#ifdef SOFTAP_CHANNEL_RANGE
uint32_t event;
#endif
if (NULL == hal_handle) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
"In %s invalid hHal", __func__);
return CDF_STATUS_E_FAILURE;
}
if (sap_ctx->sapsMachine == eSAP_DISCONNECTED) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN,
"In %s BSS already stopped", __func__);
return CDF_STATUS_E_FAILURE;
}
switch (scan_status) {
case eCSR_SCAN_SUCCESS:
/* sapScanCompleteCallback with eCSR_SCAN_SUCCESS */
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
"In %s, CSR scanStatus = %s (%d)", __func__,
"eCSR_SCAN_SUCCESS", scan_status);
/**
* Get scan results, Run channel selection algorithm,
* select channel and keep in sap_ctx->Channel
*/
get_result_status =
sme_scan_get_result(hal_handle, sap_ctx->sessionId, NULL,
&result);
event = eSAP_MAC_SCAN_COMPLETE;
if ((get_result_status != CDF_STATUS_SUCCESS)
&& (get_result_status != CDF_STATUS_E_NULL_VALUE)) {
/* No scan results */
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
"In %s, Get scan result failed! ret = %d",
__func__, get_result_status);
break;
}
#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
if (scan_id != 0) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
"%s: Sending ACS Scan skip event", __func__);
sap_signal_hdd_event(sap_ctx, NULL,
eSAP_ACS_SCAN_SUCCESS_EVENT,
(void *) eSAP_STATUS_SUCCESS);
} else
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
"%s: ACS scan id: %d (skipped ACS SCAN)",
__func__, scan_id);
#endif
operChannel = sap_select_channel(hal_handle, sap_ctx, result);
sme_scan_result_purge(hal_handle, result);
break;
default:
event = eSAP_CHANNEL_SELECTION_FAILED;
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
"In %s, CSR scanStatus = %s (%d)", __func__,
"eCSR_SCAN_ABORT/FAILURE", scan_status);
}
if (operChannel == SAP_CHANNEL_NOT_SELECTED)
#ifdef SOFTAP_CHANNEL_RANGE
{
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
"%s: No suitable channel selected due to DFS, LTE"
"COEX and concurrent mode restrictions", __func__);
sap_ctx->sapsMachine = eSAP_CH_SELECT;
event = eSAP_CHANNEL_SELECTION_FAILED;
}
#else
sap_ctx->channel = SAP_DEFAULT_24GHZ_CHANNEL;
#endif
else {
sap_ctx->channel = operChannel;
}
sap_ctx->ch_params.ch_width = sap_ctx->acs_cfg->ch_width;
sme_set_ch_params(hal_handle,
sap_ctx->csr_roamProfile.phyMode,
sap_ctx->channel,
sap_ctx->secondary_ch,
&sap_ctx->ch_params);
#ifdef SOFTAP_CHANNEL_RANGE
if (sap_ctx->channelList != NULL) {
/* Always free up the memory for channel selection whatever
* the result */
cdf_mem_free(sap_ctx->channelList);
sap_ctx->channelList = NULL;
}
#endif
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
"In %s, Channel selected = %d", __func__,
sap_ctx->channel);
/* Fill in the event structure */
sapEvent.event = event;
/* pCsrRoamInfo; */
sapEvent.params = 0;
/* roamstatus */
sapEvent.u1 = scan_status;
/* roamResult */
sapEvent.u2 = 0;
/* Handle event */
sap_sm_status = sap_fsm(sap_ctx, &sapEvent);
return sap_sm_status;
} /* wlansap_scan_callback */
/**
* sap_config_acs_result : Generate ACS result params based on ch constraints
* @sap_ctx: pointer to SAP context data struct
* @hal: HAL Handle pointer
*
* This function calculates the ACS result params: ht sec channel, vht channel
* information and channel bonding based on selected ACS channel.
*
* Return: None
*/
void sap_config_acs_result(tHalHandle hal, ptSapContext sap_ctx,
uint32_t sec_ch)
{
uint32_t channel = sap_ctx->acs_cfg->pri_ch;
chan_params_t ch_params = {0};
ch_params.ch_width = sap_ctx->acs_cfg->ch_width;
sme_set_ch_params(hal, sap_ctx->csr_roamProfile.phyMode, channel,
sec_ch, &ch_params);
sap_ctx->acs_cfg->ch_width = ch_params.ch_width;
if (sap_ctx->acs_cfg->ch_width > CH_WIDTH_40MHZ)
sap_ctx->acs_cfg->vht_seg0_center_ch =
ch_params.center_freq_seg0;
else
sap_ctx->acs_cfg->vht_seg0_center_ch = 0;
if (sap_ctx->acs_cfg->ch_width == CH_WIDTH_80P80MHZ)
sap_ctx->acs_cfg->vht_seg1_center_ch =
ch_params.center_freq_seg1;
else
sap_ctx->acs_cfg->vht_seg1_center_ch = 0;
if (ch_params.sec_ch_offset == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch - 4;
else if (ch_params.sec_ch_offset == PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
sap_ctx->acs_cfg->ht_sec_ch = sap_ctx->acs_cfg->pri_ch + 4;
else
sap_ctx->acs_cfg->ht_sec_ch = 0;
}
/**
* sap_hdd_signal_event_handler() - routine to inform hostapd via callback
*
* ctx: pointer to sap context which was passed to callback
*
* this routine will be registered as callback to sme_close_session, so upon
* closure of sap session it notifies the hostapd
*
* Return: CDF_STATUS
*/
static CDF_STATUS sap_hdd_signal_event_handler(void *ctx)
{
ptSapContext sap_ctx = (struct sSapContext *)ctx;
CDF_STATUS status;
if (NULL == sap_ctx) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("sap context is not valid"));
return CDF_STATUS_E_FAILURE;
}
status = sap_signal_hdd_event(sap_ctx, NULL,
sap_ctx->sap_state,
(void *) sap_ctx->sap_status);
return status;
}
/**
*
* wlansap_pre_start_bss_acs_scan_callback() - callback for scan results
*
* hal_handle: the hal_handle passed in with the scan request
* pcontext: the second context pass in for the caller, opaque sap Handle.
* scanid: scan id passed
* sessionid: session identifier
* status: status of scan -success, failure or abort
*
* Api for scan callback. This function is invoked as a result of scan
* completion and reports the scan results.
*
* Return: The CDF_STATUS code associated with performing the operation
*/
CDF_STATUS
wlansap_pre_start_bss_acs_scan_callback(tHalHandle hal_handle, void *pcontext,
uint8_t sessionid, uint32_t scanid,
eCsrScanStatus scan_status)
{
tScanResultHandle presult = NULL;
CDF_STATUS scan_get_result_status = CDF_STATUS_E_FAILURE;
ptSapContext sap_ctx = (ptSapContext)pcontext;
uint8_t oper_channel = 0;
CDF_STATUS status = CDF_STATUS_E_FAILURE;
if (eCSR_SCAN_SUCCESS != scan_status) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("CSR scan_status = eCSR_SCAN_ABORT/FAILURE (%d), choose default channel"),
scan_status);
#ifdef SOFTAP_CHANNEL_RANGE
if (sap_ctx->acs_cfg->hw_mode == eCSR_DOT11_MODE_11a)
sap_ctx->channel = SAP_DEFAULT_5GHZ_CHANNEL;
else
sap_ctx->channel = SAP_DEFAULT_24GHZ_CHANNEL;
#else
sap_ctx->channel = SAP_DEFAULT_24GHZ_CHANNEL;
#endif
sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED;
sap_ctx->sap_status = eSAP_STATUS_SUCCESS;
goto close_session;
}
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR scan_status = eCSR_SCAN_SUCCESS (%d)"), scan_status);
/*
* Now do
* 1. Get scan results
* 2. Run channel selection algorithm
* select channel and store in pSapContext->Channel
*/
scan_get_result_status = sme_scan_get_result(hal_handle,
sap_ctx->sessionId,
NULL, &presult);
if ((scan_get_result_status != CDF_STATUS_SUCCESS) &&
(scan_get_result_status != CDF_STATUS_E_NULL_VALUE)) {
/*
* No scan results So, set the operation channel not selected
* to allow the default channel to be set when reporting to HDD
*/
oper_channel = SAP_CHANNEL_NOT_SELECTED;
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("Get scan result failed! ret = %d"),
scan_get_result_status);
} else {
#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
if (scanid != 0) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("Sending ACS Scan skip event"));
sap_signal_hdd_event(sap_ctx, NULL,
eSAP_ACS_SCAN_SUCCESS_EVENT,
(void *) eSAP_STATUS_SUCCESS);
} else {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("ACS scanid: %d (skipped ACS SCAN)"),
scanid);
}
#endif
oper_channel = sap_select_channel(hal_handle, sap_ctx, presult);
sme_scan_result_purge(hal_handle, presult);
}
if (oper_channel == SAP_CHANNEL_NOT_SELECTED) {
#ifdef SOFTAP_CHANNEL_RANGE
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
FL("No suitable channel selected"));
sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED;
sap_ctx->sap_status = eSAP_STATUS_FAILURE;
goto close_session;
} else {
#else
sap_ctx->channel = SAP_DEFAULT_24GHZ_CHANNEL;
} else {
#endif
/* Valid Channel Found from scan results. */
sap_ctx->acs_cfg->pri_ch = oper_channel;
sap_ctx->channel = oper_channel;
}
sap_config_acs_result(hal_handle, sap_ctx,
sap_ctx->acs_cfg->ht_sec_ch);
#ifdef SOFTAP_CHANNEL_RANGE
if (sap_ctx->channelList != NULL) {
/*
* Always free up the memory for
* channel selection whatever
* the result
*/
cdf_mem_free(sap_ctx->channelList);
sap_ctx->channelList = NULL;
}
#endif
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("Channel selected = %d"), sap_ctx->channel);
sap_ctx->sap_state = eSAP_ACS_CHANNEL_SELECTED;
sap_ctx->sap_status = eSAP_STATUS_SUCCESS;
close_session:
status = sme_close_session(hal_handle,
sap_ctx->sessionId, sap_hdd_signal_event_handler,
sap_ctx);
if (CDF_STATUS_SUCCESS != status)
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("CloseSession failed"));
else
sap_ctx->isScanSessionOpen = eSAP_FALSE;
sap_ctx->sessionId = 0xff;
return status;
}
/**
* wlansap_roam_process_ch_change_success() - handles the case for
* eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS in function wlansap_roam_callback()
*
* @mac_ctx: mac global context
* @sap_ctx: sap context
* @csr_roam_info: raom info struct
* @ret_status: update return status
*
* Return: void
*/
static void
wlansap_roam_process_ch_change_success(tpAniSirGlobal mac_ctx,
ptSapContext sap_ctx,
tCsrRoamInfo *csr_roam_info,
CDF_STATUS *ret_status)
{
tWLAN_SAPEvent sap_event;
CDF_STATUS cdf_status;
/*
* Channel change is successful. If the new channel is a DFS channel,
* then we will to perform channel availability check for 60 seconds
*/
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs: changing target channel to [%d]"),
mac_ctx->sap.SapDfsInfo.target_channel);
sap_ctx->channel = mac_ctx->sap.SapDfsInfo.target_channel;
/* Identify if this is channel change in radar detected state */
if (eSAP_DISCONNECTING != sap_ctx->sapsMachine)
return;
/* check if currently selected channel is a DFS channel */
if (CHANNEL_STATE_DFS == cds_get_channel_state(sap_ctx->channel)) {
if ((false == mac_ctx->sap.SapDfsInfo.ignore_cac)
&& (eSAP_DFS_DO_NOT_SKIP_CAC ==
mac_ctx->sap.SapDfsInfo.cac_state)) {
sap_ctx->sapsMachine = eSAP_DISCONNECTED;
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs: from state eSAP_DISCONNECTING => DISCONNECTED with ignore cac false on sapctx[%p]"),
sap_ctx);
/* DFS Channel */
sap_event.event = eSAP_DFS_CHANNEL_CAC_START;
sap_event.params = csr_roam_info;
sap_event.u1 = 0;
sap_event.u2 = 0;
} else {
CDF_TRACE(CDF_MODULE_ID_SAP,
CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs: from state eSAP_DISCONNECTING => eSAP_STARTING with ignore cac true on sapctx[%p]"),
sap_ctx);
/* Start beaconing on the new channel */
wlansap_start_beacon_req(sap_ctx);
sap_ctx->sapsMachine = eSAP_STARTING;
mac_ctx->sap.SapDfsInfo.sap_radar_found_status = false;
sap_event.event = eSAP_MAC_START_BSS_SUCCESS;
sap_event.params = csr_roam_info;
sap_event.u1 = eCSR_ROAM_INFRA_IND;
sap_event.u2 = eCSR_ROAM_RESULT_INFRA_STARTED;
}
} else {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs: from state eSAP_DISCONNECTING => eSAP_STARTING on sapctx[%p]"),
sap_ctx);
/* non-DFS channel */
sap_ctx->sapsMachine = eSAP_STARTING;
mac_ctx->sap.SapDfsInfo.sap_radar_found_status = false;
sap_event.event = eSAP_MAC_START_BSS_SUCCESS;
sap_event.params = csr_roam_info;
sap_event.u1 = eCSR_ROAM_INFRA_IND;
sap_event.u2 = eCSR_ROAM_RESULT_INFRA_STARTED;
}
/* Handle the event */
cdf_status = sap_fsm(sap_ctx, &sap_event);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
*ret_status = CDF_STATUS_E_FAILURE;
}
/**
* wlansap_roam_process_dfs_chansw_update_fail() - handles the case for
* eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_FAILURE in wlansap_roam_callback()
*
* @hal: hal global context
* @sap_ctx: sap context
* @ret_status: update return status
*
* Return: void
*/
static void
wlansap_roam_process_dfs_chansw_update_fail(tHalHandle hHal,
ptSapContext sap_ctx,
CDF_STATUS *ret_status)
{
tWLAN_SAPEvent sap_event;
uint8_t intf;
CDF_STATUS cdf_status;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal);
eCsrPhyMode phy_mode = sap_ctx->csr_roamProfile.phyMode;
uint8_t dfs_beacon_start_req = 0;
if (sap_ctx->csr_roamProfile.disableDFSChSwitch) {
CDF_TRACE(CDF_MODULE_ID_SAP,
CDF_TRACE_LEVEL_ERROR,
FL("sapdfs: DFS channel switch disabled"));
/*
* Send a beacon start request to PE. CSA IE required flag from
* beacon template will be cleared by now. A new beacon template
* with no CSA IE will be sent to firmware.
*/
dfs_beacon_start_req = eSAP_TRUE;
*ret_status = sme_roam_start_beacon_req(hHal, sap_ctx->bssid,
dfs_beacon_start_req);
return;
}
/*
* Both success and failure cases are handled intentionally handled
* together. Irrespective of whether the channel switch IE was sent out
* successfully or not, SAP should still vacate the channel immediately
*/
if (eSAP_STARTED != sap_ctx->sapsMachine) {
/* Further actions to be taken here */
CDF_TRACE(CDF_MODULE_ID_SAP,
CDF_TRACE_LEVEL_WARN,
FL("eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in (%d) state\n"),
sap_ctx->sapsMachine);
return;
}
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs: from state eSAP_STARTED => eSAP_DISCONNECTING"));
/* SAP to be moved to DISCONNECTING state */
sap_ctx->sapsMachine = eSAP_DISCONNECTING;
/*
* The associated stations have been informed to move to a different
* channel. However, the AP may not always select the advertised channel
* for operation if the radar is seen. In that case, the stations will
* experience link-loss and return back through scanning if they wish to
*/
/*
* Send channel change request. From spec it is required that the AP
* should continue to operate in the same mode as it is operating
* currently. For e.g. 20/40/80 MHz operation
*/
if (mac_ctx->sap.SapDfsInfo.target_channel)
sme_set_ch_params(hHal, phy_mode,
mac_ctx->sap.SapDfsInfo.target_channel, 0,
&sap_ctx->ch_params);
/*
* Fetch the number of SAP interfaces. If the number of sap Interface
* more than one then we will make is_sap_ready_for_chnl_chng to true
* for that sapctx. If there is only one SAP interface then process
* immediately
*/
if (sap_get_total_number_sap_intf(hHal) <= 1) {
/* Send channel switch request */
sap_event.event = eWNI_SME_CHANNEL_CHANGE_REQ;
sap_event.params = 0;
sap_event.u1 = 0;
sap_event.u2 = 0;
CDF_TRACE(CDF_MODULE_ID_SAP,
CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs: Posting event eWNI_SME_CHANNEL_CHANGE_REQ to sapFSM"));
/* Handle event */
cdf_status = sap_fsm(sap_ctx, &sap_event);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
*ret_status = CDF_STATUS_E_FAILURE;
return;
}
sap_ctx->is_sap_ready_for_chnl_chng = true;
/*
* now check if the con-current sap interface is ready
* for channel change. If yes then we issue channel change for
* both the SAPs. If no then simply return success & we will
* issue channel change when second AP's 5 CSA beacon Tx is
* completed.
*/
if (false ==
is_concurrent_sap_ready_for_channel_change(hHal, sap_ctx)) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs: sapctx[%p] ready but not concurrent sap"),
sap_ctx);
*ret_status = CDF_STATUS_SUCCESS;
return;
}
/* Issue channel change req for each sapctx */
for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
ptSapContext pSapContext;
if (!((CDF_SAP_MODE == mac_ctx->sap.sapCtxList[intf].sapPersona)
&& (mac_ctx->sap.sapCtxList[intf].pSapContext != NULL)))
continue;
pSapContext = mac_ctx->sap.sapCtxList[intf].pSapContext;
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs:issue chnl change for sapctx[%p]"),
pSapContext);
/* Send channel switch request */
sap_event.event = eWNI_SME_CHANNEL_CHANGE_REQ;
sap_event.params = 0;
sap_event.u1 = 0;
sap_event.u2 = 0;
/* Handle event */
cdf_status = sap_fsm(pSapContext, &sap_event);
if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("post chnl chng req failed, sap[%p]"),
sap_ctx);
*ret_status = CDF_STATUS_E_FAILURE;
} else {
pSapContext->is_sap_ready_for_chnl_chng = false;
}
}
return;
}
/**
* wlansap_roam_process_dfs_radar_found() - handles the case for
* eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND in wlansap_roam_callback()
*
* @mac_ctx: mac global context
* @sap_ctx: sap context
* @ret_status: update return status
*
* Return: result of operation
*/
static void
wlansap_roam_process_dfs_radar_found(tpAniSirGlobal mac_ctx,
ptSapContext sap_ctx,
CDF_STATUS *ret_status)
{
CDF_STATUS cdf_status;
tWLAN_SAPEvent sap_event;
if (eSAP_DFS_CAC_WAIT == sap_ctx->sapsMachine) {
if (sap_ctx->csr_roamProfile.disableDFSChSwitch) {
CDF_TRACE(CDF_MODULE_ID_SAP,
CDF_TRACE_LEVEL_ERROR,
"sapdfs: DFS channel switch disabled");
return;
}
if (false == mac_ctx->sap.SapDfsInfo.sap_radar_found_status)
return;
CDF_TRACE(CDF_MODULE_ID_SAP,
CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs:Posting event eSAP_DFS_CHANNEL_CAC_RADAR_FOUND"));
/*
* If Radar is found, while in DFS CAC WAIT State then post stop
* and destroy the CAC timer and post a
* eSAP_DFS_CHANNEL_CAC_RADAR_FOUND to sapFsm.
*/
cdf_mc_timer_stop(&mac_ctx->sap.SapDfsInfo.sap_dfs_cac_timer);
cdf_mc_timer_destroy(&mac_ctx->sap.SapDfsInfo.sap_dfs_cac_timer);
/*
* User space is already indicated the CAC start and if
* CAC end on this channel is not indicated, the user
* space will be in some undefined state (e.g., UI frozen)
*/
cdf_status = sap_signal_hdd_event(sap_ctx, NULL,
eSAP_DFS_CAC_INTERRUPTED,
(void *) eSAP_STATUS_SUCCESS);
if (CDF_STATUS_SUCCESS != cdf_status) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("Failed to send CAC end"));
/* Want to still proceed and try to switch channel.
* Lets try not to be on the DFS channel
*/
}
mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running = 0;
sap_event.event = eSAP_DFS_CHANNEL_CAC_RADAR_FOUND;
sap_event.params = 0;
sap_event.u1 = 0;
sap_event.u2 = 0;
cdf_status = sap_fsm(sap_ctx, &sap_event);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
*ret_status = CDF_STATUS_E_FAILURE;
return;
}
if (eSAP_STARTED == sap_ctx->sapsMachine) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs:Posting event eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START"));
/*
* Radar found on the operating channel in STARTED state,
* new operating channel has already been selected. Send
* request to SME-->PE for sending CSA IE
*/
sap_event.event = eSAP_DFS_CHNL_SWITCH_ANNOUNCEMENT_START;
sap_event.params = 0;
sap_event.u1 = 0;
sap_event.u2 = 0;
cdf_status = sap_fsm(sap_ctx, &sap_event);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
*ret_status = CDF_STATUS_E_FAILURE;
return;
}
/* Further actions to be taken here */
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND received in (%d) state\n"),
sap_ctx->sapsMachine);
return;
}
/**
* wlansap_roam_process_infra_assoc_ind() - handles the case for
* eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND in wlansap_roam_callback()
*
* @sap_ctx: sap context
* @roam_result: roam result
* @csr_roam_info: roam info struct
* @ret_status: update return status
*
* Return: result of operation
*/
static void
wlansap_roam_process_infra_assoc_ind(ptSapContext sap_ctx,
eCsrRoamResult roam_result,
tCsrRoamInfo *csr_roam_info,
CDF_STATUS *ret_status)
{
CDF_STATUS cdf_status;
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND (%d)\n"),
roam_result);
sap_ctx->nStaWPARSnReqIeLength = csr_roam_info->rsnIELen;
if (sap_ctx->nStaWPARSnReqIeLength)
cdf_mem_copy(sap_ctx->pStaWpaRsnReqIE, csr_roam_info->prsnIE,
sap_ctx->nStaWPARSnReqIeLength);
#ifdef FEATURE_WLAN_WAPI
sap_ctx->nStaWAPIReqIeLength = csr_roam_info->wapiIELen;
if (sap_ctx->nStaWAPIReqIeLength)
cdf_mem_copy(sap_ctx->pStaWapiReqIE, csr_roam_info->pwapiIE,
sap_ctx->nStaWAPIReqIeLength);
#endif
sap_ctx->nStaAddIeLength = csr_roam_info->addIELen;
if (sap_ctx->nStaAddIeLength)
cdf_mem_copy(sap_ctx->pStaAddIE, csr_roam_info->paddIE,
sap_ctx->nStaAddIeLength);
sap_ctx->SapQosCfg.WmmIsEnabled = csr_roam_info->wmmEnabledSta;
/* MAC filtering */
cdf_status = sap_is_peer_mac_allowed(sap_ctx,
(uint8_t *) csr_roam_info->peerMac.bytes);
if (CDF_STATUS_SUCCESS == cdf_status) {
cdf_status = sap_signal_hdd_event(sap_ctx,
csr_roam_info, eSAP_STA_ASSOC_IND,
(void *) eSAP_STATUS_SUCCESS);
if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("CSR roam_result = (%d) MAC ("MAC_ADDRESS_STR") fail"),
roam_result, MAC_ADDR_ARRAY(
csr_roam_info->peerMac.bytes));
*ret_status = CDF_STATUS_E_FAILURE;
}
} else {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_WARN,
FL("CSR roam_result = (%d) MAC ("MAC_ADDRESS_STR") not allowed"),
roam_result,
MAC_ADDR_ARRAY(csr_roam_info->peerMac.bytes));
*ret_status = CDF_STATUS_E_FAILURE;
}
return;
}
/**
* wlansap_roam_callback() - Callback for Roam (connection status) Events
* @ctx : pContext passed in with the roam request
* @csr_roam_info : Pointer to a tCsrRoamInfo
* @roamId : to identify the callback related roam request.
* 0 means unsolicit
* @roam_status : Flag indicating the status of the callback
* @roam_result : Result
*
* This function finds dot11 mode based on current mode, operating channel and
* fw supported modes.
*
* Return: Status of operation
*/
CDF_STATUS
wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId,
eRoamCmdStatus roam_status, eCsrRoamResult roam_result)
{
/* sap_ctx value */
ptSapContext sap_ctx = (ptSapContext) ctx;
/* State machine event */
tWLAN_SAPEvent sap_event;
CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
CDF_STATUS cdf_ret_status = CDF_STATUS_SUCCESS;
tHalHandle hal = CDS_GET_HAL_CB(sap_ctx->p_cds_gctx);
tpAniSirGlobal mac_ctx = NULL;
uint8_t intf;
if (NULL == hal) {
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("Invalid hal"));
cdf_ret_status = CDF_STATUS_E_NOMEM;
return cdf_ret_status;
}
mac_ctx = PMAC_STRUCT(hal);
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("Before switch on roam_status = %d\n"), roam_status);
switch (roam_status) {
case eCSR_ROAM_SESSION_OPENED:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("Calling sme_roam_connect with eCSR_BSS_TYPE_INFRA_AP"));
sap_ctx->isSapSessionOpen = eSAP_TRUE;
cdf_ret_status = sme_roam_connect(hal, sap_ctx->sessionId,
&sap_ctx->csr_roamProfile,
&sap_ctx->csr_roamId);
break;
case eCSR_ROAM_INFRA_IND:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_status = eCSR_ROAM_INFRA_IND (%d)\n"),
roam_status);
if (roam_result == eCSR_ROAM_RESULT_INFRA_START_FAILED) {
/* Fill in the event structure */
sap_event.event = eSAP_MAC_START_FAILS;
sap_event.params = csr_roam_info;
sap_event.u1 = roam_status;
sap_event.u2 = roam_result;
/* Handle event */
cdf_status = sap_fsm(sap_ctx, &sap_event);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
}
break;
case eCSR_ROAM_LOSTLINK:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_status = eCSR_ROAM_LOSTLINK (%d)\n"),
roam_status);
break;
case eCSR_ROAM_MIC_ERROR_IND:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_status = eCSR_ROAM_MIC_ERROR_IND (%d)\n"),
roam_status);
break;
case eCSR_ROAM_SET_KEY_COMPLETE:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_status = eCSR_ROAM_SET_KEY_COMPLETE (%d)\n"),
roam_status);
if (roam_result == eCSR_ROAM_RESULT_FAILURE)
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_SET_KEY_EVENT,
(void *) eSAP_STATUS_FAILURE);
break;
case eCSR_ROAM_ASSOCIATION_COMPLETION:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_status = eCSR_ROAM_ASSOCIATION_COMPLETION (%d)\n"),
roam_status);
if (roam_result == eCSR_ROAM_RESULT_FAILURE)
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_REASSOC_EVENT,
(void *) eSAP_STATUS_FAILURE);
break;
case eCSR_ROAM_DISASSOCIATED:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_status = eCSR_ROAM_DISASSOCIATED (%d)\n"),
roam_status);
if (roam_result == eCSR_ROAM_RESULT_MIC_FAILURE)
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_MIC_FAILURE_EVENT,
(void *) eSAP_STATUS_FAILURE);
break;
case eCSR_ROAM_WPS_PBC_PROBE_REQ_IND:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_status = eCSR_ROAM_WPS_PBC_PROBE_REQ_IND (%d)\n"),
roam_status);
break;
case eCSR_ROAM_INDICATE_MGMT_FRAME:
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_INDICATE_MGMT_FRAME,
(void *) eSAP_STATUS_SUCCESS);
break;
case eCSR_ROAM_REMAIN_CHAN_READY:
/* roamId contains scan identifier */
sap_ctx->roc_ind_scan_id = csr_roam_info->roc_scan_id;
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_REMAIN_CHAN_READY,
(void *) eSAP_STATUS_SUCCESS);
break;
case eCSR_ROAM_SEND_ACTION_CNF:
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_SEND_ACTION_CNF,
(void *) ((eSapStatus)
((roam_result == eCSR_ROAM_RESULT_NONE) ?
eSAP_STATUS_SUCCESS : eSAP_STATUS_FAILURE)));
break;
case eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS:
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_DISCONNECT_ALL_P2P_CLIENT,
(void *) eSAP_STATUS_SUCCESS);
break;
case eCSR_ROAM_SEND_P2P_STOP_BSS:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("Received stopbss"));
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_MAC_TRIG_STOP_BSS_EVENT,
(void *) eSAP_STATUS_SUCCESS);
break;
case eCSR_ROAM_DFS_RADAR_IND:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("Received Radar Indication"));
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_MED,
FL("sapdfs: Indicate eSAP_DFS_RADAR_DETECT to HDD"));
sap_signal_hdd_event(sap_ctx, NULL, eSAP_DFS_RADAR_DETECT,
(void *) eSAP_STATUS_SUCCESS);
/* sync to latest DFS-NOL */
sap_signal_hdd_event(sap_ctx, NULL, eSAP_DFS_NOL_GET,
(void *) eSAP_STATUS_SUCCESS);
mac_ctx->sap.SapDfsInfo.target_channel =
sap_indicate_radar(sap_ctx, &csr_roam_info->dfs_event);
/* if there is an assigned next channel hopping */
if (0 < mac_ctx->sap.SapDfsInfo.user_provided_target_channel) {
mac_ctx->sap.SapDfsInfo.target_channel =
mac_ctx->sap.SapDfsInfo.user_provided_target_channel;
mac_ctx->sap.SapDfsInfo.user_provided_target_channel =
0;
}
if (mac_ctx->sap.SapDfsInfo.target_channel != 0) {
mac_ctx->sap.SapDfsInfo.cac_state =
eSAP_DFS_DO_NOT_SKIP_CAC;
sap_cac_reset_notify(hal);
/* set DFS-NOL back to keep it update-to-date in CNSS */
sap_signal_hdd_event(sap_ctx, NULL, eSAP_DFS_NOL_SET,
(void *) eSAP_STATUS_SUCCESS);
break;
}
/* Issue stopbss for each sapctx */
for (intf = 0; intf < SAP_MAX_NUM_SESSION; intf++) {
ptSapContext pSapContext;
if (((CDF_SAP_MODE ==
mac_ctx->sap.sapCtxList[intf].sapPersona) ||
(CDF_P2P_GO_MODE ==
mac_ctx->sap.sapCtxList[intf].sapPersona)) &&
mac_ctx->sap.sapCtxList[intf].pSapContext !=
NULL) {
pSapContext =
mac_ctx->sap.sapCtxList[intf].pSapContext;
CDF_TRACE(CDF_MODULE_ID_SAP,
CDF_TRACE_LEVEL_ERROR,
FL("sapdfs: no available channel for sapctx[%p], StopBss"),
pSapContext);
wlansap_stop_bss(pSapContext);
}
}
break;
case eCSR_ROAM_DFS_CHAN_SW_NOTIFY:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("Received Chan Sw Update Notification"));
break;
case eCSR_ROAM_SET_CHANNEL_RSP:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("Received set channel response"));
break;
default:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("CSR roam_status not handled roam_status = %s (%d)\n"),
get_e_roam_cmd_status_str(roam_status),
roam_status);
break;
}
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("Before switch on roam_result = %d\n"), roam_result);
switch (roam_result) {
case eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND:
wlansap_roam_process_infra_assoc_ind(sap_ctx, roam_result,
csr_roam_info, &cdf_ret_status);
break;
case eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF (%d)\n"),
roam_result);
sap_ctx->nStaWPARSnReqIeLength = csr_roam_info->rsnIELen;
if (sap_ctx->nStaWPARSnReqIeLength)
cdf_mem_copy(sap_ctx->pStaWpaRsnReqIE,
csr_roam_info->prsnIE,
sap_ctx->nStaWPARSnReqIeLength);
sap_ctx->nStaAddIeLength = csr_roam_info->addIELen;
if (sap_ctx->nStaAddIeLength)
cdf_mem_copy(sap_ctx->pStaAddIE,
csr_roam_info->paddIE,
sap_ctx->nStaAddIeLength);
sap_ctx->SapQosCfg.WmmIsEnabled =
csr_roam_info->wmmEnabledSta;
/* Fill in the event structure */
cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_ASSOC_EVENT,
(void *) eSAP_STATUS_SUCCESS);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
break;
case eCSR_ROAM_RESULT_DISASSOC_IND:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_DISASSOC_IND (%d)\n"),
roam_result);
/* Fill in the event structure */
cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_DISASSOC_EVENT,
(void *) eSAP_STATUS_SUCCESS);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
break;
case eCSR_ROAM_RESULT_DEAUTH_IND:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_DEAUTH_IND (%d)\n"),
roam_result);
/*
* Fill in the event structure
* we use the same event inorder to inform HDD to disassociate
* the station
*/
cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_DISASSOC_EVENT,
(void *) eSAP_STATUS_SUCCESS);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
break;
case eCSR_ROAM_RESULT_MIC_ERROR_GROUP:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_MIC_ERROR_GROUP (%d)\n"),
roam_result);
/*
* Fill in the event structure
* TODO: support for group key MIC failure event to be handled
*/
cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_MIC_FAILURE_EVENT,
(void *) NULL);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
break;
case eCSR_ROAM_RESULT_MIC_ERROR_UNICAST:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST (%d)\n"),
roam_result);
/*
* Fill in the event structure
* TODO: support for unicast key MIC failure event to be handled
*/
cdf_status =
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_MIC_FAILURE_EVENT,
(void *) NULL);
if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
cdf_ret_status = CDF_STATUS_E_FAILURE;
}
break;
case eCSR_ROAM_RESULT_AUTHENTICATED:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_AUTHENTICATED (%d)\n"),
roam_result);
/* Fill in the event structure */
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_SET_KEY_EVENT,
(void *) eSAP_STATUS_SUCCESS);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
break;
case eCSR_ROAM_RESULT_ASSOCIATED:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_ASSOCIATED (%d)\n"),
roam_result);
/* Fill in the event structure */
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_REASSOC_EVENT,
(void *) eSAP_STATUS_SUCCESS);
break;
case eCSR_ROAM_RESULT_INFRA_STARTED:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_INFRA_STARTED (%d)\n"),
roam_result);
/*
* In the current implementation, hostapd is not aware that
* drive will support DFS. Hence, driver should inform
* eSAP_MAC_START_BSS_SUCCESS to upper layers and then perform
* CAC underneath
*/
sap_event.event = eSAP_MAC_START_BSS_SUCCESS;
sap_event.params = csr_roam_info;
sap_event.u1 = roam_status;
sap_event.u2 = roam_result;
cdf_status = sap_fsm(sap_ctx, &sap_event);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
break;
case eCSR_ROAM_RESULT_INFRA_STOPPED:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_INFRA_STOPPED (%d)\n"),
roam_result);
/* Fill in the event structure */
sap_event.event = eSAP_MAC_READY_FOR_CONNECTIONS;
sap_event.params = csr_roam_info;
sap_event.u1 = roam_status;
sap_event.u2 = roam_result;
/* Handle event */
cdf_status = sap_fsm(sap_ctx, &sap_event);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
break;
case eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND (%d)\n"),
roam_result);
/*
* Fill in the event structure
* TODO: support for group key MIC failure event to be handled
*/
cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_WPS_PBC_PROBE_REQ_EVENT,
(void *) NULL);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
break;
case eCSR_ROAM_RESULT_FORCED:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_FORCED (%d)\n"),
roam_result);
/*
* This event can be used to inform hdd about user triggered
* disassoc event
* Fill in the event structure
*/
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_DISASSOC_EVENT,
(void *) eSAP_STATUS_SUCCESS);
break;
case eCSR_ROAM_RESULT_NONE:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_NONE (%d)\n"),
roam_result);
/*
* This event can be used to inform hdd about user triggered
* disassoc event
* Fill in the event structure
*/
if (roam_status == eCSR_ROAM_SET_KEY_COMPLETE)
sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_STA_SET_KEY_EVENT,
(void *) eSAP_STATUS_SUCCESS);
break;
case eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
FL("CSR roam_result = eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED (%d)\n"),
roam_result);
/* Fill in the event structure */
cdf_status = sap_signal_hdd_event(sap_ctx, csr_roam_info,
eSAP_MAX_ASSOC_EXCEEDED,
NULL);
if (!CDF_IS_STATUS_SUCCESS(cdf_status))
cdf_ret_status = CDF_STATUS_E_FAILURE;
break;
case eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND:
wlansap_roam_process_dfs_radar_found(mac_ctx, sap_ctx,
&cdf_ret_status);
break;
case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS:
case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_FAILURE:
wlansap_roam_process_dfs_chansw_update_fail(hal, sap_ctx,
&cdf_ret_status);
break;
case eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS:
wlansap_roam_process_ch_change_success(mac_ctx, sap_ctx,
csr_roam_info, &cdf_ret_status);
break;
case eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE:
/*
* This is much more serious issue, we have to vacate the
* channel due to the presence of radar but our channel change
* failed, stop the BSS operation completely and inform hostapd
*/
sap_ctx->sapsMachine = eSAP_DISCONNECTED;
/* Inform cfg80211 and hostapd that BSS is not alive anymore */
break;
default:
CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
FL("CSR roam_result = %s (%d) not handled\n"),
get_e_csr_roam_result_str(roam_result),
roam_result);
break;
}
return cdf_ret_status;
}