blob: be6f4e1220f71269b48533f7e86c3032f767931c [file] [log] [blame]
/*
* Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/**=========================================================================
\file smeApi.c
\brief Definitions for SME APIs
========================================================================*/
/*--------------------------------------------------------------------------
Include Files
------------------------------------------------------------------------*/
#include "sms_debug.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 "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"
extern tSirRetStatus u_mac_post_ctrl_msg(void *pSirGlobal, tSirMbMsg *pMb);
#define LOG_SIZE 256
static tSelfRecoveryStats g_self_recovery_stats;
/* TxMB Functions */
extern QDF_STATUS pmc_prepare_command(tpAniSirGlobal pMac, uint32_t sessionId,
eSmeCommandType cmdType, void *pvParam,
uint32_t size, tSmeCmd **ppCmd);
extern void pmc_release_command(tpAniSirGlobal pMac, tSmeCmd *pCommand);
extern void qos_release_command(tpAniSirGlobal pMac, tSmeCmd *pCommand);
static QDF_STATUS init_sme_cmd_list(tpAniSirGlobal pMac);
static void sme_abort_command(tpAniSirGlobal pMac, tSmeCmd *pCommand,
bool fStopping);
eCsrPhyMode sme_get_phy_mode(tHalHandle hHal);
QDF_STATUS sme_handle_change_country_code(tpAniSirGlobal pMac, void *pMsgBuf);
void sme_disconnect_connected_sessions(tpAniSirGlobal pMac);
QDF_STATUS sme_handle_generic_change_country_code(tpAniSirGlobal pMac,
void *pMsgBuf);
QDF_STATUS sme_process_nss_update_resp(tpAniSirGlobal mac, uint8_t *msg);
#ifdef FEATURE_WLAN_ESE
bool csr_is_supported_channel(tpAniSirGlobal pMac, uint8_t channelId);
#endif
#ifdef WLAN_FEATURE_11W
QDF_STATUS sme_unprotected_mgmt_frm_ind(tHalHandle hHal,
tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm);
#endif
/* Message processor for events from DFS */
QDF_STATUS dfs_msg_processor(tpAniSirGlobal pMac,
uint16_t msg_type, void *pMsgBuf);
/* Channel Change Response Indication Handler */
QDF_STATUS sme_process_channel_change_resp(tpAniSirGlobal pMac,
uint16_t msg_type, void *pMsgBuf);
/* 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;
}
/**
* 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 = NULL;
tSmeCmd *command = NULL;
bool found;
hw_mode_cb callback = NULL;
struct sir_set_hw_mode_resp *param;
enum sir_conn_update_reason reason;
tSmeCmd *saved_cmd;
sms_log(mac, LOG1, FL("%s"), __func__);
param = (struct sir_set_hw_mode_resp *)msg;
if (!param) {
sms_log(mac, LOGE, FL("HW mode resp param is NULL"));
/* Not returning. Need to check if active command list
* needs to be freed
*/
}
entry = csr_ll_peek_head(&mac->sme.smeCmdActiveList,
LL_ACCESS_LOCK);
if (!entry) {
sms_log(mac, LOGE, FL("No cmd found in active list"));
return QDF_STATUS_E_FAILURE;
}
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
if (!command) {
sms_log(mac, LOGE, FL("Base address is NULL"));
return QDF_STATUS_E_FAILURE;
}
if (e_sme_command_set_hw_mode != command->command) {
sms_log(mac, LOGE, FL("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;
sms_log(mac, LOG1, FL("reason:%d session:%d"),
command->u.set_hw_mode_cmd.reason,
command->u.set_hw_mode_cmd.session_id);
if (!callback) {
sms_log(mac, LOGE, FL("Callback does not exist"));
goto end;
}
if (!param) {
sms_log(mac, LOGE,
FL("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);
if (reason == SIR_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
*/
saved_cmd = (tSmeCmd *)mac->sme.saved_scan_cmd;
if (!saved_cmd) {
sms_log(mac, LOGP,
FL("saved cmd is NULL, Check this"));
goto end;
}
if (param->status == SET_HW_MODE_STATUS_OK) {
sms_log(mac, LOG1,
FL("search for ssid success"));
csr_scan_handle_search_for_ssid(mac,
saved_cmd);
} else {
sms_log(mac, LOG1,
FL("search for ssid failure"));
csr_scan_handle_search_for_ssid_failure(mac,
saved_cmd);
}
if (saved_cmd->u.roamCmd.pRoamBssEntry)
qdf_mem_free(
saved_cmd->u.roamCmd.pRoamBssEntry);
if (saved_cmd->u.scanCmd.u.scanRequest.SSIDs.SSIDList)
qdf_mem_free(saved_cmd->u.scanCmd.u.
scanRequest.SSIDs.SSIDList);
if (saved_cmd->u.scanCmd.pToRoamProfile)
qdf_mem_free(saved_cmd->u.scanCmd.
pToRoamProfile);
if (saved_cmd) {
qdf_mem_free(saved_cmd);
saved_cmd = NULL;
mac->sme.saved_scan_cmd = NULL;
}
}
end:
found = csr_ll_remove_entry(&mac->sme.smeCmdActiveList, entry,
LL_ACCESS_LOCK);
if (found) {
/* Now put this command back on the avilable command list */
sme_release_command(mac, command);
}
sme_process_pending_queue(mac);
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)
{
hw_mode_transition_cb callback = NULL;
struct sir_hw_mode_trans_ind *param;
param = (struct sir_hw_mode_trans_ind *)msg;
if (!param) {
sms_log(mac, LOGE, FL("HW mode trans ind param is NULL"));
return QDF_STATUS_E_FAILURE;
}
callback = mac->sme.sme_hw_mode_trans_cb;
if (callback) {
sms_log(mac, LOGE, FL("Calling registered callback..."));
callback(param->old_hw_mode_index,
param->new_hw_mode_index,
param->num_vdev_mac_entries,
param->vdev_mac_map);
}
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;
QDF_STATUS qdf_status;
qdf_mc_timer_t *cmdTimeoutTimer = NULL;
uint32_t sme_cmd_ptr_ary_sz;
pMac->sme.totalSmeCmd = SME_TOTAL_COMMAND;
status = csr_ll_open(pMac->hHdd, &pMac->sme.smeCmdActiveList);
if (!QDF_IS_STATUS_SUCCESS(status))
goto end;
status = csr_ll_open(pMac->hHdd, &pMac->sme.smeCmdPendingList);
if (!QDF_IS_STATUS_SUCCESS(status))
goto end;
status = csr_ll_open(pMac->hHdd, &pMac->sme.smeScanCmdActiveList);
if (!QDF_IS_STATUS_SUCCESS(status))
goto end;
status = csr_ll_open(pMac->hHdd, &pMac->sme.smeScanCmdPendingList);
if (!QDF_IS_STATUS_SUCCESS(status))
goto end;
status = csr_ll_open(pMac->hHdd, &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);
}
/* This timer is only to debug the active list command timeout */
cmdTimeoutTimer =
(qdf_mc_timer_t *) qdf_mem_malloc(sizeof(qdf_mc_timer_t));
if (cmdTimeoutTimer) {
pMac->sme.smeCmdActiveList.cmdTimeoutTimer = cmdTimeoutTimer;
qdf_status =
qdf_mc_timer_init(pMac->sme.smeCmdActiveList.
cmdTimeoutTimer, QDF_TIMER_TYPE_SW,
active_list_cmd_timeout_handle, (void *)pMac);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Init Timer fail for active list command process time out");
qdf_mem_free(pMac->sme.smeCmdActiveList.
cmdTimeoutTimer);
pMac->sme.smeCmdActiveList.cmdTimeoutTimer = NULL;
} else {
pMac->sme.smeCmdActiveList.cmdTimeoutDuration =
CSR_ACTIVE_LIST_CMD_TIMEOUT_VALUE;
}
}
end:
if (!QDF_IS_STATUS_SUCCESS(status))
sms_log(pMac, LOGE, "failed to initialize sme command list:%d\n",
status);
return status;
}
void sme_release_command(tpAniSirGlobal pMac, tSmeCmd *pCmd)
{
pCmd->command = eSmeNoCommand;
csr_ll_insert_tail(&pMac->sme.smeCmdFreeList, &pCmd->Link, LL_ACCESS_LOCK);
}
static void sme_release_cmd_list(tpAniSirGlobal pMac, tDblLinkList *pList)
{
tListElem *pEntry;
tSmeCmd *pCommand;
while ((pEntry = csr_ll_remove_head(pList, LL_ACCESS_LOCK)) != NULL) {
/* TODO: base on command type to call release functions */
/* reinitialize different command types so they can be reused */
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
sme_abort_command(pMac, pCommand, true);
}
}
static void purge_sme_cmd_list(tpAniSirGlobal pMac)
{
/* release any out standing commands back to free command list */
sme_release_cmd_list(pMac, &pMac->sme.smeCmdPendingList);
sme_release_cmd_list(pMac, &pMac->sme.smeCmdActiveList);
sme_release_cmd_list(pMac, &pMac->sme.smeScanCmdPendingList);
sme_release_cmd_list(pMac, &pMac->sme.smeScanCmdActiveList);
}
void purge_sme_session_cmd_list(tpAniSirGlobal pMac, uint32_t sessionId,
tDblLinkList *pList)
{
/* release any out standing commands back to free command list */
tListElem *pEntry, *pNext;
tSmeCmd *pCommand;
tDblLinkList localList;
qdf_mem_zero(&localList, sizeof(tDblLinkList));
if (!QDF_IS_STATUS_SUCCESS(csr_ll_open(pMac->hHdd, &localList))) {
sms_log(pMac, LOGE, FL(" failed to open list"));
return;
}
csr_ll_lock(pList);
pEntry = csr_ll_peek_head(pList, LL_ACCESS_NOLOCK);
while (pEntry != NULL) {
pNext = csr_ll_next(pList, pEntry, LL_ACCESS_NOLOCK);
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
if (pCommand->sessionId == sessionId) {
if (csr_ll_remove_entry(pList, pEntry, LL_ACCESS_NOLOCK)) {
csr_ll_insert_tail(&localList, pEntry,
LL_ACCESS_NOLOCK);
}
}
pEntry = pNext;
}
csr_ll_unlock(pList);
while ((pEntry = csr_ll_remove_head(&localList, LL_ACCESS_NOLOCK))) {
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
sme_abort_command(pMac, pCommand, true);
}
csr_ll_close(&localList);
}
static QDF_STATUS free_sme_cmd_list(tpAniSirGlobal pMac)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
purge_sme_cmd_list(pMac);
csr_ll_close(&pMac->sme.smeCmdPendingList);
csr_ll_close(&pMac->sme.smeCmdActiveList);
csr_ll_close(&pMac->sme.smeScanCmdPendingList);
csr_ll_close(&pMac->sme.smeScanCmdActiveList);
csr_ll_close(&pMac->sme.smeCmdFreeList);
/*destroy active list command time out timer */
qdf_mc_timer_destroy(pMac->sme.smeCmdActiveList.cmdTimeoutTimer);
qdf_mem_free(pMac->sme.smeCmdActiveList.cmdTimeoutTimer);
pMac->sme.smeCmdActiveList.cmdTimeoutTimer = NULL;
status = qdf_mutex_acquire(&pMac->sme.lkSmeGlobalLock);
if (status != QDF_STATUS_SUCCESS) {
sms_log(pMac, LOGE,
FL("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) {
sms_log(pMac, LOGE,
FL("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 eSmeCommandScan:
sms_log(pMac, LOGE, " scan command reason is %d",
pCmd->u.scanCmd.reason);
break;
case eSmeCommandRoam:
sms_log(pMac, LOGE, " roam command reason is %d",
pCmd->u.roamCmd.roamReason);
break;
case eSmeCommandWmStatusChange:
sms_log(pMac, LOGE, " WMStatusChange command type is %d",
pCmd->u.wmStatusChangeCmd.Type);
break;
case eSmeCommandSetKey:
sms_log(pMac, LOGE, " setKey command auth(%d) enc(%d)",
pCmd->u.setKeyCmd.authType, pCmd->u.setKeyCmd.encType);
break;
default:
sms_log(pMac, LOGE, " 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_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
if (pEntry) {
pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
}
sms_log(pMac, LOGE,
"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_ll_lock(&pMac->sme.smeCmdPendingList);
pEntry =
csr_ll_peek_head(&pMac->sme.smeCmdPendingList,
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)
sms_log(pMac, LOGE,
"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_ll_next(&pMac->sme.smeCmdPendingList, pEntry,
LL_ACCESS_NOLOCK);
}
csr_ll_unlock(&pMac->sme.smeCmdPendingList);
idx = 1;
/* There may be some more command in CSR's own pending queue */
csr_ll_lock(&pMac->roam.roamCmdPendingList);
pEntry =
csr_ll_peek_head(&pMac->roam.roamCmdPendingList,
LL_ACCESS_NOLOCK);
while (pEntry && !sme_command_queue_full) {
pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
/* Print only 1st five commands from CSR pending queue */
if (idx <= 5)
sms_log(pMac, LOGE,
"Out of command buffer.... "
"CSR roamCmdPendingList command #%d (0x%X)",
idx, pTempCmd->command);
idx++;
dump_csr_command_info(pMac, pTempCmd);
pEntry =
csr_ll_next(&pMac->roam.roamCmdPendingList, pEntry,
LL_ACCESS_NOLOCK);
}
/* Increment static variable so that it prints
* pending command only once
*/
sme_command_queue_full++;
csr_ll_unlock(&pMac->roam.roamCmdPendingList);
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 if (pMac->sme.enableSelfRecovery)
cds_trigger_recovery(false);
else
QDF_BUG(0);
}
/* 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;
}
void sme_push_command(tpAniSirGlobal pMac, tSmeCmd *pCmd, bool fHighPriority)
{
if (!SME_IS_START(pMac)) {
sms_log(pMac, LOGE, FL("Sme in stop state"));
QDF_ASSERT(0);
return;
}
if (fHighPriority) {
csr_ll_insert_head(&pMac->sme.smeCmdPendingList, &pCmd->Link,
LL_ACCESS_LOCK);
} else {
csr_ll_insert_tail(&pMac->sme.smeCmdPendingList, &pCmd->Link,
LL_ACCESS_LOCK);
}
/* process the command queue... */
sme_process_pending_queue(pMac);
return;
}
/* For commands that need to do extra cleanup. */
static void sme_abort_command(tpAniSirGlobal pMac, tSmeCmd *pCommand,
bool fStopping)
{
if (eSmePmcCommandMask & pCommand->command) {
sms_log(pMac, LOG1,
"No need to process PMC commands");
return;
}
if (eSmeCsrCommandMask & pCommand->command) {
csr_abort_command(pMac, pCommand, fStopping);
return;
}
switch (pCommand->command) {
case eSmeCommandRemainOnChannel:
if (NULL != pCommand->u.remainChlCmd.callback) {
remainOnChanCallback callback =
pCommand->u.remainChlCmd.callback;
/* process the msg */
if (callback) {
callback(pMac, pCommand->u.remainChlCmd.
callbackCtx, eCSR_SCAN_ABORT,
pCommand->u.remainChlCmd.scan_id);
}
}
sme_release_command(pMac, pCommand);
break;
default:
sme_release_command(pMac, pCommand);
break;
}
}
static
tListElem *csr_get_cmd_to_process(tpAniSirGlobal pMac, tDblLinkList *pList,
uint8_t sessionId, bool fInterlocked)
{
tListElem *pCurEntry = NULL;
tSmeCmd *pCommand;
/* Go through the list and return the command whose session id is not
* matching with the current ongoing scan cmd sessionId */
pCurEntry = csr_ll_peek_head(pList, LL_ACCESS_LOCK);
while (pCurEntry) {
pCommand = GET_BASE_ADDR(pCurEntry, tSmeCmd, Link);
if (pCommand->sessionId != sessionId) {
sms_log(pMac, LOG1,
"selected the command with different sessionId");
return pCurEntry;
}
pCurEntry = csr_ll_next(pList, pCurEntry, fInterlocked);
}
sms_log(pMac, LOG1, "No command pending with different sessionId");
return NULL;
}
static bool sme_process_scan_queue(tpAniSirGlobal pMac)
{
tListElem *pEntry;
tSmeCmd *pCommand;
tListElem *pSmeEntry = NULL;
tSmeCmd *pSmeCommand = NULL;
bool status = true;
if ((!csr_ll_is_list_empty(&pMac->sme.smeCmdActiveList,
LL_ACCESS_LOCK))) {
pSmeEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList,
LL_ACCESS_LOCK);
if (pSmeEntry)
pSmeCommand = GET_BASE_ADDR(pSmeEntry, tSmeCmd, Link);
}
csr_ll_lock(&pMac->sme.smeScanCmdActiveList);
if (csr_ll_is_list_empty(&pMac->sme.smeScanCmdPendingList,
LL_ACCESS_LOCK))
goto end;
pEntry = csr_ll_peek_head(&pMac->sme.smeScanCmdPendingList,
LL_ACCESS_LOCK);
if (!pEntry)
goto end;
sms_log(pMac, LOG1,
FL("scan_count in active scanlist %d "),
pMac->sme.smeScanCmdActiveList.Count);
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
if (pSmeCommand != NULL) {
/*
* if scan is running on one interface and SME receives
* the next command on the same interface then
* dont the allow the command to be queued to
* smeCmdPendingList. If next scan is allowed on
* the same interface the CSR state machine will
* get screwed up.
*/
if (pSmeCommand->sessionId == pCommand->sessionId) {
status = false;
goto end;
}
}
/*
* We cannot execute any command in wait-for-key state until setKey is
* through.
*/
if (CSR_IS_WAIT_FOR_KEY(pMac, pCommand->sessionId)) {
if (!CSR_IS_SET_KEY_COMMAND(pCommand)) {
sms_log(pMac, LOGE,
FL("Can't process cmd(%d), waiting for key"),
pCommand->command);
status = false;
goto end;
}
}
if (csr_ll_remove_entry(&pMac->sme.smeScanCmdPendingList, pEntry,
LL_ACCESS_LOCK)) {
csr_ll_insert_head(&pMac->sme.smeScanCmdActiveList,
&pCommand->Link, LL_ACCESS_NOLOCK);
switch (pCommand->command) {
case eSmeCommandScan:
sms_log(pMac, LOG1, FL("Processing scan offload cmd."));
qdf_mc_timer_start(&pCommand->u.scanCmd.csr_scan_timer,
CSR_ACTIVE_SCAN_LIST_CMD_TIMEOUT);
csr_process_scan_command(pMac, pCommand);
break;
case eSmeCommandRemainOnChannel:
sms_log(pMac, LOG1,
FL("Processing remain on channel offload cmd"));
p2p_process_remain_on_channel_cmd(pMac, pCommand);
break;
default:
sms_log(pMac, LOGE,
FL("Wrong cmd enqueued to ScanCmdPendingList"));
pEntry = csr_ll_remove_head(
&pMac->sme.smeScanCmdActiveList,
LL_ACCESS_NOLOCK);
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
sme_release_command(pMac, pCommand);
break;
}
}
end:
csr_ll_unlock(&pMac->sme.smeScanCmdActiveList);
return status;
}
/**
* sme_process_command() - processes SME commnd
* @mac_ctx: mac global context
*
* This function is called by sme_process_pending_queue() in a while loop
*
* Return: true indicates that caller function can proceed to next cmd
* false otherwise.
*/
static bool sme_process_command(tpAniSirGlobal pMac)
{
bool fContinue = false;
QDF_STATUS status = QDF_STATUS_SUCCESS;
tListElem *pEntry;
tSmeCmd *pCommand;
tListElem *pSmeEntry;
tSmeCmd *pSmeCommand;
/*
* if the ActiveList is empty, then nothing is active so we can process
* a pending command...
* alwasy lock active list before locking pending list
*/
csr_ll_lock(&pMac->sme.smeCmdActiveList);
if (!csr_ll_is_list_empty(&pMac->sme.smeCmdActiveList,
LL_ACCESS_NOLOCK)) {
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
goto process_scan_q;
}
if (csr_ll_is_list_empty(&pMac->sme.smeCmdPendingList,
LL_ACCESS_LOCK)) {
/* No command waiting */
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
goto process_scan_q;
}
/*
* If scan command is pending in the smeScanCmdActive list then pick the
* command from smeCmdPendingList which is not matching with the scan
* command session id. At any point of time only one command will be
* allowed on a single session.
*/
if (!csr_ll_is_list_empty(
&pMac->sme.smeScanCmdActiveList, LL_ACCESS_LOCK)) {
pSmeEntry = csr_ll_peek_head(&pMac->sme.smeScanCmdActiveList,
LL_ACCESS_LOCK);
if (pSmeEntry) {
pSmeCommand = GET_BASE_ADDR(pSmeEntry, tSmeCmd, Link);
pEntry = csr_get_cmd_to_process(pMac,
&pMac->sme.smeCmdPendingList,
pSmeCommand->sessionId,
LL_ACCESS_LOCK);
goto sme_process_cmd;
}
}
/* Peek the command */
pEntry = csr_ll_peek_head(&pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK);
sme_process_cmd:
if (!pEntry) {
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
goto process_scan_q;
}
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
/*
* Allow only disconnect command in wait-for-key state until setKey is
* through.
*/
if (CSR_IS_WAIT_FOR_KEY(pMac, pCommand->sessionId)
&& !CSR_IS_DISCONNECT_COMMAND(pCommand)
&& !CSR_IS_SET_KEY_COMMAND(pCommand)) {
if (CSR_IS_CLOSE_SESSION_COMMAND(pCommand)) {
tSmeCmd *sme_cmd = NULL;
sms_log(pMac, LOGE,
FL("SessionId %d: close session command issued while waiting for key, issue disconnect first"),
pCommand->sessionId);
status = csr_prepare_disconnect_command(pMac,
pCommand->sessionId, &sme_cmd);
if (status == QDF_STATUS_SUCCESS && sme_cmd) {
csr_ll_lock(&pMac->sme.smeCmdPendingList);
csr_ll_insert_head(&pMac->sme.smeCmdPendingList,
&sme_cmd->Link, LL_ACCESS_NOLOCK);
pEntry = csr_ll_peek_head(
&pMac->sme.smeCmdPendingList,
LL_ACCESS_NOLOCK);
csr_ll_unlock(&pMac->sme.smeCmdPendingList);
goto sme_process_cmd;
}
}
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
sms_log(pMac, LOGE,
FL("SessionId %d: Can't process cmd(%d), waiting for key"),
pCommand->sessionId, pCommand->command);
fContinue = false;
goto process_scan_q;
}
if (!csr_ll_remove_entry(&pMac->sme.smeCmdPendingList, pEntry,
LL_ACCESS_LOCK)) {
/* This is odd. Some one else pull off the command. */
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
goto process_scan_q;
}
/* we can reuse the pCommand. Insert the command onto the ActiveList */
csr_ll_insert_head(&pMac->sme.smeCmdActiveList, &pCommand->Link,
LL_ACCESS_NOLOCK);
/* .... and process the command. */
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_COMMAND,
pCommand->sessionId, pCommand->command));
switch (pCommand->command) {
case eSmeCommandScan:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
status = csr_process_scan_command(pMac, pCommand);
break;
case eSmeCommandRoam:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
status = csr_roam_process_command(pMac, pCommand);
if (!QDF_IS_STATUS_SUCCESS(status)
&& csr_ll_remove_entry(&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK))
csr_release_command_roam(pMac, pCommand);
break;
case eSmeCommandWmStatusChange:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
csr_roam_process_wm_status_change_command(pMac, pCommand);
break;
case eSmeCommandSetKey:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
status = csr_roam_process_set_key_command(pMac, pCommand);
if (!QDF_IS_STATUS_SUCCESS(status)
&& csr_ll_remove_entry(&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK)) {
csr_release_command_set_key(pMac, pCommand);
}
break;
case eSmeCommandAddStaSession:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
csr_process_add_sta_session_command(pMac, pCommand);
break;
case eSmeCommandNdpInitiatorRequest:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
if (csr_process_ndp_initiator_request(pMac, pCommand) !=
QDF_STATUS_SUCCESS)
if (csr_ll_remove_entry(
&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK))
csr_release_command(pMac, pCommand);
break;
case eSmeCommandNdpResponderRequest:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
status = csr_process_ndp_responder_request(pMac, pCommand);
if (status != QDF_STATUS_SUCCESS) {
if (csr_ll_remove_entry(&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK))
csr_release_command(pMac, pCommand);
}
break;
case eSmeCommandNdpDataEndInitiatorRequest:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
status = csr_process_ndp_data_end_request(pMac, pCommand);
if (status != QDF_STATUS_SUCCESS) {
if (csr_ll_remove_entry(&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK))
csr_release_command(pMac, pCommand);
}
break;
case eSmeCommandDelStaSession:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
csr_process_del_sta_session_command(pMac, pCommand);
break;
case eSmeCommandRemainOnChannel:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
p2p_process_remain_on_channel_cmd(pMac, pCommand);
break;
/*
* Treat standby differently here because caller may not be able
* to handle the failure so we do our best here
*/
case eSmeCommandEnterStandby:
break;
case eSmeCommandAddTs:
case eSmeCommandDelTs:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
fContinue = qos_process_command(pMac, pCommand);
if (fContinue && csr_ll_remove_entry(
&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_NOLOCK)) {
/* The command failed, remove it */
qos_release_command(pMac, pCommand);
}
#endif
break;
#ifdef FEATURE_WLAN_TDLS
case eSmeCommandTdlsSendMgmt:
case eSmeCommandTdlsAddPeer:
case eSmeCommandTdlsDelPeer:
case eSmeCommandTdlsLinkEstablish:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("sending TDLS Command 0x%x to PE"),
pCommand->command);
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
status = csr_tdls_process_cmd(pMac, pCommand);
if (!QDF_IS_STATUS_SUCCESS(status)) {
if (csr_ll_remove_entry(&pMac->sme.smeCmdActiveList,
&pCommand->Link,
LL_ACCESS_LOCK)) {
qdf_mem_zero(&pCommand->u.tdlsCmd,
sizeof(tTdlsCmd));
csr_release_command(pMac, pCommand);
}
}
break;
#endif
case e_sme_command_set_hw_mode:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
csr_process_set_hw_mode(pMac, pCommand);
break;
case e_sme_command_nss_update:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
csr_process_nss_update_req(pMac, pCommand);
break;
case e_sme_command_set_dual_mac_config:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
csr_process_set_dual_mac_config(pMac, pCommand);
break;
case e_sme_command_set_antenna_mode:
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
csr_process_set_antenna_mode(pMac, pCommand);
break;
default:
/* something is wrong */
/* remove it from the active list */
sms_log(pMac, LOGE, FL("unknown command %d"),
pCommand->command);
pEntry = csr_ll_remove_head(&pMac->sme.smeCmdActiveList,
LL_ACCESS_NOLOCK);
csr_ll_unlock(&pMac->sme.smeCmdActiveList);
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
sme_release_command(pMac, pCommand);
status = QDF_STATUS_E_FAILURE;
break;
}
if (!QDF_IS_STATUS_SUCCESS(status))
fContinue = true;
process_scan_q:
if (!(sme_process_scan_queue(pMac)))
fContinue = false;
return fContinue;
}
void sme_process_pending_queue(tpAniSirGlobal pMac)
{
while (sme_process_command(pMac))
;
}
bool sme_command_pending(tpAniSirGlobal pMac)
{
return !csr_ll_is_list_empty(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK)
|| !csr_ll_is_list_empty(&pMac->sme.smeCmdPendingList,
LL_ACCESS_NOLOCK);
}
/**
* 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_ll_peek_head(&mac->sme.smeCmdActiveList, 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);
sms_log(mac, LOG1, FL("size of buffer: %d"), *size);
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);
}
/* 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))) {
sms_log(pMac, LOGE, FL("sme_open failed init lock"));
return QDF_STATUS_E_FAILURE;
}
status = csr_open(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, FL("csr_open failed, status=%d"), status);
return status;
}
status = sme_ps_open(hHal);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
FL("sme_ps_open failed during initialization with status=%d"),
status);
return status;
}
#ifdef FEATURE_WLAN_TDLS
pMac->is_tdls_power_save_prohibited = 0;
#endif
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
status = sme_qos_open(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, FL("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)) {
sms_log(pMac, LOGE, FL("rrm_open failed, status=%d"), status);
return status;
}
sme_p2p_open(pMac);
sme_trace_init(pMac);
sme_register_debug_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);
}
/*--------------------------------------------------------------------------
\brief 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
\param hHal - The handle returned by mac_open.
\Param 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.
\sa
--------------------------------------------------------------------------*/
QDF_STATUS sme_set11dinfo(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_SET_11DINFO, NO_SESSION, 0));
if (NULL == pSmeConfigParams) {
sms_log(pMac, LOGE,
"Empty config param structure for SME, nothing to update");
return status;
}
status = csr_set_channels(hHal, &pSmeConfigParams->csrConfig);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
"csr_change_default_config_param 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);
mac_ctx->lim.scan_disabled = value;
sms_log(mac_ctx, LOG1, FL("value=%d"), value);
}
/*--------------------------------------------------------------------------
\brief sme_get_soft_ap_domain() - Get the current regulatory domain of softAp.
This is a synchronous call
\param hHal - The handle returned by HostapdAdapter.
\Param 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.
\sa
--------------------------------------------------------------------------*/
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) {
sms_log(pMac, LOGE, "Uninitialized domain Id");
return status;
}
*domainIdSoftAp = pMac->scan.domainIdCurrent;
status = QDF_STATUS_SUCCESS;
return status;
}
QDF_STATUS sme_set_reg_info(tHalHandle hHal, uint8_t *apCntryCode)
{
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_SET_REGINFO, NO_SESSION, 0));
if (NULL == apCntryCode) {
sms_log(pMac, LOGE, "Empty Country Code, nothing to update");
return status;
}
status = csr_set_reg_info(hHal, apCntryCode);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE, "csr_set_reg_info failed with status=%d",
status);
}
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);
mac_ctx->fine_time_meas_cap = 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 */
csr_roam_offload_scan(mac_ctx, session_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_CONNECT_IES_CHANGED);
}
/*--------------------------------------------------------------------------
\brief 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
\param hHal - The handle returned by mac_open.
\Param 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.
\sa
--------------------------------------------------------------------------*/
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) {
sms_log(pMac, LOGE,
"Empty config param structure for SME, nothing to update");
return status;
}
status =
csr_change_default_config_param(pMac, &pSmeConfigParams->csrConfig);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
"csr_change_default_config_param failed with status=%d",
status);
}
status =
rrm_change_default_config_param(hHal, &pSmeConfigParams->rrmConfig);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
"rrm_change_default_config_param failed with 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");
}
return 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;
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;
}
csr_roam_offload_scan(mac_ctx, session_id, ROAM_SCAN_OFFLOAD_UPDATE_CFG,
update_param);
return 0;
}
#ifdef WLAN_FEATURE_GTK_OFFLOAD
static void sme_process_get_gtk_info_rsp(tHalHandle hHal,
tpSirGtkOffloadGetInfoRspParams
pGtkOffloadGetInfoRsp)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pMac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
"%s: pMac is null", __func__);
return;
}
if (pMac->sme.gtk_offload_get_info_cb == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: HDD callback is null", __func__);
return;
}
pMac->sme.gtk_offload_get_info_cb(
pMac->sme.gtk_offload_get_info_cb_context,
pGtkOffloadGetInfoRsp);
}
#endif
/*--------------------------------------------------------------------------
\fn - sme_process_ready_to_suspend
\brief - On getting ready to suspend indication, this function calls
callback registered (HDD callbacks) with SME to inform
ready to suspend indication.
\param hHal - Handle returned by mac_open.
pReadyToSuspend - Parameter received along with ready to suspend
indication from WMA.
\return None
\sa
--------------------------------------------------------------------------*/
static void sme_process_ready_to_suspend(tHalHandle hHal,
tpSirReadyToSuspendInd pReadyToSuspend)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pMac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
"%s: pMac is null", __func__);
return;
}
if (NULL != pMac->readyToSuspendCallback) {
pMac->readyToSuspendCallback(pMac->readyToSuspendContext,
pReadyToSuspend->suspended);
pMac->readyToSuspendCallback = NULL;
}
}
#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
/**
* sme_process_ready_to_ext_wow() - inform ready to ExtWoW indication.
* @hHal - Handle returned by mac_open.
* @pReadyToExtWoW - Parameter received along with ready to Ext WoW
* indication from WMA.
*
* 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(tHalHandle hHal,
tpSirReadyToExtWoWInd pReadyToExtWoW)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pMac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
"%s: pMac is null", __func__);
return;
}
if (NULL != pMac->readyToExtWoWCallback) {
pMac->readyToExtWoWCallback(pMac->readyToExtWoWContext,
pReadyToExtWoW->status);
pMac->readyToExtWoWCallback = NULL;
pMac->readyToExtWoWContext = NULL;
}
}
#endif
/*--------------------------------------------------------------------------
\brief 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
\param 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.
\sa
--------------------------------------------------------------------------*/
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.messageType = eWNI_SME_SYS_READY_IND;
Msg.length = sizeof(tSirSmeReadyReq);
Msg.add_bssdescr_cb = csr_scan_process_single_bssdescr;
Msg.csr_roam_synch_cb = csr_roam_synch_callback;
if (eSIR_FAILURE != u_mac_post_ctrl_msg(hHal, (tSirMbMsg *) &Msg)) {
status = QDF_STATUS_SUCCESS;
} else {
sms_log(pMac, LOGE,
"u_mac_post_ctrl_msg failed to send eWNI_SME_SYS_READY_IND");
break;
}
status = csr_ready(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
"csr_ready failed with status=%d",
status);
break;
}
if (QDF_STATUS_SUCCESS != rrm_ready(hHal)) {
status = QDF_STATUS_E_FAILURE;
sms_log(pMac, LOGE, "rrm_ready failed");
break;
}
pMac->sme.state = SME_STATE_READY;
} while (0);
return status;
}
/*--------------------------------------------------------------------------
\brief 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
\param hHal - The handle returned by mac_open.
\return QDF_STATUS_SUCCESS - SME is ready.
Other status means SME is failed to start
\sa
--------------------------------------------------------------------------*/
QDF_STATUS sme_start(tHalHandle hHal)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
do {
status = csr_start(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
"csr_start failed during smeStart with status=%d",
status);
break;
}
pMac->sme.state = SME_STATE_START;
} while (0);
return status;
}
/**
* sme_handle_scan_req() - Scan request handler
* @mac_ctx: MAC global context
* @msg: message buffer
*
* Scan request message from upper layer is handled as
* part of this API
*
* Return: QDF_STATUS
*/
static QDF_STATUS sme_handle_scan_req(tpAniSirGlobal mac_ctx,
void *msg)
{
struct ani_scan_req *scan_msg;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
uint16_t session_id;
csr_scan_completeCallback callback;
scan_msg = msg;
session_id = scan_msg->session_id;
callback = scan_msg->callback;
status = csr_scan_request(mac_ctx, session_id,
scan_msg->scan_param,
callback, scan_msg->ctx);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac_ctx, LOGE,
FL("scan request failed. session_id %d"), session_id);
}
csr_scan_free_request(mac_ctx, scan_msg->scan_param);
qdf_mem_free(scan_msg->scan_param);
return status;
}
/**
* sme_handle_roc_req() - Roc request handler
* @mac_ctx: MAC global context
* @msg: message buffer
*
* Roc request message from upper layer is handled as
* part of this API
*
* Return: QDF_STATUS
*/
static QDF_STATUS sme_handle_roc_req(tHalHandle hal,
void *msg)
{
struct ani_roc_req *roc_msg;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
remainOnChanCallback callback;
if (msg == NULL) {
sms_log(mac_ctx, LOGE, FL("ROC request is NULL"));
return status;
}
roc_msg = msg;
callback = roc_msg->callback;
status = p2p_remain_on_channel(hal, roc_msg->session_id,
roc_msg->channel, roc_msg->duration, callback,
roc_msg->ctx, roc_msg->is_p2pprobe_allowed,
roc_msg->scan_id);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac_ctx, LOGE,
FL("scan request failed. session_id %d scan_id %d"),
roc_msg->session_id, roc_msg->scan_id);
}
return status;
}
#ifdef WLAN_FEATURE_11W
/*------------------------------------------------------------------
*
* Handle the unprotected management frame indication from LIM and
* forward it to HDD.
*
*------------------------------------------------------------------*/
QDF_STATUS sme_unprotected_mgmt_frm_ind(tHalHandle hHal,
tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
tCsrRoamInfo pRoamInfo = { 0 };
uint32_t SessionId = pSmeMgmtFrm->sessionId;
pRoamInfo.nFrameLength = pSmeMgmtFrm->frameLen;
pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf;
pRoamInfo.frameType = pSmeMgmtFrm->frameType;
/* forward the mgmt frame to HDD */
csr_roam_call_callback(pMac, SessionId, &pRoamInfo, 0,
eCSR_ROAM_UNPROT_MGMT_FRAME_IND, 0);
return status;
}
#endif
/*------------------------------------------------------------------
*
* Handle the DFS Radar Event and indicate it to the SAP
*
*------------------------------------------------------------------*/
QDF_STATUS dfs_msg_processor(tpAniSirGlobal pMac, uint16_t msgType, void *pMsgBuf)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tCsrRoamInfo roamInfo = { 0 };
tSirSmeDfsEventInd *dfs_event;
tSirSmeCSAIeTxCompleteRsp *csaIeTxCompleteRsp;
uint32_t sessionId = 0;
eRoamCmdStatus roamStatus;
eCsrRoamResult roamResult;
int i;
switch (msgType) {
case eWNI_SME_DFS_RADAR_FOUND:
{
/* Radar found !! */
dfs_event = (tSirSmeDfsEventInd *) pMsgBuf;
if (NULL == dfs_event) {
sms_log(pMac, LOGE,
"%s: pMsg is NULL for eWNI_SME_DFS_RADAR_FOUND message",
__func__);
return QDF_STATUS_E_FAILURE;
}
sessionId = dfs_event->sessionId;
roamInfo.dfs_event.sessionId = sessionId;
roamInfo.dfs_event.chan_list.nchannels =
dfs_event->chan_list.nchannels;
for (i = 0; i < dfs_event->chan_list.nchannels; i++) {
roamInfo.dfs_event.chan_list.channels[i] =
dfs_event->chan_list.channels[i];
}
roamInfo.dfs_event.dfs_radar_status =
dfs_event->dfs_radar_status;
roamInfo.dfs_event.use_nol = dfs_event->use_nol;
roamStatus = eCSR_ROAM_DFS_RADAR_IND;
roamResult = eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
"sapdfs: Radar indication event occurred");
break;
}
case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND:
{
csaIeTxCompleteRsp =
(tSirSmeCSAIeTxCompleteRsp *) pMsgBuf;
if (NULL == csaIeTxCompleteRsp) {
sms_log(pMac, LOGE,
"%s: pMsg is NULL for eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND",
__func__);
return QDF_STATUS_E_FAILURE;
}
sessionId = csaIeTxCompleteRsp->sessionId;
roamStatus = eCSR_ROAM_DFS_CHAN_SW_NOTIFY;
roamResult = eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
"sapdfs: Received eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND for session id [%d]",
sessionId);
break;
}
default:
{
sms_log(pMac, LOG1, "%s: Invalid DFS message = 0x%x",
__func__, msgType);
status = QDF_STATUS_E_FAILURE;
return status;
}
}
/* Indicate Radar Event to SAP */
csr_roam_call_callback(pMac, sessionId, &roamInfo, 0,
roamStatus, roamResult);
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;
tCsrRoamInfo roamInfo = {0};
eRoamCmdStatus roam_status;
eCsrRoamResult roam_result;
ext_chan_ind = msg_buf;
if (NULL == ext_chan_ind) {
sms_log(mac_ctx, LOGE,
FL("pMsg is NULL for eWNI_SME_EXT_CHANGE_CHANNEL_IND"));
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;
sms_log(mac_ctx, LOG1,
FL("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;
}
/**
* sme_process_fw_mem_dump_rsp - process fw memory dump response from WMA
*
* @mac_ctx: pointer to MAC handle.
* @msg: pointer to received SME msg.
*
* This function process the received SME message and calls the corresponding
* callback which was already registered with SME.
*
* Return: None
*/
#ifdef WLAN_FEATURE_MEMDUMP
static void sme_process_fw_mem_dump_rsp(tpAniSirGlobal mac_ctx, cds_msg_t *msg)
{
if (msg->bodyptr) {
if (mac_ctx->sme.fw_dump_callback)
mac_ctx->sme.fw_dump_callback(mac_ctx->hHdd,
(struct fw_dump_rsp *) msg->bodyptr);
qdf_mem_free(msg->bodyptr);
}
}
#else
static void sme_process_fw_mem_dump_rsp(tpAniSirGlobal mac_ctx, cds_msg_t *msg)
{
}
#endif
#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);
if (pMac->roam.configParam.isEseIniFeatureEnabled ==
isEseIniFeatureEnabled) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"%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_INFO,
"%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)
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_ESE_INI_CFG_CHANGED);
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] = { 0 };
uint8_t count, valid_count = 0;
cds_msg_t msg;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, pPlmReq->sessionId);
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
if (!pSession) {
sms_log(pMac, LOGE, FL("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 == cds_get_channel_state(
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_INFO,
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_INFO,
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(cds_mq_post_message(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
* @hHal: HAL handle
* @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(tHalHandle hHal, tSirSmeTsmIEInd *pSmeTsmIeInd)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
tCsrRoamInfo pRoamInfo = { 0 };
uint32_t SessionId = pSmeTsmIeInd->sessionId;
pRoamInfo.tsmIe.tsid = pSmeTsmIeInd->tsmIe.tsid;
pRoamInfo.tsmIe.state = pSmeTsmIeInd->tsmIe.state;
pRoamInfo.tsmIe.msmt_interval = pSmeTsmIeInd->tsmIe.msmt_interval;
/* forward the tsm ie information to HDD */
csr_roam_call_callback(pMac,
SessionId, &pRoamInfo, 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 = eSIR_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tpSirBeaconReportReqInd pSmeBcnReportReq = NULL;
tCsrEseBeaconReqParams *pBeaconReq = NULL;
uint8_t counter = 0;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
if (pSmeRrmContext->eseBcnReqInProgress == true) {
sms_log(pMac, LOGE,
"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) {
sms_log(pMac, LOGP,
"Memory Allocation Failure!!! ESE BcnReq Ind to SME");
return QDF_STATUS_E_NOMEM;
}
pSmeRrmContext->eseBcnReqInProgress = true;
sms_log(pMac, LOGE, "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
* @p_cds_context: CDS context
* @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, void *p_cds_context, 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,
p_cds_context, 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)) {
if (pMac->roam.configParam.isRoamOffloadScanEnabled)
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_CHANNEL_LIST_CHANGED);
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);
}
sme_release_global_lock(&pMac->sme);
if (pMac->roam.configParam.isRoamOffloadScanEnabled)
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_CHANNEL_LIST_CHANGED);
return status;
}
#endif /* FEATURE_WLAN_ESE */
static
QDF_STATUS sme_ibss_peer_info_response_handler(tHalHandle hHal,
tpSirIbssGetPeerInfoRspParams
pIbssPeerInfoParams)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
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) {
sms_log(mac, LOGE, FL("Dual mac config resp param is NULL"));
/* Not returning. Need to check if active command list
* needs to be freed
*/
}
entry = csr_ll_peek_head(&mac->sme.smeCmdActiveList,
LL_ACCESS_LOCK);
if (!entry) {
sms_log(mac, LOGE, FL("No cmd found in active list"));
return QDF_STATUS_E_FAILURE;
}
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
if (!command) {
sms_log(mac, LOGE, FL("Base address is NULL"));
return QDF_STATUS_E_FAILURE;
}
if (e_sme_command_set_dual_mac_config != command->command) {
sms_log(mac, LOGE, FL("Command mismatch!"));
return QDF_STATUS_E_FAILURE;
}
callback = command->u.set_dual_mac_cmd.set_dual_mac_cb;
if (callback) {
if (!param) {
sms_log(mac, LOGE,
FL("Callback failed-Dual mac config is NULL"));
} else {
sms_log(mac, LOG1,
FL("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 {
sms_log(mac, LOGE, FL("Callback does not exist"));
}
found = csr_ll_remove_entry(&mac->sme.smeCmdActiveList, entry,
LL_ACCESS_LOCK);
if (found)
/* Now put this command back on the available command list */
sme_release_command(mac, command);
sme_process_pending_queue(mac);
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;
antenna_mode_cb callback;
struct sir_antenna_mode_resp *param;
param = (struct sir_antenna_mode_resp *)msg;
if (!param) {
sms_log(mac, LOGE, FL("set antenna mode resp is NULL"));
/* Not returning. Need to check if active command list
* needs to be freed
*/
}
entry = csr_ll_peek_head(&mac->sme.smeCmdActiveList,
LL_ACCESS_LOCK);
if (!entry) {
sms_log(mac, LOGE, FL("No cmd found in active list"));
return QDF_STATUS_E_FAILURE;
}
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
if (!command) {
sms_log(mac, LOGE, FL("Base address is NULL"));
return QDF_STATUS_E_FAILURE;
}
if (e_sme_command_set_antenna_mode != command->command) {
sms_log(mac, LOGE, FL("Command mismatch!"));
return QDF_STATUS_E_FAILURE;
}
callback =
command->u.set_antenna_mode_cmd.set_antenna_mode_resp;
if (callback) {
if (!param) {
sms_log(mac, LOGE,
FL("Set antenna mode call back is NULL"));
} else {
sms_log(mac, LOG1,
FL("HDD callback for set antenna mode"));
callback(param->status);
}
} else {
sms_log(mac, LOGE, FL("Callback does not exist"));
}
found = csr_ll_remove_entry(&mac->sme.smeCmdActiveList, entry,
LL_ACCESS_LOCK);
if (found)
/* Now put this command back on the available command list */
sme_release_command(mac, command);
sme_process_pending_queue(mac);
return QDF_STATUS_SUCCESS;
}
/*--------------------------------------------------------------------------
\brief sme_process_msg() - The main message processor for SME.
The function is called by a message dispatcher when to process a message
targeted for SME.
This is a synchronous call
\param hHal - The handle returned by mac_open.
\param pMsg - A pointer to a caller allocated object of tSirMsgQ.
\return QDF_STATUS_SUCCESS - SME successfully process the message.
Other status means SME failed to process the message to HAL.
\sa
--------------------------------------------------------------------------*/
QDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (pMsg == NULL) {
sms_log(pMac, LOGE, "Empty message for SME");
return status;
}
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGW, FL("Locking failed, bailing out"));
if (pMsg->bodyptr)
qdf_mem_free(pMsg->bodyptr);
return status;
}
if (!SME_IS_START(pMac)) {
sms_log(pMac, LOGW, FL("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 {
sms_log(pMac, LOGE, FL("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 {
sms_log(pMac, LOGE, FL("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 {
sms_log(pMac, LOGE, FL("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 {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
case eWNI_SME_REMAIN_ON_CHN_RSP:
if (pMsg->bodyptr) {
status = sme_remain_on_chn_rsp(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
case eWNI_SME_REMAIN_ON_CHN_RDY_IND:
if (pMsg->bodyptr) {
status = sme_remain_on_chn_ready(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
#ifdef FEATURE_WLAN_SCAN_PNO
case eWNI_SME_PREF_NETWORK_FOUND_IND:
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_WMA_MSG,
NO_SESSION, pMsg->type));
if (pMsg->bodyptr) {
status = sme_preferred_network_found_ind((void *)pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
#endif /* FEATURE_WLAN_SCAN_PNO */
case eWNI_SME_CHANGE_COUNTRY_CODE:
if (pMsg->bodyptr) {
status = sme_handle_change_country_code((void *)pMac,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("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 {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
case eWNI_SME_SCAN_CMD:
if (pMsg->bodyptr) {
status = sme_handle_scan_req(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
case eWNI_SME_ROC_CMD:
if (pMsg->bodyptr) {
status = sme_handle_roc_req(hHal, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
#ifdef FEATURE_WLAN_TDLS
/*
* command rescived from PE, SME tdls msg processor shall be called
* to process commands recieved from PE
*/
case eWNI_SME_TDLS_SEND_MGMT_RSP:
case eWNI_SME_TDLS_ADD_STA_RSP:
case eWNI_SME_TDLS_DEL_STA_RSP:
case eWNI_SME_TDLS_DEL_STA_IND:
case eWNI_SME_TDLS_DEL_ALL_PEER_IND:
case eWNI_SME_MGMT_FRM_TX_COMPLETION_IND:
case eWNI_SME_TDLS_LINK_ESTABLISH_RSP:
case eWNI_SME_TDLS_SHOULD_DISCOVER:
case eWNI_SME_TDLS_SHOULD_TEARDOWN:
case eWNI_SME_TDLS_PEER_DISCONNECTED:
if (pMsg->bodyptr) {
status = tdls_msg_processor(pMac, pMsg->type,
pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
#endif
#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 {
sms_log(pMac, LOGE, FL("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 {
sms_log(pMac, LOGE, FL("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;
#ifdef WLAN_FEATURE_GTK_OFFLOAD
case eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP:
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_WMA_MSG,
NO_SESSION, pMsg->type));
if (pMsg->bodyptr) {
sme_process_get_gtk_info_rsp(pMac, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
#endif
#ifdef FEATURE_WLAN_LPHB
/* LPHB timeout indication arrived, send IND to client */
case eWNI_SME_LPHB_IND:
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_WMA_MSG,
NO_SESSION, pMsg->type));
if (pMac->sme.pLphbIndCb)
pMac->sme.pLphbIndCb(pMac->hHdd, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
break;
#endif /* FEATURE_WLAN_LPHB */
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 {
sms_log(pMac, LOGE, FL("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 {
sms_log(pMac, LOGE, FL("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 {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
#endif
#ifdef FEATURE_WLAN_CH_AVOID
/* channel avoid message arrived, send IND to client */
case eWNI_SME_CH_AVOID_IND:
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_RX_WMA_MSG,
NO_SESSION, pMsg->type));
if (pMac->sme.pChAvoidNotificationCb) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("CH avoid notification"));
pMac->sme.pChAvoidNotificationCb(pMac->hHdd,
pMsg->bodyptr);
}
qdf_mem_free(pMsg->bodyptr);
break;
#endif /* FEATURE_WLAN_CH_AVOID */
#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
case eWNI_SME_AUTO_SHUTDOWN_IND:
if (pMac->sme.pAutoShutdownNotificationCb) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("Auto shutdown notification"));
pMac->sme.pAutoShutdownNotificationCb();
}
qdf_mem_free(pMsg->bodyptr);
break;
#endif
case eWNI_SME_DFS_RADAR_FOUND:
case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND:
status = dfs_msg_processor(pMac, pMsg->type, pMsg->bodyptr);
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 {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
#ifdef WLAN_FEATURE_STATS_EXT
case eWNI_SME_STATS_EXT_EVENT:
if (pMsg->bodyptr) {
status = sme_stats_ext_event(hHal, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
#endif
case eWNI_SME_LINK_SPEED_IND:
if (pMac->sme.pLinkSpeedIndCb)
pMac->sme.pLinkSpeedIndCb(pMsg->bodyptr,
pMac->sme.pLinkSpeedCbContext);
if (pMsg->bodyptr)
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(hHal, 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.linkStatusCallback) {
pMac->sme.linkStatusCallback(
pLinkStatus->linkStatus,
pMac->sme.linkStatusContext);
}
pMac->sme.linkStatusCallback = NULL;
pMac->sme.linkStatusContext = 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.pExtScanIndCb)
pMac->sme.pExtScanIndCb(pMac->hHdd,
eSIR_EXTSCAN_FULL_SCAN_RESULT_IND,
pMsg->bodyptr);
else
sms_log(pMac, LOGE,
FL("callback not registered to process %d"),
pMsg->type);
qdf_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_EPNO_NETWORK_FOUND_IND:
if (pMac->sme.pExtScanIndCb)
pMac->sme.pExtScanIndCb(pMac->hHdd,
eSIR_EPNO_NETWORK_FOUND_IND,
pMsg->bodyptr);
else
sms_log(pMac, LOGE,
FL("callback not registered to process %d"),
pMsg->type);
qdf_mem_free(pMsg->bodyptr);
break;
#endif
case eWNI_SME_FW_DUMP_IND:
sme_process_fw_mem_dump_rsp(pMac, pMsg);
break;
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 {
sms_log(pMac, LOGE, FL("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 {
sms_log(pMac, LOGE, FL("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 {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
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 {
sms_log(pMac, LOGE, FL(
"Message error. The callback is NULL."));
}
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 {
sms_log(pMac, LOGE, FL(
"Message error. The callback is NULL."));
}
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 {
sms_log(pMac, LOGE, FL(
"Message error. The callback is NULL."));
}
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 {
sms_log(pMac, LOGE, FL(
"Message error. The callback is NULL."));
}
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 {
sms_log(pMac, LOGE, FL(
"Message error. The callback is NULL."));
}
qdf_mem_free(pMsg->bodyptr);
break;
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 {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
case eWNI_SME_SET_THERMAL_LEVEL_IND:
if (pMac->sme.set_thermal_level_cb)
pMac->sme.set_thermal_level_cb(pMac->hHdd,
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 {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
break;
case eWNI_SME_NDP_CONFIRM_IND:
case eWNI_SME_NDP_NEW_PEER_IND:
case eWNI_SME_NDP_INITIATOR_RSP:
case eWNI_SME_NDP_INDICATION:
case eWNI_SME_NDP_RESPONDER_RSP:
case eWNI_SME_NDP_END_RSP:
case eWNI_SME_NDP_END_IND:
case eWNI_SME_NDP_PEER_DEPARTED_IND:
sme_ndp_msg_processor(pMac, pMsg);
break;
case eWNI_SME_LOST_LINK_INFO_IND:
if (pMac->sme.lost_link_info_cb)
pMac->sme.lost_link_info_cb(pMac->hHdd,
(struct sir_lost_link_info *)pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
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(hHal, pMsg->bodyptr);
qdf_mem_free(pMsg->bodyptr);
} else {
sms_log(pMac, LOGE, FL("Empty message for %d"),
pMsg->type);
}
} else {
sms_log(pMac, LOGW, FL("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;
}
#ifdef NAPIER_CODE
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((tHalHandle)mac_ctx, (cds_msg_t *)msg);
}
#endif
/**
* 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
*/
QDF_STATUS sme_process_nss_update_resp(tpAniSirGlobal mac, uint8_t *msg)
{
tListElem *entry = NULL;
tSmeCmd *command = NULL;
bool found;
nss_update_cb callback = NULL;
struct sir_beacon_tx_complete_rsp *param;
param = (struct sir_beacon_tx_complete_rsp *)msg;
if (!param) {
sms_log(mac, LOGE, FL("nss update resp param is NULL"));
/* Not returning. Need to check if active command list
* needs to be freed
*/
}
entry = csr_ll_peek_head(&mac->sme.smeCmdActiveList,
LL_ACCESS_LOCK);
if (!entry) {
sms_log(mac, LOGE, FL("No cmd found in active list"));
return QDF_STATUS_E_FAILURE;
}
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
if (!command) {
sms_log(mac, LOGE, FL("Base address is NULL"));
return QDF_STATUS_E_FAILURE;
}
if (e_sme_command_nss_update != command->command) {
sms_log(mac, LOGE, FL("Command mismatch!"));
return QDF_STATUS_E_FAILURE;
}
callback = command->u.nss_update_cmd.nss_update_cb;
if (callback) {
if (!param) {
sms_log(mac, LOGE,
FL("Callback failed since nss update params is NULL"));
} else {
sms_log(mac, LOGE,
FL("Calling HDD callback for nss update response"));
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 {
sms_log(mac, LOGE, FL("Callback does not exisit"));
}
found = csr_ll_remove_entry(&mac->sme.smeCmdActiveList, entry,
LL_ACCESS_LOCK);
if (found) {
/* Now put this command back on the avilable command list */
sme_release_command(mac, command);
}
sme_process_pending_queue(mac);
return QDF_STATUS_SUCCESS;
}
/* No need to hold the global lock here because this function can only be called */
/* after sme_stop. */
void sme_free_msg(tHalHandle hHal, cds_msg_t *pMsg)
{
if (pMsg) {
if (pMsg->bodyptr) {
qdf_mem_free(pMsg->bodyptr);
}
}
}
/*--------------------------------------------------------------------------
\brief sme_stop() - Stop all SME modules and put them at idle state
The function stops each module in SME, PMC, CSR, etc. . Upon
return, all modules are at idle state ready to start.
This is a synchronous call
\param hHal - The handle returned by mac_open
\param tHalStopType - reason for stopping
\return QDF_STATUS_SUCCESS - SME is stopped.
Other status means SME is failed to stop but caller should still
consider SME is stopped.
\sa
--------------------------------------------------------------------------*/
QDF_STATUS sme_stop(tHalHandle hHal, tHalStopType stopType)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
QDF_STATUS fail_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
p2p_stop(hHal);
status = csr_stop(pMac, stopType);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
"csr_stop failed during smeStop with status=%d", status);
fail_status = status;
}
purge_sme_cmd_list(pMac);
if (!QDF_IS_STATUS_SUCCESS(fail_status)) {
status = fail_status;
}
pMac->sme.state = SME_STATE_STOP;
return status;
}
/*--------------------------------------------------------------------------
\brief 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
\param 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.
\sa
--------------------------------------------------------------------------*/
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)) {
sms_log(pMac, LOGE,
"csr_close failed during sme close with status=%d",
status);
fail_status = status;
}
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
status = sme_qos_close(pMac);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
"Qos close failed during sme close with status=%d",
status);
fail_status = status;
}
#endif
status = sme_ps_close(hHal);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
"sme_ps_close failed during smeClose status=%d",
status);
fail_status = status;
}
status = rrm_close(hHal);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
"RRM close failed during sme close with status=%d",
status);
fail_status = status;
}
sme_p2p_close(hHal);
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_request() - wrapper function to Request a 11d or full scan from CSR.
* @hal: hal global context
* @session_id: session id
* @scan_req: scan req
* @callback: a callback function that scan calls upon finish, will not
* be called if csr_scan_request returns error
* @ctx: a pointer passed in for the callback
*
* This is a wrapper function to Request a 11d or full scan from CSR. This is
* an asynchronous call
*
* Return: Status of operation
*/
QDF_STATUS sme_scan_request(tHalHandle hal, uint8_t session_id,
tCsrScanRequest *scan_req,
csr_scan_completeCallback callback, void *ctx)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct ani_scan_req *scan_msg;
cds_msg_t msg;
uint32_t scan_req_id, scan_count;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SCAN_REQ, session_id,
scan_req->scanType));
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sms_log(mac_ctx, LOGE, FL("Invalid session id:%d"),
session_id);
return status;
}
if (!mac_ctx->scan.fScanEnable) {
sms_log(mac_ctx, LOGE, FL("fScanEnable false"));
return status;
}
scan_count = csr_ll_count(&mac_ctx->sme.smeScanCmdActiveList);
if (scan_count >= mac_ctx->scan.max_scan_count) {
sms_log(mac_ctx, LOGE, FL("Max scan reached"));
return QDF_STATUS_E_FAILURE;
}
wma_get_scan_id(&scan_req_id);
scan_req->scan_id = scan_req_id;
status = sme_acquire_global_lock(&mac_ctx->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac_ctx, LOGE, FL("Unable to acquire lock"));
return status;
}
sms_log(mac_ctx, LOG1, FL(" called"));
scan_msg = qdf_mem_malloc(sizeof(struct ani_scan_req));
if (NULL == scan_msg) {
sms_log(mac_ctx, LOGE,
" scan_req: failed to allocate mem for msg");
sme_release_global_lock(&mac_ctx->sme);
return QDF_STATUS_E_NOMEM;
}
scan_msg->msg_type = eWNI_SME_SCAN_CMD;
scan_msg->msg_len = (uint16_t) sizeof(struct ani_scan_req);
scan_msg->session_id = session_id;
scan_msg->callback = callback;
scan_msg->ctx = ctx;
scan_msg->scan_param = qdf_mem_malloc(sizeof(tCsrScanRequest));
if (NULL == scan_msg->scan_param) {
sms_log(mac_ctx, LOGE,
"scan_req:failed to allocate mem for scanreq");
sme_release_global_lock(&mac_ctx->sme);
qdf_mem_free(scan_msg);
return QDF_STATUS_E_NOMEM;
}
csr_scan_copy_request(mac_ctx, scan_msg->scan_param, scan_req);
msg.type = eWNI_SME_SCAN_CMD;
msg.bodyptr = scan_msg;
msg.reserved = 0;
msg.bodyval = 0;
if (QDF_STATUS_SUCCESS !=
cds_mq_post_message(CDS_MQ_ID_SME, &msg)) {
sms_log(mac_ctx, LOGE,
" sme_scan_req failed to post msg");
csr_scan_free_request(mac_ctx, scan_msg->scan_param);
qdf_mem_free(scan_msg->scan_param);
qdf_mem_free(scan_msg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac_ctx->sme);
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_scan_get_result
\brief a wrapper function to request scan results from CSR.
This is a synchronous call
\param pFilter - If pFilter is NULL, all cached results are returned
\param 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));
sms_log(pMac, LOG2, FL("enter"));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_scan_get_result(hHal, pFilter, phResult);
sme_release_global_lock(&pMac->sme);
}
sms_log(pMac, LOG2, FL("exit status %d"), status);
return status;
}
/**
* 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(tHalHandle hal_handle,
tCsrRoamProfile *profile,
tScanResultHandle *scan_cache,
uint8_t *ap_chnl_id)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
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;
} else {
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(hal_handle, 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_ERROR,
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 {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("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,
tCsrRoamProfile *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;
}
/* ---------------------------------------------------------------------------
\fn sme_scan_flush_result
\brief 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(hHal);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_filter_scan_results
\brief a wrapper function to request CSR to clear scan results.
This is a synchronous call
\param tHalHandle - HAL context handle
\param 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(hHal, true);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_scan_result_get_first
\brief a wrapper function to request CSR to returns the first element of
scan result.
This is a synchronous call
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_scan_result_get_next
\brief 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
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_scan_result_purge
\brief 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
\param 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(tHalHandle hHal, tScanResultHandle hScanResult)
{
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_RESULT_PURGE,
NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_scan_result_purge(hHal, hScanResult);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_scan_get_pmkid_candidate_list
\brief a wrapper function to return the PMKID candidate list
This is a synchronous call
\param pPmkidList - caller allocated buffer point to an array of
tPmkidCandidateInfo
\param pNumItems - pointer to a variable that has the number of
tPmkidCandidateInfo allocated when retruning, this is
either the number needed or number of items put into
pPmkidList
\return QDF_STATUS - when fail, it usually means the buffer allocated is not
big enough and pNumItems
has the number of tPmkidCandidateInfo.
\Note: pNumItems is a number of tPmkidCandidateInfo,
not sizeof(tPmkidCandidateInfo) * something
---------------------------------------------------------------------------*/
QDF_STATUS sme_scan_get_pmkid_candidate_list(tHalHandle hHal, uint8_t sessionId,
tPmkidCandidateInfo *pPmkidList,
uint32_t *pNumItems)
{
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_scan_get_pmkid_candidate_list(pMac, sessionId,
pPmkidList,
pNumItems);
sme_release_global_lock(&pMac->sme);
}
return status;
}
eCsrPhyMode sme_get_phy_mode(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.phyMode;
}
/* ---------------------------------------------------------------------------
\fn sme_get_channel_bonding_mode5_g
\brief get the channel bonding mode for 5G band
\param hHal - HAL handle
\return channel bonding mode for 5G
---------------------------------------------------------------------------*/
uint32_t sme_get_channel_bonding_mode5_g(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSmeConfigParams smeConfig;
sme_get_config_param(pMac, &smeConfig);
return smeConfig.csrConfig.channelBondingMode5GHz;
}
/* ---------------------------------------------------------------------------
\fn sme_get_channel_bonding_mode24_g
\brief get the channel bonding mode for 2.4G band
\param hHal - HAL handle
\return channel bonding mode for 2.4G
---------------------------------------------------------------------------*/
uint32_t sme_get_channel_bonding_mode24_g(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tSmeConfigParams smeConfig;
sme_get_config_param(pMac, &smeConfig);
return smeConfig.csrConfig.channelBondingMode24GHz;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_connect
\brief a wrapper function to request CSR to inititiate an association
This is an asynchronous call.
\param sessionId - the sessionId returned by sme_open_session.
\param pProfile - description of the network to which to connect
\param hBssListIn - a list of BSS descriptor to roam to. It is returned
from csr_scan_get_result
\param pRoamId - to get back the request ID
\return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_roam_connect(tHalHandle hHal, uint8_t sessionId,
tCsrRoamProfile *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));
sms_log(pMac, LOG2, FL("enter"));
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 {
sms_log(pMac, LOGE, FL("invalid sessionID %d"),
sessionId);
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->sme);
} else {
sms_log(pMac, LOGE, FL("sme_acquire_global_lock failed"));
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_set_phy_mode
\brief Changes the PhyMode.
\param hHal - The handle returned by mac_open.
\param 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);
if (NULL == pMac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: invalid context", __func__);
return QDF_STATUS_E_FAILURE;
}
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;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_reassoc
\brief a wrapper function to request CSR to inititiate a re-association
\param pProfile - can be NULL to join the currently connected AP. In that
case modProfileFields should carry the modified field(s) which could trigger
reassoc
\param modProfileFields - fields which are part of tCsrRoamConnectedProfile
that might need modification dynamically once STA is up & running and this
could trigger a reassoc
\param pRoamId - to get back the request ID
\return QDF_STATUS
-------------------------------------------------------------------------------*/
QDF_STATUS sme_roam_reassoc(tHalHandle hHal, uint8_t sessionId,
tCsrRoamProfile *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));
sms_log(pMac, LOG2, FL("enter"));
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;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_connect_to_last_profile
\brief 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;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_disconnect
\brief a wrapper function to request CSR to disconnect from a network
This is an asynchronous call.
\param reason -- To indicate the reason for disconnecting. Currently, only
eCSR_DISCONNECT_REASON_MIC_ERROR is meanful.
\return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_roam_disconnect(tHalHandle hHal, uint8_t sessionId,
eCsrRoamDisconnectReason reason)
{
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_DISCONNECT, sessionId,
reason));
sms_log(pMac, LOG2, FL("enter"));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (CSR_IS_SESSION_VALID(pMac, sessionId)) {
status = csr_roam_disconnect(pMac, sessionId, reason);
} else {
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->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);
tCsrRoamSession *session;
if (!mac_ctx)
return;
session = CSR_GET_SESSION(mac_ctx, session_id);
if (!session) {
sms_log(mac_ctx, LOGE,
FL("session %d not found"), session_id);
return;
}
session->dhcp_done = true;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_stop_bss
\brief To stop BSS for Soft AP. This is an asynchronous API.
\param hHal - Global structure
\param 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);
sms_log(pMac, LOG2, FL("enter"));
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, true);
} 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 tagCsrDelStaParams *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 tagCsrDelStaParams *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;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_tkip_counter_measures
\brief To start or stop TKIP counter measures. This is an asynchronous API.
\param sessionId - sessionId of SoftAP
\param pPeerMacAddr - Caller allocated memory filled with peer MAC address (6 bytes)
\return QDF_STATUS
-------------------------------------------------------------------------------*/
QDF_STATUS sme_roam_tkip_counter_measures(tHalHandle hHal, uint8_t sessionId,
bool bEnable)
{
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_tkip_counter_measures(pMac, sessionId,
bEnable);
} else {
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_get_associated_stas
\brief To probe the list of associated stations from various modules
of CORE stack.
\This is an asynchronous API.
\param sessionId - sessionId of SoftAP
\param 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.
\param pUsrContext - Opaque HDD context
\param pfnSapEventCallback - Sap event callback in HDD
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_get_wps_session_overlap
\brief To get the WPS PBC session overlap information.
\This is an asynchronous API.
\param sessionId - sessionId of SoftAP
\param pUsrContext - Opaque HDD context
\param pfnSapEventCallback - Sap event callback in HDD
\pRemoveMac - pointer to Mac address which needs to be removed from session
\return QDF_STATUS
-------------------------------------------------------------------------------*/
QDF_STATUS sme_roam_get_wps_session_overlap(tHalHandle hHal, uint8_t sessionId,
void *pUsrContext, void
*pfnSapEventCallback,
struct qdf_mac_addr pRemoveMac)
{
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_wps_session_overlap(pMac, sessionId,
pUsrContext,
pfnSapEventCallback,
pRemoveMac);
} else {
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_get_connect_state
\brief 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;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_get_connect_profile
\brief 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.
\param pProfile - pointer to a caller allocated structure
tCsrRoamConnectedProfile
\return 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);
}
/* ---------------------------------------------------------------------------
\fn sme_roam_set_pmkid_cache
\brief a wrapper function to request CSR to return the PMKID candidate list
This is a synchronous call.
\param pPMKIDCache - caller allocated buffer point to an array of
tPmkidCacheInfo
\param 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
\param 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,
const uint8_t *pBSSId, 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,
pBSSId, flush_cache);
} else {
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
#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
/* ---------------------------------------------------------------------------
\fn sme_roam_get_security_req_ie
\brief a wrapper function to request CSR to return the WPA or RSN or WAPI IE CSR
passes to PE to JOIN request or START_BSS request
This is a synchronous call.
\param pLen - caller allocated memory that has the length of pBuf as input.
Upon returned, *pLen has the needed or IE length in pBuf.
\param pBuf - Caller allocated memory that contain the IE field, if any,
upon return
\param secType - Specifies whether looking for WPA/WPA2/WAPI IE
\return QDF_STATUS - when fail, it usually means the buffer allocated is not
big enough
---------------------------------------------------------------------------*/
QDF_STATUS sme_roam_get_security_req_ie(tHalHandle hHal, uint8_t sessionId,
uint32_t *pLen, uint8_t *pBuf,
eCsrSecurityType secType)
{
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_wpa_rsn_req_ie(hHal, sessionId, pLen, pBuf);
} else {
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_get_security_rsp_ie
\brief a wrapper function to request CSR to return the WPA or RSN or
WAPI IE from the beacon or probe rsp if connected
This is a synchronous call.
\param pLen - caller allocated memory that has the length of pBuf as input.
Upon returned, *pLen has the needed or IE length in pBuf.
\param pBuf - Caller allocated memory that contain the IE field, if any,
upon return
\param secType - Specifies whether looking for WPA/WPA2/WAPI IE
\return QDF_STATUS - when fail, it usually means the buffer allocated is not
big enough
---------------------------------------------------------------------------*/
QDF_STATUS sme_roam_get_security_rsp_ie(tHalHandle hHal, uint8_t sessionId,
uint32_t *pLen, uint8_t *pBuf,
eCsrSecurityType secType)
{
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_wpa_rsn_rsp_ie(pMac, sessionId, pLen, pBuf);
} else {
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_get_num_pmkid_cache
\brief 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;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_get_pmkid_cache
\brief a wrapper function to request CSR to return PMKID cache from CSR
This is a synchronous call.
\param 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.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_config_param
\brief a wrapper function that HDD calls to get the global settings
currently maintained by CSR.
This is a synchronous call.
\param 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) {
sms_log(pMac, LOGE, "%s csr_get_config_param failed",
__func__);
sme_release_global_lock(&pMac->sme);
return status;
}
qdf_mem_copy(&pParam->rrmConfig,
&pMac->rrm.rrmSmeContext.rrmConfig,
sizeof(pMac->rrm.rrmSmeContext.rrmConfig));
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 (eSIR_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 (eSIR_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 (eSIR_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 (eSIR_SUCCESS != wlan_cfg_get_str(pmac, cfg_id, str, length))
status = QDF_STATUS_E_INVAL;
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_get_modify_profile_fields
\brief 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.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_dhcp_till_power_active_flag
\brief Sets/Clears DHCP related flag to disable/enable auto PS
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_register11d_scan_done_callback
\brief Register a routine of type csr_scan_completeCallback which is
called whenever an 11d scan is done
\param hHal - The handle returned by mac_open.
\param callback - 11d scan complete routine to be registered
\return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_register11d_scan_done_callback(tHalHandle hHal,
csr_scan_completeCallback callback)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pMac->scan.callback11dScanDone = callback;
return status;
}
/**
* sme_deregister11d_scan_done_callback() - De-register scandone callback
* @h_hal: Handler return by mac_open
*
* This function De-registers the scandone callback to SME
*
* Return: None
*/
void sme_deregister11d_scan_done_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->scan.callback11dScanDone = NULL;
}
#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;
}
#endif
/**
* 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;
}
/**
* sme_register_ftm_msg_processor() - registers hdd ftm message processor
* function to MAC/SYS
*
* @hal: hal handle
* @callback: hdd function that has to be registered
*
* Return: void
*/
void sme_register_ftm_msg_processor(tHalHandle hal,
hdd_ftm_msg_processor callback)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
if (mac_ctx == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("mac ctx is NULL"));
return;
}
mac_ctx->ftm_msg_processor_callback = callback;
return;
}
/**
* sme_wow_add_pattern() - add a wow pattern in fw
* @hHal: handle returned by mac_open
* @pattern: pointer to input pattern
*
* Add a pattern for Pattern Byte Matching in WoW mode. Firmware will
* do a pattern match on these patterns when WoW is enabled during system
* suspend.
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_wow_add_pattern(tHalHandle hal,
struct wow_add_pattern *pattern,
uint8_t session_id)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hal);
struct wow_add_pattern *ptrn;
tSirRetStatus ret_code = eSIR_SUCCESS;
tSirMsgQ msg_q;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_WOWL_ADDBCAST_PATTERN, session_id,
0));
ptrn = qdf_mem_malloc(sizeof(*ptrn));
if (NULL == ptrn) {
sms_log(pMac, LOGP,
FL("Fail to allocate memory for WoWLAN Add Bcast Pattern "));
return QDF_STATUS_E_NOMEM;
}
(void)qdf_mem_copy(ptrn, pattern, sizeof(*ptrn));
msg_q.type = WMA_WOW_ADD_PTRN;
msg_q.reserved = 0;
msg_q.bodyptr = ptrn;
msg_q.bodyval = 0;
sms_log(pMac, LOG1, FL("Sending WMA_WOWL_ADD_BCAST_PTRN to HAL"));
ret_code = wma_post_ctrl_msg(pMac, &msg_q);
if (eSIR_SUCCESS != ret_code) {
sms_log(pMac, LOGE,
FL("Posting WMA_WOWL_ADD_BCAST_PTRN failed, reason=%X"),
ret_code);
}
return ret_code;
}
/**
* sme_wow_delete_pattern() - delete user configured wow pattern in target
* @hHal: handle returned by mac_open.
* @pattern: pointer to delete pattern parameter
* @sessionId: session id
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_wow_delete_pattern(tHalHandle hal,
struct wow_delete_pattern *pattern, uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hal);
struct wow_delete_pattern *delete_ptrn;
tSirRetStatus ret_code = eSIR_SUCCESS;
tSirMsgQ msg_q;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_WOWL_DELBCAST_PATTERN, sessionId,
0));
delete_ptrn = qdf_mem_malloc(sizeof(*delete_ptrn));
if (NULL == delete_ptrn) {
sms_log(pMac, LOGP,
FL("Fail to allocate memory for WoWLAN Delete Bcast Pattern "));
return QDF_STATUS_E_NOMEM;
}
(void)qdf_mem_copy(delete_ptrn, pattern, sizeof(*delete_ptrn));
msg_q.type = WMA_WOW_DEL_PTRN;
msg_q.reserved = 0;
msg_q.bodyptr = delete_ptrn;
msg_q.bodyval = 0;
sms_log(pMac, LOG1, FL("Sending WMA_WOWL_DEL_BCAST_PTRN"));
ret_code = wma_post_ctrl_msg(pMac, &msg_q);
if (eSIR_SUCCESS != ret_code) {
sms_log(pMac, LOGE,
FL("Posting WMA_WOWL_DEL_BCAST_PTRN failed, reason=%X"),
ret_code);
}
return ret_code;
}
/**
* sme_enter_wowl(): SME API exposed to HDD to request enabling of WOWL mode.
* @hal_ctx - The handle returned by mac_open.
* @enter_wowl_callback_routine - Callback routine provided by HDD.
* Used for success/failure notification by SME
* @enter_wowl_callback_context - A cookie passed by HDD, that is passed
* back to HDD at the time of callback.
* @wake_reason_ind_cb - Callback routine provided by HDD.
* Used for Wake Reason Indication by SME
* @wake_reason_ind_cb_ctx - A cookie passed by HDD, that is passed
* back to HDD at the time of callback.
*
* WoWLAN works on top of BMPS mode.
* If the device is not in BMPS mode,
* SME will will cache the information that
* WOWL has been enabled and attempt to put the device
* in BMPS. On entry into BMPS, SME will enable the
* WOWL mode.
* Note 1: If we exit BMPS mode (someone requests full power),
* we will NOT resume WOWL when we go back to BMPS again.
* Request for full power (while in WOWL mode) means disable
* WOWL and go to full power.
* Note 2: Both UAPSD and WOWL work on top of BMPS.
* On entry into BMPS, SME will give priority to UAPSD and
* enable only UAPSD if both UAPSD and WOWL are required.
* Currently there is no requirement or use case to support
* UAPSD and WOWL at the same time.
*
* Return: QDF_STATUS
* QDF_STATUS_SUCCESS Device is already in WoWLAN mode
* QDF_STATUS_E_FAILURE Device cannot enter WoWLAN mode.
* QDF_STATUS_PMC_PENDING Request accepted. SME will enable
* WOWL after BMPS mode is entered.
*/
QDF_STATUS sme_enter_wowl(tHalHandle hal_ctx,
void (*enter_wowl_callback_routine)(void
*callback_context,
QDF_STATUS status),
void *enter_wowl_callback_context,
#ifdef WLAN_WAKEUP_EVENTS
void (*wakeIndicationCB)(void *callback_context,
tpSirWakeReasonInd
wake_reason_ind),
void *wakeIndicationCBContext,
#endif /* WLAN_WAKEUP_EVENTS */
tpSirSmeWowlEnterParams wowl_enter_params,
uint8_t session_id)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx);
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_ENTER_WOWL, session_id, 0));
/* cache the WOWL information */
ps_global_info->ps_params[session_id].wowl_enter_params =
*wowl_enter_params;
ps_global_info->ps_params[session_id].enter_wowl_callback_routine =
enter_wowl_callback_routine;
ps_global_info->ps_params[session_id].enter_wowl_callback_context =
enter_wowl_callback_context;
#ifdef WLAN_WAKEUP_EVENTS
/* Cache the Wake Reason Indication callback information */
ps_global_info->ps_params[session_id].wake_reason_ind_cb =
wakeIndicationCB;
ps_global_info->ps_params[session_id].wake_reason_ind_cb_ctx =
wakeIndicationCBContext;
#endif /* WLAN_WAKEUP_EVENTS */
status = sme_ps_process_command(mac_ctx, session_id, SME_PS_WOWL_ENTER);
return status;
}
/**
*sme_exit_wowl(): SME API exposed to HDD to request exit from WoWLAN mode.
* @hal_ctx - The handle returned by mac_open.
* @wowl_exit_params - Carries info on which smesession
* wowl exit is requested.
*
* SME will initiate exit from WoWLAN mode and device will be
* put in BMPS mode.
* Return QDF_STATUS
* QDF_STATUS_E_FAILURE Device cannot exit WoWLAN mode.
* QDF_STATUS_SUCCESS Request accepted to exit WoWLAN mode.
*/
QDF_STATUS sme_exit_wowl(tHalHandle hal_ctx,
tpSirSmeWowlExitParams wowl_exit_params)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_ctx);
uint8_t session_id;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_EXIT_WOWL, NO_SESSION, 0));
session_id = wowl_exit_params->sessionId;
status = sme_ps_process_command(mac_ctx, session_id, SME_PS_WOWL_EXIT);
return status;
}
/**
* 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;
uint32_t i;
tCsrRoamSession *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) {
sms_log(mac_ctx, LOGE, FL("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;
sms_log(mac_ctx, LOG2, FL("keyLength %d"), set_key->keyLength);
for (i = 0; i < set_key->keyLength; i++)
sms_log(mac_ctx, LOG2, FL("%02x"), set_key->Key[i]);
sms_log(mac_ctx, LOG2, "\n session_id=%d roam_id=%d", session_id,
roam_id);
session = CSR_GET_SESSION(mac_ctx, session_id);
if (!session) {
sms_log(mac_ctx, LOGE, FL("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)
{
cds_msg_t msg;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct wep_update_default_key_idx *update_key;
update_key = qdf_mem_malloc(sizeof(*update_key));
if (!update_key) {
sms_log(mac_ctx, LOGE,
FL("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 !=
cds_mq_post_message(QDF_MODULE_ID_WMA, &msg)) {
sms_log(mac_ctx, LOGE,
FL("Failed to post WMA_UPDATE_WEP_DEFAULT_KEY to WMA"));
qdf_mem_free(update_key);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/* ---------------------------------------------------------------------------
\fn sme_get_rssi
\brief a wrapper function that client calls to register a callback to get
RSSI
\param hHal - HAL handle for device
\param callback - SME sends back the requested stats using the callback
\param staId - The station ID for which the stats is requested for
\param bssid - The bssid of the connected session
\param lastRSSI - RSSI value at time of request. In case fw cannot provide
RSSI, do not hold up but return this value.
\param pContext - user context to be passed back along with the callback
\param p_cds_context - cds context
\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, void *p_cds_context)
{
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, p_cds_context);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_get_snr
\brief a wrapper function that client calls to register a callback to
get SNR
\param callback - SME sends back the requested stats using the callback
\param staId - The station ID for which the stats is requested for
\param pContext - user context to be passed back along with the callback
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_statistics
\brief a wrapper function that client calls to register a callback to get
different PHY level statistics from CSR.
\param requesterId - different client requesting for statistics,
HDD, UMA/GAN etc
\param statsMask - The different category/categories of stats requester
is looking for
\param callback - SME sends back the requested stats using the callback
\param periodicity - If requester needs periodic update in millisec, 0 means
it's an one time request
\param cache - If requester is happy with cached stats
\param staId - The station ID for which the stats is requested for
\param pContext - user context to be passed back along with the callback
\param sessionId - sme session interface
\return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_get_statistics(tHalHandle hHal,
eCsrStatsRequesterType requesterId,
uint32_t statsMask, tCsrStatsCallback callback,
uint32_t periodicity, bool cache, uint8_t staId,
void *pContext, 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_GET_STATS, NO_SESSION,
periodicity));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status =
csr_get_statistics(pMac, requesterId, statsMask, callback,
periodicity, cache, staId, pContext,
sessionId);
sme_release_global_lock(&pMac->sme);
}
return status;
}
QDF_STATUS sme_get_link_status(tHalHandle hHal,
tCsrLinkStatusCallback callback,
void *pContext, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tAniGetLinkStatus *pMsg;
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
pMsg = qdf_mem_malloc(sizeof(tAniGetLinkStatus));
if (NULL == pMsg) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for link status",
__func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
pMsg->msgType = WMA_LINK_STATUS_GET_REQ;
pMsg->msgLen = (uint16_t) sizeof(tAniGetLinkStatus);
pMsg->sessionId = sessionId;
pMac->sme.linkStatusContext = pContext;
pMac->sme.linkStatusCallback = callback;
cds_message.type = WMA_LINK_STATUS_GET_REQ;
cds_message.bodyptr = pMsg;
cds_message.reserved = 0;
if (!QDF_IS_STATUS_SUCCESS
(cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_message))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post LINK STATUS MSG fail", __func__);
qdf_mem_free(pMsg);
pMac->sme.linkStatusContext = NULL;
pMac->sme.linkStatusCallback = NULL;
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_get_country_code
\brief 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.
\param pBuf - pointer to a caller allocated buffer for returned country code.
\param 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);
}
/**
* sme_apply_channel_power_info_to_fw() - sends channel info to fw
* @hHal: hal handle
*
* This function sends the channel power info to firmware
*
* Return: none
*/
void sme_apply_channel_power_info_to_fw(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
csr_apply_channel_power_info_wrapper(pMac);
}
/* some support functions */
bool sme_is11d_supported(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return csr_is11d_supported(pMac);
}
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);
}
/* ---------------------------------------------------------------------------
\fn sme_change_country_code
\brief Change Country code from upperlayer during WLAN driver operation.
This is a synchronous API.
\param hHal - The handle returned by mac_open.
\param pCountry New Country Code String
\param sendRegHint If we want to send reg hint to nl80211
\return QDF_STATUS SUCCESS.
FAILURE or RESOURCES The API finished and failed.
-------------------------------------------------------------------------------*/
QDF_STATUS sme_change_country_code(tHalHandle hHal,
tSmeChangeCountryCallback callback,
uint8_t *pCountry,
void *pContext,
void *p_cds_context,
tAniBool countryFromUserSpace,
tAniBool sendRegHint)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t msg;
tAniChangeCountryCodeReq *pMsg;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CHANGE_CNTRYCODE, NO_SESSION,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOG1, FL(" called"));
if ((pMac->roam.configParam.Is11dSupportEnabledOriginal == true)
&& (!pMac->roam.configParam.
fSupplicantCountryCodeHasPriority)) {
sms_log(pMac, LOGW,
"Set Country Code Fail since the STA is associated and userspace does not have priority ");
sme_release_global_lock(&pMac->sme);
status = QDF_STATUS_E_FAILURE;
return status;
}
pMsg = qdf_mem_malloc(sizeof(tAniChangeCountryCodeReq));
if (NULL == pMsg) {
sms_log(pMac, LOGE,
" csrChangeCountryCode: failed to allocate mem for req");
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
pMsg->msgType = eWNI_SME_CHANGE_COUNTRY_CODE;
pMsg->msgLen = (uint16_t) sizeof(tAniChangeCountryCodeReq);
qdf_mem_copy(pMsg->countryCode, pCountry, 3);
pMsg->countryFromUserSpace = countryFromUserSpace;
pMsg->sendRegHint = sendRegHint;
pMsg->changeCCCallback = callback;
pMsg->pDevContext = pContext;
pMsg->p_cds_context = p_cds_context;
msg.type = eWNI_SME_CHANGE_COUNTRY_CODE;
msg.bodyptr = pMsg;
msg.reserved = 0;
if (QDF_STATUS_SUCCESS !=
cds_mq_post_message(CDS_MQ_ID_SME, &msg)) {
sms_log(pMac, LOGE,
" sme_change_country_code failed to post msg to self ");
qdf_mem_free((void *)pMsg);
status = QDF_STATUS_E_FAILURE;
}
sms_log(pMac, LOG1, FL(" returned"));
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*--------------------------------------------------------------------------
\fn sme_generic_change_country_code
\brief Change Country code from upperlayer during WLAN driver operation.
This is a synchronous API.
\param hHal - The handle returned by mac_open.
\param pCountry New Country Code String
\param 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);
cds_msg_t msg;
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)) {
sms_log(pMac, LOG1, FL(" called"));
pMsg = qdf_mem_malloc(sizeof(tAniGenericChangeCountryCodeReq));
if (NULL == pMsg) {
sms_log(pMac, LOGE,
" 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 !=
cds_mq_post_message(CDS_MQ_ID_SME, &msg)) {
sms_log(pMac, LOGE,
"sme_generic_change_country_code failed to post msg to self");
qdf_mem_free(pMsg);
status = QDF_STATUS_E_FAILURE;
}
sms_log(pMac, LOG1, FL(" returned"));
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_dhcp_start_ind
\brief API to signal the FW about the DHCP Start event.
\param hHal - HAL handle for device.
\param device_mode - mode(AP,SAP etc) of the device.
\param macAddr - MAC address of the adapter.
\param 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);
cds_msg_t cds_message;
tAniDHCPInd *pMsg;
tCsrRoamSession *pSession;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
pSession = CSR_GET_SESSION(pMac, sessionId);
if (!pSession) {
sms_log(pMac, LOGE, FL("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);
cds_message.type = WMA_DHCP_START_IND;
cds_message.bodyptr = pMsg;
cds_message.reserved = 0;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
sessionId, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/* ---------------------------------------------------------------------------
\fn sme_dhcp_stop_ind
\brief API to signal the FW about the DHCP complete event.
\param hHal - HAL handle for device.
\param device_mode - mode(AP, SAP etc) of the device.
\param macAddr - MAC address of the adapter.
\param 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);
cds_msg_t cds_message;
tAniDHCPInd *pMsg;
tCsrRoamSession *pSession;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
pSession = CSR_GET_SESSION(pMac, sessionId);
if (!pSession) {
sms_log(pMac, LOGE, FL("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);
cds_message.type = WMA_DHCP_STOP_IND;
cds_message.bodyptr = pMsg;
cds_message.reserved = 0;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
sessionId, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/*---------------------------------------------------------------------------
\fn sme_TXFailMonitorStopInd
\brief 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);
cds_msg_t cds_message;
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;
cds_message.type = WMA_TX_FAIL_MONITOR_IND;
cds_message.bodyptr = pMsg;
cds_message.reserved = 0;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_cfg_privacy
\brief API to set configure privacy parameters
\param hHal - The handle returned by mac_open.
\param pProfile - Pointer CSR Roam profile.
\param fPrivacy - This parameter indicates status of privacy
\return void
---------------------------------------------------------------------------*/
void sme_set_cfg_privacy(tHalHandle hHal,
tCsrRoamProfile *pProfile, bool fPrivacy)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SET_CFGPRIVACY, NO_SESSION, 0));
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
csr_set_cfg_privacy(pMac, pProfile, fPrivacy);
sme_release_global_lock(&pMac->sme);
}
}
/* ---------------------------------------------------------------------------
\fn sme_neighbor_report_request
\brief API to request neighbor report.
\param hHal - The handle returned by mac_open.
\param 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 (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
status =
sme_rrm_neighbor_report_request(hHal, sessionId,
pRrmNeighborReq, callbackInfo);
sme_release_global_lock(&pMac->sme);
}
return status;
}
void sms_log(tpAniSirGlobal pMac, uint32_t loglevel, const char *pString, ...)
{
#ifdef WLAN_DEBUG
/* Verify against current log level */
if (loglevel >
pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE(SIR_SMS_MODULE_ID)])
return;
else {
va_list marker;
va_start(marker, pString); /* Initialize variable arguments. */
log_debug(pMac, SIR_SMS_MODULE_ID, loglevel, pString, marker);
va_end(marker); /* Reset variable arguments. */
}
#endif
}
/* ---------------------------------------------------------------------------
\fn sme_get_wcnss_wlan_compiled_version
\brief This API returns the version of the WCNSS WLAN API with
which the HOST driver was built
\param hHal - The handle returned by mac_open.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_wcnss_wlan_reported_version
\brief This API returns the version of the WCNSS WLAN API with
which the WCNSS driver reports it was built
\param hHal - The handle returned by mac_open.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_wcnss_software_version
\brief This API returns the version string of the WCNSS driver
\param hHal - The handle returned by mac_open.
\param pVersion - Points to the Version string buffer to be filled
\param 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);
v_CONTEXT_t cds_context = cds_get_global_context();
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
if (pVersion != NULL) {
status =
wma_get_wcnss_software_version(cds_context,
pVersion,
versionBufferSize);
} else {
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_get_wcnss_hardware_version
\brief This API returns the version string of the WCNSS hardware
\param hHal - The handle returned by mac_open.
\param pVersion - Points to the Version string buffer to be filled
\param 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_WLAN_WAPI
/* ---------------------------------------------------------------------------
\fn sme_scan_get_bkid_candidate_list
\brief a wrapper function to return the BKID candidate list
\param pBkidList - caller allocated buffer point to an array of
tBkidCandidateInfo
\param pNumItems - pointer to a variable that has the number of
tBkidCandidateInfo allocated when retruning, this is
either the number needed or number of items put into
pPmkidList
\return QDF_STATUS - when fail, it usually means the buffer allocated is not
big enough and pNumItems
has the number of tBkidCandidateInfo.
\Note: pNumItems is a number of tBkidCandidateInfo,
not sizeof(tBkidCandidateInfo) * something
---------------------------------------------------------------------------*/
QDF_STATUS sme_scan_get_bkid_candidate_list(tHalHandle hHal, uint32_t sessionId,
tBkidCandidateInfo *pBkidList,
uint32_t *pNumItems)
{
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_scan_get_bkid_candidate_list(pMac, sessionId, pBkidList,
pNumItems);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif /* FEATURE_WLAN_WAPI */
#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;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct oem_data_req *oem_data_req;
void *wma_handle;
sms_log(mac_ctx, LOG1, FL("enter"));
wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
if (!wma_handle) {
sms_log(mac_ctx, LOGE, FL("wma_handle is NULL"));
return QDF_STATUS_E_FAILURE;
}
oem_data_req = qdf_mem_malloc(sizeof(*oem_data_req));
if (!oem_data_req) {
sms_log(mac_ctx, LOGE, FL("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) {
sms_log(mac_ctx, LOGE, FL("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)) {
sms_log(mac_ctx, LOGE, FL("Post oem data request msg fail"));
} else {
sms_log(mac_ctx, LOG1,
FL("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);
sms_log(mac_ctx, LOG1, FL("exit"));
return status;
}
#endif /*FEATURE_OEM_DATA_SUPPORT */
/*--------------------------------------------------------------------------
\brief sme_open_session() - Open a session for scan/roam operation.
This is a synchronous API.
\param hHal - The handle returned by mac_open.
\param callback - A pointer to the function caller specifies for
roam/connect status indication
\param pContext - The context passed with callback
\param pSelfMacAddr - Caller allocated memory filled with self MAC address
(6 bytes)
\param pbSessionId - pointer to a caller allocated buffer for returned session ID
\return QDF_STATUS_SUCCESS - session is opened. sessionId returned.
Other status means SME is failed to open the session.
QDF_STATUS_E_RESOURCES - no more session available.
\sa
--------------------------------------------------------------------------*/
QDF_STATUS sme_open_session(tHalHandle hHal, csr_roam_completeCallback callback,
void *pContext,
uint8_t *pSelfMacAddr, uint8_t *pbSessionId,
uint32_t type, uint32_t subType)
{
QDF_STATUS status;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
"%s: type=%d, subType=%d addr:%pM",
__func__, type, subType, pSelfMacAddr);
if (NULL == pbSessionId) {
status = QDF_STATUS_E_INVAL;
} else {
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_roam_open_session(pMac, callback, pContext,
pSelfMacAddr,
pbSessionId, type,
subType);
sme_release_global_lock(&pMac->sme);
}
}
if (NULL != pbSessionId)
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_OPEN_SESSION,
*pbSessionId, 0));
return status;
}
/*--------------------------------------------------------------------------
\brief sme_close_session() - Open a session for scan/roam operation.
This is a synchronous API.
\param hHal - The handle returned by mac_open.
\param sessionId - A previous opened session's ID.
\return QDF_STATUS_SUCCESS - session is closed.
Other status means SME is failed to open the session.
QDF_STATUS_E_INVAL - session is not opened.
\sa
--------------------------------------------------------------------------*/
QDF_STATUS sme_close_session(tHalHandle hHal, uint8_t sessionId,
csr_roamSessionCloseCallback callback,
void *pContext)
{
QDF_STATUS status;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CLOSE_SESSION, sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_roam_close_session(pMac, sessionId, false,
callback, pContext);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_update_apwpsie
\brief To update AP's WPS IE. This function should be called after SME AP session is created
This is an asynchronous API.
\param pAPWPSIES - pointer to a caller allocated object of tSirAPWPSIEs
\return QDF_STATUS – SUCCESS –
FAILURE or RESOURCES – The API finished and failed.
-------------------------------------------------------------------------------*/
QDF_STATUS sme_roam_update_apwpsie(tHalHandle hHal, uint8_t sessionId,
tSirAPWPSIEs *pAPWPSIES)
{
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_apwpsie(pMac, sessionId, pAPWPSIES);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_roam_update_apwparsni_es
\brief To update AP's WPA/RSN IEs. This function should be called after SME AP session is created
This is an asynchronous API.
\param pAPSirRSNie - pointer to a caller allocated object of tSirRSNie with WPS/RSN IEs
\return QDF_STATUS – SUCCESS –
FAILURE or RESOURCES – The API finished and failed.
-------------------------------------------------------------------------------*/
QDF_STATUS sme_roam_update_apwparsni_es(tHalHandle hHal, uint8_t sessionId,
tSirRSNie *pAPSirRSNie)
{
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_wparsni_es(pMac, sessionId, pAPSirRSNie);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_change_mcc_beacon_interval
\brief To update P2P-GO beaconInterval. This function should be called after
disassociating all the station is done
This is an asynchronous API.
\param
\return QDF_STATUS SUCCESS
FAILURE or RESOURCES
The API finished and failed.
-------------------------------------------------------------------------------*/
QDF_STATUS sme_change_mcc_beacon_interval(tHalHandle hHal, uint8_t sessionId)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
sms_log(pMac, LOG1, FL("Update Beacon PARAMS "));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_send_chng_mcc_beacon_interval(pMac, sessionId);
sme_release_global_lock(&pMac->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;
}
#ifdef WLAN_FEATURE_GTK_OFFLOAD
/**
* sme_set_gtk_offload(): API to set GTK offload information.
* @hHal: The handle returned by mac_open.
* @sessionId: Session Identifier
* @pGtkOffload: Pointer to the GTK offload request..
*
* Return QDF_STATUS
*/
QDF_STATUS sme_set_gtk_offload(tHalHandle hHal,
tpSirGtkOffloadParams pGtkOffload,
uint8_t sessionId)
{
tpSirGtkOffloadParams request_buf;
cds_msg_t msg;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
"%s: KeyReplayCounter: %lld", __func__,
pGtkOffload->ullKeyReplayCounter);
if (NULL == pSession) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Session not found ", __func__);
return QDF_STATUS_E_FAILURE;
}
request_buf = qdf_mem_malloc(sizeof(*request_buf));
if (NULL == request_buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to allocate memory for GTK offload request"));
return QDF_STATUS_E_NOMEM;
}
qdf_copy_macaddr(&pGtkOffload->bssid,
&pSession->connectedProfile.bssid);
*request_buf = *pGtkOffload;
msg.type = WMA_GTK_OFFLOAD_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_IS_STATUS_SUCCESS
(cds_mq_post_message(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post SIR_HAL_SET_GTK_OFFLOAD message to HAL"));
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/**
* sme_get_gtk_offload(): API to get GTK offload information
* @hHal: The handle returned by mac_open.
* @callback_routine: callback_routine.
* @sessionId: Session Identifier.
* callback_context: callback_context.
*
* Return QDF_STATUS
*/
QDF_STATUS sme_get_gtk_offload(tHalHandle hHal,
gtk_offload_get_info_callback callback_routine,
void *callback_context, uint8_t session_id)
{
tpSirGtkOffloadGetInfoRspParams request_buf;
cds_msg_t msg;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, session_id);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO, "%s: Entered",
__func__);
if (NULL == pSession) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Session not found", __func__);
return QDF_STATUS_E_FAILURE;
}
request_buf = qdf_mem_malloc(sizeof(*request_buf));
if (NULL == request_buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to allocate memory for Get GTK offload request"));
return QDF_STATUS_E_NOMEM;
}
qdf_copy_macaddr(&request_buf->bssid,
&pSession->connectedProfile.bssid);
msg.type = WMA_GTK_OFFLOAD_GETINFO_REQ;
msg.reserved = 0;
msg.bodyptr = request_buf;
/* Cache the Get GTK Offload callback information */
if (NULL != pMac->sme.gtk_offload_get_info_cb) {
/* Do we need to check if the callback is in use? */
/* Because we are not sending the same message again
* when it is pending,
* the only case when the callback is not NULL is that
* the previous message was timed out or failed.
* So, it will be safe to set the callback in this case.
*/
}
pMac->sme.gtk_offload_get_info_cb = callback_routine;
pMac->sme.gtk_offload_get_info_cb_context = callback_context;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
session_id, msg.type));
if (!QDF_IS_STATUS_SUCCESS
(cds_mq_post_message(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post WMA_GTK_OFFLOAD_GETINFO_REQ message to WMA"));
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_FEATURE_GTK_OFFLOAD */
/* ---------------------------------------------------------------------------
\fn sme_set_keep_alive
\brief API to set the Keep Alive feature.
\param hHal - The handle returned by mac_open.
\param 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;
cds_msg_t msg;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, session_id);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_LOW,
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,
FL("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_INFO_LOW,
"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 !=
cds_mq_post_message(QDF_MODULE_ID_WMA, &msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("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;
}
#ifdef FEATURE_WLAN_SCAN_PNO
/* ---------------------------------------------------------------------------
\fn sme_set_preferred_network_list
\brief API to set the Preferred Network List Offload feature.
\param hHal - The handle returned by mac_open.
\param request - Pointer to the offload request.
\return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_set_preferred_network_list(tHalHandle hHal,
tpSirPNOScanReq request,
uint8_t sessionId,
void (*callback_routine)(void *callback_context,
tSirPrefNetworkFoundInd
*pPrefNetworkFoundInd),
void *callback_context)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_PREF_NET_LIST,
sessionId, request->ucNetworksCount));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = sme_set_ps_preferred_network_list(hHal, request,
sessionId,
callback_routine,
callback_context);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif /* FEATURE_WLAN_SCAN_PNO */
/* ---------------------------------------------------------------------------
\fn sme_abort_mac_scan
\brief API to cancel MAC scan.
\param hHal - The handle returned by mac_open.
\param sessionId - sessionId on which we need to abort scan.
\param reason - Reason to abort the scan.
\return QDF_STATUS
QDF_STATUS_E_FAILURE - failure
QDF_STATUS_SUCCESS success
---------------------------------------------------------------------------*/
QDF_STATUS sme_abort_mac_scan(tHalHandle hHal, uint8_t sessionId,
eCsrAbortReason reason)
{
QDF_STATUS status;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_ABORT_MACSCAN, NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_scan_abort_mac_scan(pMac, sessionId, reason);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ----------------------------------------------------------------------------
\fn sme_get_operation_channel
\brief API to get current channel on which STA is parked
this function gives channel information only of infra station or IBSS station
\param 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);
tCsrRoamSession *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_p2p_ack_ind_callback() - p2p ack indication callback
* @hal: hal pointer
* @callback: callback pointer to be registered
*
* This function is used to register a callback to PE for p2p ack
* indication
*
* Return: Success if msg is posted to PE else Failure.
*/
QDF_STATUS sme_register_p2p_ack_ind_callback(tHalHandle hal,
sir_p2p_ack_ind_callback callback)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct sir_sme_p2p_ack_ind_cb_req *msg;
QDF_STATUS status = QDF_STATUS_SUCCESS;
sms_log(mac_ctx, LOG1, FL(": ENTER"));
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
msg = qdf_mem_malloc(sizeof(*msg));
if (NULL == msg) {
sms_log(mac_ctx, LOGE,
FL("Failed to allocate memory"));
sme_release_global_lock(&mac_ctx->sme);
return QDF_STATUS_E_NOMEM;
}
msg->message_type = eWNI_SME_REGISTER_P2P_ACK_CB;
msg->length = sizeof(*msg);
msg->callback = callback;
status = cds_send_mb_message_to_mac(msg);
sme_release_global_lock(&mac_ctx->sme);
return status;
}
return status;
}
/**
* 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;
sms_log(mac_ctx, LOG1, FL(": ENTER"));
if (QDF_STATUS_SUCCESS ==
sme_acquire_global_lock(&mac_ctx->sme)) {
msg = qdf_mem_malloc(sizeof(*msg));
if (NULL == msg) {
sms_log(mac_ctx, LOGE,
FL("Not able to allocate memory for eWNI_SME_REGISTER_MGMT_FRAME_CB"));
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 = cds_send_mb_message_to_mac(msg);
sme_release_global_lock(&mac_ctx->sme);
return status;
}
return QDF_STATUS_E_FAILURE;
}
/* ---------------------------------------------------------------------------
\fn sme_RegisterMgtFrame
\brief To register managment frame of specified type and subtype.
\param frameType - type of the frame that needs to be passed to HDD.
\param matchData - data which needs to be matched before passing frame
to HDD.
\param 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);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_REGISTER_MGMTFR, sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
tSirRegisterMgmtFrame *pMsg;
uint16_t len;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
if (!CSR_IS_SESSION_ANY(sessionId) && !pSession) {
sms_log(pMac, LOGE, FL(" 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 = cds_send_mb_message_to_mac(pMsg);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_DeregisterMgtFrame
\brief To De-register managment frame of specified type and subtype.
\param frameType - type of the frame that needs to be passed to HDD.
\param matchData - data which needs to be matched before passing frame
to HDD.
\param 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;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
if (!CSR_IS_SESSION_ANY(sessionId) && !pSession) {
sms_log(pMac, LOGE, FL(" 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 = cds_send_mb_message_to_mac(pMsg);
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* sme_remain_on_channel - API to request remain on channel for 'x' duration
*
* @hHal: pointer to MAC handle
* @session_id: Session identifier
* @channel: channel information
* @duration: duration in ms
* @callback: HDD registered callback to process reaminOnChannelRsp
* @context: HDD Callback param
* @scan_id: scan identifier
*
* This function process the roc request and generates scan identifier.s
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_remain_on_channel(tHalHandle hHal, uint8_t session_id,
uint8_t channel, uint32_t duration,
remainOnChanCallback callback,
void *pContext, uint8_t isP2PProbeReqAllowed,
uint32_t *scan_id)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hHal);
uint32_t san_req_id, scan_count;
struct ani_roc_req *roc_msg;
cds_msg_t msg;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_REMAIN_ONCHAN, session_id, 0));
scan_count = csr_ll_count(&mac_ctx->sme.smeScanCmdActiveList);
if (scan_count >= mac_ctx->scan.max_scan_count) {
sms_log(mac_ctx, LOGE, FL("Max scan reached"));
return QDF_STATUS_E_FAILURE;
}
wma_get_scan_id(&san_req_id);
*scan_id = san_req_id;
status = sme_acquire_global_lock(&mac_ctx->sme);
sms_log(mac_ctx, LOG1, FL(" called"));
roc_msg = qdf_mem_malloc(sizeof(struct ani_roc_req));
if (NULL == roc_msg) {
sms_log(mac_ctx, LOGE,
" scan_req: failed to allocate mem for msg");
sme_release_global_lock(&mac_ctx->sme);
return QDF_STATUS_E_NOMEM;
}
roc_msg->msg_type = eWNI_SME_ROC_CMD;
roc_msg->msg_len = (uint16_t) sizeof(struct ani_roc_req);
roc_msg->session_id = session_id;
roc_msg->callback = callback;
roc_msg->duration = duration;
roc_msg->channel = channel;
roc_msg->is_p2pprobe_allowed = isP2PProbeReqAllowed;
roc_msg->ctx = pContext;
roc_msg->scan_id = *scan_id;
msg.type = eWNI_SME_ROC_CMD;
msg.bodyptr = roc_msg;
msg.reserved = 0;
msg.bodyval = 0;
if (QDF_STATUS_SUCCESS !=
cds_mq_post_message(CDS_MQ_ID_SME, &msg)) {
sms_log(mac_ctx, LOGE,
" sme_scan_req failed to post msg");
qdf_mem_free(roc_msg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac_ctx->sme);
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_report_probe_req
\brief API to enable/disable forwarding of probeReq to apps in p2p.
\param hHal - The handle returned by mac_open.
\param falg: to set the Probe request forarding to wpa_supplicant in listen state in p2p
\return QDF_STATUS
---------------------------------------------------------------------------*/
#ifndef WLAN_FEATURE_CONCURRENT_P2P
QDF_STATUS sme_report_probe_req(tHalHandle hHal, uint8_t flag)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
do {
/* acquire the lock for the sme object */
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* call set in context */
pMac->p2pContext.probeReqForwarding = flag;
/* release the lock for the sme object */
sme_release_global_lock(&pMac->sme);
}
} while (0);
sms_log(pMac, LOGW, "exiting function %s", __func__);
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_update_p2p_ie
\brief API to set the P2p Ie in p2p context
\param hHal - The handle returned by mac_open.
\param p2pIe - Ptr to p2pIe from HDD.
\param p2pIeLength: length of p2pIe
\return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_update_p2p_ie(tHalHandle hHal, void *p2pIe, uint32_t p2pIeLength)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_UPDATE_P2P_IE, NO_SESSION, 0));
/* acquire the lock for the sme object */
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
if (NULL != pMac->p2pContext.probeRspIe) {
qdf_mem_free(pMac->p2pContext.probeRspIe);
pMac->p2pContext.probeRspIeLength = 0;
}
pMac->p2pContext.probeRspIe = qdf_mem_malloc(p2pIeLength);
if (NULL == pMac->p2pContext.probeRspIe) {
sms_log(pMac, LOGE, "%s: Unable to allocate P2P IE",
__func__);
pMac->p2pContext.probeRspIeLength = 0;
status = QDF_STATUS_E_NOMEM;
} else {
pMac->p2pContext.probeRspIeLength = p2pIeLength;
sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG2,
pMac->p2pContext.probeRspIe,
pMac->p2pContext.probeRspIeLength);
qdf_mem_copy((uint8_t *) pMac->p2pContext.probeRspIe,
p2pIe, p2pIeLength);
}
/* release the lock for the sme object */
sme_release_global_lock(&pMac->sme);
}
sms_log(pMac, LOG2, "exiting function %s", __func__);
return status;
}
#endif
/* ---------------------------------------------------------------------------
\fn sme_send_action
\brief API to send action frame from supplicant.
\param hHal - The handle returned by mac_open.
\return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_send_action(tHalHandle hHal, uint8_t sessionId,
const uint8_t *pBuf, uint32_t len,
uint16_t wait, bool noack,
uint16_t channel_freq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_SEND_ACTION, sessionId, 0));
/* acquire the lock for the sme object */
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
p2p_send_action(hHal, sessionId, pBuf, len, wait, noack,
channel_freq);
/* release the lock for the sme object */
sme_release_global_lock(&pMac->sme);
}
sms_log(pMac, LOGW, "exiting function %s", __func__);
return status;
}
QDF_STATUS sme_cancel_remain_on_channel(tHalHandle hHal,
uint8_t sessionId, uint32_t scan_id)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CANCEL_REMAIN_ONCHAN, sessionId,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = p2p_cancel_remain_on_channel(hHal, sessionId, scan_id);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* Power Save Related */
QDF_STATUS sme_p2p_set_ps(tHalHandle hHal, tP2pPsConfig *data)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = p2p_set_ps(hHal, data);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_configure_rxp_filter
\brief
SME will pass this request to lower mac to set/reset the filter on RXP for
multicast & broadcast traffic.
\param
hHal - The handle returned by mac_open.
filterMask- Currently the API takes a 1 or 0 (set or reset) as filter.
Basically to enable/disable the filter (to filter "all" mcbc traffic) based
on this param. In future we can use this as a mask to set various types of
filters as suggested below:
FILTER_ALL_MULTICAST:
FILTER_ALL_BROADCAST:
FILTER_ALL_MULTICAST_BROADCAST:
\return QDF_STATUS
--------------------------------------------------------------------------- */
QDF_STATUS sme_configure_rxp_filter(tHalHandle hHal,
tpSirWlanSetRxpFilters wlanRxpFilterParam)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CONFIG_RXPFIL, NO_SESSION, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* serialize the req through MC thread */
cds_message.bodyptr = wlanRxpFilterParam;
cds_message.type = WMA_CFG_RXP_FILTER_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_configure_suspend_ind
\brief
SME will pass this request to lower mac to Indicate that the wlan needs to
be suspended
\param
hHal - The handle returned by mac_open.
wlanSuspendParam- Depicts the wlan suspend params
csr_readyToSuspendCallback - Callback to be called when ready to suspend
event is received.
callback_context - Context associated with csr_readyToSuspendCallback.
\return QDF_STATUS
--------------------------------------------------------------------------- */
QDF_STATUS sme_configure_suspend_ind(tHalHandle hHal,
uint32_t conn_state_mask,
csr_readyToSuspendCallback callback,
void *callback_context)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CONFIG_SUSPENDIND, NO_SESSION,
0));
pMac->readyToSuspendCallback = callback;
pMac->readyToSuspendContext = callback_context;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* serialize the req through MC thread */
cds_message.bodyval = conn_state_mask;
cds_message.type = WMA_WLAN_SUSPEND_IND;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
pMac->readyToSuspendCallback = NULL;
pMac->readyToSuspendContext = NULL;
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_configure_resume_req
\brief
SME will pass this request to lower mac to Indicate that the wlan needs to
be Resumed
\param
hHal - The handle returned by mac_open.
wlanResumeParam- Depicts the wlan resume params
\return QDF_STATUS
--------------------------------------------------------------------------- */
QDF_STATUS sme_configure_resume_req(tHalHandle hHal,
tpSirWlanResumeParam wlanResumeParam)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_CONFIG_RESUMEREQ, NO_SESSION,
0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* serialize the req through MC thread */
cds_message.bodyptr = wlanResumeParam;
cds_message.type = WMA_WLAN_RESUME_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->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);
cds_msg_t cds_message;
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));
cds_message.bodyptr = MsgPtr;
cds_message.type = WMA_WLAN_EXT_WOW;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/* ---------------------------------------------------------------------------
\fn sme_configure_app_type1_params
\brief
SME will pass this request to lower mac to configure Indoor WoW parameters.
\param
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);
cds_msg_t cds_message;
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));
cds_message.bodyptr = MsgPtr;
cds_message.type = WMA_WLAN_SET_APP_TYPE1_PARAMS;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/* ---------------------------------------------------------------------------
\fn sme_configure_app_type2_params
\brief
SME will pass this request to lower mac to configure Indoor WoW parameters.
\param
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);
cds_msg_t cds_message;
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));
cds_message.bodyptr = MsgPtr;
cds_message.type = WMA_WLAN_SET_APP_TYPE2_PARAMS;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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
/* ---------------------------------------------------------------------------
\fn sme_get_infra_session_id
\brief To get the session ID for infra session, if connected
This is a synchronous API.
\param hHal - The handle returned by mac_open.
\return 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_infra_operation_channel
\brief To get the operating channel for infra session, if connected
This is a synchronous API.
\param hHal - The handle returned by mac_open.
\param 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_HIGH, "%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
#ifdef FEATURE_WLAN_SCAN_PNO
/**
* sme_update_roam_pno_channel_prediction_config() - Update PNO config
* @csr_config: config from SME context
* @hal: Global Hal handle
* @copy_from_to: Used to specify the source and destination
*
* Copy the PNO channel prediction configuration parameters from
* SME context to MAC context or vice-versa
*
* Return: None
*/
void sme_update_roam_pno_channel_prediction_config(
tHalHandle hal, tCsrConfigParam *csr_config,
uint8_t copy_from_to)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
if (copy_from_to == SME_CONFIG_TO_ROAM_CONFIG) {
mac_ctx->roam.configParam.pno_channel_prediction =
csr_config->pno_channel_prediction;
mac_ctx->roam.configParam.top_k_num_of_channels =
csr_config->top_k_num_of_channels;
mac_ctx->roam.configParam.stationary_thresh =
csr_config->stationary_thresh;
mac_ctx->roam.configParam.channel_prediction_full_scan =
csr_config->channel_prediction_full_scan;
mac_ctx->roam.configParam.pnoscan_adaptive_dwell_mode =
csr_config->pnoscan_adaptive_dwell_mode;
} else if (copy_from_to == ROAM_CONFIG_TO_SME_CONFIG) {
csr_config->pno_channel_prediction =
mac_ctx->roam.configParam.pno_channel_prediction;
csr_config->top_k_num_of_channels =
mac_ctx->roam.configParam.top_k_num_of_channels;
csr_config->stationary_thresh =
mac_ctx->roam.configParam.stationary_thresh;
csr_config->channel_prediction_full_scan =
mac_ctx->roam.configParam.channel_prediction_full_scan;
csr_config->pnoscan_adaptive_dwell_mode =
mac_ctx->roam.configParam.pnoscan_adaptive_dwell_mode;
}
}
/******************************************************************************
*
* Name: sme_preferred_network_found_ind
*
* Description:
* Invoke Preferred Network Found Indication
*
* Parameters:
* hHal - HAL handle for device
* pMsg - found network description
*
* Returns: QDF_STATUS
*
******************************************************************************/
QDF_STATUS sme_preferred_network_found_ind(tHalHandle hHal, void *pMsg)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
tSirPrefNetworkFoundInd *pPrefNetworkFoundInd =
(tSirPrefNetworkFoundInd *) pMsg;
uint8_t dumpSsId[SIR_MAC_MAX_SSID_LENGTH + 1];
uint8_t ssIdLength = 0;
if (NULL == pMsg) {
sms_log(pMac, LOGE, "in %s msg ptr is NULL", __func__);
return QDF_STATUS_E_FAILURE;
}
if (pMac->pnoOffload) {
/* Call Preferred Network Found Indication callback routine. */
if (pMac->sme.pref_netw_found_cb != NULL) {
pMac->sme.pref_netw_found_cb(pMac->sme.
preferred_network_found_ind_cb_ctx,
pPrefNetworkFoundInd);
}
return status;
}
if (pPrefNetworkFoundInd->ssId.length > 0) {
ssIdLength = CSR_MIN(SIR_MAC_MAX_SSID_LENGTH,
pPrefNetworkFoundInd->ssId.length);
qdf_mem_copy(dumpSsId, pPrefNetworkFoundInd->ssId.ssId,
ssIdLength);
dumpSsId[ssIdLength] = 0;
sms_log(pMac, LOG2, "%s:SSID=%s frame length %d",
__func__, dumpSsId, pPrefNetworkFoundInd->frameLength);
/* Flush scan results, So as to avoid indication/updation of
* stale entries, which may not have aged out during APPS collapse
*/
sme_scan_flush_result(hHal);
/* Save the frame to scan result */
if (pPrefNetworkFoundInd->mesgLen >
sizeof(tSirPrefNetworkFoundInd)) {
/* we may have a frame */
status = csr_scan_save_preferred_network_found(pMac,
pPrefNetworkFoundInd);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, LOGE,
FL(" fail to save preferred network"));
}
} else {
sms_log(pMac, LOGE,
FL(" not enough data length %d needed %zu"),
pPrefNetworkFoundInd->mesgLen,
sizeof(tSirPrefNetworkFoundInd));
}
/* Call Preferred Netowrk Found Indication callback routine. */
if (QDF_IS_STATUS_SUCCESS(status)
&& (pMac->sme.pref_netw_found_cb != NULL)) {
pMac->sme.pref_netw_found_cb(pMac->sme.
preferred_network_found_ind_cb_ctx,
pPrefNetworkFoundInd);
}
} else {
sms_log(pMac, LOGE, "%s: callback failed - SSID is NULL",
__func__);
status = QDF_STATUS_E_FAILURE;
}
return status;
}
#endif /* FEATURE_WLAN_SCAN_PNO */
/**
* 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;
cds_msg_t 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 = cds_mq_post_message(CDS_MQ_ID_WMA, &tsf_msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE, "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(tHalHandle hHal, uint8_t *aValidChannels,
uint32_t *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)) {
status = csr_get_cfg_valid_channels(pMac, aValidChannels, len);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_handle_change_country_code
\brief Change Country code, Reg Domain and channel list
\details Country Code Priority
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 courtry code.
User can send reset command XX (instead of country code) to reset the
country code to default values.
If 11D is priority,
Than Supplicant country code code is set to default code. But 11D code is set as current country code
\param pMac - The handle returned by mac_open.
\param pMsgBuf - MSG Buffer
\return QDF_STATUS
-------------------------------------------------------------------------------*/
QDF_STATUS sme_handle_change_country_code(tpAniSirGlobal pMac, void *pMsgBuf)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tAniChangeCountryCodeReq *pMsg;
v_REGDOMAIN_t domainIdIoctl;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
static uint8_t default_country[CDS_COUNTRY_CODE_LEN + 1];
pMsg = (tAniChangeCountryCodeReq *) pMsgBuf;
/*
* if the reset Supplicant country code command is triggered,
* enable 11D, reset the country code and return
*/
if (!qdf_mem_cmp(pMsg->countryCode, SME_INVALID_COUNTRY_CODE, 2)) {
pMac->roam.configParam.Is11dSupportEnabled =
pMac->roam.configParam.Is11dSupportEnabledOriginal;
qdf_status = cds_read_default_country(default_country);
/* read the country code and use it */
if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
qdf_mem_copy(pMsg->countryCode,
default_country,
WNI_CFG_COUNTRY_CODE_LEN);
} else {
status = QDF_STATUS_E_FAILURE;
return status;
}
/*
* Update the 11d country to default country so that when
* callback is received for this default country, driver will
* not disable the 11d taking it as valid country by user.
*/
sms_log(pMac, LOG1,
FL("Set default country code (%c%c) as invalid country received"),
pMsg->countryCode[0], pMsg->countryCode[1]);
qdf_mem_copy(pMac->scan.countryCode11d,
pMsg->countryCode,
WNI_CFG_COUNTRY_CODE_LEN);
} else {
/* if Supplicant country code has priority, disable 11d */
if (pMac->roam.configParam.fSupplicantCountryCodeHasPriority &&
pMsg->countryFromUserSpace) {
pMac->roam.configParam.Is11dSupportEnabled = false;
}
}
if (pMac->roam.configParam.Is11dSupportEnabled)
return QDF_STATUS_SUCCESS;
/* Set Current Country code and Current Regulatory domain */
status = csr_set_country_code(pMac, pMsg->countryCode);
if (QDF_STATUS_SUCCESS != status) {
/* Supplicant country code failed. So give 11D priority */
pMac->roam.configParam.Is11dSupportEnabled =
pMac->roam.configParam.Is11dSupportEnabledOriginal;
sms_log(pMac, LOGE, "Set Country Code Fail %d", status);
return status;
}
/* overwrite the defualt country code */
qdf_mem_copy(pMac->scan.countryCodeDefault,
pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN);
/* Get Domain ID from country code */
status = csr_get_regulatory_domain_for_country(pMac,
pMac->scan.countryCodeCurrent,
(v_REGDOMAIN_t *) &
domainIdIoctl,
SOURCE_QUERY);
if (status != QDF_STATUS_SUCCESS) {
sms_log(pMac, LOGE, FL(" fail to get regId %d"), domainIdIoctl);
return status;
} else if (REGDOMAIN_WORLD == domainIdIoctl) {
/* Supplicant country code is invalid, so we are on world mode now. So
give 11D chance to update */
pMac->roam.configParam.Is11dSupportEnabled =
pMac->roam.configParam.Is11dSupportEnabledOriginal;
sms_log(pMac, LOG1, FL("Country Code unrecognized by driver"));
}
status = wma_set_reg_domain(pMac, domainIdIoctl);
if (status != QDF_STATUS_SUCCESS) {
sms_log(pMac, LOGE, FL(" fail to set regId %d"), domainIdIoctl);
return status;
} else {
/* if 11d has priority, clear currentCountryBssid & countryCode11d to get */
/* set again if we find AP with 11d info during scan */
if (!pMac->roam.configParam.fSupplicantCountryCodeHasPriority) {
sms_log(pMac, LOGW,
FL
("Clearing currentCountryBssid, countryCode11d"));
qdf_mem_zero(&pMac->scan.currentCountryBssid,
sizeof(struct qdf_mac_addr));
qdf_mem_zero(pMac->scan.countryCode11d,
sizeof(pMac->scan.countryCode11d));
}
}
if (pMsg->changeCCCallback) {
((tSmeChangeCountryCallback) (pMsg->changeCCCallback))((void *)
pMsg->
pDevContext);
}
return QDF_STATUS_SUCCESS;
}
/**
* 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
*/
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;
sms_log(mac_ctx, LOG1, FL(" called"));
if (!mac_ctx->is_11d_hint) {
if (user_ctry_priority)
mac_ctx->roam.configParam.Is11dSupportEnabled = false;
else {
if (mac_ctx->roam.configParam.Is11dSupportEnabled &&
mac_ctx->scan.countryCode11d[0] != 0) {
sms_log(mac_ctx, LOGW,
FL("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);
mac_ctx->is_11d_hint = false;
}
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) {
sms_log(mac_ctx, LOGE, FL("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;
sme_disconnect_connected_sessions(mac_ctx);
sms_log(mac_ctx, LOG1, FL(" returned"));
return QDF_STATUS_SUCCESS;
}
static bool
sme_search_in_base_ch_lst(tpAniSirGlobal mac_ctx, uint8_t curr_ch)
{
uint8_t i;
tCsrChannel *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
*/
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);
sms_log(mac_ctx, LOGW,
FL("Current Operating channel : %d, session :%d"),
curr_ch, session_id);
found = sme_search_in_base_ch_lst(mac_ctx, curr_ch);
if (!found) {
sms_log(mac_ctx, LOGW, FL("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;
cds_msg_t msg;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tCsrRoamSession *pSession = NULL;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO, "%s: "
"ulMulticastAddrCnt=%d, multicastAddr[0]=%p", __func__,
pMulticastAddrs->ulMulticastAddrCnt,
pMulticastAddrs->multicastAddr[0].bytes);
/* Find the connected Infra / P2P_client connected session */
if (CSR_IS_SESSION_VALID(pMac, sessionId) &&
(csr_is_conn_state_infra(pMac, sessionId) ||
csr_is_ndi_started(pMac, sessionId))) {
pSession = CSR_GET_SESSION(pMac, sessionId);
}
if (pSession == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN,
"%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 != cds_mq_post_message(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;
}
QDF_STATUS sme_receive_filter_set_filter(tHalHandle hHal,
tpSirRcvPktFilterCfgType pRcvPktFilterCfg,
uint8_t sessionId)
{
tpSirRcvPktFilterCfgType request_buf;
int32_t allocSize;
cds_msg_t msg;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
uint8_t idx = 0;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO, "%s: filterType=%d, "
"filterId = %d", __func__,
pRcvPktFilterCfg->filterType, pRcvPktFilterCfg->filterId);
allocSize = sizeof(tSirRcvPktFilterCfgType);
request_buf = qdf_mem_malloc(allocSize);
if (NULL == request_buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to "
"allocate memory for Receive Filter Set Filter request",
__func__);
return QDF_STATUS_E_NOMEM;
}
if (NULL == pSession) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Session Not found ", __func__);
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
qdf_copy_macaddr(&pRcvPktFilterCfg->self_macaddr,
&pSession->selfMacAddr);
qdf_copy_macaddr(&pRcvPktFilterCfg->bssid,
&pSession->connectedProfile.bssid);
qdf_mem_copy(request_buf, pRcvPktFilterCfg, allocSize);
msg.type = WMA_RECEIVE_FILTER_SET_FILTER_REQ;
msg.reserved = 0;
msg.bodyptr = request_buf;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
sessionId, msg.type));
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO, "Pkt Flt Req : "
"FT %d FID %d ",
request_buf->filterType, request_buf->filterId);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO, "Pkt Flt Req : "
"params %d CT %d",
request_buf->numFieldParams, request_buf->coalesceTime);
for (idx = 0; idx < request_buf->numFieldParams; idx++) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"Proto %d Comp Flag %d ",
request_buf->paramsData[idx].protocolLayer,
request_buf->paramsData[idx].cmpFlag);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"Data Offset %d Data Len %d",
request_buf->paramsData[idx].dataOffset,
request_buf->paramsData[idx].dataLength);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"CData: %d:%d:%d:%d:%d:%d",
request_buf->paramsData[idx].compareData[0],
request_buf->paramsData[idx].compareData[1],
request_buf->paramsData[idx].compareData[2],
request_buf->paramsData[idx].compareData[3],
request_buf->paramsData[idx].compareData[4],
request_buf->paramsData[idx].compareData[5]);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"MData: %d:%d:%d:%d:%d:%d",
request_buf->paramsData[idx].dataMask[0],
request_buf->paramsData[idx].dataMask[1],
request_buf->paramsData[idx].dataMask[2],
request_buf->paramsData[idx].dataMask[3],
request_buf->paramsData[idx].dataMask[4],
request_buf->paramsData[idx].dataMask[5]);
}
if (QDF_STATUS_SUCCESS != cds_mq_post_message(QDF_MODULE_ID_WMA, &msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post "
"WMA_RECEIVE_FILTER_SET_FILTER message to WMA",
__func__);
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS sme_receive_filter_clear_filter(tHalHandle hHal,
tpSirRcvFltPktClearParam
pRcvFltPktClearParam, uint8_t sessionId)
{
tpSirRcvFltPktClearParam request_buf;
cds_msg_t msg;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO, "%s: filterId = %d",
__func__, pRcvFltPktClearParam->filterId);
if (NULL == pSession) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Session Not found", __func__);
return QDF_STATUS_E_FAILURE;
}
request_buf = qdf_mem_malloc(sizeof(tSirRcvFltPktClearParam));
if (NULL == request_buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for Receive Filter "
"Clear Filter request", __func__);
return QDF_STATUS_E_NOMEM;
}
qdf_copy_macaddr(&pRcvFltPktClearParam->self_macaddr,
&pSession->selfMacAddr);
qdf_copy_macaddr(&pRcvFltPktClearParam->bssid,
&pSession->connectedProfile.bssid);
qdf_mem_copy(request_buf, pRcvFltPktClearParam,
sizeof(tSirRcvFltPktClearParam));
msg.type = WMA_RECEIVE_FILTER_CLEAR_FILTER_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 != cds_mq_post_message(QDF_MODULE_ID_WMA, &msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post "
"WMA_RECEIVE_FILTER_CLEAR_FILTER message to WMA",
__func__);
qdf_mem_free(request_buf);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_FEATURE_PACKET_FILTERING */
/* ---------------------------------------------------------------------------
\fn sme_is_channel_valid
\brief To check if the channel is valid for currently established domain
This is a synchronous API.
\param hHal - The handle returned by mac_open.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_freq_band
\brief Used to set frequency band.
\param hHal
\param sessionId - Session Identifier
\eBand band value to be configured
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_set_freq_band(tHalHandle hHal, uint8_t sessionId, eCsrBand 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_freq_band
\brief Used to get the current band settings.
\param hHal
\pBand pointer to hold band value
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_get_freq_band(tHalHandle hHal, eCsrBand *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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_max_tx_power_per_band
\brief Set the Maximum Transmit Power specific to band dynamically.
Note: this setting will not persist over reboots.
\param band
\param power to set in dB
\- return QDF_STATUS
----------------------------------------------------------------------------*/
QDF_STATUS sme_set_max_tx_power_per_band(eCsrBand band, int8_t dB)
{
cds_msg_t msg;
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 != cds_mq_post_message(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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_max_tx_power
\brief Set the Maximum Transmit Power dynamically. Note: this setting will
not persist over reboots.
\param hHal
\param pBssid BSSID to set the power cap for
\param pBssid pSelfMacAddress self MAC Address
\param 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)
{
cds_msg_t msg;
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 != cds_mq_post_message(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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_custom_mac_addr
\brief Set the customer Mac Address.
\param customMacAddr customer MAC Address
\- return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_set_custom_mac_addr(tSirMacAddr customMacAddr)
{
cds_msg_t msg;
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 != cds_mq_post_message(QDF_MODULE_ID_WMA, &msg)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL
("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;
}
/* ----------------------------------------------------------------------------
\fn sme_set_tx_power
\brief Set Transmit Power dynamically.
\param hHal
\param sessionId Target Session ID
\pBSSId BSSID
\dev_mode dev_mode such as station, P2PGO, SAP
\param dBm power to set
\- return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_set_tx_power(tHalHandle hHal, uint8_t sessionId,
struct qdf_mac_addr pBSSId,
enum tQDF_ADAPTER_MODE dev_mode, int dBm)
{
cds_msg_t msg;
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 != cds_mq_post_message(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_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;
tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
if (!session) {
sms_log(mac_ctx, LOGE, FL("session %d not found"),
session_id);
sme_release_global_lock(&mac_ctx->sme);
return status;
}
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 = cds_send_mb_message_to_mac(msg);
}
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_set_tm_level
\brief Set Thermal Mitigation Level to RIVA
\param hHal - The handle returned by mac_open.
\param newTMLevel - new Thermal Mitigation Level
\param 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);
cds_msg_t cds_message;
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 */
cds_message.bodyptr = setTmLevelReq;
cds_message.type = WMA_SET_TM_LEVEL_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/*---------------------------------------------------------------------------
\brief sme_feature_caps_exchange() - SME interface to exchange capabilities between
Host and FW.
\param 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));
}
/*---------------------------------------------------------------------------
\brief sme_disable_feature_capablity() - SME interface to disable Active mode offload capablity
in Host.
\param hHal - HAL handle for device
\return NONE
---------------------------------------------------------------------------*/
void sme_disable_feature_capablity(uint8_t feature_index)
{
}
/* ---------------------------------------------------------------------------
\fn sme_reset_power_values_for5_g
\brief Reset the power values for 5G band with default power values.
\param 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);
csr_apply_power2_current(pMac); /* Store the channel+power info in the global place: Cfg */
}
/* ---------------------------------------------------------------------------
\fn sme_update_roam_prefer5_g_hz
\brief enable/disable Roam prefer 5G runtime option
This function is called through dynamic setConfig callback function
to configure the Roam prefer 5G runtime option
\param hHal - HAL handle for device
\param 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_INFO,
"%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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_roam_intra_band
\brief enable/disable Intra band roaming
This function is called through dynamic setConfig callback function
to configure the intra band roaming
\param hHal - HAL handle for device
\param 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_INFO,
"%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;
}
/* ---------------------------------------------------------------------------
\fn sme_update_roam_scan_n_probes
\brief function to update roam scan N probes
This function is called through dynamic setConfig callback function
to update roam scan N probes
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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_INFO,
"%s: gRoamScanNProbes is changed from %d to %d",
__func__, pMac->roam.configParam.nProbes, nProbes);
pMac->roam.configParam.nProbes = nProbes;
sme_release_global_lock(&pMac->sme);
}
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_NPROBES_CHANGED);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_update_roam_scan_home_away_time
\brief function to update roam scan Home away time
This function is called through dynamic setConfig callback function
to update roam scan home away time
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param nRoamScanAwayTime Scan home away time
\param 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_INFO,
"%s: gRoamScanHomeAwayTime is changed from %d to %d",
__func__,
pMac->roam.configParam.nRoamScanHomeAwayTime,
nRoamScanHomeAwayTime);
pMac->roam.configParam.nRoamScanHomeAwayTime =
nRoamScanHomeAwayTime;
sme_release_global_lock(&pMac->sme);
}
if (pMac->roam.configParam.isRoamOffloadScanEnabled && bSendOffloadCmd) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_HOME_AWAY_TIME_CHANGED);
}
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;
sms_log(mac_ctx, LOGE, FL(" Set Channel %d "), channel);
channel_state =
cds_get_channel_state(channel);
if (CHANNEL_STATE_DISABLE == channel_state) {
sms_log(mac_ctx, LOGE, FL(" 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_roam_intra_band
\brief get Intra band roaming
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_roam_scan_n_probes
\brief get N Probes
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_roam_scan_home_away_time
\brief get Roam scan home away time
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_update_roam_rssi_diff
\brief Update RoamRssiDiff
This function is called through dynamic setConfig callback function
to configure RoamRssiDiff
Usage: adb shell iwpriv wlan0 setConfig RoamRssiDiff=[0 .. 125]
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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;
sme_release_global_lock(&pMac->sme);
}
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_RSSI_DIFF_CHANGED);
}
return status;
}
/*--------------------------------------------------------------------------
\brief 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
\param 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.
\sa
--------------------------------------------------------------------------*/
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_INFO,
"%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;
}
/* ---------------------------------------------------------------------------
\fn sme_update_wes_mode
\brief Update WES Mode
This function is called through dynamic setConfig callback function
to configure isWESModeEnabled
\param hHal - HAL handle for device
\param isWESModeEnabled - WES mode
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_roam_scan_control
\brief 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
\param hHal - HAL handle for device
\param 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;
}
/*--------------------------------------------------------------------------
\brief 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
\param hHal - The handle returned by mac_open.
\param sessionId - Session Identifier
\return QDF_STATUS_SUCCESS - SME update isFastRoamIniFeatureEnabled config
successfully.
Other status means SME is failed to update isFastRoamIniFeatureEnabled.
\sa
--------------------------------------------------------------------------*/
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);
tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
QDF_STATUS status;
if (!mac_ctx->roam.configParam.isFastRoamIniFeatureEnabled) {
sms_log(mac_ctx, LOGE, FL("Fast roam is disabled through ini"));
if (!is_fast_roam_enabled)
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
if (is_fast_roam_enabled && session && session->pCurRoamProfile)
session->pCurRoamProfile->do_not_roam = false;
status = csr_neighbor_roam_update_fast_roaming_enabled(mac_ctx,
session_id, is_fast_roam_enabled);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac_ctx, LOGE,
FL("csr_neighbor_roam_update_fast_roaming_enabled failed"));
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/*--------------------------------------------------------------------------
\brief 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
\param 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.
\sa
--------------------------------------------------------------------------*/
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_INFO,
"%s: MAWCEnabled is changed from %d to %d", __func__,
pMac->roam.configParam.MAWCEnabled, MAWCEnabled);
pMac->roam.configParam.MAWCEnabled = MAWCEnabled;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*--------------------------------------------------------------------------
\brief sme_stop_roaming() - Stop roaming for a given sessionId
This is a synchronous call
\param hHal - The handle returned by mac_open
\param sessionId - Session Identifier
\return QDF_STATUS_SUCCESS on success
Other status on failure
\sa
--------------------------------------------------------------------------*/
QDF_STATUS sme_stop_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_STOP,
reason);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/*--------------------------------------------------------------------------
\brief sme_start_roaming() - Start roaming for a given sessionId
This is a synchronous call
\param hHal - The handle returned by mac_open
\param sessionId - Session Identifier
\return QDF_STATUS_SUCCESS on success
Other status on failure
\sa
--------------------------------------------------------------------------*/
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;
}
/*--------------------------------------------------------------------------
\brief sme_update_enable_fast_roam_in_concurrency() - enable/disable LFR if
Concurrent session exists
This is a synchronuous call
\param hHal - The handle returned by mac_open.
\return QDF_STATUS_SUCCESS
Other status means SME is failed
\sa
--------------------------------------------------------------------------*/
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;
}
/*--------------------------------------------------------------------------
\brief sme_update_config_fw_rssi_monitoring() - enable/disable firmware RSSI
Monitoring at runtime
It is used at in the REG_DYNAMIC_VARIABLE macro definition of
fEnableFwRssiMonitoring.
This is a synchronous call
\param hHal - The handle returned by mac_open.
\return QDF_STATUS_SUCCESS - SME update fEnableFwRssiMonitoring.
config successfully.
Other status means SME is failed to update fEnableFwRssiMonitoring.
\sa
--------------------------------------------------------------------------*/
QDF_STATUS sme_update_config_fw_rssi_monitoring(tHalHandle hHal,
bool fEnableFwRssiMonitoring)
{
QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
if (sme_cfg_set_int (hHal, WNI_CFG_PS_ENABLE_RSSI_MONITOR,
fEnableFwRssiMonitoring) == QDF_STATUS_E_FAILURE) {
qdf_ret_status = QDF_STATUS_E_FAILURE;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"Could not pass on WNI_CFG_PS_RSSI_MONITOR to CFG");
}
return qdf_ret_status;
}
/* ---------------------------------------------------------------------------
\fn sme_set_roam_opportunistic_scan_threshold_diff
\brief Update Opportunistic Scan threshold diff
This function is called through dynamic setConfig callback function
to configure nOpportunisticThresholdDiff
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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;
}
/*--------------------------------------------------------------------------
\fn sme_get_roam_opportunistic_scan_threshold_diff()
\brief gets Opportunistic Scan threshold diff
This is a synchronous call
\param hHal - The handle returned by mac_open
\return uint8_t - nOpportunisticThresholdDiff
\sa
--------------------------------------------------------------------------*/
uint8_t sme_get_roam_opportunistic_scan_threshold_diff(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.
nOpportunisticThresholdDiff;
}
/* ---------------------------------------------------------------------------
\fn sme_set_roam_rescan_rssi_diff
\brief Update roam rescan rssi diff
This function is called through dynamic setConfig callback function
to configure nRoamRescanRssiDiff
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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;
}
/*--------------------------------------------------------------------------
\fn sme_get_roam_rescan_rssi_diff
\brief gets roam rescan rssi diff
This is a synchronous call
\param hHal - The handle returned by mac_open
\return int8_t - nRoamRescanRssiDiff
\sa
--------------------------------------------------------------------------*/
uint8_t sme_get_roam_rescan_rssi_diff(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.nRoamRescanRssiDiff;
}
/* ---------------------------------------------------------------------------
\fn sme_set_roam_bmiss_first_bcnt
\brief Update Roam count for first beacon miss
This function is called through dynamic setConfig callback function
to configure nRoamBmissFirstBcnt
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_roam_bmiss_first_bcnt
\brief get neighbor roam beacon miss first count
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_roam_bmiss_final_bcnt
\brief Update Roam count for final beacon miss
This function is called through dynamic setConfig callback function
to configure nRoamBmissFinalBcnt
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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;
}
/*--------------------------------------------------------------------------
\fn sme_get_roam_bmiss_final_bcnt
\brief gets Roam count for final beacon miss
This is a synchronous call
\param hHal - The handle returned by mac_open
\return uint8_t - nRoamBmissFinalBcnt
\sa
--------------------------------------------------------------------------*/
uint8_t sme_get_roam_bmiss_final_bcnt(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.nRoamBmissFinalBcnt;
}
/* ---------------------------------------------------------------------------
\fn sme_set_roam_beacon_rssi_weight
\brief Update Roam beacon rssi weight
This function is called through dynamic setConfig callback function
to configure nRoamBeaconRssiWeight
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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;
}
/*--------------------------------------------------------------------------
\fn sme_get_roam_beacon_rssi_weight
\brief gets Roam beacon rssi weight
This is a synchronous call
\param hHal - The handle returned by mac_open
\return uint8_t - nRoamBeaconRssiWeight
\sa
--------------------------------------------------------------------------*/
uint8_t sme_get_roam_beacon_rssi_weight(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.nRoamBeaconRssiWeight;
}
/*--------------------------------------------------------------------------
\brief sme_set_neighbor_lookup_rssi_threshold() - update neighbor lookup
rssi threshold
This is a synchronous call
\param hHal - The handle returned by mac_open.
\param sessionId - Session Identifier
\return QDF_STATUS_SUCCESS - SME update config successful.
Other status means SME is failed to update
\sa
--------------------------------------------------------------------------*/
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;
}
/*--------------------------------------------------------------------------
\brief sme_set_delay_before_vdev_stop() - update delay before VDEV_STOP
This is a synchronous call
\param hal - The handle returned by macOpen.
\param session_id - Session Identifier
\param delay_before_vdev_stop - value to be set
\return QDF_STATUS_SUCCESS - SME update config successful.
Other status means SME is failed to update
\sa
--------------------------------------------------------------------------*/
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,
FL("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;
}
/*--------------------------------------------------------------------------
\brief sme_get_neighbor_lookup_rssi_threshold() - get neighbor lookup
rssi threshold
This is a synchronous call
\param hHal - The handle returned by mac_open.
\return QDF_STATUS_SUCCESS - SME update config successful.
Other status means SME is failed to update
\sa
--------------------------------------------------------------------------*/
uint8_t sme_get_neighbor_lookup_rssi_threshold(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.
nNeighborLookupRssiThreshold;
}
/*--------------------------------------------------------------------------
\brief sme_set_neighbor_scan_refresh_period() - set neighbor scan results
refresh period
This is a synchronous call
\param hHal - The handle returned by mac_open.
\param sessionId - Session Identifier
\return QDF_STATUS_SUCCESS - SME update config successful.
Other status means SME is failed to update
\sa
--------------------------------------------------------------------------*/
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;
tCsrNeighborRoamConfig *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;
sme_release_global_lock(&pMac->sme);
}
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED);
}
return status;
}
/*--------------------------------------------------------------------------
\brief 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
\param hHal - The handle returned by mac_open.
\return QDF_STATUS_SUCCESS - SME update config successfully.
Other status means SME is failed to update.
\sa
--------------------------------------------------------------------------*/
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,
FL
("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;
}
/*--------------------------------------------------------------------------
\brief 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
\sa
--------------------------------------------------------------------------*/
uint16_t sme_get_neighbor_scan_refresh_period(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.
nNeighborResultsRefreshPeriod;
}
/*--------------------------------------------------------------------------
\brief sme_get_empty_scan_refresh_period() - get empty scan refresh period
This is a synchronuous call
\param hHal - The handle returned by mac_open.
\return QDF_STATUS_SUCCESS - SME update config successful.
Other status means SME is failed to update
\sa
--------------------------------------------------------------------------*/
uint16_t sme_get_empty_scan_refresh_period(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.neighborRoamConfig.
nEmptyScanRefreshPeriod;
}
/* ---------------------------------------------------------------------------
\fn sme_update_empty_scan_refresh_period
\brief Update nEmptyScanRefreshPeriod
This function is called through dynamic setConfig callback function
to configure nEmptyScanRefreshPeriod
Usage: adb shell iwpriv wlan0 setConfig
nEmptyScanRefreshPeriod=[0 .. 60]
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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;
tCsrNeighborRoamConfig *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;
sme_release_global_lock(&pMac->sme);
}
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_EMPTY_SCAN_REF_PERIOD_CHANGED);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_set_neighbor_scan_min_chan_time
\brief Update nNeighborScanMinChanTime
This function is called through dynamic setConfig callback function
to configure gNeighborScanChannelMinTime
Usage: adb shell iwpriv wlan0 setConfig
gNeighborScanChannelMinTime=[0 .. 60]
\param hHal - HAL handle for device
\param nNeighborScanMinChanTime - Channel minimum dwell time
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_neighbor_scan_max_chan_time
\brief Update nNeighborScanMaxChanTime
This function is called through dynamic setConfig callback function
to configure gNeighborScanChannelMaxTime
Usage: adb shell iwpriv wlan0 setConfig
gNeighborScanChannelMaxTime=[0 .. 60]
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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;
tCsrNeighborRoamConfig *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;
sme_release_global_lock(&pMac->sme);
}
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_SCAN_CH_TIME_CHANGED);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_get_neighbor_scan_min_chan_time
\brief get neighbor scan min channel time
\param hHal - The handle returned by mac_open.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_neighbor_roam_state
\brief get neighbor roam state
\param hHal - The handle returned by mac_open.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_current_roam_state
\brief get current roam state
\param hHal - The handle returned by mac_open.
\param 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];
}
/* ---------------------------------------------------------------------------
\fn sme_get_current_roam_sub_state
\brief get neighbor roam sub state
\param hHal - The handle returned by mac_open.
\param 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];
}
/* ---------------------------------------------------------------------------
\fn sme_get_lim_sme_state
\brief get Lim Sme state
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_lim_mlm_state
\brief get Lim Mlm state
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_is_lim_session_valid
\brief is Lim session valid
\param hHal - The handle returned by mac_open.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_lim_sme_session_state
\brief get Lim Sme session state
\param hHal - The handle returned by mac_open.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_lim_mlm_session_state
\brief get Lim Mlm session state
\param hHal - The handle returned by mac_open.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_get_neighbor_scan_max_chan_time
\brief get neighbor scan max channel time
\param hHal - The handle returned by mac_open.
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_neighbor_scan_period
\brief Update nNeighborScanPeriod
This function is called through dynamic setConfig callback function
to configure nNeighborScanPeriod
Usage: adb shell iwpriv wlan0 setConfig
nNeighborScanPeriod=[0 .. 1000]
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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;
tCsrNeighborRoamConfig *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;
sme_release_global_lock(&pMac->sme);
}
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_SCAN_HOME_TIME_CHANGED);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_get_neighbor_scan_period
\brief get neighbor scan period
\param hHal - The handle returned by mac_open.
\param 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;
}
/*--------------------------------------------------------------------------
\brief sme_get_roam_rssi_diff() - get Roam rssi diff
This is a synchronous call
\param hHal - The handle returned by mac_open.
\return uint16_t - Rssi diff value
\sa
--------------------------------------------------------------------------*/
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)) {
if (pMac->roam.configParam.isRoamOffloadScanEnabled)
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_CHANNEL_LIST_CHANGED);
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,
FL("LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d"),
newChannelList, oldChannelList,
pMac->roam.neighborRoamInfo[sessionId].neighborRoamState);
sme_release_global_lock(&pMac->sme);
if (pMac->roam.configParam.isRoamOffloadScanEnabled)
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_CHANNEL_LIST_CHANGED);
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;
}
/*--------------------------------------------------------------------------
\brief sme_get_is_ese_feature_enabled() - get ESE feature enabled or not
This is a synchronuous call
\param 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)
\sa
--------------------------------------------------------------------------*/
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
}
/*--------------------------------------------------------------------------
\brief sme_get_wes_mode() - get WES Mode
This is a synchronous call
\param hHal - The handle returned by mac_open
\return uint8_t - WES Mode Enabled(1)/Disabled(0)
\sa
--------------------------------------------------------------------------*/
bool sme_get_wes_mode(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.isWESModeEnabled;
}
/*--------------------------------------------------------------------------
\brief sme_get_roam_scan_control() - get scan control
This is a synchronous call
\param hHal - The handle returned by mac_open.
\return bool - Enabled(1)/Disabled(0)
\sa
--------------------------------------------------------------------------*/
bool sme_get_roam_scan_control(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.nRoamScanControl;
}
/*--------------------------------------------------------------------------
\brief sme_get_is_lfr_feature_enabled() - get LFR feature enabled or not
This is a synchronuous call
\param hHal - The handle returned by mac_open.
\return true (1) - if the feature is enabled
false (0) - if feature is disabled (compile or runtime)
\sa
--------------------------------------------------------------------------*/
bool sme_get_is_lfr_feature_enabled(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.isFastRoamIniFeatureEnabled;
}
/*--------------------------------------------------------------------------
\brief sme_get_is_ft_feature_enabled() - get FT feature enabled or not
This is a synchronuous call
\param hHal - The handle returned by mac_open.
\return true (1) - if the feature is enabled
false (0) - if feature is disabled (compile or runtime)
\sa
--------------------------------------------------------------------------*/
bool sme_get_is_ft_feature_enabled(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.isFastTransitionEnabled;
}
/* ---------------------------------------------------------------------------
\fn sme_is_feature_supported_by_fw
\brief Check if an feature is enabled by FW
\param feattEnumValue - Enumeration value from placeHolderInCapBitmap
\- return 1/0 (true/false)
-------------------------------------------------------------------------*/
uint8_t sme_is_feature_supported_by_fw(uint8_t featEnumValue)
{
return IS_FEATURE_SUPPORTED_BY_FW(featEnumValue);
}
#ifdef FEATURE_WLAN_TDLS
/* ---------------------------------------------------------------------------
\fn sme_send_tdls_link_establish_params
\brief API to send TDLS Peer Link Establishment Parameters.
\param peerMac - peer's Mac Adress.
\param tdlsLinkEstablishParams - TDLS Peer Link Establishment Parameters
\- return QDF_STATUS_SUCCES
-------------------------------------------------------------------------*/
QDF_STATUS sme_send_tdls_link_establish_params(tHalHandle hHal,
uint8_t sessionId,
const tSirMacAddr peerMac,
tCsrTdlsLinkEstablishParams *
tdlsLinkEstablishParams)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_TDLS_LINK_ESTABLISH_PARAM,
sessionId,
tdlsLinkEstablishParams->isOffChannelSupported));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_tdls_send_link_establish_params(hHal, sessionId,
peerMac, tdlsLinkEstablishParams);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_send_tdls_mgmt_frame
\brief API to send TDLS management frames.
\param peerMac - peer's Mac Adress.
\param frame_type - Type of TDLS mgmt frame to be sent.
\param dialog - dialog token used in the frame.
\param status - status to be incuded in the frame.
\param peerCapability - peer cpabilities
\param buf - additional IEs to be included
\param len - lenght of additional Ies
\param responder - Tdls request type
\- return QDF_STATUS_SUCCES
-------------------------------------------------------------------------*/
QDF_STATUS sme_send_tdls_mgmt_frame(tHalHandle hHal, uint8_t sessionId,
const tSirMacAddr peerMac,
uint8_t frame_type,
uint8_t dialog, uint16_t statusCode,
uint32_t peerCapability, uint8_t *buf,
uint8_t len, uint8_t responder)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tCsrTdlsSendMgmt sendTdlsReq = { {0} };
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_TDLS_SEND_MGMT_FRAME,
sessionId, statusCode));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
qdf_mem_copy(sendTdlsReq.peerMac, peerMac, sizeof(tSirMacAddr));
sendTdlsReq.frameType = frame_type;
sendTdlsReq.buf = buf;
sendTdlsReq.len = len;
sendTdlsReq.dialog = dialog;
sendTdlsReq.statusCode = statusCode;
sendTdlsReq.responder = responder;
sendTdlsReq.peerCapability = peerCapability;
status = csr_tdls_send_mgmt_req(hHal, sessionId, &sendTdlsReq);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_change_tdls_peer_sta
\brief API to Update TDLS peer sta parameters.
\param peerMac - peer's Mac Adress.
\param staParams - Peer Station Parameters
\- return QDF_STATUS_SUCCES
-------------------------------------------------------------------------*/
QDF_STATUS sme_change_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId,
const tSirMacAddr peerMac,
tCsrStaParams *pstaParams)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pstaParams) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s :pstaParams is NULL", __func__);
return QDF_STATUS_E_FAILURE;
}
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_TDLS_CHANGE_PEER_STA,
sessionId, pstaParams->capability));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_tdls_change_peer_sta(hHal, sessionId, peerMac,
pstaParams);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_add_tdls_peer_sta
\brief API to Add TDLS peer sta entry.
\param peerMac - peer's Mac Adress.
\- return QDF_STATUS_SUCCES
-------------------------------------------------------------------------*/
QDF_STATUS sme_add_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId,
const tSirMacAddr peerMac)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_TDLS_ADD_PEER_STA,
sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_tdls_add_peer_sta(hHal, sessionId, peerMac);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_delete_tdls_peer_sta
\brief API to Delete TDLS peer sta entry.
\param peerMac - peer's Mac Adress.
\- return QDF_STATUS_SUCCES
-------------------------------------------------------------------------*/
QDF_STATUS sme_delete_tdls_peer_sta(tHalHandle hHal, uint8_t sessionId,
const tSirMacAddr peerMac)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_TDLS_DEL_PEER_STA,
sessionId, 0));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_tdls_del_peer_sta(hHal, sessionId, peerMac);
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_set_tdls_power_save_prohibited
\API to set/reset the is_tdls_power_save_prohibited.
\- return void
-------------------------------------------------------------------------*/
void sme_set_tdls_power_save_prohibited(tHalHandle hHal, uint32_t sessionId,
bool val)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct ps_global_info *ps_global_info = &pMac->sme.ps_global_info;
struct ps_params *ps_param = &ps_global_info->ps_params[sessionId];
ps_param->is_tdls_power_save_prohibited = val;
return;
}
/* ---------------------------------------------------------------------------
\fn sme_update_fw_tdls_state
\brief
SME will send message to WMA to set TDLS state in f/w
\param
hHal - The handle returned by mac_open
psmeTdlsParams - TDLS state info to update in f/w
useSmeLock - Need to acquire SME Global Lock before state update or not
\return QDF_STATUS
--------------------------------------------------------------------------- */
QDF_STATUS sme_update_fw_tdls_state(tHalHandle hHal, void *psmeTdlsParams,
bool useSmeLock)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = NULL;
cds_msg_t cds_message;
pMac = PMAC_STRUCT(hHal);
if (NULL == pMac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("pMac is Null"));
return QDF_STATUS_E_FAILURE;
}
/* only acquire sme global lock before state update if asked to */
if (useSmeLock) {
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS != status)
return status;
}
/* serialize the req through MC thread */
cds_message.bodyptr = psmeTdlsParams;
cds_message.type = WMA_UPDATE_FW_TDLS_STATE;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
/* release the lock if it was acquired */
if (useSmeLock)
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_update_tdls_peer_state() - to update the state of TDLS peer
* @hHal: The handle returned by mac_open
* @peerStateParams: TDLS Peer state info to update in f/w
*
* SME will send message to WMA to set TDLS Peer state in f/w
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_update_tdls_peer_state(tHalHandle hHal,
tSmeTdlsPeerStateParams *peerStateParams)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tTdlsPeerStateParams *pTdlsPeerStateParams = NULL;
tTdlsPeerCapParams *peer_cap = NULL;
cds_msg_t cds_message;
uint8_t num;
uint8_t peer_chan_len;
uint8_t chanId;
uint8_t i;
status = sme_acquire_global_lock(&pMac->sme);
if (!QDF_IS_STATUS_SUCCESS(status))
return status;
pTdlsPeerStateParams = qdf_mem_malloc(sizeof(*pTdlsPeerStateParams));
if (NULL == pTdlsPeerStateParams) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("failed to allocate mem for tdls peer state param"));
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(&pTdlsPeerStateParams->peerMacAddr,
&peerStateParams->peerMacAddr, sizeof(tSirMacAddr));
pTdlsPeerStateParams->vdevId = peerStateParams->vdevId;
pTdlsPeerStateParams->peerState = peerStateParams->peerState;
switch (peerStateParams->peerState) {
case eSME_TDLS_PEER_STATE_PEERING:
pTdlsPeerStateParams->peerState =
WMA_TDLS_PEER_STATE_PEERING;
break;
case eSME_TDLS_PEER_STATE_CONNECTED:
pTdlsPeerStateParams->peerState =
WMA_TDLS_PEER_STATE_CONNECTED;
break;
case eSME_TDLS_PEER_STATE_TEARDOWN:
pTdlsPeerStateParams->peerState =
WMA_TDLS_PEER_STATE_TEARDOWN;
break;
case eSME_TDLS_PEER_ADD_MAC_ADDR:
pTdlsPeerStateParams->peerState = WMA_TDLS_PEER_ADD_MAC_ADDR;
break;
case eSME_TDLS_PEER_REMOVE_MAC_ADDR:
pTdlsPeerStateParams->peerState = WMA_TDLS_PEER_REMOVE_MAC_ADDR;
break;
default:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("invalid peer state param (%d)"),
peerStateParams->peerState);
goto error_return;
}
peer_cap = &(pTdlsPeerStateParams->peerCap);
peer_cap->isPeerResponder =
peerStateParams->peerCap.isPeerResponder;
peer_cap->peerUapsdQueue =
peerStateParams->peerCap.peerUapsdQueue;
peer_cap->peerMaxSp =
peerStateParams->peerCap.peerMaxSp;
peer_cap->peerBuffStaSupport =
peerStateParams->peerCap.peerBuffStaSupport;
peer_cap->peerOffChanSupport =
peerStateParams->peerCap.peerOffChanSupport;
peer_cap->peerCurrOperClass =
peerStateParams->peerCap.peerCurrOperClass;
peer_cap->selfCurrOperClass =
peerStateParams->peerCap.selfCurrOperClass;
num = 0;
peer_chan_len = peerStateParams->peerCap.peerChanLen;
if (peer_chan_len >= 0 &&
peer_chan_len <= SME_TDLS_MAX_SUPP_CHANNELS) {
for (i = 0; i < peerStateParams->peerCap.peerChanLen; i++) {
chanId = peerStateParams->peerCap.peerChan[i];
if (csr_roam_is_channel_valid(pMac, chanId) &&
!(cds_get_channel_state(chanId) ==
CHANNEL_STATE_DFS) &&
!cds_is_dsrc_channel(cds_chan_to_freq(chanId))) {
peer_cap->peerChan[num].chanId = chanId;
peer_cap->peerChan[num].pwr =
csr_get_cfg_max_tx_power(pMac, chanId);
peer_cap->peerChan[num].dfsSet = false;
num++;
}
}
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("invalid peer channel len (%d)"),
peer_chan_len);
goto error_return;
}
peer_cap->peerChanLen = num;
peer_cap->peerOperClassLen =
peerStateParams->peerCap.peerOperClassLen;
for (i = 0; i < HAL_TDLS_MAX_SUPP_OPER_CLASSES; i++) {
peer_cap->peerOperClass[i] =
peerStateParams->peerCap.peerOperClass[i];
}
peer_cap->prefOffChanNum =
peerStateParams->peerCap.prefOffChanNum;
peer_cap->prefOffChanBandwidth =
peerStateParams->peerCap.prefOffChanBandwidth;
peer_cap->opClassForPrefOffChan =
peerStateParams->peerCap.opClassForPrefOffChan;
cds_message.type = WMA_UPDATE_TDLS_PEER_STATE;
cds_message.reserved = 0;
cds_message.bodyptr = pTdlsPeerStateParams;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("cds_mq_post_message failed "));
goto error_return;
} else {
goto success_return;
}
error_return:
status = QDF_STATUS_E_FAILURE;
qdf_mem_free(pTdlsPeerStateParams);
success_return:
sme_release_global_lock(&pMac->sme);
return status;
}
/**
* sme_send_tdls_chan_switch_req() - send tdls channel switch request
* @hal: UMAC handler
* @ch_switch_params: Pointer to the chan switch parameter structure
*
* API to set tdls channel switch parameters.
*
* Return: QDF_STATUS_SUCCESS on success; another QDF_STATUS_** code otherwise
*/
QDF_STATUS sme_send_tdls_chan_switch_req(tHalHandle hal,
sme_tdls_chan_switch_params *ch_switch_params)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
tdls_chan_switch_params *chan_switch_params = NULL;
cds_msg_t cds_message;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_TDLS_CHAN_SWITCH_REQ,
NO_SESSION, ch_switch_params->tdls_off_channel));
status = sme_acquire_global_lock(&mac->sme);
if (QDF_STATUS_SUCCESS != status)
return status;
chan_switch_params = qdf_mem_malloc(sizeof(*chan_switch_params));
if (NULL == chan_switch_params) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("fail to alloc mem for tdls chan switch param"));
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_FAILURE;
}
switch (ch_switch_params->tdls_off_ch_mode) {
case ENABLE_CHANSWITCH:
chan_switch_params->tdls_sw_mode = WMA_TDLS_ENABLE_OFFCHANNEL;
break;
case DISABLE_CHANSWITCH:
chan_switch_params->tdls_sw_mode = WMA_TDLS_DISABLE_OFFCHANNEL;
break;
default:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("invalid off channel command (%d)"),
ch_switch_params->tdls_off_ch_mode);
qdf_mem_free(chan_switch_params);
sme_release_global_lock(&mac->sme);
return QDF_STATUS_E_FAILURE;
}
qdf_mem_copy(&chan_switch_params->peer_mac_addr,
&ch_switch_params->peer_mac_addr, sizeof(tSirMacAddr));
chan_switch_params->vdev_id = ch_switch_params->vdev_id;
chan_switch_params->tdls_off_ch = ch_switch_params->tdls_off_channel;
chan_switch_params->tdls_off_ch_bw_offset =
ch_switch_params->tdls_off_ch_bw_offset;
chan_switch_params->is_responder = ch_switch_params->is_responder;
chan_switch_params->oper_class = ch_switch_params->opclass;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("Country Code=%s, Req offset=%d, Selected Operate Class=%d"),
mac->scan.countryCodeCurrent,
chan_switch_params->tdls_off_ch_bw_offset,
chan_switch_params->oper_class);
cds_message.type = WMA_TDLS_SET_OFFCHAN_MODE;
cds_message.reserved = 0;
cds_message.bodyptr = chan_switch_params;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Message Post failed status=%d"),
qdf_status);
qdf_mem_free(chan_switch_params);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
return status;
}
#endif /* FEATURE_WLAN_TDLS */
QDF_STATUS sme_get_link_speed(tHalHandle hHal, tSirLinkSpeedInfo *lsReq,
void *plsContext,
void (*pCallbackfn)(tSirLinkSpeedInfo *indParam,
void *pContext))
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
if ((NULL == pCallbackfn) &&
(NULL == pMac->sme.pLinkSpeedIndCb)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Indication Call back did not registered",
__func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
} else if (NULL != pCallbackfn) {
pMac->sme.pLinkSpeedCbContext = plsContext;
pMac->sme.pLinkSpeedIndCb = pCallbackfn;
}
/* serialize the req through MC thread */
cds_message.bodyptr = lsReq;
cds_message.type = WMA_GET_LINK_SPEED;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post Link Speed msg fail", __func__);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->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)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
"SSR level is changed %d", enableSSR);
/* not serializing this messsage, as this is only going
* to set a variable in WMA/WDI
*/
WMA_SetEnableSSR(enableSSR);
sme_release_global_lock(&pMac->sme);
}
return;
}
QDF_STATUS sme_check_ch_in_band(tpAniSirGlobal mac_ctx, uint8_t start_ch,
uint8_t ch_cnt)
{
uint8_t i;
for (i = 0; i < ch_cnt; i++) {
if (QDF_STATUS_SUCCESS != csr_is_valid_channel(mac_ctx,
(start_ch + i*4)))
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
/*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);
}
/*--------------------------------------------------------------------------
\brief sme_set_curr_device_mode() - Sets the current operating device mode.
\param hHal - The handle returned by mac_open.
\param currDeviceMode - Current operating device mode.
--------------------------------------------------------------------------*/
void sme_set_curr_device_mode(tHalHandle hHal,
enum tQDF_ADAPTER_MODE currDeviceMode)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pMac->sme.currDeviceMode = currDeviceMode;
return;
}
/*--------------------------------------------------------------------------
\brief sme_handoff_request() - a wrapper function to Request a handoff
from CSR.
This is a synchronous call
\param hHal - The handle returned by mac_open
\param sessionId - Session Identifier
\param 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.
\sa
--------------------------------------------------------------------------*/
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_INFO,
"%s: invoked", __func__);
status = csr_handoff_request(pMac, sessionId, pHandoffInfo);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#ifdef IPA_OFFLOAD
/* ---------------------------------------------------------------------------
\fn sme_ipa_offload_enable_disable
\brief API to enable/disable IPA offload
\param hal - The handle returned by macOpen.
\param session_id - Session Identifier
\param request - Pointer to the offload request.
\return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_ipa_offload_enable_disable(tHalHandle hal, uint8_t session_id,
struct sir_ipa_offload_enable_disable *request)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hal);
QDF_STATUS status = QDF_STATUS_E_FAILURE;
struct sir_ipa_offload_enable_disable *request_buf;
cds_msg_t msg;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
request_buf = qdf_mem_malloc(sizeof(*request_buf));
if (NULL == request_buf) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to allocate memory for IPA_OFFLOAD_ENABLE_DISABLE"));
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
request_buf->offload_type = request->offload_type;
request_buf->vdev_id = request->vdev_id;
request_buf->enable = request->enable;
msg.type = WMA_IPA_OFFLOAD_ENABLE_DISABLE;
msg.reserved = 0;
msg.bodyptr = request_buf;
if (!QDF_IS_STATUS_SUCCESS(
cds_mq_post_message(CDS_MQ_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post WMA_IPA_OFFLOAD_ENABLE_DISABLE message to WMA"));
qdf_mem_free(request_buf);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return QDF_STATUS_SUCCESS;
}
#endif /* IPA_OFFLOAD */
/*
* 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;
}
#ifdef FEATURE_WLAN_LPHB
/* ---------------------------------------------------------------------------
\fn sme_lphb_config_req
\API to make configuration LPHB within FW.
\param hHal - The handle returned by mac_open
\param lphdReq - LPHB request argument by client
\param pCallbackfn - LPHB timeout notification callback function pointer
\- return Configuration message posting status, SUCCESS or Fail
-------------------------------------------------------------------------*/
QDF_STATUS sme_lphb_config_req
(tHalHandle hHal,
tSirLPHBReq *lphdReq,
void (*pCallbackfn)(void *pHddCtx, tSirLPHBInd * indParam)
) {
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
MTRACE(qdf_trace(QDF_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_LPHB_CONFIG_REQ,
NO_SESSION, lphdReq->cmd));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
if ((LPHB_SET_EN_PARAMS_INDID == lphdReq->cmd) &&
(NULL == pCallbackfn) && (NULL == pMac->sme.pLphbIndCb)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Indication Call back did not registered",
__func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_FAILURE;
} else if (NULL != pCallbackfn) {
pMac->sme.pLphbIndCb = pCallbackfn;
}
/* serialize the req through MC thread */
cds_message.bodyptr = lphdReq;
cds_message.type = WMA_LPHB_CONF_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Post Config LPHB MSG fail", __func__);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif /* FEATURE_WLAN_LPHB */
/*--------------------------------------------------------------------------
\brief sme_enable_disable_split_scan() - a wrapper function to set the split
scan parameter.
This is a synchronous call
\param hHal - The handle returned by mac_open
\return NONE.
\sa
--------------------------------------------------------------------------*/
void sme_enable_disable_split_scan(tHalHandle hHal, uint8_t nNumStaChan,
uint8_t nNumP2PChan)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pMac->roam.configParam.nNumStaChanCombinedConc = nNumStaChan;
pMac->roam.configParam.nNumP2PChanCombinedConc = nNumP2PChan;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"%s: SCAN nNumStaChanCombinedConc : %d,"
"nNumP2PChanCombinedConc : %d ",
__func__, nNumStaChan, nNumP2PChan);
return;
}
/**
* 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;
cds_msg_t msg;
sms_log(mac, LOG1, FL("enter"));
req_msg = qdf_mem_malloc(sizeof(*req_msg));
if (!req_msg) {
sms_log(mac, LOGE, FL("memory allocation failed"));
return QDF_STATUS_E_NOMEM;
}
*req_msg = *addPeriodicTxPtrnParams;
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("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 = cds_mq_post_message(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("cds_mq_post_message 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;
cds_msg_t msg;
sms_log(mac, LOG1, FL("enter"));
req_msg = qdf_mem_malloc(sizeof(*req_msg));
if (!req_msg) {
sms_log(mac, LOGE, FL("memory allocation failed"));
return QDF_STATUS_E_NOMEM;
}
*req_msg = *delPeriodicTxPtrnParams;
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("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 = cds_mq_post_message(QDF_MODULE_ID_WMA, &msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("cds_mq_post_message failed!(err=%d)"),
status);
qdf_mem_free(req_msg);
}
sme_release_global_lock(&mac->sme);
return status;
}
/**
* 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);
cds_msg_t cds_message;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
sms_log(pMac, LOG1, FL("enable RMC"));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
cds_message.bodyptr = NULL;
cds_message.type = WMA_RMC_ENABLE_IND;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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);
cds_msg_t cds_message;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
sms_log(pMac, LOG1, FL("disable RMC"));
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
cds_message.bodyptr = NULL;
cds_message.type = WMA_RMC_DISABLE_IND;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
cds_message.bodyptr = NULL;
cds_message.type = WMA_RMC_ACTION_PERIOD_IND;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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_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);
cds_msg_t cds_message;
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;
cds_message.type = WMA_GET_IBSS_PEER_INFO_REQ;
cds_message.bodyptr = pIbssInfoReqParams;
cds_message.reserved = 0;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/* ---------------------------------------------------------------------------
\fn sme_send_cesium_enable_ind
\brief Used to send proprietary cesium enable indication to fw
\param hHal
\param 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);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
cds_message.bodyptr = NULL;
cds_message.type = WMA_IBSS_CESIUM_ENABLE_IND;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
void sme_get_command_q_status(tHalHandle hHal)
{
tSmeCmd *pTempCmd = NULL;
tListElem *pEntry;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
if (NULL == pMac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: pMac is NULL", __func__);
return;
}
pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
if (pEntry) {
pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
}
sms_log(pMac, LOGE, "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) */
sms_log(pMac, LOGE, "Currently smeCmdPendingList has %d commands",
csr_ll_count(&pMac->sme.smeCmdPendingList));
sms_log(pMac, LOGE, "Currently roamCmdPendingList has %d commands",
csr_ll_count(&pMac->roam.roamCmdPendingList));
return;
}
/**
* 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);
cds_msg_t 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 = cds_mq_post_message(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);
cds_msg_t 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 = cds_mq_post_message(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);
cds_msg_t 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 = cds_mq_post_message(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);
cds_msg_t 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 = cds_mq_post_message(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);
cds_msg_t 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 = cds_mq_post_message(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);
cds_msg_t 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 = cds_mq_post_message(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);
cds_msg_t 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 = cds_mq_post_message(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);
cds_msg_t 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 = cds_mq_post_message(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;
}
#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);
}
}
}
/**
* sme_save_active_cmd_stats() - To save active command stats
* @hHal: HAL context
*
* This routine is to save active command stats
*
* Return: None
*/
static void sme_save_active_cmd_stats(tHalHandle hHal)
{
tSmeCmd *pTempCmd = NULL;
tListElem *pEntry;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
uint8_t statidx = 0;
tActiveCmdStats *actv_cmd_stat = NULL;
if (NULL == pMac) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("pMac is NULL"));
return;
}
pEntry = csr_ll_peek_head(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
if (pEntry)
pTempCmd = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
if (!pTempCmd)
return;
if (eSmeCsrCommandMask & pTempCmd->command) {
statidx = g_self_recovery_stats.cmdStatsIndx;
actv_cmd_stat = &g_self_recovery_stats.activeCmdStats[statidx];
actv_cmd_stat->command = pTempCmd->command;
actv_cmd_stat->sessionId = pTempCmd->sessionId;
actv_cmd_stat->timestamp = cds_get_monotonic_boottime();
if (eSmeCommandRoam == pTempCmd->command)
actv_cmd_stat->reason = pTempCmd->u.roamCmd.roamReason;
else if (eSmeCommandScan == pTempCmd->command)
actv_cmd_stat->reason = pTempCmd->u.scanCmd.reason;
else
actv_cmd_stat->reason = 0xFF;
g_self_recovery_stats.cmdStatsIndx =
((g_self_recovery_stats.cmdStatsIndx + 1) &
(MAX_ACTIVE_CMD_STATS - 1));
}
return;
}
void active_list_cmd_timeout_handle(void *userData)
{
tHalHandle hal = (tHalHandle)userData;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
tListElem *entry;
tSmeCmd *temp_cmd = NULL;
if (NULL == mac_ctx) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: mac_ctx is null", __func__);
return;
}
/* Return if no cmd pending in active list as
* in this case we should not be here.
*/
if (0 == csr_ll_count(&mac_ctx->sme.smeCmdActiveList))
return;
sms_log(mac_ctx, LOGE,
FL("Active List command timeout Cmd List Count %d"),
csr_ll_count(&mac_ctx->sme.smeCmdActiveList));
sme_get_command_q_status(hal);
if (mac_ctx->roam.configParam.enable_fatal_event)
cds_flush_logs(WLAN_LOG_TYPE_FATAL,
WLAN_LOG_INDICATOR_HOST_DRIVER,
WLAN_LOG_REASON_SME_COMMAND_STUCK,
false,
mac_ctx->sme.enableSelfRecovery ? true : false);
else
qdf_trace_dump_all(mac_ctx, 0, 0, 500, 0);
entry = csr_ll_peek_head(&mac_ctx->sme.smeCmdActiveList,
LL_ACCESS_LOCK);
if (entry)
temp_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link);
/* Ignore if ROC took more than 120 sec */
if (temp_cmd && (eSmeCommandRemainOnChannel == temp_cmd->command))
return;
if (mac_ctx->sme.enableSelfRecovery) {
sme_save_active_cmd_stats(hal);
cds_trigger_recovery(false);
} else {
if (!mac_ctx->roam.configParam.enable_fatal_event &&
!(cds_is_load_or_unload_in_progress() ||
cds_is_driver_recovering()))
QDF_BUG(0);
}
}
QDF_STATUS sme_notify_modem_power_state(tHalHandle hHal, uint32_t value)
{
cds_msg_t msg;
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
(cds_mq_post_message(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)
{
cds_msg_t msg;
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
(cds_mq_post_message(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_INFO,
"%s: Notifed FW about OP mode: %d for staId=%d",
__func__, pHtOpMode->opMode, staId);
return QDF_STATUS_SUCCESS;
}
/* ---------------------------------------------------------------------------
\fn sme_set_ht2040_mode
\brief To update HT Operation beacon IE.
\param
\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;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"%s: Update HT operation beacon IE, channel_type=%d",
__func__, channel_type);
switch (channel_type) {
case eHT_CHAN_HT20:
cbMode = PHY_SINGLE_CHANNEL_CENTERED;
break;
case eHT_CHAN_HT40MINUS:
cbMode = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
break;
case eHT_CHAN_HT40PLUS:
cbMode = PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
break;
default:
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s:Error!!! Invalid HT20/40 mode !", __func__);
return QDF_STATUS_E_FAILURE;
}
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(void *cds_context,
tHalHandle hHal, uint32_t value)
{
void *wmaContext = cds_get_context(QDF_MODULE_ID_WMA);
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
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);
pMac->imps_enabled = false;
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;
}
if (value)
pMac->imps_enabled = true;
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);
tCsrRoamSession *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);
tCsrRoamSession *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;
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:
pSession->htConfig.ht_sgi20 = value;
break;
case WNI_CFG_HT_CAP_INFO_SHORT_GI_40MHZ:
pSession->htConfig.ht_sgi40 = value;
break;
}
return 0;
}
#define HT20_SHORT_GI_MCS7_RATE 722
/* ---------------------------------------------------------------------------
\fn sme_send_rate_update_ind
\brief API to Update rate
\param hHal - The handle returned by mac_open
\param 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;
cds_msg_t msg;
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 =
eHAL_TX_RATE_HT20 | eHAL_TX_RATE_SGI;
else if (rate_upd->reliableMcastDataRate ==
HT20_SHORT_GI_MCS7_RATE)
rate_upd->reliableMcastDataRateTxFlag =
eHAL_TX_RATE_HT20 | eHAL_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
(cds_mq_post_message(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able "
"to post WMA_SET_RMC_RATE_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;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
msg_len = sizeof(*msg);
msg = qdf_mem_malloc(msg_len);
if (!msg) {
sms_log(mac, LOGE,
"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;
sms_log(mac, LOG1, "sme_session_id %hu, access_policy %d", session_id,
access_policy);
status = cds_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)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct sme_short_retry_limit *srl;
cds_msg_t msg;
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;
}
sms_log(mac_ctx, LOG1, FL("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 = cds_mq_post_message(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)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct sme_long_retry_limit *lrl;
cds_msg_t msg;
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;
}
sms_log(mac_ctx, LOG1, FL("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 = cds_mq_post_message(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_INFO,
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].power);
SME_SET_CHANNEL_MAX_TX_POWER(*regInfo2,
pMac->scan.defaultPowerTable[i].power);
found = true;
break;
}
}
if (!found)
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
return status;
}
#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
/* ---------------------------------------------------------------------------
\fn sme_auto_shutdown_cb
\brief Used to plug in callback function for receiving auto shutdown evt
\param hHal
\param 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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_auto_shutdown_timer
\API to set auto shutdown timer value in FW.
\param hHal - The handle returned by mac_open
\param 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;
cds_msg_t cds_message;
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) {
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
"%s Request Buffer Alloc Fail", __func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
auto_sh_cmd->timer_val = timer_val;
/* serialize the req through MC thread */
cds_message.bodyptr = auto_sh_cmd;
cds_message.type = WMA_SET_AUTO_SHUTDOWN_TIMER_REQ;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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_INFO,
"%s: Posted Auto shutdown MSG", __func__);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif
#ifdef FEATURE_WLAN_CH_AVOID
/* ---------------------------------------------------------------------------
\fn sme_add_ch_avoid_callback
\brief Used to plug in callback function
Which notify channel may not be used with SAP or P2PGO mode.
Notification come from FW.
\param hHal
\param pCallbackfn : callback function pointer should be plugged in
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_add_ch_avoid_callback
(tHalHandle hHal, void (*pCallbackfn)(void *pAdapter, void *indParam)
) {
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Plug in CH AVOID CB", __func__);
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
if (NULL != pCallbackfn) {
pMac->sme.pChAvoidNotificationCb = pCallbackfn;
}
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_ch_avoid_update_req
\API to request channel avoidance update from FW.
\param hHal - The handle returned by mac_open
\param update_type - The udpate_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;
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
cauReq = (tSirChAvoidUpdateReq *)
qdf_mem_malloc(sizeof(tSirChAvoidUpdateReq));
if (NULL == cauReq) {
QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
"%s Request Buffer Alloc Fail", __func__);
sme_release_global_lock(&pMac->sme);
return QDF_STATUS_E_NOMEM;
}
cauReq->reserved_param = 0;
/* serialize the req through MC thread */
cds_message.bodyptr = cauReq;
cds_message.type = WMA_CH_AVOID_UPDATE_REQ;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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_INFO,
"%s: Posted Ch Avoid Update MSG", __func__);
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif /* FEATURE_WLAN_CH_AVOID */
/**
* 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)
{
cds_msg_t msg;
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(
cds_mq_post_message(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)
{
cds_msg_t msg;
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(
cds_mq_post_message(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_s *ch_params,
tCsrRoamProfile *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;
}
/* -------------------------------------------------------------------------
\fn sme_process_channel_change_resp
\brief API to Indicate Channel change response message to SAP.
\return QDF_STATUS
---------------------------------------------------------------------------*/
QDF_STATUS sme_process_channel_change_resp(tpAniSirGlobal pMac,
uint16_t msg_type, void *pMsgBuf)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tCsrRoamInfo 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;
sms_log(pMac, LOGE,
"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;
proam_info.channelChangeRespEvent->secondaryChannelOffset =
pChnlParams->ch_width;
if (pChnlParams->status == QDF_STATUS_SUCCESS) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_MED,
"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_INFO_MED,
"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;
sms_log(pMac, LOGE, "Invalid Channel Change Resp Message: %d\n",
status);
}
qdf_mem_free(proam_info.channelChangeRespEvent);
return status;
}
/* -------------------------------------------------------------------------
\fn sme_roam_start_beacon_req
\brief API to Indicate LIM to start Beacon Tx
\after SAP CAC Wait is completed.
\param hHal - The handle returned by mac_open
\param sessionId - session ID
\param 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_s *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;
}
/* ---------------------------------------------------------------------------
\fn sme_init_thermal_info
\brief SME API to initialize the thermal mitigation parameters
\param hHal
\param thermalParam : thermal mitigation parameters
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_init_thermal_info(tHalHandle hHal, tSmeThermalParams thermalParam)
{
t_thermal_mgmt *pWmaParam;
cds_msg_t msg;
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
(cds_mq_post_message(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)
{
cds_msg_t msg;
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 = cds_mq_post_message(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;
}
/* ---------------------------------------------------------------------------
\fn sme_txpower_limit
\brief SME API to set txpower limits
\param hHal
\param 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;
cds_msg_t cds_message;
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)) {
cds_message.type = WMA_TX_POWER_LIMIT;
cds_message.reserved = 0;
cds_message.bodyptr = tx_power_limit;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/* ---------------------------------------------------------------------------
\fn sme_ap_disable_intra_bss_fwd
\brief
SME will send message to WMA to set Intra BSS in txrx
\param
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;
cds_msg_t cds_message;
tpDisableIntraBssFwd pSapDisableIntraFwd = NULL;
/* Prepare the request to send to SME. */
pSapDisableIntraFwd = qdf_mem_malloc(sizeof(tDisableIntraBssFwd));
if (NULL == pSapDisableIntraFwd) {
sms_log(pMac, LOGP, "Memory Allocation Failure!!! %s", __func__);
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 */
cds_message.bodyptr = pSapDisableIntraFwd;
cds_message.type = WMA_SET_SAP_INTRABSS_DIS;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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
/******************************************************************************
\fn sme_stats_ext_register_callback
\brief
a function called to register the callback that send vendor event for stats
ext
\param callback - callback to be registered
******************************************************************************/
void sme_stats_ext_register_callback(tHalHandle hHal, StatsExtCallback callback)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
pMac->sme.StatsExtCallback = callback;
}
/**
* sme_stats_ext_deregister_callback() - De-register ext stats callback
* @h_hal: Hal Handle
*
* This function is called to de initialize the HDD NAN feature. Currently
* the only operation required is to de-register a callback with SME.
*
* Return: None
*/
void sme_stats_ext_deregister_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.StatsExtCallback = NULL;
}
/******************************************************************************
\fn sme_stats_ext_request
\brief
a function called when HDD receives STATS EXT vendor command from userspace
\param sessionID - vdevID for the stats ext request
\param input - Stats Ext Request structure ptr
\return QDF_STATUS
******************************************************************************/
QDF_STATUS sme_stats_ext_request(uint8_t session_id, tpStatsExtRequestReq input)
{
cds_msg_t msg;
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 != cds_mq_post_message(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;
}
/******************************************************************************
\fn sme_stats_ext_event
\brief
a callback function called when SME received eWNI_SME_STATS_EXT_EVENT
response from WMA
\param hHal - HAL handle for device
\param pMsg - Message body passed from WMA; includes NAN header
\return QDF_STATUS
******************************************************************************/
QDF_STATUS sme_stats_ext_event(tHalHandle hHal, void *pMsg)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (NULL == pMsg) {
sms_log(pMac, LOGE, "in %s msg ptr is NULL", __func__);
status = QDF_STATUS_E_FAILURE;
} else {
sms_log(pMac, LOG2, "SME: entering %s", __func__);
if (pMac->sme.StatsExtCallback) {
pMac->sme.StatsExtCallback(pMac->hHdd,
(tpStatsExtEvent) pMsg);
}
}
return status;
}
#endif
/* ---------------------------------------------------------------------------
\fn sme_update_dfs_scan_mode
\brief Update DFS roam scan mode
This function is called through dynamic setConfig callback function
to configure allowDFSChannelRoam.
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param 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.
\sa
-------------------------------------------------------------------------*/
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;
sme_release_global_lock(&pMac->sme);
}
if (pMac->roam.configParam.isRoamOffloadScanEnabled) {
csr_roam_offload_scan(pMac, sessionId,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_ROAM_DFS_SCAN_MODE_CHANGED);
}
return status;
}
/*--------------------------------------------------------------------------
\brief sme_get_dfs_scan_mode() - get DFS roam scan mode
This is a synchronous call
\param hHal - The handle returned by mac_open.
\return DFS roaming scan mode 0 (disable), 1 (passive), 2 (active)
\sa
--------------------------------------------------------------------------*/
uint8_t sme_get_dfs_scan_mode(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
return pMac->roam.configParam.allowDFSChannelRoam;
}
/*----------------------------------------------------------------------------
\fn sme_modify_add_ie
\brief This function sends msg to updates the additional IE buffers in PE
\param hHal - global structure
\param pModifyIE - pointer to tModifyIE structure
\param 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;
}
/*----------------------------------------------------------------------------
\fn sme_update_add_ie
\brief This function sends msg to updates the additional IE buffers in PE
\param hHal - global structure
\param pUpdateIE - pointer to structure tUpdateIE
\param 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,
sme_QosWmmUpType *dscpmapping,
uint8_t sessionId)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint8_t i, j, peSessionId;
tCsrRoamSession *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) {
hdd_notice("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_ERROR,
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;
}
/* ---------------------------------------------------------------------------
\fn sme_abort_roam_scan
\brief API to abort current roam scan cycle by roam scan offload module.
\param hHal - The handle returned by mac_open.
\param 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);
sms_log(pMac, LOGW, "entering function %s", __func__);
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 };
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
uint8_t numChannels = 0;
uint8_t i = 0;
uint32_t totValidChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN;
if (!aValidChannels || !pNumChannels) {
sms_log(pMac, QDF_TRACE_LEVEL_ERROR,
FL("Output channel list/NumChannels is NULL"));
return QDF_STATUS_E_INVAL;
}
if ((wifiBand < WIFI_BAND_UNSPECIFIED) || (wifiBand >= WIFI_BAND_MAX)) {
sms_log(pMac, QDF_TRACE_LEVEL_ERROR,
FL("Invalid wifiBand (%d)"), wifiBand);
return QDF_STATUS_E_INVAL;
}
status = sme_get_cfg_valid_channels(hHal, &chanList[0],
&totValidChannels);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(pMac, QDF_TRACE_LEVEL_ERROR,
FL("Fail to get valid channel list (err=%d)"), status);
return status;
}
switch (wifiBand) {
case WIFI_BAND_UNSPECIFIED:
sms_log(pMac, QDF_TRACE_LEVEL_INFO,
FL("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:
sms_log(pMac, QDF_TRACE_LEVEL_INFO,
FL("WIFI_BAND_BG (2.4 GHz)"));
for (i = 0; i < totValidChannels; i++) {
if (CDS_IS_CHANNEL_24GHZ(chanList[i])) {
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
}
break;
case WIFI_BAND_A:
sms_log(pMac, QDF_TRACE_LEVEL_INFO,
FL("WIFI_BAND_A (5 GHz without DFS)"));
for (i = 0; i < totValidChannels; i++) {
if (CDS_IS_CHANNEL_5GHZ(chanList[i]) &&
!CDS_IS_DFS_CH(chanList[i])) {
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
}
break;
case WIFI_BAND_ABG:
sms_log(pMac, QDF_TRACE_LEVEL_INFO,
FL("WIFI_BAND_ABG (2.4 GHz + 5 GHz; no DFS)"));
for (i = 0; i < totValidChannels; i++) {
if ((CDS_IS_CHANNEL_24GHZ(chanList[i]) ||
CDS_IS_CHANNEL_5GHZ(chanList[i])) &&
!CDS_IS_DFS_CH(chanList[i])) {
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
}
break;
case WIFI_BAND_A_DFS_ONLY:
sms_log(pMac, QDF_TRACE_LEVEL_INFO,
FL("WIFI_BAND_A_DFS (5 GHz DFS only)"));
for (i = 0; i < totValidChannels; i++) {
if (CDS_IS_CHANNEL_5GHZ(chanList[i]) &&
CDS_IS_DFS_CH(chanList[i])) {
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
}
break;
case WIFI_BAND_A_WITH_DFS:
sms_log(pMac, QDF_TRACE_LEVEL_INFO,
FL("WIFI_BAND_A_WITH_DFS (5 GHz with DFS)"));
for (i = 0; i < totValidChannels; i++) {
if (CDS_IS_CHANNEL_5GHZ(chanList[i])) {
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
}
break;
case WIFI_BAND_ABG_WITH_DFS:
sms_log(pMac, QDF_TRACE_LEVEL_INFO,
FL("WIFI_BAND_ABG_WITH_DFS (2.4 GHz+5 GHz with DFS)"));
for (i = 0; i < totValidChannels; i++) {
if (CDS_IS_CHANNEL_24GHZ(chanList[i]) ||
CDS_IS_CHANNEL_5GHZ(chanList[i])) {
aValidChannels[numChannels++] =
cds_chan_to_freq(chanList[i]);
}
}
break;
default:
sms_log(pMac, QDF_TRACE_LEVEL_ERROR,
FL("Unknown wifiBand (%d))"), wifiBand);
return QDF_STATUS_E_INVAL;
break;
}
*pNumChannels = numChannels;
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_ext_scan_get_capabilities
\brief SME API to fetch extscan capabilities
\param hHal
\param 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);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
cds_message.bodyptr = pReq;
cds_message.type = WMA_EXTSCAN_GET_CAPABILITIES_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_ext_scan_start
\brief SME API to issue extscan start
\param hHal
\param 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);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
cds_message.bodyptr = pStartCmd;
cds_message.type = WMA_EXTSCAN_START_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_ext_scan_stop
\brief SME API to issue extscan stop
\param hHal
\param 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);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
cds_message.bodyptr = pStopReq;
cds_message.type = WMA_EXTSCAN_STOP_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_set_bss_hotlist
\brief SME API to set BSSID hotlist
\param hHal
\param pSetHotListReq: extscan set hotlist structure
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_set_bss_hotlist(tHalHandle hHal,
tSirExtScanSetBssidHotListReqParams *
pSetHotListReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
cds_message.bodyptr = pSetHotListReq;
cds_message.type = WMA_EXTSCAN_SET_BSSID_HOTLIST_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_reset_bss_hotlist
\brief SME API to reset BSSID hotlist
\param hHal
\param pSetHotListReq: extscan set hotlist structure
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_reset_bss_hotlist(tHalHandle hHal,
tSirExtScanResetBssidHotlistReqParams *
pResetReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
cds_message.bodyptr = pResetReq;
cds_message.type = WMA_EXTSCAN_RESET_BSSID_HOTLIST_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/**
* 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);
cds_msg_t cds_message;
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)) {
cds_message.bodyptr = cds_msg_wisa_params;
cds_message.type = WMA_SET_WISA_PARAMS;
status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
sme_release_global_lock(&mac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_set_significant_change
\brief SME API to set significant change
\param hHal
\param pSetSignificantChangeReq: extscan set significant change structure
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_set_significant_change(tHalHandle hHal,
tSirExtScanSetSigChangeReqParams *
pSetSignificantChangeReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
cds_message.bodyptr = pSetSignificantChangeReq;
cds_message.type = WMA_EXTSCAN_SET_SIGNF_CHANGE_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_reset_significant_change
\brief SME API to reset significant change
\param hHal
\param 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);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
cds_message.bodyptr = pResetReq;
cds_message.type = WMA_EXTSCAN_RESET_SIGNF_CHANGE_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_get_cached_results
\brief SME API to get cached results
\param hHal
\param 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);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
/* Serialize the req through MC thread */
cds_message.bodyptr = pCachedResultsReq;
cds_message.type = WMA_EXTSCAN_GET_CACHED_RESULTS_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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);
cds_msg_t cds_message;
struct wifi_epno_params *req_msg;
int len, i;
sms_log(mac, LOG1, FL("enter"));
len = sizeof(*req_msg) +
(input->num_networks * sizeof(struct wifi_epno_network));
req_msg = qdf_mem_malloc(len);
if (!req_msg) {
sms_log(mac, LOGE, FL("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)) {
sms_log(mac, LOGE,
FL("sme_acquire_global_lock failed!(status=%d)"),
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
cds_message.bodyptr = req_msg;
cds_message.type = WMA_SET_EPNO_LIST_REQ;
status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("cds_mq_post_message 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);
cds_msg_t cds_message;
struct wifi_passpoint_req *req_msg;
int len, i;
sms_log(mac, LOG1, FL("enter"));
len = sizeof(*req_msg) +
(input->num_networks * sizeof(struct wifi_passpoint_network));
req_msg = qdf_mem_malloc(len);
if (!req_msg) {
sms_log(mac, LOGE, FL("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)) {
sms_log(mac, LOGE,
FL("sme_acquire_global_lock failed!(status=%d)"),
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
cds_message.bodyptr = req_msg;
cds_message.type = WMA_SET_PASSPOINT_LIST_REQ;
status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("cds_mq_post_message 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);
cds_msg_t cds_message;
struct wifi_passpoint_req *req_msg;
sms_log(mac, LOG1, FL("enter"));
req_msg = qdf_mem_malloc(sizeof(*req_msg));
if (!req_msg) {
sms_log(mac, LOGE, FL("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)) {
sms_log(mac, LOGE,
FL("sme_acquire_global_lock failed!(status=%d)"),
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
cds_message.bodyptr = req_msg;
cds_message.type = WMA_RESET_PASSPOINT_LIST_REQ;
status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("cds_mq_post_message failed!(err=%d)"),
status);
qdf_mem_free(req_msg);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&mac->sme);
return status;
}
/**
* sme_set_ssid_hotlist() - Set the SSID hotlist
* @hal: SME handle
* @request: set ssid hotlist request
*
* Return: QDF_STATUS
*/
QDF_STATUS
sme_set_ssid_hotlist(tHalHandle hal,
struct sir_set_ssid_hotlist_request *request)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
cds_msg_t cds_message;
struct sir_set_ssid_hotlist_request *set_req;
set_req = qdf_mem_malloc(sizeof(*set_req));
if (!set_req) {
sms_log(mac, LOGE, FL("qdf_mem_malloc failed"));
return QDF_STATUS_E_FAILURE;
}
*set_req = *request;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_STATUS_SUCCESS == status) {
/* Serialize the req through MC thread */
cds_message.bodyptr = set_req;
cds_message.type = WMA_EXTSCAN_SET_SSID_HOTLIST_REQ;
status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
sme_release_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
qdf_mem_free(set_req);
status = QDF_STATUS_E_FAILURE;
}
} else {
sms_log(mac, LOGE,
FL("sme_acquire_global_lock failed!(status=%d)"),
status);
qdf_mem_free(set_req);
status = QDF_STATUS_E_FAILURE;
}
return status;
}
QDF_STATUS sme_ext_scan_register_callback(tHalHandle hHal,
void (*pExtScanIndCb)(void *,
const uint16_t,
void *))
{
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.pExtScanIndCb = pExtScanIndCb;
sme_release_global_lock(&pMac->sme);
}
return status;
}
#endif /* FEATURE_WLAN_EXTSCAN */
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
/* ---------------------------------------------------------------------------
\fn sme_ll_stats_clear_req
\brief SME API to clear Link Layer Statistics
\param hHal
\param 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);
cds_msg_t cds_message;
tSirLLStatsClearReq *clear_stats_req;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"staId = %u", pclearStatsReq->staId);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"statsClearReqMask = 0x%X",
pclearStatsReq->statsClearReqMask);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"stopReq = %u", pclearStatsReq->stopReq);
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 */
cds_message.bodyptr = clear_stats_req;
cds_message.type = WMA_LINK_LAYER_STATS_CLEAR_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/* ---------------------------------------------------------------------------
\fn sme_ll_stats_set_req
\brief SME API to set the Link Layer Statistics
\param hHal
\param 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);
cds_msg_t cds_message;
tSirLLStatsSetReq *set_stats_req;
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
"%s: MPDU Size = %u", __func__,
psetStatsReq->mpduSizeThreshold);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
" 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 */
cds_message.bodyptr = set_stats_req;
cds_message.type = WMA_LINK_LAYER_STATS_SET_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/* ---------------------------------------------------------------------------
\fn sme_ll_stats_get_req
\brief SME API to get the Link Layer Statistics
\param hHal
\param pgetStatsReq: Link Layer get stats request params structure
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_ll_stats_get_req(tHalHandle hHal, tSirLLStatsGetReq *pgetStatsReq)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
tSirLLStatsGetReq *get_stats_req;
get_stats_req = qdf_mem_malloc(sizeof(*get_stats_req));
if (!get_stats_req) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for WMA_LL_STATS_GET_REQ",
__func__);
return QDF_STATUS_E_NOMEM;
}
*get_stats_req = *pgetStatsReq;
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
/* Serialize the req through MC thread */
cds_message.bodyptr = get_stats_req;
cds_message.type = WMA_LINK_LAYER_STATS_GET_REQ;
MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
NO_SESSION, cds_message.type));
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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_GET_REQ",
__func__);
qdf_mem_free(get_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(get_stats_req);
status = QDF_STATUS_E_FAILURE;
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_set_link_layer_stats_ind_cb
\brief SME API to trigger the stats are available after get request
\param hHal
\param callback_routine - HDD callback which needs to be invoked after
getting status notification from FW
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_set_link_layer_stats_ind_cb
(tHalHandle hHal,
void (*callback_routine)(void *callbackCtx, int indType, void *pRsp)
) {
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.pLinkLayerStatsIndCallback = callback_routine;
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_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.pLinkLayerStatsIndCallback = 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;
}
#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
/**
* sme_fw_mem_dump_register_cb() - Register fw memory dump callback
*
* @hal - MAC global handle
* @callback_routine - callback routine from HDD
*
* This API is invoked by HDD to register its callback in SME
*
* Return: QDF_STATUS
*/
#ifdef WLAN_FEATURE_MEMDUMP
QDF_STATUS sme_fw_mem_dump_register_cb(tHalHandle hal,
void (*callback_routine)(void *cb_context,
struct fw_dump_rsp *rsp))
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&pmac->sme);
if (QDF_STATUS_SUCCESS == status) {
pmac->sme.fw_dump_callback = callback_routine;
sme_release_global_lock(&pmac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock error"));
}
return status;
}
#else
QDF_STATUS sme_fw_mem_dump_register_cb(tHalHandle hal,
void (*callback_routine)(void *cb_context,
struct fw_dump_rsp *rsp))
{
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_FEATURE_MEMDUMP */
/**
* sme_fw_mem_dump_unregister_cb() - Unregister fw memory dump callback
*
* @hHal - MAC global handle
*
* This API is invoked by HDD to unregister its callback in SME
*
* Return: QDF_STATUS
*/
#ifdef WLAN_FEATURE_MEMDUMP
QDF_STATUS sme_fw_mem_dump_unregister_cb(tHalHandle hal)
{
QDF_STATUS status;
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&pmac->sme);
if (QDF_STATUS_SUCCESS == status) {
pmac->sme.fw_dump_callback = NULL;
sme_release_global_lock(&pmac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock error"));
}
return status;
}
#else
QDF_STATUS sme_fw_mem_dump_unregister_cb(tHalHandle hal)
{
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_FEATURE_MEMDUMP */
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
/*--------------------------------------------------------------------------
\brief sme_update_roam_offload_enabled() - enable/disable roam offload feaure
It is used at in the REG_DYNAMIC_VARIABLE macro definition of
\param hHal - The handle returned by mac_open.
\param nRoamOffloadEnabled - The bool to update with
\return QDF_STATUS_SUCCESS - SME update config successfully.
Other status means SME is failed to update.
\sa
--------------------------------------------------------------------------*/
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_INFO,
"%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
* @okc_enabled: Opportunistic key caching enable/disable flag
* 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,
bool okc_enabled)
{
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_INFO,
"%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,
okc_enabled);
} else {
status = QDF_STATUS_E_INVAL;
}
sme_release_global_lock(&mac_ctx->sme);
}
return status;
}
#endif
/* ---------------------------------------------------------------------------
\fn sme_get_temperature
\brief SME API to get the pdev temperature
\param hHal
\param temperature context
\param 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);
cds_msg_t cds_message;
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,
FL
("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 */
cds_message.bodyptr = NULL;
cds_message.type = WMA_GET_TEMPERATURE_REQ;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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;
}
/* ---------------------------------------------------------------------------
\fn sme_set_scanning_mac_oui
\brief SME API to set scanning mac oui
\param hHal
\param 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);
cds_msg_t cds_message;
status = sme_acquire_global_lock(&pMac->sme);
if (QDF_STATUS_SUCCESS == status) {
/* Serialize the req through MC thread */
cds_message.bodyptr = pScanMacOui;
cds_message.type = WMA_SET_SCAN_MAC_OUI_REQ;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_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
/* ---------------------------------------------------------------------------
\fn sme_set_dhcp_srv_offload
\brief SME API to set DHCP server offload info
\param hHal
\param pDhcpSrvInfo : DHCP server offload info struct
\- return QDF_STATUS
-------------------------------------------------------------------------*/
QDF_STATUS sme_set_dhcp_srv_offload(tHalHandle hHal,
tSirDhcpSrvOffloadInfo *pDhcpSrvInfo)
{
cds_msg_t cds_message;
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 */
cds_message.type = WMA_SET_DHCP_SERVER_OFFLOAD_CMD;
cds_message.bodyptr = pSmeDhcpSrvInfo;
if (!QDF_IS_STATUS_SUCCESS
(cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_message))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post WMA_SET_DHCP_SERVER_OFFLOAD_CMD to WMA!",
__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 */
#ifdef WLAN_FEATURE_GPIO_LED_FLASHING
/* ---------------------------------------------------------------------------
\fn sme_set_led_flashing
\brief API to set the Led flashing parameters.
\param hHal - The handle returned by mac_open.
\param 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 = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t cds_message;
tSirLedFlashingReq *ledflashing;
ledflashing = qdf_mem_malloc(sizeof(*ledflashing));
if (!ledflashing) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL
("Not able to allocate memory for WMA_LED_TIMING_REQ"));
return QDF_STATUS_E_NOMEM;
}
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 */
cds_message.bodyptr = ledflashing;
cds_message.type = WMA_LED_FLASHING_REQ;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status))
status = QDF_STATUS_E_FAILURE;
sme_release_global_lock(&pMac->sme);
}
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;
}
#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);
tCsrRoamSession *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)
{
cds_msg_t msg;
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(
cds_mq_post_message(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)
{
cds_msg_t msg;
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(
cds_mq_post_message(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_configure_modulated_dtim() - function to configure modulated dtim
* @h_hal: SME API to enable/disable modulated DTIM instantaneously
* @session_id: session ID
* @modulated_dtim: modulated dtim value
*
* This function configures the modulated dtim in firmware
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_configure_modulated_dtim(tHalHandle h_hal, uint8_t session_id,
uint32_t modulated_dtim)
{
cds_msg_t msg;
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(h_hal);
wma_cli_set_cmd_t *iwcmd;
iwcmd = qdf_mem_malloc(sizeof(*iwcmd));
if (NULL == iwcmd) {
QDF_TRACE(QDF_MODULE_ID_SME,
QDF_TRACE_LEVEL_FATAL,
"%s: qdf_mem_malloc failed", __func__);
return QDF_STATUS_E_NOMEM;
}
status = sme_acquire_global_lock(&mac->sme);
if (QDF_STATUS_SUCCESS == status) {
iwcmd->param_value = modulated_dtim;
iwcmd->param_vdev_id = session_id;
iwcmd->param_id = GEN_PARAM_MODULATED_DTIM;
iwcmd->param_vp_dev = GEN_CMD;
msg.type = WMA_CLI_SET_CMD;
msg.reserved = 0;
msg.bodyptr = (void *)iwcmd;
if (!QDF_IS_STATUS_SUCCESS(
cds_mq_post_message(QDF_MODULE_ID_WMA, &msg))) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: Not able to post GEN_PARAM_DYNAMIC_DTIM to WMA!",
__func__);
qdf_mem_free(iwcmd);
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(iwcmd);
}
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);
cds_msg_t cds_message;
struct sir_wifi_start_log *req_msg;
uint32_t len;
len = sizeof(*req_msg);
req_msg = qdf_mem_malloc(len);
if (!req_msg) {
sms_log(mac, LOGE, FL("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;
status = sme_acquire_global_lock(&mac->sme);
if (status != QDF_STATUS_SUCCESS) {
sms_log(mac, LOGE,
FL("sme_acquire_global_lock failed(status=%d)"),
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
cds_message.bodyptr = req_msg;
cds_message.type = SIR_HAL_START_STOP_LOGGING;
status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("cds_mq_post_message 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
sms_log(mac_ctx, LOGE, FL("Invalid Sesion = %d"), sessionId);
return val;
}
/*
* 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;
cds_msg_t message;
/* Serialize the req through MC thread */
message.bodyptr = NULL;
message.type = SIR_HAL_FLUSH_LOG_TO_FW;
status = cds_mq_post_message(CDS_MQ_ID_WMA, &message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("cds_mq_post_message failed!(err=%d)"),
status);
status = QDF_STATUS_E_FAILURE;
}
return status;
}
/**
* sme_enable_uapsd_for_ac() - enable uapsd for access catagory requerst to WMA
* @cds_ctx: cds context
* @sta_id: station id
* @ac: access catagory
* @tid: tid value
* @pri: user priority
* @srvc_int: service interval
* @sus_int: suspend interval
* @dir: tspec direction
* @psb: PSB value
* @sessionId: session id
* @delay_interval: delay interval
*
* Return: QDF status
*/
QDF_STATUS sme_enable_uapsd_for_ac(void *cds_ctx, uint8_t sta_id,
sme_ac_enum_type ac, uint8_t tid,
uint8_t pri, uint32_t srvc_int,
uint32_t sus_int,
sme_tspec_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;
}
/**
* sme_disable_uapsd_for_ac() - disable uapsed access catagory request to WMA
* @cds_ctx: cds context
* @sta_id: station id
* @ac: access catagory
* @sessionId: session id
*
* Return: QDF status
*/
QDF_STATUS sme_disable_uapsd_for_ac(void *cds_ctx, 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, value = 0;
union {
uint16_t cfg_value16;
tSirMacHTCapabilityInfo ht_cap_info;
} uHTCapabilityInfo;
tCsrRoamSession *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*/
sme_cfg_get_int(mac_ctx, WNI_CFG_HT_CAP_INFO, &value);
uHTCapabilityInfo.cfg_value16 = (0xFFFF & value);
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 =
uHTCapabilityInfo.ht_cap_info.txSTBC;
}
}
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;
}
/**
* sme_set_rssi_threshold_breached_cb() - set rssi threshold breached callback
* @h_hal: global hal handle
* @cb: callback function pointer
*
* This function stores the rssi threshold breached callback function.
*
* Return: QDF_STATUS enumeration.
*/
QDF_STATUS sme_set_rssi_threshold_breached_cb(tHalHandle h_hal,
void (*cb)(void *, struct rssi_breach_event *))
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac;
if (!h_hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("hHal 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("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;
}
/**
* sme_set_rssi_threshold_breached_cb() - Reset rssi threshold breached callback
* @hal: global hal handle
*
* This function de-registers the rssi threshold breached callback function.
*
* Return: QDF_STATUS enumeration.
*/
QDF_STATUS sme_reset_rssi_threshold_breached_cb(tHalHandle hal)
{
QDF_STATUS status;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("sme_acquire_global_lock failed!(status=%d)"),
status);
return status;
}
mac->sme.rssi_threshold_breached_cb = NULL;
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;
}
/**
* 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);
cds_msg_t cds_message;
struct rssi_monitor_req *req_msg;
sms_log(mac, LOG1, FL("enter"));
req_msg = qdf_mem_malloc(sizeof(*req_msg));
if (!req_msg) {
sms_log(mac, LOGE, FL("memory allocation failed"));
return QDF_STATUS_E_NOMEM;
}
*req_msg = *input;
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("sme_acquire_global_lock failed!(status=%d)"),
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
cds_message.bodyptr = req_msg;
cds_message.type = WMA_SET_RSSI_MONITOR_REQ;
status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("cds_mq_post_message failed!(err=%d)"),
status);
qdf_mem_free(req_msg);
}
sme_release_global_lock(&mac->sme);
return status;
}
/**
* sme_fw_mem_dump() - Get FW memory dump
* @hHal: hal handle
* @recvd_req: received memory dump request.
*
* This API is invoked by HDD to indicate FW to start
* dumping firmware memory.
*
* Return: QDF_STATUS
*/
#ifdef WLAN_FEATURE_MEMDUMP
QDF_STATUS sme_fw_mem_dump(tHalHandle hHal, void *recvd_req)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
cds_msg_t msg;
struct fw_dump_req *send_req;
struct fw_dump_seg_req seg_req;
int loop;
send_req = qdf_mem_malloc(sizeof(*send_req));
if (!send_req) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Memory allocation failed for WDA_FW_MEM_DUMP"));
return QDF_STATUS_E_FAILURE;
}
qdf_mem_copy(send_req, recvd_req, sizeof(*send_req));
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("request_id:%d num_seg:%d"),
send_req->request_id, send_req->num_seg);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("Segment Information"));
for (loop = 0; loop < send_req->num_seg; loop++) {
seg_req = send_req->segment[loop];
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("seg_number:%d"), loop);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("seg_id:%d start_addr_lo:0x%x start_addr_hi:0x%x"),
seg_req.seg_id, seg_req.seg_start_addr_lo,
seg_req.seg_start_addr_hi);
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO,
FL("seg_length:%d dst_addr_lo:0x%x dst_addr_hi:0x%x"),
seg_req.seg_length, seg_req.dst_addr_lo,
seg_req.dst_addr_hi);
}
if (QDF_STATUS_SUCCESS == sme_acquire_global_lock(&pMac->sme)) {
msg.bodyptr = send_req;
msg.type = WMA_FW_MEM_DUMP_REQ;
msg.reserved = 0;
qdf_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &msg);
if (QDF_STATUS_SUCCESS != qdf_status) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Not able to post WMA_FW_MEM_DUMP"));
qdf_mem_free(send_req);
status = QDF_STATUS_E_FAILURE;
}
sme_release_global_lock(&pMac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Failed to acquire SME Global Lock"));
qdf_mem_free(send_req);
status = QDF_STATUS_E_FAILURE;
}
return status;
}
#else
QDF_STATUS sme_fw_mem_dump(tHalHandle hHal, void *recvd_req)
{
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_FEATURE_MEMDUMP */
/*
* 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(tHalHandle hal,
struct sir_pcl_list msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
cds_msg_t cds_message;
struct wmi_pcl_chan_weights *req_msg;
uint32_t len, i;
len = sizeof(*req_msg);
req_msg = qdf_mem_malloc(len);
if (!req_msg) {
sms_log(mac, LOGE, FL("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) {
sms_log(mac, LOGE,
FL("sme_acquire_global_lock failed!(status=%d)"),
status);
qdf_mem_free(req_msg);
return status;
}
/* Serialize the req through MC thread */
cds_message.bodyptr = req_msg;
cds_message.type = SIR_HAL_PDEV_SET_PCL_TO_FW;
status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE,
FL("cds_mq_post_message 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(tHalHandle hal,
struct sir_hw_mode msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
tSmeCmd *cmd = NULL;
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE, FL("Failed to acquire lock"));
return QDF_STATUS_E_RESOURCES;
}
cmd = sme_get_command_buffer(mac);
if (!cmd) {
sms_log(mac, LOGE, FL("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->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;
sms_log(mac, LOG1,
FL("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;
sms_log(mac, LOG1, FL("HW mode transition callback registered"));
}
/**
* 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(tHalHandle hHal, uint32_t vdev_id,
uint8_t new_nss, void *cback, uint8_t next_action,
void *hdd_context,
enum sir_conn_update_reason reason)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
tpAniSirGlobal mac = PMAC_STRUCT(hHal);
tSmeCmd *cmd = NULL;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
cmd = sme_get_command_buffer(mac);
if (!cmd) {
sms_log(mac, LOGE, FL("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 = hdd_context;
cmd->u.nss_update_cmd.next_action = next_action;
cmd->u.nss_update_cmd.reason = reason;
sms_log(mac, LOG1, FL("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(tHalHandle hal,
struct sir_dual_mac_config msg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
tSmeCmd *cmd;
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE, FL("Failed to acquire lock"));
return QDF_STATUS_E_RESOURCES;
}
cmd = sme_get_command_buffer(mac);
if (!cmd) {
sms_log(mac, LOGE, FL("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;
sms_log(mac, LOG1,
FL("Queuing e_sme_command_set_dual_mac_config to CSR: %x %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;
cds_msg_t cds_message;
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,
FL("Not able to allocate memory for gw param update request"));
return QDF_STATUS_E_NOMEM;
}
*request_buf = *gw_params;
cds_message.type = WMA_GW_PARAM_UPDATE_REQ;
cds_message.reserved = 0;
cds_message.bodyptr = request_buf;
qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("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) {
sms_log(mac, LOGE, FL("antenna mode mesg is NULL"));
return QDF_STATUS_E_FAILURE;
}
status = sme_acquire_global_lock(&mac->sme);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sms_log(mac, LOGE, FL("Failed to acquire lock"));
return QDF_STATUS_E_RESOURCES;
}
cmd = sme_get_command_buffer(mac);
if (!cmd) {
sme_release_global_lock(&mac->sme);
sms_log(mac, LOGE, FL("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;
sms_log(mac, LOG1,
FL("Queuing e_sme_command_set_antenna_mode to CSR: %d %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;
tCsrNeighborRoamConfig *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_INFO,
"%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_INFO,
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_INFO,
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_INFO,
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_INFO,
FL("invalid parameter notify_id %d"),
notify_id);
status = QDF_STATUS_E_INVAL;
break;
}
sme_release_global_lock(&mac_ctx->sme);
}
if (mac_ctx->roam.configParam.isRoamOffloadScanEnabled &&
status == QDF_STATUS_SUCCESS) {
csr_roam_offload_scan(mac_ctx, session_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG, reason);
}
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->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_INFO,
FL("mac_ctx->pmf_offload: %d"), mac_ctx->pmf_offload);
return;
}
/**
* 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 = PMAC_STRUCT(hal);
if (!mac) {
/* Using QDF_TRACE since mac is not available for sms_log */
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;
} else {
sms_log(mac, LOGE,
FL("invalid session id:%d"), session_id);
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 = cds_reg_dmn_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BW40_LOW_PRIMARY);
if (!(*opclass)) {
*opclass = cds_reg_dmn_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BW40_HIGH_PRIMARY);
}
} else if (bw_offset & (1 << BW_20_OFFSET_BIT)) {
*opclass = cds_reg_dmn_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BW20);
} else {
*opclass = cds_reg_dmn_get_opclass_from_channel(
mac_ctx->scan.countryCodeCurrent,
channel, BWALL);
}
}
#endif
#ifdef FEATURE_GREEN_AP
/**
* sme_send_egap_conf_params() - set the enhanced green ap configuration params
* @enable: enable/disable the enhanced green ap feature
* @inactivity_time: inactivity timeout value
* @wait_time: wait timeout value
* @flag: feature flag in bitmasp
*
* Return: Return QDF_STATUS, otherwise appropriate failure code
*/
QDF_STATUS sme_send_egap_conf_params(uint32_t enable, uint32_t inactivity_time,
uint32_t wait_time, uint32_t flags)
{
cds_msg_t message;
QDF_STATUS status;
struct egap_conf_params *egap_params;
egap_params = qdf_mem_malloc(sizeof(*egap_params));
if (NULL == egap_params) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
"%s: fail to alloc egap_params", __func__);
return QDF_STATUS_E_NOMEM;
}
egap_params->enable = enable;
egap_params->inactivity_time = inactivity_time;
egap_params->wait_time = wait_time;
egap_params->flags = flags;
message.type = WMA_SET_EGAP_CONF_PARAMS;
message.bodyptr = egap_params;
status = cds_mq_post_message(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(egap_params);
}
return status;
}
#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 sucsess else failue 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);
sms_log(mac_ctx, LOG1,
"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);
tCsrRoamSession *csr_session;
csr_session = CSR_GET_SESSION(mac_ctx, session_id);
if (NULL == csr_session) {
sms_log(mac_ctx, LOGE,
FL("SME session not valid: %d"), session_id);
return false;
}
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sms_log(mac_ctx, LOGE,
FL("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)
{
cds_msg_t message;
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)) {
sms_log(mac_ctx, LOGE,
"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 = cds_mq_post_message(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)
{
cds_msg_t message;
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)) {
sms_log(mac_ctx, LOGE,
"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 = cds_mq_post_message(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 = cds_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"));
}
/**
* sme_get_bpf_offload_capabilities() - Get length for BPF offload
* @hal: Global HAL handle
* This function constructs the cds message and fill in message type,
* post the same to WDA.
* Return: QDF_STATUS enumeration
*/
QDF_STATUS sme_get_bpf_offload_capabilities(tHalHandle hal)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
cds_msg_t cds_msg;
sms_log(mac_ctx, LOG1, FL("enter"));
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
/* Serialize the req through MC thread */
cds_msg.bodyptr = NULL;
cds_msg.type = WDA_BPF_GET_CAPABILITIES_REQ;
status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Post bpf 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"));
}
sms_log(mac_ctx, LOG1, FL("exit"));
return status;
}
/**
* sme_set_bpf_instructions() - Set BPF bpf filter instructions.
* @hal: HAL handle
* @bpf_set_offload: struct to set bpf filter instructions.
*
* Return: QDF_STATUS enumeration.
*/
QDF_STATUS sme_set_bpf_instructions(tHalHandle hal,
struct sir_bpf_set_offload *req)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
cds_msg_t cds_msg;
struct sir_bpf_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_BPF_SET_INSTRUCTIONS_REQ;
status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Post BPF 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;
}
/**
* sme_bpf_offload_register_callback() - Register get bpf offload callbacK
*
* @hal - MAC global handle
* @callback_routine - callback routine from HDD
*
* This API is invoked by HDD to register its callback in SME
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_bpf_offload_register_callback(tHalHandle hal,
void (*pbpf_get_offload_cb)(void *context,
struct sir_bpf_get_offload *))
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
mac->sme.pbpf_get_offload_cb = pbpf_get_offload_cb;
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock failed"));
}
return status;
}
/**
* 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_bpf_offload_deregister_callback() - Register get bpf offload callbacK
*
* @h_hal - MAC global handle
* @callback_routine - callback routine from HDD
*
* This API is invoked by HDD to de-register its callback in SME
*
* Return: QDF_STATUS Enumeration
*/
QDF_STATUS sme_bpf_offload_deregister_callback(tHalHandle h_hal)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac;
if (!h_hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("hHal 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.pbpf_get_offload_cb = NULL;
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock failed"));
}
return status;
}
/**
* sme_create_mon_session() - post message to create PE session for monitormode
* operation
* @hal_handle: Handle to the HAL
* @bssid: pointer to bssid
*
* Return: QDF_STATUS_SUCCESS on success, non-zero error code on failure.
*/
QDF_STATUS sme_create_mon_session(tHalHandle hal_handle, tSirMacAddr bss_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->msg_len = sizeof(*msg);
qdf_mem_copy(msg->bss_id.bytes, bss_id, QDF_MAC_ADDR_SIZE);
status = cds_send_mb_message_to_mac(msg);
}
return status;
}
/**
* 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 sucsess else failure status
*/
QDF_STATUS sme_set_adaptive_dwelltime_config(tHalHandle hal,
struct adaptive_dwelltime_params *params)
{
cds_msg_t message;
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 = cds_mq_post_message(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)
{
tpAniSirGlobal p_mac = PMAC_STRUCT(hal);
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) {
sms_log(p_mac, LOGE, FL("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);
sms_log(p_mac, LOG1,
FL("sending eWNI_SME_SET_VDEV_IES_PER_BAND: vdev_id: %d "),
vdev_id);
status = cds_send_mb_message_to_mac(p_msg);
if (QDF_STATUS_SUCCESS != status)
sms_log(p_mac, LOGE,
FL("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) {
sms_log(mac_ctx, LOGE,
"%s: mem alloc failed for ht_vht_cfg",
__func__);
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);
sms_log(mac_ctx, LOG1,
FL("SET_HT_VHT_IE with nss %d, dot11mode %d"),
ht_vht_cfg->nss,
ht_vht_cfg->dot11mode);
status = cds_send_mb_message_to_mac(ht_vht_cfg);
if (QDF_STATUS_SUCCESS != status) {
sms_log(mac_ctx, LOGE, FL(
"Send SME_PDEV_SET_HT_VHT_IE fail"));
}
sme_release_global_lock(&mac_ctx->sme);
}
return;
}
/**
* 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, eCsrBand band)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct vdev_type_nss *vdev_nss;
if (eCSR_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));
sms_log(mac_ctx, LOG1,
"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);
}
/**
* 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);
}
/**
* 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)
{
cds_msg_t message;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
struct sir_mac_pwr_dbg_cmd *req;
int i;
if (!CSR_IS_SESSION_VALID(mac_ctx, session_id)) {
sms_log(mac_ctx, LOGE,
"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(cds_mq_post_message
(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
* @hal: Pointer to HAL
* @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(tHalHandle hal, enum tQDF_ADAPTER_MODE dev_mode,
uint8_t *nss_2g, uint8_t *nss_5g)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
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
*
* 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)
{
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;
}
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_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)
csr_roam_offload_scan(mac_ctx, session_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG,
REASON_ROAM_SCAN_STA_ROAM_POLICY_CHANGED);
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);
cds_msg_t msg;
sms_log(mac_ctx, LOG1, FL("set_value: %d"), set_value);
status = sme_acquire_global_lock(&mac_ctx->sme);
if (QDF_STATUS_SUCCESS == status) {
qdf_mem_zero(&msg, sizeof(cds_msg_t));
msg.type = WMA_SEND_FREQ_RANGE_CONTROL_IND;
msg.bodyval = set_value;
status = cds_mq_post_message(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;
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 = cds_send_mb_message_to_mac(set_ie_params);
}
sme_release_global_lock(&mac_ctx->sme);
}
sms_log(mac_ctx, LOG1, FL("Set default scan IE status %d"), status);
return status;
}
#ifdef WLAN_FEATURE_DISA
/**
* sme_encrypt_decrypt_msg() - handles encrypt/decrypt mesaage
* @hal: HAL handle
* @encrypt_decrypt_params: struct to set encryption/decryption params.
*
* Return: QDF_STATUS enumeration.
*/
QDF_STATUS sme_encrypt_decrypt_msg(tHalHandle hal,
struct encrypt_decrypt_req_params *encrypt_decrypt_params)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
cds_msg_t cds_msg;
struct encrypt_decrypt_req_params *params;
uint8_t *ptr;
ptr = qdf_mem_malloc(sizeof(*params) +
encrypt_decrypt_params->data_len);
if (ptr == NULL) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Failed to alloc memory for encrypt/decrypt params"));
return QDF_STATUS_E_NOMEM;
}
params = (struct encrypt_decrypt_req_params *)ptr;
*params = *encrypt_decrypt_params;
if (params->data_len) {
params->data = ptr + sizeof(*params);
qdf_mem_copy(params->data, encrypt_decrypt_params->data,
params->data_len);
}
status = sme_acquire_global_lock(&mac_ctx->sme);
if (status == QDF_STATUS_SUCCESS) {
/* Serialize the req through MC thread */
cds_msg.bodyptr = params;
cds_msg.type = WMA_ENCRYPT_DECRYPT_MSG;
status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg);
if (!QDF_IS_STATUS_SUCCESS(status)) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("Post encrypt/decrypt msg fail"));
status = QDF_STATUS_E_FAILURE;
qdf_mem_free(params);
}
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(params);
}
return status;
}
/**
* sme_encrypt_decrypt_msg_register_callback() - Registers
* encrypt/decrypt message callback
*
* @hal - MAC global handle
* @callback_routine - callback routine from HDD
*
* This API is invoked by HDD to register its callback in SME
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_encrypt_decrypt_msg_register_callback(tHalHandle hal,
void (*encrypt_decrypt_cb)(void *hdd_context,
struct sir_encrypt_decrypt_rsp_params
*encrypt_decrypt_rsp_params))
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac;
if (!hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("hHal 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)) {
mac->sme.encrypt_decrypt_cb = encrypt_decrypt_cb;
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock failed"));
}
return status;
}
/**
* sme_encrypt_decrypt_msg_deregister_callback() - Registers
* encrypt/decrypt message callback
*
* @h_hal - MAC global handle
* @callback_routine - callback routine from HDD
*
* This API is invoked by HDD to de-register its callback in SME
*
* Return: QDF_STATUS Enumeration
*/
QDF_STATUS sme_encrypt_decrypt_msg_deregister_callback(tHalHandle h_hal)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac;
if (!h_hal) {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("hHal 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.encrypt_decrypt_cb = NULL;
sme_release_global_lock(&mac->sme);
} else {
QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
FL("sme_acquire_global_lock failed"));
}
return status;
}
#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)
{
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal_handle);
QDF_STATUS status = QDF_STATUS_E_FAILURE;
struct sme_tx_fail_cnt_threshold *tx_fail_cnt;
cds_msg_t msg;
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;
}
sms_log(mac_ctx, LOG1,
FL("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(cds_msg_t));
msg.type = SIR_HAL_UPDATE_TX_FAIL_CNT_TH;
msg.reserved = 0;
msg.bodyptr = tx_fail_cnt;
status = cds_mq_post_message(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(tHalHandle hal,
void (*cb)(void *, struct sir_lost_link_info *))
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
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);
sms_log(mac, LOG1, FL("set lost link info callback"));
} else {
sms_log(mac, LOGE,
FL("sme_acquire_global_lock error status %d"),
status);
}
return status;
}