blob: f7c09071e12912a5cb67fb32ee69bc6c0c3e83ab [file] [log] [blame]
/*
* Copyright (c) 2012-2018 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: smeApi.c
*
* Definitions for SME APIs
*/
/* Include Files */
#include <sir_common.h>
#include <ani_global.h>
#include "sme_api.h"
#include "csr_inside_api.h"
#include "sme_inside.h"
#include "csr_internal.h"
#include "wma_types.h"
#include "wma_if.h"
#include "wma_fips_api.h"
#include "qdf_trace.h"
#include "sme_trace.h"
#include "qdf_types.h"
#include "qdf_trace.h"
#include "cds_utils.h"
#include "sap_api.h"
#include "mac_trace.h"
#ifdef WLAN_FEATURE_NAN
#include "nan_api.h"
#endif
#include "cds_regdomain.h"
#include "cfg_api.h"
#include "sme_power_save_api.h"
#include "wma.h"
#include "sch_api.h"
#include "sme_nan_datapath.h"
#include "csr_api.h"
#include "wlan_reg_services_api.h"
#include <wlan_scan_ucfg_api.h>
#include "wlan_reg_ucfg_api.h"
#include "ol_txrx.h"
#include "wifi_pos_api.h"
#include "net/cfg80211.h"
#include <qca_vendor.h>
#include <wlan_spectral_utils_api.h>
#include "wlan_mlme_public_struct.h"
static tSelfRecoveryStats g_self_recovery_stats;
static QDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac);
static void sme_disconnect_connected_sessions(tpAniSirGlobal pMac);
static QDF_STATUS sme_handle_generic_change_country_code(tpAniSirGlobal pMac,
void *pMsgBuf);
static QDF_STATUS sme_process_nss_update_resp(tpAniSirGlobal mac, uint8_t *msg);
/* Channel Change Response Indication Handler */
static QDF_STATUS sme_process_channel_change_resp(tpAniSirGlobal pMac,
uint16_t msg_type, void *pMsgBuf);
static QDF_STATUS sme_stats_ext_event(tpAniSirGlobal mac,
struct stats_ext_event *msg);
/* Internal SME APIs */
QDF_STATUS sme_acquire_global_lock(tSmeStruct *psSme)
{
QDF_STATUS status = QDF_STATUS_E_INVAL;
if (psSme) {
if (QDF_IS_STATUS_SUCCESS
(qdf_mutex_acquire(&psSme->lkSmeGlobalLock)))
status = QDF_STATUS_SUCCESS;
}
return status;
}
QDF_STATUS sme_release_global_lock(tSmeStruct *psSme)
{
QDF_STATUS status = QDF_STATUS_E_INVAL;
if (psSme) {
if (QDF_IS_STATUS_SUCCESS
(qdf_mutex_release(&psSme->lkSmeGlobalLock)))
status = QDF_STATUS_SUCCESS;
}
return status;
}
tpAniSirGlobal sme_get_mac_context(void)
{
tpAniSirGlobal mac_ctx;
tHalHandle h_hal;
h_hal = cds_get_context(QDF_MODULE_ID_SME);
if (NULL == h_hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
FL("invalid h_hal"));
return NULL;
}
mac_ctx = PMAC_STRUCT(h_hal);
return mac_ctx;
}
/**
* sme_process_set_hw_mode_resp() - Process set HW mode response
* @mac: Global MAC pointer
* @msg: HW mode response
*
* Processes the HW mode response and invokes the HDD callback
* to process further
*/
static QDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg)
{
tListElem *entry;
tSmeCmd *command = NULL;
bool found;
policy_mgr_pdev_set_hw_mode_cback callback = NULL;
struct sir_set_hw_mode_resp *param;
enum policy_mgr_conn_update_reason reason;
struct csr_roam_session *session;
uint32_t session_id;
param = (struct sir_set_hw_mode_resp *)msg;
if (!param) {
sme_err("HW mode resp param is NULL");
/* Not returning. Need to check if active command list
* needs to be freed
*/
}
entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK);
if (!entry) {
sme_err("No cmd found in active list");
return QDF_STATUS_E_FAILURE;
}
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
if (!command) {
sme_err("Base address is NULL");
return QDF_STATUS_E_FAILURE;
}
if (e_sme_command_set_hw_mode != command->command) {
sme_err("Command mismatch!");
return QDF_STATUS_E_FAILURE;
}
callback = command->u.set_hw_mode_cmd.set_hw_mode_cb;
reason = command->u.set_hw_mode_cmd.reason;
session_id = command->u.set_hw_mode_cmd.session_id;
sme_debug("reason: %d session: %d",
command->u.set_hw_mode_cmd.reason,
command->u.set_hw_mode_cmd.session_id);
if (!callback) {
sme_err("Callback does not exist");
goto end;
}
if (!param) {
sme_err("Callback failed since HW mode params is NULL");
goto end;
}
/* Irrespective of the reason for which the hw mode change request
* was issued, the policy manager connection table needs to be updated
* with the new vdev-mac id mapping, tx/rx spatial streams etc., if the
* set hw mode was successful.
*/
callback(param->status,
param->cfgd_hw_mode_index,
param->num_vdev_mac_entries,
param->vdev_mac_map,
command->u.set_hw_mode_cmd.next_action,
command->u.set_hw_mode_cmd.reason,
command->u.set_hw_mode_cmd.session_id,
command->u.set_hw_mode_cmd.context);
if (!CSR_IS_SESSION_VALID(mac, session_id)) {
sme_err("session %d is invalid", session_id);
goto end;
}
session = CSR_GET_SESSION(mac, session_id);
if (reason == POLICY_MGR_UPDATE_REASON_HIDDEN_STA) {
/* In the case of hidden SSID, connection update
* (set hw mode) is done after the scan with reason
* code eCsrScanForSsid completes. The connect/failure
* needs to be handled after the response of set hw
* mode
*/
if (param->status == SET_HW_MODE_STATUS_OK) {
sme_debug("search for ssid success");
csr_scan_handle_search_for_ssid(mac,
session_id);
} else {
sme_debug("search for ssid failure");
csr_scan_handle_search_for_ssid_failure(mac,
session_id);
}
csr_saved_scan_cmd_free_fields(mac, session);
}
end:
found = csr_nonscan_active_ll_remove_entry(mac, entry,
LL_ACCESS_LOCK);
if (found)
/* Now put this command back on the avilable command list */
csr_release_command(mac, command);
return QDF_STATUS_SUCCESS;
}
/**
* sme_process_hw_mode_trans_ind() - Process HW mode transition indication
* @mac: Global MAC pointer
* @msg: HW mode transition response
*
* Processes the HW mode transition indication and invoke the HDD callback
* to process further
*/
static QDF_STATUS sme_process_hw_mode_trans_ind(tpAniSirGlobal mac,
uint8_t *msg)
{
struct sir_hw_mode_trans_ind *param;
param = (struct sir_hw_mode_trans_ind *)msg;
if (!param) {
sme_err("HW mode trans ind param is NULL");
return QDF_STATUS_E_FAILURE;
}
policy_mgr_hw_mode_transition_cb(param->old_hw_mode_index,
param->new_hw_mode_index,
param->num_vdev_mac_entries,
param->vdev_mac_map, mac->psoc);
return QDF_STATUS_SUCCESS;
}
/**
* free_sme_cmds() - This function frees memory allocated for SME commands
* @mac_ctx: Pointer to Global MAC structure
*
* This function frees memory allocated for SME commands
*
* @Return: void
*/
static void free_sme_cmds(tpAniSirGlobal mac_ctx)
{
uint32_t idx;
if (NULL == mac_ctx->sme.pSmeCmdBufAddr)
return;
for (idx = 0; idx < mac_ctx->sme.totalSmeCmd; idx++)
qdf_mem_free(mac_ctx->sme.pSmeCmdBufAddr[idx]);
qdf_mem_free(mac_ctx->sme.pSmeCmdBufAddr);
mac_ctx->sme.pSmeCmdBufAddr = NULL;
}
static QDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac)
{
QDF_STATUS status;
tSmeCmd *pCmd;
uint32_t cmd_idx;
uint32_t sme_cmd_ptr_ary_sz;
pMac->sme.totalSmeCmd = SME_TOTAL_COMMAND;
status = csr_ll_open(&pMac->sme.smeCmdFreeList);
if (!QDF_IS_STATUS_SUCCESS(status))
goto end;
/* following pointer contains array of pointers for tSmeCmd* */
sme_cmd_ptr_ary_sz = sizeof(void *) * pMac->sme.totalSmeCmd;
pMac->sme.pSmeCmdBufAddr = qdf_mem_malloc(sme_cmd_ptr_ary_sz);
if (NULL == pMac->sme.pSmeCmdBufAddr) {
status = QDF_STATUS_E_NOMEM;
goto end;
}
status = QDF_STATUS_SUCCESS;
for (cmd_idx = 0; cmd_idx < pMac->sme.totalSmeCmd; cmd_idx++) {
/*
* Since total size of all commands together can be huge chunk
* of memory, allocate SME cmd individually. These SME CMDs are
* moved between pending and active queues. And these freeing of
* these queues just manipulates the list but does not actually
* frees SME CMD pointers. Hence store each SME CMD address in
* the array, sme.pSmeCmdBufAddr. This will later facilitate
* freeing up of all SME CMDs with just a for loop.
*/
pMac->sme.pSmeCmdBufAddr[cmd_idx] =
qdf_mem_malloc(sizeof(tSmeCmd));
if (NULL == pMac->sme.pSmeCmdBufAddr[cmd_idx]) {
status = QDF_STATUS_E_NOMEM;
free_sme_cmds(pMac);
goto end;
}
pCmd = (tSmeCmd *)pMac->sme.pSmeCmdBufAddr[cmd_idx];
csr_ll_insert_tail(&pMac->sme.smeCmdFreeList,
&pCmd->Link, LL_ACCESS_LOCK);
}
end:
if (!QDF_IS_STATUS_SUCCESS(status))
sme_err("Failed to initialize sme command list: %d", status);
return status;
}
void sme_release_command(tpAniSirGlobal mac_ctx, tSmeCmd *sme_cmd)
{
sme_cmd->command = eSmeNoCommand;
csr_ll_insert_tail(&mac_ctx->sme.smeCmdFreeList, &sme_cmd->Link,
LL_ACCESS_LOCK);
}
static QDF_STATUS free_sme_cmd_list(tpAniSirGlobal pMac)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
csr_ll_close(&pMac->sme.smeCmdFreeList);
status = qdf_mutex_acquire(&pMac->sme.lkSmeGlobalLock);
if (status != QDF_STATUS_SUCCESS) {
sme_err("Failed to acquire the lock status: %d", status);
goto done;
}
free_sme_cmds(pMac);
status = qdf_mutex_release(&pMac->sme.lkSmeGlobalLock);
if (status != QDF_STATUS_SUCCESS)
sme_err("Failed to release the lock status: %d", status);
done:
return status;
}
static void dump_csr_command_info(tpAniSirGlobal pMac, tSmeCmd *pCmd)
{
switch (pCmd->command) {
case eSmeCommandRoam:
sme_debug("roam command reason is %d",
pCmd->u.roamCmd.roamReason);
break;
case eSmeCommandWmStatusChange:
sme_debug("WMStatusChange command type is %d",
pCmd->u.wmStatusChangeCmd.Type);
break;
case e_sme_command_del_sta_session:
sme_debug("Issue del STA command for session:%d",
pCmd->sessionId);
break;
default:
sme_debug("default: Unhandled command %d",
pCmd->command);
break;
}
}
tSmeCmd *sme_get_command_buffer(tpAniSirGlobal pMac)
{
tSmeCmd *pRetCmd = NULL, *pTempCmd = NULL;
tListElem *pEntry;
static int sme_command_queue_full;
pEntry = csr_ll_remove_head(&pMac->sme.smeCmdFreeList, LL_ACCESS_LOCK);
/* If we can get another MS Msg buffer, then we are ok. Just link */
/* the entry onto the linked list. (We are using the linked list */
/* to keep track of tfhe message buffers). */
if (pEntry) {
pRetCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
/* reset when free list is available */
sme_command_queue_full = 0;
} else {
int idx = 1;
/* Cannot change pRetCmd here since it needs to return later. */
pEntry = csr_nonscan_active_ll_peek_head(pMac, LL_ACCESS_LOCK);
if (pEntry)
pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
sme_err("Out of command buffer.... command (0x%X) stuck",
(pTempCmd) ? pTempCmd->command : eSmeNoCommand);
if (pTempCmd) {
if (eSmeCsrCommandMask & pTempCmd->command)
/* CSR command is stuck. See what the reason
* code is for that command
*/
dump_csr_command_info(pMac, pTempCmd);
} /* if(pTempCmd) */
/* dump what is in the pending queue */
csr_nonscan_pending_ll_lock(pMac);
pEntry =
csr_nonscan_pending_ll_peek_head(pMac,
LL_ACCESS_NOLOCK);
while (pEntry && !sme_command_queue_full) {
pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
/* Print only 1st five commands from pending queue. */
if (idx <= 5)
sme_err("Out of command buffer.... SME pending command #%d (0x%X)",
idx, pTempCmd->command);
idx++;
if (eSmeCsrCommandMask & pTempCmd->command)
/* CSR command is stuck. See what the reason
* code is for that command
*/
dump_csr_command_info(pMac, pTempCmd);
pEntry = csr_nonscan_pending_ll_next(pMac, pEntry,
LL_ACCESS_NOLOCK);
}
csr_nonscan_pending_ll_unlock(pMac);
if (pMac->roam.configParam.enable_fatal_event)
cds_flush_logs(WLAN_LOG_TYPE_FATAL,
WLAN_LOG_INDICATOR_HOST_DRIVER,
WLAN_LOG_REASON_SME_OUT_OF_CMD_BUF,
false,
pMac->sme.enableSelfRecovery ? true : false);
else
cds_trigger_recovery(QDF_GET_MSG_BUFF_FAILURE);
}
/* memset to zero */
if (pRetCmd) {
qdf_mem_set((uint8_t *)&pRetCmd->command,
sizeof(pRetCmd->command), 0);
qdf_mem_set((uint8_t *)&pRetCmd->sessionId,
sizeof(pRetCmd->sessionId), 0);
qdf_mem_set((uint8_t *)&pRetCmd->u, sizeof(pRetCmd->u), 0);
}
return pRetCmd;
}
/**
* sme_ser_handle_active_cmd() - handle command activation callback from
* new serialization module
* @cmd: pointer to new serialization command
*
* This API is to handle command activation callback from new serialization
* callback
*
* Return: QDF_STATUS_SUCCESS
*/
static
QDF_STATUS sme_ser_handle_active_cmd(struct wlan_serialization_command *cmd)
{
tSmeCmd *sme_cmd;
tHalHandle hal;
tpAniSirGlobal mac_ctx;
QDF_STATUS status = QDF_STATUS_SUCCESS;
bool do_continue;
if (!cmd) {
sme_err("No serialization command found");
return QDF_STATUS_E_FAILURE;
}
hal = cds_get_context(QDF_MODULE_ID_SME);
if (NULL != hal) {
mac_ctx = PMAC_STRUCT(hal);
} else {
sme_err("No hal found");
return QDF_STATUS_E_FAILURE;
}
sme_cmd = cmd->umac_cmd;
if (!sme_cmd) {
sme_err("No SME command found");
return QDF_STATUS_E_FAILURE;
}
switch (sme_cmd->command) {
case eSmeCommandRoam:
status = csr_roam_process_command(mac_ctx, sme_cmd);
break;
case eSmeCommandWmStatusChange:
csr_roam_process_wm_status_change_command(mac_ctx,
sme_cmd);
break;
case e_sme_command_del_sta_session:
csr_process_del_sta_session_command(mac_ctx, sme_cmd);
break;
case eSmeCommandAddTs:
case eSmeCommandDelTs:
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
do_continue = qos_process_command(mac_ctx, sme_cmd);
if (do_continue)
status = QDF_STATUS_E_FAILURE;
#endif
break;
case e_sme_command_set_hw_mode:
csr_process_set_hw_mode(mac_ctx, sme_cmd);
break;
case e_sme_command_nss_update:
csr_process_nss_update_req(mac_ctx, sme_cmd);
break;
case e_sme_command_set_dual_mac_config:
csr_process_set_dual_mac_config(mac_ctx, sme_cmd);
break;
case e_sme_command_set_antenna_mode:
csr_process_set_antenna_mode(mac_ctx, sme_cmd);
break;
default:
/* something is wrong */
sme_err("unknown command %d", sme_cmd->command);
status = QDF_STATUS_E_FAILURE;
break;
}
return status;
}
QDF_STATUS sme_ser_cmd_callback(void *buf,
enum wlan_serialization_cb_reason reason)
{
struct wlan_serialization_command *cmd = buf;
tHalHandle hal;
tpAniSirGlobal mac_ctx;
QDF_STATUS status = QDF_STATUS_SUCCESS;
tSmeCmd *sme_cmd;
hal = cds_get_context(QDF_MODULE_ID_SME);
if (hal != NULL) {
mac_ctx = PMAC_STRUCT(hal);
} else {
sme_err("hal is null");
return QDF_STATUS_E_FAILURE;
}
/*
* Do not acquire lock here as sme global lock is already acquired in
* caller or MC thread context
*/
if (!cmd) {
sme_err("serialization command is null");
return QDF_STATUS_E_FAILURE;
}
switch (reason) {
case WLAN_SER_CB_ACTIVATE_CMD:
sme_debug("WLAN_SER_CB_ACTIVATE_CMD callback");
status = sme_ser_handle_active_cmd(cmd);
break;
case WLAN_SER_CB_CANCEL_CMD:
sme_debug("WLAN_SER_CB_CANCEL_CMD callback");
break;
case WLAN_SER_CB_RELEASE_MEM_CMD:
sme_debug("WLAN_SER_CB_RELEASE_MEM_CMD callback");
sme_cmd = cmd->umac_cmd;
csr_release_command_buffer(mac_ctx, sme_cmd);
break;
case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
sme_debug("WLAN_SER_CB_ACTIVE_CMD_TIMEOUT callback");
break;
default:
sme_debug("STOP: unknown reason code");
return QDF_STATUS_E_FAILURE;
}
return status;
}
#ifdef WLAN_FEATURE_MEMDUMP_ENABLE
/**
* sme_get_sessionid_from_activelist() - gets session id
* @mac: mac context
*
* This function is used to get session id from sme command
* active list
*
* Return: returns session id
*/
static uint32_t sme_get_sessionid_from_activelist(tpAniSirGlobal mac)
{
tListElem *entry;
tSmeCmd *command;
uint32_t session_id = CSR_SESSION_ID_INVALID;
entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK);
if (entry) {
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
session_id = command->sessionId;
}
return session_id;
}
/**
* sme_state_info_dump() - prints state information of sme layer
* @buf: buffer pointer
* @size: size of buffer to be filled
*
* This function is used to dump state information of sme layer
*
* Return: None
*/
static void sme_state_info_dump(char **buf_ptr, uint16_t *size)
{
uint32_t session_id, active_session_id;
tHalHandle hal;
tpAniSirGlobal mac;
uint16_t len = 0;
char *buf = *buf_ptr;
eCsrConnectState connect_state;
hal = cds_get_context(QDF_MODULE_ID_SME);
if (hal == NULL) {
QDF_ASSERT(0);
return;
}
mac = PMAC_STRUCT(hal);
active_session_id = sme_get_sessionid_from_activelist(mac);
if (active_session_id != CSR_SESSION_ID_INVALID) {
len += qdf_scnprintf(buf + len, *size - len,
"\n active command sessionid %d", active_session_id);
}
for (session_id = 0; session_id < CSR_ROAM_SESSION_MAX; session_id++) {
if (CSR_IS_SESSION_VALID(mac, session_id)) {
connect_state =
mac->roam.roamSession[session_id].connectState;
if ((eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED ==
connect_state)
|| (eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED ==
connect_state)) {
len += qdf_scnprintf(buf + len, *size - len,
"\n NeighborRoamState: %d",
mac->roam.neighborRoamInfo[session_id].
neighborRoamState);
len += qdf_scnprintf(buf + len, *size - len,
"\n RoamState: %d", mac->roam.
curState[session_id]);
len += qdf_scnprintf(buf + len, *size - len,
"\n RoamSubState: %d", mac->roam.
curSubState[session_id]);
len += qdf_scnprintf(buf + len, *size - len,
"\n ConnectState: %d",
connect_state);
}
}
}
*size -= len;
*buf_ptr += len;
}
/**
* sme_register_debug_callback() - registration function sme layer
* to print sme state information
*
* Return: None
*/
static void sme_register_debug_callback(void)
{
qdf_register_debug_callback(QDF_MODULE_ID_SME, &sme_state_info_dump);
}
#else /* WLAN_FEATURE_MEMDUMP_ENABLE */
static void sme_register_debug_callback(void)
{
}
#endif /* WLAN_FEATURE_MEMDUMP_ENABLE */
/* Global APIs */
/**
* sme_open() - Initialze all SME modules and put them at idle state
* @hHal: The handle returned by mac_open
*
* The function initializes each module inside SME, PMC, CSR, etc. Upon
* successfully return, all modules are at idle state ready to start.
* smeOpen must be called before any other SME APIs can be involved.
* smeOpen must be called after mac_open.
*
* Return: QDF_STATUS_SUCCESS - SME is successfully initialized.
* Other status means SME is failed to be initialized
*/
QDF_STATUS sme_open(tHalHandle hHal)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pMac->sme.state = SME_STATE_STOP;
pMac->sme.currDeviceMode = QDF_STA_MODE;
if (!QDF_IS_STATUS_SUCCESS(qdf_mutex_create(
&pMac->sme.lkSmeGlobalLock))) {
sme_err("sme_open failed init lock");
return QDF_STATUS_E_FAILURE;
}
status = csr_open(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("csr_open failed, status: %d", status);
return status;
}
status = sme_ps_open(hHal);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("sme_ps_open failed with status: %d", status);
return status;
}
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
status = sme_qos_open(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Qos open, status: %d", status);
return status;
}
#endif
status = init_sme_cmd_list(pMac);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
status = rrm_open(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("rrm_open failed, status: %d", status);
return status;
}
sme_trace_init(pMac);
sme_register_debug_callback();
wlan_serialization_legacy_init_callback();
return status;
}
/*
* sme_init_chan_list, triggers channel setup based on country code.
*/
QDF_STATUS sme_init_chan_list(tHalHandle hal, uint8_t *alpha2,
enum country_src cc_src)
{
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
if ((cc_src == SOURCE_USERSPACE) &&
(pmac->roam.configParam.fSupplicantCountryCodeHasPriority)) {
pmac->roam.configParam.Is11dSupportEnabled = false;
}
return csr_init_chan_list(pmac, alpha2);
}
/*
* sme_set11dinfo() - Set the 11d information about valid channels
* and there power using information from nvRAM
* This function is called only for AP.
*
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* pSmeConfigParams - a pointer to a caller allocated object of
* typedef struct _smeConfigParams.
*
* Return QDF_STATUS_SUCCESS - SME update the config parameters successfully.
*
* Other status means SME is failed to update the config parameters.
*/
QDF_STATUS sme_set11dinfo(tHalHandle hal, tpSmeConfigParams pSmeConfigParams)
{
tpAniSirGlobal mac_ctx = MAC_CONTEXT(hal);
QDF_STATUS status = QDF_STATUS_E_FAILURE;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SET_11DINFO, NO_SESSION, 0));
if (NULL == pSmeConfigParams) {
sme_err("SME config params empty");
return status;
}
status = csr_set_channels(mac_ctx, &pSmeConfigParams->csrConfig);
if (!QDF_IS_STATUS_SUCCESS(status))
sme_err("csr_set_channels failed with status: %d", status);
return status;
}
/**
* sme_set_scan_disable() - Dynamically enable/disable scan
* @h_hal: Handle to HAL
*
* This command gives the user an option to dynamically
* enable or disable scans.
*
* Return: None
*/
void sme_set_scan_disable(tHalHandle h_hal, int value)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(h_hal);
sme_info("scan disable %d", value);
ucfg_scan_set_enable(mac_ctx->psoc, !value);
}
/*
* sme_get_soft_ap_domain() - Get the current regulatory domain of softAp.
* This is a synchronous call
*
* hHal - The handle returned by HostapdAdapter.
* v_REGDOMAIN_t - The current Regulatory Domain requested for SoftAp.
* Return QDF_STATUS_SUCCESS - SME successfully completed the request.
* Other status means, failed to get the current regulatory domain.
*/
QDF_STATUS sme_get_soft_ap_domain(tHalHandle hHal, v_REGDOMAIN_t
*domainIdSoftAp)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_GET_SOFTAP_DOMAIN,
NO_SESSION, 0));
if (NULL == domainIdSoftAp) {
sme_err("Uninitialized domain Id");
return status;
}
*domainIdSoftAp = pMac->scan.domainIdCurrent;
status = QDF_STATUS_SUCCESS;
return status;
}
/**
* sme_update_fine_time_measurement_capab() - Update the FTM capabitlies from
* incoming val
* @hal: Handle for Hal layer
* @val: New FTM capability value
*
* Return: None
*/
void sme_update_fine_time_measurement_capab(tHalHandle hal, uint8_t session_id,
uint32_t val)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
QDF_STATUS status;
ucfg_wifi_pos_set_ftm_cap(mac_ctx->psoc, val);
if (!val) {
mac_ctx->rrm.rrmPEContext.rrmEnabledCaps.fine_time_meas_rpt = 0;
((tpRRMCaps)mac_ctx->rrm.rrmSmeContext.
rrmConfig.rm_capability)->fine_time_meas_rpt = 0;
} else {
mac_ctx->rrm.rrmPEContext.rrmEnabledCaps.fine_time_meas_rpt = 1;
((tpRRMCaps)mac_ctx->rrm.rrmSmeContext.
rrmConfig.rm_capability)->fine_time_meas_rpt = 1;
}
/* Inform this RRM IE change to FW */
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_roam_offload_scan(mac_ctx, session_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_CONNECT_IES_CHANGED);
sme_release_global_lock(&mac_ctx->sme);
} else {
sme_err("Failed to acquire SME lock");
}
}
/*
* sme_update_config() - Change configurations for all SME moduels
* The function updates some configuration for modules in SME, CSR, etc
* during SMEs close open sequence.
* Modules inside SME apply the new configuration at the next transaction.
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* pSmeConfigParams - a pointer to a caller allocated object of
* typedef struct _smeConfigParams.
* Return QDF_STATUS_SUCCESS - SME update the config parameters successfully.
* Other status means SME is failed to update the config parameters.
*/
QDF_STATUS sme_update_config(tHalHandle hHal, tpSmeConfigParams
pSmeConfigParams)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CONFIG, NO_SESSION,
0));
if (NULL == pSmeConfigParams) {
sme_err("SME config params empty");
return status;
}
status = csr_change_default_config_param(pMac, &pSmeConfigParams->
csrConfig);
if (!QDF_IS_STATUS_SUCCESS(status))
sme_err("csr_change_default_config_param failed status: %d",
status);
status = rrm_change_default_config_param(pMac, &pSmeConfigParams->
rrmConfig);
if (!QDF_IS_STATUS_SUCCESS(status))
sme_err("rrm_change_default_config_param failed status: %d",
status);
/* For SOC, CFG is set before start We don't want to apply global CFG
* in connect state because that may cause some side affect
*/
if (csr_is_all_session_disconnected(pMac))
csr_set_global_cfgs(pMac);
/*
* If scan offload is enabled then lim has allow the sending of
* scan request to firmware even in powersave mode. The firmware has
* to take care of exiting from power save mode
*/
status = sme_cfg_set_int(hHal, WNI_CFG_SCAN_IN_POWERSAVE, true);
if (QDF_STATUS_SUCCESS != status)
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Could not pass on WNI_CFG_SCAN_IN_POWERSAVE to CFG");
pMac->snr_monitor_enabled = pSmeConfigParams->snr_monitor_enabled;
return status;
}
/**
* sme_update_scan_roam_params() - Update the scan roaming params
* @mac_ctx: mac ctx
*
* Return: void.
*/
static void sme_update_scan_roam_params(tpAniSirGlobal mac_ctx)
{
struct roam_filter_params scan_params = {0};
struct roam_ext_params *roam_params_src;
uint8_t i;
QDF_STATUS status;
roam_params_src = &mac_ctx->roam.configParam.roam_params;
scan_params.num_bssid_avoid_list =
roam_params_src->num_bssid_avoid_list;
if (scan_params.num_bssid_avoid_list >
MAX_AVOID_LIST_BSSID)
scan_params.num_bssid_avoid_list =
MAX_AVOID_LIST_BSSID;
for (i = 0; i < scan_params.num_bssid_avoid_list; i++) {
qdf_copy_macaddr(&scan_params.bssid_avoid_list[i],
&roam_params_src->bssid_avoid_list[i]);
}
status = ucfg_scan_update_roam_params(mac_ctx->psoc, &scan_params);
if (QDF_IS_STATUS_ERROR(status))
sme_err("ailed to update scan roam params with status=%d",
status);
}
/**
* sme_update_roam_params() - Store/Update the roaming params
* @hal: Handle for Hal layer
* @session_id: SME Session ID
* @roam_params_src: The source buffer to copy
* @update_param: Type of parameter to be updated
*
* Return: Return the status of the updation.
*/
QDF_STATUS sme_update_roam_params(tHalHandle hal,
uint8_t session_id, struct roam_ext_params *roam_params_src,
int update_param)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct roam_ext_params *roam_params_dst;
QDF_STATUS status;
uint8_t i;
roam_params_dst = &mac_ctx->roam.configParam.roam_params;
switch (update_param) {
case REASON_ROAM_EXT_SCAN_PARAMS_CHANGED:
roam_params_dst->raise_rssi_thresh_5g =
roam_params_src->raise_rssi_thresh_5g;
roam_params_dst->drop_rssi_thresh_5g =
roam_params_src->drop_rssi_thresh_5g;
roam_params_dst->raise_factor_5g =
roam_params_src->raise_factor_5g;
roam_params_dst->drop_factor_5g =
roam_params_src->drop_factor_5g;
roam_params_dst->max_raise_rssi_5g =
roam_params_src->max_raise_rssi_5g;
roam_params_dst->max_drop_rssi_5g =
roam_params_src->max_drop_rssi_5g;
roam_params_dst->alert_rssi_threshold =
roam_params_src->alert_rssi_threshold;
roam_params_dst->is_5g_pref_enabled = true;
break;
case REASON_ROAM_SET_SSID_ALLOWED:
qdf_mem_set(&roam_params_dst->ssid_allowed_list, 0,
sizeof(tSirMacSSid) * MAX_SSID_ALLOWED_LIST);
roam_params_dst->num_ssid_allowed_list =
roam_params_src->num_ssid_allowed_list;
for (i = 0; i < roam_params_dst->num_ssid_allowed_list; i++) {
roam_params_dst->ssid_allowed_list[i].length =
roam_params_src->ssid_allowed_list[i].length;
qdf_mem_copy(roam_params_dst->ssid_allowed_list[i].ssId,
roam_params_src->ssid_allowed_list[i].ssId,
roam_params_dst->ssid_allowed_list[i].length);
}
break;
case REASON_ROAM_SET_FAVORED_BSSID:
qdf_mem_set(&roam_params_dst->bssid_favored, 0,
sizeof(tSirMacAddr) * MAX_BSSID_FAVORED);
roam_params_dst->num_bssid_favored =
roam_params_src->num_bssid_favored;
for (i = 0; i < roam_params_dst->num_bssid_favored; i++) {
qdf_mem_copy(&roam_params_dst->bssid_favored[i],
&roam_params_src->bssid_favored[i],
sizeof(tSirMacAddr));
roam_params_dst->bssid_favored_factor[i] =
roam_params_src->bssid_favored_factor[i];
}
break;
case REASON_ROAM_SET_BLACKLIST_BSSID:
qdf_mem_set(&roam_params_dst->bssid_avoid_list, 0,
QDF_MAC_ADDR_SIZE * MAX_BSSID_AVOID_LIST);
roam_params_dst->num_bssid_avoid_list =
roam_params_src->num_bssid_avoid_list;
for (i = 0; i < roam_params_dst->num_bssid_avoid_list; i++) {
qdf_copy_macaddr(&roam_params_dst->bssid_avoid_list[i],
&roam_params_src->bssid_avoid_list[i]);
}
break;
case REASON_ROAM_GOOD_RSSI_CHANGED:
roam_params_dst->good_rssi_roam =
roam_params_src->good_rssi_roam;
break;
default:
break;
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_roam_offload_scan(mac_ctx, session_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
update_param);
sme_release_global_lock(&mac_ctx->sme);
} else {
sme_err("Failed to acquire SME lock");
}
sme_update_scan_roam_params(mac_ctx);
return 0;
}
/**
* sme_process_ready_to_suspend() -
* @mac: Global MAC context
* @pReadyToSuspend: Parameter received along with ready to suspend
* indication from WMA.
*
* On getting ready to suspend indication, this function calls
* callback registered (HDD callbacks) with SME to inform ready
* to suspend indication.
*
* Return: None
*/
static void sme_process_ready_to_suspend(tpAniSirGlobal mac,
tpSirReadyToSuspendInd pReadyToSuspend)
{
if (NULL == mac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
"%s: mac is null", __func__);
return;
}
if (NULL != mac->readyToSuspendCallback) {
mac->readyToSuspendCallback(mac->readyToSuspendContext,
pReadyToSuspend->suspended);
mac->readyToSuspendCallback = NULL;
}
}
#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
/**
* sme_process_ready_to_ext_wow() - inform ready to ExtWoW indication.
* @mac: Global MAC context
* @indication: ready to Ext WoW indication from lower layer
*
* On getting ready to Ext WoW indication, this function calls callback
* registered (HDD callback) with SME to inform ready to ExtWoW indication.
*
* Return: None
*/
static void sme_process_ready_to_ext_wow(tpAniSirGlobal mac,
tpSirReadyToExtWoWInd indication)
{
if (!mac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
"%s: mac is null", __func__);
return;
}
if (NULL != mac->readyToExtWoWCallback) {
mac->readyToExtWoWCallback(mac->readyToExtWoWContext,
indication->status);
mac->readyToExtWoWCallback = NULL;
mac->readyToExtWoWContext = NULL;
}
}
#endif
/*
* sme_hdd_ready_ind() - SME sends eWNI_SME_SYS_READY_IND to PE to inform
* that the NIC is ready tio run.
* The function is called by HDD at the end of initialization stage so PE/HAL
* can enable the NIC to running state.
* This is a synchronous call
*
* @hHal - The handle returned by mac_open.
* Return QDF_STATUS_SUCCESS - eWNI_SME_SYS_READY_IND is sent to PE
* successfully.
* Other status means SME failed to send the message to PE.
*/
QDF_STATUS sme_hdd_ready_ind(tHalHandle hHal)
{
tSirSmeReadyReq *msg;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_HDDREADYIND, NO_SESSION, 0));
do {
msg = qdf_mem_malloc(sizeof(*msg));
if (!msg) {
sme_err("Memory allocation failed! for msg");
return QDF_STATUS_E_NOMEM;
}
msg->messageType = eWNI_SME_SYS_READY_IND;
msg->length = sizeof(*msg);
msg->csr_roam_synch_cb = csr_roam_synch_callback;
msg->sme_msg_cb = sme_process_msg_callback;
msg->stop_roaming_cb = sme_stop_roaming;
status = u_mac_post_ctrl_msg(hHal, (tSirMbMsg *)msg);
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("u_mac_post_ctrl_msg failed to send eWNI_SME_SYS_READY_IND");
break;
}
status = csr_ready(pMac);
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("csr_ready failed with status: %d", status);
break;
}
pMac->sme.state = SME_STATE_READY;
} while (0);
return status;
}
QDF_STATUS sme_get_valid_channels(uint8_t *chan_list, uint32_t *list_len)
{
tpAniSirGlobal mac_ctx = sme_get_mac_context();
if (NULL == mac_ctx) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid MAC context"));
return QDF_STATUS_E_FAILURE;
}
return wlan_cfg_get_str(mac_ctx, WNI_CFG_VALID_CHANNEL_LIST,
chan_list, list_len);
}
#ifdef WLAN_CONV_SPECTRAL_ENABLE
static QDF_STATUS sme_register_spectral_cb(tpAniSirGlobal mac_ctx)
{
struct spectral_legacy_cbacks spectral_cb;
QDF_STATUS status;
spectral_cb.vdev_get_chan_freq = sme_get_oper_chan_freq;
spectral_cb.vdev_get_ch_width = sme_get_oper_ch_width;
spectral_cb.vdev_get_sec20chan_freq_mhz = sme_get_sec20chan_freq_mhz;
status = spectral_register_legacy_cb(mac_ctx->psoc, &spectral_cb);
return status;
}
#else
static QDF_STATUS sme_register_spectral_cb(tpAniSirGlobal mac_ctx)
{
return QDF_STATUS_SUCCESS;
}
#endif
/*
* sme_start() - Put all SME modules at ready state.
* The function starts each module in SME, PMC, CSR, etc. . Upon
* successfully return, all modules are ready to run.
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* Return QDF_STATUS_SUCCESS - SME is ready.
* Other status means SME is failed to start
*/
QDF_STATUS sme_start(tHalHandle hHal)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct policy_mgr_sme_cbacks sme_cbacks;
do {
status = csr_start(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("csr_start failed status: %d", status);
break;
}
sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
sme_cbacks.sme_get_valid_channels = sme_get_valid_channels;
sme_cbacks.sme_nss_update_request = sme_nss_update_request;
sme_cbacks.sme_pdev_set_hw_mode = sme_pdev_set_hw_mode;
sme_cbacks.sme_pdev_set_pcl = sme_pdev_set_pcl;
sme_cbacks.sme_soc_set_dual_mac_config =
sme_soc_set_dual_mac_config;
sme_cbacks.sme_change_mcc_beacon_interval =
sme_change_mcc_beacon_interval;
sme_cbacks.sme_get_ap_channel_from_scan =
sme_get_ap_channel_from_scan;
sme_cbacks.sme_scan_result_purge = sme_scan_result_purge;
status = policy_mgr_register_sme_cb(pMac->psoc, &sme_cbacks);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Failed to register sme cb with Policy Manager: %d",
status);
break;
}
sme_register_spectral_cb(pMac);
pMac->sme.state = SME_STATE_START;
/* START RRM */
status = rrm_start(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Failed to start RRM");
break;
}
} while (0);
return status;
}
static QDF_STATUS dfs_msg_processor(tpAniSirGlobal mac,
struct scheduler_msg *msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_roam_info roam_info = { 0 };
tSirSmeCSAIeTxCompleteRsp *csa_ie_tx_complete_rsp;
uint32_t session_id = 0;
eRoamCmdStatus roam_status;
eCsrRoamResult roam_result;
switch (msg->type) {
case eWNI_SME_DFS_RADAR_FOUND:
{
session_id = msg->bodyval;
roam_status = eCSR_ROAM_DFS_RADAR_IND;
roam_result = eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"sapdfs: Radar indication event occurred");
break;
}
case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND:
{
csa_ie_tx_complete_rsp =
(tSirSmeCSAIeTxCompleteRsp *) msg->bodyptr;
if (!csa_ie_tx_complete_rsp) {
sme_err("eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND null msg");
return QDF_STATUS_E_FAILURE;
}
session_id = csa_ie_tx_complete_rsp->sessionId;
roam_status = eCSR_ROAM_DFS_CHAN_SW_NOTIFY;
roam_result = eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND session=%d",
session_id);
break;
}
case eWNI_SME_DFS_CAC_COMPLETE:
{
session_id = msg->bodyval;
roam_status = eCSR_ROAM_CAC_COMPLETE_IND;
roam_result = eCSR_ROAM_RESULT_CAC_END_IND;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"sapdfs: Received eWNI_SME_DFS_CAC_COMPLETE vdevid%d",
session_id);
break;
}
default:
{
sme_err("Invalid DFS message: 0x%x", msg->type);
status = QDF_STATUS_E_FAILURE;
return status;
}
}
/* Indicate Radar Event to SAP */
csr_roam_call_callback(mac, session_id, &roam_info, 0,
roam_status, roam_result);
return status;
}
#ifdef WLAN_FEATURE_11W
/*
* Handle the unprotected management frame indication from LIM and
* forward it to HDD.
*/
static QDF_STATUS
sme_unprotected_mgmt_frm_ind(tpAniSirGlobal mac,
tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_roam_info roam_info = { 0 };
uint32_t SessionId = pSmeMgmtFrm->sessionId;
roam_info.nFrameLength = pSmeMgmtFrm->frameLen;
roam_info.pbFrames = pSmeMgmtFrm->frameBuf;
roam_info.frameType = pSmeMgmtFrm->frameType;
/* forward the mgmt frame to HDD */
csr_roam_call_callback(mac, SessionId, &roam_info, 0,
eCSR_ROAM_UNPROT_MGMT_FRAME_IND, 0);
return status;
}
#endif
QDF_STATUS sme_update_new_channel_event(tHalHandle hal, uint8_t session_id)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct csr_roam_info *roamInfo;
eRoamCmdStatus roamStatus;
eCsrRoamResult roamResult;
roamInfo = qdf_mem_malloc(sizeof(*roamInfo));
if (!roamInfo) {
sme_err("mem alloc failed for roam info");
return QDF_STATUS_E_FAILURE;
}
roamInfo->dfs_event.sessionId = session_id;
roamStatus = eCSR_ROAM_CHANNEL_COMPLETE_IND;
roamResult = eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"sapdfs: Updated new channel event");
/* Indicate channel Event to SAP */
csr_roam_call_callback(mac, session_id, roamInfo, 0,
roamStatus, roamResult);
qdf_mem_free(roamInfo);
return status;
}
/**
* sme_extended_change_channel_ind()- function to indicate ECSA
* action frame is received in lim to SAP
* @mac_ctx: pointer to global mac structure
* @msg_buf: contain new channel and session id.
*
* This function is called to post ECSA action frame
* receive event to SAP.
*
* Return: success if msg indicated to SAP else return failure
*/
static QDF_STATUS sme_extended_change_channel_ind(tpAniSirGlobal mac_ctx,
void *msg_buf)
{
struct sir_sme_ext_cng_chan_ind *ext_chan_ind;
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint32_t session_id = 0;
struct csr_roam_info roamInfo = {0};
eRoamCmdStatus roam_status;
eCsrRoamResult roam_result;
ext_chan_ind = msg_buf;
if (NULL == ext_chan_ind) {
sme_err("ext_chan_ind is NULL");
return QDF_STATUS_E_FAILURE;
}
session_id = ext_chan_ind->session_id;
roamInfo.target_channel = ext_chan_ind->new_channel;
roam_status = eCSR_ROAM_EXT_CHG_CHNL_IND;
roam_result = eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND;
sme_debug("sapdfs: Received eWNI_SME_EXT_CHANGE_CHANNEL_IND for session id [%d]",
session_id);
/* Indicate Ext Channel Change event to SAP */
csr_roam_call_callback(mac_ctx, session_id, &roamInfo, 0,
roam_status, roam_result);
return status;
}
#ifdef FEATURE_WLAN_ESE
/**
* sme_update_is_ese_feature_enabled() - enable/disable ESE support at runtime
* @hHal: HAL handle
* @sessionId: session id
* @isEseIniFeatureEnabled: ese ini enabled
*
* It is used at in the REG_DYNAMIC_VARIABLE macro definition of
* isEseIniFeatureEnabled. This is a synchronous call
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_update_is_ese_feature_enabled(tHalHandle hHal,
uint8_t sessionId, const bool isEseIniFeatureEnabled)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status;
if (pMac->roam.configParam.isEseIniFeatureEnabled ==
isEseIniFeatureEnabled) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: ESE Mode is already enabled or disabled, nothing to do (returning) old(%d) new(%d)",
__func__,
pMac->roam.configParam.isEseIniFeatureEnabled,
isEseIniFeatureEnabled);
return QDF_STATUS_SUCCESS;
}
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: EseEnabled is changed from %d to %d", __func__,
pMac->roam.configParam.isEseIniFeatureEnabled,
isEseIniFeatureEnabled);
pMac->roam.configParam.isEseIniFeatureEnabled = isEseIniFeatureEnabled;
csr_neighbor_roam_update_fast_roaming_enabled(
pMac, sessionId, isEseIniFeatureEnabled);
if (true == isEseIniFeatureEnabled)
sme_update_fast_transition_enabled(hHal, true);
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_ESE_INI_CFG_CHANGED);
sme_release_global_lock(&pMac->sme);
} else {
sme_err("Failed to acquire SME lock");
return status;
}
}
return QDF_STATUS_SUCCESS;
}
/**
* sme_set_plm_request() - set plm request
* @hHal: HAL handle
* @pPlmReq: Pointer to input plm request
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_set_plm_request(tHalHandle hHal, tpSirPlmReq pPlmReq)
{
QDF_STATUS status;
bool ret = false;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
uint8_t ch_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 };
uint8_t count, valid_count = 0;
struct scheduler_msg msg = {0};
struct csr_roam_session *pSession = CSR_GET_SESSION(pMac,
pPlmReq->sessionId);
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
if (!pSession) {
sme_err("session %d not found", pPlmReq->sessionId);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
if (!pSession->sessionActive) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid Sessionid"));
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
if (!pPlmReq->enable)
goto send_plm_start;
/* validating channel numbers */
for (count = 0; count < pPlmReq->plmNumCh; count++) {
ret = csr_is_supported_channel(pMac, pPlmReq->plmChList[count]);
if (ret && pPlmReq->plmChList[count] > 14) {
if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
pMac->pdev,
pPlmReq->plmChList[count])) {
/* DFS channel is provided, no PLM bursts can be
* transmitted. Ignoring these channels.
*/
QDF_TRACE(QDF_MODULE_ID_SME,
QDF_TRACE_LEVEL_DEBUG,
FL("DFS channel %d ignored for PLM"),
pPlmReq->plmChList[count]);
continue;
}
} else if (!ret) {
/* Not supported, ignore the channel */
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
FL("Unsupported channel %d ignored for PLM"),
pPlmReq->plmChList[count]);
continue;
}
ch_list[valid_count] = pPlmReq->plmChList[count];
valid_count++;
} /* End of for () */
/* Copying back the valid channel list to plm struct */
qdf_mem_set((void *)pPlmReq->plmChList,
pPlmReq->plmNumCh, 0);
if (valid_count)
qdf_mem_copy(pPlmReq->plmChList, ch_list,
valid_count);
/* All are invalid channels, FW need to send the PLM
* report with "incapable" bit set.
*/
pPlmReq->plmNumCh = valid_count;
send_plm_start:
/* PLM START */
msg.type = WMA_SET_PLM_REQ;
msg.reserved = 0;
msg.bodyptr = pPlmReq;
if (!QDF_IS_STATUS_SUCCESS(scheduler_post_msg(QDF_MODULE_ID_WMA,
&msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post WMA_SET_PLM_REQ to WMA"));
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_tsm_ie_ind() - sme tsm ie indication
* @mac: Global mac context
* @pSmeTsmIeInd: Pointer to tsm ie indication
*
* Handle the tsm ie indication from LIM and forward it to HDD.
*
* Return: QDF_STATUS enumeration
*/
static QDF_STATUS sme_tsm_ie_ind(tpAniSirGlobal mac,
tSirSmeTsmIEInd *pSmeTsmIeInd)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_roam_info roam_info = { 0 };
uint32_t SessionId = pSmeTsmIeInd->sessionId;
roam_info.tsmIe.tsid = pSmeTsmIeInd->tsmIe.tsid;
roam_info.tsmIe.state = pSmeTsmIeInd->tsmIe.state;
roam_info.tsmIe.msmt_interval = pSmeTsmIeInd->tsmIe.msmt_interval;
/* forward the tsm ie information to HDD */
csr_roam_call_callback(mac, SessionId, &roam_info, 0,
eCSR_ROAM_TSM_IE_IND, 0);
return status;
}
/**
* sme_set_cckm_ie() - set cckm ie
* @hHal: HAL handle
* @sessionId: session id
* @pCckmIe: Pointer to CCKM Ie
* @cckmIeLen: Length of @pCckmIe
*
* Function to store the CCKM IE passed from supplicant and use
* it while packing reassociation request.
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_set_cckm_ie(tHalHandle hHal, uint8_t sessionId,
uint8_t *pCckmIe, uint8_t cckmIeLen)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_set_cckm_ie(pMac, sessionId, pCckmIe, cckmIeLen);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_set_ese_beacon_request() - set ese beacon request
* @hHal: HAL handle
* @sessionId: session id
* @pEseBcnReq: Ese beacon report
*
* function to set ESE beacon request parameters
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_set_ese_beacon_request(tHalHandle hHal, const uint8_t sessionId,
const tCsrEseBeaconReq *pEseBcnReq)
{
QDF_STATUS status;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tpSirBeaconReportReqInd pSmeBcnReportReq = NULL;
tCsrEseBeaconReqParams *pBeaconReq = NULL;
uint8_t counter = 0;
struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, sessionId);
tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
if (pSmeRrmContext->eseBcnReqInProgress == true) {
sme_err("A Beacon Report Req is already in progress");
return QDF_STATUS_E_RESOURCES;
}
/* Store the info in RRM context */
qdf_mem_copy(&pSmeRrmContext->eseBcnReqInfo, pEseBcnReq,
sizeof(tCsrEseBeaconReq));
/* Prepare the request to send to SME. */
pSmeBcnReportReq = qdf_mem_malloc(sizeof(tSirBeaconReportReqInd));
if (NULL == pSmeBcnReportReq) {
sme_err("Memory Allocation Failure!!! ESE BcnReq Ind to SME");
return QDF_STATUS_E_NOMEM;
}
pSmeRrmContext->eseBcnReqInProgress = true;
sme_debug("Sending Beacon Report Req to SME");
pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND;
pSmeBcnReportReq->length = sizeof(tSirBeaconReportReqInd);
qdf_mem_copy(pSmeBcnReportReq->bssId,
pSession->connectedProfile.bssid.bytes,
sizeof(tSirMacAddr));
pSmeBcnReportReq->channelInfo.channelNum = 255;
pSmeBcnReportReq->channelList.numChannels = pEseBcnReq->numBcnReqIe;
pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_ESE_UPLOAD;
for (counter = 0; counter < pEseBcnReq->numBcnReqIe; counter++) {
pBeaconReq =
(tCsrEseBeaconReqParams *) &pEseBcnReq->bcnReq[counter];
pSmeBcnReportReq->fMeasurementtype[counter] =
pBeaconReq->scanMode;
pSmeBcnReportReq->measurementDuration[counter] =
SYS_TU_TO_MS(pBeaconReq->measurementDuration);
pSmeBcnReportReq->channelList.channelNumber[counter] =
pBeaconReq->channel;
}
status = sme_rrm_process_beacon_report_req_ind(pMac, pSmeBcnReportReq);
if (status != QDF_STATUS_SUCCESS)
pSmeRrmContext->eseBcnReqInProgress = false;
qdf_mem_free(pSmeBcnReportReq);
return status;
}
/**
* sme_get_tsm_stats() - SME get tsm stats
* @hHal: HAL handle
* @callback: SME sends back the requested stats using the callback
* @staId: The station ID for which the stats is requested for
* @bssId: bssid
* @pContext: user context to be passed back along with the callback
* @tid: Traffic id
*
* API register a callback to get TSM Stats.
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_get_tsm_stats(tHalHandle hHal,
tCsrTsmStatsCallback callback,
uint8_t staId, struct qdf_mac_addr bssId,
void *pContext, uint8_t tid)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_get_tsm_stats(pMac, callback,
staId, bssId, pContext,
tid);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_set_ese_roam_scan_channel_list() - To set ese roam scan channel list
* @hHal: pointer HAL handle returned by mac_open
* @sessionId: sme session id
* @pChannelList: Output channel list
* @numChannels: Output number of channels
*
* This routine is called to set ese roam scan channel list.
* This is a synchronous call
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_set_ese_roam_scan_channel_list(tHalHandle hHal,
uint8_t sessionId,
uint8_t *pChannelList,
uint8_t numChannels)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL;
tpCsrChannelInfo curchnl_list_info = NULL;
uint8_t oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN * 2] = { 0 };
uint8_t newChannelList[128] = { 0 };
uint8_t i = 0, j = 0;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId];
curchnl_list_info =
&pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo;
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Failed to acquire SME lock");
return status;
}
if (NULL != curchnl_list_info->ChannelList) {
for (i = 0; i < curchnl_list_info->numOfChannels; i++) {
j += snprintf(oldChannelList + j,
sizeof(oldChannelList) - j, "%d",
curchnl_list_info->ChannelList[i]);
}
}
status = csr_create_roam_scan_channel_list(pMac, sessionId,
pChannelList, numChannels,
csr_get_current_band(hHal));
if (QDF_IS_STATUS_SUCCESS(status)) {
if (NULL != curchnl_list_info->ChannelList) {
j = 0;
for (i = 0; i < curchnl_list_info->numOfChannels; i++) {
j += snprintf(newChannelList + j,
sizeof(newChannelList) - j, "%d",
curchnl_list_info->ChannelList[i]);
}
}
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"ESE roam scan chnl list successfully set to %s-old value is %s-roam state is %d",
newChannelList, oldChannelList,
pNeighborRoamInfo->neighborRoamState);
}
if (pMac->roam.configParam.isRoamOffloadScanEnabled)
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_CHANNEL_LIST_CHANGED);
sme_release_global_lock(&pMac->sme);
return status;
}
#endif /* FEATURE_WLAN_ESE */
static
QDF_STATUS sme_ibss_peer_info_response_handler(tpAniSirGlobal pMac,
tpSirIbssGetPeerInfoRspParams
pIbssPeerInfoParams)
{
if (NULL == pMac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
"%s: pMac is null", __func__);
return QDF_STATUS_E_FAILURE;
}
if (pMac->sme.peerInfoParams.peerInfoCbk == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: HDD callback is null", __func__);
return QDF_STATUS_E_FAILURE;
}
pMac->sme.peerInfoParams.peerInfoCbk(pMac->sme.peerInfoParams.pUserData,
&pIbssPeerInfoParams->
ibssPeerInfoRspParams);
return QDF_STATUS_SUCCESS;
}
/**
* sme_process_dual_mac_config_resp() - Process set Dual mac config response
* @mac: Global MAC pointer
* @msg: Dual mac config response
*
* Processes the dual mac configuration response and invokes the HDD callback
* to process further
*/
static QDF_STATUS sme_process_dual_mac_config_resp(tpAniSirGlobal mac,
uint8_t *msg)
{
tListElem *entry = NULL;
tSmeCmd *command = NULL;
bool found;
dual_mac_cb callback = NULL;
struct sir_dual_mac_config_resp *param;
param = (struct sir_dual_mac_config_resp *)msg;
if (!param) {
sme_err("Dual mac config resp param is NULL");
/* Not returning. Need to check if active command list
* needs to be freed
*/
}
entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK);
if (!entry) {
sme_err("No cmd found in active list");
return QDF_STATUS_E_FAILURE;
}
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
if (!command) {
sme_err("Base address is NULL");
return QDF_STATUS_E_FAILURE;
}
if (e_sme_command_set_dual_mac_config != command->command) {
sme_err("Command mismatch!");
return QDF_STATUS_E_FAILURE;
}
callback = command->u.set_dual_mac_cmd.set_dual_mac_cb;
if (callback) {
if (!param) {
sme_err("Callback failed-Dual mac config is NULL");
} else {
sme_debug("Calling HDD callback for Dual mac config");
callback(param->status,
command->u.set_dual_mac_cmd.scan_config,
command->u.set_dual_mac_cmd.fw_mode_config);
}
} else {
sme_err("Callback does not exist");
}
found = csr_nonscan_active_ll_remove_entry(mac, entry, LL_ACCESS_LOCK);
if (found)
/* Now put this command back on the available command list */
csr_release_command(mac, command);
return QDF_STATUS_SUCCESS;
}
/**
* sme_process_antenna_mode_resp() - Process set antenna mode
* response
* @mac: Global MAC pointer
* @msg: antenna mode response
*
* Processes the antenna mode response and invokes the HDD
* callback to process further
*/
static QDF_STATUS sme_process_antenna_mode_resp(tpAniSirGlobal mac,
uint8_t *msg)
{
tListElem *entry;
tSmeCmd *command;
bool found;
void *context = NULL;
antenna_mode_cb callback;
struct sir_antenna_mode_resp *param;
param = (struct sir_antenna_mode_resp *)msg;
if (!param)
sme_err("set antenna mode resp is NULL");
/* Not returning. Need to check if active command list
* needs to be freed
*/
entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK);
if (!entry) {
sme_err("No cmd found in active list");
return QDF_STATUS_E_FAILURE;
}
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
if (!command) {
sme_err("Base address is NULL");
return QDF_STATUS_E_FAILURE;
}
if (e_sme_command_set_antenna_mode != command->command) {
sme_err("Command mismatch!");
return QDF_STATUS_E_FAILURE;
}
context = command->u.set_antenna_mode_cmd.set_antenna_mode_ctx;
callback = command->u.set_antenna_mode_cmd.set_antenna_mode_resp;
if (callback) {
if (!param)
sme_err("Set antenna mode call back is NULL");
else
callback(param->status, context);
} else {
sme_err("Callback does not exist");
}
found = csr_nonscan_active_ll_remove_entry(mac, entry, LL_ACCESS_LOCK);
if (found)
/* Now put this command back on the available command list */
csr_release_command(mac, command);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS sme_process_msg(tpAniSirGlobal pMac, struct scheduler_msg *pMsg)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
struct sir_peer_info *peer_stats;
struct sir_peer_info_resp *peer_info_rsp;
if (pMsg == NULL) {
sme_err("Empty message for SME");
return status;
}
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_warn("Locking failed, bailing out");
if (pMsg->bodyptr)
qdf_mem_free(pMsg->bodyptr);
return status;
}
if (!SME_IS_START(pMac)) {
sme_debug("message type %d in stop state ignored", pMsg->type);
if (pMsg->bodyptr)
qdf_mem_free(pMsg->bodyptr);
goto release_lock;
}
switch (pMsg->type) {
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
case eWNI_SME_HO_FAIL_IND:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("LFR3: Rcvd eWNI_SME_HO_FAIL_IND"));
csr_process_ho_fail_ind(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
break;
#endif
case WNI_CFG_SET_CNF:
case WNI_CFG_DNLD_CNF:
case WNI_CFG_GET_RSP:
case WNI_CFG_ADD_GRP_ADDR_CNF:
case WNI_CFG_DEL_GRP_ADDR_CNF:
break;
case eWNI_SME_ADDTS_RSP:
case eWNI_SME_DELTS_RSP:
case eWNI_SME_DELTS_IND:
case eWNI_SME_FT_AGGR_QOS_RSP:
/* QoS */
if (pMsg->bodyptr) {
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
status = sme_qos_msg_processor(pMac, pMsg->type,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
#endif
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_NEIGHBOR_REPORT_IND:
case eWNI_SME_BEACON_REPORT_REQ_IND:
if (pMsg->bodyptr) {
status = sme_rrm_msg_processor(pMac, pMsg->type,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_ADD_STA_SELF_RSP:
if (pMsg->bodyptr) {
status = csr_process_add_sta_session_rsp(pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_DEL_STA_SELF_RSP:
if (pMsg->bodyptr) {
status = csr_process_del_sta_session_rsp(pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE:
if (pMsg->bodyptr) {
status = sme_handle_generic_change_country_code(
(void *)pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
#ifdef WLAN_FEATURE_11W
case eWNI_SME_UNPROT_MGMT_FRM_IND:
if (pMsg->bodyptr) {
sme_unprotected_mgmt_frm_ind(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
#endif
#ifdef FEATURE_WLAN_ESE
case eWNI_SME_TSM_IE_IND:
if (pMsg->bodyptr) {
sme_tsm_ie_ind(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
#endif /* FEATURE_WLAN_ESE */
case eWNI_SME_ROAM_SCAN_OFFLOAD_RSP:
status = csr_roam_offload_scan_rsp_hdlr((void *)pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_IBSS_PEER_INFO_RSP:
if (pMsg->bodyptr) {
sme_ibss_peer_info_response_handler(pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_READY_TO_SUSPEND_IND:
if (pMsg->bodyptr) {
sme_process_ready_to_suspend(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
case eWNI_SME_READY_TO_EXTWOW_IND:
if (pMsg->bodyptr) {
sme_process_ready_to_ext_wow(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
#endif
#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
case eWNI_SME_AUTO_SHUTDOWN_IND:
if (pMac->sme.pAutoShutdownNotificationCb) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
FL("Auto shutdown notification"));
pMac->sme.pAutoShutdownNotificationCb();
}
qdf_mem_free(pMsg->bodyptr);
break;
#endif
case eWNI_SME_DFS_RADAR_FOUND:
case eWNI_SME_DFS_CAC_COMPLETE:
case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND:
status = dfs_msg_processor(pMac, pMsg);
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_CHANNEL_CHANGE_RSP:
if (pMsg->bodyptr) {
status = sme_process_channel_change_resp(pMac,
pMsg->type,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_STATS_EXT_EVENT:
status = sme_stats_ext_event(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_GET_PEER_INFO_IND:
if (pMac->sme.pget_peer_info_ind_cb)
pMac->sme.pget_peer_info_ind_cb(pMsg->bodyptr,
pMac->sme.pget_peer_info_cb_context);
if (pMsg->bodyptr) {
peer_info_rsp = (struct sir_peer_info_resp *)
(pMsg->bodyptr);
peer_stats = (struct sir_peer_info *)
(peer_info_rsp->info);
if (peer_stats) {
pMac->peer_rssi = peer_stats[0].rssi;
pMac->peer_txrate = peer_stats[0].tx_rate;
pMac->peer_rxrate = peer_stats[0].rx_rate;
}
}
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_GET_PEER_INFO_EXT_IND:
if (pMac->sme.pget_peer_info_ext_ind_cb)
pMac->sme.pget_peer_info_ext_ind_cb(pMsg->bodyptr,
pMac->sme.pget_peer_info_ext_cb_context);
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_CSA_OFFLOAD_EVENT:
if (pMsg->bodyptr) {
csr_scan_flush_bss_entry(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
}
break;
case eWNI_SME_TSF_EVENT:
if (pMac->sme.get_tsf_cb) {
pMac->sme.get_tsf_cb(pMac->sme.get_tsf_cxt,
(struct stsf *)pMsg->bodyptr);
}
if (pMsg->bodyptr)
qdf_mem_free(pMsg->bodyptr);
break;
#ifdef WLAN_FEATURE_NAN
case eWNI_SME_NAN_EVENT:
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_WMA_MSG,
NO_SESSION, pMsg->type));
if (pMsg->bodyptr) {
sme_nan_event(MAC_HANDLE(pMac), pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
}
break;
#endif /* WLAN_FEATURE_NAN */
case eWNI_SME_LINK_STATUS_IND:
{
tAniGetLinkStatus *pLinkStatus =
(tAniGetLinkStatus *) pMsg->bodyptr;
if (pLinkStatus) {
if (pMac->sme.link_status_callback)
pMac->sme.link_status_callback(
pLinkStatus->linkStatus,
pMac->sme.link_status_context);
pMac->sme.link_status_callback = NULL;
pMac->sme.link_status_context = NULL;
qdf_mem_free(pLinkStatus);
}
break;
}
case eWNI_SME_MSG_GET_TEMPERATURE_IND:
if (pMac->sme.pGetTemperatureCb)
pMac->sme.pGetTemperatureCb(pMsg->bodyval,
pMac->sme.pTemperatureCbContext);
break;
case eWNI_SME_SNR_IND:
{
tAniGetSnrReq *pSnrReq = (tAniGetSnrReq *) pMsg->bodyptr;
if (pSnrReq) {
if (pSnrReq->snrCallback) {
((tCsrSnrCallback)
(pSnrReq->snrCallback))
(pSnrReq->snr, pSnrReq->staId,
pSnrReq->pDevContext);
}
qdf_mem_free(pSnrReq);
}
break;
}
#ifdef FEATURE_WLAN_EXTSCAN
case eWNI_SME_EXTSCAN_FULL_SCAN_RESULT_IND:
if (pMac->sme.ext_scan_ind_cb)
pMac->sme.ext_scan_ind_cb(pMac->hdd_handle,
eSIR_EXTSCAN_FULL_SCAN_RESULT_IND,
pMsg->bodyptr);
else
sme_err("callback not registered to process: %d",
pMsg->type);
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_EPNO_NETWORK_FOUND_IND:
if (pMac->sme.ext_scan_ind_cb)
pMac->sme.ext_scan_ind_cb(pMac->hdd_handle,
eSIR_EPNO_NETWORK_FOUND_IND,
pMsg->bodyptr);
else
sme_err("callback not registered to process: %d",
pMsg->type);
qdf_mem_free(pMsg->bodyptr);
break;
#endif
case eWNI_SME_SET_HW_MODE_RESP:
if (pMsg->bodyptr) {
status = sme_process_set_hw_mode_resp(pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_HW_MODE_TRANS_IND:
if (pMsg->bodyptr) {
status = sme_process_hw_mode_trans_ind(pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_NSS_UPDATE_RSP:
if (pMsg->bodyptr) {
status = sme_process_nss_update_resp(pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
#ifdef WLAN_FEATURE_DSRC
case eWNI_SME_OCB_SET_CONFIG_RSP:
if (pMac->sme.ocb_set_config_callback)
pMac->sme.ocb_set_config_callback(
pMac->sme.ocb_set_config_context,
pMsg->bodyptr);
else
sme_err("No callback for Msg type: %d", pMsg->type);
pMac->sme.ocb_set_config_callback = NULL;
pMac->sme.ocb_set_config_context = NULL;
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_OCB_GET_TSF_TIMER_RSP:
if (pMac->sme.ocb_get_tsf_timer_callback)
pMac->sme.ocb_get_tsf_timer_callback(
pMac->sme.ocb_get_tsf_timer_context,
pMsg->bodyptr);
else
sme_err("No callback for Msg type: %d", pMsg->type);
pMac->sme.ocb_get_tsf_timer_callback = NULL;
pMac->sme.ocb_get_tsf_timer_context = NULL;
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_DCC_GET_STATS_RSP:
if (pMac->sme.dcc_get_stats_callback)
pMac->sme.dcc_get_stats_callback(
pMac->sme.dcc_get_stats_context,
pMsg->bodyptr);
else
sme_err("No callback for Msg type: %d", pMsg->type);
pMac->sme.dcc_get_stats_callback = NULL;
pMac->sme.dcc_get_stats_context = NULL;
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_DCC_UPDATE_NDL_RSP:
if (pMac->sme.dcc_update_ndl_callback)
pMac->sme.dcc_update_ndl_callback(
pMac->sme.dcc_update_ndl_context,
pMsg->bodyptr);
else
sme_err("No callback for Msg type: %d", pMsg->type);
pMac->sme.dcc_update_ndl_callback = NULL;
pMac->sme.dcc_update_ndl_context = NULL;
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_DCC_STATS_EVENT:
if (pMac->sme.dcc_stats_event_callback)
pMac->sme.dcc_stats_event_callback(
pMac->sme.dcc_stats_event_context,
pMsg->bodyptr);
else
sme_err("No callback for Msg type: %d", pMsg->type);
qdf_mem_free(pMsg->bodyptr);
break;
#endif
case eWNI_SME_SET_DUAL_MAC_CFG_RESP:
if (pMsg->bodyptr) {
status = sme_process_dual_mac_config_resp(pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_SET_THERMAL_LEVEL_IND:
if (pMac->sme.set_thermal_level_cb)
pMac->sme.set_thermal_level_cb(pMac->hdd_handle,
pMsg->bodyval);
break;
case eWNI_SME_EXT_CHANGE_CHANNEL_IND:
status = sme_extended_change_channel_ind(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_SET_ANTENNA_MODE_RESP:
if (pMsg->bodyptr) {
status = sme_process_antenna_mode_resp(pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sme_err("Empty message for: %d", pMsg->type);
}
break;
case eWNI_SME_LOST_LINK_INFO_IND:
if (pMac->sme.lost_link_info_cb)
pMac->sme.lost_link_info_cb(pMac->hdd_handle,
(struct sir_lost_link_info *)pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_RSO_CMD_STATUS_IND:
if (pMac->sme.rso_cmd_status_cb)
pMac->sme.rso_cmd_status_cb(pMac->hdd_handle,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
break;
case eWMI_SME_LL_STATS_IND:
if (pMac->sme.link_layer_stats_ext_cb)
pMac->sme.link_layer_stats_ext_cb(pMac->hdd_handle,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_BT_ACTIVITY_INFO_IND:
if (pMac->sme.bt_activity_info_cb)
pMac->sme.bt_activity_info_cb(pMac->hdd_handle,
pMsg->bodyval);
break;
default:
if ((pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN)
&& (pMsg->type <= eWNI_SME_MSG_TYPES_END)) {
/* CSR */
if (pMsg->bodyptr) {
status = csr_msg_processor(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else
sme_err("Empty message for: %d", pMsg->type);
} else {
sme_warn("Unknown message type: %d", pMsg->type);
if (pMsg->bodyptr)
qdf_mem_free(pMsg->bodyptr);
}
} /* switch */
release_lock:
sme_release_global_lock(&pMac->sme);
return status;
}
QDF_STATUS sme_mc_process_handler(struct scheduler_msg *msg)
{
tpAniSirGlobal mac_ctx = cds_get_context(QDF_MODULE_ID_SME);
if (mac_ctx == NULL) {
QDF_ASSERT(0);
return QDF_STATUS_E_FAILURE;
}
return sme_process_msg(mac_ctx, msg);
}
/**
* sme_process_nss_update_resp() - Process nss update response
* @mac: Global MAC pointer
* @msg: nss update response
*
* Processes the nss update response and invokes the HDD
* callback to process further
*/
static QDF_STATUS sme_process_nss_update_resp(tpAniSirGlobal mac, uint8_t *msg)
{
tListElem *entry = NULL;
tSmeCmd *command = NULL;
bool found;
policy_mgr_nss_update_cback callback = NULL;
struct sir_beacon_tx_complete_rsp *param;
param = (struct sir_beacon_tx_complete_rsp *)msg;
if (!param)
sme_err("nss update resp param is NULL");
/* Not returning. Need to check if active command list
* needs to be freed
*/
entry = csr_nonscan_active_ll_peek_head(mac, LL_ACCESS_LOCK);
if (!entry) {
sme_err("No cmd found in active list");
return QDF_STATUS_E_FAILURE;
}
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
if (!command) {
sme_err("Base address is NULL");
return QDF_STATUS_E_FAILURE;
}
if (e_sme_command_nss_update != command->command) {
sme_err("Command mismatch!");
return QDF_STATUS_E_FAILURE;
}
callback = command->u.nss_update_cmd.nss_update_cb;
if (callback) {
if (!param)
sme_err("Callback failed since nss update params is NULL");
else
callback(command->u.nss_update_cmd.context,
param->tx_status,
param->session_id,
command->u.nss_update_cmd.next_action,
command->u.nss_update_cmd.reason);
} else {
sme_err("Callback does not exisit");
}
found = csr_nonscan_active_ll_remove_entry(mac, entry, LL_ACCESS_LOCK);
if (found) {
/* Now put this command back on the avilable command list */
csr_release_command(mac, command);
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS sme_stop(mac_handle_t mac_handle)
{
QDF_STATUS status;
QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
status = rrm_stop(mac);
if (QDF_IS_STATUS_ERROR(status)) {
ret_status = status;
sme_err("rrm_stop failed with status: %d", status);
}
status = csr_stop(mac);
if (QDF_IS_STATUS_ERROR(status)) {
ret_status = status;
sme_err("csr_stop failed with status: %d", status);
}
mac->sme.state = SME_STATE_STOP;
return ret_status;
}
/*
* sme_close() - Release all SME modules and their resources.
* The function release each module in SME, PMC, CSR, etc. . Upon
* return, all modules are at closed state.
*
* No SME APIs can be involved after smeClose except smeOpen.
* smeClose must be called before mac_close.
* This is a synchronous call
*
* hHal - The handle returned by mac_open
* Return QDF_STATUS_SUCCESS - SME is successfully close.
*
* Other status means SME is failed to be closed but caller still cannot
* call any other SME functions except smeOpen.
*/
QDF_STATUS sme_close(tHalHandle hHal)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
QDF_STATUS fail_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (!pMac)
return QDF_STATUS_E_FAILURE;
/* Note: pSession will be invalid from here on, do not access */
status = csr_close(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("csr_close failed with status: %d", status);
fail_status = status;
}
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
status = sme_qos_close(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Qos close failed with status: %d", status);
fail_status = status;
}
#endif
status = sme_ps_close(hHal);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("sme_ps_close failed status: %d", status);
fail_status = status;
}
status = rrm_close(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("RRM close failed with status: %d", status);
fail_status = status;
}
free_sme_cmd_list(pMac);
if (!QDF_IS_STATUS_SUCCESS
(qdf_mutex_destroy(&pMac->sme.lkSmeGlobalLock)))
fail_status = QDF_STATUS_E_FAILURE;
if (!QDF_IS_STATUS_SUCCESS(fail_status))
status = fail_status;
pMac->sme.state = SME_STATE_STOP;
return status;
}
/**
* sme_remove_bssid_from_scan_list() - wrapper to remove the bssid from
* scan list
* @hal: hal context.
* @bssid: bssid to be removed
*
* This function remove the given bssid from scan list.
*
* Return: QDF status.
*/
QDF_STATUS sme_remove_bssid_from_scan_list(tHalHandle hal,
tSirMacAddr bssid)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_remove_bssid_from_scan_list(mac_ctx, bssid);
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
/*
* sme_scan_get_result
* A wrapper function to request scan results from CSR.
* This is a synchronous call
*
* pFilter - If pFilter is NULL, all cached results are returned
* phResult - an object for the result.
* Return QDF_STATUS
*/
QDF_STATUS sme_scan_get_result(tHalHandle hHal, uint8_t sessionId,
tCsrScanResultFilter *pFilter,
tScanResultHandle *phResult)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SCAN_GET_RESULTS, sessionId,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_scan_get_result(pMac, pFilter, phResult);
sme_release_global_lock(&pMac->sme);
}
return status;
}
QDF_STATUS sme_scan_get_result_for_bssid(tHalHandle hal_handle,
struct qdf_mac_addr *bssid,
tCsrScanResultInfo *res)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
QDF_STATUS status;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_scan_get_result_for_bssid(mac_ctx, bssid, res);
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
/**
* sme_get_ap_channel_from_scan() - a wrapper function to get
* AP's channel id from
* CSR by filtering the
* result which matches
* our roam profile.
* @profile: SAP profile
* @ap_chnl_id: pointer to channel id of SAP. Fill the value after finding the
* best ap from scan cache.
*
* This function is written to get AP's channel id from CSR by filtering
* the result which matches our roam profile. This is a synchronous call.
*
* Return: QDF_STATUS.
*/
QDF_STATUS sme_get_ap_channel_from_scan(void *profile,
tScanResultHandle *scan_cache,
uint8_t *ap_chnl_id)
{
return sme_get_ap_channel_from_scan_cache((struct csr_roam_profile *)
profile,
scan_cache,
ap_chnl_id);
}
/**
* sme_get_ap_channel_from_scan_cache() - a wrapper function to get AP's
* channel id from CSR by filtering the
* result which matches our roam profile.
* @profile: SAP adapter
* @ap_chnl_id: pointer to channel id of SAP. Fill the value after finding the
* best ap from scan cache.
*
* This function is written to get AP's channel id from CSR by filtering
* the result which matches our roam profile. This is a synchronous call.
*
* Return: QDF_STATUS.
*/
QDF_STATUS sme_get_ap_channel_from_scan_cache(
struct csr_roam_profile *profile, tScanResultHandle *scan_cache,
uint8_t *ap_chnl_id)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = sme_get_mac_context();
tCsrScanResultFilter *scan_filter = NULL;
tScanResultHandle filtered_scan_result = NULL;
tSirBssDescription first_ap_profile;
if (NULL == mac_ctx) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("mac_ctx is NULL"));
return QDF_STATUS_E_FAILURE;
}
scan_filter = qdf_mem_malloc(sizeof(tCsrScanResultFilter));
if (NULL == scan_filter) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("scan_filter mem alloc failed"));
return QDF_STATUS_E_FAILURE;
}
qdf_mem_set(&first_ap_profile, sizeof(tSirBssDescription), 0);
if (NULL == profile) {
scan_filter->EncryptionType.numEntries = 1;
scan_filter->EncryptionType.encryptionType[0]
= eCSR_ENCRYPT_TYPE_NONE;
} else {
/* Here is the profile we need to connect to */
status = csr_roam_prepare_filter_from_profile(mac_ctx,
profile,
scan_filter);
}
if (QDF_STATUS_SUCCESS == status) {
/* Save the WPS info */
if (NULL != profile) {
scan_filter->bWPSAssociation =
profile->bWPSAssociation;
scan_filter->bOSENAssociation =
profile->bOSENAssociation;
} else {
scan_filter->bWPSAssociation = 0;
scan_filter->bOSENAssociation = 0;
}
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Preparing the profile filter failed"));
qdf_mem_free(scan_filter);
return QDF_STATUS_E_FAILURE;
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
status = csr_scan_get_result(mac_ctx, scan_filter,
&filtered_scan_result);
if (QDF_STATUS_SUCCESS == status) {
csr_get_bssdescr_from_scan_handle(filtered_scan_result,
&first_ap_profile);
*scan_cache = filtered_scan_result;
if (0 != first_ap_profile.channelId) {
*ap_chnl_id = first_ap_profile.channelId;
QDF_TRACE(QDF_MODULE_ID_SME,
QDF_TRACE_LEVEL_DEBUG,
FL("Found best AP & its on chnl[%d]"),
first_ap_profile.channelId);
} else {
/*
* This means scan result is empty
* so set the channel to zero, caller should
* take of zero channel id case.
*/
*ap_chnl_id = 0;
QDF_TRACE(QDF_MODULE_ID_SME,
QDF_TRACE_LEVEL_ERROR,
FL("Scan is empty, set chnl to 0"));
status = QDF_STATUS_E_FAILURE;
}
} else {
sme_err("Failed to get scan get result");
status = QDF_STATUS_E_FAILURE;
}
csr_free_scan_filter(mac_ctx, scan_filter);
sme_release_global_lock(&mac_ctx->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Aquiring lock failed"));
csr_free_scan_filter(mac_ctx, scan_filter);
status = QDF_STATUS_E_FAILURE;
}
qdf_mem_free(scan_filter);
return status;
}
/**
* sme_store_joinreq_param() - This function will pass station's join
* request to store to csr.
* @hal_handle: pointer to hal context.
* @profile: pointer to station's roam profile.
* @scan_cache: pointer to station's scan cache.
* @roam_id: reference to roam_id variable being passed.
* @session_id: station's session id.
*
* This function will pass station's join request further down to csr
* to store it. this stored parameter will be used later.
*
* Return: true or false based on function's overall success.
**/
bool sme_store_joinreq_param(tHalHandle hal_handle,
struct csr_roam_profile *profile,
tScanResultHandle scan_cache,
uint32_t *roam_id,
uint32_t session_id)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
QDF_STATUS status = QDF_STATUS_E_FAILURE;
bool ret_status = true;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_STORE_JOIN_REQ,
session_id, 0));
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
if (false == csr_store_joinreq_param(mac_ctx, profile,
scan_cache, roam_id, session_id))
ret_status = false;
sme_release_global_lock(&mac_ctx->sme);
} else {
ret_status = false;
}
return ret_status;
}
/**
* sme_clear_joinreq_param() - This function will pass station's clear
* the join request to csr.
* @hal_handle: pointer to hal context.
* @session_id: station's session id.
*
* This function will pass station's clear join request further down to csr
* to cleanup.
*
* Return: true or false based on function's overall success.
**/
bool sme_clear_joinreq_param(tHalHandle hal_handle,
uint32_t session_id)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
QDF_STATUS status = QDF_STATUS_E_FAILURE;
bool ret_status = true;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CLEAR_JOIN_REQ,
session_id, 0));
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
if (false == csr_clear_joinreq_param(mac_ctx,
session_id))
ret_status = false;
sme_release_global_lock(&mac_ctx->sme);
} else {
ret_status = false;
}
return ret_status;
}
/**
* sme_issue_stored_joinreq() - This function will issues station's stored
* the join request to csr.
* @hal_handle: pointer to hal context.
* @roam_id: reference to roam_id variable being passed.
* @session_id: station's session id.
*
* This function will issue station's stored join request further down to csr
* to proceed forward.
*
* Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE.
**/
QDF_STATUS sme_issue_stored_joinreq(tHalHandle hal_handle,
uint32_t *roam_id,
uint32_t session_id)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
QDF_STATUS status = QDF_STATUS_E_FAILURE;
QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ISSUE_JOIN_REQ,
session_id, 0));
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
if (QDF_STATUS_SUCCESS != csr_issue_stored_joinreq(mac_ctx,
roam_id,
session_id)) {
ret_status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac_ctx->sme);
} else {
csr_clear_joinreq_param(mac_ctx, session_id);
ret_status = QDF_STATUS_E_FAILURE;
}
return ret_status;
}
/*
* sme_scan_flush_result() -
* A wrapper function to request CSR to clear scan results.
* This is a synchronous call
*
* Return QDF_STATUS
*/
QDF_STATUS sme_scan_flush_result(tHalHandle hHal)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS,
0, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_scan_flush_result(pMac);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_filter_scan_results() -
* A wrapper function to request CSR to clear scan results.
* This is a synchronous call
*
* tHalHandle - HAL context handle
* sessionId - session id
* Return QDF_STATUS
*/
QDF_STATUS sme_filter_scan_results(tHalHandle hHal, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_RESULTS,
sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_scan_filter_results(pMac);
sme_release_global_lock(&pMac->sme);
}
return status;
}
QDF_STATUS sme_scan_flush_p2p_result(tHalHandle hHal, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SCAN_FLUSH_P2PRESULTS,
sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_scan_flush_selective_result(pMac, true);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_scan_result_get_first() -
* A wrapper function to request CSR to returns the first element of
* scan result.
* This is a synchronous call
*
* hScanResult - returned from csr_scan_get_result
* Return tCsrScanResultInfo * - NULL if no result
*/
tCsrScanResultInfo *sme_scan_result_get_first(tHalHandle hHal,
tScanResultHandle hScanResult)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tCsrScanResultInfo *pRet = NULL;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_GETFIRST,
NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pRet = csr_scan_result_get_first(pMac, hScanResult);
sme_release_global_lock(&pMac->sme);
}
return pRet;
}
/*
* sme_scan_result_get_next() -
* A wrapper function to request CSR to returns the next element of
* scan result. It can be called without calling csr_scan_result_get_first first
* This is a synchronous call
*
* hScanResult - returned from csr_scan_get_result
* Return Null if no result or reach the end
*/
tCsrScanResultInfo *sme_scan_result_get_next(tHalHandle hHal,
tScanResultHandle hScanResult)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tCsrScanResultInfo *pRet = NULL;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pRet = csr_scan_result_get_next(pMac, hScanResult);
sme_release_global_lock(&pMac->sme);
}
return pRet;
}
/*
* sme_scan_result_purge() -
* A wrapper function to request CSR to remove all items(tCsrScanResult)
* in the list and free memory for each item
* This is a synchronous call
*
* hScanResult - returned from csr_scan_get_result. hScanResult is
* considered gone by
* calling this function and even before this function reutrns.
* Return QDF_STATUS
*/
QDF_STATUS sme_scan_result_purge(tScanResultHandle hScanResult)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = sme_get_mac_context();
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SCAN_RESULT_PURGE,
NO_SESSION, 0));
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_scan_result_purge(mac_ctx, hScanResult);
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
eCsrPhyMode sme_get_phy_mode(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.phyMode;
}
/*
* sme_get_channel_bonding_mode5_g() - get the channel bonding mode for 5G band
*
* hHal - HAL handle
* mode - channel bonding mode
*
* Return QDF_STATUS
*/
QDF_STATUS sme_get_channel_bonding_mode5_g(tHalHandle hHal, uint32_t *mode)
{
tSmeConfigParams *smeConfig;
if (!mode) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: invalid mode", __func__);
return QDF_STATUS_E_FAILURE;
}
smeConfig = qdf_mem_malloc(sizeof(*smeConfig));
if (!smeConfig) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: failed to alloc smeConfig", __func__);
return QDF_STATUS_E_NOMEM;
}
if (sme_get_config_param(hHal, smeConfig) != QDF_STATUS_SUCCESS) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: sme_get_config_param failed", __func__);
qdf_mem_free(smeConfig);
return QDF_STATUS_E_FAILURE;
}
*mode = smeConfig->csrConfig.channelBondingMode5GHz;
qdf_mem_free(smeConfig);
return QDF_STATUS_SUCCESS;
}
/*
* sme_get_channel_bonding_mode24_g() - get the channel bonding mode for 2.4G
* band
*
* hHal - HAL handle
* mode - channel bonding mode
*
* Return QDF_STATUS
*/
QDF_STATUS sme_get_channel_bonding_mode24_g(tHalHandle hHal, uint32_t *mode)
{
tSmeConfigParams *smeConfig;
if (!mode) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: invalid mode", __func__);
return QDF_STATUS_E_FAILURE;
}
smeConfig = qdf_mem_malloc(sizeof(*smeConfig));
if (!smeConfig) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: failed to alloc smeConfig", __func__);
return QDF_STATUS_E_NOMEM;
}
if (sme_get_config_param(hHal, smeConfig) != QDF_STATUS_SUCCESS) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: sme_get_config_param failed", __func__);
qdf_mem_free(smeConfig);
return QDF_STATUS_E_FAILURE;
}
*mode = smeConfig->csrConfig.channelBondingMode24GHz;
qdf_mem_free(smeConfig);
return QDF_STATUS_SUCCESS;
}
/*
* sme_roam_connect() -
* A wrapper function to request CSR to inititiate an association
* This is an asynchronous call.
*
* sessionId - the sessionId returned by sme_open_session.
* pProfile - description of the network to which to connect
* hBssListIn - a list of BSS descriptor to roam to. It is returned
* from csr_scan_get_result
* pRoamId - to get back the request ID
* Return QDF_STATUS
*/
QDF_STATUS sme_roam_connect(tHalHandle hHal, uint8_t sessionId,
struct csr_roam_profile *pProfile,
uint32_t *pRoamId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (!pMac)
return QDF_STATUS_E_FAILURE;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_CONNECT, sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
status =
csr_roam_connect(pMac, sessionId, pProfile,
pRoamId);
} else {
sme_err("Invalid sessionID: %d", sessionId);
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->sme);
} else {
sme_err("sme_acquire_global_lock failed");
}
return status;
}
/*
* sme_set_phy_mode() -
* Changes the PhyMode.
*
* hHal - The handle returned by mac_open.
* phyMode new phyMode which is to set
* Return QDF_STATUS SUCCESS.
*/
QDF_STATUS sme_set_phy_mode(tHalHandle hHal, eCsrPhyMode phyMode)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pMac->roam.configParam.phyMode = phyMode;
pMac->roam.configParam.uCfgDot11Mode =
csr_get_cfg_dot11_mode_from_csr_phy_mode(NULL,
pMac->roam.configParam.phyMode,
pMac->roam.configParam.
ProprietaryRatesEnabled);
return QDF_STATUS_SUCCESS;
}
/*
* sme_roam_reassoc() -
* A wrapper function to request CSR to inititiate a re-association
*
* pProfile - can be NULL to join the currently connected AP. In that
* case modProfileFields should carry the modified field(s) which could trigger
* reassoc
* modProfileFields - fields which are part of tCsrRoamConnectedProfile
* that might need modification dynamically once STA is up & running and this
* could trigger a reassoc
* pRoamId - to get back the request ID
* Return QDF_STATUS
*/
QDF_STATUS sme_roam_reassoc(tHalHandle hHal, uint8_t sessionId,
struct csr_roam_profile *pProfile,
tCsrRoamModifyProfileFields modProfileFields,
uint32_t *pRoamId, bool fForce)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ROAM_REASSOC, sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
if ((NULL == pProfile) && (fForce == 1))
status = csr_reassoc(pMac, sessionId,
&modProfileFields, pRoamId,
fForce);
else
status = csr_roam_reassoc(pMac, sessionId,
pProfile,
modProfileFields, pRoamId);
} else {
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_roam_connect_to_last_profile() -
* A wrapper function to request CSR to disconnect and reconnect with
* the same profile
* This is an asynchronous call.
*
* Return QDF_STATUS. It returns fail if currently connected
*/
QDF_STATUS sme_roam_connect_to_last_profile(tHalHandle hHal, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE,
sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_roam_connect_to_last_profile(pMac,
sessionId);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
QDF_STATUS sme_roam_disconnect(tHalHandle hal, uint8_t session_id,
eCsrRoamDisconnectReason reason)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ROAM_DISCONNECT, session_id,
reason));
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(mac_ctx, session_id))
status = csr_roam_disconnect(mac_ctx, session_id,
reason);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
/* sme_dhcp_done_ind() - send dhcp done ind
* @hal: hal context
* @session_id: session id
*
* Return: void.
*/
void sme_dhcp_done_ind(tHalHandle hal, uint8_t session_id)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct csr_roam_session *session;
if (!mac_ctx)
return;
session = CSR_GET_SESSION(mac_ctx, session_id);
if (!session) {
sme_err("Session: %d not found", session_id);
return;
}
session->dhcp_done = true;
}
/*
* sme_roam_stop_bss() -
* To stop BSS for Soft AP. This is an asynchronous API.
*
* hHal - Global structure
* sessionId - sessionId of SoftAP
* Return QDF_STATUS SUCCESS Roam callback will be called to indicate
* actual results
*/
QDF_STATUS sme_roam_stop_bss(tHalHandle hHal, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_roam_issue_stop_bss_cmd(pMac, sessionId,
false);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_roam_disconnect_sta() - disassociate a station
* @hHal: Global structure
* @sessionId: SessionId of SoftAP
* @p_del_sta_params: Pointer to parameters of the station to disassoc
*
* To disassociate a station. This is an asynchronous API.
*
* Return: QDF_STATUS_SUCCESS on success.Roam callback will
* be called to indicate actual result.
*/
QDF_STATUS sme_roam_disconnect_sta(tHalHandle hHal, uint8_t sessionId,
struct csr_del_sta_params *p_del_sta_params)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pMac) {
QDF_ASSERT(0);
return status;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_roam_issue_disassociate_sta_cmd(pMac,
sessionId, p_del_sta_params);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_roam_deauth_sta() - deauthenticate a station
* @hHal: Global structure
* @sessionId: SessionId of SoftAP
* @pDelStaParams: Pointer to parameters of the station to deauthenticate
*
* To disassociate a station. This is an asynchronous API.
*
* Return: QDF_STATUS_SUCCESS on success or another QDF_STATUS error
* code on error. Roam callback will be called to indicate actual
* result
*/
QDF_STATUS sme_roam_deauth_sta(tHalHandle hHal, uint8_t sessionId,
struct csr_del_sta_params *pDelStaParams)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pMac) {
QDF_ASSERT(0);
return status;
}
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_DEAUTH_STA,
sessionId, pDelStaParams->reason_code));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status =
csr_roam_issue_deauth_sta_cmd(pMac, sessionId,
pDelStaParams);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_roam_get_associated_stas() -
* To probe the list of associated stations from various modules
* of CORE stack.
* This is an asynchronous API.
*
* sessionId - sessionId of SoftAP
* modId - Module from whom list of associtated stations is
* to be probed. If an invalid module is passed then
* by default QDF_MODULE_ID_PE will be probed.
* pUsrContext - Opaque HDD context
* pfnSapEventCallback - Sap event callback in HDD
* pAssocBuf - Caller allocated memory to be filled with associatd
* stations info
* Return QDF_STATUS
*/
QDF_STATUS sme_roam_get_associated_stas(tHalHandle hHal, uint8_t sessionId,
QDF_MODULE_ID modId, void *pUsrContext,
void *pfnSapEventCallback,
uint8_t *pAssocStasBuf)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pMac) {
QDF_ASSERT(0);
return status;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status =
csr_roam_get_associated_stas(pMac, sessionId,
modId,
pUsrContext,
pfnSapEventCallback,
pAssocStasBuf);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_roam_get_connect_state() -
* A wrapper function to request CSR to return the current connect state
* of Roaming
* This is a synchronous call.
*
* Return QDF_STATUS
*/
QDF_STATUS sme_roam_get_connect_state(tHalHandle hHal, uint8_t sessionId,
eCsrConnectState *pState)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_roam_get_connect_state(pMac, sessionId,
pState);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_roam_get_connect_profile() -
* A wrapper function to request CSR to return the current connect
* profile. Caller must call csr_roam_free_connect_profile after it is done
* and before reuse for another csr_roam_get_connect_profile call.
* This is a synchronous call.
*
* pProfile - pointer to a caller allocated structure
* tCsrRoamConnectedProfile
* eturn QDF_STATUS. Failure if not connected
*/
QDF_STATUS sme_roam_get_connect_profile(tHalHandle hHal, uint8_t sessionId,
tCsrRoamConnectedProfile *pProfile)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ROAM_GET_CONNECTPROFILE,
sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_roam_get_connect_profile(pMac, sessionId,
pProfile);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_roam_free_connect_profile - a wrapper function to request CSR to free and
* reinitialize the profile returned previously by csr_roam_get_connect_profile.
*
* @profile - pointer to a caller allocated structure tCsrRoamConnectedProfile
*
* Return: none
*/
void sme_roam_free_connect_profile(tCsrRoamConnectedProfile *profile)
{
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ROAM_FREE_CONNECTPROFILE,
NO_SESSION, 0));
csr_roam_free_connect_profile(profile);
}
/*
* sme_roam_set_pmkid_cache() -
* A wrapper function to request CSR to return the PMKID candidate list
* This is a synchronous call.
* pPMKIDCache - caller allocated buffer point to an array of
* tPmkidCacheInfo
* numItems - a variable that has the number of tPmkidCacheInfo
* allocated when retruning, this is either the number needed
* or number of items put into pPMKIDCache
* update_entire_cache - this bool value specifies if the entire pmkid
* cache should be overwritten or should it be
* updated entry by entry.
* Return QDF_STATUS - when fail, it usually means the buffer allocated is not
* big enough and pNumItems has the number of
* tPmkidCacheInfo.
* \Note: pNumItems is a number of tPmkidCacheInfo,
* not sizeof(tPmkidCacheInfo) * something
*/
QDF_STATUS sme_roam_set_pmkid_cache(tHalHandle hHal, uint8_t sessionId,
tPmkidCacheInfo *pPMKIDCache,
uint32_t numItems, bool update_entire_cache)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ROAM_SET_PMKIDCACHE, sessionId,
numItems));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_roam_set_pmkid_cache(pMac, sessionId,
pPMKIDCache,
numItems, update_entire_cache);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
QDF_STATUS sme_roam_del_pmkid_from_cache(tHalHandle hHal, uint8_t sessionId,
tPmkidCacheInfo *pmksa,
bool flush_cache)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ROAM_DEL_PMKIDCACHE,
sessionId, flush_cache));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_roam_del_pmkid_from_cache(pMac, sessionId,
pmksa, flush_cache);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
void sme_get_pmk_info(tHalHandle hal, uint8_t session_id,
tPmkidCacheInfo *pmk_cache)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
QDF_STATUS status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(mac_ctx, session_id))
csr_get_pmk_info(mac_ctx, session_id, pmk_cache);
sme_release_global_lock(&mac_ctx->sme);
}
}
#else
static inline
void sme_get_pmk_info(tHalHandle hal, uint8_t session_id,
tPmkidCacheInfo *pmk_cache)
{}
#endif
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
/*
* \fn sme_roam_set_psk_pmk
* \brief a wrapper function to request CSR to save PSK/PMK
* This is a synchronous call.
* \param hHal - Global structure
* \param sessionId - SME sessionId
* \param pPSK_PMK - pointer to an array of Psk[]/Pmk
* \param pmk_len - Length could be only 16 bytes in case if LEAP
* connections. Need to pass this information to
* firmware.
* \return QDF_STATUS -status whether PSK/PMK is set or not
*/
QDF_STATUS sme_roam_set_psk_pmk(tHalHandle hHal, uint8_t sessionId,
uint8_t *pPSK_PMK, size_t pmk_len)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_roam_set_psk_pmk(pMac, sessionId, pPSK_PMK,
pmk_len);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif
QDF_STATUS sme_roam_get_wpa_rsn_req_ie(tHalHandle hal, uint8_t session_id,
uint32_t *len, uint8_t *buf)
{
QDF_STATUS status;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(mac, session_id))
status = csr_roam_get_wpa_rsn_req_ie(mac, session_id,
len, buf);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&mac->sme);
}
return status;
}
QDF_STATUS sme_roam_get_wpa_rsn_rsp_ie(tHalHandle hal, uint8_t session_id,
uint32_t *len, uint8_t *buf)
{
QDF_STATUS status;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(mac, session_id))
status = csr_roam_get_wpa_rsn_rsp_ie(mac, session_id,
len, buf);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&mac->sme);
}
return status;
}
/*
* sme_roam_get_num_pmkid_cache() -
* A wrapper function to request CSR to return number of PMKID cache
* entries
* This is a synchronous call.
*
* Return uint32_t - the number of PMKID cache entries
*/
uint32_t sme_roam_get_num_pmkid_cache(tHalHandle hHal, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
uint32_t numPmkidCache = 0;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
numPmkidCache =
csr_roam_get_num_pmkid_cache(pMac, sessionId);
status = QDF_STATUS_SUCCESS;
} else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return numPmkidCache;
}
/*
* sme_roam_get_pmkid_cache() -
* A wrapper function to request CSR to return PMKID cache from CSR
* This is a synchronous call.
*
* pNum - caller allocated memory that has the space of the number of
* pBuf tPmkidCacheInfo as input. Upon returned, *pNum has the
* needed or actually number in tPmkidCacheInfo.
* pPmkidCache - Caller allocated memory that contains PMKID cache, if
* any, upon return
* Return QDF_STATUS - when fail, it usually means the buffer allocated is not
* big enough
*/
QDF_STATUS sme_roam_get_pmkid_cache(tHalHandle hHal, uint8_t sessionId,
uint32_t *pNum, tPmkidCacheInfo *pPmkidCache)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ROAM_GET_PMKIDCACHE, sessionId,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_roam_get_pmkid_cache(pMac, sessionId, pNum,
pPmkidCache);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_config_param() -
* A wrapper function that HDD calls to get the global settings
* currently maintained by CSR.
* This is a synchronous call.
*
* pParam - caller allocated memory
* Return QDF_STATUS
*/
QDF_STATUS sme_get_config_param(tHalHandle hHal, tSmeConfigParams *pParam)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_GET_CONFIGPARAM, NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_get_config_param(pMac, &pParam->csrConfig);
if (status != QDF_STATUS_SUCCESS) {
sme_err("csr_get_config_param failed");
sme_release_global_lock(&pMac->sme);
return status;
}
qdf_mem_copy(&pParam->rrmConfig,
&pMac->rrm.rrmSmeContext.rrmConfig,
sizeof(pMac->rrm.rrmSmeContext.rrmConfig));
pParam->snr_monitor_enabled = pMac->snr_monitor_enabled;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_cfg_set_int() - Sets the cfg parameter value.
* @hal: Handle to hal.
* @cfg_id: Configuration parameter ID.
* @value: value to be saved in the cfg parameter.
*
* This function sets the string value in cfg parameter.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_cfg_set_int(tHalHandle hal, uint16_t cfg_id, uint32_t value)
{
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (QDF_STATUS_SUCCESS != cfg_set_int(pmac, cfg_id, value))
status = QDF_STATUS_E_FAILURE;
return status;
}
/**
* sme_cfg_set_str() - Sets the cfg parameter string.
* @hal: Handle to hal.
* @cfg_id: Configuration parameter ID.
* @str: Pointer to the string buffer.
* @length: Length of the string.
*
* This function sets the string value in cfg parameter.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_cfg_set_str(tHalHandle hal, uint16_t cfg_id, uint8_t *str,
uint32_t length)
{
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (QDF_STATUS_SUCCESS != cfg_set_str(pmac, cfg_id, str, length))
status = QDF_STATUS_E_FAILURE;
return status;
}
/**
* sme_cfg_get_int() - Gets the cfg parameter value.
* @hal: Handle to hal.
* @cfg_id: Configuration parameter ID.
* @cfg_value: Pointer to variable in which cfg value
* will be saved.
*
* This function gets the value of the cfg parameter.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_cfg_get_int(tHalHandle hal, uint16_t cfg_id, uint32_t *cfg_value)
{
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (QDF_STATUS_SUCCESS != wlan_cfg_get_int(pmac, cfg_id, cfg_value))
status = QDF_STATUS_E_FAILURE;
return status;
}
/**
* sme_cfg_get_str() - Gets the cfg parameter string.
* @hal: Handle to hal.
* @cfg_id: Configuration parameter ID.
* @str: Pointer to the string buffer.
* @length: Pointer to length of the string.
*
* This function gets the string value of the cfg parameter.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_cfg_get_str(tHalHandle hal, uint16_t cfg_id, uint8_t *str,
uint32_t *length)
{
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (QDF_STATUS_SUCCESS != wlan_cfg_get_str(pmac, cfg_id, str, length))
status = QDF_STATUS_E_INVAL;
return status;
}
/*
* sme_get_modify_profile_fields() -
* HDD or SME - QOS calls this function to get the current values of
* connected profile fields, changing which can cause reassoc.
* This function must be called after CFG is downloaded and STA is in connected
* state. Also, make sure to call this function to get the current profile
* fields before calling the reassoc. So that pModifyProfileFields will have
* all the latest values plus the one(s) has been updated as part of reassoc
* request.
*
* pModifyProfileFields - pointer to the connected profile fields
* changing which can cause reassoc
* Return QDF_STATUS
*/
QDF_STATUS sme_get_modify_profile_fields(tHalHandle hHal, uint8_t sessionId,
tCsrRoamModifyProfileFields *
pModifyProfileFields)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_GET_MODPROFFIELDS, sessionId,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId))
status = csr_get_modify_profile_fields(pMac, sessionId,
pModifyProfileFields);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_dhcp_till_power_active_flag() -
* Sets/Clears DHCP related flag to disable/enable auto PS
*
* hal - The handle returned by mac_open.
*/
void sme_set_dhcp_till_power_active_flag(tHalHandle hal, uint8_t flag)
{
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct ps_global_info *ps_global_info = &mac->sme.ps_global_info;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SET_DHCP_FLAG, NO_SESSION,
flag));
/* Set/Clear the DHCP flag which will disable/enable auto PS */
ps_global_info->remain_in_power_active_till_dhcp = flag;
}
#ifdef FEATURE_OEM_DATA_SUPPORT
/**
* sme_register_oem_data_rsp_callback() - Register a routine of
* type send_oem_data_rsp_msg
* @h_hal: Handle returned by mac_open.
* @callback: Callback to send response
* to oem application.
*
* sme_oem_data_rsp_callback is used to register sme_send_oem_data_rsp_msg
* callback function.
*
* Return: QDF_STATUS.
*/
QDF_STATUS sme_register_oem_data_rsp_callback(tHalHandle h_hal,
sme_send_oem_data_rsp_msg callback)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pmac = PMAC_STRUCT(h_hal);
pmac->sme.oem_data_rsp_callback = callback;
return status;
}
/**
* sme_deregister_oem_data_rsp_callback() - De-register OEM datarsp callback
* @h_hal: Handler return by mac_open
* This function De-registers the OEM data response callback to SME
*
* Return: None
*/
void sme_deregister_oem_data_rsp_callback(tHalHandle h_hal)
{
tpAniSirGlobal pmac;
if (!h_hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("hHal is not valid"));
return;
}
pmac = PMAC_STRUCT(h_hal);
pmac->sme.oem_data_rsp_callback = NULL;
}
/**
* sme_oem_update_capability() - update UMAC's oem related capability.
* @hal: Handle returned by mac_open
* @oem_cap: pointer to oem_capability
*
* This function updates OEM capability to UMAC. Currently RTT
* related capabilities are updated. More capabilities can be
* added in future.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_oem_update_capability(tHalHandle hal,
struct sme_oem_capability *cap)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
uint8_t *bytes;
bytes = pmac->rrm.rrmSmeContext.rrmConfig.rm_capability;
if (cap->ftm_rr)
bytes[4] |= RM_CAP_FTM_RANGE_REPORT;
if (cap->lci_capability)
bytes[4] |= RM_CAP_CIVIC_LOC_MEASUREMENT;
return status;
}
/**
* sme_oem_get_capability() - get oem capability
* @hal: Handle returned by mac_open
* @oem_cap: pointer to oem_capability
*
* This function is used to get the OEM capability from UMAC.
* Currently RTT related capabilities are received. More
* capabilities can be added in future.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_oem_get_capability(tHalHandle hal,
struct sme_oem_capability *cap)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
uint8_t *bytes;
bytes = pmac->rrm.rrmSmeContext.rrmConfig.rm_capability;
cap->ftm_rr = bytes[4] & RM_CAP_FTM_RANGE_REPORT;
cap->lci_capability = bytes[4] & RM_CAP_CIVIC_LOC_MEASUREMENT;
return status;
}
#endif
/**
* sme_roam_set_key() - To set encryption key.
* @hal: hal global context
* @session_id: session id
* @set_key: pointer to a caller allocated object of tCsrSetContextInfo
* @ptr_roam_id: Upon success return, this is the id caller can use to
* identify the request in roamcallback
*
* This function should be called only when connected. This is an asynchronous
* API.
*
* Return: Status of operation
*/
QDF_STATUS sme_roam_set_key(tHalHandle hal, uint8_t session_id,
tCsrRoamSetKey *set_key, uint32_t *ptr_roam_id)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
uint32_t roam_id;
struct csr_roam_session *session = NULL;
struct ps_global_info *ps_global_info = &mac_ctx->sme.ps_global_info;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_SET_KEY,
session_id, 0));
if (set_key->keyLength > CSR_MAX_KEY_LEN) {
sme_err("Invalid key length: %d", set_key->keyLength);
return QDF_STATUS_E_FAILURE;
}
/*Once Setkey is done, we can go in BMPS */
if (set_key->keyLength)
ps_global_info->remain_in_power_active_till_dhcp = false;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
roam_id = GET_NEXT_ROAM_ID(&mac_ctx->roam);
if (ptr_roam_id)
*ptr_roam_id = roam_id;
sme_debug("keyLength: %d", set_key->keyLength);
sme_debug("Session_id: %d roam_id: %d", session_id, roam_id);
session = CSR_GET_SESSION(mac_ctx, session_id);
if (!session) {
sme_err("session %d not found", session_id);
sme_release_global_lock(&mac_ctx->sme);
return QDF_STATUS_E_FAILURE;
}
if (CSR_IS_INFRA_AP(&session->connectedProfile)
&& set_key->keyDirection == eSIR_TX_DEFAULT) {
if ((eCSR_ENCRYPT_TYPE_WEP40 == set_key->encType)
|| (eCSR_ENCRYPT_TYPE_WEP40_STATICKEY ==
set_key->encType)) {
session->pCurRoamProfile->negotiatedUCEncryptionType =
eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
}
if ((eCSR_ENCRYPT_TYPE_WEP104 == set_key->encType)
|| (eCSR_ENCRYPT_TYPE_WEP104_STATICKEY ==
set_key->encType)) {
session->pCurRoamProfile->negotiatedUCEncryptionType =
eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
}
}
status = csr_roam_set_key(mac_ctx, session_id, set_key, roam_id);
sme_release_global_lock(&mac_ctx->sme);
return status;
}
/**
* sme_roam_set_default_key_index - To set default wep key idx
* @hal: pointer to hal handler
* @session_id: session id
* @default_idx: default wep key index
*
* This function prepares a message and post to WMA to set wep default
* key index
*
* Return: Success:QDF_STATUS_SUCCESS Failure: Error value
*/
QDF_STATUS sme_roam_set_default_key_index(tHalHandle hal, uint8_t session_id,
uint8_t default_idx)
{
struct scheduler_msg msg = {0};
struct wep_update_default_key_idx *update_key;
update_key = qdf_mem_malloc(sizeof(*update_key));
if (!update_key) {
sme_err("Failed to allocate memory for update key");
return QDF_STATUS_E_NOMEM;
}
update_key->session_id = session_id;
update_key->default_idx = default_idx;
msg.type = WMA_UPDATE_WEP_DEFAULT_KEY;
msg.reserved = 0;
msg.bodyptr = (void *)update_key;
if (QDF_STATUS_SUCCESS !=
scheduler_post_msg(QDF_MODULE_ID_WMA, &msg)) {
sme_err("Failed to post WMA_UPDATE_WEP_DEFAULT_KEY to WMA");
qdf_mem_free(update_key);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* sme_get_rssi() - API to retrieve current RSSI
* @hHal: HAL handle for device
* @callback: SME sends back the requested stats using the callback
* @staId: The station ID for which the RSSI is requested for
* @bssid: The bssid of the connected session
* @lastRSSI: RSSI value at time of request. In case fw cannot provide
* RSSI, do not hold up but return this value.
* @pContext: user context to be passed back along with the callback
*
* A wrapper function that client calls to register a callback to get RSSI
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_get_rssi(tHalHandle hHal,
tCsrRssiCallback callback, uint8_t staId,
struct qdf_mac_addr bssId, int8_t lastRSSI,
void *pContext)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_GET_RSSI, NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_get_rssi(pMac, callback,
staId, bssId, lastRSSI,
pContext);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_snr() -
* A wrapper function that client calls to register a callback to get SNR
*
* callback - SME sends back the requested stats using the callback
* staId - The station ID for which the stats is requested for
* pContext - user context to be passed back along with the callback
* p_cds_context - cds context
* \return QDF_STATUS
*/
QDF_STATUS sme_get_snr(tHalHandle hHal,
tCsrSnrCallback callback,
uint8_t staId, struct qdf_mac_addr bssId, void *pContext)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_get_snr(pMac, callback, staId, bssId, pContext);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#ifndef QCA_SUPPORT_CP_STATS
/*
* sme_get_statistics() -
* A wrapper function that client calls to register a callback to get
* different PHY level statistics from CSR.
*
* requesterId - different client requesting for statistics,
* HDD, UMA/GAN etc
* statsMask - The different category/categories of stats requester
* is looking for
* callback - SME sends back the requested stats using the callback
* periodicity - If requester needs periodic update in millisec, 0 means
* it's an one time request
* cache - If requester is happy with cached stats
* staId - The station ID for which the stats is requested for
* pContext - user context to be passed back along with the callback
* sessionId - sme session interface
* Return QDF_STATUS
*/
QDF_STATUS sme_get_statistics(tHalHandle hHal,
eCsrStatsRequesterType requesterId,
uint32_t statsMask, tCsrStatsCallback callback,
uint8_t staId, void *pContext, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_get_statistics(pMac, requesterId, statsMask,
callback, staId, pContext,
sessionId);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif
QDF_STATUS sme_get_link_status(mac_handle_t mac_handle,
csr_link_status_callback callback,
void *context, uint8_t session_id)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
tAniGetLinkStatus *msg;
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
msg = qdf_mem_malloc(sizeof(*msg));
if (!msg) {
sme_err("Malloc failure");
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_NOMEM;
}
msg->msgType = WMA_LINK_STATUS_GET_REQ;
msg->msgLen = sizeof(*msg);
msg->sessionId = session_id;
mac->sme.link_status_context = context;
mac->sme.link_status_callback = callback;
message.type = WMA_LINK_STATUS_GET_REQ;
message.bodyptr = msg;
message.reserved = 0;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("post msg failed, %d", status);
qdf_mem_free(msg);
mac->sme.link_status_context = NULL;
mac->sme.link_status_callback = NULL;
}
sme_release_global_lock(&mac->sme);
}
return status;
}
/*
* sme_get_country_code() -
* To return the current country code. If no country code is applied,
* default country code is used to fill the buffer.
* If 11d supported is turned off, an error is return and the last
* applied/default country code is used.
* This is a synchronous API.
*
* pBuf - pointer to a caller allocated buffer for returned country code.
* pbLen For input, this parameter indicates how big is the buffer.
* Upon return, this parameter has the number of bytes for
* country. If pBuf doesn't have enough space, this function
* returns fail status and this parameter contains the number
* that is needed.
*
* Return QDF_STATUS SUCCESS.
*
* FAILURE or RESOURCES The API finished and failed.
*/
QDF_STATUS sme_get_country_code(tHalHandle hHal, uint8_t *pBuf, uint8_t *pbLen)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_GET_CNTRYCODE, NO_SESSION, 0));
return csr_get_country_code(pMac, pBuf, pbLen);
}
/* some support functions */
bool sme_is11d_supported(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return wlan_reg_11d_enabled_on_host(pMac->psoc);
}
bool sme_is11h_supported(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return csr_is11h_supported(pMac);
}
bool sme_is_wmm_supported(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return csr_is_wmm_supported(pMac);
}
/*
* sme_generic_change_country_code() -
* Change Country code from upperlayer during WLAN driver operation.
* This is a synchronous API.
*
* hHal - The handle returned by mac_open.
* pCountry New Country Code String
* reg_domain regulatory domain
* Return QDF_STATUS SUCCESS.
* FAILURE or RESOURCES The API finished and failed.
*/
QDF_STATUS sme_generic_change_country_code(tHalHandle hHal,
uint8_t *pCountry)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg msg = {0};
tAniGenericChangeCountryCodeReq *pMsg;
if (NULL == pMac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
"%s: pMac is null", __func__);
return status;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMsg = qdf_mem_malloc(sizeof(tAniGenericChangeCountryCodeReq));
if (NULL == pMsg) {
sme_err("sme_generic_change_country_code: failed to allocate mem for req");
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
pMsg->msgType = eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE;
pMsg->msgLen =
(uint16_t) sizeof(tAniGenericChangeCountryCodeReq);
qdf_mem_copy(pMsg->countryCode, pCountry, 2);
pMsg->countryCode[2] = ' ';
msg.type = eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE;
msg.bodyptr = pMsg;
msg.reserved = 0;
if (QDF_STATUS_SUCCESS !=
scheduler_post_msg(QDF_MODULE_ID_SME, &msg)) {
sme_err("sme_generic_change_country_code failed to post msg to self");
qdf_mem_free(pMsg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_dhcp_start_ind() -
* API to signal the FW about the DHCP Start event.
*
* hHal - HAL handle for device.
* device_mode - mode(AP,SAP etc) of the device.
* macAddr - MAC address of the adapter.
* sessionId - session ID.
* Return QDF_STATUS SUCCESS.
* FAILURE or RESOURCES The API finished and failed.
*/
QDF_STATUS sme_dhcp_start_ind(tHalHandle hHal,
uint8_t device_mode,
uint8_t *macAddr, uint8_t sessionId)
{
QDF_STATUS status;
QDF_STATUS qdf_status;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tAniDHCPInd *pMsg;
struct csr_roam_session *pSession;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
pSession = CSR_GET_SESSION(pMac, sessionId);
if (!pSession) {
sme_err("Session: %d not found", sessionId);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
pSession->dhcp_done = false;
pMsg = (tAniDHCPInd *) qdf_mem_malloc(sizeof(tAniDHCPInd));
if (NULL == pMsg) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for dhcp start",
__func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
pMsg->msgType = WMA_DHCP_START_IND;
pMsg->msgLen = (uint16_t) sizeof(tAniDHCPInd);
pMsg->device_mode = device_mode;
qdf_mem_copy(pMsg->adapterMacAddr.bytes, macAddr,
QDF_MAC_ADDR_SIZE);
qdf_copy_macaddr(&pMsg->peerMacAddr,
&pSession->connectedProfile.bssid);
message.type = WMA_DHCP_START_IND;
message.bodyptr = pMsg;
message.reserved = 0;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
sessionId, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post DHCP Start MSG fail", __func__);
qdf_mem_free(pMsg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_dhcp_stop_ind() -
* API to signal the FW about the DHCP complete event.
*
* hHal - HAL handle for device.
* device_mode - mode(AP, SAP etc) of the device.
* macAddr - MAC address of the adapter.
* sessionId - session ID.
* Return QDF_STATUS SUCCESS.
* FAILURE or RESOURCES The API finished and failed.
*/
QDF_STATUS sme_dhcp_stop_ind(tHalHandle hHal,
uint8_t device_mode,
uint8_t *macAddr, uint8_t sessionId)
{
QDF_STATUS status;
QDF_STATUS qdf_status;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tAniDHCPInd *pMsg;
struct csr_roam_session *pSession;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
pSession = CSR_GET_SESSION(pMac, sessionId);
if (!pSession) {
sme_err("Session: %d not found", sessionId);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
pSession->dhcp_done = true;
pMsg = (tAniDHCPInd *) qdf_mem_malloc(sizeof(tAniDHCPInd));
if (NULL == pMsg) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for dhcp stop",
__func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
pMsg->msgType = WMA_DHCP_STOP_IND;
pMsg->msgLen = (uint16_t) sizeof(tAniDHCPInd);
pMsg->device_mode = device_mode;
qdf_mem_copy(pMsg->adapterMacAddr.bytes, macAddr,
QDF_MAC_ADDR_SIZE);
qdf_copy_macaddr(&pMsg->peerMacAddr,
&pSession->connectedProfile.bssid);
message.type = WMA_DHCP_STOP_IND;
message.bodyptr = pMsg;
message.reserved = 0;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
sessionId, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post DHCP Stop MSG fail", __func__);
qdf_mem_free(pMsg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_TXFailMonitorStopInd() -
* API to signal the FW to start monitoring TX failures
*
* Return QDF_STATUS SUCCESS.
* FAILURE or RESOURCES The API finished and failed.
*/
QDF_STATUS sme_tx_fail_monitor_start_stop_ind(tHalHandle hHal, uint8_t
tx_fail_count,
void *txFailIndCallback)
{
QDF_STATUS status;
QDF_STATUS qdf_status;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tAniTXFailMonitorInd *pMsg;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
pMsg = (tAniTXFailMonitorInd *)
qdf_mem_malloc(sizeof(tAniTXFailMonitorInd));
if (NULL == pMsg) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Failed to allocate memory", __func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
pMsg->msgType = WMA_TX_FAIL_MONITOR_IND;
pMsg->msgLen = (uint16_t) sizeof(tAniTXFailMonitorInd);
/* tx_fail_count = 0 should disable the Monitoring in FW */
pMsg->tx_fail_count = tx_fail_count;
pMsg->txFailIndCallback = txFailIndCallback;
message.type = WMA_TX_FAIL_MONITOR_IND;
message.bodyptr = pMsg;
message.reserved = 0;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post TX Fail monitor Start MSG fail",
__func__);
qdf_mem_free(pMsg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_neighbor_report_request() -
* API to request neighbor report.
*
* hHal - The handle returned by mac_open.
* pRrmNeighborReq - Pointer to a caller allocated object of type
* tRrmNeighborReq. Caller owns the memory and is
* responsible for freeing it.
* Return QDF_STATUS
* QDF_STATUS_E_FAILURE - failure
* QDF_STATUS_SUCCESS success
*/
QDF_STATUS sme_neighbor_report_request(tHalHandle hHal, uint8_t sessionId,
tpRrmNeighborReq pRrmNeighborReq,
tpRrmNeighborRspCallbackInfo callbackInfo)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_NEIGHBOR_REPORTREQ, NO_SESSION,
0));
if (pRrmNeighborReq->neighbor_report_offload) {
status = csr_invoke_neighbor_report_request(sessionId,
pRrmNeighborReq,
false);
return status;
}
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
status =
sme_rrm_neighbor_report_request(pMac, sessionId,
pRrmNeighborReq, callbackInfo);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_wcnss_wlan_compiled_version() -
* This API returns the version of the WCNSS WLAN API with
* which the HOST driver was built
*
* hHal - The handle returned by mac_open.
* pVersion - Points to the Version structure to be filled
* Return QDF_STATUS
* QDF_STATUS_E_INVAL - failure
* QDF_STATUS_SUCCESS success
*/
QDF_STATUS sme_get_wcnss_wlan_compiled_version(tHalHandle hHal,
tSirVersionType *pVersion)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
if (pVersion != NULL)
status = QDF_STATUS_SUCCESS;
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_wcnss_wlan_reported_version() -
* This API returns the version of the WCNSS WLAN API with
* which the WCNSS driver reports it was built
* hHal - The handle returned by mac_open.
* pVersion - Points to the Version structure to be filled
* Return QDF_STATUS
* QDF_STATUS_E_INVAL - failure
* QDF_STATUS_SUCCESS success
*/
QDF_STATUS sme_get_wcnss_wlan_reported_version(tHalHandle hHal,
tSirVersionType *pVersion)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
if (pVersion != NULL)
status = QDF_STATUS_SUCCESS;
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_wcnss_software_version() -
* This API returns the version string of the WCNSS driver
*
* hHal - The handle returned by mac_open.
* pVersion - Points to the Version string buffer to be filled
* versionBufferSize - THe size of the Version string buffer
* Return QDF_STATUS
* QDF_STATUS_E_INVAL - failure
* QDF_STATUS_SUCCESS success
*/
QDF_STATUS sme_get_wcnss_software_version(tHalHandle hHal,
uint8_t *pVersion,
uint32_t versionBufferSize)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
if (pVersion != NULL)
status =
wma_get_wcnss_software_version(
pVersion,
versionBufferSize);
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_wcnss_hardware_version() -
* This API returns the version string of the WCNSS hardware
*
* hHal - The handle returned by mac_open.
* pVersion - Points to the Version string buffer to be filled
* versionBufferSize - THe size of the Version string buffer
* Return QDF_STATUS
* QDF_STATUS_E_INVAL - failure
* QDF_STATUS_SUCCESS success
*/
QDF_STATUS sme_get_wcnss_hardware_version(tHalHandle hHal,
uint8_t *pVersion,
uint32_t versionBufferSize)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
if (pVersion != NULL)
status = QDF_STATUS_SUCCESS;
else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&pMac->sme);
}
return status;
}
#ifdef FEATURE_OEM_DATA_SUPPORT
/**
* sme_oem_data_req() - send oem data request to WMA
* @hal: HAL handle
* @hdd_oem_req: OEM data request from HDD
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_oem_data_req(tHalHandle hal, struct oem_data_req *hdd_oem_req)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct oem_data_req *oem_data_req;
void *wma_handle;
SME_ENTER();
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
sme_err("wma_handle is NULL");
return QDF_STATUS_E_FAILURE;
}
oem_data_req = qdf_mem_malloc(sizeof(*oem_data_req));
if (!oem_data_req) {
sme_err("mem alloc failed");
return QDF_STATUS_E_NOMEM;
}
oem_data_req->data_len = hdd_oem_req->data_len;
oem_data_req->data = qdf_mem_malloc(oem_data_req->data_len);
if (!oem_data_req->data) {
sme_err("mem alloc failed");
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(oem_data_req->data, hdd_oem_req->data,
oem_data_req->data_len);
status = wma_start_oem_data_req(wma_handle, oem_data_req);
if (!QDF_IS_STATUS_SUCCESS(status))
sme_err("Post oem data request msg fail");
else
sme_debug("OEM request(length: %d) sent to WMA",
oem_data_req->data_len);
if (oem_data_req->data_len)
qdf_mem_free(oem_data_req->data);
qdf_mem_free(oem_data_req);
SME_EXIT();
return status;
}
#endif /*FEATURE_OEM_DATA_SUPPORT */
QDF_STATUS sme_open_session(tHalHandle hal, struct sme_session_params *params)
{
QDF_STATUS status = QDF_STATUS_E_INVAL;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct cdp_pdev *pdev;
ol_txrx_peer_handle peer;
uint8_t peer_id;
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_DEBUG,
"%s: type=%d, session_id %d subType=%d addr:%pM",
__func__, params->type_of_persona,
params->sme_session_id, params->subtype_of_persona,
params->self_mac_addr);
pdev = cds_get_context(QDF_MODULE_ID_TXRX);
if (NULL == pdev) {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
"%s: Failed to get pdev handler", __func__);
return status;
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_ERROR(status))
return status;
peer = cdp_peer_find_by_addr(soc, pdev, params->self_mac_addr,
&peer_id);
if (peer) {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
"%s: Peer=%d exist with same MAC",
__func__, peer_id);
status = QDF_STATUS_E_INVAL;
} else {
status = csr_roam_open_session(mac_ctx, params);
}
sme_release_global_lock(&mac_ctx->sme);
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_OPEN_SESSION,
params->sme_session_id, 0));
return status;
}
QDF_STATUS sme_close_session(tHalHandle hal, uint8_t session_id)
{
QDF_STATUS status;
tpAniSirGlobal pMac = PMAC_STRUCT(hal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CLOSE_SESSION, session_id, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_roam_close_session(pMac, session_id, false);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_change_mcc_beacon_interval() -
* To update P2P-GO beaconInterval. This function should be called after
* disassociating all the station is done
* This is an asynchronous API.
*
* @sessionId: Session Identifier
* Return QDF_STATUS SUCCESS
* FAILURE or RESOURCES
* The API finished and failed.
*/
QDF_STATUS sme_change_mcc_beacon_interval(uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = sme_get_mac_context();
if (!mac_ctx) {
sme_err("mac_ctx is NULL");
return status;
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_send_chng_mcc_beacon_interval(mac_ctx,
sessionId);
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
/**
* sme_set_host_offload(): API to set the host offload feature.
* @hHal: The handle returned by mac_open.
* @sessionId: Session Identifier
* @request: Pointer to the offload request.
*
* Return QDF_STATUS
*/
QDF_STATUS sme_set_host_offload(tHalHandle hHal, uint8_t sessionId,
tpSirHostOffloadReq request)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_E_FAILURE;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SET_HOSTOFFLOAD, sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
#ifdef WLAN_NS_OFFLOAD
if (SIR_IPV6_NS_OFFLOAD == request->offloadType) {
status = sme_set_ps_ns_offload(hHal, request,
sessionId);
} else
#endif /* WLAN_NS_OFFLOAD */
{
status = sme_set_ps_host_offload(hHal, request,
sessionId);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_keep_alive() -
* API to set the Keep Alive feature.
*
* hHal - The handle returned by mac_open.
* request - Pointer to the Keep Alive request.
* Return QDF_STATUS
*/
QDF_STATUS sme_set_keep_alive(tHalHandle hHal, uint8_t session_id,
tpSirKeepAliveReq request)
{
tpSirKeepAliveReq request_buf;
struct scheduler_msg msg = {0};
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, session_id);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
FL("WMA_SET_KEEP_ALIVE message"));
if (pSession == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Session not Found"));
return QDF_STATUS_E_FAILURE;
}
request_buf = qdf_mem_malloc(sizeof(tSirKeepAliveReq));
if (NULL == request_buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Not able to allocate memory for keep alive request");
return QDF_STATUS_E_NOMEM;
}
qdf_copy_macaddr(&request->bssid, &pSession->connectedProfile.bssid);
qdf_mem_copy(request_buf, request, sizeof(tSirKeepAliveReq));
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"buff TP %d input TP %d ", request_buf->timePeriod,
request->timePeriod);
request_buf->sessionId = session_id;
msg.type = WMA_SET_KEEP_ALIVE;
msg.reserved = 0;
msg.bodyptr = request_buf;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
session_id, msg.type));
if (QDF_STATUS_SUCCESS !=
scheduler_post_msg(QDF_MODULE_ID_WMA, &msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Not able to post WMA_SET_KEEP_ALIVE message to WMA");
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/*
* sme_get_operation_channel() -
* API to get current channel on which STA is parked his function gives
* channel information only of infra station or IBSS station
*
* hHal, pointer to memory location and sessionId
* Returns QDF_STATUS_SUCCESS
* QDF_STATUS_E_FAILURE
*/
QDF_STATUS sme_get_operation_channel(tHalHandle hHal, uint32_t *pChannel,
uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct csr_roam_session *pSession;
if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
pSession = CSR_GET_SESSION(pMac, sessionId);
if ((pSession->connectedProfile.BSSType ==
eCSR_BSS_TYPE_INFRASTRUCTURE)
|| (pSession->connectedProfile.BSSType ==
eCSR_BSS_TYPE_IBSS)
|| (pSession->connectedProfile.BSSType ==
eCSR_BSS_TYPE_INFRA_AP)
|| (pSession->connectedProfile.BSSType ==
eCSR_BSS_TYPE_START_IBSS)) {
*pChannel = pSession->connectedProfile.operationChannel;
return QDF_STATUS_SUCCESS;
}
}
return QDF_STATUS_E_FAILURE;
} /* sme_get_operation_channel ends here */
/**
* sme_register_mgmt_frame_ind_callback() - Register a callback for
* management frame indication to PE.
*
* @hal: hal pointer
* @callback: callback pointer to be registered
*
* This function is used to register a callback for management
* frame indication to PE.
*
* Return: Success if msg is posted to PE else Failure.
*/
QDF_STATUS sme_register_mgmt_frame_ind_callback(tHalHandle hal,
sir_mgmt_frame_ind_callback callback)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct sir_sme_mgmt_frame_cb_req *msg;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (QDF_STATUS_SUCCESS ==
sme_acquire_global_lock(&mac_ctx->sme)) {
msg = qdf_mem_malloc(sizeof(*msg));
if (NULL == msg) {
sme_err("Not able to allocate memory");
sme_release_global_lock(&mac_ctx->sme);
return QDF_STATUS_E_NOMEM;
}
msg->message_type = eWNI_SME_REGISTER_MGMT_FRAME_CB;
msg->length = sizeof(*msg);
msg->callback = callback;
status = umac_send_mb_message_to_mac(msg);
sme_release_global_lock(&mac_ctx->sme);
return status;
}
return QDF_STATUS_E_FAILURE;
}
/*
* sme_RegisterMgtFrame() -
* To register management frame of specified type and subtype.
*
* frameType - type of the frame that needs to be passed to HDD.
* matchData - data which needs to be matched before passing frame
* to HDD.
* matchDataLen - Length of matched data.
* Return QDF_STATUS
*/
QDF_STATUS sme_register_mgmt_frame(tHalHandle hHal, uint8_t sessionId,
uint16_t frameType, uint8_t *matchData,
uint16_t matchLen)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
tSirRegisterMgmtFrame *pMsg;
uint16_t len;
struct csr_roam_session *pSession = CSR_GET_SESSION(pMac,
sessionId);
if (!CSR_IS_SESSION_ANY(sessionId) && !pSession) {
sme_err("Session %d not found", sessionId);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
if (!CSR_IS_SESSION_ANY(sessionId) &&
!pSession->sessionActive) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s Invalid Sessionid", __func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
len = sizeof(tSirRegisterMgmtFrame) + matchLen;
pMsg = qdf_mem_malloc(len);
if (NULL == pMsg)
status = QDF_STATUS_E_NOMEM;
else {
pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ;
pMsg->length = len;
pMsg->sessionId = sessionId;
pMsg->registerFrame = true;
pMsg->frameType = frameType;
pMsg->matchLen = matchLen;
qdf_mem_copy(pMsg->matchData, matchData, matchLen);
status = umac_send_mb_message_to_mac(pMsg);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_DeregisterMgtFrame() -
* To De-register management frame of specified type and subtype.
*
* frameType - type of the frame that needs to be passed to HDD.
* matchData - data which needs to be matched before passing frame
* to HDD.
* matchDataLen - Length of matched data.
* Return QDF_STATUS
*/
QDF_STATUS sme_deregister_mgmt_frame(tHalHandle hHal, uint8_t sessionId,
uint16_t frameType, uint8_t *matchData,
uint16_t matchLen)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_DEREGISTER_MGMTFR, sessionId,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
tSirRegisterMgmtFrame *pMsg;
uint16_t len;
struct csr_roam_session *pSession = CSR_GET_SESSION(pMac,
sessionId);
if (!CSR_IS_SESSION_ANY(sessionId) && !pSession) {
sme_err("Session %d not found", sessionId);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
if (!CSR_IS_SESSION_ANY(sessionId) &&
!pSession->sessionActive) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s Invalid Sessionid", __func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
len = sizeof(tSirRegisterMgmtFrame) + matchLen;
pMsg = qdf_mem_malloc(len);
if (NULL == pMsg)
status = QDF_STATUS_E_NOMEM;
else {
pMsg->messageType = eWNI_SME_REGISTER_MGMT_FRAME_REQ;
pMsg->length = len;
pMsg->registerFrame = false;
pMsg->frameType = frameType;
pMsg->matchLen = matchLen;
qdf_mem_copy(pMsg->matchData, matchData, matchLen);
status = umac_send_mb_message_to_mac(pMsg);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_prepare_mgmt_tx() - Prepares mgmt frame
* @hal: The handle returned by mac_open
* @session_id: session id
* @buf: pointer to frame
* @len: frame length
*
* Return: QDF_STATUS
*/
static QDF_STATUS sme_prepare_mgmt_tx(tHalHandle hal, uint8_t session_id,
const uint8_t *buf, uint32_t len)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct sir_mgmt_msg *msg;
uint16_t msg_len;
struct scheduler_msg sch_msg = {0};
sme_debug("prepares auth frame");
msg_len = sizeof(*msg) + len;
msg = qdf_mem_malloc(msg_len);
if (msg == NULL) {
status = QDF_STATUS_E_NOMEM;
} else {
msg->type = eWNI_SME_SEND_MGMT_FRAME_TX;
msg->msg_len = msg_len;
msg->session_id = session_id;
msg->data = (uint8_t *)msg + sizeof(*msg);
qdf_mem_copy(msg->data, buf, len);
sch_msg.type = eWNI_SME_SEND_MGMT_FRAME_TX;
sch_msg.bodyptr = msg;
status = scheduler_post_msg(QDF_MODULE_ID_PE, &sch_msg);
}
return status;
}
QDF_STATUS sme_send_mgmt_tx(tHalHandle hal, uint8_t session_id,
const uint8_t *buf, uint32_t len)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SEND_MGMT_TX, session_id, 0));
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = sme_prepare_mgmt_tx(hal, session_id, buf, len);
sme_release_global_lock(&mac->sme);
}
return status;
}
#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
/**
* sme_configure_ext_wow() - configure Extr WoW
* @hHal - The handle returned by mac_open.
* @wlanExtParams - Depicts the wlan Ext params.
* @callback - ext_wow callback to be registered.
* @callback_context - ext_wow callback context
*
* SME will pass this request to lower mac to configure Extr WoW
* Return: QDF_STATUS
*/
QDF_STATUS sme_configure_ext_wow(tHalHandle hHal,
tpSirExtWoWParams wlanExtParams,
csr_readyToExtWoWCallback callback,
void *callback_context)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tpSirExtWoWParams MsgPtr = qdf_mem_malloc(sizeof(*MsgPtr));
if (!MsgPtr)
return QDF_STATUS_E_NOMEM;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CONFIG_EXTWOW, NO_SESSION, 0));
pMac->readyToExtWoWCallback = callback;
pMac->readyToExtWoWContext = callback_context;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* serialize the req through MC thread */
qdf_mem_copy(MsgPtr, wlanExtParams, sizeof(*MsgPtr));
message.bodyptr = MsgPtr;
message.type = WMA_WLAN_EXT_WOW;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
pMac->readyToExtWoWCallback = NULL;
pMac->readyToExtWoWContext = NULL;
qdf_mem_free(MsgPtr);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
} else {
pMac->readyToExtWoWCallback = NULL;
pMac->readyToExtWoWContext = NULL;
qdf_mem_free(MsgPtr);
}
return status;
}
/*
* sme_configure_app_type1_params() -
* SME will pass this request to lower mac to configure Indoor WoW parameters.
*
* hHal - The handle returned by mac_open.
* wlanAppType1Params- Depicts the wlan App Type 1(Indoor) params
* Return QDF_STATUS
*/
QDF_STATUS sme_configure_app_type1_params(tHalHandle hHal,
tpSirAppType1Params wlanAppType1Params)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tpSirAppType1Params MsgPtr = qdf_mem_malloc(sizeof(*MsgPtr));
if (!MsgPtr)
return QDF_STATUS_E_NOMEM;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE1, NO_SESSION,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* serialize the req through MC thread */
qdf_mem_copy(MsgPtr, wlanAppType1Params, sizeof(*MsgPtr));
message.bodyptr = MsgPtr;
message.type = WMA_WLAN_SET_APP_TYPE1_PARAMS;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
qdf_mem_free(MsgPtr);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
} else {
qdf_mem_free(MsgPtr);
}
return status;
}
/*
* sme_configure_app_type2_params() -
* SME will pass this request to lower mac to configure Indoor WoW parameters.
*
* hHal - The handle returned by mac_open.
* wlanAppType2Params- Depicts the wlan App Type 2 (Outdoor) params
* Return QDF_STATUS
*/
QDF_STATUS sme_configure_app_type2_params(tHalHandle hHal,
tpSirAppType2Params wlanAppType2Params)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tpSirAppType2Params MsgPtr = qdf_mem_malloc(sizeof(*MsgPtr));
if (!MsgPtr)
return QDF_STATUS_E_NOMEM;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CONFIG_APP_TYPE2, NO_SESSION,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* serialize the req through MC thread */
qdf_mem_copy(MsgPtr, wlanAppType2Params, sizeof(*MsgPtr));
message.bodyptr = MsgPtr;
message.type = WMA_WLAN_SET_APP_TYPE2_PARAMS;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
qdf_mem_free(MsgPtr);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
} else {
qdf_mem_free(MsgPtr);
}
return status;
}
#endif
/*
* sme_get_infra_session_id
* To get the session ID for infra session, if connected
* This is a synchronous API.
*
* hHal - The handle returned by mac_open.
* sessionid, -1 if infra session is not connected
*/
int8_t sme_get_infra_session_id(tHalHandle hHal)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
int8_t sessionid = -1;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
sessionid = csr_get_infra_session_id(pMac);
sme_release_global_lock(&pMac->sme);
}
return sessionid;
}
/*
* sme_get_infra_operation_channel() -
* To get the operating channel for infra session, if connected
* This is a synchronous API.
*
* hHal - The handle returned by mac_open.
* sessionId - the sessionId returned by sme_open_session.
* Return operating channel, 0 if infra session is not connected
*/
uint8_t sme_get_infra_operation_channel(tHalHandle hHal, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
uint8_t channel = 0;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
channel = csr_get_infra_operation_channel(pMac, sessionId);
sme_release_global_lock(&pMac->sme);
}
return channel;
}
/* This routine will return poerating channel on which other BSS is operating
* to be used for concurrency mode. If other BSS is not up or not connected it
* will return 0
*/
uint8_t sme_get_concurrent_operation_channel(tHalHandle hHal)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
uint8_t channel = 0;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
channel = csr_get_concurrent_operation_channel(pMac);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"%s: Other Concurrent Channel: %d", __func__, channel);
sme_release_global_lock(&pMac->sme);
}
return channel;
}
#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
uint16_t sme_check_concurrent_channel_overlap(tHalHandle hHal, uint16_t sap_ch,
eCsrPhyMode sapPhyMode,
uint8_t cc_switch_mode)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
uint16_t channel = 0;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
channel =
csr_check_concurrent_channel_overlap(pMac, sap_ch,
sapPhyMode,
cc_switch_mode);
sme_release_global_lock(&pMac->sme);
}
return channel;
}
#endif
/**
* sme_set_tsfcb() - Set callback for TSF capture
* @h_hal: Handler return by mac_open
* @cb_fn: Callback function pointer
* @db_ctx: Callback data
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_set_tsfcb(tHalHandle h_hal,
int (*cb_fn)(void *cb_ctx, struct stsf *ptsf), void *cb_ctx)
{
tpAniSirGlobal mac = PMAC_STRUCT(h_hal);
QDF_STATUS status;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.get_tsf_cb = cb_fn;
mac->sme.get_tsf_cxt = cb_ctx;
sme_release_global_lock(&mac->sme);
}
return status;
}
/**
* sme_reset_tsfcb() - Reset callback for TSF capture
* @h_hal: Handler return by mac_open
*
* This function reset the tsf capture callback to SME
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_reset_tsfcb(tHalHandle h_hal)
{
tpAniSirGlobal mac;
QDF_STATUS status;
if (!h_hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("h_hal is not valid"));
return QDF_STATUS_E_INVAL;
}
mac = PMAC_STRUCT(h_hal);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.get_tsf_cb = NULL;
mac->sme.get_tsf_cxt = NULL;
sme_release_global_lock(&mac->sme);
}
return status;
}
#ifdef WLAN_FEATURE_TSF
/*
* sme_set_tsf_gpio() - set gpio pin that be toggled when capture tef
* @h_hal: Handler return by mac_open
* @pinvalue: gpio pin id
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_set_tsf_gpio(tHalHandle h_hal, uint32_t pinvalue)
{
QDF_STATUS status;
struct scheduler_msg tsf_msg = {0};
tpAniSirGlobal mac = PMAC_STRUCT(h_hal);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
tsf_msg.type = WMA_TSF_GPIO_PIN;
tsf_msg.reserved = 0;
tsf_msg.bodyval = pinvalue;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &tsf_msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Unable to post WMA_TSF_GPIO_PIN");
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
}
return status;
}
#endif
QDF_STATUS sme_get_cfg_valid_channels(uint8_t *aValidChannels,
uint32_t *len)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = sme_get_mac_context();
if (NULL == mac_ctx) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid MAC context"));
return QDF_STATUS_E_FAILURE;
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_get_cfg_valid_channels(mac_ctx,
aValidChannels, len);
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
static uint8_t *sme_reg_hint_to_str(const enum country_src src)
{
switch (src) {
case SOURCE_CORE:
return "WORLD MODE";
case SOURCE_DRIVER:
return "BDF file";
case SOURCE_USERSPACE:
return "user-space";
case SOURCE_11D:
return "802.11D IEs in beacons";
default:
return "unknown";
}
}
void sme_set_cc_src(tHalHandle hHal, enum country_src cc_src)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal);
mac_ctx->reg_hint_src = cc_src;
sme_debug("Country source is %s",
sme_reg_hint_to_str(cc_src));
}
/**
* sme_handle_generic_change_country_code() - handles country ch req
* @mac_ctx: mac global context
* @msg: request msg packet
*
* If Supplicant country code is priority than 11d is disabled.
* If 11D is enabled, we update the country code after every scan.
* Hence when Supplicant country code is priority, we don't need 11D info.
* Country code from Supplicant is set as current country code.
*
* Return: status of operation
*/
static QDF_STATUS
sme_handle_generic_change_country_code(tpAniSirGlobal mac_ctx,
void *pMsgBuf)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
v_REGDOMAIN_t reg_domain_id = 0;
bool user_ctry_priority =
mac_ctx->roam.configParam.fSupplicantCountryCodeHasPriority;
tAniGenericChangeCountryCodeReq *msg = pMsgBuf;
if (SOURCE_11D != mac_ctx->reg_hint_src) {
if (SOURCE_DRIVER != mac_ctx->reg_hint_src) {
if (user_ctry_priority)
mac_ctx->roam.configParam.Is11dSupportEnabled =
false;
else {
if (mac_ctx->roam.configParam.
Is11dSupportEnabled &&
mac_ctx->scan.countryCode11d[0] != 0) {
sme_debug("restore 11d");
status =
csr_get_regulatory_domain_for_country(
mac_ctx,
mac_ctx->scan.countryCode11d,
&reg_domain_id,
SOURCE_11D);
return QDF_STATUS_E_FAILURE;
}
}
}
} else {
/* if kernel gets invalid country code; it
* resets the country code to world
*/
if (('0' != msg->countryCode[0]) ||
('0' != msg->countryCode[1]))
qdf_mem_copy(mac_ctx->scan.countryCode11d,
msg->countryCode,
WNI_CFG_COUNTRY_CODE_LEN);
}
qdf_mem_copy(mac_ctx->scan.countryCodeCurrent,
msg->countryCode,
WNI_CFG_COUNTRY_CODE_LEN);
/* get the channels based on new cc */
status = csr_get_channel_and_power_list(mac_ctx);
if (status != QDF_STATUS_SUCCESS) {
sme_err("fail to get Channels");
return status;
}
/* reset info based on new cc, and we are done */
csr_apply_channel_power_info_wrapper(mac_ctx);
csr_scan_filter_results(mac_ctx);
/* scans after the country is set by User hints or
* Country IE
*/
mac_ctx->scan.curScanType = eSIR_ACTIVE_SCAN;
mac_ctx->reg_hint_src = SOURCE_UNKNOWN;
sme_disconnect_connected_sessions(mac_ctx);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS sme_update_channel_list(tHalHandle hal)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
QDF_STATUS status;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Update umac channel (enable/disable) from cds channels */
status = csr_get_channel_and_power_list(mac_ctx);
if (status != QDF_STATUS_SUCCESS) {
sme_err("fail to get Channels");
sme_release_global_lock(&mac_ctx->sme);
return status;
}
csr_apply_channel_power_info_wrapper(mac_ctx);
csr_scan_filter_results(mac_ctx);
sme_disconnect_connected_sessions(mac_ctx);
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
static bool
sme_search_in_base_ch_lst(tpAniSirGlobal mac_ctx, uint8_t curr_ch)
{
uint8_t i;
struct csr_channel *ch_lst_info;
ch_lst_info = &mac_ctx->scan.base_channels;
for (i = 0; i < ch_lst_info->numChannels; i++) {
if (ch_lst_info->channelList[i] == curr_ch)
return true;
}
return false;
}
/**
* sme_disconnect_connected_sessions() - Disconnect STA and P2P client session
* if channel is not supported
* @mac_ctx: mac global context
*
* If new country code does not support the channel on which STA/P2P client
* is connetced, it sends the disconnect to the AP/P2P GO
*
* Return: void
*/
static void sme_disconnect_connected_sessions(tpAniSirGlobal mac_ctx)
{
uint8_t session_id, found = false;
uint8_t curr_ch;
for (session_id = 0; session_id < CSR_ROAM_SESSION_MAX; session_id++) {
if (!csr_is_session_client_and_connected(mac_ctx, session_id))
continue;
found = false;
/* Session is connected.Check the channel */
curr_ch = csr_get_infra_operation_channel(mac_ctx,
session_id);
sme_debug("Current Operating channel : %d, session :%d",
curr_ch, session_id);
found = sme_search_in_base_ch_lst(mac_ctx, curr_ch);
if (!found) {
sme_debug("Disconnect Session: %d", session_id);
csr_roam_disconnect(mac_ctx, session_id,
eCSR_DISCONNECT_REASON_UNSPECIFIED);
}
}
}
#ifdef WLAN_FEATURE_PACKET_FILTERING
QDF_STATUS sme_8023_multicast_list(tHalHandle hHal, uint8_t sessionId,
tpSirRcvFltMcAddrList pMulticastAddrs)
{
tpSirRcvFltMcAddrList request_buf;
struct scheduler_msg msg = {0};
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct csr_roam_session *pSession = NULL;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: ulMulticastAddrCnt: %d, multicastAddr[0]: %pK", __func__,
pMulticastAddrs->ulMulticastAddrCnt,
pMulticastAddrs->multicastAddr[0].bytes);
/* Find the connected Infra / P2P_client connected session */
pSession = CSR_GET_SESSION(pMac, sessionId);
if (!CSR_IS_SESSION_VALID(pMac, sessionId) ||
(!csr_is_conn_state_infra(pMac, sessionId) &&
!csr_is_ndi_started(pMac, sessionId))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Unable to find the session Id: %d", __func__,
sessionId);
return QDF_STATUS_E_FAILURE;
}
request_buf = qdf_mem_malloc(sizeof(tSirRcvFltMcAddrList));
if (NULL == request_buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for 8023 Multicast List request",
__func__);
return QDF_STATUS_E_NOMEM;
}
if (!csr_is_conn_state_connected_infra(pMac, sessionId) &&
!csr_is_ndi_started(pMac, sessionId)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Request ignored, session %d is not connected or started",
__func__, sessionId);
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
qdf_mem_copy(request_buf, pMulticastAddrs,
sizeof(tSirRcvFltMcAddrList));
qdf_copy_macaddr(&request_buf->self_macaddr, &pSession->selfMacAddr);
qdf_copy_macaddr(&request_buf->bssid,
&pSession->connectedProfile.bssid);
msg.type = WMA_8023_MULTICAST_LIST_REQ;
msg.reserved = 0;
msg.bodyptr = request_buf;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
sessionId, msg.type));
if (QDF_STATUS_SUCCESS != scheduler_post_msg(QDF_MODULE_ID_WMA,
&msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WMA_8023_MULTICAST_LIST message to WMA",
__func__);
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_FEATURE_PACKET_FILTERING */
/*
* sme_is_channel_valid() -
* To check if the channel is valid for currently established domain
* This is a synchronous API.
*
* hHal - The handle returned by mac_open.
* channel - channel to verify
* Return true/false, true if channel is valid
*/
bool sme_is_channel_valid(tHalHandle hHal, uint8_t channel)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
bool valid = false;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
valid = csr_roam_is_channel_valid(pMac, channel);
sme_release_global_lock(&pMac->sme);
}
return valid;
}
/*
* sme_set_freq_band() -
* Used to set frequency band.
*
* hHal
* sessionId - Session Identifier
* band value to be configured
* Return QDF_STATUS
*/
QDF_STATUS sme_set_freq_band(tHalHandle hHal, uint8_t sessionId,
enum band_info eBand)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_set_band(hHal, sessionId, eBand);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_freq_band() -
* Used to get the current band settings.
*
* hHal
* pBand pointer to hold band value
* Return QDF_STATUS
*/
QDF_STATUS sme_get_freq_band(tHalHandle hHal, enum band_info *pBand)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
*pBand = csr_get_current_band(hHal);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_max_tx_power_per_band() -
* Set the Maximum Transmit Power specific to band dynamically.
* Note: this setting will not persist over reboots.
*
* band
* power to set in dB
* Return QDF_STATUS
*/
QDF_STATUS sme_set_max_tx_power_per_band(enum band_info band, int8_t dB)
{
struct scheduler_msg msg = {0};
tpMaxTxPowerPerBandParams pMaxTxPowerPerBandParams = NULL;
pMaxTxPowerPerBandParams =
qdf_mem_malloc(sizeof(tMaxTxPowerPerBandParams));
if (NULL == pMaxTxPowerPerBandParams) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s:Not able to allocate memory for pMaxTxPowerPerBandParams",
__func__);
return QDF_STATUS_E_NOMEM;
}
pMaxTxPowerPerBandParams->power = dB;
pMaxTxPowerPerBandParams->bandInfo = band;
msg.type = WMA_SET_MAX_TX_POWER_PER_BAND_REQ;
msg.reserved = 0;
msg.bodyptr = pMaxTxPowerPerBandParams;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, msg.type));
if (QDF_STATUS_SUCCESS != scheduler_post_msg(QDF_MODULE_ID_WMA,
&msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s:Not able to post WMA_SET_MAX_TX_POWER_PER_BAND_REQ",
__func__);
qdf_mem_free(pMaxTxPowerPerBandParams);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/*
* sme_set_max_tx_power() -
* Set the Maximum Transmit Power dynamically. Note: this setting will
* not persist over reboots.
*
* hHal
* pBssid BSSID to set the power cap for
* pBssid pSelfMacAddress self MAC Address
* pBssid power to set in dB
* Return QDF_STATUS
*/
QDF_STATUS sme_set_max_tx_power(tHalHandle hHal, struct qdf_mac_addr pBssid,
struct qdf_mac_addr pSelfMacAddress, int8_t dB)
{
struct scheduler_msg msg = {0};
tpMaxTxPowerParams pMaxTxParams = NULL;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SET_MAXTXPOW, NO_SESSION, 0));
pMaxTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams));
if (NULL == pMaxTxParams) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for pMaxTxParams",
__func__);
return QDF_STATUS_E_NOMEM;
}
qdf_copy_macaddr(&pMaxTxParams->bssId, &pBssid);
qdf_copy_macaddr(&pMaxTxParams->selfStaMacAddr, &pSelfMacAddress);
pMaxTxParams->power = dB;
msg.type = WMA_SET_MAX_TX_POWER_REQ;
msg.reserved = 0;
msg.bodyptr = pMaxTxParams;
if (QDF_STATUS_SUCCESS != scheduler_post_msg(QDF_MODULE_ID_WMA,
&msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WMA_SET_MAX_TX_POWER_REQ message to WMA",
__func__);
qdf_mem_free(pMaxTxParams);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/*
* sme_set_custom_mac_addr() -
* Set the customer Mac Address.
*
* customMacAddr customer MAC Address
* Return QDF_STATUS
*/
QDF_STATUS sme_set_custom_mac_addr(tSirMacAddr customMacAddr)
{
struct scheduler_msg msg = {0};
tSirMacAddr *pBaseMacAddr;
pBaseMacAddr = qdf_mem_malloc(sizeof(tSirMacAddr));
if (NULL == pBaseMacAddr) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to allocate memory for pBaseMacAddr"));
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(*pBaseMacAddr, customMacAddr, sizeof(tSirMacAddr));
msg.type = SIR_HAL_SET_BASE_MACADDR_IND;
msg.reserved = 0;
msg.bodyptr = pBaseMacAddr;
if (QDF_STATUS_SUCCESS != scheduler_post_msg(QDF_MODULE_ID_WMA,
&msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Not able to post SIR_HAL_SET_BASE_MACADDR_IND message to WMA");
qdf_mem_free(pBaseMacAddr);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/*
* sme_set_tx_power() -
* Set Transmit Power dynamically.
*
* hHal
* sessionId Target Session ID
* BSSID
* dev_mode dev_mode such as station, P2PGO, SAP
* dBm power to set
* Return QDF_STATUS
*/
QDF_STATUS sme_set_tx_power(tHalHandle hHal, uint8_t sessionId,
struct qdf_mac_addr pBSSId,
enum QDF_OPMODE dev_mode, int dBm)
{
struct scheduler_msg msg = {0};
tpMaxTxPowerParams pTxParams = NULL;
int8_t power = (int8_t) dBm;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SET_TXPOW, sessionId, 0));
/* make sure there is no overflow */
if ((int)power != dBm) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: error, invalid power = %d", __func__, dBm);
return QDF_STATUS_E_FAILURE;
}
pTxParams = qdf_mem_malloc(sizeof(tMaxTxPowerParams));
if (NULL == pTxParams) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for pTxParams",
__func__);
return QDF_STATUS_E_NOMEM;
}
qdf_copy_macaddr(&pTxParams->bssId, &pBSSId);
pTxParams->power = power; /* unit is dBm */
pTxParams->dev_mode = dev_mode;
msg.type = WMA_SET_TX_POWER_REQ;
msg.reserved = 0;
msg.bodyptr = pTxParams;
if (QDF_STATUS_SUCCESS != scheduler_post_msg(QDF_MODULE_ID_WMA,
&msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: failed to post WMA_SET_TX_POWER_REQ to WMA",
__func__);
qdf_mem_free(pTxParams);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS sme_update_fils_setting(tHalHandle hal, uint8_t session_id,
uint8_t param_val)
{
QDF_STATUS status;
tpAniSirGlobal pMac = PMAC_STRUCT(hal);
pMac->roam.configParam.is_fils_enabled = !param_val;
pMac->roam.configParam.enable_bcast_probe_rsp = !param_val;
status = wma_cli_set_command((int)session_id,
(int)WMI_VDEV_PARAM_ENABLE_BCAST_PROBE_RESPONSE,
!param_val, VDEV_CMD);
if (status)
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Failed to set enable bcast probe setting",
__func__);
return status;
}
QDF_STATUS sme_update_session_param(tHalHandle hal, uint8_t session_id,
uint32_t param_type, uint32_t param_val)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
uint16_t len;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
struct sir_update_session_param *msg;
struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx,
session_id);
if (!session) {
sme_err("Session: %d not found", session_id);
sme_release_global_lock(&mac_ctx->sme);
return status;
}
if (param_type == SIR_PARAM_IGNORE_ASSOC_DISALLOWED)
mac_ctx->ignore_assoc_disallowed = param_val;
if (!session->sessionActive)
QDF_ASSERT(0);
len = sizeof(*msg);
msg = qdf_mem_malloc(len);
if (!msg)
status = QDF_STATUS_E_NOMEM;
else {
msg->message_type = eWNI_SME_SESSION_UPDATE_PARAM;
msg->length = len;
msg->session_id = session_id;
msg->param_type = param_type;
msg->param_val = param_val;
status = umac_send_mb_message_to_mac(msg);
}
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
/*
* sme_set_tm_level() -
* Set Thermal Mitigation Level to RIVA
*
* hHal - The handle returned by mac_open.
* newTMLevel - new Thermal Mitigation Level
* tmMode - Thermal Mitigation handle mode, default 0
* Return QDF_STATUS
*/
QDF_STATUS sme_set_tm_level(tHalHandle hHal, uint16_t newTMLevel, uint16_t
tmMode)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tAniSetTmLevelReq *setTmLevelReq = NULL;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SET_TMLEVEL, NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
setTmLevelReq =
(tAniSetTmLevelReq *)
qdf_mem_malloc(sizeof(tAniSetTmLevelReq));
if (NULL == setTmLevelReq) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for sme_set_tm_level",
__func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
setTmLevelReq->tmMode = tmMode;
setTmLevelReq->newTmLevel = newTMLevel;
/* serialize the req through MC thread */
message.bodyptr = setTmLevelReq;
message.type = WMA_SET_TM_LEVEL_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post Set TM Level MSG fail", __func__);
qdf_mem_free(setTmLevelReq);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_feature_caps_exchange() - SME interface to exchange capabilities between
* Host and FW.
*
* hHal - HAL handle for device
* Return NONE
*/
void sme_feature_caps_exchange(tHalHandle hHal)
{
MTRACE(qdf_trace
(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_HDD_CAPS_EXCH,
NO_SESSION, 0));
}
/*
* sme_disable_feature_capablity() - SME interface to disable Active mode
* offload capablity in Host.
*
* hHal - HAL handle for device
* Return NONE
*/
void sme_disable_feature_capablity(uint8_t feature_index)
{
}
/*
* sme_reset_power_values_for5_g
* Reset the power values for 5G band with default power values.
*
* hHal - HAL handle for device
* Return NONE
*/
void sme_reset_power_values_for5_g(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_RESET_PW5G, NO_SESSION, 0));
csr_save_channel_power_for_band(pMac, true);
/* Store the channel+power info in the global place: Cfg */
csr_apply_power2_current(pMac);
}
/*
* sme_update_roam_prefer5_g_hz() -
* Enable/disable Roam prefer 5G runtime option
* This function is called through dynamic setConfig callback function
* to configure the Roam prefer 5G runtime option
*
* hHal - HAL handle for device
* nRoamPrefer5GHz Enable/Disable Roam prefer 5G runtime option
* Return Success or failure
*/
QDF_STATUS sme_update_roam_prefer5_g_hz(tHalHandle hHal,
bool nRoamPrefer5GHz)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_UPDATE_RP5G, NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: gRoamPrefer5GHz is changed from %d to %d",
__func__, pMac->roam.configParam.nRoamPrefer5GHz,
nRoamPrefer5GHz);
pMac->roam.configParam.nRoamPrefer5GHz = nRoamPrefer5GHz;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_roam_intra_band() -
* enable/disable Intra band roaming
* This function is called through dynamic setConfig callback function
* to configure the intra band roaming
* hHal - HAL handle for device
* nRoamIntraBand Enable/Disable Intra band roaming
* Return Success or failure
*/
QDF_STATUS sme_set_roam_intra_band(tHalHandle hHal, const bool nRoamIntraBand)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SET_ROAMIBAND, NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: gRoamIntraBand is changed from %d to %d",
__func__, pMac->roam.configParam.nRoamIntraBand,
nRoamIntraBand);
pMac->roam.configParam.nRoamIntraBand = nRoamIntraBand;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_update_roam_scan_n_probes() -
* Function to update roam scan N probes
* This function is called through dynamic setConfig callback function
* to update roam scan N probes
* hHal - HAL handle for device
* sessionId - Session Identifier
* nProbes number of probe requests to be sent out
* Return Success or failure
*/
QDF_STATUS sme_update_roam_scan_n_probes(tHalHandle hHal, uint8_t sessionId,
const uint8_t nProbes)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_N_PROBES,
NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: gRoamScanNProbes is changed from %d to %d",
__func__, pMac->roam.configParam.nProbes, nProbes);
pMac->roam.configParam.nProbes = nProbes;
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_NPROBES_CHANGED);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_update_roam_scan_home_away_time() -
* Function to update roam scan Home away time
* This function is called through dynamic setConfig callback function
* to update roam scan home away time
*
* hHal - HAL handle for device
* sessionId - Session Identifier
* nRoamScanAwayTime Scan home away time
* bSendOffloadCmd If true then send offload command to firmware
* If false then command is not sent to firmware
* Return Success or failure
*/
QDF_STATUS sme_update_roam_scan_home_away_time(tHalHandle hHal,
uint8_t sessionId,
const uint16_t nRoamScanHomeAwayTime,
const bool bSendOffloadCmd)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_UPDATE_ROAM_SCAN_HOME_AWAY_TIME,
NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: gRoamScanHomeAwayTime is changed from %d to %d",
__func__,
pMac->roam.configParam.nRoamScanHomeAwayTime,
nRoamScanHomeAwayTime);
pMac->roam.configParam.nRoamScanHomeAwayTime =
nRoamScanHomeAwayTime;
if (pMac->roam.configParam.isRoamOffloadScanEnabled &&
bSendOffloadCmd) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_HOME_AWAY_TIME_CHANGED);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_ext_change_channel()- function to post send ECSA
* action frame to csr.
* @hHal: Hal context
* @channel: new channel to switch
* @session_id: senssion it should be sent on.
*
* This function is called to post ECSA frame to csr.
*
* Return: success if msg is sent else return failure
*/
QDF_STATUS sme_ext_change_channel(tHalHandle h_hal, uint32_t channel,
uint8_t session_id)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(h_hal);
uint8_t channel_state;
sme_err("Set Channel: %d", channel);
channel_state =
wlan_reg_get_channel_state(mac_ctx->pdev, channel);
if (CHANNEL_STATE_DISABLE == channel_state) {
sme_err("Invalid channel: %d", channel);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
/* update the channel list to the firmware */
status = csr_send_ext_change_channel(mac_ctx,
channel, session_id);
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
/*
* sme_get_roam_intra_band() -
* get Intra band roaming
*
* hHal - HAL handle for device
* Return Success or failure
*/
bool sme_get_roam_intra_band(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_GET_ROAMIBAND, NO_SESSION, 0));
return pMac->roam.configParam.nRoamIntraBand;
}
/*
* sme_get_roam_scan_n_probes() -
* get N Probes
*
* hHal - HAL handle for device
* Return Success or failure
*/
uint8_t sme_get_roam_scan_n_probes(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.nProbes;
}
/*
* sme_get_roam_scan_home_away_time() -
* get Roam scan home away time
*
* hHal - HAL handle for device
* Return Success or failure
*/
uint16_t sme_get_roam_scan_home_away_time(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.nRoamScanHomeAwayTime;
}
/*
* sme_update_roam_rssi_diff() -
* Update RoamRssiDiff
* This function is called through dynamic setConfig callback function
* to configure RoamRssiDiff
* Usage: adb shell iwpriv wlan0 setConfig RoamRssiDiff=[0 .. 125]
*
* hHal - HAL handle for device
* sessionId - Session Identifier
* RoamRssiDiff - minimum rssi difference between potential
* candidate and current AP.
* Return Success or failure
*/
QDF_STATUS sme_update_roam_rssi_diff(tHalHandle hHal, uint8_t sessionId,
uint8_t RoamRssiDiff)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set roam rssi diff to %d - old value is %d - roam state is %s",
RoamRssiDiff,
pMac->roam.configParam.RoamRssiDiff,
mac_trace_get_neighbour_roam_state(pMac->roam.
neighborRoamInfo
[sessionId].
neighborRoamState));
pMac->roam.configParam.RoamRssiDiff = RoamRssiDiff;
if (pMac->roam.configParam.isRoamOffloadScanEnabled)
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_RSSI_DIFF_CHANGED);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#ifdef WLAN_FEATURE_FILS_SK
QDF_STATUS sme_update_fils_config(tHalHandle hal, uint8_t session_id,
struct csr_roam_profile *src_profile)
{
tpAniSirGlobal mac = PMAC_STRUCT(hal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpCsrNeighborRoamControlInfo neighbor_roam_info =
&mac->roam.neighborRoamInfo[session_id];
if (session_id >= CSR_ROAM_SESSION_MAX) {
sme_err("Invalid sme session id: %d", session_id);
return QDF_STATUS_E_INVAL;
}
if (!src_profile) {
sme_err("src roam profile NULL");
return QDF_STATUS_E_INVAL;
}
if (!mac->roam.configParam.isFastRoamIniFeatureEnabled ||
(neighbor_roam_info->neighborRoamState !=
eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)) {
sme_info("Fast roam is disabled or not connected(%d)",
neighbor_roam_info->neighborRoamState);
return QDF_STATUS_E_PERM;
}
csr_update_fils_config(mac, session_id, src_profile);
if (csr_roamIsRoamOffloadEnabled(mac)) {
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
sme_debug("Updating fils config to fw");
csr_roam_offload_scan(mac, session_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_FILS_PARAMS_CHANGED);
sme_release_global_lock(&mac->sme);
} else {
sme_err("Failed to acquire SME lock");
}
} else {
sme_info("LFR3 not enabled");
return QDF_STATUS_E_INVAL;
}
return status;
}
void sme_send_hlp_ie_info(tHalHandle hal, uint8_t session_id,
struct csr_roam_profile *profile, uint32_t if_addr)
{
int i;
struct scheduler_msg msg;
QDF_STATUS status;
struct hlp_params *params;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct csr_roam_session *session = CSR_GET_SESSION(mac, session_id);
tpCsrNeighborRoamControlInfo neighbor_roam_info =
&mac->roam.neighborRoamInfo[session_id];
if (!session) {
sme_err("session NULL");
return;
}
if (!mac->roam.configParam.isFastRoamIniFeatureEnabled ||
(neighbor_roam_info->neighborRoamState !=
eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)) {
sme_debug("Fast roam is disabled or not connected(%d)",
neighbor_roam_info->neighborRoamState);
return;
}
params = qdf_mem_malloc(sizeof(*params));
if (!params) {
sme_err("Mem alloc for HLP IE fails");
return;
}
if ((profile->hlp_ie_len +
SIR_IPV4_ADDR_LEN) > FILS_MAX_HLP_DATA_LEN) {
sme_err("HLP IE len exceeds %d",
profile->hlp_ie_len);
qdf_mem_free(params);
return;
}
params->vdev_id = session_id;
params->hlp_ie_len = profile->hlp_ie_len + SIR_IPV4_ADDR_LEN;
for (i = 0; i < SIR_IPV4_ADDR_LEN; i++)
params->hlp_ie[i] = (if_addr >> (i * 8)) & 0xFF;
qdf_mem_copy(params->hlp_ie + SIR_IPV4_ADDR_LEN,
profile->hlp_ie, profile->hlp_ie_len);
msg.type = SIR_HAL_HLP_IE_INFO;
msg.reserved = 0;
msg.bodyptr = params;
status = sme_acquire_global_lock(&mac->sme);
if (status != QDF_STATUS_SUCCESS) {
sme_err("sme lock acquire fails");
qdf_mem_free(params);
return;
}
if (!QDF_IS_STATUS_SUCCESS
(scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
sme_err("Not able to post WMA_HLP_IE_INFO message to HAL");
sme_release_global_lock(&mac->sme);
qdf_mem_free(params);
return;
}
sme_release_global_lock(&mac->sme);
}
void sme_free_join_rsp_fils_params(struct csr_roam_info *roam_info)
{
struct fils_join_rsp_params *roam_fils_params;
if (!roam_info) {
sme_err("FILS Roam Info NULL");
return;
}
roam_fils_params = roam_info->fils_join_rsp;
if (!roam_fils_params) {
sme_err("FILS Roam Param NULL");
return;
}
if (roam_fils_params->fils_pmk)
qdf_mem_free(roam_fils_params->fils_pmk);
qdf_mem_free(roam_fils_params);
roam_info->fils_join_rsp = NULL;
}
#else
inline void sme_send_hlp_ie_info(tHalHandle hal, uint8_t session_id,
struct csr_roam_profile *profile, uint32_t if_addr)
{}
#endif
/*
* sme_update_fast_transition_enabled() - enable/disable Fast Transition
* support at runtime
* It is used at in the REG_DYNAMIC_VARIABLE macro definition of
* isFastTransitionEnabled.
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* Return QDF_STATUS_SUCCESS - SME update isFastTransitionEnabled config
* successfully.
* Other status means SME is failed to update isFastTransitionEnabled.
*/
QDF_STATUS sme_update_fast_transition_enabled(tHalHandle hHal,
bool isFastTransitionEnabled)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_UPDATE_FTENABLED, NO_SESSION,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: FastTransitionEnabled is changed from %d to %d",
__func__,
pMac->roam.configParam.isFastTransitionEnabled,
isFastTransitionEnabled);
pMac->roam.configParam.isFastTransitionEnabled =
isFastTransitionEnabled;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_update_wes_mode() -
* Update WES Mode
* This function is called through dynamic setConfig callback function
* to configure isWESModeEnabled
*
* hHal - HAL handle for device
* isWESModeEnabled - WES mode
* sessionId - Session Identifier
* Return QDF_STATUS_SUCCESS - SME update isWESModeEnabled config successfully.
* Other status means SME is failed to update isWESModeEnabled.
*/
QDF_STATUS sme_update_wes_mode(tHalHandle hHal, bool isWESModeEnabled,
uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set WES Mode to %d - old value is %d - roam state is %s",
isWESModeEnabled,
pMac->roam.configParam.isWESModeEnabled,
mac_trace_get_neighbour_roam_state(pMac->roam.
neighborRoamInfo
[sessionId].
neighborRoamState));
pMac->roam.configParam.isWESModeEnabled = isWESModeEnabled;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_roam_scan_control() -
* Set roam scan control
* This function is called to set roam scan control
* if roam scan control is set to 0, roaming scan cache is cleared
* any value other than 0 is treated as invalid value
* hHal - HAL handle for device
* sessionId - Session Identifier
* Return QDF_STATUS_SUCCESS - SME update config successfully.
* Other status means SME failure to update
*/
QDF_STATUS sme_set_roam_scan_control(tHalHandle hHal, uint8_t sessionId,
bool roamScanControl)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SET_SCANCTRL, NO_SESSION, 0));
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set roam scan control to %d - old value is %d - roam state is %s",
roamScanControl,
pMac->roam.configParam.nRoamScanControl,
mac_trace_get_neighbour_roam_state(pMac->roam.
neighborRoamInfo
[sessionId].
neighborRoamState));
pMac->roam.configParam.nRoamScanControl = roamScanControl;
if (0 == roamScanControl) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully cleared roam scan cache");
csr_flush_cfg_bg_scan_roam_channel_list(pMac,
sessionId);
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_FLUSH_CHANNEL_LIST);
}
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_update_is_fast_roam_ini_feature_enabled() - enable/disable LFR
* support at runtime
* It is used at in the REG_DYNAMIC_VARIABLE macro definition of
* isFastRoamIniFeatureEnabled.
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return QDF_STATUS_SUCCESS - SME update isFastRoamIniFeatureEnabled config
* successfully.
* Other status means SME is failed to update isFastRoamIniFeatureEnabled.
*/
QDF_STATUS sme_update_is_fast_roam_ini_feature_enabled(tHalHandle hHal,
uint8_t sessionId, const bool isFastRoamIniFeatureEnabled)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (pMac->roam.configParam.isFastRoamIniFeatureEnabled ==
isFastRoamIniFeatureEnabled) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: FastRoam is already enabled or disabled, nothing to do (returning) old(%d) new(%d)",
__func__,
pMac->roam.configParam.isFastRoamIniFeatureEnabled,
isFastRoamIniFeatureEnabled);
return QDF_STATUS_SUCCESS;
}
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: FastRoamEnabled is changed from %d to %d", __func__,
pMac->roam.configParam.isFastRoamIniFeatureEnabled,
isFastRoamIniFeatureEnabled);
pMac->roam.configParam.isFastRoamIniFeatureEnabled =
isFastRoamIniFeatureEnabled;
csr_neighbor_roam_update_fast_roaming_enabled(pMac, sessionId,
isFastRoamIniFeatureEnabled);
return QDF_STATUS_SUCCESS;
}
/**
* sme_config_fast_roaming() - enable/disable LFR support at runtime
* @hal - The handle returned by macOpen.
* @session_id - Session Identifier
* @is_fast_roam_enabled - flag to enable/disable roaming
*
* When Supplicant issues enabled/disable fast roaming on the basis
* of the Bssid modification in network block (e.g. AutoJoin mode N/W block)
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_config_fast_roaming(tHalHandle hal, uint8_t session_id,
const bool is_fast_roam_enabled)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct csr_roam_session *session = CSR_GET_SESSION(mac_ctx, session_id);
QDF_STATUS status;
/*
* supplicant_disabled_roaming flag is set to true in
* wlan_hdd_cfg80211_connect_start when supplicant initiate connect
* request with BSSID. This flag is reset when supplicant sends
* vendor command to enable roaming after association.
*
* This request from wpa_supplicant will be skipped in this function
* if roaming is disabled using driver command or INI and
* supplicant_disabled_roaming flag remains set. So make sure to set
* supplicant_disabled_roaming flag as per wpa_supplicant even if roam
* request from wpa_supplicant ignored.
*/
if (session && session->pCurRoamProfile)
session->pCurRoamProfile->supplicant_disabled_roaming =
!is_fast_roam_enabled;
if (!mac_ctx->roam.configParam.isFastRoamIniFeatureEnabled) {
sme_debug("Fast roam is disabled through ini");
if (!is_fast_roam_enabled)
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
status = csr_neighbor_roam_update_fast_roaming_enabled(mac_ctx,
session_id, is_fast_roam_enabled);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("update fast roaming failed. status: %d", status);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/*
* sme_update_is_mawc_ini_feature_enabled() -
* Enable/disable LFR MAWC support at runtime
* It is used at in the REG_DYNAMIC_VARIABLE macro definition of
* isMAWCIniFeatureEnabled.
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* Return QDF_STATUS_SUCCESS - SME update MAWCEnabled config successfully.
* Other status means SME is failed to update MAWCEnabled.
*/
QDF_STATUS sme_update_is_mawc_ini_feature_enabled(tHalHandle hHal,
const bool MAWCEnabled)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: MAWCEnabled is changed from %d to %d", __func__,
pMac->roam.configParam.csr_mawc_config.mawc_enabled,
MAWCEnabled);
pMac->roam.configParam.csr_mawc_config.mawc_enabled =
MAWCEnabled;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_stop_roaming() - Stop roaming for a given sessionId
* This is a synchronous call
*
* @hHal - The handle returned by mac_open
* @sessionId - Session Identifier
*
* Return QDF_STATUS_SUCCESS on success
* Other status on failure
*/
QDF_STATUS sme_stop_roaming(tHalHandle hal, uint8_t session_id, uint8_t reason)
{
struct scheduler_msg wma_msg = {0};
QDF_STATUS status;
tSirRoamOffloadScanReq *req;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
tpCsrNeighborRoamControlInfo roam_info;
struct csr_roam_session *session;
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sme_err("incorrect session/vdev ID");
return QDF_STATUS_E_INVAL;
}
session = CSR_GET_SESSION(mac_ctx, session_id);
/*
* set the driver_disabled_roaming flag to true even if roaming
* is not enabled on this session so that roam start requests for
* this session can be blocked until driver enables roaming
*/
if (reason == ecsr_driver_disabled && session->pCurRoamProfile &&
session->pCurRoamProfile->csrPersona == QDF_STA_MODE) {
session->pCurRoamProfile->driver_disabled_roaming = true;
sme_debug("driver_disabled_roaming set for session %d",
session_id);
}
roam_info = &mac_ctx->roam.neighborRoamInfo[session_id];
if (!roam_info->b_roam_scan_offload_started) {
sme_debug("Roaming already disabled for session %d", session_id);
return QDF_STATUS_SUCCESS;
}
req = qdf_mem_malloc(sizeof(*req));
if (!req) {
sme_err("failed to allocated memory");
return QDF_STATUS_E_NOMEM;
}
req->Command = ROAM_SCAN_OFFLOAD_STOP;
if ((reason == eCsrForcedDisassoc) || reason == ecsr_driver_disabled)
req->reason = REASON_ROAM_STOP_ALL;
else
req->reason = REASON_SME_ISSUED;
req->sessionId = session_id;
if (csr_neighbor_middle_of_roaming(mac_ctx, session_id))
req->middle_of_roaming = 1;
else
csr_roam_reset_roam_params(mac_ctx);
wma_msg.type = WMA_ROAM_SCAN_OFFLOAD_REQ;
wma_msg.bodyptr = req;
status = wma_post_ctrl_msg(mac_ctx, &wma_msg);
if (QDF_STATUS_SUCCESS != status) {
sme_err("WMA_ROAM_SCAN_OFFLOAD_REQ failed, session_id: %d",
session_id);
qdf_mem_free(req);
return QDF_STATUS_E_FAULT;
}
roam_info->b_roam_scan_offload_started = false;
roam_info->last_sent_cmd = ROAM_SCAN_OFFLOAD_STOP;
return QDF_STATUS_SUCCESS;
}
/*
* sme_start_roaming() - Start roaming for a given sessionId
* This is a synchronous call
*
* hHal - The handle returned by mac_open
* sessionId - Session Identifier
* Return QDF_STATUS_SUCCESS on success
* Other status on failure
*/
QDF_STATUS sme_start_roaming(tHalHandle hHal, uint8_t sessionId, uint8_t reason)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_roam_offload_scan(pMac, sessionId, ROAM_SCAN_OFFLOAD_START,
reason);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_update_enable_fast_roam_in_concurrency() - enable/disable LFR if
* Concurrent session exists
* This is a synchronuous call
*
* hHal - The handle returned by mac_open.
* Return QDF_STATUS_SUCCESS
* Other status means SME is failed
*/
QDF_STATUS sme_update_enable_fast_roam_in_concurrency(tHalHandle hHal,
bool
bFastRoamInConIniFeatureEnabled)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMac->roam.configParam.bFastRoamInConIniFeatureEnabled =
bFastRoamInConIniFeatureEnabled;
if (0 == pMac->roam.configParam.isRoamOffloadScanEnabled) {
pMac->roam.configParam.bFastRoamInConIniFeatureEnabled =
0;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_roam_opportunistic_scan_threshold_diff() -
* Update Opportunistic Scan threshold diff
* This function is called through dynamic setConfig callback function
* to configure nOpportunisticThresholdDiff
*
* hHal - HAL handle for device
* sessionId - Session Identifier
* nOpportunisticThresholdDiff - Opportunistic Scan threshold diff
* Return QDF_STATUS_SUCCESS - SME update nOpportunisticThresholdDiff config
* successfully.
* else SME is failed to update nOpportunisticThresholdDiff.
*/
QDF_STATUS sme_set_roam_opportunistic_scan_threshold_diff(tHalHandle hHal,
uint8_t sessionId,
const uint8_t
nOpportunisticThresholdDiff)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_neighbor_roam_update_config(pMac, sessionId,
nOpportunisticThresholdDiff,
REASON_OPPORTUNISTIC_THRESH_DIFF_CHANGED);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMac->roam.configParam.neighborRoamConfig.
nOpportunisticThresholdDiff =
nOpportunisticThresholdDiff;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_roam_opportunistic_scan_threshold_diff()
* gets Opportunistic Scan threshold diff
* This is a synchronous call
*
* hHal - The handle returned by mac_open
* Return uint8_t - nOpportunisticThresholdDiff
*/
uint8_t sme_get_roam_opportunistic_scan_threshold_diff(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.
nOpportunisticThresholdDiff;
}
/*
* sme_set_roam_rescan_rssi_diff() - Update roam rescan rssi diff
* This function is called through dynamic setConfig callback function
* to configure nRoamRescanRssiDiff
*
* hHal - HAL handle for device
* sessionId - Session Identifier
* nRoamRescanRssiDiff - roam rescan rssi diff
* Return QDF_STATUS_SUCCESS - SME update nRoamRescanRssiDiff config
* successfully.
* else SME is failed to update nRoamRescanRssiDiff.
*/
QDF_STATUS sme_set_roam_rescan_rssi_diff(tHalHandle hHal,
uint8_t sessionId,
const uint8_t nRoamRescanRssiDiff)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_neighbor_roam_update_config(pMac, sessionId,
nRoamRescanRssiDiff,
REASON_ROAM_RESCAN_RSSI_DIFF_CHANGED);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMac->roam.configParam.neighborRoamConfig.
nRoamRescanRssiDiff = nRoamRescanRssiDiff;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_roam_rescan_rssi_diff()
* gets roam rescan rssi diff
* This is a synchronous call
*
* hHal - The handle returned by mac_open
* Return int8_t - nRoamRescanRssiDiff
*/
uint8_t sme_get_roam_rescan_rssi_diff(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff;
}
/*
* sme_set_roam_bmiss_first_bcnt() -
* Update Roam count for first beacon miss
* This function is called through dynamic setConfig callback function
* to configure nRoamBmissFirstBcnt
* hHal - HAL handle for device
* sessionId - Session Identifier
* nRoamBmissFirstBcnt - Roam first bmiss count
* Return QDF_STATUS_SUCCESS - SME update nRoamBmissFirstBcnt
* successfully.
* else SME is failed to update nRoamBmissFirstBcnt
*/
QDF_STATUS sme_set_roam_bmiss_first_bcnt(tHalHandle hHal,
uint8_t sessionId,
const uint8_t nRoamBmissFirstBcnt)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_neighbor_roam_update_config(pMac, sessionId,
nRoamBmissFirstBcnt,
REASON_ROAM_BMISS_FIRST_BCNT_CHANGED);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMac->roam.configParam.neighborRoamConfig.
nRoamBmissFirstBcnt = nRoamBmissFirstBcnt;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_roam_bmiss_first_bcnt() -
* get neighbor roam beacon miss first count
*
* hHal - The handle returned by mac_open.
* Return uint8_t - neighbor roam beacon miss first count
*/
uint8_t sme_get_roam_bmiss_first_bcnt(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.nRoamBmissFirstBcnt;
}
/*
* sme_set_roam_bmiss_final_bcnt() -
* Update Roam count for final beacon miss
* This function is called through dynamic setConfig callback function
* to configure nRoamBmissFinalBcnt
* hHal - HAL handle for device
* sessionId - Session Identifier
* nRoamBmissFinalBcnt - Roam final bmiss count
* Return QDF_STATUS_SUCCESS - SME update nRoamBmissFinalBcnt
* successfully.
* else SME is failed to update nRoamBmissFinalBcnt
*/
QDF_STATUS sme_set_roam_bmiss_final_bcnt(tHalHandle hHal,
uint8_t sessionId,
const uint8_t nRoamBmissFinalBcnt)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_neighbor_roam_update_config(pMac, sessionId,
nRoamBmissFinalBcnt,
REASON_ROAM_BMISS_FINAL_BCNT_CHANGED);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMac->roam.configParam.neighborRoamConfig.
nRoamBmissFinalBcnt = nRoamBmissFinalBcnt;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_roam_bmiss_final_bcnt() -
* gets Roam count for final beacon miss
* This is a synchronous call
*
* hHal - The handle returned by mac_open
* Return uint8_t - nRoamBmissFinalBcnt
*/
uint8_t sme_get_roam_bmiss_final_bcnt(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt;
}
/*
* sme_set_roam_beacon_rssi_weight() -
* Update Roam beacon rssi weight
* This function is called through dynamic setConfig callback function
* to configure nRoamBeaconRssiWeight
*
* hHal - HAL handle for device
* sessionId - Session Identifier
* nRoamBeaconRssiWeight - Roam beacon rssi weight
* Return QDF_STATUS_SUCCESS - SME update nRoamBeaconRssiWeight config
* successfully.
* else SME is failed to update nRoamBeaconRssiWeight
*/
QDF_STATUS sme_set_roam_beacon_rssi_weight(tHalHandle hHal,
uint8_t sessionId,
const uint8_t nRoamBeaconRssiWeight)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_neighbor_roam_update_config(pMac, sessionId,
nRoamBeaconRssiWeight,
REASON_ROAM_BEACON_RSSI_WEIGHT_CHANGED);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMac->roam.configParam.neighborRoamConfig.
nRoamBeaconRssiWeight = nRoamBeaconRssiWeight;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_roam_beacon_rssi_weight() -
* gets Roam beacon rssi weight
* This is a synchronous call
*
* hHal - The handle returned by mac_open
* Return uint8_t - nRoamBeaconRssiWeight
*/
uint8_t sme_get_roam_beacon_rssi_weight(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight;
}
/*
* sme_set_neighbor_lookup_rssi_threshold() - update neighbor lookup
* rssi threshold
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return QDF_STATUS_SUCCESS - SME update config successful.
* Other status means SME is failed to update
*/
QDF_STATUS sme_set_neighbor_lookup_rssi_threshold(tHalHandle hHal,
uint8_t sessionId, uint8_t neighborLookupRssiThreshold)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_neighbor_roam_update_config(pMac,
sessionId, neighborLookupRssiThreshold,
REASON_LOOKUP_THRESH_CHANGED);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMac->roam.configParam.neighborRoamConfig.
nNeighborLookupRssiThreshold =
neighborLookupRssiThreshold;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_delay_before_vdev_stop() - update delay before VDEV_STOP
* This is a synchronous call
*
* hal - The handle returned by macOpen.
* session_id - Session Identifier
* delay_before_vdev_stop - value to be set
* Return QDF_STATUS_SUCCESS - SME update config successful.
* Other status means SME is failed to update
*/
QDF_STATUS sme_set_delay_before_vdev_stop(tHalHandle hal,
uint8_t session_id,
uint8_t delay_before_vdev_stop)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (session_id >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), session_id);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR param delay_before_vdev_stop changed from %d to %d",
pMac->roam.configParam.neighborRoamConfig.
delay_before_vdev_stop,
delay_before_vdev_stop);
pMac->roam.neighborRoamInfo[session_id].cfgParams.
delay_before_vdev_stop = delay_before_vdev_stop;
pMac->roam.configParam.neighborRoamConfig.
delay_before_vdev_stop = delay_before_vdev_stop;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_neighbor_lookup_rssi_threshold() - get neighbor lookup
* rssi threshold
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* Return QDF_STATUS_SUCCESS - SME update config successful.
* Other status means SME is failed to update
*/
uint8_t sme_get_neighbor_lookup_rssi_threshold(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.
nNeighborLookupRssiThreshold;
}
/*
* sme_set_neighbor_scan_refresh_period() - set neighbor scan results
* refresh period
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return QDF_STATUS_SUCCESS - SME update config successful.
* Other status means SME is failed to update
*/
QDF_STATUS sme_set_neighbor_scan_refresh_period(tHalHandle hHal,
uint8_t sessionId, uint16_t neighborScanResultsRefreshPeriod)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_neighbor_roamconfig *pNeighborRoamConfig = NULL;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pNeighborRoamConfig =
&pMac->roam.configParam.neighborRoamConfig;
pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId];
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set roam scan refresh period to %d- old value is %d - roam state is %s",
neighborScanResultsRefreshPeriod,
pMac->roam.configParam.neighborRoamConfig.
nNeighborResultsRefreshPeriod,
mac_trace_get_neighbour_roam_state(pMac->roam.
neighborRoamInfo
[sessionId].
neighborRoamState));
pNeighborRoamConfig->nNeighborResultsRefreshPeriod =
neighborScanResultsRefreshPeriod;
pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod =
neighborScanResultsRefreshPeriod;
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_update_roam_scan_offload_enabled() - enable/disable roam scan
* offload feaure
* It is used at in the REG_DYNAMIC_VARIABLE macro definition of
* gRoamScanOffloadEnabled.
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* Return QDF_STATUS_SUCCESS - SME update config successfully.
* Other status means SME is failed to update.
*/
QDF_STATUS sme_update_roam_scan_offload_enabled(tHalHandle hHal,
bool nRoamScanOffloadEnabled)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"gRoamScanOffloadEnabled is changed from %d to %d",
pMac->roam.configParam.isRoamOffloadScanEnabled,
nRoamScanOffloadEnabled);
pMac->roam.configParam.isRoamOffloadScanEnabled =
nRoamScanOffloadEnabled;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_neighbor_scan_refresh_period() - get neighbor scan results
* refresh period
* This is a synchronous call
*
* \param hHal - The handle returned by mac_open.
* \return uint16_t - Neighbor scan results refresh period value
*/
uint16_t sme_get_neighbor_scan_refresh_period(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.
nNeighborResultsRefreshPeriod;
}
/*
* sme_get_empty_scan_refresh_period() - get empty scan refresh period
* This is a synchronuous call
*
* hHal - The handle returned by mac_open.
* Return QDF_STATUS_SUCCESS - SME update config successful.
* Other status means SME is failed to update
*/
uint16_t sme_get_empty_scan_refresh_period(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.
nEmptyScanRefreshPeriod;
}
/*
* sme_update_empty_scan_refresh_period
* Update nEmptyScanRefreshPeriod
* This function is called through dynamic setConfig callback function
* to configure nEmptyScanRefreshPeriod
* Usage: adb shell iwpriv wlan0 setConfig
* nEmptyScanRefreshPeriod=[0 .. 60]
*
* hHal - HAL handle for device
* sessionId - Session Identifier
* nEmptyScanRefreshPeriod - scan period following empty scan results.
* Return Success or failure
*/
QDF_STATUS sme_update_empty_scan_refresh_period(tHalHandle hHal, uint8_t
sessionId, uint16_t
nEmptyScanRefreshPeriod)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_neighbor_roamconfig *pNeighborRoamConfig = NULL;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pNeighborRoamConfig =
&pMac->roam.configParam.neighborRoamConfig;
pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId];
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set roam scan period to %d -old value is %d - roam state is %s",
nEmptyScanRefreshPeriod,
pMac->roam.configParam.neighborRoamConfig.
nEmptyScanRefreshPeriod,
mac_trace_get_neighbour_roam_state(pMac->roam.
neighborRoamInfo
[sessionId].
neighborRoamState));
pNeighborRoamConfig->nEmptyScanRefreshPeriod =
nEmptyScanRefreshPeriod;
pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod =
nEmptyScanRefreshPeriod;
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_EMPTY_SCAN_REF_PERIOD_CHANGED);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_neighbor_scan_min_chan_time() -
* Update nNeighborScanMinChanTime
* This function is called through dynamic setConfig callback function
* to configure gNeighborScanChannelMinTime
* Usage: adb shell iwpriv wlan0 setConfig
* gNeighborScanChannelMinTime=[0 .. 60]
*
* hHal - HAL handle for device
* nNeighborScanMinChanTime - Channel minimum dwell time
* sessionId - Session Identifier
* Return Success or failure
*/
QDF_STATUS sme_set_neighbor_scan_min_chan_time(tHalHandle hHal,
const uint16_t
nNeighborScanMinChanTime,
uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set channel min dwell time to %d - old value is %d - roam state is %s",
nNeighborScanMinChanTime,
pMac->roam.configParam.neighborRoamConfig.
nNeighborScanMinChanTime,
mac_trace_get_neighbour_roam_state(pMac->roam.
neighborRoamInfo
[sessionId].
neighborRoamState));
pMac->roam.configParam.neighborRoamConfig.
nNeighborScanMinChanTime = nNeighborScanMinChanTime;
pMac->roam.neighborRoamInfo[sessionId].cfgParams.
minChannelScanTime = nNeighborScanMinChanTime;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_neighbor_scan_max_chan_time() -
* Update nNeighborScanMaxChanTime
* This function is called through dynamic setConfig callback function
* to configure gNeighborScanChannelMaxTime
* Usage: adb shell iwpriv wlan0 setConfig
* gNeighborScanChannelMaxTime=[0 .. 60]
*
* hHal - HAL handle for device
* sessionId - Session Identifier
* nNeighborScanMinChanTime - Channel maximum dwell time
* Return Success or failure
*/
QDF_STATUS sme_set_neighbor_scan_max_chan_time(tHalHandle hHal, uint8_t
sessionId,
const uint16_t
nNeighborScanMaxChanTime)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_neighbor_roamconfig *pNeighborRoamConfig = NULL;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pNeighborRoamConfig =
&pMac->roam.configParam.neighborRoamConfig;
pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId];
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set channel max dwell time to %d - old value is %d - roam state is %s",
nNeighborScanMaxChanTime,
pMac->roam.configParam.neighborRoamConfig.
nNeighborScanMaxChanTime,
mac_trace_get_neighbour_roam_state(pMac->roam.
neighborRoamInfo
[sessionId].
neighborRoamState));
pNeighborRoamConfig->nNeighborScanMaxChanTime =
nNeighborScanMaxChanTime;
pNeighborRoamInfo->cfgParams.maxChannelScanTime =
nNeighborScanMaxChanTime;
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_SCAN_CH_TIME_CHANGED);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_neighbor_scan_min_chan_time() -
* get neighbor scan min channel time
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return uint16_t - channel min time value
*/
uint16_t sme_get_neighbor_scan_min_chan_time(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return 0;
}
return pMac->roam.neighborRoamInfo[sessionId].cfgParams.
minChannelScanTime;
}
/*
* sme_get_neighbor_roam_state() -
* get neighbor roam state
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return uint32_t - neighbor roam state
*/
uint32_t sme_get_neighbor_roam_state(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return 0;
}
return pMac->roam.neighborRoamInfo[sessionId].neighborRoamState;
}
/*
* sme_get_current_roam_state() -
* get current roam state
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return uint32_t - current roam state
*/
uint32_t sme_get_current_roam_state(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.curState[sessionId];
}
/*
* sme_get_current_roam_sub_state() -
* \brief get neighbor roam sub state
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return uint32_t - current roam sub state
*/
uint32_t sme_get_current_roam_sub_state(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.curSubState[sessionId];
}
/*
* sme_get_lim_sme_state() -
* get Lim Sme state
*
* hHal - The handle returned by mac_open.
* Return uint32_t - Lim Sme state
*/
uint32_t sme_get_lim_sme_state(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->lim.gLimSmeState;
}
/*
* sme_get_lim_mlm_state() -
* get Lim Mlm state
*
* hHal - The handle returned by mac_open.
* Return uint32_t - Lim Mlm state
*/
uint32_t sme_get_lim_mlm_state(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->lim.gLimMlmState;
}
/*
* sme_is_lim_session_valid() -
* is Lim session valid
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return bool - true or false
*/
bool sme_is_lim_session_valid(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (sessionId > pMac->lim.maxBssId)
return false;
return pMac->lim.gpSession[sessionId].valid;
}
/*
* sme_get_lim_sme_session_state() -
* get Lim Sme session state
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return uint32_t - Lim Sme session state
*/
uint32_t sme_get_lim_sme_session_state(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->lim.gpSession[sessionId].limSmeState;
}
/*
* sme_get_lim_mlm_session_state() -
* \brief get Lim Mlm session state
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return uint32_t - Lim Mlm session state
*/
uint32_t sme_get_lim_mlm_session_state(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->lim.gpSession[sessionId].limMlmState;
}
/*
* sme_get_neighbor_scan_max_chan_time() -
* get neighbor scan max channel time
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return uint16_t - channel max time value
*/
uint16_t sme_get_neighbor_scan_max_chan_time(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return 0;
}
return pMac->roam.neighborRoamInfo[sessionId].cfgParams.
maxChannelScanTime;
}
/*
* sme_set_neighbor_scan_period() -
* Update nNeighborScanPeriod
* This function is called through dynamic setConfig callback function
* to configure nNeighborScanPeriod
* Usage: adb shell iwpriv wlan0 setConfig
* nNeighborScanPeriod=[0 .. 1000]
*
* hHal - HAL handle for device
* sessionId - Session Identifier
* nNeighborScanPeriod - neighbor scan period
* Return Success or failure
*/
QDF_STATUS sme_set_neighbor_scan_period(tHalHandle hHal, uint8_t sessionId,
const uint16_t nNeighborScanPeriod)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_neighbor_roamconfig *pNeighborRoamConfig = NULL;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pNeighborRoamConfig =
&pMac->roam.configParam.neighborRoamConfig;
pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId];
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set neighbor scan period to %d - old value is %d - roam state is %s",
nNeighborScanPeriod,
pMac->roam.configParam.neighborRoamConfig.
nNeighborScanTimerPeriod,
mac_trace_get_neighbour_roam_state(pMac->roam.
neighborRoamInfo
[sessionId].
neighborRoamState));
pNeighborRoamConfig->nNeighborScanTimerPeriod =
nNeighborScanPeriod;
pNeighborRoamInfo->cfgParams.neighborScanPeriod =
nNeighborScanPeriod;
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_SCAN_HOME_TIME_CHANGED);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_neighbor_scan_period() -
* get neighbor scan period
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return uint16_t - neighbor scan period
*/
uint16_t sme_get_neighbor_scan_period(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return 0;
}
return pMac->roam.neighborRoamInfo[sessionId].cfgParams.
neighborScanPeriod;
}
/**
* sme_set_neighbor_scan_min_period() - Update neighbor_scan_min_period
* This function is called through dynamic setConfig callback function
* to configure neighbor_scan_min_period
*
* @hal - HAL handle for device
* @session_id - Session Identifier
* @neighbor_scan_min_period - neighbor scan min period
*
* Return - QDF_STATUS
*/
QDF_STATUS sme_set_neighbor_scan_min_period(tHalHandle hal,
uint8_t session_id,
const uint16_t
neighbor_scan_min_period)
{
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_neighbor_roamconfig *p_neighbor_roam_config = NULL;
tpCsrNeighborRoamControlInfo p_neighbor_roam_info = NULL;
if (session_id >= CSR_ROAM_SESSION_MAX) {
sme_err("Invalid sme session id: %d", session_id);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pmac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
p_neighbor_roam_config =
&pmac->roam.configParam.neighborRoamConfig;
p_neighbor_roam_info = &pmac->
roam.neighborRoamInfo[session_id];
sme_debug("LFR:set neighbor scan min period, old:%d, "
"new: %d, state: %s",
pmac->roam.configParam.neighborRoamConfig.
neighbor_scan_min_timer_period,
neighbor_scan_min_period,
mac_trace_get_neighbour_roam_state(pmac->roam.
neighborRoamInfo[session_id].
neighborRoamState));
p_neighbor_roam_config->neighbor_scan_min_timer_period =
neighbor_scan_min_period;
p_neighbor_roam_info->cfgParams.neighbor_scan_min_period =
neighbor_scan_min_period;
sme_release_global_lock(&pmac->sme);
}
return status;
}
/*
* sme_get_roam_rssi_diff() - get Roam rssi diff
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* Return uint16_t - Rssi diff value
*/
uint8_t sme_get_roam_rssi_diff(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.RoamRssiDiff;
}
/**
* sme_change_roam_scan_channel_list() - to change scan channel list
* @hHal: pointer HAL handle returned by mac_open
* @sessionId: sme session id
* @pChannelList: Output channel list
* @numChannels: Output number of channels
*
* This routine is called to Change roam scan channel list.
* This is a synchronous call
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_change_roam_scan_channel_list(tHalHandle hHal, uint8_t sessionId,
uint8_t *pChannelList,
uint8_t numChannels)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL;
uint8_t oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN * 2] = { 0 };
uint8_t newChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN * 2] = { 0 };
uint8_t i = 0, j = 0;
tCsrChannelInfo *chan_info;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId];
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Failed to acquire SME lock");
return status;
}
chan_info = &pNeighborRoamInfo->cfgParams.channelInfo;
if (NULL != chan_info->ChannelList) {
for (i = 0; i < chan_info->numOfChannels; i++) {
if (j < sizeof(oldChannelList))
j += snprintf(oldChannelList + j,
sizeof(oldChannelList) -
j, "%d",
chan_info->ChannelList[i]);
else
break;
}
}
csr_flush_cfg_bg_scan_roam_channel_list(pMac, sessionId);
csr_create_bg_scan_roam_channel_list(pMac, sessionId, pChannelList,
numChannels);
sme_set_roam_scan_control(hHal, sessionId, 1);
if (NULL != chan_info->ChannelList) {
j = 0;
for (i = 0; i < chan_info->numOfChannels; i++) {
if (j < sizeof(newChannelList))
j += snprintf(newChannelList + j,
sizeof(newChannelList) -
j, " %d",
chan_info->ChannelList[i]);
else
break;
}
}
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d",
newChannelList, oldChannelList,
pMac->roam.neighborRoamInfo[sessionId].neighborRoamState);
if (pMac->roam.configParam.isRoamOffloadScanEnabled)
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_CHANNEL_LIST_CHANGED);
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_get_roam_scan_channel_list() - To get roam scan channel list
* @hHal: HAL pointer
* @pChannelList: Output channel list
* @pNumChannels: Output number of channels
* @sessionId: Session Identifier
*
* To get roam scan channel list This is a synchronous call
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_get_roam_scan_channel_list(tHalHandle hHal,
uint8_t *pChannelList, uint8_t *pNumChannels,
uint8_t sessionId)
{
int i = 0;
uint8_t *pOutPtr = pChannelList;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
pNeighborRoamInfo = &pMac->roam.neighborRoamInfo[sessionId];
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
FL("Roam Scan channel list is NOT yet initialized"));
*pNumChannels = 0;
sme_release_global_lock(&pMac->sme);
return status;
}
*pNumChannels = pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels;
for (i = 0; i < (*pNumChannels); i++)
pOutPtr[i] =
pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i];
pOutPtr[i] = '\0';
sme_release_global_lock(&pMac->sme);
return status;
}
/*
* sme_get_is_ese_feature_enabled() - get ESE feature enabled or not
* This is a synchronuous call
*
* hHal - The handle returned by mac_open.
* Return true (1) - if the ESE feature is enabled
* false (0) - if feature is disabled (compile or runtime)
*/
bool sme_get_is_ese_feature_enabled(tHalHandle hHal)
{
#ifdef FEATURE_WLAN_ESE
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return csr_roam_is_ese_ini_feature_enabled(pMac);
#else
return false;
#endif
}
/*
* sme_get_wes_mode() - get WES Mode
* This is a synchronous call
*
* hHal - The handle returned by mac_open
* Return uint8_t - WES Mode Enabled(1)/Disabled(0)
*/
bool sme_get_wes_mode(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.isWESModeEnabled;
}
/*
* sme_get_roam_scan_control() - get scan control
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* Return bool - Enabled(1)/Disabled(0)
*/
bool sme_get_roam_scan_control(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.nRoamScanControl;
}
/*
* sme_get_is_lfr_feature_enabled() - get LFR feature enabled or not
* This is a synchronuous call
* hHal - The handle returned by mac_open.
* Return true (1) - if the feature is enabled
* false (0) - if feature is disabled (compile or runtime)
*/
bool sme_get_is_lfr_feature_enabled(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.isFastRoamIniFeatureEnabled;
}
/*
* sme_get_is_ft_feature_enabled() - get FT feature enabled or not
* This is a synchronuous call
*
* hHal - The handle returned by mac_open.
* Return true (1) - if the feature is enabled
* false (0) - if feature is disabled (compile or runtime)
*/
bool sme_get_is_ft_feature_enabled(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.isFastTransitionEnabled;
}
/**
* sme_is_feature_supported_by_fw() - check if feature is supported by FW
* @feature: enum value of requested feature.
*
* Retrun: 1 if supported; 0 otherwise
*/
bool sme_is_feature_supported_by_fw(enum cap_bitmap feature)
{
return IS_FEATURE_SUPPORTED_BY_FW(feature);
}
QDF_STATUS sme_get_link_speed(tHalHandle hHal, tSirLinkSpeedInfo *lsReq,
void *plsContext,
void (*pCallbackfn)(tSirLinkSpeedInfo *indParam,
void *pContext))
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac;
void *wma_handle;
if (!hHal || !pCallbackfn || !lsReq) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid parameter"));
return QDF_STATUS_E_FAILURE;
}
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS != status) {
sme_err("Failed to acquire global lock");
return QDF_STATUS_E_FAILURE;
}
pMac->sme.pLinkSpeedCbContext = plsContext;
pMac->sme.pLinkSpeedIndCb = pCallbackfn;
status = wma_get_link_speed(wma_handle, lsReq);
sme_release_global_lock(&pMac->sme);
return status;
}
QDF_STATUS sme_get_peer_stats(tpAniSirGlobal mac,
struct sir_peer_info_req req)
{
QDF_STATUS qdf_status;
struct scheduler_msg message = {0};
qdf_status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
sme_debug("Failed to get Lock");
return qdf_status;
}
/* serialize the req through MC thread */
message.bodyptr = qdf_mem_malloc(sizeof(req));
if (NULL == message.bodyptr) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Memory allocation failed.", __func__);
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(message.bodyptr, &req, sizeof(req));
message.type = WMA_GET_PEER_INFO;
message.reserved = 0;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post get peer info msg fail", __func__);
qdf_mem_free(message.bodyptr);
qdf_status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
return qdf_status;
}
QDF_STATUS sme_get_peer_info(tHalHandle hal, struct sir_peer_info_req req,
void *context,
void (*callbackfn)(struct sir_peer_info_resp *param,
void *pcontext))
{
QDF_STATUS status;
QDF_STATUS qdf_status;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&mac->sme);
if (QDF_STATUS_SUCCESS == status) {
if (NULL == callbackfn) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Indication Call back is NULL",
__func__);
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_FAILURE;
}
mac->sme.pget_peer_info_ind_cb = callbackfn;
mac->sme.pget_peer_info_cb_context = context;
/* serialize the req through MC thread */
message.bodyptr = qdf_mem_malloc(sizeof(req));
if (NULL == message.bodyptr) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Memory allocation failed.", __func__);
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(message.bodyptr, &req, sizeof(req));
message.type = WMA_GET_PEER_INFO;
message.reserved = 0;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post get peer info msg fail", __func__);
qdf_mem_free(message.bodyptr);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
}
return status;
}
QDF_STATUS sme_get_peer_info_ext(tHalHandle hal,
struct sir_peer_info_ext_req *req,
void *context,
void (*callbackfn)(struct sir_peer_info_ext_resp *param,
void *pcontext))
{
QDF_STATUS status;
QDF_STATUS qdf_status;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&mac->sme);
if (QDF_STATUS_SUCCESS == status) {
if (NULL == callbackfn) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Indication Call back is NULL",
__func__);
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_FAILURE;
}
mac->sme.pget_peer_info_ext_ind_cb = callbackfn;
mac->sme.pget_peer_info_ext_cb_context = context;
/* serialize the req through MC thread */
message.bodyptr =
qdf_mem_malloc(sizeof(struct sir_peer_info_ext_req));
if (NULL == message.bodyptr) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Memory allocation failed.", __func__);
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(message.bodyptr,
req,
sizeof(struct sir_peer_info_ext_req));
message.type = WMA_GET_PEER_INFO_EXT;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post get rssi msg fail", __func__);
qdf_mem_free(message.bodyptr);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
}
return status;
}
/*
* SME API to enable/disable WLAN driver initiated SSR
*/
void sme_update_enable_ssr(tHalHandle hHal, bool enableSSR)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
sme_debug("SSR level is changed %d", enableSSR);
/* not serializing this message, as this is only going
* to set a variable in WMA/WDI
*/
WMA_SetEnableSSR(enableSSR);
sme_release_global_lock(&pMac->sme);
}
}
/*convert the ini value to the ENUM used in csr and MAC for CB state*/
ePhyChanBondState sme_get_cb_phy_state_from_cb_ini_value(uint32_t cb_ini_value)
{
return csr_convert_cb_ini_value_to_phy_cb_state(cb_ini_value);
}
/*
* sme_set_curr_device_mode() - Sets the current operating device mode.
*
* hHal - The handle returned by mac_open.
* currDeviceMode - Current operating device mode.
*/
void sme_set_curr_device_mode(tHalHandle hHal,
enum QDF_OPMODE currDeviceMode)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pMac->sme.currDeviceMode = currDeviceMode;
}
/*
* sme_handoff_request() - a wrapper function to Request a handoff from CSR.
* This is a synchronous call
*
* hHal - The handle returned by mac_open
* sessionId - Session Identifier
* pHandoffInfo - info provided by HDD with the handoff request (namely:
* BSSID, channel etc.)
* Return QDF_STATUS_SUCCESS - SME passed the request to CSR successfully.
* Other status means SME is failed to send the request.
*/
QDF_STATUS sme_handoff_request(tHalHandle hHal,
uint8_t sessionId,
tCsrHandoffRequest *pHandoffInfo)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: invoked", __func__);
status = csr_handoff_request(pMac, sessionId, pHandoffInfo);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* SME API to check if there is any infra station or
* P2P client is connected
*/
QDF_STATUS sme_is_sta_p2p_client_connected(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (csr_is_infra_connected(pMac))
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
/**
* sme_add_periodic_tx_ptrn() - Add Periodic TX Pattern
* @hal: global hal handle
* @addPeriodicTxPtrnParams: request message
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS
sme_add_periodic_tx_ptrn(tHalHandle hal,
struct sSirAddPeriodicTxPtrn *addPeriodicTxPtrnParams)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct sSirAddPeriodicTxPtrn *req_msg;
struct scheduler_msg msg = {0};
SME_ENTER();
req_msg = qdf_mem_malloc(sizeof(*req_msg));
if (!req_msg) {
sme_err("memory allocation failed");
return QDF_STATUS_E_NOMEM;
}
*req_msg = *addPeriodicTxPtrnParams;
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("sme_acquire_global_lock failed!(status=%d)",
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
msg.bodyptr = req_msg;
msg.type = WMA_ADD_PERIODIC_TX_PTRN_IND;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, msg.type));
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("scheduler_post_msg failed!(err=%d)",
status);
qdf_mem_free(req_msg);
}
sme_release_global_lock(&mac->sme);
return status;
}
/**
* sme_del_periodic_tx_ptrn() - Delete Periodic TX Pattern
* @hal: global hal handle
* @delPeriodicTxPtrnParams: request message
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS
sme_del_periodic_tx_ptrn(tHalHandle hal,
struct sSirDelPeriodicTxPtrn *delPeriodicTxPtrnParams)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct sSirDelPeriodicTxPtrn *req_msg;
struct scheduler_msg msg = {0};
SME_ENTER();
req_msg = qdf_mem_malloc(sizeof(*req_msg));
if (!req_msg) {
sme_err("memory allocation failed");
return QDF_STATUS_E_NOMEM;
}
*req_msg = *delPeriodicTxPtrnParams;
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("sme_acquire_global_lock failed!(status=%d)",
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
msg.bodyptr = req_msg;
msg.type = WMA_DEL_PERIODIC_TX_PTRN_IND;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, msg.type));
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("scheduler_post_msg failed!(err=%d)",
status);
qdf_mem_free(req_msg);
}
sme_release_global_lock(&mac->sme);
return status;
}
#ifdef FEATURE_WLAN_RMC
/*
* sme_enable_rmc() - enables RMC
* @hHal : Pointer to global HAL handle
* @sessionId : Session ID
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_enable_rmc(tHalHandle hHal, uint32_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
SME_ENTER();
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
message.bodyptr = NULL;
message.type = WMA_RMC_ENABLE_IND;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: failed to post message to WMA",
__func__);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_disable_rmc() - disables RMC
* @hHal : Pointer to global HAL handle
* @sessionId : Session ID
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_disable_rmc(tHalHandle hHal, uint32_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
SME_ENTER();
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
message.bodyptr = NULL;
message.type = WMA_RMC_DISABLE_IND;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: failed to post message to WMA",
__func__);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_send_rmc_action_period() - sends RMC action period param to target
* @hHal : Pointer to global HAL handle
* @sessionId : Session ID
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_send_rmc_action_period(tHalHandle hHal, uint32_t sessionId)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
message.bodyptr = NULL;
message.type = WMA_RMC_ACTION_PERIOD_IND;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: failed to post message to WMA",
__func__);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif /* FEATURE_WLAN_RMC */
/*
* sme_request_ibss_peer_info() - request ibss peer info
* @hHal : Pointer to global HAL handle
* @pUserData : Pointer to user data
* @peerInfoCbk : Peer info callback
* @allPeerInfoReqd : All peer info required or not
* @staIdx : sta index
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_request_ibss_peer_info(tHalHandle hHal, void *pUserData,
pIbssPeerInfoCb peerInfoCbk,
bool allPeerInfoReqd, uint8_t staIdx)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tSirIbssGetPeerInfoReqParams *pIbssInfoReqParams;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
pMac->sme.peerInfoParams.peerInfoCbk = peerInfoCbk;
pMac->sme.peerInfoParams.pUserData = pUserData;
pIbssInfoReqParams = (tSirIbssGetPeerInfoReqParams *)
qdf_mem_malloc(sizeof(tSirIbssGetPeerInfoReqParams));
if (NULL == pIbssInfoReqParams) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for dhcp start",
__func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
pIbssInfoReqParams->allPeerInfoReqd = allPeerInfoReqd;
pIbssInfoReqParams->staIdx = staIdx;
message.type = WMA_GET_IBSS_PEER_INFO_REQ;
message.bodyptr = pIbssInfoReqParams;
message.reserved = 0;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (QDF_STATUS_SUCCESS != qdf_status) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post WMA_GET_IBSS_PEER_INFO_REQ MSG failed",
__func__);
qdf_mem_free(pIbssInfoReqParams);
qdf_status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return qdf_status;
}
/*
* sme_send_cesium_enable_ind() -
* Used to send proprietary cesium enable indication to fw
*
* hHal
* sessionId
* Return QDF_STATUS
*/
QDF_STATUS sme_send_cesium_enable_ind(tHalHandle hHal, uint32_t sessionId)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
message.bodyptr = NULL;
message.type = WMA_IBSS_CESIUM_ENABLE_IND;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: failed to post message to WMA",
__func__);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
QDF_STATUS sme_set_wlm_latency_level(tHalHandle hal, uint16_t session_id,
uint16_t latency_level)
{
QDF_STATUS status;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct wlm_latency_level_param params;
void *wma = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma)
return QDF_STATUS_E_FAILURE;
if (!mac_ctx->roam.configParam.wlm_latency_enable) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: WLM latency level setting is disabled",
__func__);
return QDF_STATUS_E_FAILURE;
}
if (!wma) {
sme_err("wma is NULL");
return QDF_STATUS_E_FAILURE;
}
params.wlm_latency_level = latency_level;
params.wlm_latency_flags =
mac_ctx->roam.configParam.wlm_latency_flags[latency_level];
params.vdev_id = session_id;
status = wma_set_wlm_latency_level(wma, &params);
if (!QDF_IS_STATUS_SUCCESS(status))
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: failed to set latency level",
__func__);
return status;
}
void sme_get_command_q_status(tHalHandle hHal)
{
tSmeCmd *pTempCmd = NULL;
tListElem *pEntry;
tpAniSirGlobal pMac;
if (NULL != hHal) {
pMac = PMAC_STRUCT(hHal);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Invalid hHal pointer", __func__);
return;
}
pEntry = csr_nonscan_active_ll_peek_head(pMac, LL_ACCESS_LOCK);
if (pEntry)
pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
sme_err("WLAN_BUG_RCA: Currently smeCmdActiveList has command (0x%X)",
(pTempCmd) ? pTempCmd->command : eSmeNoCommand);
if (pTempCmd) {
if (eSmeCsrCommandMask & pTempCmd->command)
/* CSR command is stuck. See what the reason code is
* for that command
*/
dump_csr_command_info(pMac, pTempCmd);
} /* if(pTempCmd) */
sme_err("Currently smeCmdPendingList has %d commands",
csr_nonscan_pending_ll_count(pMac));
}
/**
* sme_set_prefer_80MHz_over_160MHz() - API to set sta_prefer_80MHz_over_160MHz
* @hal: The handle returned by macOpen
* @sta_prefer_80MHz_over_160MHz: sta_prefer_80MHz_over_160MHz config param
*/
void sme_set_prefer_80MHz_over_160MHz(tHalHandle hal,
bool sta_prefer_80MHz_over_160MHz)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
mac_ctx->sta_prefer_80MHz_over_160MHz = sta_prefer_80MHz_over_160MHz;
}
#ifdef WLAN_FEATURE_DSRC
/**
* sme_set_dot11p_config() - API to set the 802.11p config
* @hHal: The handle returned by macOpen
* @enable_dot11p: 802.11p config param
*/
void sme_set_dot11p_config(tHalHandle hHal, bool enable_dot11p)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pMac->enable_dot11p = enable_dot11p;
}
/**
* copy_sir_ocb_config() - Performs deep copy of an OCB configuration
* @src: the source configuration
*
* Return: pointer to the copied OCB configuration
*/
static struct sir_ocb_config *sme_copy_sir_ocb_config(
struct sir_ocb_config *src)
{
struct sir_ocb_config *dst;
uint32_t length;
void *cursor;
length = sizeof(*src) +
src->channel_count * sizeof(*src->channels) +
src->schedule_size * sizeof(*src->schedule) +
src->dcc_ndl_chan_list_len +
src->dcc_ndl_active_state_list_len;
dst = qdf_mem_malloc(length);
if (!dst)
return NULL;
*dst = *src;
cursor = dst;
cursor += sizeof(*dst);
dst->channels = cursor;
cursor += src->channel_count * sizeof(*src->channels);
qdf_mem_copy(dst->channels, src->channels,
src->channel_count * sizeof(*src->channels));
dst->schedule = cursor;
cursor += src->schedule_size * sizeof(*src->schedule);
qdf_mem_copy(dst->schedule, src->schedule,
src->schedule_size * sizeof(*src->schedule));
dst->dcc_ndl_chan_list = cursor;
cursor += src->dcc_ndl_chan_list_len;
qdf_mem_copy(dst->dcc_ndl_chan_list, src->dcc_ndl_chan_list,
src->dcc_ndl_chan_list_len);
dst->dcc_ndl_active_state_list = cursor;
cursor += src->dcc_ndl_active_state_list_len;
qdf_mem_copy(dst->dcc_ndl_active_state_list,
src->dcc_ndl_active_state_list,
src->dcc_ndl_active_state_list_len);
return dst;
}
/**
* sme_ocb_set_config() - Set the OCB configuration
* @hHal: reference to the HAL
* @context: the context of the call
* @callback: the callback to hdd
* @config: the OCB configuration
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
*/
QDF_STATUS sme_ocb_set_config(tHalHandle hHal, void *context,
ocb_callback callback,
struct sir_ocb_config *config)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg msg = {0};
struct sir_ocb_config *msg_body;
/* Lock the SME structure */
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
/*
* Check if there is a pending request and return an error if one
* exists
*/
if (pMac->sme.ocb_set_config_callback) {
status = QDF_STATUS_E_BUSY;
goto end;
}
msg_body = sme_copy_sir_ocb_config(config);
if (!msg_body) {
status = QDF_STATUS_E_NOMEM;
goto end;
}
msg.type = WMA_OCB_SET_CONFIG_CMD;
msg.bodyptr = msg_body;
/* Set the request callback and context */
pMac->sme.ocb_set_config_callback = callback;
pMac->sme.ocb_set_config_context = context;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Error posting message to WDA: %d"), status);
pMac->sme.ocb_set_config_callback = callback;
pMac->sme.ocb_set_config_context = context;
qdf_mem_free(msg_body);
goto end;
}
end:
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_ocb_set_utc_time() - Set the OCB UTC time
* @hHal: reference to the HAL
* @utc: the UTC time struct
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
*/
QDF_STATUS sme_ocb_set_utc_time(tHalHandle hHal, struct sir_ocb_utc *utc)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg msg = {0};
struct sir_ocb_utc *sme_utc;
/* Lock the SME structure */
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
sme_utc = qdf_mem_malloc(sizeof(*sme_utc));
if (!sme_utc) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Malloc failed"));
status = QDF_STATUS_E_NOMEM;
goto end;
}
*sme_utc = *utc;
msg.type = WMA_OCB_SET_UTC_TIME_CMD;
msg.reserved = 0;
msg.bodyptr = sme_utc;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post message to WDA"));
qdf_mem_free(utc);
goto end;
}
end:
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_ocb_start_timing_advert() - Start sending timing advert frames
* @hHal: reference to the HAL
* @timing_advert: the timing advertisement struct
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
*/
QDF_STATUS sme_ocb_start_timing_advert(tHalHandle hHal,
struct sir_ocb_timing_advert *timing_advert)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg msg = {0};
void *buf;
struct sir_ocb_timing_advert *sme_timing_advert;
/* Lock the SME structure */
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
buf = qdf_mem_malloc(sizeof(*sme_timing_advert) +
timing_advert->template_length);
if (!buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to allocate memory for start TA"));
status = QDF_STATUS_E_NOMEM;
goto end;
}
sme_timing_advert = (struct sir_ocb_timing_advert *)buf;
*sme_timing_advert = *timing_advert;
sme_timing_advert->template_value = buf + sizeof(*sme_timing_advert);
qdf_mem_copy(sme_timing_advert->template_value,
timing_advert->template_value, timing_advert->template_length);
msg.type = WMA_OCB_START_TIMING_ADVERT_CMD;
msg.reserved = 0;
msg.bodyptr = buf;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post msg to WDA"));
goto end;
}
end:
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_ocb_stop_timing_advert() - Stop sending timing advert frames on a channel
* @hHal: reference to the HAL
* @timing_advert: the timing advertisement struct
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
*/
QDF_STATUS sme_ocb_stop_timing_advert(tHalHandle hHal,
struct sir_ocb_timing_advert *timing_advert)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg msg = {0};
struct sir_ocb_timing_advert *sme_timing_advert;
/* Lock the SME structure */
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
sme_timing_advert = qdf_mem_malloc(sizeof(*timing_advert));
if (!sme_timing_advert) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to allocate memory for stop TA"));
status = QDF_STATUS_E_NOMEM;
goto end;
}
*sme_timing_advert = *timing_advert;
msg.type = WMA_OCB_STOP_TIMING_ADVERT_CMD;
msg.reserved = 0;
msg.bodyptr = sme_timing_advert;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post msg to WDA"));
goto end;
}
end:
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_ocb_gen_timing_advert_frame() - generate TA frame and populate the buffer
* @hal_handle: reference to the HAL
* @self_addr: the self MAC address
* @buf: the buffer that will contain the frame
* @timestamp_offset: return for the offset of the timestamp field
* @time_value_offset: return for the time_value field in the TA IE
*
* Return: the length of the buffer.
*/
int sme_ocb_gen_timing_advert_frame(tHalHandle hal_handle,
tSirMacAddr self_addr, uint8_t **buf,
uint32_t *timestamp_offset,
uint32_t *time_value_offset)
{
int template_length;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
template_length = sch_gen_timing_advert_frame(mac_ctx, self_addr, buf,
timestamp_offset,
time_value_offset);
return template_length;
}
/**
* sme_ocb_get_tsf_timer() - Get the TSF timer value
* @hHal: reference to the HAL
* @context: the context of the call
* @callback: the callback to hdd
* @request: the TSF timer request
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
*/
QDF_STATUS sme_ocb_get_tsf_timer(tHalHandle hHal, void *context,
ocb_callback callback,
struct sir_ocb_get_tsf_timer *request)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg msg = {0};
struct sir_ocb_get_tsf_timer *msg_body;
/* Lock the SME structure */
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
/* Allocate memory for the WMI request, and copy the parameter */
msg_body = qdf_mem_malloc(sizeof(*msg_body));
if (!msg_body) {
status = QDF_STATUS_E_NOMEM;
goto end;
}
*msg_body = *request;
msg.type = WMA_OCB_GET_TSF_TIMER_CMD;
msg.bodyptr = msg_body;
/* Set the request callback and the context */
pMac->sme.ocb_get_tsf_timer_callback = callback;
pMac->sme.ocb_get_tsf_timer_context = context;
/* Post the message to WDA */
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Error posting message to WDA: %d"), status);
pMac->sme.ocb_get_tsf_timer_callback = NULL;
pMac->sme.ocb_get_tsf_timer_context = NULL;
qdf_mem_free(msg_body);
goto end;
}
end:
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_dcc_get_stats() - Get the DCC stats
* @hHal: reference to the HAL
* @context: the context of the call
* @callback: the callback to hdd
* @request: the get DCC stats request
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
*/
QDF_STATUS sme_dcc_get_stats(tHalHandle hHal, void *context,
ocb_callback callback,
struct sir_dcc_get_stats *request)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg msg = {0};
struct sir_dcc_get_stats *msg_body;
/* Lock the SME structure */
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
/* Allocate memory for the WMI request, and copy the parameter */
msg_body = qdf_mem_malloc(sizeof(*msg_body) +
request->request_array_len);
if (!msg_body) {
status = QDF_STATUS_E_NOMEM;
goto end;
}
*msg_body = *request;
msg_body->request_array = (void *)msg_body + sizeof(*msg_body);
qdf_mem_copy(msg_body->request_array, request->request_array,
request->request_array_len);
msg.type = WMA_DCC_GET_STATS_CMD;
msg.bodyptr = msg_body;
/* Set the request callback and context */
pMac->sme.dcc_get_stats_callback = callback;
pMac->sme.dcc_get_stats_context = context;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Error posting message to WDA: %d"), status);
pMac->sme.dcc_get_stats_callback = callback;
pMac->sme.dcc_get_stats_context = context;
qdf_mem_free(msg_body);
goto end;
}
end:
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_dcc_clear_stats() - Clear the DCC stats
* @hHal: reference to the HAL
* @vdev_id: vdev id for OCB interface
* @dcc_stats_bitmap: the entries in the stats to clear
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
*/
QDF_STATUS sme_dcc_clear_stats(tHalHandle hHal, uint32_t vdev_id,
uint32_t dcc_stats_bitmap)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg msg = {0};
struct sir_dcc_clear_stats *request;
/* Lock the SME structure */
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
request = qdf_mem_malloc(sizeof(struct sir_dcc_clear_stats));
if (!request) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to allocate memory"));
status = QDF_STATUS_E_NOMEM;
goto end;
}
request->vdev_id = vdev_id;
request->dcc_stats_bitmap = dcc_stats_bitmap;
msg.type = WMA_DCC_CLEAR_STATS_CMD;
msg.bodyptr = request;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post msg to WDA"));
qdf_mem_free(request);
goto end;
}
end:
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_dcc_update_ndl() - Update the DCC settings
* @hHal: reference to the HAL
* @context: the context of the call
* @callback: the callback to hdd
* @request: the update DCC request
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
*/
QDF_STATUS sme_dcc_update_ndl(tHalHandle hHal, void *context,
ocb_callback callback,
struct sir_dcc_update_ndl *request)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg msg = {0};
struct sir_dcc_update_ndl *msg_body;
/* Lock the SME structure */
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
/* Allocate memory for the WMI request, and copy the parameter */
msg_body = qdf_mem_malloc(sizeof(*msg_body) +
request->dcc_ndl_chan_list_len +
request->dcc_ndl_active_state_list_len);
if (!msg_body) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Failed to allocate memory"));
status = QDF_STATUS_E_NOMEM;
goto end;
}
*msg_body = *request;
msg_body->dcc_ndl_chan_list = (void *)msg_body + sizeof(*msg_body);
msg_body->dcc_ndl_active_state_list = msg_body->dcc_ndl_chan_list +
request->dcc_ndl_chan_list_len;
qdf_mem_copy(msg_body->dcc_ndl_chan_list, request->dcc_ndl_chan_list,
request->dcc_ndl_active_state_list_len);
qdf_mem_copy(msg_body->dcc_ndl_active_state_list,
request->dcc_ndl_active_state_list,
request->dcc_ndl_active_state_list_len);
msg.type = WMA_DCC_UPDATE_NDL_CMD;
msg.bodyptr = msg_body;
/* Set the request callback and the context */
pMac->sme.dcc_update_ndl_callback = callback;
pMac->sme.dcc_update_ndl_context = context;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Error posting message to WDA: %d"), status);
pMac->sme.dcc_update_ndl_callback = NULL;
pMac->sme.dcc_update_ndl_context = NULL;
qdf_mem_free(msg_body);
goto end;
}
end:
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_register_for_dcc_stats_event() - Register for the periodic DCC stats
* event
* @hHal: reference to the HAL
* @context: the context of the call
* @callback: the callback to hdd
*
* Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE on failure
*/
QDF_STATUS sme_register_for_dcc_stats_event(tHalHandle hHal, void *context,
ocb_callback callback)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_E_FAILURE;
status = sme_acquire_global_lock(&pMac->sme);
pMac->sme.dcc_stats_event_callback = callback;
pMac->sme.dcc_stats_event_context = context;
sme_release_global_lock(&pMac->sme);
return 0;
}
/**
* sme_deregister_for_dcc_stats_event() - De-Register for the periodic DCC stats
* event
* @h_hal: Hal Handle
*
* This function de-registers the DCC perioc stats callback
*
* Return: QDF_STATUS Enumeration
*/
QDF_STATUS sme_deregister_for_dcc_stats_event(tHalHandle h_hal)
{
tpAniSirGlobal mac;
QDF_STATUS status;
if (!h_hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("h_hal is not valid"));
return QDF_STATUS_E_INVAL;
}
mac = PMAC_STRUCT(h_hal);
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Failed to acquire global lock"));
return status;
}
mac->sme.dcc_stats_event_callback = NULL;
mac->sme.dcc_stats_event_context = NULL;
sme_release_global_lock(&mac->sme);
return status;
}
#else
void sme_set_etsi13_srd_ch_in_master_mode(tHalHandle hal,
bool etsi13_srd_chan_support)
{
tpAniSirGlobal mac;
mac = PMAC_STRUCT(hal);
mac->sap.enable_etsi13_srd_chan_support = etsi13_srd_chan_support;
sme_debug("srd_ch_support %d", mac->sap.enable_etsi13_srd_chan_support);
}
#endif
void sme_get_recovery_stats(tHalHandle hHal)
{
uint8_t i;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Self Recovery Stats");
for (i = 0; i < MAX_ACTIVE_CMD_STATS; i++) {
if (eSmeNoCommand !=
g_self_recovery_stats.activeCmdStats[i].command) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"timestamp %llu: command 0x%0X: reason %d: session %d",
g_self_recovery_stats.activeCmdStats[i].
timestamp,
g_self_recovery_stats.activeCmdStats[i].command,
g_self_recovery_stats.activeCmdStats[i].reason,
g_self_recovery_stats.activeCmdStats[i].
sessionId);
}
}
}
QDF_STATUS sme_notify_modem_power_state(tHalHandle hHal, uint32_t value)
{
struct scheduler_msg msg = {0};
tpSirModemPowerStateInd request_buf;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pMac)
return QDF_STATUS_E_FAILURE;
request_buf = qdf_mem_malloc(sizeof(tSirModemPowerStateInd));
if (NULL == request_buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for MODEM POWER STATE IND",
__func__);
return QDF_STATUS_E_NOMEM;
}
request_buf->param = value;
msg.type = WMA_MODEM_POWER_STATE_IND;
msg.reserved = 0;
msg.bodyptr = request_buf;
if (!QDF_IS_STATUS_SUCCESS
(scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WMA_MODEM_POWER_STATE_IND message to WMA",
__func__);
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
#ifdef QCA_HT_2040_COEX
QDF_STATUS sme_notify_ht2040_mode(tHalHandle hHal, uint16_t staId,
struct qdf_mac_addr macAddrSTA,
uint8_t sessionId,
uint8_t channel_type)
{
struct scheduler_msg msg = {0};
tUpdateVHTOpMode *pHtOpMode = NULL;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pMac)
return QDF_STATUS_E_FAILURE;
pHtOpMode = qdf_mem_malloc(sizeof(tUpdateVHTOpMode));
if (NULL == pHtOpMode) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for setting OP mode",
__func__);
return QDF_STATUS_E_NOMEM;
}
switch (channel_type) {
case eHT_CHAN_HT20:
pHtOpMode->opMode = eHT_CHANNEL_WIDTH_20MHZ;
break;
case eHT_CHAN_HT40MINUS:
case eHT_CHAN_HT40PLUS:
pHtOpMode->opMode = eHT_CHANNEL_WIDTH_40MHZ;
break;
default:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Invalid OP mode", __func__);
return QDF_STATUS_E_FAILURE;
}
pHtOpMode->staId = staId,
qdf_mem_copy(pHtOpMode->peer_mac, macAddrSTA.bytes,
sizeof(tSirMacAddr));
pHtOpMode->smesessionId = sessionId;
msg.type = WMA_UPDATE_OP_MODE;
msg.reserved = 0;
msg.bodyptr = pHtOpMode;
if (!QDF_IS_STATUS_SUCCESS
(scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WMA_UPDATE_OP_MODE message to WMA",
__func__);
qdf_mem_free(pHtOpMode);
return QDF_STATUS_E_FAILURE;
}
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: Notified FW about OP mode: %d for staId=%d",
__func__, pHtOpMode->opMode, staId);
return QDF_STATUS_SUCCESS;
}
/*
* sme_set_ht2040_mode() -
* To update HT Operation beacon IE.
*
* Return QDF_STATUS SUCCESS
* FAILURE or RESOURCES
* The API finished and failed.
*/
QDF_STATUS sme_set_ht2040_mode(tHalHandle hHal, uint8_t sessionId,
uint8_t channel_type, bool obssEnabled)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
ePhyChanBondState cbMode;
struct csr_roam_session *session = CSR_GET_SESSION(pMac, sessionId);
if (!CSR_IS_SESSION_VALID(pMac, sessionId)) {
sme_err("Session not valid for session id %d", sessionId);
return QDF_STATUS_E_INVAL;
}
session = CSR_GET_SESSION(pMac, sessionId);
sme_debug("Update HT operation beacon IE, channel_type=%d cur cbmode %d",
channel_type, session->bssParams.cbMode);
switch (channel_type) {
case eHT_CHAN_HT20:
if (!session->bssParams.cbMode)
return QDF_STATUS_SUCCESS;
cbMode = PHY_SINGLE_CHANNEL_CENTERED;
break;
case eHT_CHAN_HT40MINUS:
if (session->bssParams.cbMode)
return QDF_STATUS_SUCCESS;
cbMode = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
break;
case eHT_CHAN_HT40PLUS:
if (session->bssParams.cbMode)
return QDF_STATUS_SUCCESS;
cbMode = PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
break;
default:
sme_err("Error!!! Invalid HT20/40 mode !");
return QDF_STATUS_E_FAILURE;
}
session->bssParams.cbMode = cbMode;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_set_ht2040_mode(pMac, sessionId,
cbMode, obssEnabled);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif
/*
* SME API to enable/disable idle mode powersave
* This should be called only if powersave offload
* is enabled
*/
QDF_STATUS sme_set_idle_powersave_config(bool value)
{
void *wmaContext = cds_get_context(QDF_MODULE_ID_WMA);
if (NULL == wmaContext) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: wmaContext is NULL", __func__);
return QDF_STATUS_E_FAILURE;
}
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
" Idle Ps Set Value %d", value);
if (QDF_STATUS_SUCCESS != wma_set_idle_ps_config(wmaContext, value)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
" Failed to Set Idle Ps Value %d", value);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
int16_t sme_get_ht_config(tHalHandle hHal, uint8_t session_id,
uint16_t ht_capab)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, session_id);
if (NULL == pSession) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: pSession is NULL", __func__);
return -EIO;
}
switch (ht_capab) {
case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
return pSession->htConfig.ht_rx_ldpc;
case WNI_CFG_HT_CAP_INFO_TX_STBC:
return pSession->htConfig.ht_tx_stbc;
case WNI_CFG_HT_CAP_INFO_RX_STBC:
return pSession->htConfig.ht_rx_stbc;
case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
return pSession->htConfig.ht_sgi20;
case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
return pSession->htConfig.ht_sgi40;
default:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"invalid ht capability");
return -EIO;
}
}
int sme_update_ht_config(tHalHandle hHal, uint8_t sessionId, uint16_t htCapab,
int value)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, sessionId);
if (NULL == pSession) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: pSession is NULL", __func__);
return -EIO;
}
if (QDF_STATUS_SUCCESS != wma_set_htconfig(sessionId, htCapab, value)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Failed to set ht capability in target");
return -EIO;
}
switch (htCapab) {
case WNI_CFG_HT_CAP_INFO_ADVANCE_CODING:
pSession->htConfig.ht_rx_ldpc = value;
pMac->roam.configParam.rx_ldpc_enable = value;
break;
case WNI_CFG_HT_CAP_INFO_TX_STBC:
pSession->htConfig.ht_tx_stbc = value;
break;
case WNI_CFG_HT_CAP_INFO_RX_STBC:
pSession->htConfig.ht_rx_stbc = value;
break;
case WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ:
value = value ? 1 : 0; /* HT SGI can be only 1 or 0 */
pSession->htConfig.ht_sgi20 = value;
break;
case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
value = value ? 1 : 0; /* HT SGI can be only 1 or 0 */
pSession->htConfig.ht_sgi40 = value;
break;
}
csr_roam_update_config(pMac, sessionId, htCapab, value);
return 0;
}
int sme_set_addba_accept(tHalHandle hal, uint8_t session_id, int value)
{
struct sme_addba_accept *addba_accept;
struct scheduler_msg msg = {0};
QDF_STATUS status;
addba_accept = qdf_mem_malloc(sizeof(*addba_accept));
if (!addba_accept) {
sme_err("mem alloc failed for addba_accept");
return -EIO;
}
addba_accept->session_id = session_id;
addba_accept->addba_accept = value;
qdf_mem_zero(&msg, sizeof(msg));
msg.type = eWNI_SME_SET_ADDBA_ACCEPT;
msg.reserved = 0;
msg.bodyptr = addba_accept;
status = scheduler_post_msg(QDF_MODULE_ID_PE, &msg);
if (status != QDF_STATUS_SUCCESS) {
sme_err("Not able to post addba reject");
qdf_mem_free(addba_accept);
return -EIO;
}
return 0;
}
int sme_set_ba_buff_size(tHalHandle hal, uint8_t session_id,
uint16_t buff_size)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
if (!buff_size) {
sme_err("invalid buff size %d", buff_size);
return -EINVAL;
}
mac_ctx->usr_cfg_ba_buff_size = buff_size;
sme_debug("addba buff size is set to %d",
mac_ctx->usr_cfg_ba_buff_size);
return 0;
}
#define DEFAULT_BA_BUFF_SIZE 64
int sme_send_addba_req(tHalHandle hal, uint8_t session_id, uint8_t tid,
uint16_t buff_size)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
uint16_t ba_buff = 0;
QDF_STATUS status;
struct scheduler_msg msg = {0};
struct send_add_ba_req *send_ba_req;
struct csr_roam_session *csr_session = NULL;
if (!csr_is_conn_state_connected_infra(mac_ctx, session_id)) {
sme_err("STA not infra/connected state session_id: %d",
session_id);
return -EINVAL;
}
csr_session = CSR_GET_SESSION(mac_ctx, session_id);
if (!csr_session) {
sme_err("CSR session is NULL");
return -EINVAL;
}
send_ba_req = qdf_mem_malloc(sizeof(*send_ba_req));
if (!send_ba_req) {
sme_err("mem alloc failed");
return -EIO;
}
qdf_mem_copy(send_ba_req->mac_addr,
csr_session->connectedProfile.bssid.bytes,
QDF_MAC_ADDR_SIZE);
ba_buff = buff_size;
if (!buff_size) {
if (mac_ctx->usr_cfg_ba_buff_size)
ba_buff = mac_ctx->usr_cfg_ba_buff_size;
else
ba_buff = DEFAULT_BA_BUFF_SIZE;
}
send_ba_req->param.vdev_id = session_id;
send_ba_req->param.tidno = tid;
send_ba_req->param.buffersize = ba_buff;
msg.type = WMA_SEND_ADDBA_REQ;
msg.bodyptr = send_ba_req;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (QDF_STATUS_SUCCESS != status) {
sme_err("Failed to post WMA_SEND_ADDBA_REQ");
qdf_mem_free(send_ba_req);
return -EIO;
}
sme_debug("ADDBA_REQ sent to FW: tid %d buff_size %d", tid, ba_buff);
return 0;
}
int sme_set_no_ack_policy(tHalHandle hal, uint8_t session_id,
uint8_t val, uint8_t ac)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
uint8_t i, set_val;
struct scheduler_msg msg = {0};
QDF_STATUS status;
if (ac > MAX_NUM_AC) {
sme_err("invalid ac val %d", ac);
return -EINVAL;
}
if (val)
set_val = 1;
else
set_val = 0;
if (ac == MAX_NUM_AC) {
for (i = 0; i < ac; i++)
mac_ctx->no_ack_policy_cfg[i] = set_val;
} else {
mac_ctx->no_ack_policy_cfg[ac] = set_val;
}
sme_debug("no ack is set to %d for ac %d", set_val, ac);
qdf_mem_zero(&msg, sizeof(msg));
msg.type = eWNI_SME_UPDATE_EDCA_PROFILE;
msg.reserved = 0;
msg.bodyval = session_id;
status = scheduler_post_msg(QDF_MODULE_ID_PE, &msg);
if (status != QDF_STATUS_SUCCESS) {
sme_err("Not able to post update edca profile");
return -EIO;
}
return 0;
}
int sme_set_auto_rate_he_ltf(tHalHandle hal, uint8_t session_id,
uint8_t cfg_val)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
uint32_t set_val;
uint32_t bit_mask = 0;
int status;
if (cfg_val > QCA_WLAN_HE_LTF_4X) {
sme_err("invalid HE LTF cfg %d", cfg_val);
return -EINVAL;
}
/*set the corresponding HE LTF cfg BIT*/
if (cfg_val == QCA_WLAN_HE_LTF_AUTO)
bit_mask = HE_LTF_ALL;
else
bit_mask = (1 << (cfg_val - 1));
set_val = mac_ctx->he_sgi_ltf_cfg_bit_mask;
SET_AUTO_RATE_HE_LTF_VAL(set_val, bit_mask);
mac_ctx->he_sgi_ltf_cfg_bit_mask = set_val;
status = wma_cli_set_command(session_id,
WMI_VDEV_PARAM_AUTORATE_MISC_CFG,
set_val, VDEV_CMD);
if (status) {
sme_err("failed to set he_ltf_sgi");
return status;
}
sme_debug("HE SGI_LTF is set to 0x%08X",
mac_ctx->he_sgi_ltf_cfg_bit_mask);
return 0;
}
int sme_set_auto_rate_he_sgi(tHalHandle hal, uint8_t session_id,
uint8_t cfg_val)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
uint32_t set_val;
uint32_t sgi_bit_mask = 0;
int status;
if ((cfg_val > AUTO_RATE_GI_3200NS) ||
(cfg_val < AUTO_RATE_GI_400NS)) {
sme_err("invalid auto rate GI cfg %d", cfg_val);
return -EINVAL;
}
sgi_bit_mask = (1 << cfg_val);
set_val = mac_ctx->he_sgi_ltf_cfg_bit_mask;
SET_AUTO_RATE_SGI_VAL(set_val, sgi_bit_mask);
mac_ctx->he_sgi_ltf_cfg_bit_mask = set_val;
status = wma_cli_set_command(session_id,
WMI_VDEV_PARAM_AUTORATE_MISC_CFG,
set_val, VDEV_CMD);
if (status) {
sme_err("failed to set he_ltf_sgi");
return status;
}
sme_debug("auto rate HE SGI_LTF is set to 0x%08X",
mac_ctx->he_sgi_ltf_cfg_bit_mask);
return 0;
}
#define HT20_SHORT_GI_MCS7_RATE 722
/*
* sme_send_rate_update_ind() -
* API to Update rate
*
* hHal - The handle returned by mac_open
* rateUpdateParams - Pointer to rate update params
* Return QDF_STATUS
*/
QDF_STATUS sme_send_rate_update_ind(tHalHandle hHal,
tSirRateUpdateInd *rateUpdateParams)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status;
struct scheduler_msg msg = {0};
tSirRateUpdateInd *rate_upd = qdf_mem_malloc(sizeof(tSirRateUpdateInd));
if (rate_upd == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Rate update struct alloc failed");
return QDF_STATUS_E_FAILURE;
}
*rate_upd = *rateUpdateParams;
if (rate_upd->mcastDataRate24GHz == HT20_SHORT_GI_MCS7_RATE)
rate_upd->mcastDataRate24GHzTxFlag =
TX_RATE_HT20 | TX_RATE_SGI;
else if (rate_upd->reliableMcastDataRate ==
HT20_SHORT_GI_MCS7_RATE)
rate_upd->reliableMcastDataRateTxFlag =
TX_RATE_HT20 | TX_RATE_SGI;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
msg.type = WMA_RATE_UPDATE_IND;
msg.bodyptr = rate_upd;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, msg.type));
if (!QDF_IS_STATUS_SUCCESS
(scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WMA_RATE_UPDATE_IND to WMA!",
__func__);
sme_release_global_lock(&pMac->sme);
qdf_mem_free(rate_upd);
return QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_SUCCESS;
}
return status;
}
/**
* sme_update_access_policy_vendor_ie() - update vendor ie and access policy.
* @hal: Pointer to the mac context
* @session_id: sme session id
* @vendor_ie: vendor ie
* @access_policy: vendor ie access policy
*
* This function updates the vendor ie and access policy to lim.
*
* Return: success or failure.
*/
QDF_STATUS sme_update_access_policy_vendor_ie(tHalHandle hal,
uint8_t session_id, uint8_t *vendor_ie, int access_policy)
{
struct sme_update_access_policy_vendor_ie *msg;
uint16_t msg_len;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
msg_len = sizeof(*msg);
msg = qdf_mem_malloc(msg_len);
if (!msg) {
sme_err("failed to allocate memory for sme_update_access_policy_vendor_ie");
return QDF_STATUS_E_FAILURE;
}
msg->msg_type = (uint16_t)eWNI_SME_UPDATE_ACCESS_POLICY_VENDOR_IE;
msg->length = (uint16_t)msg_len;
qdf_mem_copy(&msg->ie[0], vendor_ie, sizeof(msg->ie));
msg->sme_session_id = session_id;
msg->access_policy = access_policy;
sme_debug("sme_session_id: %hu, access_policy: %d", session_id,
access_policy);
status = umac_send_mb_message_to_mac(msg);
return status;
}
/**
* sme_update_short_retry_limit_threshold() - update short frame retry limit TH
* @hal: Handle returned by mac_open
* @session_id: Session ID on which short frame retry limit needs to be
* updated to FW
* @short_limit_count_th: Retry count TH to retry short frame.
*
* This function is used to configure count to retry short frame.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_update_short_retry_limit_threshold(tHalHandle hal_handle,
struct sme_short_retry_limit *short_retry_limit_th)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct sme_short_retry_limit *srl;
struct scheduler_msg msg = {0};
srl = qdf_mem_malloc(sizeof(*srl));
if (NULL == srl) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc short retry limit", __func__);
return QDF_STATUS_E_FAILURE;
}
sme_debug("session_id %d short retry limit count: %d",
short_retry_limit_th->session_id,
short_retry_limit_th->short_retry_limit);
srl->session_id = short_retry_limit_th->session_id;
srl->short_retry_limit = short_retry_limit_th->short_retry_limit;
qdf_mem_zero(&msg, sizeof(msg));
msg.type = SIR_HAL_SHORT_RETRY_LIMIT_CNT;
msg.reserved = 0;
msg.bodyptr = srl;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (status != QDF_STATUS_SUCCESS) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post short retry limit count to WDA"));
qdf_mem_free(srl);
return QDF_STATUS_E_FAILURE;
}
return status;
}
/**
* sme_update_long_retry_limit_threshold() - update long retry limit TH
* @hal: Handle returned by mac_open
* @session_id: Session ID on which long frames retry TH needs to be updated
* to FW
* @long_limit_count_th: Retry count to retry long frame.
*
* This function is used to configure TH to retry long frame.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_update_long_retry_limit_threshold(tHalHandle hal_handle,
struct sme_long_retry_limit *long_retry_limit_th)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct sme_long_retry_limit *lrl;
struct scheduler_msg msg = {0};
lrl = qdf_mem_malloc(sizeof(*lrl));
if (NULL == lrl) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc long retry limit", __func__);
return QDF_STATUS_E_FAILURE;
}
sme_debug("session_id %d long retry limit count: %d",
long_retry_limit_th->session_id,
long_retry_limit_th->long_retry_limit);
lrl->session_id = long_retry_limit_th->session_id;
lrl->long_retry_limit = long_retry_limit_th->long_retry_limit;
qdf_mem_zero(&msg, sizeof(msg));
msg.type = SIR_HAL_LONG_RETRY_LIMIT_CNT;
msg.reserved = 0;
msg.bodyptr = lrl;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (status != QDF_STATUS_SUCCESS) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post long retry limit count to WDA"));
qdf_mem_free(lrl);
return QDF_STATUS_E_FAILURE;
}
return status;
}
/**
* sme_update_sta_inactivity_timeout(): Update sta_inactivity_timeout to FW
* @hal: Handle returned by mac_open
* @session_id: Session ID on which sta_inactivity_timeout needs
* to be updated to FW
* @sta_inactivity_timeout: sta inactivity timeout.
*
* If a station does not send anything in sta_inactivity_timeout seconds, an
* empty data frame is sent to it in order to verify whether it is
* still in range. If this frame is not ACKed, the station will be
* disassociated and then deauthenticated.
*
* Return: QDF_STATUS_SUCCESS or non-zero on failure.
*/
QDF_STATUS sme_update_sta_inactivity_timeout(tHalHandle hal_handle,
struct sme_sta_inactivity_timeout *sta_inactivity_timer)
{
struct sme_sta_inactivity_timeout *inactivity_time;
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
inactivity_time = qdf_mem_malloc(sizeof(*inactivity_time));
if (NULL == inactivity_time) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc inactivity_time", __func__);
return QDF_STATUS_E_FAILURE;
}
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
FL("sta_inactivity_timeout: %d"),
sta_inactivity_timer->sta_inactivity_timeout);
inactivity_time->session_id = sta_inactivity_timer->session_id;
inactivity_time->sta_inactivity_timeout =
sta_inactivity_timer->sta_inactivity_timeout;
wma_update_sta_inactivity_timeout(wma_handle,
inactivity_time);
return QDF_STATUS_SUCCESS;
}
/**
* sme_get_reg_info() - To get registration info
* @hHal: HAL context
* @chanId: channel id
* @regInfo1: first reg info to fill
* @regInfo2: second reg info to fill
*
* This routine will give you reg info
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_get_reg_info(tHalHandle hHal, uint8_t chanId,
uint32_t *regInfo1, uint32_t *regInfo2)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status;
uint8_t i;
bool found = false;
status = sme_acquire_global_lock(&pMac->sme);
*regInfo1 = 0;
*regInfo2 = 0;
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
for (i = 0; i < WNI_CFG_VALID_CHANNEL_LIST_LEN; i++) {
if (pMac->scan.defaultPowerTable[i].chan_num == chanId) {
SME_SET_CHANNEL_REG_POWER(*regInfo1,
pMac->scan.defaultPowerTable[i].tx_power);
SME_SET_CHANNEL_MAX_TX_POWER(*regInfo2,
pMac->scan.defaultPowerTable[i].tx_power);
found = true;
break;
}
}
if (!found)
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
return status;
}
#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
/*
* sme_auto_shutdown_cb() -
* Used to plug in callback function for receiving auto shutdown evt
*
* hHal
* pCallbackfn : callback function pointer should be plugged in
* Return QDF_STATUS
*/
QDF_STATUS sme_set_auto_shutdown_cb(tHalHandle hHal, void (*pCallbackfn)(void)
) {
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Plug in Auto shutdown event callback", __func__);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
if (NULL != pCallbackfn)
pMac->sme.pAutoShutdownNotificationCb = pCallbackfn;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_auto_shutdown_timer() -
* API to set auto shutdown timer value in FW.
*
* hHal - The handle returned by mac_open
* timer_val - The auto shutdown timer value to be set
* Return Configuration message posting status, SUCCESS or Fail
*/
QDF_STATUS sme_set_auto_shutdown_timer(tHalHandle hHal, uint32_t timer_val)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSirAutoShutdownCmdParams *auto_sh_cmd;
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
auto_sh_cmd = (tSirAutoShutdownCmdParams *)
qdf_mem_malloc(sizeof(tSirAutoShutdownCmdParams));
if (auto_sh_cmd == NULL) {
sme_err("Request Buffer Alloc Fail");
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
auto_sh_cmd->timer_val = timer_val;
/* serialize the req through MC thread */
message.bodyptr = auto_sh_cmd;
message.type = WMA_SET_AUTO_SHUTDOWN_TIMER_REQ;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post Auto shutdown MSG fail", __func__);
qdf_mem_free(auto_sh_cmd);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: Posted Auto shutdown MSG", __func__);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif
#ifdef FEATURE_WLAN_CH_AVOID
/*
* sme_ch_avoid_update_req() -
* API to request channel avoidance update from FW.
*
* hHal - The handle returned by mac_open
* update_type - The update_type parameter of this request call
* Return Configuration message posting status, SUCCESS or Fail
*/
QDF_STATUS sme_ch_avoid_update_req(tHalHandle hHal)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSirChAvoidUpdateReq *cauReq;
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
cauReq = (tSirChAvoidUpdateReq *)
qdf_mem_malloc(sizeof(tSirChAvoidUpdateReq));
if (NULL == cauReq) {
sme_err("Request Buffer Alloc Fail");
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
cauReq->reserved_param = 0;
/* serialize the req through MC thread */
message.bodyptr = cauReq;
message.type = WMA_CH_AVOID_UPDATE_REQ;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post Ch Avoid Update MSG fail",
__func__);
qdf_mem_free(cauReq);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: Posted Ch Avoid Update MSG", __func__);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif
/**
* sme_set_miracast() - Function to set miracast value to UMAC
* @hal: Handle returned by macOpen
* @filter_type: 0-Disabled, 1-Source, 2-sink
*
* This function passes down the value of miracast set by
* framework to UMAC
*
* Return: Configuration message posting status, SUCCESS or Fail
*
*/
QDF_STATUS sme_set_miracast(tHalHandle hal, uint8_t filter_type)
{
struct scheduler_msg msg = {0};
uint32_t *val;
tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal);
val = qdf_mem_malloc(sizeof(*val));
if (NULL == val || NULL == mac_ptr) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Invalid pointer", __func__);
return QDF_STATUS_E_NOMEM;
}
*val = filter_type;
msg.type = SIR_HAL_SET_MIRACAST;
msg.reserved = 0;
msg.bodyptr = val;
if (!QDF_IS_STATUS_SUCCESS(
scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WDA_SET_MAS_ENABLE_DISABLE to WMA!",
__func__);
qdf_mem_free(val);
return QDF_STATUS_E_FAILURE;
}
mac_ptr->sme.miracast_value = filter_type;
return QDF_STATUS_SUCCESS;
}
/**
* sme_set_mas() - Function to set MAS value to UMAC
* @val: 1-Enable, 0-Disable
*
* This function passes down the value of MAS to the UMAC. A
* value of 1 will enable MAS and a value of 0 will disable MAS
*
* Return: Configuration message posting status, SUCCESS or Fail
*
*/
QDF_STATUS sme_set_mas(uint32_t val)
{
struct scheduler_msg msg = {0};
uint32_t *ptr_val;
ptr_val = qdf_mem_malloc(sizeof(*ptr_val));
if (NULL == ptr_val) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: could not allocate ptr_val", __func__);
return QDF_STATUS_E_NOMEM;
}
*ptr_val = val;
msg.type = SIR_HAL_SET_MAS;
msg.reserved = 0;
msg.bodyptr = ptr_val;
if (!QDF_IS_STATUS_SUCCESS(
scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WDA_SET_MAS_ENABLE_DISABLE to WMA!",
__func__);
qdf_mem_free(ptr_val);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* sme_roam_channel_change_req() - Channel change to new target channel
* @hHal: handle returned by mac_open
* @bssid: mac address of BSS
* @ch_params: target channel information
* @profile: CSR profile
*
* API to Indicate Channel change to new target channel
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_roam_channel_change_req(tHalHandle hHal,
struct qdf_mac_addr bssid,
struct ch_params *ch_params,
struct csr_roam_profile *profile)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_roam_channel_change_req(pMac, bssid, ch_params,
profile);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_process_channel_change_resp() -
* API to Indicate Channel change response message to SAP.
*
* Return QDF_STATUS
*/
static QDF_STATUS sme_process_channel_change_resp(tpAniSirGlobal pMac,
uint16_t msg_type, void *pMsgBuf)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_roam_info proam_info = { 0 };
eCsrRoamResult roamResult;
tpSwitchChannelParams pChnlParams = (tpSwitchChannelParams) pMsgBuf;
uint32_t SessionId = pChnlParams->peSessionId;
proam_info.channelChangeRespEvent =
(tSirChanChangeResponse *)
qdf_mem_malloc(sizeof(tSirChanChangeResponse));
if (NULL == proam_info.channelChangeRespEvent) {
status = QDF_STATUS_E_NOMEM;
sme_err("Channel Change Event Allocation Failed: %d\n", status);
return status;
}
if (msg_type == eWNI_SME_CHANNEL_CHANGE_RSP) {
proam_info.channelChangeRespEvent->sessionId = SessionId;
proam_info.channelChangeRespEvent->newChannelNumber =
pChnlParams->channelNumber;
if (pChnlParams->status == QDF_STATUS_SUCCESS) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"sapdfs: Received success eWNI_SME_CHANNEL_CHANGE_RSP for sessionId[%d]",
SessionId);
proam_info.channelChangeRespEvent->channelChangeStatus =
1;
roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS;
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"sapdfs: Received failure eWNI_SME_CHANNEL_CHANGE_RSP for sessionId[%d]",
SessionId);
proam_info.channelChangeRespEvent->channelChangeStatus =
0;
roamResult = eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE;
}
csr_roam_call_callback(pMac, SessionId, &proam_info, 0,
eCSR_ROAM_SET_CHANNEL_RSP, roamResult);
} else {
status = QDF_STATUS_E_FAILURE;
sme_err("Invalid Channel Change Resp Message: %d",
status);
}
qdf_mem_free(proam_info.channelChangeRespEvent);
return status;
}
/*
* sme_roam_start_beacon_req() -
* API to Indicate LIM to start Beacon Tx after SAP CAC Wait is completed.
*
* hHal - The handle returned by mac_open
* sessionId - session ID
* dfsCacWaitStatus - CAC WAIT status flag
* Return QDF_STATUS
*/
QDF_STATUS sme_roam_start_beacon_req(tHalHandle hHal, struct qdf_mac_addr bssid,
uint8_t dfsCacWaitStatus)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_roam_start_beacon_req(pMac, bssid,
dfsCacWaitStatus);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_roam_csa_ie_request() - request CSA IE transmission from PE
* @hHal: handle returned by mac_open
* @bssid: SAP bssid
* @targetChannel: target channel information
* @csaIeReqd: CSA IE Request
* @ch_params: channel information
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_roam_csa_ie_request(tHalHandle hHal, struct qdf_mac_addr bssid,
uint8_t targetChannel, uint8_t csaIeReqd,
struct ch_params *ch_params)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_roam_send_chan_sw_ie_request(pMac, bssid,
targetChannel, csaIeReqd, ch_params);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_init_thermal_info() -
* SME API to initialize the thermal mitigation parameters
*
* hHal
* thermalParam : thermal mitigation parameters
* Return QDF_STATUS
*/
QDF_STATUS sme_init_thermal_info(tHalHandle hHal, tSmeThermalParams
thermalParam)
{
t_thermal_mgmt *pWmaParam;
struct scheduler_msg msg = {0};
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pWmaParam = (t_thermal_mgmt *) qdf_mem_malloc(sizeof(t_thermal_mgmt));
if (NULL == pWmaParam) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: could not allocate tThermalMgmt", __func__);
return QDF_STATUS_E_NOMEM;
}
pWmaParam->thermalMgmtEnabled = thermalParam.smeThermalMgmtEnabled;
pWmaParam->throttlePeriod = thermalParam.smeThrottlePeriod;
pWmaParam->throttle_duty_cycle_tbl[0] =
thermalParam.sme_throttle_duty_cycle_tbl[0];
pWmaParam->throttle_duty_cycle_tbl[1] =
thermalParam.sme_throttle_duty_cycle_tbl[1];
pWmaParam->throttle_duty_cycle_tbl[2] =
thermalParam.sme_throttle_duty_cycle_tbl[2];
pWmaParam->throttle_duty_cycle_tbl[3] =
thermalParam.sme_throttle_duty_cycle_tbl[3];
pWmaParam->thermalLevels[0].minTempThreshold =
thermalParam.smeThermalLevels[0].smeMinTempThreshold;
pWmaParam->thermalLevels[0].maxTempThreshold =
thermalParam.smeThermalLevels[0].smeMaxTempThreshold;
pWmaParam->thermalLevels[1].minTempThreshold =
thermalParam.smeThermalLevels[1].smeMinTempThreshold;
pWmaParam->thermalLevels[1].maxTempThreshold =
thermalParam.smeThermalLevels[1].smeMaxTempThreshold;
pWmaParam->thermalLevels[2].minTempThreshold =
thermalParam.smeThermalLevels[2].smeMinTempThreshold;
pWmaParam->thermalLevels[2].maxTempThreshold =
thermalParam.smeThermalLevels[2].smeMaxTempThreshold;
pWmaParam->thermalLevels[3].minTempThreshold =
thermalParam.smeThermalLevels[3].smeMinTempThreshold;
pWmaParam->thermalLevels[3].maxTempThreshold =
thermalParam.smeThermalLevels[3].smeMaxTempThreshold;
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
msg.type = WMA_INIT_THERMAL_INFO_CMD;
msg.bodyptr = pWmaParam;
if (!QDF_IS_STATUS_SUCCESS
(scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WMA_SET_THERMAL_INFO_CMD to WMA!",
__func__);
qdf_mem_free(pWmaParam);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_SUCCESS;
}
qdf_mem_free(pWmaParam);
return QDF_STATUS_E_FAILURE;
}
/**
* sme_add_set_thermal_level_callback() - Plug in set thermal level callback
* @hal: Handle returned by macOpen
* @callback: sme_set_thermal_level_callback
*
* Plug in set thermal level callback
*
* Return: none
*/
void sme_add_set_thermal_level_callback(tHalHandle hal,
sme_set_thermal_level_callback callback)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hal);
pMac->sme.set_thermal_level_cb = callback;
}
/**
* sme_set_thermal_level() - SME API to set the thermal mitigation level
* @hal: Handler to HAL
* @level: Thermal mitigation level
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_set_thermal_level(tHalHandle hal, uint8_t level)
{
struct scheduler_msg msg = {0};
tpAniSirGlobal pMac = PMAC_STRUCT(hal);
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
qdf_mem_set(&msg, sizeof(msg), 0);
msg.type = WMA_SET_THERMAL_LEVEL;
msg.bodyval = level;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WMA_SET_THERMAL_LEVEL to WMA!",
__func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_SUCCESS;
}
return QDF_STATUS_E_FAILURE;
}
/*
* sme_txpower_limit() -
* SME API to set txpower limits
*
* hHal
* psmetx : power limits for 2g/5g
* Return QDF_STATUS
*/
QDF_STATUS sme_txpower_limit(tHalHandle hHal, tSirTxPowerLimit *psmetx)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
struct scheduler_msg message = {0};
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSirTxPowerLimit *tx_power_limit;
tx_power_limit = qdf_mem_malloc(sizeof(*tx_power_limit));
if (!tx_power_limit) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Memory allocation for TxPowerLimit failed!",
__func__);
return QDF_STATUS_E_FAILURE;
}
*tx_power_limit = *psmetx;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
message.type = WMA_TX_POWER_LIMIT;
message.reserved = 0;
message.bodyptr = tx_power_limit;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: not able to post WMA_TX_POWER_LIMIT",
__func__);
status = QDF_STATUS_E_FAILURE;
qdf_mem_free(tx_power_limit);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
QDF_STATUS sme_update_connect_debug(tHalHandle hHal, uint32_t set_value)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pMac->fEnableDebugLog = set_value;
return status;
}
/*
* sme_ap_disable_intra_bss_fwd() -
* SME will send message to WMA to set Intra BSS in txrx
*
* hHal - The handle returned by mac_open
* sessionId - session id ( vdev id)
* disablefwd - bool value that indicate disable intrabss fwd disable
* Return QDF_STATUS
*/
QDF_STATUS sme_ap_disable_intra_bss_fwd(tHalHandle hHal, uint8_t sessionId,
bool disablefwd)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
int status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
struct scheduler_msg message = {0};
tpDisableIntraBssFwd pSapDisableIntraFwd = NULL;
/* Prepare the request to send to SME. */
pSapDisableIntraFwd = qdf_mem_malloc(sizeof(tDisableIntraBssFwd));
if (NULL == pSapDisableIntraFwd) {
sme_err("Memory Allocation Failure!!!");
return QDF_STATUS_E_NOMEM;
}
pSapDisableIntraFwd->sessionId = sessionId;
pSapDisableIntraFwd->disableintrabssfwd = disablefwd;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* serialize the req through MC thread */
message.bodyptr = pSapDisableIntraFwd;
message.type = WMA_SET_SAP_INTRABSS_DIS;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
status = QDF_STATUS_E_FAILURE;
qdf_mem_free(pSapDisableIntraFwd);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
#ifdef WLAN_FEATURE_STATS_EXT
void sme_stats_ext_register_callback(mac_handle_t mac_handle,
stats_ext_cb callback)
{
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
if (!mac) {
sme_err("Invalid mac context");
return;
}
mac->sme.stats_ext_cb = callback;
}
void sme_stats_ext_deregister_callback(mac_handle_t mac_handle)
{
sme_stats_ext_register_callback(mac_handle, NULL);
}
void sme_stats_ext2_register_callback(mac_handle_t mac_handle,
stats_ext2_cb callback)
{
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
if (!mac) {
sme_err("Invalid mac context");
return;
}
mac->sme.stats_ext2_cb = callback;
}
/*
* sme_stats_ext_request() -
* Function called when HDD receives STATS EXT vendor command from userspace
*
* sessionID - vdevID for the stats ext request
* input - Stats Ext Request structure ptr
* Return QDF_STATUS
*/
QDF_STATUS sme_stats_ext_request(uint8_t session_id, tpStatsExtRequestReq input)
{
struct scheduler_msg msg = {0};
tpStatsExtRequest data;
size_t data_len;
data_len = sizeof(tStatsExtRequest) + input->request_data_len;
data = qdf_mem_malloc(data_len);
if (data == NULL)
return QDF_STATUS_E_NOMEM;
data->vdev_id = session_id;
data->request_data_len = input->request_data_len;
if (input->request_data_len)
qdf_mem_copy(data->request_data,
input->request_data, input->request_data_len);
msg.type = WMA_STATS_EXT_REQUEST;
msg.reserved = 0;
msg.bodyptr = data;
if (QDF_STATUS_SUCCESS != scheduler_post_msg(QDF_MODULE_ID_WMA,
&msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WMA_STATS_EXT_REQUEST message to WMA",
__func__);
qdf_mem_free(data);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* sme_stats_ext_event() - eWNI_SME_STATS_EXT_EVENT processor
* @mac: Global MAC context
* @msg: "stats ext" message
* This callback function called when SME received eWNI_SME_STATS_EXT_EVENT
* response from WMA
*
* Return: QDF_STATUS
*/
static QDF_STATUS sme_stats_ext_event(tpAniSirGlobal mac,
struct stats_ext_event *msg)
{
if (!msg) {
sme_err("Null msg");
return QDF_STATUS_E_FAILURE;
}
if (mac->sme.stats_ext_cb)
mac->sme.stats_ext_cb(mac->hdd_handle, msg);
return QDF_STATUS_SUCCESS;
}
#else
static QDF_STATUS sme_stats_ext_event(tpAniSirGlobal mac,
struct stats_ext_event *msg)
{
return QDF_STATUS_SUCCESS;
}
#endif
/*
* sme_update_dfs_scan_mode() -
* Update DFS roam scan mode
* This function is called through dynamic setConfig callback function
* to configure allowDFSChannelRoam.
* hHal - HAL handle for device
* sessionId - Session Identifier
* allowDFSChannelRoam - DFS roaming scan mode 0 (disable),
* 1 (passive), 2 (active)
* Return QDF_STATUS_SUCCESS - SME update DFS roaming scan config
* successfully.
* Other status means SME failed to update DFS roaming scan config.
*/
QDF_STATUS sme_update_dfs_scan_mode(tHalHandle hHal, uint8_t sessionId,
uint8_t allowDFSChannelRoam)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (sessionId >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), sessionId);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"LFR runtime successfully set AllowDFSChannelRoam Mode to %d - old value is %d - roam state is %s",
allowDFSChannelRoam,
pMac->roam.configParam.allowDFSChannelRoam,
mac_trace_get_neighbour_roam_state(pMac->roam.
neighborRoamInfo
[sessionId].
neighborRoamState));
pMac->roam.configParam.allowDFSChannelRoam =
allowDFSChannelRoam;
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_ROAM_DFS_SCAN_MODE_CHANGED);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_dfs_scan_mode() - get DFS roam scan mode
* This is a synchronous call
*
* hHal - The handle returned by mac_open.
* Return DFS roaming scan mode 0 (disable), 1 (passive), 2 (active)
*/
uint8_t sme_get_dfs_scan_mode(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.allowDFSChannelRoam;
}
/*
* sme_modify_add_ie() -
* This function sends msg to updates the additional IE buffers in PE
*
* hHal - global structure
* pModifyIE - pointer to tModifyIE structure
* updateType - type of buffer
* Return Success or failure
*/
QDF_STATUS sme_modify_add_ie(tHalHandle hHal,
tSirModifyIE *pModifyIE, eUpdateIEsType updateType)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_roam_modify_add_ies(pMac, pModifyIE, updateType);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_update_add_ie() -
* This function sends msg to updates the additional IE buffers in PE
*
* hHal - global structure
* pUpdateIE - pointer to structure tUpdateIE
* updateType - type of buffer
* Return Success or failure
*/
QDF_STATUS sme_update_add_ie(tHalHandle hHal,
tSirUpdateIE *pUpdateIE, eUpdateIEsType updateType)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_roam_update_add_ies(pMac, pUpdateIE, updateType);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_update_dsc_pto_up_mapping()
* @hHal: HAL context
* @dscpmapping: pointer to DSCP mapping structure
* @sessionId: SME session id
*
* This routine is called to update dscp mapping
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_update_dsc_pto_up_mapping(tHalHandle hHal,
enum sme_qos_wmmuptype *dscpmapping,
uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t i, j, peSessionId;
struct csr_roam_session *pCsrSession = NULL;
tpPESession pSession = NULL;
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
pCsrSession = CSR_GET_SESSION(pMac, sessionId);
if (pCsrSession == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Session lookup fails for CSR session"));
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
if (!CSR_IS_SESSION_VALID(pMac, sessionId)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid session Id %u"), sessionId);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
pSession = pe_find_session_by_bssid(pMac,
pCsrSession->connectedProfile.bssid.bytes,
&peSessionId);
if (pSession == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL(" Session lookup fails for BSSID"));
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
if (!pSession->QosMapSet.present) {
sme_debug("QOS Mapping IE not present");
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
for (i = 0; i < SME_QOS_WMM_UP_MAX; i++) {
for (j = pSession->QosMapSet.dscp_range[i][0];
j <= pSession->QosMapSet.dscp_range[i][1];
j++) {
if ((pSession->QosMapSet.dscp_range[i][0] == 255)
&& (pSession->QosMapSet.dscp_range[i][1] ==
255)) {
QDF_TRACE(QDF_MODULE_ID_SME,
QDF_TRACE_LEVEL_DEBUG,
FL("User Priority %d isn't used"), i);
break;
} else {
dscpmapping[j] = i;
}
}
}
for (i = 0; i < pSession->QosMapSet.num_dscp_exceptions; i++)
if (pSession->QosMapSet.dscp_exceptions[i][0] != 255)
dscpmapping[pSession->QosMapSet.dscp_exceptions[i][0]] =
pSession->QosMapSet.dscp_exceptions[i][1];
sme_release_global_lock(&pMac->sme);
return status;
}
/*
* sme_abort_roam_scan() -
* API to abort current roam scan cycle by roam scan offload module.
*
* hHal - The handle returned by mac_open.
* sessionId - Session Identifier
* Return QDF_STATUS
*/
QDF_STATUS sme_abort_roam_scan(tHalHandle hHal, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
/* acquire the lock for the sme object */
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_ABORT_SCAN,
REASON_ROAM_ABORT_ROAM_SCAN);
/* release the lock for the sme object */
sme_release_global_lock(&pMac->sme);
}
}
return status;
}
#ifdef FEATURE_WLAN_EXTSCAN
/**
* sme_get_valid_channels_by_band() - to fetch valid channels filtered by band
* @hHal: HAL context
* @wifiBand: RF band information
* @aValidChannels: output array to store channel info
* @pNumChannels: output number of channels
*
* SME API to fetch all valid channels filtered by band
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_get_valid_channels_by_band(tHalHandle hHal,
uint8_t wifiBand,
uint32_t *aValidChannels,
uint8_t *pNumChannels)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t chanList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = { 0 };
uint8_t numChannels = 0;
uint8_t i = 0;
uint32_t totValidChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal);
if (!aValidChannels || !pNumChannels) {
sme_err("Output channel list/NumChannels is NULL");
return QDF_STATUS_E_INVAL;
}
if (wifiBand >= WIFI_BAND_MAX) {
sme_err("Invalid wifiBand: %d", wifiBand);
return QDF_STATUS_E_INVAL;
}
status = sme_get_cfg_valid_channels(&chanList[0],
&totValidChannels);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Fail to get valid channel list (err=%d)", status);
return status;
}
switch (wifiBand) {
case WIFI_BAND_UNSPECIFIED:
sme_debug("Unspec Band, return all %d valid channels",
totValidChannels);
numChannels = totValidChannels;
for (i = 0; i < totValidChannels; i++)
aValidChannels[i] = cds_chan_to_freq(chanList[i]);
break;
case WIFI_BAND_BG:
sme_debug("WIFI_BAND_BG (2.4 GHz)");
for (i = 0; i < totValidChannels; i++) {
if (WLAN_REG_IS_24GHZ_CH(chanList[i]))
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
break;
case WIFI_BAND_A:
sme_debug("WIFI_BAND_A (5 GHz without DFS)");
for (i = 0; i < totValidChannels; i++) {
if (WLAN_REG_IS_5GHZ_CH(chanList[i]) &&
!wlan_reg_is_dfs_ch(mac_ctx->pdev, chanList[i]))
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
break;
case WIFI_BAND_ABG:
sme_debug("WIFI_BAND_ABG (2.4 GHz + 5 GHz; no DFS)");
for (i = 0; i < totValidChannels; i++) {
if ((WLAN_REG_IS_24GHZ_CH(chanList[i]) ||
WLAN_REG_IS_5GHZ_CH(chanList[i])) &&
!wlan_reg_is_dfs_ch(mac_ctx->pdev, chanList[i]))
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
break;
case WIFI_BAND_A_DFS_ONLY:
sme_debug("WIFI_BAND_A_DFS (5 GHz DFS only)");
for (i = 0; i < totValidChannels; i++) {
if (WLAN_REG_IS_5GHZ_CH(chanList[i]) &&
wlan_reg_is_dfs_ch(mac_ctx->pdev, chanList[i]))
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
break;
case WIFI_BAND_A_WITH_DFS:
sme_debug("WIFI_BAND_A_WITH_DFS (5 GHz with DFS)");
for (i = 0; i < totValidChannels; i++) {
if (WLAN_REG_IS_5GHZ_CH(chanList[i]))
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
break;
case WIFI_BAND_ABG_WITH_DFS:
sme_debug("WIFI_BAND_ABG_WITH_DFS (2.4 GHz+5 GHz with DFS)");
for (i = 0; i < totValidChannels; i++) {
if (WLAN_REG_IS_24GHZ_CH(chanList[i]) ||
WLAN_REG_IS_5GHZ_CH(chanList[i]))
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
break;
default:
sme_err("Unknown wifiBand: %d", wifiBand);
return QDF_STATUS_E_INVAL;
}
*pNumChannels = numChannels;
return status;
}
/*
* sme_ext_scan_get_capabilities() -
* SME API to fetch extscan capabilities
*
* hHal
* pReq: extscan capabilities structure
* Return QDF_STATUS
*/
QDF_STATUS sme_ext_scan_get_capabilities(tHalHandle hHal,
tSirGetExtScanCapabilitiesReqParams *
pReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = pReq;
message.type = WMA_EXTSCAN_GET_CAPABILITIES_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_ext_scan_start() -
* SME API to issue extscan start
*
* hHal
* pStartCmd: extscan start structure
* Return QDF_STATUS
*/
QDF_STATUS sme_ext_scan_start(tHalHandle hHal,
tSirWifiScanCmdReqParams *pStartCmd)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = pStartCmd;
message.type = WMA_EXTSCAN_START_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_ext_scan_stop() -
* SME API to issue extscan stop
*
* hHal
* pStopReq: extscan stop structure
* Return QDF_STATUS
*/
QDF_STATUS sme_ext_scan_stop(tHalHandle hHal, tSirExtScanStopReqParams
*pStopReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = pStopReq;
message.type = WMA_EXTSCAN_STOP_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
QDF_STATUS
sme_set_bss_hotlist(mac_handle_t mac_handle,
struct extscan_bssid_hotlist_set_params *params)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
struct scheduler_msg message = {0};
struct extscan_bssid_hotlist_set_params *bodyptr;
/* per contract must make a copy of the params when messaging */
bodyptr = qdf_mem_malloc(sizeof(*bodyptr));
if (!bodyptr) {
sme_err("buffer allocation failure");
return QDF_STATUS_E_NOMEM;
}
*bodyptr = *params;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = bodyptr;
message.type = WMA_EXTSCAN_SET_BSSID_HOTLIST_REQ;
qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type);
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
sme_release_global_lock(&mac->sme);
}
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("failure: %d", status);
qdf_mem_free(bodyptr);
}
return status;
}
QDF_STATUS
sme_reset_bss_hotlist(mac_handle_t mac_handle,
struct extscan_bssid_hotlist_reset_params *params)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
struct scheduler_msg message = {0};
struct extscan_bssid_hotlist_reset_params *bodyptr;
/* per contract must make a copy of the params when messaging */
bodyptr = qdf_mem_malloc(sizeof(*bodyptr));
if (!bodyptr) {
sme_err("buffer allocation failure");
return QDF_STATUS_E_NOMEM;
}
*bodyptr = *params;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = bodyptr;
message.type = WMA_EXTSCAN_RESET_BSSID_HOTLIST_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
sme_release_global_lock(&mac->sme);
}
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("failure: %d", status);
qdf_mem_free(bodyptr);
}
return status;
}
QDF_STATUS
sme_set_significant_change(mac_handle_t mac_handle,
struct extscan_set_sig_changereq_params *params)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
struct scheduler_msg message = {0};
struct extscan_set_sig_changereq_params *bodyptr;
/* per contract must make a copy of the params when messaging */
bodyptr = qdf_mem_malloc(sizeof(*bodyptr));
if (!bodyptr) {
sme_err("buffer allocation failure");
return QDF_STATUS_E_NOMEM;
}
*bodyptr = *params;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = bodyptr;
message.type = WMA_EXTSCAN_SET_SIGNF_CHANGE_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
sme_release_global_lock(&mac->sme);
}
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("failure: %d", status);
qdf_mem_free(bodyptr);
}
return status;
}
/*
* sme_reset_significant_change
* SME API to reset significant change
*
* hHal
* pResetReq: extscan reset significant change structure
* Return QDF_STATUS
*/
QDF_STATUS sme_reset_significant_change(tHalHandle hHal,
tSirExtScanResetSignificantChangeReqParams
*pResetReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = pResetReq;
message.type = WMA_EXTSCAN_RESET_SIGNF_CHANGE_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_get_cached_results() -
* SME API to get cached results
*
* hHal
* pCachedResultsReq: extscan get cached results structure
* Return QDF_STATUS
*/
QDF_STATUS sme_get_cached_results(tHalHandle hHal,
tSirExtScanGetCachedResultsReqParams *
pCachedResultsReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = pCachedResultsReq;
message.type = WMA_EXTSCAN_GET_CACHED_RESULTS_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_set_epno_list() - set epno network list
* @hal: global hal handle
* @input: request message
*
* This function constructs the cds message and fill in message type,
* bodyptr with %input and posts it to WDA queue.
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_set_epno_list(tHalHandle hal,
struct wifi_epno_params *input)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct scheduler_msg message = {0};
struct wifi_epno_params *req_msg;
int len, i;
SME_ENTER();
len = sizeof(*req_msg) +
(input->num_networks * sizeof(struct wifi_epno_network));
req_msg = qdf_mem_malloc(len);
if (!req_msg) {
sme_err("qdf_mem_malloc failed");
return QDF_STATUS_E_NOMEM;
}
req_msg->num_networks = input->num_networks;
req_msg->request_id = input->request_id;
req_msg->session_id = input->session_id;
/* Fill only when num_networks are non zero */
if (req_msg->num_networks) {
req_msg->min_5ghz_rssi = input->min_5ghz_rssi;
req_msg->min_24ghz_rssi = input->min_24ghz_rssi;
req_msg->initial_score_max = input->initial_score_max;
req_msg->same_network_bonus = input->same_network_bonus;
req_msg->secure_bonus = input->secure_bonus;
req_msg->band_5ghz_bonus = input->band_5ghz_bonus;
req_msg->current_connection_bonus =
input->current_connection_bonus;
for (i = 0; i < req_msg->num_networks; i++) {
req_msg->networks[i].flags = input->networks[i].flags;
req_msg->networks[i].auth_bit_field =
input->networks[i].auth_bit_field;
req_msg->networks[i].ssid.length =
input->networks[i].ssid.length;
qdf_mem_copy(req_msg->networks[i].ssid.ssId,
input->networks[i].ssid.ssId,
req_msg->networks[i].ssid.length);
}
}
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("sme_acquire_global_lock failed!(status=%d)",
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
message.bodyptr = req_msg;
message.type = WMA_SET_EPNO_LIST_REQ;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("scheduler_post_msg failed!(err=%d)",
status);
qdf_mem_free(req_msg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
return status;
}
/**
* sme_set_passpoint_list() - set passpoint network list
* @hal: global hal handle
* @input: request message
*
* This function constructs the cds message and fill in message type,
* bodyptr with @input and posts it to WDA queue.
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_set_passpoint_list(tHalHandle hal,
struct wifi_passpoint_req *input)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct scheduler_msg message = {0};
struct wifi_passpoint_req *req_msg;
int len, i;
SME_ENTER();
len = sizeof(*req_msg) +
(input->num_networks * sizeof(struct wifi_passpoint_network));
req_msg = qdf_mem_malloc(len);
if (!req_msg) {
sme_err("qdf_mem_malloc failed");
return QDF_STATUS_E_NOMEM;
}
req_msg->num_networks = input->num_networks;
req_msg->request_id = input->request_id;
req_msg->session_id = input->session_id;
for (i = 0; i < req_msg->num_networks; i++) {
req_msg->networks[i].id =
input->networks[i].id;
qdf_mem_copy(req_msg->networks[i].realm,
input->networks[i].realm,
strlen(input->networks[i].realm) + 1);
qdf_mem_copy(req_msg->networks[i].plmn,
input->networks[i].plmn,
SIR_PASSPOINT_PLMN_LEN);
qdf_mem_copy(req_msg->networks[i].roaming_consortium_ids,
input->networks[i].roaming_consortium_ids,
sizeof(req_msg->networks[i].roaming_consortium_ids));
}
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("sme_acquire_global_lock failed!(status=%d)",
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
message.bodyptr = req_msg;
message.type = WMA_SET_PASSPOINT_LIST_REQ;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("scheduler_post_msg failed!(err=%d)",
status);
qdf_mem_free(req_msg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
return status;
}
/**
* sme_reset_passpoint_list() - reset passpoint network list
* @hHal: global hal handle
* @input: request message
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_reset_passpoint_list(tHalHandle hal,
struct wifi_passpoint_req *input)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct scheduler_msg message = {0};
struct wifi_passpoint_req *req_msg;
SME_ENTER();
req_msg = qdf_mem_malloc(sizeof(*req_msg));
if (!req_msg) {
sme_err("qdf_mem_malloc failed");
return QDF_STATUS_E_NOMEM;
}
req_msg->request_id = input->request_id;
req_msg->session_id = input->session_id;
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("sme_acquire_global_lock failed!(status=%d)",
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
message.bodyptr = req_msg;
message.type = WMA_RESET_PASSPOINT_LIST_REQ;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("scheduler_post_msg failed!(err=%d)",
status);
qdf_mem_free(req_msg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
return status;
}
QDF_STATUS sme_ext_scan_register_callback(mac_handle_t mac_handle,
ext_scan_ind_cb ext_scan_ind_cb)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.ext_scan_ind_cb = ext_scan_ind_cb;
sme_release_global_lock(&mac->sme);
}
return status;
}
#endif /* FEATURE_WLAN_EXTSCAN */
/**
* sme_send_wisa_params(): Pass WISA mode to WMA
* @hal: HAL context
* @wisa_params: pointer to WISA params struct
* @sessionId: SME session id
*
* Pass WISA params to WMA
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_set_wisa_params(tHalHandle hal,
struct sir_wisa_params *wisa_params)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct scheduler_msg message = {0};
struct sir_wisa_params *cds_msg_wisa_params;
cds_msg_wisa_params = qdf_mem_malloc(sizeof(struct sir_wisa_params));
if (!cds_msg_wisa_params)
return QDF_STATUS_E_NOMEM;
*cds_msg_wisa_params = *wisa_params;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
message.bodyptr = cds_msg_wisa_params;
message.type = WMA_SET_WISA_PARAMS;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
sme_release_global_lock(&mac->sme);
}
return status;
}
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
/*
* sme_ll_stats_clear_req() -
* SME API to clear Link Layer Statistics
*
* hHal
* pclearStatsReq: Link Layer clear stats request params structure
* Return QDF_STATUS
*/
QDF_STATUS sme_ll_stats_clear_req(tHalHandle hHal,
tSirLLStatsClearReq *pclearStatsReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tSirLLStatsClearReq *clear_stats_req;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"staId = %u", pclearStatsReq->staId);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"statsClearReqMask = 0x%X",
pclearStatsReq->statsClearReqMask);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"stopReq = %u", pclearStatsReq->stopReq);
if (!sme_is_session_id_valid(hHal, pclearStatsReq->staId)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: invalid staId %d",
__func__, pclearStatsReq->staId);
return QDF_STATUS_E_INVAL;
}
clear_stats_req = qdf_mem_malloc(sizeof(*clear_stats_req));
if (!clear_stats_req) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for WMA_LL_STATS_CLEAR_REQ",
__func__);
return QDF_STATUS_E_NOMEM;
}
*clear_stats_req = *pclearStatsReq;
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
/* Serialize the req through MC thread */
message.bodyptr = clear_stats_req;
message.type = WMA_LINK_LAYER_STATS_CLEAR_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: not able to post WMA_LL_STATS_CLEAR_REQ",
__func__);
qdf_mem_free(clear_stats_req);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: sme_acquire_global_lock error", __func__);
qdf_mem_free(clear_stats_req);
status = QDF_STATUS_E_FAILURE;
}
return status;
}
/*
* sme_ll_stats_set_req() -
* SME API to set the Link Layer Statistics
*
* hHal
* psetStatsReq: Link Layer set stats request params structure
* Return QDF_STATUS
*/
QDF_STATUS sme_ll_stats_set_req(tHalHandle hHal, tSirLLStatsSetReq
*psetStatsReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
tSirLLStatsSetReq *set_stats_req;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: MPDU Size = %u", __func__,
psetStatsReq->mpduSizeThreshold);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
" Aggressive Stats Collections = %u",
psetStatsReq->aggressiveStatisticsGathering);
set_stats_req = qdf_mem_malloc(sizeof(*set_stats_req));
if (!set_stats_req) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for WMA_LL_STATS_SET_REQ",
__func__);
return QDF_STATUS_E_NOMEM;
}
*set_stats_req = *psetStatsReq;
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
/* Serialize the req through MC thread */
message.bodyptr = set_stats_req;
message.type = WMA_LINK_LAYER_STATS_SET_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: not able to post WMA_LL_STATS_SET_REQ",
__func__);
qdf_mem_free(set_stats_req);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: sme_acquire_global_lock error", __func__);
qdf_mem_free(set_stats_req);
status = QDF_STATUS_E_FAILURE;
}
return status;
}
QDF_STATUS sme_ll_stats_get_req(mac_handle_t mac_handle,
tSirLLStatsGetReq *get_stats_req,
void *context)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
struct scheduler_msg message = {0};
tSirLLStatsGetReq *ll_stats_get_req;
ll_stats_get_req = qdf_mem_malloc(sizeof(*ll_stats_get_req));
if (!ll_stats_get_req) {
sme_err("Unable to allocate memory for WMA_LL_STATS_GET_REQ");
return QDF_STATUS_E_NOMEM;
}
*ll_stats_get_req = *get_stats_req;
mac->sme.ll_stats_context = context;
if (sme_acquire_global_lock(&mac->sme) == QDF_STATUS_SUCCESS) {
/* Serialize the req through MC thread */
message.bodyptr = ll_stats_get_req;
message.type = WMA_LINK_LAYER_STATS_GET_REQ;
qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type);
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Not able to post WMA_LL_STATS_GET_REQ");
qdf_mem_free(ll_stats_get_req);
}
sme_release_global_lock(&mac->sme);
} else {
sme_err("sme_acquire_global_lock error");
qdf_mem_free(ll_stats_get_req);
}
return status;
}
QDF_STATUS sme_set_link_layer_stats_ind_cb(mac_handle_t mac_handle,
link_layer_stats_cb callback)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.link_layer_stats_cb = callback;
sme_release_global_lock(&mac->sme);
} else {
sme_err("sme_acquire_global_lock error");
}
return status;
}
/**
* sme_set_link_layer_ext_cb() - Register callback for link layer statistics
* @hal: Mac global handle
* @ll_stats_ext_cb: HDD callback which needs to be invoked after getting
* status notification from FW
*
* Return: eHalStatus
*/
QDF_STATUS sme_set_link_layer_ext_cb(tHalHandle hal, void (*ll_stats_ext_cb)
(hdd_handle_t callback_ctx, tSirLLStatsResults
*rsp))
{
QDF_STATUS status;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&mac->sme);
if (status == QDF_STATUS_SUCCESS) {
mac->sme.link_layer_stats_ext_cb = ll_stats_ext_cb;
sme_release_global_lock(&mac->sme);
} else
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: sme_qcquire_global_lock error", __func__);
return status;
}
/**
* sme_reset_link_layer_stats_ind_cb() - SME API to reset link layer stats
* indication
* @h_hal: Hal Handle
*
* This function reset's the link layer stats indication
*
* Return: QDF_STATUS Enumeration
*/
QDF_STATUS sme_reset_link_layer_stats_ind_cb(tHalHandle h_hal)
{
QDF_STATUS status;
tpAniSirGlobal pmac;
if (!h_hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("hHal is not valid"));
return QDF_STATUS_E_INVAL;
}
pmac = PMAC_STRUCT(h_hal);
status = sme_acquire_global_lock(&pmac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pmac->sme.link_layer_stats_cb = NULL;
sme_release_global_lock(&pmac->sme);
} else
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: sme_acquire_global_lock error", __func__);
return status;
}
/**
* sme_ll_stats_set_thresh - set threshold for mac counters
* @hal, hal layer handle
* @threshold, threshold for mac counters
*
* Return: QDF_STATUS Enumeration
*/
QDF_STATUS sme_ll_stats_set_thresh(tHalHandle hal,
struct sir_ll_ext_stats_threshold *threshold)
{
QDF_STATUS status;
tpAniSirGlobal mac;
struct scheduler_msg message = {0};
struct sir_ll_ext_stats_threshold *thresh;
if (!threshold) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("threshold is not valid"));
return QDF_STATUS_E_INVAL;
}
if (!hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("hal is not valid"));
return QDF_STATUS_E_INVAL;
}
mac = PMAC_STRUCT(hal);
thresh = qdf_mem_malloc(sizeof(*thresh));
if (!thresh) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Fail to alloc mem", __func__);
return QDF_STATUS_E_NOMEM;
}
*thresh = *threshold;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = thresh;
message.type = WDA_LINK_LAYER_STATS_SET_THRESHOLD;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, message.type));
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: not able to post WDA_LL_STATS_GET_REQ",
__func__);
qdf_mem_free(thresh);
}
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock error"));
qdf_mem_free(thresh);
}
return status;
}
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
#ifdef WLAN_POWER_DEBUGFS
/**
* sme_power_debug_stats_req() - SME API to collect Power debug stats
* @callback_fn: Pointer to the callback function for Power stats event
* @power_stats_context: Pointer to context
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_power_debug_stats_req(tHalHandle hal, void (*callback_fn)
(struct power_stats_response *response,
void *context), void *power_stats_context)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct scheduler_msg msg = {0};
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (!callback_fn) {
sme_err("Indication callback did not registered");
sme_release_global_lock(&mac_ctx->sme);
return QDF_STATUS_E_FAILURE;
}
mac_ctx->sme.power_debug_stats_context = power_stats_context;
mac_ctx->sme.power_stats_resp_callback = callback_fn;
msg.bodyptr = NULL;
msg.type = WMA_POWER_DEBUG_STATS_REQ;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status))
sme_err("not able to post WDA_POWER_DEBUG_STATS_REQ");
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
#endif
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
/*
* sme_update_roam_offload_enabled() - enable/disable roam offload feaure
* It is used at in the REG_DYNAMIC_VARIABLE macro definition of
*
* hHal - The handle returned by mac_open.
* nRoamOffloadEnabled - The bool to update with
* Return QDF_STATUS_SUCCESS - SME update config successfully.
* Other status means SME is failed to update.
*/
QDF_STATUS sme_update_roam_offload_enabled(tHalHandle hHal,
bool nRoamOffloadEnabled)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: LFR3:gRoamOffloadEnabled is changed from %d to %d",
__func__, pMac->roam.configParam.isRoamOffloadEnabled,
nRoamOffloadEnabled);
pMac->roam.configParam.isRoamOffloadEnabled =
nRoamOffloadEnabled;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_update_roam_key_mgmt_offload_enabled() - enable/disable key mgmt offload
* This is a synchronous call
* @hal_ctx: The handle returned by mac_open.
* @session_id: Session Identifier
* @key_mgmt_offload_enabled: key mgmt enable/disable flag
* @pmkid_modes: PMKID modes of PMKSA caching and OKC
* Return: QDF_STATUS_SUCCESS - SME updated config successfully.
* Other status means SME is failed to update.
*/
QDF_STATUS sme_update_roam_key_mgmt_offload_enabled(tHalHandle hal_ctx,
uint8_t session_id,
bool key_mgmt_offload_enabled,
struct pmkid_mode_bits *pmkid_modes)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx);
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: LFR3: key_mgmt_offload_enabled changed to %d",
__func__, key_mgmt_offload_enabled);
status = csr_roam_set_key_mgmt_offload(mac_ctx,
session_id,
key_mgmt_offload_enabled,
pmkid_modes);
} else
status = QDF_STATUS_E_INVAL;
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
#endif
/*
* sme_get_temperature() -
* SME API to get the pdev temperature
*
* hHal
* temperature context
* pCallbackfn: callback fn with response (temperature)
* Return QDF_STATUS
*/
QDF_STATUS sme_get_temperature(tHalHandle hHal,
void *tempContext,
void (*pCallbackfn)(int temperature,
void *pContext))
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
if ((NULL == pCallbackfn) &&
(NULL == pMac->sme.pGetTemperatureCb)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Indication Call back did not registered");
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
} else if (NULL != pCallbackfn) {
pMac->sme.pTemperatureCbContext = tempContext;
pMac->sme.pGetTemperatureCb = pCallbackfn;
}
/* serialize the req through MC thread */
message.bodyptr = NULL;
message.type = WMA_GET_TEMPERATURE_REQ;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Post Get Temperature msg fail"));
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*
* sme_set_scanning_mac_oui() -
* SME API to set scanning mac oui
*
* hHal
* pScanMacOui: Scanning Mac Oui (input 3 bytes)
* Return QDF_STATUS
*/
QDF_STATUS sme_set_scanning_mac_oui(tHalHandle hHal, tSirScanMacOui
*pScanMacOui)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
/* Serialize the req through MC thread */
message.bodyptr = pScanMacOui;
message.type = WMA_SET_SCAN_MAC_OUI_REQ;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Msg post Set Scan Mac OUI failed"));
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
#ifdef DHCP_SERVER_OFFLOAD
/*
* sme_set_dhcp_srv_offload() -
* SME API to set DHCP server offload info
*
* hHal
* pDhcpSrvInfo : DHCP server offload info struct
* Return QDF_STATUS
*/
QDF_STATUS sme_set_dhcp_srv_offload(tHalHandle hHal,
tSirDhcpSrvOffloadInfo *pDhcpSrvInfo)
{
struct scheduler_msg message = {0};
tSirDhcpSrvOffloadInfo *pSmeDhcpSrvInfo;
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pSmeDhcpSrvInfo = qdf_mem_malloc(sizeof(*pSmeDhcpSrvInfo));
if (!pSmeDhcpSrvInfo) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for WMA_SET_DHCP_SERVER_OFFLOAD_CMD",
__func__);
return QDF_STATUS_E_NOMEM;
}
*pSmeDhcpSrvInfo = *pDhcpSrvInfo;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
/* serialize the req through MC thread */
message.type = WMA_SET_DHCP_SERVER_OFFLOAD_CMD;
message.bodyptr = pSmeDhcpSrvInfo;
if (!QDF_IS_STATUS_SUCCESS
(scheduler_post_msg(QDF_MODULE_ID_WMA,
&message))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s:WMA_SET_DHCP_SERVER_OFFLOAD_CMD failed",
__func__);
qdf_mem_free(pSmeDhcpSrvInfo);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: sme_acquire_global_lock error!", __func__);
qdf_mem_free(pSmeDhcpSrvInfo);
}
return status;
}
#endif /* DHCP_SERVER_OFFLOAD */
QDF_STATUS sme_send_unit_test_cmd(uint32_t vdev_id, uint32_t module_id,
uint32_t arg_count, uint32_t *arg)
{
return wma_form_unit_test_cmd_and_send(vdev_id, module_id,
arg_count, arg);
}
#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
/*
* sme_set_led_flashing() -
* API to set the Led flashing parameters.
*
* hHal - The handle returned by mac_open.
* x0, x1 - led flashing parameters
* Return QDF_STATUS
*/
QDF_STATUS sme_set_led_flashing(tHalHandle hHal, uint8_t type,
uint32_t x0, uint32_t x1)
{
QDF_STATUS status;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct scheduler_msg message = {0};
struct flashing_req_params *ledflashing;
ledflashing = qdf_mem_malloc(sizeof(*ledflashing));
if (!ledflashing) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Not able to allocate memory for WMA_LED_TIMING_REQ");
return QDF_STATUS_E_NOMEM;
}
ledflashing->req_id = 0;
ledflashing->pattern_id = type;
ledflashing->led_x0 = x0;
ledflashing->led_x1 = x1;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
message.bodyptr = ledflashing;
message.type = WMA_LED_FLASHING_REQ;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
sme_release_global_lock(&pMac->sme);
}
if (!QDF_IS_STATUS_SUCCESS(status))
qdf_mem_free(ledflashing);
return status;
}
#endif
/**
* sme_handle_dfS_chan_scan() - handle DFS channel configuration
* @h_hal: corestack handler
* @dfs_flag: flag indicating dfs channel enable/disable
* Return: QDF_STATUS
*/
QDF_STATUS sme_handle_dfs_chan_scan(tHalHandle h_hal, uint8_t dfs_flag)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(h_hal);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_STATUS_SUCCESS == status) {
mac->scan.fEnableDFSChnlScan = dfs_flag;
/* update the channel list to the firmware */
status = csr_update_channel_list(mac);
sme_release_global_lock(&mac->sme);
}
return status;
}
/**
* sme_enable_dfS_chan_scan() - set DFS channel scan enable/disable
* @h_hal: corestack handler
* @dfs_flag: flag indicating dfs channel enable/disable
* Return: QDF_STATUS
*/
QDF_STATUS sme_enable_dfs_chan_scan(tHalHandle h_hal, uint8_t dfs_flag)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac;
if (!h_hal) {
sme_err("hal is NULL");
return QDF_STATUS_E_INVAL;
}
mac = PMAC_STRUCT(h_hal);
mac->scan.fEnableDFSChnlScan = dfs_flag;
return status;
}
#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
/**
* sme_validate_sap_channel_switch() - validate target channel switch w.r.t
* concurreny rules set to avoid channel interference.
* @hal - Hal context
* @sap_ch - channel to switch
* @sap_phy_mode - phy mode of SAP
* @cc_switch_mode - concurreny switch mode
* @session_id - sme session id.
*
* Return: true if there is no channel interference else return false
*/
bool sme_validate_sap_channel_switch(tHalHandle hal,
uint16_t sap_ch, eCsrPhyMode sap_phy_mode, uint8_t cc_switch_mode,
uint8_t session_id)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct csr_roam_session *session = CSR_GET_SESSION(mac, session_id);
uint16_t intf_channel = 0;
if (!session)
return false;
session->ch_switch_in_progress = true;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
intf_channel = csr_check_concurrent_channel_overlap(mac, sap_ch,
sap_phy_mode,
cc_switch_mode);
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock error!"));
session->ch_switch_in_progress = false;
return false;
}
session->ch_switch_in_progress = false;
return (intf_channel == 0) ? true : false;
}
#endif
/**
* sme_configure_stats_avg_factor() - function to config avg. stats factor
* @hal: hal
* @session_id: session ID
* @stats_avg_factor: average stats factor
*
* This function configures the stats avg factor in firmware
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_configure_stats_avg_factor(tHalHandle hal, uint8_t session_id,
uint16_t stats_avg_factor)
{
struct scheduler_msg msg = {0};
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct sir_stats_avg_factor *stats_factor;
stats_factor = qdf_mem_malloc(sizeof(*stats_factor));
if (!stats_factor) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for SIR_HAL_CONFIG_STATS_FACTOR",
__func__);
return QDF_STATUS_E_NOMEM;
}
status = sme_acquire_global_lock(&mac->sme);
if (QDF_STATUS_SUCCESS == status) {
stats_factor->vdev_id = session_id;
stats_factor->stats_avg_factor = stats_avg_factor;
/* serialize the req through MC thread */
msg.type = SIR_HAL_CONFIG_STATS_FACTOR;
msg.bodyptr = stats_factor;
if (!QDF_IS_STATUS_SUCCESS(
scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post SIR_HAL_CONFIG_STATS_FACTOR to WMA!",
__func__);
qdf_mem_free(stats_factor);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: sme_acquire_global_lock error!",
__func__);
qdf_mem_free(stats_factor);
}
return status;
}
/**
* sme_configure_guard_time() - function to configure guard time
* @hal: hal
* @session_id: session id
* @guard_time: guard time
*
* This function configures the guard time in firmware
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_configure_guard_time(tHalHandle hal, uint8_t session_id,
uint32_t guard_time)
{
struct scheduler_msg msg = {0};
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct sir_guard_time_request *g_time;
g_time = qdf_mem_malloc(sizeof(*g_time));
if (!g_time) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for SIR_HAL_CONFIG_GUARD_TIME",
__func__);
return QDF_STATUS_E_NOMEM;
}
status = sme_acquire_global_lock(&mac->sme);
if (QDF_STATUS_SUCCESS == status) {
g_time->vdev_id = session_id;
g_time->guard_time = guard_time;
/* serialize the req through MC thread */
msg.type = SIR_HAL_CONFIG_GUARD_TIME;
msg.bodyptr = g_time;
if (!QDF_IS_STATUS_SUCCESS(
scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post SIR_HAL_CONFIG_GUARD_TIME to WMA!",
__func__);
qdf_mem_free(g_time);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: sme_acquire_global_lock error!",
__func__);
qdf_mem_free(g_time);
}
return status;
}
/*
* sme_wifi_start_logger() - Send the start/stop logging command to WMA
* to either start/stop logging
* @hal: HAL context
* @start_log: Structure containing the wifi start logger params
*
* This function sends the start/stop logging command to WMA
*
* Return: QDF_STATUS_SUCCESS on successful posting
*/
QDF_STATUS sme_wifi_start_logger(tHalHandle hal,
struct sir_wifi_start_log start_log)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct scheduler_msg message = {0};
struct sir_wifi_start_log *req_msg;
uint32_t len;
len = sizeof(*req_msg);
req_msg = qdf_mem_malloc(len);
if (!req_msg) {
sme_err("qdf_mem_malloc failed");
return QDF_STATUS_E_NOMEM;
}
req_msg->verbose_level = start_log.verbose_level;
req_msg->is_iwpriv_command = start_log.is_iwpriv_command;
req_msg->ring_id = start_log.ring_id;
req_msg->ini_triggered = start_log.ini_triggered;
req_msg->user_triggered = start_log.user_triggered;
req_msg->size = start_log.size;
req_msg->is_pktlog_buff_clear = start_log.is_pktlog_buff_clear;
status = sme_acquire_global_lock(&mac->sme);
if (status != QDF_STATUS_SUCCESS) {
sme_err("sme_acquire_global_lock failed(status=%d)", status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
message.bodyptr = req_msg;
message.type = SIR_HAL_START_STOP_LOGGING;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("scheduler_post_msg failed!(err=%d)", status);
qdf_mem_free(req_msg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
return status;
}
/**
* sme_neighbor_middle_of_roaming() - Function to know if
* STA is in the middle of roaming states
* @hal: Handle returned by macOpen
* @sessionId: sessionId of the STA session
*
* This function is a wrapper to call
* csr_neighbor_middle_of_roaming to know STA is in the
* middle of roaming states
*
* Return: True or False
*
*/
bool sme_neighbor_middle_of_roaming(tHalHandle hHal, uint8_t sessionId)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal);
bool val = false;
if (CSR_IS_SESSION_VALID(mac_ctx, sessionId))
val = csr_neighbor_middle_of_roaming(mac_ctx, sessionId);
else
sme_debug("Invalid Session: %d", sessionId);
return val;
}
bool sme_is_any_session_in_middle_of_roaming(mac_handle_t hal)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
uint8_t session_id;
for (session_id = 0; session_id < CSR_ROAM_SESSION_MAX; session_id++) {
if (CSR_IS_SESSION_VALID(mac_ctx, session_id) &&
csr_neighbor_middle_of_roaming(mac_ctx, session_id))
return true;
}
return false;
}
/*
* sme_send_flush_logs_cmd_to_fw() - Flush FW logs
* @mac: MAC handle
*
* This function is used to send the command that will
* be used to flush the logs in the firmware
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_send_flush_logs_cmd_to_fw(tpAniSirGlobal mac)
{
QDF_STATUS status;
struct scheduler_msg message = {0};
/* Serialize the req through MC thread */
message.bodyptr = NULL;
message.type = SIR_HAL_FLUSH_LOG_TO_FW;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("scheduler_post_msg failed!(err=%d)", status);
status = QDF_STATUS_E_FAILURE;
}
return status;
}
QDF_STATUS sme_enable_uapsd_for_ac(uint8_t sta_id,
sme_ac_enum_type ac, uint8_t tid,
uint8_t pri, uint32_t srvc_int,
uint32_t sus_int,
enum sme_qos_wmm_dir_type dir,
uint8_t psb, uint32_t sessionId,
uint32_t delay_interval)
{
void *wma_handle;
t_wma_trigger_uapsd_params uapsd_params;
enum uapsd_ac access_category;
if (!psb) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"No need to configure auto trigger:psb is 0");
return QDF_STATUS_SUCCESS;
}
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma_handle is NULL");
return QDF_STATUS_E_FAILURE;
}
switch (ac) {
case SME_AC_BK:
access_category = UAPSD_BK;
break;
case SME_AC_BE:
access_category = UAPSD_BE;
break;
case SME_AC_VI:
access_category = UAPSD_VI;
break;
case SME_AC_VO:
access_category = UAPSD_VO;
break;
default:
return QDF_STATUS_E_FAILURE;
}
uapsd_params.wmm_ac = access_category;
uapsd_params.user_priority = pri;
uapsd_params.service_interval = srvc_int;
uapsd_params.delay_interval = delay_interval;
uapsd_params.suspend_interval = sus_int;
if (QDF_STATUS_SUCCESS !=
wma_trigger_uapsd_params(wma_handle, sessionId, &uapsd_params)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Failed to Trigger Uapsd params for sessionId %d",
sessionId);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS sme_disable_uapsd_for_ac(uint8_t sta_id,
sme_ac_enum_type ac,
uint32_t sessionId)
{
void *wma_handle;
enum uapsd_ac access_category;
switch (ac) {
case SME_AC_BK:
access_category = UAPSD_BK;
break;
case SME_AC_BE:
access_category = UAPSD_BE;
break;
case SME_AC_VI:
access_category = UAPSD_VI;
break;
case SME_AC_VO:
access_category = UAPSD_VO;
break;
default:
return QDF_STATUS_E_FAILURE;
}
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
if (QDF_STATUS_SUCCESS !=
wma_disable_uapsd_per_ac(wma_handle, sessionId, access_category)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Failed to disable uapsd for ac %d for sessionId %d",
ac, sessionId);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* sme_update_nss() - SME API to change the number for spatial streams
* (1 or 2)
* @hal: Handle returned by mac open
* @nss: Number of spatial streams
*
* This function is used to update the number of spatial streams supported.
*
* Return: Success upon successfully changing nss else failure
*
*/
QDF_STATUS sme_update_nss(tHalHandle h_hal, uint8_t nss)
{
QDF_STATUS status;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(h_hal);
uint32_t i;
struct mlme_ht_capabilities_info *ht_cap_info;
struct csr_roam_session *csr_session;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
mac_ctx->roam.configParam.enable2x2 = (nss == 1) ? 0 : 1;
/* get the HT capability info*/
ht_cap_info = &mac_ctx->mlme_cfg->ht_caps.ht_cap_info;
for (i = 0; i < CSR_ROAM_SESSION_MAX; i++) {
if (CSR_IS_SESSION_VALID(mac_ctx, i)) {
csr_session = &mac_ctx->roam.roamSession[i];
csr_session->htConfig.ht_tx_stbc =
ht_cap_info->tx_stbc;
}
}
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
/**
* sme_update_user_configured_nss() - sets the nss based on user request
* @hal: Pointer to HAL
* @nss: number of streams
*
* Return: None
*/
void sme_update_user_configured_nss(tHalHandle hal, uint8_t nss)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
mac_ctx->user_configured_nss = nss;
}
int sme_update_tx_bfee_supp(tHalHandle hal, uint8_t session_id,
uint8_t cfg_val)
{
QDF_STATUS status;
status = sme_cfg_set_int(hal, WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
cfg_val);
if (status != QDF_STATUS_SUCCESS) {
sme_err("Failed to set SU BFEE CFG");
return -EFAULT;
}
return sme_update_he_tx_bfee_supp(hal, session_id, cfg_val);
}
int sme_update_tx_bfee_nsts(mac_handle_t hal, uint8_t session_id,
uint8_t usr_cfg_val, uint8_t nsts_val)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t nsts_set_val;
mac_ctx->usr_cfg_tx_bfee_nsts = usr_cfg_val;
if (usr_cfg_val)
nsts_set_val = usr_cfg_val;
else
nsts_set_val = nsts_val;
status = sme_cfg_set_int(hal,
WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED,
nsts_set_val);
if (status != QDF_STATUS_SUCCESS) {
sme_err("Failed to set SU BFEE NSTS CFG");
return -EFAULT;
}
if (usr_cfg_val)
sme_set_he_tx_bf_cbf_rates(session_id);
return sme_update_he_tx_bfee_nsts(hal, session_id, nsts_set_val);
}
#ifdef WLAN_FEATURE_11AX
void sme_update_tgt_he_cap(mac_handle_t mac_handle, struct wma_tgt_cfg *cfg)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle);
qdf_mem_copy(&mac_ctx->he_cap_2g,
&cfg->he_cap_2g,
sizeof(tDot11fIEhe_cap));
qdf_mem_copy(&mac_ctx->he_cap_5g,
&cfg->he_cap_5g,
sizeof(tDot11fIEhe_cap));
}
void sme_update_he_cap_nss(tHalHandle hal, uint8_t session_id,
uint8_t nss)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct csr_roam_session *csr_session;
uint32_t tx_mcs_map = 0;
uint32_t rx_mcs_map = 0;
uint32_t mcs_map = 0;
if (!nss || (nss > 2)) {
sme_err("invalid Nss value %d", nss);
}
csr_session = CSR_GET_SESSION(mac_ctx, session_id);
sme_cfg_get_int(hal, WNI_CFG_HE_RX_MCS_MAP_LT_80, &rx_mcs_map);
sme_cfg_get_int(hal, WNI_CFG_HE_TX_MCS_MAP_LT_80, &tx_mcs_map);
mcs_map = rx_mcs_map & 0x3;
if (nss == 1) {
tx_mcs_map = HE_SET_MCS_4_NSS(tx_mcs_map, HE_MCS_DISABLE, 2);
rx_mcs_map = HE_SET_MCS_4_NSS(rx_mcs_map, HE_MCS_DISABLE, 2);
} else {
tx_mcs_map = HE_SET_MCS_4_NSS(tx_mcs_map, mcs_map, 2);
rx_mcs_map = HE_SET_MCS_4_NSS(rx_mcs_map, mcs_map, 2);
}
sme_info("new HE Nss MCS MAP: Rx 0x%0X, Tx: 0x%0X",
rx_mcs_map, tx_mcs_map);
sme_cfg_set_int(hal, WNI_CFG_HE_RX_MCS_MAP_LT_80, rx_mcs_map);
sme_cfg_set_int(hal, WNI_CFG_HE_TX_MCS_MAP_LT_80, tx_mcs_map);
csr_update_session_he_cap(mac_ctx, csr_session);
}
int sme_update_he_mcs(tHalHandle hal, uint8_t session_id, uint16_t he_mcs)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct csr_roam_session *csr_session;
uint16_t mcs_val = 0;
uint16_t mcs_map = HE_MCS_ALL_DISABLED;
uint32_t wni_cfg_tx_param = 0;
uint32_t wni_cfg_rx_param = 0;
csr_session = CSR_GET_SESSION(mac_ctx, session_id);
if (!csr_session) {
sme_err("No session for id %d", session_id);
return -EINVAL;
}
if ((he_mcs & 0x3) == HE_MCS_DISABLE) {
sme_err("Invalid HE MCS 0x%0x, can't disable 0-7 for 1ss",
he_mcs);
return -EINVAL;
}
mcs_val = he_mcs & 0x3;
switch (he_mcs) {
case HE_80_MCS0_7:
case HE_80_MCS0_9:
case HE_80_MCS0_11:
if (mac_ctx->roam.configParam.enable2x2) {
mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 1);
mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 2);
} else {
mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 1);
}
wni_cfg_tx_param = WNI_CFG_HE_TX_MCS_MAP_LT_80;
wni_cfg_rx_param = WNI_CFG_HE_RX_MCS_MAP_LT_80;
break;
case HE_160_MCS0_7:
case HE_160_MCS0_9:
case HE_160_MCS0_11:
mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 1);
wni_cfg_tx_param = WNI_CFG_HE_TX_MCS_MAP_160;
wni_cfg_rx_param = WNI_CFG_HE_RX_MCS_MAP_160;
break;
case HE_80p80_MCS0_7:
case HE_80p80_MCS0_9:
case HE_80p80_MCS0_11:
mcs_map = HE_SET_MCS_4_NSS(mcs_map, mcs_val, 1);
wni_cfg_tx_param = WNI_CFG_HE_TX_MCS_MAP_80_80;
wni_cfg_rx_param = WNI_CFG_HE_RX_MCS_MAP_80_80;
break;
default:
sme_err("Invalid HE MCS 0x%0x", he_mcs);
return -EINVAL;
}
sme_info("new HE MCS 0x%0x", mcs_map);
sme_cfg_set_int(hal, wni_cfg_tx_param, mcs_map);
sme_cfg_set_int(hal, wni_cfg_rx_param, mcs_map);
csr_update_session_he_cap(mac_ctx, csr_session);
return 0;
}
static int sme_update_he_cap(tHalHandle hal, uint8_t session_id,
uint16_t he_cap, int value)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct csr_roam_session *session;
session = CSR_GET_SESSION(mac_ctx, session_id);
if (!session) {
sme_err("No session for id %d", session_id);
return -EINVAL;
}
sme_cfg_set_int(hal, he_cap, value);
csr_update_session_he_cap(mac_ctx, session);
return 0;
}
void sme_set_usr_cfg_mu_edca(mac_handle_t hal, bool val)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
mac_ctx->usr_cfg_mu_edca_params = val;
}
int sme_update_mu_edca_params(mac_handle_t hal, uint8_t session_id)
{
struct scheduler_msg msg = {0};
QDF_STATUS status;
qdf_mem_zero(&msg, sizeof(msg));
msg.type = WNI_SME_UPDATE_MU_EDCA_PARAMS;
msg.reserved = 0;
msg.bodyval = session_id;
status = scheduler_post_msg(QDF_MODULE_ID_PE, &msg);
if (status != QDF_STATUS_SUCCESS) {
sme_err("Not able to post update edca profile");
return -EIO;
}
return 0;
}
void sme_set_he_mu_edca_def_cfg(mac_handle_t hal)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
uint8_t i;
sme_debug("Set MU EDCA params to default");
for (i = 0; i < MAX_NUM_AC; i++) {
mac_ctx->usr_mu_edca_params[i].aci.aifsn = MU_EDCA_DEF_AIFSN;
mac_ctx->usr_mu_edca_params[i].aci.aci = i;
mac_ctx->usr_mu_edca_params[i].cw.max = MU_EDCA_DEF_CW_MAX;
mac_ctx->usr_mu_edca_params[i].cw.min = MU_EDCA_DEF_CW_MIN;
mac_ctx->usr_mu_edca_params[i].mu_edca_timer =
MU_EDCA_DEF_TIMER;
}
}
int sme_update_he_tx_bfee_supp(tHalHandle hal, uint8_t session_id,
uint8_t cfg_val)
{
return sme_update_he_cap(hal, session_id, WNI_CFG_HE_SU_BEAMFORMEE,
cfg_val);
}
int sme_update_he_trigger_frm_mac_pad(mac_handle_t hal, uint8_t session_id,
uint8_t cfg_val)
{
return sme_update_he_cap(hal, session_id, WNI_CFG_HE_TRIG_PAD,
cfg_val);
}
int sme_update_he_tx_bfee_nsts(mac_handle_t hal, uint8_t session_id,
uint8_t cfg_val)
{
return sme_update_he_cap(hal, session_id, WNI_CFG_HE_BFEE_STS_LT80,
cfg_val);
}
void sme_set_he_tx_bf_cbf_rates(uint8_t session_id)
{
uint32_t tx_bf_cbf_rates_5g[] = {91, 1, 0, 3, 2, 4, 0};
uint32_t tx_bf_cbf_rates_2g[] = {91, 1, 1, 3, 1, 3, 0};
QDF_STATUS status;
status = wma_form_unit_test_cmd_and_send(session_id, 0x48, 7,
tx_bf_cbf_rates_5g);
if (QDF_STATUS_SUCCESS != status)
sme_err("send_unit_test_cmd returned %d", status);
status = wma_form_unit_test_cmd_and_send(session_id, 0x48, 7,
tx_bf_cbf_rates_2g);
if (QDF_STATUS_SUCCESS != status)
sme_err("send_unit_test_cmd returned %d", status);
}
int sme_update_he_tx_stbc_cap(tHalHandle hal, uint8_t session_id, int value)
{
int ret;
uint32_t he_cap_val = 0;
he_cap_val = value ? 1 : 0;
ret = sme_update_he_cap(hal, session_id,
WNI_CFG_HE_TX_STBC_LT80, he_cap_val);
if (ret)
return ret;
return sme_update_he_cap(hal, session_id,
WNI_CFG_HE_TX_STBC_GT80, he_cap_val);
}
int sme_update_he_rx_stbc_cap(tHalHandle hal, uint8_t session_id, int value)
{
int ret;
uint32_t he_cap_val = 0;
he_cap_val = value ? 1 : 0;
ret = sme_update_he_cap(hal, session_id,
WNI_CFG_HE_RX_STBC_LT80, he_cap_val);
if (ret)
return ret;
return sme_update_he_cap(hal, session_id,
WNI_CFG_HE_RX_STBC_GT80, he_cap_val);
}
int sme_update_he_frag_supp(tHalHandle hal, uint8_t session_id,
uint16_t he_frag)
{
return sme_update_he_cap(hal, session_id,
WNI_CFG_HE_FRAGMENTATION, he_frag);
}
int sme_update_he_ldpc_supp(tHalHandle hal, uint8_t session_id,
uint16_t he_ldpc)
{
return sme_update_he_cap(hal, session_id, WNI_CFG_HE_LDPC, he_ldpc);
}
#endif
/**
* sme_set_nud_debug_stats_cb() - set nud debug stats callback
* @hal: global hal handle
* @cb: callback function pointer
* @context: callback context
*
* This function stores nud debug stats callback function.
*
* Return: QDF_STATUS enumeration.
*/
QDF_STATUS sme_set_nud_debug_stats_cb(tHalHandle hal,
void (*cb)(void *, struct rsp_stats *, void *),
void *context)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac;
if (!hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("hal is not valid"));
return QDF_STATUS_E_INVAL;
}
mac = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock failed!(status=%d)"),
status);
return status;
}
mac->sme.get_arp_stats_cb = cb;
mac->sme.get_arp_stats_context = context;
sme_release_global_lock(&mac->sme);
return status;
}
/**
* sme_is_any_session_in_connected_state() - SME wrapper API to
* check if any session is in connected state or not.
*
* @hal: Handle returned by mac open
*
* This function is used to check if any valid sme session is in
* connected state or not.
*
* Return: true if any session is connected, else false.
*
*/
bool sme_is_any_session_in_connected_state(tHalHandle h_hal)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(h_hal);
QDF_STATUS status;
bool ret = false;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
ret = csr_is_any_session_in_connect_state(mac_ctx);
sme_release_global_lock(&mac_ctx->sme);
}
return ret;
}
QDF_STATUS sme_set_chip_pwr_save_fail_cb(mac_handle_t mac_handle,
pwr_save_fail_cb cb)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
status = sme_acquire_global_lock(&mac->sme);
if (status != QDF_STATUS_SUCCESS) {
sme_err("sme_AcquireGlobalLock failed!(status=%d)", status);
return status;
}
mac->sme.chip_power_save_fail_cb = cb;
sme_release_global_lock(&mac->sme);
return status;
}
#ifdef FEATURE_RSSI_MONITOR
/**
* sme_set_rssi_monitoring() - set rssi monitoring
* @hal: global hal handle
* @input: request message
*
* This function constructs the vos message and fill in message type,
* bodyptr with @input and posts it to WDA queue.
*
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_set_rssi_monitoring(tHalHandle hal,
struct rssi_monitor_req *input)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct scheduler_msg message = {0};
struct rssi_monitor_req *req_msg;
SME_ENTER();
req_msg = qdf_mem_malloc(sizeof(*req_msg));
if (!req_msg) {
sme_err("memory allocation failed");
return QDF_STATUS_E_NOMEM;
}
*req_msg = *input;
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("sme_acquire_global_lock failed!(status=%d)", status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
message.bodyptr = req_msg;
message.type = WMA_SET_RSSI_MONITOR_REQ;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("scheduler_post_msg failed!(err=%d)", status);
qdf_mem_free(req_msg);
}
sme_release_global_lock(&mac->sme);
return status;
}
QDF_STATUS sme_set_rssi_threshold_breached_cb(mac_handle_t mac_handle,
rssi_threshold_breached_cb cb)
{
QDF_STATUS status;
tpAniSirGlobal mac;
mac = MAC_CONTEXT(mac_handle);
if (!mac) {
sme_err("Invalid mac context");
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("sme_acquire_global_lock failed!(status=%d)",
status);
return status;
}
mac->sme.rssi_threshold_breached_cb = cb;
sme_release_global_lock(&mac->sme);
return status;
}
#endif /* FEATURE_RSSI_MONITOR */
QDF_STATUS sme_reset_rssi_threshold_breached_cb(mac_handle_t mac_handle)
{
return sme_set_rssi_threshold_breached_cb(mac_handle, NULL);
}
/*
* sme_pdev_set_pcl() - Send WMI_PDEV_SET_PCL_CMDID to the WMA
* @hal: Handle returned by macOpen
* @msg: PCL channel list and length structure
*
* Sends the command to WMA to send WMI_PDEV_SET_PCL_CMDID to FW
* Return: QDF_STATUS_SUCCESS on successful posting
*/
QDF_STATUS sme_pdev_set_pcl(struct policy_mgr_pcl_list *msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = sme_get_mac_context();
struct scheduler_msg message = {0};
struct wmi_pcl_chan_weights *req_msg;
uint32_t len, i;
if (!mac) {
sme_err("mac is NULL");
return QDF_STATUS_E_FAILURE;
}
if (!msg) {
sme_err("msg is NULL");
return QDF_STATUS_E_FAILURE;
}
len = sizeof(*req_msg);
req_msg = qdf_mem_malloc(len);
if (!req_msg) {
sme_err("qdf_mem_malloc failed");
return QDF_STATUS_E_NOMEM;
}
for (i = 0; i < msg->pcl_len; i++) {
req_msg->pcl_list[i] = msg->pcl_list[i];
req_msg->weight_list[i] = msg->weight_list[i];
}
req_msg->pcl_len = msg->pcl_len;
status = sme_acquire_global_lock(&mac->sme);
if (status != QDF_STATUS_SUCCESS) {
sme_err("sme_acquire_global_lock failed!(status=%d)", status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
message.bodyptr = req_msg;
message.type = SIR_HAL_PDEV_SET_PCL_TO_FW;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("scheduler_post_msg failed!(err=%d)", status);
qdf_mem_free(req_msg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
return status;
}
/*
* sme_pdev_set_hw_mode() - Send WMI_PDEV_SET_HW_MODE_CMDID to the WMA
* @hal: Handle returned by macOpen
* @msg: HW mode structure containing hw mode and callback details
*
* Sends the command to CSR to send WMI_PDEV_SET_HW_MODE_CMDID to FW
* Return: QDF_STATUS_SUCCESS on successful posting
*/
QDF_STATUS sme_pdev_set_hw_mode(struct policy_mgr_hw_mode msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = sme_get_mac_context();
tSmeCmd *cmd = NULL;
if (!mac) {
sme_err("mac is NULL");
return QDF_STATUS_E_FAILURE;
}
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Failed to acquire lock");
return QDF_STATUS_E_RESOURCES;
}
cmd = csr_get_command_buffer(mac);
if (!cmd) {
sme_err("Get command buffer failed");
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_NULL_VALUE;
}
cmd->command = e_sme_command_set_hw_mode;
cmd->sessionId = msg.session_id;
cmd->u.set_hw_mode_cmd.hw_mode_index = msg.hw_mode_index;
cmd->u.set_hw_mode_cmd.set_hw_mode_cb = msg.set_hw_mode_cb;
cmd->u.set_hw_mode_cmd.reason = msg.reason;
cmd->u.set_hw_mode_cmd.session_id = msg.session_id;
cmd->u.set_hw_mode_cmd.next_action = msg.next_action;
cmd->u.set_hw_mode_cmd.context = msg.context;
sme_debug("Queuing set hw mode to CSR, session: %d reason: %d",
cmd->u.set_hw_mode_cmd.session_id,
cmd->u.set_hw_mode_cmd.reason);
csr_queue_sme_command(mac, cmd, false);
sme_release_global_lock(&mac->sme);
return QDF_STATUS_SUCCESS;
}
/**
* sme_register_hw_mode_trans_cb() - HW mode transition callback registration
* @hal: Handle returned by macOpen
* @callback: HDD callback to be registered
*
* Registers the HDD callback with SME. This callback will be invoked when
* HW mode transition event is received from the FW
*
* Return: None
*/
void sme_register_hw_mode_trans_cb(tHalHandle hal,
hw_mode_transition_cb callback)
{
tpAniSirGlobal mac = PMAC_STRUCT(hal);
mac->sme.sme_hw_mode_trans_cb = callback;
}
/**
* sme_nss_update_request() - Send beacon templete update to FW with new
* nss value
* @hal: Handle returned by macOpen
* @vdev_id: the session id
* @new_nss: the new nss value
* @cback: hdd callback
* @next_action: next action to happen at policy mgr after beacon update
*
* Sends the command to CSR to send to PE
* Return: QDF_STATUS_SUCCESS on successful posting
*/
QDF_STATUS sme_nss_update_request(uint32_t vdev_id,
uint8_t new_nss, policy_mgr_nss_update_cback cback,
uint8_t next_action, struct wlan_objmgr_psoc *psoc,
enum policy_mgr_conn_update_reason reason)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac = sme_get_mac_context();
tSmeCmd *cmd = NULL;
if (!mac) {
sme_err("mac is null");
return status;
}
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
cmd = csr_get_command_buffer(mac);
if (!cmd) {
sme_err("Get command buffer failed");
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_NULL_VALUE;
}
cmd->command = e_sme_command_nss_update;
/* Sessionized modules may require this info */
cmd->sessionId = vdev_id;
cmd->u.nss_update_cmd.new_nss = new_nss;
cmd->u.nss_update_cmd.session_id = vdev_id;
cmd->u.nss_update_cmd.nss_update_cb = cback;
cmd->u.nss_update_cmd.context = psoc;
cmd->u.nss_update_cmd.next_action = next_action;
cmd->u.nss_update_cmd.reason = reason;
sme_debug("Queuing e_sme_command_nss_update to CSR");
csr_queue_sme_command(mac, cmd, false);
sme_release_global_lock(&mac->sme);
}
return status;
}
/**
* sme_soc_set_dual_mac_config() - Set dual mac configurations
* @hal: Handle returned by macOpen
* @msg: Structure containing the dual mac config parameters
*
* Queues configuration information to CSR to configure
* WLAN firmware for the dual MAC features
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_soc_set_dual_mac_config(struct policy_mgr_dual_mac_config msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = sme_get_mac_context();
tSmeCmd *cmd;
if (!mac) {
sme_err("mac is null");
return QDF_STATUS_E_FAILURE;
}
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Failed to acquire lock");
return QDF_STATUS_E_RESOURCES;
}
cmd = csr_get_command_buffer(mac);
if (!cmd) {
sme_err("Get command buffer failed");
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_NULL_VALUE;
}
cmd->command = e_sme_command_set_dual_mac_config;
cmd->u.set_dual_mac_cmd.scan_config = msg.scan_config;
cmd->u.set_dual_mac_cmd.fw_mode_config = msg.fw_mode_config;
cmd->u.set_dual_mac_cmd.set_dual_mac_cb = msg.set_dual_mac_cb;
sme_debug("set_dual_mac_config scan_config: %x fw_mode_config: %x",
cmd->u.set_dual_mac_cmd.scan_config,
cmd->u.set_dual_mac_cmd.fw_mode_config);
csr_queue_sme_command(mac, cmd, false);
sme_release_global_lock(&mac->sme);
return QDF_STATUS_SUCCESS;
}
#ifdef FEATURE_LFR_SUBNET_DETECTION
/**
* sme_gateway_param_update() - to update gateway parameters with WMA
* @Hal: hal handle
* @gw_params: request parameters from HDD
*
* Return: QDF_STATUS
*
* This routine will update gateway parameters to WMA
*/
QDF_STATUS sme_gateway_param_update(tHalHandle Hal,
struct gateway_param_update_req *gw_params)
{
QDF_STATUS qdf_status;
struct scheduler_msg message = {0};
struct gateway_param_update_req *request_buf;
request_buf = qdf_mem_malloc(sizeof(*request_buf));
if (NULL == request_buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Not able to allocate memory for gw param update request");
return QDF_STATUS_E_NOMEM;
}
*request_buf = *gw_params;
message.type = WMA_GW_PARAM_UPDATE_REQ;
message.reserved = 0;
message.bodyptr = request_buf;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Not able to post WMA_GW_PARAM_UPDATE_REQ message to HAL");
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
#endif /* FEATURE_LFR_SUBNET_DETECTION */
/**
* sme_soc_set_antenna_mode() - set antenna mode
* @hal: Handle returned by macOpen
* @msg: Structure containing the antenna mode parameters
*
* Send the command to CSR to send
* WMI_SOC_SET_ANTENNA_MODE_CMDID to FW
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_soc_set_antenna_mode(tHalHandle hal,
struct sir_antenna_mode_param *msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
tSmeCmd *cmd;
if (NULL == msg) {
sme_err("antenna mode mesg is NULL");
return QDF_STATUS_E_FAILURE;
}
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Failed to acquire lock");
return QDF_STATUS_E_RESOURCES;
}
cmd = csr_get_command_buffer(mac);
if (!cmd) {
sme_release_global_lock(&mac->sme);
sme_err("Get command buffer failed");
return QDF_STATUS_E_NULL_VALUE;
}
cmd->command = e_sme_command_set_antenna_mode;
cmd->u.set_antenna_mode_cmd = *msg;
sme_debug("Antenna mode rx_chains: %d tx_chains: %d",
cmd->u.set_antenna_mode_cmd.num_rx_chains,
cmd->u.set_antenna_mode_cmd.num_tx_chains);
csr_queue_sme_command(mac, cmd, false);
sme_release_global_lock(&mac->sme);
return QDF_STATUS_SUCCESS;
}
/**
* sme_set_peer_authorized() - call peer authorized callback
* @peer_addr: peer mac address
* @auth_cb: auth callback
* @vdev_id: vdev id
*
* Return: QDF Status
*/
QDF_STATUS sme_set_peer_authorized(uint8_t *peer_addr,
sme_peer_authorized_fp auth_cb,
uint32_t vdev_id)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
wma_set_peer_authorized_cb(wma_handle, auth_cb);
return wma_set_peer_param(wma_handle, peer_addr, WMI_PEER_AUTHORIZE,
1, vdev_id);
}
/*
* sme_handle_set_fcc_channel() - set spec. tx power for non-fcc channel
* @hal: HAL pointer
* @fcc_constraint: flag to enable/disable the constraint
* @scan_pending: whether there is pending scan
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_handle_set_fcc_channel(tHalHandle hal, bool fcc_constraint,
bool scan_pending)
{
QDF_STATUS status;
tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&mac_ptr->sme);
if (QDF_STATUS_SUCCESS == status) {
if (fcc_constraint != mac_ptr->scan.fcc_constraint) {
mac_ptr->scan.fcc_constraint = fcc_constraint;
if (scan_pending)
mac_ptr->scan.defer_update_channel_list = true;
else
status = csr_update_channel_list(mac_ptr);
}
sme_release_global_lock(&mac_ptr->sme);
}
return status;
}
/**
* sme_setdef_dot11mode() - Updates pMac with default dot11mode
* @hal: Global MAC pointer
*
* Return: NULL.
*/
void sme_setdef_dot11mode(tHalHandle hal)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
csr_set_default_dot11_mode(mac_ctx);
}
/**
* sme_update_roam_scan_hi_rssi_scan_params() - update high rssi scan
* params
* @hal_handle - The handle returned by macOpen.
* @session_id - Session Identifier
* @notify_id - Identifies 1 of the 4 parameters to be modified
* @val New value of the parameter
*
* Return: QDF_STATUS - SME update config successful.
* Other status means SME failed to update
*/
QDF_STATUS sme_update_roam_scan_hi_rssi_scan_params(tHalHandle hal_handle,
uint8_t session_id,
uint32_t notify_id,
int32_t val)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct csr_neighbor_roamconfig *nr_config = NULL;
tpCsrNeighborRoamControlInfo nr_info = NULL;
uint32_t reason = 0;
if (session_id >= CSR_ROAM_SESSION_MAX) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid sme session id: %d"), session_id);
return QDF_STATUS_E_INVAL;
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
nr_config = &mac_ctx->roam.configParam.neighborRoamConfig;
nr_info = &mac_ctx->roam.neighborRoamInfo[session_id];
switch (notify_id) {
case eCSR_HI_RSSI_SCAN_MAXCOUNT_ID:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"%s: gRoamScanHirssiMaxCount %d => %d",
__func__, nr_config->nhi_rssi_scan_max_count,
val);
nr_config->nhi_rssi_scan_max_count = val;
nr_info->cfgParams.hi_rssi_scan_max_count = val;
reason = REASON_ROAM_SCAN_HI_RSSI_MAXCOUNT_CHANGED;
break;
case eCSR_HI_RSSI_SCAN_RSSI_DELTA_ID:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
FL("gRoamScanHiRssiDelta %d => %d"),
nr_config->nhi_rssi_scan_rssi_delta,
val);
nr_config->nhi_rssi_scan_rssi_delta = val;
nr_info->cfgParams.hi_rssi_scan_rssi_delta = val;
reason = REASON_ROAM_SCAN_HI_RSSI_DELTA_CHANGED;
break;
case eCSR_HI_RSSI_SCAN_DELAY_ID:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
FL("gRoamScanHiRssiDelay %d => %d"),
nr_config->nhi_rssi_scan_delay,
val);
nr_config->nhi_rssi_scan_delay = val;
nr_info->cfgParams.hi_rssi_scan_delay = val;
reason = REASON_ROAM_SCAN_HI_RSSI_DELAY_CHANGED;
break;
case eCSR_HI_RSSI_SCAN_RSSI_UB_ID:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
FL("gRoamScanHiRssiUpperBound %d => %d"),
nr_config->nhi_rssi_scan_rssi_ub,
val);
nr_config->nhi_rssi_scan_rssi_ub = val;
nr_info->cfgParams.hi_rssi_scan_rssi_ub = val;
reason = REASON_ROAM_SCAN_HI_RSSI_UB_CHANGED;
break;
default:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
FL("invalid parameter notify_id %d"),
notify_id);
status = QDF_STATUS_E_INVAL;
break;
}
if (mac_ctx->roam.configParam.isRoamOffloadScanEnabled &&
status == QDF_STATUS_SUCCESS) {
csr_roam_offload_scan(mac_ctx, session_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG, reason);
}
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
/**
* sme_update_tgt_services() - update the target services config.
* @hal: HAL pointer.
* @cfg: wma_tgt_services parameters.
*
* update the target services config.
*
* Return: None.
*/
void sme_update_tgt_services(tHalHandle hal, struct wma_tgt_services *cfg)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
mac_ctx->obss_scan_offload = cfg->obss_scan_offload;
sme_debug("obss_scan_offload: %d", mac_ctx->obss_scan_offload);
mac_ctx->lteCoexAntShare = cfg->lte_coex_ant_share;
mac_ctx->beacon_offload = cfg->beacon_offload;
mac_ctx->pmf_offload = cfg->pmf_offload;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
FL("mac_ctx->pmf_offload: %d"), mac_ctx->pmf_offload);
mac_ctx->is_fils_roaming_supported =
cfg->is_fils_roaming_supported;
mac_ctx->is_11k_offload_supported =
cfg->is_11k_offload_supported;
sme_debug("pmf_offload: %d fils_roam support %d 11k_offload %d",
mac_ctx->pmf_offload, mac_ctx->is_fils_roaming_supported,
mac_ctx->is_11k_offload_supported);
}
/**
* sme_is_session_id_valid() - Check if the session id is valid
* @hal: Pointer to HAL
* @session_id: Session id
*
* Checks if the session id is valid or not
*
* Return: True is the session id is valid, false otherwise
*/
bool sme_is_session_id_valid(tHalHandle hal, uint32_t session_id)
{
tpAniSirGlobal mac;
if (NULL != hal) {
mac = PMAC_STRUCT(hal);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: null mac pointer", __func__);
return false;
}
if (CSR_IS_SESSION_VALID(mac, session_id))
return true;
return false;
}
#ifdef FEATURE_WLAN_TDLS
/**
* sme_get_opclass() - determine operating class
* @hal: Pointer to HAL
* @channel: channel id
* @bw_offset: bandwidth offset
* @opclass: pointer to operating class
*
* Function will determine operating class from regdm_get_opclass_from_channel
*
* Return: none
*/
void sme_get_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset,
uint8_t *opclass)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
/* redgm opclass table contains opclass for 40MHz low primary,
* 40MHz high primary and 20MHz. No support for 80MHz yet. So
* first we will check if bit for 40MHz is set and if so find
* matching opclass either with low primary or high primary
* (a channel would never be in both) and then search for opclass
* matching 20MHz, else for any BW.
*/
if (bw_offset & (1 << BW_40_OFFSET_BIT)) {
*opclass = wlan_reg_dmn_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BW40_LOW_PRIMARY);
if (!(*opclass)) {
*opclass = wlan_reg_dmn_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BW40_HIGH_PRIMARY);
}
} else if (bw_offset & (1 << BW_20_OFFSET_BIT)) {
*opclass = wlan_reg_dmn_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BW20);
} else {
*opclass = wlan_reg_dmn_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BWALL);
}
}
#endif
/**
* sme_set_fw_test() - set fw test
* @fw_test: fw test param
*
* Return: Return QDF_STATUS, otherwise appropriate failure code
*/
QDF_STATUS sme_set_fw_test(struct set_fwtest_params *fw_test)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
wma_process_fw_test_cmd(wma_handle, fw_test);
return QDF_STATUS_SUCCESS;
}
/**
* sme_ht40_stop_obss_scan() - ht40 obss stop scan
* @hal: mac handel
* @vdev_id: vdev identifier
*
* Return: Return QDF_STATUS, otherwise appropriate failure code
*/
QDF_STATUS sme_ht40_stop_obss_scan(tHalHandle hal, uint32_t vdev_id)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
wma_ht40_stop_obss_scan(wma_handle, vdev_id);
return QDF_STATUS_SUCCESS;
}
/**
* sme_update_mimo_power_save() - Update MIMO power save
* configuration
* @hal: The handle returned by macOpen
* @is_ht_smps_enabled: enable/disable ht smps
* @ht_smps_mode: smps mode disabled/static/dynamic
* @send_smps_action: flag to send smps force mode command
* to FW
*
* Return: QDF_STATUS if SME update mimo power save
* configuration success else failure status
*/
QDF_STATUS sme_update_mimo_power_save(tHalHandle hal,
uint8_t is_ht_smps_enabled,
uint8_t ht_smps_mode,
bool send_smps_action)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
sme_debug("SMPS enable: %d mode: %d send action: %d",
is_ht_smps_enabled, ht_smps_mode,
send_smps_action);
mac_ctx->roam.configParam.enableHtSmps =
is_ht_smps_enabled;
mac_ctx->roam.configParam.htSmps = ht_smps_mode;
mac_ctx->roam.configParam.send_smps_action =
send_smps_action;
return QDF_STATUS_SUCCESS;
}
/**
* sme_is_sta_smps_allowed() - check if the supported nss for
* the session is greater than 1x1 to enable sta SMPS
* @hal: The handle returned by macOpen
* @session_id: session id
*
* Return: bool returns true if supported nss is greater than
* 1x1 else false
*/
bool sme_is_sta_smps_allowed(tHalHandle hal, uint8_t session_id)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct csr_roam_session *csr_session;
csr_session = CSR_GET_SESSION(mac_ctx, session_id);
if (NULL == csr_session) {
sme_err("SME session not valid: %d", session_id);
return false;
}
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sme_err("CSR session not valid: %d", session_id);
return false;
}
return (csr_session->supported_nss_1x1 == true) ? false : true;
}
/**
* sme_add_beacon_filter() - set the beacon filter configuration
* @hal: The handle returned by macOpen
* @session_id: session id
* @ie_map: bitwise array of IEs
*
* Return: Return QDF_STATUS, otherwise appropriate failure code
*/
QDF_STATUS sme_add_beacon_filter(tHalHandle hal,
uint32_t session_id,
uint32_t *ie_map)
{
struct scheduler_msg message = {0};
QDF_STATUS qdf_status;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct beacon_filter_param *filter_param;
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sme_err("CSR session not valid: %d", session_id);
return QDF_STATUS_E_FAILURE;
}
filter_param = qdf_mem_malloc(sizeof(*filter_param));
if (NULL == filter_param) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc filter_param", __func__);
return QDF_STATUS_E_FAILURE;
}
filter_param->vdev_id = session_id;
qdf_mem_copy(filter_param->ie_map, ie_map,
BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(uint32_t));
message.type = WMA_ADD_BCN_FILTER_CMDID;
message.bodyptr = filter_param;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post msg to WDA!",
__func__);
qdf_mem_free(filter_param);
}
return qdf_status;
}
/**
* sme_remove_beacon_filter() - set the beacon filter configuration
* @hal: The handle returned by macOpen
* @session_id: session id
*
* Return: Return QDF_STATUS, otherwise appropriate failure code
*/
QDF_STATUS sme_remove_beacon_filter(tHalHandle hal, uint32_t session_id)
{
struct scheduler_msg message = {0};
QDF_STATUS qdf_status;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct beacon_filter_param *filter_param;
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sme_err("CSR session not valid: %d", session_id);
return QDF_STATUS_E_FAILURE;
}
filter_param = qdf_mem_malloc(sizeof(*filter_param));
if (NULL == filter_param) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc filter_param", __func__);
return QDF_STATUS_E_FAILURE;
}
filter_param->vdev_id = session_id;
message.type = WMA_REMOVE_BCN_FILTER_CMDID;
message.bodyptr = filter_param;
qdf_status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post msg to WDA!",
__func__);
qdf_mem_free(filter_param);
}
return qdf_status;
}
/**
* sme_send_disassoc_req_frame - send disassoc req
* @hal: handler to hal
* @session_id: session id
* @peer_mac: peer mac address
* @reason: reason for disassociation
* wait_for_ack: wait for acknowledgment
*
* function to send disassoc request to lim
*
* return: none
*/
void sme_send_disassoc_req_frame(tHalHandle hal, uint8_t session_id,
uint8_t *peer_mac, uint16_t reason, uint8_t wait_for_ack)
{
struct sme_send_disassoc_frm_req *msg;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
A_UINT8 *buf;
A_UINT16 tmp;
msg = qdf_mem_malloc(sizeof(struct sme_send_disassoc_frm_req));
if (NULL == msg)
qdf_status = QDF_STATUS_E_FAILURE;
else
qdf_status = QDF_STATUS_SUCCESS;
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
return;
msg->msg_type = (uint16_t) eWNI_SME_SEND_DISASSOC_FRAME;
msg->length = (uint16_t) sizeof(struct sme_send_disassoc_frm_req);
buf = &msg->session_id;
/* session id */
*buf = (A_UINT8) session_id;
buf += sizeof(A_UINT8);
/* transaction id */
*buf = 0;
*(buf + 1) = 0;
buf += sizeof(A_UINT16);
/* Set the peer MAC address before sending the message to LIM */
qdf_mem_copy(buf, peer_mac, QDF_MAC_ADDR_SIZE);
buf += QDF_MAC_ADDR_SIZE;
/* reasoncode */
tmp = (uint16_t) reason;
qdf_mem_copy(buf, &tmp, sizeof(uint16_t));
buf += sizeof(uint16_t);
*buf = wait_for_ack;
buf += sizeof(uint8_t);
qdf_status = umac_send_mb_message_to_mac(msg);
if (qdf_status != QDF_STATUS_SUCCESS)
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("cds_send_mb_message Failed"));
}
#ifdef FEATURE_WLAN_APF
QDF_STATUS sme_get_apf_capabilities(tHalHandle hal,
apf_get_offload_cb callback,
void *context)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct scheduler_msg cds_msg = {0};
SME_ENTER();
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
/* Serialize the req through MC thread */
mac_ctx->sme.apf_get_offload_cb = callback;
mac_ctx->sme.apf_get_offload_context = context;
cds_msg.bodyptr = NULL;
cds_msg.type = WDA_APF_GET_CAPABILITIES_REQ;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &cds_msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Post apf get offload msg fail"));
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac_ctx->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock error"));
}
SME_EXIT();
return status;
}
QDF_STATUS sme_set_apf_instructions(tHalHandle hal,
struct sir_apf_set_offload *req)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct scheduler_msg cds_msg = {0};
struct sir_apf_set_offload *set_offload;
set_offload = qdf_mem_malloc(sizeof(*set_offload) +
req->current_length);
if (NULL == set_offload) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Failed to alloc set_offload"));
return QDF_STATUS_E_NOMEM;
}
set_offload->session_id = req->session_id;
set_offload->filter_id = req->filter_id;
set_offload->current_offset = req->current_offset;
set_offload->total_length = req->total_length;
set_offload->current_length = req->current_length;
if (set_offload->total_length) {
set_offload->program = ((uint8_t *)set_offload) +
sizeof(*set_offload);
qdf_mem_copy(set_offload->program, req->program,
set_offload->current_length);
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
/* Serialize the req through MC thread */
cds_msg.bodyptr = set_offload;
cds_msg.type = WDA_APF_SET_INSTRUCTIONS_REQ;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &cds_msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Post APF set offload msg fail"));
status = QDF_STATUS_E_FAILURE;
qdf_mem_free(set_offload);
}
sme_release_global_lock(&mac_ctx->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock failed"));
qdf_mem_free(set_offload);
}
return status;
}
QDF_STATUS sme_set_apf_enable_disable(tHalHandle hal, uint8_t vdev_id,
bool apf_enable)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
return wma_send_apf_enable_cmd(wma_handle, vdev_id, apf_enable);
}
QDF_STATUS
sme_apf_write_work_memory(tHalHandle hal,
struct wmi_apf_write_memory_params *write_params)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
return wma_send_apf_write_work_memory_cmd(wma_handle, write_params);
}
QDF_STATUS
sme_apf_read_work_memory(tHalHandle hal,
struct wmi_apf_read_memory_params *read_params,
apf_read_mem_cb callback)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
void *wma_handle;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.apf_read_mem_cb = callback;
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock failed"));
}
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
return wma_send_apf_read_work_memory_cmd(wma_handle, read_params);
}
#endif /* FEATURE_WLAN_APF */
/**
* sme_get_wni_dot11_mode() - return configured wni dot11mode
* @hal: hal pointer
*
* Return: wni dot11 mode.
*/
uint32_t sme_get_wni_dot11_mode(tHalHandle hal)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
return csr_translate_to_wni_cfg_dot11_mode(mac_ctx,
mac_ctx->roam.configParam.uCfgDot11Mode);
}
/**
* sme_create_mon_session() - post message to create PE session for monitormode
* operation
* @hal_handle: Handle to the HAL
* @bssid: pointer to bssid
* @vdev_id: sme session id
*
* Return: QDF_STATUS_SUCCESS on success, non-zero error code on failure.
*/
QDF_STATUS sme_create_mon_session(tHalHandle hal_handle, tSirMacAddr bss_id,
uint8_t vdev_id)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
struct sir_create_session *msg;
msg = qdf_mem_malloc(sizeof(*msg));
if (NULL != msg) {
msg->type = eWNI_SME_MON_INIT_SESSION;
msg->vdev_id = vdev_id;
msg->msg_len = sizeof(*msg);
qdf_mem_copy(msg->bss_id.bytes, bss_id, QDF_MAC_ADDR_SIZE);
status = umac_send_mb_message_to_mac(msg);
}
return status;
}
void sme_set_chan_info_callback(tHalHandle hal_handle,
void (*callback)(struct scan_chan_info *chan_info))
{
tpAniSirGlobal mac;
if (hal_handle == NULL) {
QDF_ASSERT(0);
return;
}
mac = PMAC_STRUCT(hal_handle);
mac->chan_info_cb = callback;
}
/**
* sme_set_adaptive_dwelltime_config() - Update Adaptive dwelltime configuration
* @hal: The handle returned by macOpen
* @params: adaptive_dwelltime_params config
*
* Return: QDF_STATUS if adaptive dwell time update
* configuration success else failure status
*/
QDF_STATUS sme_set_adaptive_dwelltime_config(tHalHandle hal,
struct adaptive_dwelltime_params *params)
{
struct scheduler_msg message = {0};
QDF_STATUS status;
struct adaptive_dwelltime_params *dwelltime_params;
dwelltime_params = qdf_mem_malloc(sizeof(*dwelltime_params));
if (NULL == dwelltime_params) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc dwelltime_params", __func__);
return QDF_STATUS_E_NOMEM;
}
dwelltime_params->is_enabled = params->is_enabled;
dwelltime_params->dwelltime_mode = params->dwelltime_mode;
dwelltime_params->lpf_weight = params->lpf_weight;
dwelltime_params->passive_mon_intval = params->passive_mon_intval;
dwelltime_params->wifi_act_threshold = params->wifi_act_threshold;
message.type = WMA_SET_ADAPT_DWELLTIME_CONF_PARAMS;
message.bodyptr = dwelltime_params;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post msg to WMA!", __func__);
qdf_mem_free(dwelltime_params);
}
return status;
}
/**
* sme_set_vdev_ies_per_band() - sends the per band IEs to vdev
* @hal: Pointer to HAL
* @vdev_id: vdev_id for which IE is targeted
*
* Return: None
*/
void sme_set_vdev_ies_per_band(tHalHandle hal, uint8_t vdev_id)
{
struct sir_set_vdev_ies_per_band *p_msg;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
p_msg = qdf_mem_malloc(sizeof(*p_msg));
if (NULL == p_msg) {
sme_err("mem alloc failed for sme msg");
return;
}
p_msg->vdev_id = vdev_id;
p_msg->msg_type = eWNI_SME_SET_VDEV_IES_PER_BAND;
p_msg->len = sizeof(*p_msg);
sme_debug("sending eWNI_SME_SET_VDEV_IES_PER_BAND: vdev_id: %d",
vdev_id);
status = umac_send_mb_message_to_mac(p_msg);
if (QDF_STATUS_SUCCESS != status)
sme_err("Send eWNI_SME_SET_VDEV_IES_PER_BAND fail");
}
/**
* sme_set_pdev_ht_vht_ies() - sends the set pdev IE req
* @hal: Pointer to HAL
* @enable2x2: 1x1 or 2x2 mode.
*
* Sends the set pdev IE req with Nss value.
*
* Return: None
*/
void sme_set_pdev_ht_vht_ies(tHalHandle hal, bool enable2x2)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct sir_set_ht_vht_cfg *ht_vht_cfg;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
if (!((mac_ctx->roam.configParam.uCfgDot11Mode ==
eCSR_CFG_DOT11_MODE_AUTO) ||
(mac_ctx->roam.configParam.uCfgDot11Mode ==
eCSR_CFG_DOT11_MODE_11N) ||
(mac_ctx->roam.configParam.uCfgDot11Mode ==
eCSR_CFG_DOT11_MODE_11N_ONLY) ||
(mac_ctx->roam.configParam.uCfgDot11Mode ==
eCSR_CFG_DOT11_MODE_11AC) ||
(mac_ctx->roam.configParam.uCfgDot11Mode ==
eCSR_CFG_DOT11_MODE_11AC_ONLY)))
return;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
ht_vht_cfg = qdf_mem_malloc(sizeof(*ht_vht_cfg));
if (NULL == ht_vht_cfg) {
sme_err("mem alloc failed for ht_vht_cfg");
sme_release_global_lock(&mac_ctx->sme);
return;
}
ht_vht_cfg->pdev_id = 0;
if (enable2x2)
ht_vht_cfg->nss = 2;
else
ht_vht_cfg->nss = 1;
ht_vht_cfg->dot11mode =
(uint8_t)csr_translate_to_wni_cfg_dot11_mode(mac_ctx,
mac_ctx->roam.configParam.uCfgDot11Mode);
ht_vht_cfg->msg_type = eWNI_SME_PDEV_SET_HT_VHT_IE;
ht_vht_cfg->len = sizeof(*ht_vht_cfg);
sme_debug("SET_HT_VHT_IE with nss: %d, dot11mode: %d",
ht_vht_cfg->nss,
ht_vht_cfg->dot11mode);
status = umac_send_mb_message_to_mac(ht_vht_cfg);
if (QDF_STATUS_SUCCESS != status)
sme_err("Send SME_PDEV_SET_HT_VHT_IE fail");
sme_release_global_lock(&mac_ctx->sme);
}
}
/**
* sme_update_vdev_type_nss() - sets the nss per vdev type
* @hal: Pointer to HAL
* @max_supp_nss: max_supported Nss
* @band: 5G or 2.4G band
*
* Sets the per band Nss for each vdev type based on INI and configured
* chain mask value.
*
* Return: None
*/
void sme_update_vdev_type_nss(tHalHandle hal, uint8_t max_supp_nss,
uint32_t vdev_type_nss, enum band_info band)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct vdev_type_nss *vdev_nss;
if (BAND_5G == band)
vdev_nss = &mac_ctx->vdev_type_nss_5g;
else
vdev_nss = &mac_ctx->vdev_type_nss_2g;
vdev_nss->sta = QDF_MIN(max_supp_nss, CFG_STA_NSS(vdev_type_nss));
vdev_nss->sap = QDF_MIN(max_supp_nss, CFG_SAP_NSS(vdev_type_nss));
vdev_nss->p2p_go = QDF_MIN(max_supp_nss,
CFG_P2P_GO_NSS(vdev_type_nss));
vdev_nss->p2p_cli = QDF_MIN(max_supp_nss,
CFG_P2P_CLI_NSS(vdev_type_nss));
vdev_nss->p2p_dev = QDF_MIN(max_supp_nss,
CFG_P2P_DEV_NSS(vdev_type_nss));
vdev_nss->ibss = QDF_MIN(max_supp_nss, CFG_IBSS_NSS(vdev_type_nss));
vdev_nss->tdls = QDF_MIN(max_supp_nss, CFG_TDLS_NSS(vdev_type_nss));
vdev_nss->ocb = QDF_MIN(max_supp_nss, CFG_OCB_NSS(vdev_type_nss));
sme_debug("band %d NSS:sta %d sap %d cli %d go %d dev %d ibss %d tdls %d ocb %d",
band, vdev_nss->sta, vdev_nss->sap, vdev_nss->p2p_cli,
vdev_nss->p2p_go, vdev_nss->p2p_dev, vdev_nss->ibss,
vdev_nss->tdls, vdev_nss->ocb);
}
#ifdef WLAN_FEATURE_11AX_BSS_COLOR
#define MAX_BSS_COLOR_VAL 63
#define MIN_BSS_COLOR_VAL 1
QDF_STATUS sme_set_he_bss_color(tHalHandle hal, uint8_t session_id,
uint8_t bss_color)
{
struct sir_set_he_bss_color *bss_color_msg;
uint8_t len;
if (!hal) {
sme_err("Invalid hal pointer");
return QDF_STATUS_E_FAULT;
}
sme_debug("Set HE bss_color %d", bss_color);
if (bss_color < MIN_BSS_COLOR_VAL || bss_color > MAX_BSS_COLOR_VAL) {
sme_debug("Invalid HE bss_color %d", bss_color);
return QDF_STATUS_E_INVAL;
}
len = sizeof(*bss_color_msg);
bss_color_msg = qdf_mem_malloc(len);
if (!bss_color_msg) {
sme_err("mem alloc failed");
return QDF_STATUS_E_NOMEM;
}
bss_color_msg->message_type = eWNI_SME_SET_HE_BSS_COLOR;
bss_color_msg->length = len;
bss_color_msg->session_id = session_id;
bss_color_msg->bss_color = bss_color;
return umac_send_mb_message_to_mac(bss_color_msg);
}
#endif
/**
* sme_update_hw_dbs_capable() - sets the HW DBS capability
* @hal: Pointer to HAL
* @hw_dbs_capable: HW DBS capability
*
* Sets HW DBS capability based on INI and fw capability.
*
* Return: None
*/
void sme_update_hw_dbs_capable(tHalHandle hal, uint8_t hw_dbs_capable)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
mac_ctx->hw_dbs_capable = hw_dbs_capable;
}
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
/**
* sme_register_p2p_lo_event() - Register for the p2p lo event
* @hHal: reference to the HAL
* @context: the context of the call
* @callback: the callback to hdd
*
* This function registers the callback function for P2P listen
* offload stop event.
*
* Return: none
*/
void sme_register_p2p_lo_event(tHalHandle hHal, void *context,
p2p_lo_callback callback)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_E_FAILURE;
status = sme_acquire_global_lock(&pMac->sme);
pMac->sme.p2p_lo_event_callback = callback;
pMac->sme.p2p_lo_event_context = context;
sme_release_global_lock(&pMac->sme);
}
#endif
/**
* sme_process_mac_pwr_dbg_cmd() - enable mac pwr debugging
* @hal: The handle returned by macOpen
* @session_id: session id
* @dbg_args: args for mac pwr debug command
* Return: Return QDF_STATUS, otherwise appropriate failure code
*/
QDF_STATUS sme_process_mac_pwr_dbg_cmd(tHalHandle hal, uint32_t session_id,
struct sir_mac_pwr_dbg_cmd*
dbg_args)
{
struct scheduler_msg message = {0};
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct sir_mac_pwr_dbg_cmd *req;
int i;
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sme_err("CSR session not valid: %d", session_id);
return QDF_STATUS_E_FAILURE;
}
req = qdf_mem_malloc(sizeof(*req));
if (NULL == req) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc mac_pwr_dbg_args", __func__);
return QDF_STATUS_E_FAILURE;
}
req->module_id = dbg_args->module_id;
req->pdev_id = dbg_args->pdev_id;
req->num_args = dbg_args->num_args;
for (i = 0; i < req->num_args; i++)
req->args[i] = dbg_args->args[i];
message.type = SIR_HAL_POWER_DBG_CMD;
message.bodyptr = req;
if (!QDF_IS_STATUS_SUCCESS(scheduler_post_msg
(QDF_MODULE_ID_WMA, &message))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post msg to WDA!",
__func__);
qdf_mem_free(req);
}
return QDF_STATUS_SUCCESS;
}
/**
* sme_get_vdev_type_nss() - gets the nss per vdev type
* @dev_mode: connection type.
* @nss2g: Pointer to the 2G Nss parameter.
* @nss5g: Pointer to the 5G Nss parameter.
*
* Fills the 2G and 5G Nss values based on connection type.
*
* Return: None
*/
void sme_get_vdev_type_nss(enum QDF_OPMODE dev_mode,
uint8_t *nss_2g, uint8_t *nss_5g)
{
tpAniSirGlobal mac_ctx = sme_get_mac_context();
if (NULL == mac_ctx) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Invalid MAC context"));
return;
}
csr_get_vdev_type_nss(mac_ctx, dev_mode, nss_2g, nss_5g);
}
/**
* sme_update_sta_roam_policy() - update sta roam policy for
* unsafe and DFS channels.
* @hal_handle: hal handle for getting global mac struct
* @dfs_mode: dfs mode which tell if dfs channel needs to be
* skipped or not
* @skip_unsafe_channels: Param to tell if driver needs to
* skip unsafe channels or not.
* @param session_id: sme_session_id
* @sap_operating_band: Band on which SAP is operating
*
* sme_update_sta_roam_policy update sta rome policies to csr
* this function will call csrUpdateChannelList as well
* to include/exclude DFS channels and unsafe channels.
*
* Return: eHAL_STATUS_SUCCESS or non-zero on failure.
*/
QDF_STATUS sme_update_sta_roam_policy(tHalHandle hal_handle,
enum sta_roam_policy_dfs_mode dfs_mode,
bool skip_unsafe_channels,
uint8_t session_id, uint8_t sap_operating_band)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
QDF_STATUS status = QDF_STATUS_SUCCESS;
tSmeConfigParams *sme_config;
if (!mac_ctx) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
"%s: mac_ctx is null", __func__);
return QDF_STATUS_E_FAILURE;
}
sme_config = qdf_mem_malloc(sizeof(*sme_config));
if (!sme_config) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("failed to allocate memory for sme_config"));
return QDF_STATUS_E_FAILURE;
}
qdf_mem_zero(sme_config, sizeof(*sme_config));
sme_get_config_param(hal_handle, sme_config);
sme_config->csrConfig.sta_roam_policy_params.dfs_mode =
dfs_mode;
sme_config->csrConfig.sta_roam_policy_params.skip_unsafe_channels =
skip_unsafe_channels;
sme_config->csrConfig.sta_roam_policy_params.sap_operating_band =
sap_operating_band;
sme_update_config(hal_handle, sme_config);
status = csr_update_channel_list(mac_ctx);
if (QDF_STATUS_SUCCESS != status) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("failed to update the supported channel list"));
}
if (mac_ctx->roam.configParam.isRoamOffloadScanEnabled) {
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_roam_offload_scan(mac_ctx, session_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_ROAM_SCAN_STA_ROAM_POLICY_CHANGED);
sme_release_global_lock(&mac_ctx->sme);
} else {
sme_err("Failed to acquire SME lock");
}
}
qdf_mem_free(sme_config);
return status;
}
/**
* sme_enable_disable_chanavoidind_event - configure ca event ind
* @hal: handler to hal
* @set_value: enable/disable
*
* function to enable/disable chan avoidance indication
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_enable_disable_chanavoidind_event(tHalHandle hal,
uint8_t set_value)
{
QDF_STATUS status;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct scheduler_msg msg = {0};
sme_debug("set_value: %d", set_value);
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
qdf_mem_zero(&msg, sizeof(struct scheduler_msg));
msg.type = WMA_SEND_FREQ_RANGE_CONTROL_IND;
msg.bodyval = set_value;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
sme_release_global_lock(&mac_ctx->sme);
return status;
}
return status;
}
/*
* sme_set_default_scan_ie() - API to send default scan IE to LIM
* @hal: reference to the HAL
* @session_id: current session ID
* @ie_data: Pointer to Scan IE data
* @ie_len: Length of @ie_data
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_set_default_scan_ie(tHalHandle hal, uint16_t session_id,
uint8_t *ie_data, uint16_t ie_len)
{
QDF_STATUS status;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct hdd_default_scan_ie *set_ie_params;
if (!ie_data)
return QDF_STATUS_E_INVAL;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
set_ie_params = qdf_mem_malloc(sizeof(*set_ie_params));
if (!set_ie_params)
status = QDF_STATUS_E_NOMEM;
else {
set_ie_params->message_type = eWNI_SME_DEFAULT_SCAN_IE;
set_ie_params->length = sizeof(*set_ie_params);
set_ie_params->session_id = session_id;
set_ie_params->ie_len = ie_len;
qdf_mem_copy(set_ie_params->ie_data, ie_data, ie_len);
status = umac_send_mb_message_to_mac(set_ie_params);
}
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
QDF_STATUS sme_get_sar_power_limits(tHalHandle hal,
wma_sar_cb callback, void *context)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
return wma_get_sar_limit(wma_handle, callback, context);
}
QDF_STATUS sme_set_sar_power_limits(tHalHandle hal,
struct sar_limit_cmd_params *sar_limit_cmd)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
return wma_set_sar_limit(wma_handle, sar_limit_cmd);
}
#ifdef WLAN_FEATURE_FIPS
QDF_STATUS sme_fips_request(tHalHandle hal, struct fips_params *param,
wma_fips_cb callback, void *context)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
sme_err("wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
return wma_fips_request(wma_handle, param, callback, context);
}
#endif
QDF_STATUS sme_set_cts2self_for_p2p_go(tHalHandle hal_handle)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma_handle is NULL");
return QDF_STATUS_E_FAILURE;
}
if (QDF_STATUS_SUCCESS !=
wma_set_cts2self_for_p2p_go(wma_handle, true)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Failed to set cts2self for p2p GO to firmware",
__func__);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* sme_update_tx_fail_cnt_threshold() - update tx fail count Threshold
* @hal: Handle returned by mac_open
* @session_id: Session ID on which tx fail count needs to be updated to FW
* @tx_fail_count: Count for tx fail threshold after which FW will disconnect
*
* This function is used to set tx fail count threshold to firmware.
* firmware will issue disocnnect with peer device once this threshold is
* reached.
*
* Return: Return QDF_STATUS, otherwise appropriate failure code
*/
QDF_STATUS sme_update_tx_fail_cnt_threshold(tHalHandle hal_handle,
uint8_t session_id, uint32_t tx_fail_count)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
struct sme_tx_fail_cnt_threshold *tx_fail_cnt;
struct scheduler_msg msg = {0};
tx_fail_cnt = qdf_mem_malloc(sizeof(*tx_fail_cnt));
if (NULL == tx_fail_cnt) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc filter_param", __func__);
return QDF_STATUS_E_FAILURE;
}
sme_debug("session_id: %d tx_fail_count: %d",
session_id, tx_fail_count);
tx_fail_cnt->session_id = session_id;
tx_fail_cnt->tx_fail_cnt_threshold = tx_fail_count;
qdf_mem_zero(&msg, sizeof(struct scheduler_msg));
msg.type = SIR_HAL_UPDATE_TX_FAIL_CNT_TH;
msg.reserved = 0;
msg.bodyptr = tx_fail_cnt;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post Tx fail count message to WDA"));
qdf_mem_free(tx_fail_cnt);
}
return status;
}
QDF_STATUS sme_set_lost_link_info_cb(mac_handle_t mac_handle,
lost_link_info_cb cb)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.lost_link_info_cb = cb;
sme_release_global_lock(&mac->sme);
} else {
sme_err("sme_acquire_global_lock error status: %d", status);
}
return status;
}
#ifdef FEATURE_WLAN_ESE
bool sme_roam_is_ese_assoc(struct csr_roam_info *roam_info)
{
return roam_info->isESEAssoc;
}
#endif
/**
* sme_set_5g_band_pref(): If 5G preference is enabled,set boost/drop
* params from ini.
* @hal_handle: Handle returned by mac_open
* @5g_pref_params: pref params from ini.
*
* Returns: None
*/
void sme_set_5g_band_pref(tHalHandle hal_handle,
struct sme_5g_band_pref_params *pref_params)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
struct roam_ext_params *roam_params;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!pref_params) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Invalid 5G pref params!");
return;
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
roam_params = &mac_ctx->roam.configParam.roam_params;
roam_params->raise_rssi_thresh_5g =
pref_params->rssi_boost_threshold_5g;
roam_params->raise_factor_5g =
pref_params->rssi_boost_factor_5g;
roam_params->max_raise_rssi_5g =
pref_params->max_rssi_boost_5g;
roam_params->drop_rssi_thresh_5g =
pref_params->rssi_penalize_threshold_5g;
roam_params->drop_factor_5g =
pref_params->rssi_penalize_factor_5g;
roam_params->max_drop_rssi_5g =
pref_params->max_rssi_penalize_5g;
sme_release_global_lock(&mac_ctx->sme);
} else
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Unable to acquire global sme lock");
}
bool sme_neighbor_roam_is11r_assoc(tHalHandle hal_ctx, uint8_t session_id)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx);
return csr_neighbor_roam_is11r_assoc(mac_ctx, session_id);
}
#ifdef WLAN_FEATURE_WOW_PULSE
/**
* sme_set_wow_pulse() - set wow pulse info
* @wow_pulse_set_info: wow_pulse_mode structure pointer
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_set_wow_pulse(struct wow_pulse_mode *wow_pulse_set_info)
{
struct scheduler_msg message = {0};
QDF_STATUS status;
struct wow_pulse_mode *wow_pulse_set_cmd;
if (!wow_pulse_set_info) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: invalid wow_pulse_set_info pointer", __func__);
return QDF_STATUS_E_FAILURE;
}
wow_pulse_set_cmd = qdf_mem_malloc(sizeof(*wow_pulse_set_cmd));
if (NULL == wow_pulse_set_cmd) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc wow_pulse_set_cmd", __func__);
return QDF_STATUS_E_NOMEM;
}
*wow_pulse_set_cmd = *wow_pulse_set_info;
message.type = WMA_SET_WOW_PULSE_CMD;
message.bodyptr = wow_pulse_set_cmd;
status = scheduler_post_msg(QDF_MODULE_ID_WMA,
&message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post msg to WDA!",
__func__);
qdf_mem_free(wow_pulse_set_cmd);
status = QDF_STATUS_E_FAILURE;
}
return status;
}
#endif
/**
* sme_prepare_beacon_from_bss_descp() - prepares beacon frame by populating
* different fields and IEs from bss descriptor.
* @frame_buf: frame buffer to populate
* @bss_descp: bss descriptor
* @bssid: bssid of the beacon frame to populate
* @ie_len: length of IE fields
*
* Return: None
*/
static void sme_prepare_beacon_from_bss_descp(uint8_t *frame_buf,
tSirBssDescription *bss_descp,
const tSirMacAddr bssid,
uint32_t ie_len)
{
tDot11fBeacon1 *bcn_fixed;
tpSirMacMgmtHdr mac_hdr = (tpSirMacMgmtHdr)frame_buf;
/* populate mac header first to indicate beacon */
mac_hdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
mac_hdr->fc.type = SIR_MAC_MGMT_FRAME;
mac_hdr->fc.subType = SIR_MAC_MGMT_BEACON;
qdf_mem_copy((uint8_t *) mac_hdr->da,
(uint8_t *) "\xFF\xFF\xFF\xFF\xFF\xFF",
sizeof(struct qdf_mac_addr));
qdf_mem_copy((uint8_t *) mac_hdr->sa, bssid,
sizeof(struct qdf_mac_addr));
qdf_mem_copy((uint8_t *) mac_hdr->bssId, bssid,
sizeof(struct qdf_mac_addr));
/* now populate fixed params */
bcn_fixed = (tDot11fBeacon1 *)(frame_buf + SIR_MAC_HDR_LEN_3A);
/* populate timestamp */
qdf_mem_copy(&bcn_fixed->TimeStamp.timestamp, &bss_descp->timeStamp,
sizeof(bss_descp->timeStamp));
/* populate beacon interval */
bcn_fixed->BeaconInterval.interval = bss_descp->beaconInterval;
/* populate capability */
qdf_mem_copy(&bcn_fixed->Capabilities, &bss_descp->capabilityInfo,
sizeof(bss_descp->capabilityInfo));
/* copy IEs now */
qdf_mem_copy(frame_buf + SIR_MAC_HDR_LEN_3A
+ SIR_MAC_B_PR_SSID_OFFSET,
&bss_descp->ieFields, ie_len);
}
QDF_STATUS sme_get_rssi_snr_by_bssid(tHalHandle hal,
struct csr_roam_profile *profile,
const uint8_t *bssid,
int8_t *rssi, int8_t *snr)
{
tSirBssDescription *bss_descp;
tCsrScanResultFilter *scan_filter;
struct scan_result_list *bss_list;
tScanResultHandle result_handle = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
scan_filter = qdf_mem_malloc(sizeof(tCsrScanResultFilter));
if (NULL == scan_filter) {
sme_err("memory allocation failed");
status = QDF_STATUS_E_NOMEM;
goto free_scan_flter;
}
status = csr_roam_prepare_filter_from_profile(mac_ctx,
profile, scan_filter);
if (QDF_STATUS_SUCCESS != status) {
sme_err("prepare_filter failed");
goto free_scan_flter;
}
/* update filter to get scan result with just target BSSID */
if (NULL == scan_filter->BSSIDs.bssid) {
scan_filter->BSSIDs.bssid =
qdf_mem_malloc(sizeof(struct qdf_mac_addr));
if (scan_filter->BSSIDs.bssid == NULL) {
sme_err("malloc failed");
status = QDF_STATUS_E_NOMEM;
goto free_scan_flter;
}
}
scan_filter->BSSIDs.numOfBSSIDs = 1;
qdf_mem_copy(scan_filter->BSSIDs.bssid[0].bytes,
bssid, sizeof(struct qdf_mac_addr));
status = csr_scan_get_result(mac_ctx, scan_filter, &result_handle);
if (QDF_STATUS_SUCCESS != status) {
sme_err("parse_scan_result failed");
goto free_scan_flter;
}
bss_list = (struct scan_result_list *)result_handle;
bss_descp = csr_get_fst_bssdescr_ptr(bss_list);
if (!bss_descp) {
sme_err("unable to fetch bss descriptor");
status = QDF_STATUS_E_FAULT;
goto free_scan_flter;
}
sme_debug("snr: %d, rssi: %d, raw_rssi: %d",
bss_descp->sinr, bss_descp->rssi, bss_descp->rssi_raw);
if (rssi)
*rssi = bss_descp->rssi;
if (snr)
*snr = bss_descp->sinr;
free_scan_flter:
/* free scan filter and exit */
if (scan_filter) {
csr_free_scan_filter(mac_ctx, scan_filter);
qdf_mem_free(scan_filter);
}
if (result_handle)
csr_scan_result_purge(mac_ctx, result_handle);
return status;
}
QDF_STATUS sme_get_beacon_frm(tHalHandle hal, struct csr_roam_profile *profile,
const tSirMacAddr bssid,
uint8_t **frame_buf, uint32_t *frame_len,
int *channel)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tScanResultHandle result_handle = NULL;
tCsrScanResultFilter *scan_filter;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
tSirBssDescription *bss_descp;
struct scan_result_list *bss_list;
uint32_t ie_len;
scan_filter = qdf_mem_malloc(sizeof(tCsrScanResultFilter));
if (NULL == scan_filter) {
sme_err("memory allocation failed");
status = QDF_STATUS_E_NOMEM;
goto free_scan_flter;
}
status = csr_roam_prepare_filter_from_profile(mac_ctx,
profile, scan_filter);
if (QDF_IS_STATUS_ERROR(status)) {
sme_err("prepare_filter failed");
status = QDF_STATUS_E_FAULT;
goto free_scan_flter;
}
/* update filter to get scan result with just target BSSID */
if (NULL == scan_filter->BSSIDs.bssid) {
scan_filter->BSSIDs.bssid =
qdf_mem_malloc(sizeof(struct qdf_mac_addr));
if (scan_filter->BSSIDs.bssid == NULL) {
sme_err("malloc failed");
status = QDF_STATUS_E_NOMEM;
goto free_scan_flter;
}
}
scan_filter->BSSIDs.numOfBSSIDs = 1;
qdf_mem_copy(scan_filter->BSSIDs.bssid[0].bytes,
bssid, sizeof(struct qdf_mac_addr));
status = csr_scan_get_result(mac_ctx, scan_filter, &result_handle);
if (QDF_STATUS_SUCCESS != status) {
sme_err("parse_scan_result failed");
status = QDF_STATUS_E_FAULT;
goto free_scan_flter;
}
bss_list = (struct scan_result_list *)result_handle;
bss_descp = csr_get_fst_bssdescr_ptr(bss_list);
if (!bss_descp) {
sme_err("unable to fetch bss descriptor");
status = QDF_STATUS_E_FAULT;
goto free_scan_flter;
}
/**
* Length of BSS descriptor is without length of
* length itself and length of pointer that holds ieFields.
*
* tSirBssDescription
* +--------+---------------------------------+---------------+
* | length | other fields | pointer to IEs|
* +--------+---------------------------------+---------------+
* ^
* ieFields
*/
ie_len = bss_descp->length + sizeof(bss_descp->length)
- (uint16_t)(offsetof(tSirBssDescription, ieFields[0]));
sme_debug("found bss_descriptor ie_len: %d channel %d",
ie_len, bss_descp->channelId);
/* include mac header and fixed params along with IEs in frame */
*frame_len = SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET + ie_len;
*frame_buf = qdf_mem_malloc(*frame_len);
if (NULL == *frame_buf) {
sme_err("memory allocation failed");
status = QDF_STATUS_E_NOMEM;
goto free_scan_flter;
}
sme_prepare_beacon_from_bss_descp(*frame_buf, bss_descp, bssid, ie_len);
if (!*channel)
*channel = bss_descp->channelId;
free_scan_flter:
/* free scan filter and exit */
if (scan_filter) {
csr_free_scan_filter(mac_ctx, scan_filter);
qdf_mem_free(scan_filter);
}
if (result_handle)
csr_scan_result_purge(mac_ctx, result_handle);
return status;
}
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
QDF_STATUS sme_fast_reassoc(tHalHandle hal, struct csr_roam_profile *profile,
const tSirMacAddr bssid, int channel,
uint8_t vdev_id, const tSirMacAddr connected_bssid)
{
QDF_STATUS status;
struct wma_roam_invoke_cmd *fastreassoc;
struct scheduler_msg msg = {0};
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct csr_roam_session *session;
struct csr_roam_profile *roam_profile;
session = CSR_GET_SESSION(mac_ctx, vdev_id);
if (!session || !session->pCurRoamProfile) {
sme_err("session %d not found", vdev_id);
return QDF_STATUS_E_FAILURE;
}
roam_profile = session->pCurRoamProfile;
if (roam_profile->supplicant_disabled_roaming ||
roam_profile->driver_disabled_roaming) {
sme_debug("roaming status in Supplicant %d and in driver %d",
roam_profile->supplicant_disabled_roaming,
roam_profile->driver_disabled_roaming);
return QDF_STATUS_E_FAILURE;
}
fastreassoc = qdf_mem_malloc(sizeof(*fastreassoc));
if (NULL == fastreassoc) {
sme_err("qdf_mem_malloc failed for fastreassoc");
return QDF_STATUS_E_NOMEM;
}
/* if both are same then set the flag */
if (!qdf_mem_cmp(connected_bssid, bssid, ETH_ALEN)) {
fastreassoc->is_same_bssid = true;
sme_debug("bssid same, bssid[%pM]", bssid);
}
fastreassoc->vdev_id = vdev_id;
fastreassoc->bssid[0] = bssid[0];
fastreassoc->bssid[1] = bssid[1];
fastreassoc->bssid[2] = bssid[2];
fastreassoc->bssid[3] = bssid[3];
fastreassoc->bssid[4] = bssid[4];
fastreassoc->bssid[5] = bssid[5];
status = sme_get_beacon_frm(hal, profile, bssid,
&fastreassoc->frame_buf,
&fastreassoc->frame_len,
&channel);
if (!channel) {
sme_err("channel retrieval from BSS desc fails!");
qdf_mem_free(fastreassoc);
return QDF_STATUS_E_FAULT;
}
fastreassoc->channel = channel;
if (QDF_STATUS_SUCCESS != status) {
sme_warn("sme_get_beacon_frm failed");
fastreassoc->frame_buf = NULL;
fastreassoc->frame_len = 0;
}
if (csr_is_auth_type_ese(mac_ctx->roam.roamSession[vdev_id].
connectedProfile.AuthType)) {
sme_debug("Beacon is not required for ESE");
if (fastreassoc->frame_len) {
qdf_mem_free(fastreassoc->frame_buf);
fastreassoc->frame_buf = NULL;
fastreassoc->frame_len = 0;
}
}
msg.type = SIR_HAL_ROAM_INVOKE;
msg.reserved = 0;
msg.bodyptr = fastreassoc;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
if (QDF_STATUS_SUCCESS != status) {
sme_err("Not able to post ROAM_INVOKE_CMD message to WMA");
qdf_mem_free(fastreassoc);
}
return status;
}
#endif
QDF_STATUS sme_set_del_pmkid_cache(tHalHandle hal, uint8_t session_id,
tPmkidCacheInfo *pmk_cache_info,
bool is_add)
{
struct wmi_unified_pmk_cache *pmk_cache;
struct scheduler_msg msg;
pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
if (!pmk_cache) {
sme_err("Memory allocation failure");
return QDF_STATUS_E_NOMEM;
}
qdf_mem_set(pmk_cache, sizeof(*pmk_cache), 0);
pmk_cache->session_id = session_id;
if (!pmk_cache_info)
goto send_flush_cmd;
if (!pmk_cache_info->ssid_len) {
pmk_cache->cat_flag = WMI_PMK_CACHE_CAT_FLAG_BSSID;
WMI_CHAR_ARRAY_TO_MAC_ADDR(pmk_cache_info->BSSID.bytes,
&pmk_cache->bssid);
} else {
pmk_cache->cat_flag = WMI_PMK_CACHE_CAT_FLAG_SSID_CACHE_ID;
pmk_cache->ssid.length = pmk_cache_info->ssid_len;
qdf_mem_copy(pmk_cache->ssid.mac_ssid,
pmk_cache_info->ssid,
pmk_cache->ssid.length);
}
pmk_cache->cache_id = (uint32_t) (pmk_cache_info->cache_id[0] << 8 |
pmk_cache_info->cache_id[1]);
if (is_add)
pmk_cache->action_flag = WMI_PMK_CACHE_ACTION_FLAG_ADD_ENTRY;
else
pmk_cache->action_flag = WMI_PMK_CACHE_ACTION_FLAG_DEL_ENTRY;
pmk_cache->pmkid_len = CSR_RSN_PMKID_SIZE;
qdf_mem_copy(pmk_cache->pmkid, pmk_cache_info->PMKID,
CSR_RSN_PMKID_SIZE);
pmk_cache->pmk_len = pmk_cache_info->pmk_len;
qdf_mem_copy(pmk_cache->pmk, pmk_cache_info->pmk,
pmk_cache->pmk_len);
send_flush_cmd:
msg.type = SIR_HAL_SET_DEL_PMKID_CACHE;
msg.reserved = 0;
msg.bodyptr = pmk_cache;
if (QDF_STATUS_SUCCESS !=
scheduler_post_msg(QDF_MODULE_ID_WMA, &msg)) {
sme_err("Not able to post message to WDA");
qdf_mem_free(pmk_cache);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/* ARP DEBUG STATS */
/**
* sme_set_nud_debug_stats() - sme api to set nud debug stats
* @hal: handle to hal
* @set_stats_param: pointer to set stats param
*
* Return: Return QDF_STATUS.
*/
QDF_STATUS sme_set_nud_debug_stats(tHalHandle hal,
struct set_arp_stats_params
*set_stats_param)
{
struct set_arp_stats_params *arp_set_param;
struct scheduler_msg msg;
arp_set_param = qdf_mem_malloc(sizeof(*arp_set_param));
if (arp_set_param == NULL) {
sme_err("Memory allocation failure");
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(arp_set_param, set_stats_param, sizeof(*arp_set_param));
msg.type = WMA_SET_ARP_STATS_REQ;
msg.reserved = 0;
msg.bodyptr = arp_set_param;
if (QDF_STATUS_SUCCESS !=
scheduler_post_msg(QDF_MODULE_ID_WMA, &msg)) {
sme_err("Not able to post message to WDA");
qdf_mem_free(arp_set_param);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* sme_get_nud_debug_stats() - sme api to get nud debug stats
* @hal: handle to hal
* @get_stats_param: pointer to set stats param
*
* Return: Return QDF_STATUS.
*/
QDF_STATUS sme_get_nud_debug_stats(tHalHandle hal,
struct get_arp_stats_params
*get_stats_param)
{
struct get_arp_stats_params *arp_get_param;
struct scheduler_msg msg;
arp_get_param = qdf_mem_malloc(sizeof(*arp_get_param));
if (arp_get_param == NULL) {
sme_err("Memory allocation failure");
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(arp_get_param, get_stats_param, sizeof(*arp_get_param));
msg.type = WMA_GET_ARP_STATS_REQ;
msg.reserved = 0;
msg.bodyptr = arp_get_param;
if (QDF_STATUS_SUCCESS !=
scheduler_post_msg(QDF_MODULE_ID_WMA, &msg)) {
sme_err("Not able to post message to WDA");
qdf_mem_free(arp_get_param);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS sme_set_peer_param(uint8_t *peer_addr, uint32_t param_id,
uint32_t param_value, uint32_t vdev_id)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
sme_err("wma handle is NULL");
return QDF_STATUS_E_FAILURE;
}
return wma_set_peer_param(wma_handle, peer_addr, param_id,
param_value, vdev_id);
}
QDF_STATUS sme_register_set_connection_info_cb(tHalHandle hHal,
bool (*set_connection_info_cb)(bool),
bool (*get_connection_info_cb)(uint8_t *session_id,
enum scan_reject_states *reason))
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMac->sme.set_connection_info_cb = set_connection_info_cb;
pMac->sme.get_connection_info_cb = get_connection_info_cb;
sme_release_global_lock(&pMac->sme);
}
return status;
}
QDF_STATUS sme_rso_cmd_status_cb(mac_handle_t mac_handle,
rso_cmd_status_cb cb)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
mac->sme.rso_cmd_status_cb = cb;
sme_debug("Registered RSO command status callback");
return status;
}
QDF_STATUS sme_set_dbs_scan_selection_config(tHalHandle hal,
struct wmi_dbs_scan_sel_params *params)
{
struct scheduler_msg message = {0};
QDF_STATUS status;
struct wmi_dbs_scan_sel_params *dbs_scan_params;
uint32_t i;
if (0 == params->num_clients) {
sme_err("Num of clients is 0");
return QDF_STATUS_E_FAILURE;
}
dbs_scan_params = qdf_mem_malloc(sizeof(*dbs_scan_params));
if (!dbs_scan_params) {
sme_err("fail to alloc dbs_scan_params");
return QDF_STATUS_E_NOMEM;
}
dbs_scan_params->num_clients = params->num_clients;
dbs_scan_params->pdev_id = params->pdev_id;
for (i = 0; i < params->num_clients; i++) {
dbs_scan_params->module_id[i] = params->module_id[i];
dbs_scan_params->num_dbs_scans[i] = params->num_dbs_scans[i];
dbs_scan_params->num_non_dbs_scans[i] =
params->num_non_dbs_scans[i];
}
message.type = WMA_SET_DBS_SCAN_SEL_CONF_PARAMS;
message.bodyptr = dbs_scan_params;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Not able to post msg to WMA!");
qdf_mem_free(dbs_scan_params);
}
return status;
}
QDF_STATUS sme_get_rcpi(tHalHandle hal, struct sme_rcpi_req *rcpi)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hal);
struct scheduler_msg msg = {0};
struct sme_rcpi_req *rcpi_req;
rcpi_req = qdf_mem_malloc(sizeof(*rcpi_req));
if (rcpi_req == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for rcpi req",
__func__);
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(rcpi_req, rcpi, sizeof(*rcpi_req));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
msg.bodyptr = rcpi_req;
msg.type = WMA_GET_RCPI_REQ;
status = scheduler_post_msg(QDF_MODULE_ID_WMA, &msg);
sme_release_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("post get rcpi req failed"));
status = QDF_STATUS_E_FAILURE;
qdf_mem_free(rcpi_req);
}
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock failed"));
qdf_mem_free(rcpi_req);
}
return status;
}
void sme_store_pdev(tHalHandle hal, struct wlan_objmgr_pdev *pdev)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
void *wma_handle;
QDF_STATUS status;
status = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_LEGACY_MAC_ID);
if (QDF_STATUS_SUCCESS != status) {
mac_ctx->pdev = NULL;
return;
}
mac_ctx->pdev = pdev;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("wma handle is NULL"));
return;
}
wma_store_pdev(wma_handle, pdev);
}
QDF_STATUS sme_congestion_register_callback(tHalHandle hal,
congestion_cb congestion_cb)
{
QDF_STATUS status;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.congestion_cb = congestion_cb;
sme_release_global_lock(&mac->sme);
sme_debug("congestion callback set");
} else {
sme_err("Aquiring lock failed %d", status);
}
return status;
}
QDF_STATUS sme_register_tx_queue_cb(mac_handle_t mac_handle,
tx_queue_cb tx_queue_cb)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.tx_queue_cb = tx_queue_cb;
sme_release_global_lock(&mac->sme);
sme_debug("Tx queue callback set");
} else {
sme_err("Aquiring lock failed %d", status);
}
return status;
}
QDF_STATUS sme_deregister_tx_queue_cb(mac_handle_t mac_handle)
{
return sme_register_tx_queue_cb(mac_handle, NULL);
}
#ifdef WLAN_SUPPORT_TWT
QDF_STATUS sme_register_twt_enable_complete_cb(mac_handle_t mac_handle,
twt_enable_cb twt_enable_cb)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.twt_enable_cb = twt_enable_cb;
sme_release_global_lock(&mac->sme);
sme_debug("TWT: enable callback set");
} else {
sme_err("Aquiring lock failed %d", status);
}
return status;
}
QDF_STATUS sme_register_twt_disable_complete_cb(mac_handle_t mac_handle,
twt_disable_cb twt_disable_cb)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.twt_disable_cb = twt_disable_cb;
sme_release_global_lock(&mac->sme);
sme_debug("TWT: disable callback set");
} else {
sme_err("Aquiring lock failed %d", status);
}
return status;
}
QDF_STATUS sme_deregister_twt_enable_complete_cb(mac_handle_t mac_handle)
{
return sme_register_twt_enable_complete_cb(mac_handle, NULL);
}
QDF_STATUS sme_deregister_twt_disable_complete_cb(mac_handle_t mac_handle)
{
return sme_register_twt_disable_complete_cb(mac_handle, NULL);
}
#endif
QDF_STATUS sme_set_smps_cfg(uint32_t vdev_id, uint32_t param_id,
uint32_t param_val)
{
return wma_configure_smps_params(vdev_id, param_id, param_val);
}
QDF_STATUS sme_ipa_uc_stat_request(tHalHandle hal, uint32_t vdev_id,
uint32_t param_id, uint32_t param_val, uint32_t req_cat)
{
wma_cli_set_cmd_t *iwcmd;
QDF_STATUS status = QDF_STATUS_SUCCESS;
iwcmd = qdf_mem_malloc(sizeof(*iwcmd));
if (!iwcmd) {
sme_err("Failed alloc memory for iwcmd");
return QDF_STATUS_E_NOMEM;
}
qdf_mem_zero(iwcmd, sizeof(*iwcmd));
iwcmd->param_sec_value = 0;
iwcmd->param_vdev_id = vdev_id;
iwcmd->param_id = param_id;
iwcmd->param_vp_dev = req_cat;
iwcmd->param_value = param_val;
wma_ipa_uc_stat_request(iwcmd);
qdf_mem_free(iwcmd);
return status;
}
QDF_STATUS sme_set_reorder_timeout(tHalHandle hal,
struct sir_set_rx_reorder_timeout_val *req)
{
QDF_STATUS status;
tp_wma_handle wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
status = wma_set_rx_reorder_timeout_val(wma_handle, req);
return status;
}
QDF_STATUS sme_set_rx_set_blocksize(tHalHandle hal,
struct sir_peer_set_rx_blocksize *req)
{
QDF_STATUS status;
tp_wma_handle wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
status = wma_set_rx_blocksize(wma_handle, req);
return status;
}
int sme_cli_set_command(int vdev_id, int param_id, int sval, int vpdev)
{
return wma_cli_set_command(vdev_id, param_id, sval, vpdev);
}
QDF_STATUS sme_set_bt_activity_info_cb(mac_handle_t mac_handle,
bt_activity_info_cb cb)
{
QDF_STATUS status;
tpAniSirGlobal mac = MAC_CONTEXT(mac_handle);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.bt_activity_info_cb = cb;
sme_release_global_lock(&mac->sme);
sme_debug("bt activity info callback set");
} else {
sme_debug("sme_acquire_global_lock failed %d", status);
}
return status;
}
QDF_STATUS sme_get_chain_rssi(tHalHandle hal,
struct get_chain_rssi_req_params *input,
get_chain_rssi_callback callback,
void *context)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
tp_wma_handle wma_handle;
SME_ENTER();
if (NULL == input) {
sme_err("Invalid req params");
return QDF_STATUS_E_INVAL;
}
mac_ctx->sme.get_chain_rssi_cb = callback;
mac_ctx->sme.get_chain_rssi_context = context;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
wma_get_chain_rssi(wma_handle, input);
SME_EXIT();
return status;
}
QDF_STATUS sme_process_msg_callback(tpAniSirGlobal mac,
struct scheduler_msg *msg)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
if (msg == NULL) {
sme_err("Empty message for SME Msg callback");
return status;
}
status = sme_process_msg(mac, msg);
return status;
}
void sme_display_disconnect_stats(tHalHandle hal, uint8_t session_id)
{
struct csr_roam_session *session;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sme_err("%s Invalid session id: %d", __func__, session_id);
return;
}
session = CSR_GET_SESSION(mac_ctx, session_id);
if (!session) {
sme_err("%s Failed to get session for id: %d",
__func__, session_id);
return;
}
sme_nofl_info("Total No. of Disconnections: %d",
session->disconnect_stats.disconnection_cnt);
sme_nofl_info("No. of Diconnects Triggered by Application: %d",
session->disconnect_stats.disconnection_by_app);
sme_nofl_info("No. of Disassoc Sent by Peer: %d",
session->disconnect_stats.disassoc_by_peer);
sme_nofl_info("No. of Deauth Sent by Peer: %d",
session->disconnect_stats.deauth_by_peer);
sme_nofl_info("No. of Disconnections due to Beacon Miss: %d",
session->disconnect_stats.bmiss);
sme_nofl_info("No. of Disconnections due to Peer Kickout: %d",
session->disconnect_stats.peer_kickout);
}
#ifdef FEATURE_WLAN_DYNAMIC_CVM
/**
* sme_set_vc_mode_config() - Set voltage corner config to FW
* @bitmap: Bitmap that referes to voltage corner config with
* different phymode and bw configuration
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_set_vc_mode_config(uint32_t vc_bitmap)
{
void *wma_handle;
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"wma_handle is NULL");
return QDF_STATUS_E_FAILURE;
}
if (QDF_STATUS_SUCCESS !=
wma_set_vc_mode_config(wma_handle, vc_bitmap)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Failed to set Voltage Control config to FW",
__func__);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
#endif
/**
* sme_set_bmiss_bcnt() - set bmiss config parameters
* @vdev_id: virtual device for the command
* @first_cnt: bmiss first value
* @final_cnt: bmiss final value
*
* Return: QDF_STATUS_SUCCESS or non-zero on failure
*/
QDF_STATUS sme_set_bmiss_bcnt(uint32_t vdev_id, uint32_t first_cnt,
uint32_t final_cnt)
{
return wma_config_bmiss_bcnt_params(vdev_id, first_cnt, final_cnt);
}
QDF_STATUS sme_send_limit_off_channel_params(tHalHandle hal, uint8_t vdev_id,
bool is_tos_active, uint32_t max_off_chan_time,
uint32_t rest_time, bool skip_dfs_chan)
{
struct sir_limit_off_chan *cmd;
struct scheduler_msg msg = {0};
cmd = qdf_mem_malloc(sizeof(*cmd));
if (!cmd) {
sme_err("qdf_mem_malloc failed for limit off channel");
return QDF_STATUS_E_NOMEM;
}
cmd->vdev_id = vdev_id;
cmd->is_tos_active = is_tos_active;
cmd->max_off_chan_time = max_off_chan_time;
cmd->rest_time = rest_time;
cmd->skip_dfs_chans = skip_dfs_chan;
msg.type = WMA_SET_LIMIT_OFF_CHAN;
msg.reserved = 0;
msg.bodyptr = cmd;
if (!QDF_IS_STATUS_SUCCESS(scheduler_post_msg(QDF_MODULE_ID_WMA,
&msg))) {
sme_err("Not able to post WMA_SET_LIMIT_OFF_CHAN to WMA");
qdf_mem_free(cmd);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
uint32_t sme_unpack_rsn_ie(tHalHandle hal, uint8_t *buf,
uint8_t buf_len, tDot11fIERSN *rsn_ie,
bool append_ie)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
return dot11f_unpack_ie_rsn(mac_ctx, buf, buf_len, rsn_ie, append_ie);
}
#ifdef FEATURE_BSS_TRANSITION
/**
* sme_get_status_for_candidate() - Get bss transition status for candidate
* @hal: Handle for HAL
* @conn_bss_desc: connected bss descriptor
* @bss_desc: candidate bss descriptor
* @info: candiadate bss information
* @trans_reason: transition reason code
* @is_bt_in_progress: bt activity indicator
*
* Return : true if candidate is rejected and reject reason is filled
* @info->status. Otherwise returns false.
*/
static bool sme_get_status_for_candidate(tHalHandle hal,
tSirBssDescription *conn_bss_desc,
tSirBssDescription *bss_desc,
struct bss_candidate_info *info,
uint8_t trans_reason,
bool is_bt_in_progress)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
/*
* Low RSSI based rejection
* If candidate rssi is less than mbo_candidate_rssi_thres and connected
* bss rssi is greater than mbo_current_rssi_thres, then reject the
* candidate with MBO reason code 4.
*/
if ((bss_desc->rssi < mac_ctx->roam.configParam.mbo_thresholds.
mbo_candidate_rssi_thres) &&
(conn_bss_desc->rssi > mac_ctx->roam.configParam.mbo_thresholds.
mbo_current_rssi_thres)) {
sme_err("Candidate BSS "MAC_ADDRESS_STR" has LOW RSSI(%d), hence reject",
MAC_ADDR_ARRAY(bss_desc->bssId), bss_desc->rssi);
info->status = QCA_STATUS_REJECT_LOW_RSSI;
return true;
}
if (trans_reason == MBO_TRANSITION_REASON_LOAD_BALANCING ||
trans_reason == MBO_TRANSITION_REASON_TRANSITIONING_TO_PREMIUM_AP) {
/*
* MCC rejection
* If moving to candidate's channel will result in MCC scenario
* and the rssi of connected bss is greater than
* mbo_current_rssi_mss_thres, then reject the candidate with
* MBO reason code 3.
*/
if ((conn_bss_desc->rssi >
mac_ctx->roam.configParam.mbo_thresholds.
mbo_current_rssi_mcc_thres) &&
csr_is_mcc_channel(mac_ctx, bss_desc->channelId)) {
sme_err("Candidate BSS "MAC_ADDRESS_STR" causes MCC, hence reject",
MAC_ADDR_ARRAY(bss_desc->bssId));
info->status =
QCA_STATUS_REJECT_INSUFFICIENT_QOS_CAPACITY;
return true;
}
/*
* BT coex rejection
* If AP is trying to move the client from 5G to 2.4G and moving
* to 2.4G will result in BT coex and candidate channel rssi is
* less than mbo_candidate_rssi_btc_thres, then reject the
* candidate with MBO reason code 2.
*/
if (WLAN_REG_IS_5GHZ_CH(conn_bss_desc->channelId) &&
WLAN_REG_IS_24GHZ_CH(bss_desc->channelId) &&
is_bt_in_progress &&
(bss_desc->rssi <
mac_ctx->roam.configParam.mbo_thresholds.
mbo_candidate_rssi_btc_thres)) {
sme_err("Candidate BSS "MAC_ADDRESS_STR" causes BT coex, hence reject",
MAC_ADDR_ARRAY(bss_desc->bssId));
info->status =
QCA_STATUS_REJECT_EXCESSIVE_DELAY_EXPECTED;
return true;
}
/*
* LTE coex rejection
* If moving to candidate's channel can cause LTE coex, then
* reject the candidate with MBO reason code 5.
*/
if (policy_mgr_is_safe_channel(mac_ctx->psoc,
conn_bss_desc->channelId) &&
!(policy_mgr_is_safe_channel(mac_ctx->psoc,
bss_desc->channelId))) {
sme_err("High interference expected if transitioned to BSS "
MAC_ADDRESS_STR" hence reject",
MAC_ADDR_ARRAY(bss_desc->bssId));
info->status =
QCA_STATUS_REJECT_HIGH_INTERFERENCE;
return true;
}
}
return false;
}
/**
* wlan_hdd_get_bss_transition_status() - get bss transition status all cadidates
* @adapter : Pointer to adapter
* @transition_reason : Transition reason
* @info : bss candidate information
* @n_candidates : number of candidates
*
* Return : 0 on success otherwise errno
*/
int sme_get_bss_transition_status(tHalHandle hal,
uint8_t transition_reason,
struct qdf_mac_addr *bssid,
struct bss_candidate_info *info,
uint16_t n_candidates,
bool is_bt_in_progress)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tSirBssDescription *bss_desc, *conn_bss_desc;
tCsrScanResultInfo *res, *conn_res;
uint16_t i;
if (!n_candidates || !info) {
sme_err("No candidate info available");
return QDF_STATUS_E_INVAL;
}
conn_res = qdf_mem_malloc(sizeof(tCsrScanResultInfo));
if (!conn_res) {
sme_err("Failed to allocate memory for conn_res");
return QDF_STATUS_E_NOMEM;
}
res = qdf_mem_malloc(sizeof(tCsrScanResultInfo));
if (!res) {
sme_err("Failed to allocate memory for conn_res");
status = QDF_STATUS_E_NOMEM;
goto free;
}
/* Get the connected BSS descriptor */
status = sme_scan_get_result_for_bssid(hal, bssid, conn_res);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("Failed to find connected BSS in scan list");
goto free;
}
conn_bss_desc = &conn_res->BssDescriptor;
for (i = 0; i < n_candidates; i++) {
/* Get candidate BSS descriptors */
status = sme_scan_get_result_for_bssid(hal, &info[i].bssid,
res);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sme_err("BSS "MAC_ADDRESS_STR" not present in scan list",
MAC_ADDR_ARRAY(info[i].bssid.bytes));
info[i].status = QCA_STATUS_REJECT_UNKNOWN;
continue;
}
bss_desc = &res->BssDescriptor;
if (!sme_get_status_for_candidate(hal, conn_bss_desc, bss_desc,
&info[i], transition_reason, is_bt_in_progress)) {
/*
* If status is not over written, it means it is a
* candidate for accept.
*/
info[i].status = QCA_STATUS_ACCEPT;
}
}
/* success */
status = QDF_STATUS_SUCCESS;
free:
/* free allocated memory */
if (conn_res)
qdf_mem_free(conn_res);
if (res)
qdf_mem_free(res);
return status;
}
#endif /* FEATURE_BSS_TRANSITION */
void sme_enable_roaming_on_connected_sta(tHalHandle hal)
{
uint8_t session_id;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
QDF_STATUS status;
session_id = csr_get_roam_enabled_sta_sessionid(mac_ctx);
if (session_id != CSR_SESSION_ID_INVALID)
return;
session_id = csr_get_connected_infra(mac_ctx);
if (session_id == CSR_SESSION_ID_INVALID) {
sme_debug("No STA in conencted state");
return;
}
sme_debug("Roaming not enabled on any STA, enable roaming on session %d",
session_id);
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
csr_roam_offload_scan(mac_ctx, session_id,
ROAM_SCAN_OFFLOAD_START,
REASON_CTX_INIT);
sme_release_global_lock(&mac_ctx->sme);
}
}
int16_t sme_get_oper_chan_freq(struct wlan_objmgr_vdev *vdev)
{
uint8_t vdev_id, chan;
struct csr_roam_session *session;
tpAniSirGlobal mac_ctx;
tHalHandle h_hal;
int16_t freq = 0;
if (vdev == NULL) {
sme_err("Invalid vdev id is passed");
return 0;
}
h_hal = cds_get_context(QDF_MODULE_ID_SME);
if (!h_hal) {
sme_err("h_hal is null");
return 0;
}
mac_ctx = PMAC_STRUCT(h_hal);
vdev_id = wlan_vdev_get_id(vdev);
if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
sme_err("Invalid vdev id is passed");
return 0;
}
session = CSR_GET_SESSION(mac_ctx, vdev_id);
chan = csr_get_infra_operation_channel(mac_ctx, vdev_id);
if (chan)
freq = cds_chan_to_freq(chan);
return freq;
}
enum phy_ch_width sme_get_oper_ch_width(struct wlan_objmgr_vdev *vdev)
{
uint8_t vdev_id;
struct csr_roam_session *session;
tpAniSirGlobal mac_ctx;
tHalHandle h_hal;
enum phy_ch_width ch_width = CH_WIDTH_20MHZ;
if (vdev == NULL) {
sme_err("Invalid vdev id is passed");
return CH_WIDTH_INVALID;
}
h_hal = cds_get_context(QDF_MODULE_ID_SME);
if (!h_hal) {
sme_err("h_hal is null");
return CH_WIDTH_INVALID;
}
mac_ctx = PMAC_STRUCT(h_hal);
vdev_id = wlan_vdev_get_id(vdev);
if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
sme_err("Invalid vdev id is passed");
return CH_WIDTH_INVALID;
}
session = CSR_GET_SESSION(mac_ctx, vdev_id);
if (csr_is_conn_state_connected(mac_ctx, vdev_id))
ch_width = session->connectedProfile.vht_channel_width;
return ch_width;
}
int sme_get_sec20chan_freq_mhz(struct wlan_objmgr_vdev *vdev,
uint16_t *sec20chan_freq)
{
uint8_t vdev_id;
vdev_id = wlan_vdev_get_id(vdev);
/* Need to extend */
return 0;
}
#ifdef WLAN_FEATURE_SAE
QDF_STATUS sme_handle_sae_msg(tHalHandle hal, uint8_t session_id,
uint8_t sae_status)
{
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
struct sir_sae_msg *sae_msg;
struct scheduler_msg sch_msg = {0};
qdf_status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
sae_msg = qdf_mem_malloc(sizeof(*sae_msg));
if (!sae_msg) {
qdf_status = QDF_STATUS_E_NOMEM;
sme_err("SAE: memory allocation failed");
} else {
sae_msg->message_type = eWNI_SME_SEND_SAE_MSG;
sae_msg->length = sizeof(*sae_msg);
sae_msg->session_id = session_id;
sae_msg->sae_status = sae_status;
sme_debug("SAE: sae_status %d session_id %d",
sae_msg->sae_status,
sae_msg->session_id);
sch_msg.type = eWNI_SME_SEND_SAE_MSG;
sch_msg.bodyptr = sae_msg;
qdf_status =
scheduler_post_msg(QDF_MODULE_ID_PE, &sch_msg);
}
sme_release_global_lock(&mac->sme);
}
return qdf_status;
}
#endif
bool sme_is_sta_key_exchange_in_progress(tHalHandle hal, uint8_t session_id)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sme_err("Invalid session id: %d", session_id);
return false;
}
return CSR_IS_WAIT_FOR_KEY(mac_ctx, session_id);
}
bool sme_validate_channel_list(tHalHandle hal,
uint8_t *chan_list,
uint8_t num_channels)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
uint8_t i = 0;
uint8_t j;
bool found;
struct csr_channel *ch_lst_info = &mac_ctx->scan.base_channels;
if (!chan_list || !num_channels) {
sme_err("Chan list empty %pK or num_channels is 0", chan_list);
return false;
}
while (i < num_channels) {
found = false;
for (j = 0; j < ch_lst_info->numChannels; j++) {
if (ch_lst_info->channelList[j] == chan_list[i]) {
found = true;
break;
}
}
if (!found) {
sme_debug("Invalid channel %d", chan_list[i]);
return false;
}
i++;
}
return true;
}
void sme_set_amsdu(tHalHandle hal, bool enable)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
mac_ctx->is_usr_cfg_amsdu_enabled = enable;
}
uint8_t sme_get_mcs_idx(uint16_t max_rate, uint8_t rate_flags,
uint8_t *nss, uint8_t *mcs_rate_flags)
{
return wma_get_mcs_idx(max_rate, rate_flags, nss, mcs_rate_flags);
}
bool sme_find_session_by_bssid(tHalHandle hal, uint8_t *bssid)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
bool ret;
ret = csr_find_session_by_bssid(mac_ctx, bssid);
return ret;
}