blob: 5b85bf9a73c8c855f8c7a67b77e0d708926f4f37 [file] [log] [blame]
/*
* Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/**=========================================================================
\file rrm_api.c
\brief implementation for PE RRM APIs
========================================================================*/
/* $Header$ */
#if defined WLAN_FEATURE_VOWIFI
/*--------------------------------------------------------------------------
Include Files
------------------------------------------------------------------------*/
#include "cds_api.h"
#include "wni_api.h"
#include "sir_api.h"
#include "ani_global.h"
#include "wni_cfg.h"
#include "lim_types.h"
#include "lim_utils.h"
#include "lim_send_sme_rsp_messages.h"
#include "parser_api.h"
#include "lim_send_messages.h"
#include "rrm_global.h"
#include "rrm_api.h"
uint8_t
rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac,
tPowerdBm regMax, tPowerdBm apTxPower)
{
uint8_t maxTxPower = 0;
uint8_t txPower = CDF_MIN(regMax, (apTxPower));
if ((txPower >= RRM_MIN_TX_PWR_CAP) && (txPower <= RRM_MAX_TX_PWR_CAP))
maxTxPower = txPower;
else if (txPower < RRM_MIN_TX_PWR_CAP)
maxTxPower = RRM_MIN_TX_PWR_CAP;
else
maxTxPower = RRM_MAX_TX_PWR_CAP;
lim_log(pMac, LOG3,
"%s: regulatoryMax = %d, apTxPwr = %d, maxTxpwr = %d",
__func__, regMax, apTxPower, maxTxPower);
return maxTxPower;
}
/* -------------------------------------------------------------------- */
/**
* rrm_cache_mgmt_tx_power
**
* FUNCTION: Store Tx power for management frames.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pSessionEntry session entry.
* @return None
*/
void
rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, tPowerdBm txPower,
tpPESession pSessionEntry)
{
lim_log(pMac, LOG3, "Cache Mgmt Tx Power = %d", txPower);
if (pSessionEntry == NULL) {
lim_log(pMac, LOG3, "%s: pSessionEntry is NULL", __func__);
pMac->rrm.rrmPEContext.txMgmtPower = txPower;
} else
pSessionEntry->txMgmtPower = txPower;
}
/* -------------------------------------------------------------------- */
/**
* rrm_get_mgmt_tx_power
*
* FUNCTION: Get the Tx power for management frames.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pSessionEntry session entry.
* @return txPower
*/
tPowerdBm rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, tpPESession pSessionEntry)
{
lim_log(pMac, LOG3, "RrmGetMgmtTxPower called");
if (pSessionEntry == NULL) {
lim_log(pMac, LOG3, "%s: txpower from rrmPEContext: %d",
__func__, pMac->rrm.rrmPEContext.txMgmtPower);
return pMac->rrm.rrmPEContext.txMgmtPower;
}
return pSessionEntry->txMgmtPower;
}
/* -------------------------------------------------------------------- */
/**
* rrm_send_set_max_tx_power_req
*
* FUNCTION: Send WMA_SET_MAX_TX_POWER_REQ message to change the max tx power.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param txPower txPower to be set.
* @param pSessionEntry session entry.
* @return None
*/
tSirRetStatus
rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, tPowerdBm txPower,
tpPESession pSessionEntry)
{
tpMaxTxPowerParams pMaxTxParams;
tSirRetStatus retCode = eSIR_SUCCESS;
tSirMsgQ msgQ;
if (pSessionEntry == NULL) {
PELOGE(lim_log(pMac, LOGE, FL("Invalid parameters"));)
return eSIR_FAILURE;
}
pMaxTxParams = cdf_mem_malloc(sizeof(tMaxTxPowerParams));
if (NULL == pMaxTxParams) {
lim_log(pMac, LOGP,
FL("Unable to allocate memory for pMaxTxParams "));
return eSIR_MEM_ALLOC_FAILED;
}
/* Allocated memory for pMaxTxParams...will be freed in other module */
pMaxTxParams->power = txPower;
cdf_mem_copy(pMaxTxParams->bssId, pSessionEntry->bssId,
sizeof(tSirMacAddr));
cdf_mem_copy(pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr,
sizeof(tSirMacAddr));
msgQ.type = WMA_SET_MAX_TX_POWER_REQ;
msgQ.reserved = 0;
msgQ.bodyptr = pMaxTxParams;
msgQ.bodyval = 0;
lim_log(pMac, LOG3,
FL("Sending WMA_SET_MAX_TX_POWER_REQ with power(%d) to HAL"),
txPower);
MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, msgQ.type));
if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
lim_log(pMac, LOGP,
FL
("Posting WMA_SET_MAX_TX_POWER_REQ to HAL failed, reason=%X"),
retCode);
cdf_mem_free(pMaxTxParams);
return retCode;
}
return retCode;
}
/* -------------------------------------------------------------------- */
/**
* rrm_set_max_tx_power_rsp
*
* FUNCTION: Process WMA_SET_MAX_TX_POWER_RSP message.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param txPower txPower to be set.
* @param pSessionEntry session entry.
* @return None
*/
tSirRetStatus rrm_set_max_tx_power_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ)
{
tSirRetStatus retCode = eSIR_SUCCESS;
tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr;
tpPESession pSessionEntry;
uint8_t sessionId, i;
tSirMacAddr bssid = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
if (cdf_mem_compare(bssid, pMaxTxParams->bssId, sizeof(tSirMacAddr))) {
for (i = 0; i < pMac->lim.maxBssId; i++) {
if ((pMac->lim.gpSession[i].valid == true)) {
pSessionEntry = &pMac->lim.gpSession[i];
rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power,
pSessionEntry);
}
}
} else {
if ((pSessionEntry =
pe_find_session_by_bssid(pMac, pMaxTxParams->bssId,
&sessionId)) == NULL) {
PELOGE(lim_log
(pMac, LOGE, FL("Unable to find session:"));
)
retCode = eSIR_FAILURE;
} else {
rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power,
pSessionEntry);
}
}
cdf_mem_free(limMsgQ->bodyptr);
limMsgQ->bodyptr = NULL;
return retCode;
}
/* -------------------------------------------------------------------- */
/**
* rrm_process_link_measurement_request
*
* FUNCTION: Processes the Link measurement request and send the report.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pBd pointer to BD to extract RSSI and SNR
* @param pLinkReq pointer to the Link request frame structure.
* @param pSessionEntry session entry.
* @return None
*/
tSirRetStatus
rrm_process_link_measurement_request(tpAniSirGlobal pMac,
uint8_t *pRxPacketInfo,
tDot11fLinkMeasurementRequest *pLinkReq,
tpPESession pSessionEntry)
{
tSirMacLinkReport LinkReport;
tpSirMacMgmtHdr pHdr;
int8_t currentRSSI = 0;
lim_log(pMac, LOG3, "Received Link measurement request");
if (pRxPacketInfo == NULL || pLinkReq == NULL || pSessionEntry == NULL) {
PELOGE(lim_log(pMac, LOGE,
"%s Invalid parameters - Ignoring the request",
__func__);
)
return eSIR_FAILURE;
}
pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
LinkReport.txPower = lim_get_max_tx_power(pLinkReq->MaxTxPower.maxTxPower,
pLinkReq->MaxTxPower.maxTxPower,
pMac->roam.configParam.
nTxPowerCap);
if ((LinkReport.txPower != (uint8_t) (pSessionEntry->maxTxPower)) &&
(eSIR_SUCCESS == rrm_send_set_max_tx_power_req(pMac,
(tPowerdBm) (LinkReport.
txPower),
pSessionEntry))) {
PELOGW(lim_log
(pMac, LOGW,
FL(" maxTx power in link report is not same as local..."
" Local = %d Link Request TxPower = %d"
" Link Report TxPower = %d"),
pSessionEntry->maxTxPower, LinkReport.txPower,
pLinkReq->MaxTxPower.maxTxPower);
)
pSessionEntry->maxTxPower =
(tPowerdBm) (LinkReport.txPower);
}
LinkReport.dialogToken = pLinkReq->DialogToken.token;
LinkReport.rxAntenna = 0;
LinkReport.txAntenna = 0;
currentRSSI = WMA_GET_RX_RSSI_DB(pRxPacketInfo);
lim_log(pMac, LOG1, "Received Link report frame with %d", currentRSSI);
/* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */
if ((currentRSSI) <= RCPI_LOW_RSSI_VALUE)
LinkReport.rcpi = 0;
else if ((currentRSSI > RCPI_LOW_RSSI_VALUE) && (currentRSSI <= 0))
LinkReport.rcpi = CALCULATE_RCPI(currentRSSI);
else
LinkReport.rcpi = RCPI_MAX_VALUE;
LinkReport.rsni = WMA_GET_RX_SNR(pRxPacketInfo);
lim_log(pMac, LOG3, "Sending Link report frame");
return lim_send_link_report_action_frame(pMac, &LinkReport, pHdr->sa,
pSessionEntry);
}
/* -------------------------------------------------------------------- */
/**
* rrm_process_neighbor_report_response
*
* FUNCTION: Processes the Neighbor Report response from the peer AP.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pNeighborRep pointer to the Neighbor report frame structure.
* @param pSessionEntry session entry.
* @return None
*/
tSirRetStatus
rrm_process_neighbor_report_response(tpAniSirGlobal pMac,
tDot11fNeighborReportResponse *pNeighborRep,
tpPESession pSessionEntry)
{
tSirRetStatus status = eSIR_FAILURE;
tpSirNeighborReportInd pSmeNeighborRpt = NULL;
uint16_t length;
uint8_t i;
tSirMsgQ mmhMsg;
if (pNeighborRep == NULL || pSessionEntry == NULL) {
PELOGE(lim_log(pMac, LOGE, FL(" Invalid parameters"));)
return status;
}
lim_log(pMac, LOG3, FL("Neighbor report response received "));
/* Dialog token */
if (pMac->rrm.rrmPEContext.DialogToken !=
pNeighborRep->DialogToken.token) {
PELOGE(lim_log
(pMac, LOGE,
"Dialog token mismatch in the received Neighbor report");
)
return eSIR_FAILURE;
}
if (pNeighborRep->num_NeighborReport == 0) {
PELOGE(lim_log
(pMac, LOGE,
"No neighbor report in the frame...Dropping it");
)
return eSIR_FAILURE;
}
length = (sizeof(tSirNeighborReportInd)) +
(sizeof(tSirNeighborBssDescription) *
(pNeighborRep->num_NeighborReport - 1));
/* Prepare the request to send to SME. */
pSmeNeighborRpt = cdf_mem_malloc(length);
if (NULL == pSmeNeighborRpt) {
PELOGE(lim_log(pMac, LOGP, FL("Unable to allocate memory"));)
return eSIR_MEM_ALLOC_FAILED;
}
cdf_mem_set(pSmeNeighborRpt, length, 0);
/* Allocated memory for pSmeNeighborRpt...will be freed by other module */
for (i = 0; i < pNeighborRep->num_NeighborReport; i++) {
pSmeNeighborRpt->sNeighborBssDescription[i].length = sizeof(tSirNeighborBssDescription); /*+ any optional ies */
cdf_mem_copy(pSmeNeighborRpt->sNeighborBssDescription[i].bssId,
pNeighborRep->NeighborReport[i].bssid,
sizeof(tSirMacAddr));
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fApPreauthReachable =
pNeighborRep->NeighborReport[i].APReachability;
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fSameSecurityMode =
pNeighborRep->NeighborReport[i].Security;
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fSameAuthenticator =
pNeighborRep->NeighborReport[i].KeyScope;
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fCapSpectrumMeasurement =
pNeighborRep->NeighborReport[i].SpecMgmtCap;
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fCapQos = pNeighborRep->NeighborReport[i].QosCap;
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fCapApsd = pNeighborRep->NeighborReport[i].apsd;
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fCapRadioMeasurement = pNeighborRep->NeighborReport[i].rrm;
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fCapDelayedBlockAck =
pNeighborRep->NeighborReport[i].DelayedBA;
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fCapImmediateBlockAck =
pNeighborRep->NeighborReport[i].ImmBA;
pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
fMobilityDomain =
pNeighborRep->NeighborReport[i].MobilityDomain;
pSmeNeighborRpt->sNeighborBssDescription[i].regClass =
pNeighborRep->NeighborReport[i].regulatoryClass;
pSmeNeighborRpt->sNeighborBssDescription[i].channel =
pNeighborRep->NeighborReport[i].channel;
pSmeNeighborRpt->sNeighborBssDescription[i].phyType =
pNeighborRep->NeighborReport[i].PhyType;
}
pSmeNeighborRpt->messageType = eWNI_SME_NEIGHBOR_REPORT_IND;
pSmeNeighborRpt->length = length;
pSmeNeighborRpt->sessionId = pSessionEntry->smeSessionId;
pSmeNeighborRpt->numNeighborReports = pNeighborRep->num_NeighborReport;
cdf_mem_copy(pSmeNeighborRpt->bssId, pSessionEntry->bssId,
sizeof(tSirMacAddr));
/* Send request to SME. */
mmhMsg.type = pSmeNeighborRpt->messageType;
mmhMsg.bodyptr = pSmeNeighborRpt;
MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, mmhMsg.type));
status = lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
return status;
}
/* -------------------------------------------------------------------- */
/**
* rrm_process_neighbor_report_req
*
* FUNCTION:
*
* LOGIC: Create a Neighbor report request and send it to peer.
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pNeighborReq Neighbor report request params .
* @return None
*/
tSirRetStatus
rrm_process_neighbor_report_req(tpAniSirGlobal pMac,
tpSirNeighborReportReqInd pNeighborReq)
{
tSirRetStatus status = eSIR_SUCCESS;
tSirMacNeighborReportReq NeighborReportReq;
tpPESession pSessionEntry;
uint8_t sessionId;
if (pNeighborReq == NULL) {
PELOGE(lim_log(pMac, LOGE, "NeighborReq is NULL");)
return eSIR_FAILURE;
}
if ((pSessionEntry =
pe_find_session_by_bssid(pMac, pNeighborReq->bssId,
&sessionId)) == NULL) {
PELOGE(lim_log
(pMac, LOGE,
FL("session does not exist for given bssId"));
)
return eSIR_FAILURE;
}
lim_log(pMac, LOG1, FL("SSID present = %d "), pNeighborReq->noSSID);
cdf_mem_set(&NeighborReportReq, sizeof(tSirMacNeighborReportReq), 0);
NeighborReportReq.dialogToken = ++pMac->rrm.rrmPEContext.DialogToken;
NeighborReportReq.ssid_present = !pNeighborReq->noSSID;
if (NeighborReportReq.ssid_present) {
cdf_mem_copy(&NeighborReportReq.ssid, &pNeighborReq->ucSSID,
sizeof(tSirMacSSid));
PELOGE(sir_dump_buf
(pMac, SIR_LIM_MODULE_ID, LOGE,
(uint8_t *) NeighborReportReq.ssid.ssId,
NeighborReportReq.ssid.length);
)
}
status =
lim_send_neighbor_report_request_frame(pMac, &NeighborReportReq,
pNeighborReq->bssId,
pSessionEntry);
return status;
}
#define ABS(x) ((x < 0) ? -x : x)
/* -------------------------------------------------------------------- */
/**
* rrm_process_beacon_report_req
*
* FUNCTION: Processes the Beacon report request from the peer AP.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pCurrentReq pointer to the current Req comtext.
* @param pBeaconReq pointer to the beacon report request IE from the peer.
* @param pSessionEntry session entry.
* @return None
*/
static tRrmRetStatus
rrm_process_beacon_report_req(tpAniSirGlobal pMac,
tpRRMReq pCurrentReq,
tDot11fIEMeasurementRequest *pBeaconReq,
tpPESession pSessionEntry)
{
tSirMsgQ mmhMsg;
tpSirBeaconReportReqInd pSmeBcnReportReq;
uint8_t num_channels = 0, num_APChanReport;
uint16_t measDuration, maxMeasduration;
int8_t maxDuration;
uint8_t sign;
if (pBeaconReq->measurement_request.Beacon.BeaconReporting.present &&
(pBeaconReq->measurement_request.Beacon.BeaconReporting.
reportingCondition != 0)) {
/* Repeated measurement is not supported. This means number of repetitions should be zero.(Already checked) */
/* All test case in VoWifi(as of version 0.36) use zero for number of repetitions. */
/* Beacon reporting should not be included in request if number of repetitons is zero. */
/* IEEE Std 802.11k-2008 Table 7-29g and section 11.10.8.1 */
PELOGE(lim_log
(pMac, LOGE,
"Dropping the request: Reporting condition included in beacon report request and it is not zero");
)
return eRRM_INCAPABLE;
}
/* The logic here is to check the measurement duration passed in the beacon request. Following are the cases handled.
Case 1: If measurement duration received in the beacon request is greater than the max measurement duration advertised
in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 1, REFUSE the beacon request
Case 2: If measurement duration received in the beacon request is greater than the max measurement duration advertised
in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 0, perform measurement for
the duration advertised in the RRM capabilities
maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval
*/
maxDuration =
pMac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4;
sign = (maxDuration < 0) ? 1 : 0;
maxDuration = (1L << ABS(maxDuration));
if (!sign)
maxMeasduration =
maxDuration * pSessionEntry->beaconParams.beaconInterval;
else
maxMeasduration =
pSessionEntry->beaconParams.beaconInterval / maxDuration;
measDuration = pBeaconReq->measurement_request.Beacon.meas_duration;
lim_log(pMac, LOG3,
"maxDuration = %d sign = %d maxMeasduration = %d measDuration = %d",
maxDuration, sign, maxMeasduration, measDuration);
if (maxMeasduration < measDuration) {
if (pBeaconReq->durationMandatory) {
PELOGE(lim_log
(pMac, LOGE,
"Dropping the request: duration mandatory and maxduration > measduration");
)
return eRRM_REFUSED;
} else
measDuration = maxMeasduration;
}
/* Cache the data required for sending report. */
pCurrentReq->request.Beacon.reportingDetail =
pBeaconReq->measurement_request.Beacon.BcnReportingDetail.
present ? pBeaconReq->measurement_request.Beacon.BcnReportingDetail.
reportingDetail : BEACON_REPORTING_DETAIL_ALL_FF_IE;
if (pBeaconReq->measurement_request.Beacon.RequestedInfo.present) {
pCurrentReq->request.Beacon.reqIes.pElementIds =
cdf_mem_malloc(sizeof(uint8_t) *
pBeaconReq->measurement_request.Beacon.
RequestedInfo.num_requested_eids);
if (NULL == pCurrentReq->request.Beacon.reqIes.pElementIds) {
lim_log(pMac, LOGP,
FL
("Unable to allocate memory for request IEs buffer"));
return eRRM_FAILURE;
}
lim_log(pMac, LOG3, FL(" Allocated memory for pElementIds"));
pCurrentReq->request.Beacon.reqIes.num =
pBeaconReq->measurement_request.Beacon.RequestedInfo.
num_requested_eids;
cdf_mem_copy(pCurrentReq->request.Beacon.reqIes.pElementIds,
pBeaconReq->measurement_request.Beacon.
RequestedInfo.requested_eids,
pCurrentReq->request.Beacon.reqIes.num);
}
if (pBeaconReq->measurement_request.Beacon.num_APChannelReport) {
for (num_APChanReport = 0;
num_APChanReport <
pBeaconReq->measurement_request.Beacon.num_APChannelReport;
num_APChanReport++)
num_channels +=
pBeaconReq->measurement_request.Beacon.
APChannelReport[num_APChanReport].num_channelList;
}
/* Prepare the request to send to SME. */
pSmeBcnReportReq = cdf_mem_malloc(sizeof(tSirBeaconReportReqInd));
if (NULL == pSmeBcnReportReq) {
lim_log(pMac, LOGP,
FL
("Unable to allocate memory during Beacon Report Req Ind to SME"));
return eRRM_FAILURE;
}
cdf_mem_set(pSmeBcnReportReq, sizeof(tSirBeaconReportReqInd), 0);
/* Allocated memory for pSmeBcnReportReq....will be freed by other modulea */
cdf_mem_copy(pSmeBcnReportReq->bssId, pSessionEntry->bssId,
sizeof(tSirMacAddr));
pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND;
pSmeBcnReportReq->length = sizeof(tSirBeaconReportReqInd);
pSmeBcnReportReq->uDialogToken = pBeaconReq->measurement_token;
pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_11K;
pSmeBcnReportReq->randomizationInterval =
SYS_TU_TO_MS(pBeaconReq->measurement_request.Beacon.randomization);
pSmeBcnReportReq->channelInfo.regulatoryClass =
pBeaconReq->measurement_request.Beacon.regClass;
pSmeBcnReportReq->channelInfo.channelNum =
pBeaconReq->measurement_request.Beacon.channel;
pSmeBcnReportReq->measurementDuration[0] = SYS_TU_TO_MS(measDuration);
pSmeBcnReportReq->fMeasurementtype[0] =
pBeaconReq->measurement_request.Beacon.meas_mode;
cdf_mem_copy(pSmeBcnReportReq->macaddrBssid,
pBeaconReq->measurement_request.Beacon.BSSID,
sizeof(tSirMacAddr));
if (pBeaconReq->measurement_request.Beacon.SSID.present) {
pSmeBcnReportReq->ssId.length =
pBeaconReq->measurement_request.Beacon.SSID.num_ssid;
cdf_mem_copy(pSmeBcnReportReq->ssId.ssId,
pBeaconReq->measurement_request.Beacon.SSID.ssid,
pSmeBcnReportReq->ssId.length);
}
pCurrentReq->token = pBeaconReq->measurement_token;
pSmeBcnReportReq->channelList.numChannels = num_channels;
if (pBeaconReq->measurement_request.Beacon.num_APChannelReport) {
uint8_t *pChanList =
pSmeBcnReportReq->channelList.channelNumber;
for (num_APChanReport = 0;
num_APChanReport <
pBeaconReq->measurement_request.Beacon.num_APChannelReport;
num_APChanReport++) {
cdf_mem_copy(pChanList,
pBeaconReq->measurement_request.Beacon.
APChannelReport[num_APChanReport].
channelList,
pBeaconReq->measurement_request.Beacon.
APChannelReport[num_APChanReport].
num_channelList);
pChanList +=
pBeaconReq->measurement_request.Beacon.
APChannelReport[num_APChanReport].num_channelList;
}
}
/* Send request to SME. */
mmhMsg.type = eWNI_SME_BEACON_REPORT_REQ_IND;
mmhMsg.bodyptr = pSmeBcnReportReq;
MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, mmhMsg.type));
return lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
}
/* -------------------------------------------------------------------- */
/**
* rrm_fill_beacon_ies
*
* FUNCTION:
*
* LOGIC: Fills Fixed fields and Ies in bss description to an array of uint8_t.
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pIes - pointer to the buffer that should be populated with ies.
* @param pNumIes - returns the num of ies filled in this param.
* @param pIesMaxSize - Max size of the buffer pIes.
* @param eids - pointer to array of eids. If NULL, all ies will be populated.
* @param numEids - number of elements in array eids.
* @param pBssDesc - pointer to Bss Description.
* @return None
*/
static void
rrm_fill_beacon_ies(tpAniSirGlobal pMac,
uint8_t *pIes, uint8_t *pNumIes, uint8_t pIesMaxSize,
uint8_t *eids, uint8_t numEids, tpSirBssDescription pBssDesc)
{
uint8_t len, *pBcnIes, count = 0, i;
uint8_t BcnNumIes;
if ((pIes == NULL) || (pNumIes == NULL) || (pBssDesc == NULL)) {
PELOGE(lim_log(pMac, LOGE, FL(" Invalid parameters"));)
return;
}
/* Make sure that if eid is null, numEids is set to zero. */
numEids = (eids == NULL) ? 0 : numEids;
pBcnIes = (uint8_t *) &pBssDesc->ieFields[0];
BcnNumIes = (uint8_t) GET_IE_LEN_IN_BSS(pBssDesc->length);
*pNumIes = 0;
*((uint32_t *) pIes) = pBssDesc->timeStamp[0];
*pNumIes += sizeof(uint32_t);
pIes += sizeof(uint32_t);
*((uint32_t *) pIes) = pBssDesc->timeStamp[1];
*pNumIes += sizeof(uint32_t);
pIes += sizeof(uint32_t);
*((uint16_t *) pIes) = pBssDesc->beaconInterval;
*pNumIes += sizeof(uint16_t);
pIes += sizeof(uint16_t);
*((uint16_t *) pIes) = pBssDesc->capabilityInfo;
*pNumIes += sizeof(uint16_t);
pIes += sizeof(uint16_t);
while (BcnNumIes > 0) {
len = *(pBcnIes + 1) + 2; /* element id + length. */
lim_log(pMac, LOG3, "EID = %d, len = %d total = %d",
*pBcnIes, *(pBcnIes + 1), len);
i = 0;
do {
if (((eids == NULL) || (*pBcnIes == eids[i])) &&
((*pNumIes) + len) < pIesMaxSize) {
lim_log(pMac, LOG3, "Adding Eid %d, len=%d",
*pBcnIes, len);
cdf_mem_copy(pIes, pBcnIes, len);
pIes += len;
*pNumIes += len;
count++;
break;
}
i++;
} while (i < numEids);
pBcnIes += len;
BcnNumIes -= len;
}
lim_log(pMac, LOG1, "Total length of Ies added = %d", *pNumIes);
}
/* -------------------------------------------------------------------- */
/**
* rrm_process_beacon_report_xmit
*
* FUNCTION:
*
* LOGIC: Create a Radio measurement report action frame and send it to peer.
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pBcnReport Data for beacon report IE from SME.
* @return None
*/
tSirRetStatus
rrm_process_beacon_report_xmit(tpAniSirGlobal pMac,
tpSirBeaconReportXmitInd pBcnReport)
{
tSirRetStatus status = eSIR_SUCCESS;
tSirMacRadioMeasureReport *pReport = NULL;
tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq;
tpPESession pSessionEntry;
uint8_t sessionId;
uint8_t flagBSSPresent = false, bssDescCnt = 0;
lim_log(pMac, LOG1, "Received beacon report xmit indication");
if (NULL == pBcnReport) {
PELOGE(lim_log(pMac, LOGE, "Received pBcnReport is NULL in PE");)
return eSIR_FAILURE;
}
if (NULL == pCurrentReq) {
PELOGE(lim_log(pMac, LOGE,
"Received report xmit while there is no request pending in PE");
)
return eSIR_FAILURE;
}
if ((pBcnReport->numBssDesc) ||
(!pBcnReport->numBssDesc && pCurrentReq->sendEmptyBcnRpt)) {
pBcnReport->numBssDesc =
(pBcnReport->numBssDesc ==
RRM_BCN_RPT_NO_BSS_INFO) ? RRM_BCN_RPT_MIN_RPT :
pBcnReport->numBssDesc;
if (NULL == (pSessionEntry = pe_find_session_by_bssid(pMac,
pBcnReport->
bssId,
&sessionId)))
{
PELOGE(lim_log
(pMac, LOGE,
FL("session does not exist for given bssId"));
)
return eSIR_FAILURE;
}
pReport = cdf_mem_malloc(pBcnReport->numBssDesc *
sizeof(tSirMacRadioMeasureReport));
if (NULL == pReport) {
PELOGE(lim_log
(pMac, LOGE,
FL("RRM Report is NULL, allocation failed"));
)
return eSIR_MEM_ALLOC_FAILED;
}
cdf_mem_zero(pReport,
pBcnReport->numBssDesc *
sizeof(tSirMacRadioMeasureReport));
for (bssDescCnt = 0; bssDescCnt < pBcnReport->numBssDesc;
bssDescCnt++) {
/* Prepare the beacon report and send it to the peer. */
pReport[bssDescCnt].token = pBcnReport->uDialogToken;
pReport[bssDescCnt].refused = 0;
pReport[bssDescCnt].incapable = 0;
pReport[bssDescCnt].type = SIR_MAC_RRM_BEACON_TYPE;
/* If the scan result is NULL then send report request with */
/* option subelement as NULL.. */
if (NULL != pBcnReport->pBssDescription[bssDescCnt]) {
flagBSSPresent = true;
}
/* Valid response is included if the size of beacon xmit */
/* is == size of beacon xmit ind + ies */
if (pBcnReport->length >=
sizeof(tSirBeaconReportXmitInd)) {
pReport[bssDescCnt].report.beaconReport.
regClass = pBcnReport->regClass;
if (flagBSSPresent) {
pReport[bssDescCnt].report.beaconReport.
channel =
pBcnReport->
pBssDescription[bssDescCnt]->
channelId;
cdf_mem_copy(pReport[bssDescCnt].report.
beaconReport.measStartTime,
pBcnReport->
pBssDescription
[bssDescCnt]->startTSF,
sizeof(pBcnReport->
pBssDescription
[bssDescCnt]->
startTSF));
pReport[bssDescCnt].report.beaconReport.
measDuration =
SYS_MS_TO_TU(pBcnReport->duration);
pReport[bssDescCnt].report.beaconReport.
phyType =
pBcnReport->
pBssDescription[bssDescCnt]->nwType;
pReport[bssDescCnt].report.beaconReport.
bcnProbeRsp = 1;
pReport[bssDescCnt].report.beaconReport.
rsni =
pBcnReport->
pBssDescription[bssDescCnt]->sinr;
pReport[bssDescCnt].report.beaconReport.
rcpi =
pBcnReport->
pBssDescription[bssDescCnt]->rssi;
pReport[bssDescCnt].report.beaconReport.
antennaId = 0;
pReport[bssDescCnt].report.beaconReport.
parentTSF =
pBcnReport->
pBssDescription[bssDescCnt]->
parentTSF;
cdf_mem_copy(pReport[bssDescCnt].report.
beaconReport.bssid,
pBcnReport->
pBssDescription
[bssDescCnt]->bssId,
sizeof(tSirMacAddr));
}
switch (pCurrentReq->request.Beacon.
reportingDetail) {
case BEACON_REPORTING_DETAIL_NO_FF_IE:
/* 0 No need to include any elements. */
lim_log(pMac, LOG3,
"No reporting detail requested");
break;
case BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE:
/* 1: Include all FFs and Requested Ies. */
lim_log(pMac, LOG3,
"Only requested IEs in reporting detail requested");
if (flagBSSPresent) {
rrm_fill_beacon_ies(pMac,
(uint8_t *) &
pReport
[bssDescCnt].
report.
beaconReport.
Ies[0],
(uint8_t *) &
pReport
[bssDescCnt].
report.
beaconReport.
numIes,
BEACON_REPORT_MAX_IES,
pCurrentReq->
request.Beacon.
reqIes.
pElementIds,
pCurrentReq->
request.Beacon.
reqIes.num,
pBcnReport->
pBssDescription
[bssDescCnt]);
}
break;
case BEACON_REPORTING_DETAIL_ALL_FF_IE:
/* 2 / default - Include all FFs and all Ies. */
default:
lim_log(pMac, LOG3,
"Default all IEs and FFs");
if (flagBSSPresent) {
rrm_fill_beacon_ies(pMac,
(uint8_t *) &
pReport
[bssDescCnt].
report.
beaconReport.
Ies[0],
(uint8_t *) &
pReport
[bssDescCnt].
report.
beaconReport.
numIes,
BEACON_REPORT_MAX_IES,
NULL, 0,
pBcnReport->
pBssDescription
[bssDescCnt]);
}
break;
}
}
}
lim_log(pMac, LOG1, "Sending Action frame with %d bss info",
bssDescCnt);
lim_send_radio_measure_report_action_frame(pMac,
pCurrentReq->dialog_token,
bssDescCnt, pReport,
pBcnReport->bssId,
pSessionEntry);
pCurrentReq->sendEmptyBcnRpt = false;
}
if (pBcnReport->fMeasureDone) {
lim_log(pMac, LOG3, "Measurement done....cleanup the context");
rrm_cleanup(pMac);
}
if (NULL != pReport)
cdf_mem_free(pReport);
return status;
}
void rrm_process_beacon_request_failure(tpAniSirGlobal pMac,
tpPESession pSessionEntry, tSirMacAddr peer,
tRrmRetStatus status)
{
tpSirMacRadioMeasureReport pReport = NULL;
tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq;
pReport = cdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
if (NULL == pReport) {
lim_log(pMac, LOGP,
FL
("Unable to allocate memory during RRM Req processing"));
return;
}
cdf_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0);
pReport->token = pCurrentReq->token;
pReport->type = SIR_MAC_RRM_BEACON_TYPE;
switch (status) {
case eRRM_REFUSED:
pReport->refused = 1;
break;
case eRRM_INCAPABLE:
pReport->incapable = 1;
break;
default:
PELOGE(lim_log(pMac, LOGE,
FL
(" Beacon request processing failed no report sent with status %d "),
status);
);
cdf_mem_free(pReport);
return;
}
lim_send_radio_measure_report_action_frame(pMac, pCurrentReq->dialog_token, 1,
pReport, peer, pSessionEntry);
cdf_mem_free(pReport);
lim_log(pMac, LOG3, FL(" Free memory for pReport"));
return;
}
/* -------------------------------------------------------------------- */
/**
* rrm_process_radio_measurement_request
*
* FUNCTION: Processes the Radio Resource Measurement request.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param peer Macaddress of the peer requesting the radio measurement.
* @param pRRMReq Array of Measurement request IEs
* @param pSessionEntry session entry.
* @return None
*/
tSirRetStatus
rrm_process_radio_measurement_request(tpAniSirGlobal pMac,
tSirMacAddr peer,
tDot11fRadioMeasurementRequest *pRRMReq,
tpPESession pSessionEntry)
{
uint8_t i;
tSirRetStatus status = eSIR_SUCCESS;
tpSirMacRadioMeasureReport pReport = NULL;
uint8_t num_report = 0;
tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq;
tRrmRetStatus rrmStatus = eRRM_SUCCESS;
if (!pRRMReq->num_MeasurementRequest) {
/* No measurement requests.... */
/* */
pReport = cdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
if (NULL == pReport) {
lim_log(pMac, LOGP,
FL
("Unable to allocate memory during RRM Req processing"));
return eSIR_MEM_ALLOC_FAILED;
}
cdf_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0);
PELOGE(lim_log(pMac, LOGE,
FL
("No requestIes in the measurement request, sending incapable report"));
)
pReport->incapable = 1;
num_report = 1;
lim_send_radio_measure_report_action_frame(pMac,
pRRMReq->DialogToken.token,
num_report, pReport, peer,
pSessionEntry);
cdf_mem_free(pReport);
return eSIR_FAILURE;
}
/* PF Fix */
if (pRRMReq->NumOfRepetitions.repetitions > 0) {
lim_log(pMac, LOG1,
FL(" number of repetitions %d"),
pRRMReq->NumOfRepetitions.repetitions);
/* Send a report with incapable bit set. Not supporting repetitions. */
pReport = cdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
if (NULL == pReport) {
lim_log(pMac, LOGP,
FL
("Unable to allocate memory during RRM Req processing"));
return eSIR_MEM_ALLOC_FAILED;
}
cdf_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0);
PELOGE(lim_log(pMac, LOGE, FL(" Allocated memory for pReport"));)
pReport->incapable = 1;
pReport->type = pRRMReq->MeasurementRequest[0].measurement_type;
num_report = 1;
goto end;
}
for (i = 0; i < pRRMReq->num_MeasurementRequest; i++) {
switch (pRRMReq->MeasurementRequest[i].measurement_type) {
case SIR_MAC_RRM_BEACON_TYPE:
/* Process beacon request. */
if (pCurrentReq) {
if (pReport == NULL) /* Allocate memory to send reports for any subsequent requests. */
{
pReport =
cdf_mem_malloc(sizeof
(tSirMacRadioMeasureReport)
*
(pRRMReq->
num_MeasurementRequest
- i));
if (NULL == pReport) {
lim_log(pMac, LOGP,
FL
("Unable to allocate memory during RRM Req processing"));
return eSIR_MEM_ALLOC_FAILED;
}
cdf_mem_set(pReport,
sizeof
(tSirMacRadioMeasureReport)
*
(pRRMReq->
num_MeasurementRequest -
i), 0);
lim_log(pMac, LOG3,
FL
(" rrm beacon type refused of %d report in beacon table"),
num_report);
}
pReport[num_report].refused = 1;
pReport[num_report].type =
SIR_MAC_RRM_BEACON_TYPE;
pReport[num_report].token =
pRRMReq->MeasurementRequest[i].
measurement_token;
num_report++;
continue;
} else {
pCurrentReq =
cdf_mem_malloc(sizeof(*pCurrentReq));
if (NULL == pCurrentReq) {
lim_log(pMac, LOGP,
FL
("Unable to allocate memory during RRM Req processing"));
cdf_mem_free(pReport);
return eSIR_MEM_ALLOC_FAILED;
}
lim_log(pMac, LOG3,
FL(" Processing Beacon Report request"));
cdf_mem_set(pCurrentReq, sizeof(*pCurrentReq),
0);
pCurrentReq->dialog_token =
pRRMReq->DialogToken.token;
pCurrentReq->token =
pRRMReq->MeasurementRequest[i].
measurement_token;
pCurrentReq->sendEmptyBcnRpt = true;
pMac->rrm.rrmPEContext.pCurrentReq =
pCurrentReq;
rrmStatus =
rrm_process_beacon_report_req(pMac, pCurrentReq,
&pRRMReq->
MeasurementRequest
[i],
pSessionEntry);
if (eRRM_SUCCESS != rrmStatus) {
rrm_process_beacon_request_failure(pMac,
pSessionEntry,
peer,
rrmStatus);
rrm_cleanup(pMac);
}
}
break;
case SIR_MAC_RRM_LCI_TYPE:
case SIR_MAC_RRM_LOCATION_CIVIC_TYPE:
case SIR_MAC_RRM_FINE_TIME_MEAS_TYPE:
lim_log(pMac, LOG1,
FL("RRM with type: %d sent to userspace"),
pRRMReq->MeasurementRequest[i].measurement_type);
break;
default:
/* Send a report with incapabale bit set. */
if (pReport == NULL) /* Allocate memory to send reports for any subsequent requests. */
{
pReport =
cdf_mem_malloc(sizeof
(tSirMacRadioMeasureReport)
*
(pRRMReq->
num_MeasurementRequest -
i));
if (NULL == pReport) {
lim_log(pMac, LOGP,
FL
("Unable to allocate memory during RRM Req processing"));
return eSIR_MEM_ALLOC_FAILED;
}
cdf_mem_set(pReport,
sizeof(tSirMacRadioMeasureReport)
* (pRRMReq->num_MeasurementRequest -
i), 0);
lim_log(pMac, LOG3,
FL
("rrm beacon type incapable of %d report "),
num_report);
}
pReport[num_report].incapable = 1;
pReport[num_report].type =
pRRMReq->MeasurementRequest[i].measurement_type;
pReport[num_report].token =
pRRMReq->MeasurementRequest[i].measurement_token;
num_report++;
break;
}
}
end:
if (pReport) {
lim_send_radio_measure_report_action_frame(pMac,
pRRMReq->DialogToken.token,
num_report, pReport, peer,
pSessionEntry);
cdf_mem_free(pReport);
lim_log(pMac, LOG3, FL(" Free memory for pReport"));
}
return status;
}
/* -------------------------------------------------------------------- */
/**
* rrm_update_start_tsf
**
* FUNCTION: Store start TSF of measurement.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param startTSF - TSF value at the start of measurement.
* @return None
*/
void rrm_update_start_tsf(tpAniSirGlobal pMac, uint32_t startTSF[2])
{
pMac->rrm.rrmPEContext.startTSF[0] = startTSF[0];
pMac->rrm.rrmPEContext.startTSF[1] = startTSF[1];
}
/* -------------------------------------------------------------------- */
/**
* rrm_get_start_tsf
*
* FUNCTION: Get the Start TSF.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param startTSF - store star TSF in this buffer.
* @return txPower
*/
void rrm_get_start_tsf(tpAniSirGlobal pMac, uint32_t *pStartTSF)
{
pStartTSF[0] = pMac->rrm.rrmPEContext.startTSF[0];
pStartTSF[1] = pMac->rrm.rrmPEContext.startTSF[1];
}
/* -------------------------------------------------------------------- */
/**
* rrm_get_capabilities
*
* FUNCTION:
* Returns a pointer to tpRRMCaps with all the caps enabled in RRM
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pSessionEntry
* @return pointer to tRRMCaps
*/
tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, tpPESession pSessionEntry)
{
return &pMac->rrm.rrmPEContext.rrmEnabledCaps;
}
/* -------------------------------------------------------------------- */
/**
* rrm_update_config
*
* FUNCTION:
* Update the configuration. This is called from lim_update_config.
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pSessionEntry
* @return pointer to tRRMCaps
*/
void rrm_update_config(tpAniSirGlobal pMac, tpPESession pSessionEntry)
{
uint32_t val;
tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps;
if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_ENABLED, &val) != eSIR_SUCCESS) {
lim_log(pMac, LOGP, FL("cfg get rrm enabled failed"));
return;
}
pMac->rrm.rrmPEContext.rrmEnable = (val) ? 1 : 0;
if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_OPERATING_CHAN_MAX, &val) !=
eSIR_SUCCESS) {
lim_log(pMac, LOGP,
FL
("cfg get rrm operating channel max measurement duration failed"));
return;
}
pRRMCaps->operatingChanMax = (uint8_t) val;
if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, &val) !=
eSIR_SUCCESS) {
lim_log(pMac, LOGP,
FL
("cfg get rrm non-operating channel max measurement duration failed"));
return;
}
pRRMCaps->nonOperatingChanMax = (uint8_t) val;
lim_log(pMac, LOG1,
"RRM enabled = %d OperatingChanMax = %d NonOperatingMax = %d",
pMac->rrm.rrmPEContext.rrmEnable,
pRRMCaps->operatingChanMax, pRRMCaps->nonOperatingChanMax);
}
/* -------------------------------------------------------------------- */
/**
* rrm_initialize
*
* FUNCTION:
* Initialize RRM module
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @return None
*/
tSirRetStatus rrm_initialize(tpAniSirGlobal pMac)
{
tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps;
pMac->rrm.rrmPEContext.pCurrentReq = NULL;
pMac->rrm.rrmPEContext.txMgmtPower = 0;
pMac->rrm.rrmPEContext.DialogToken = 0;
pMac->rrm.rrmPEContext.rrmEnable = 0;
cdf_mem_set(pRRMCaps, sizeof(tRRMCaps), 0);
pRRMCaps->LinkMeasurement = 1;
pRRMCaps->NeighborRpt = 1;
pRRMCaps->BeaconPassive = 1;
pRRMCaps->BeaconActive = 1;
pRRMCaps->BeaconTable = 1;
pRRMCaps->APChanReport = 1;
pRRMCaps->fine_time_meas_rpt = 1;
pRRMCaps->lci_capability = 1;
pRRMCaps->operatingChanMax = 3;
pRRMCaps->nonOperatingChanMax = 3;
return eSIR_SUCCESS;
}
/* -------------------------------------------------------------------- */
/**
* rrm_cleanup
*
* FUNCTION:
* cleanup RRM module
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param mode
* @param rate
* @return None
*/
tSirRetStatus rrm_cleanup(tpAniSirGlobal pMac)
{
if (pMac->rrm.rrmPEContext.pCurrentReq) {
if (pMac->rrm.rrmPEContext.pCurrentReq->request.Beacon.reqIes.
pElementIds) {
cdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq->
request.Beacon.reqIes.pElementIds);
lim_log(pMac, LOG4, FL(" Free memory for pElementIds"));
}
cdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq);
lim_log(pMac, LOG4, FL(" Free memory for pCurrentReq"));
}
pMac->rrm.rrmPEContext.pCurrentReq = NULL;
return eSIR_SUCCESS;
}
/* -------------------------------------------------------------------- */
/**
* rrm_process_message
*
* FUNCTION: Processes the next received Radio Resource Management message
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param None
* @return None
*/
void rrm_process_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
{
switch (pMsg->type) {
case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
rrm_process_neighbor_report_req(pMac, pMsg->bodyptr);
break;
case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
rrm_process_beacon_report_xmit(pMac, pMsg->bodyptr);
break;
}
}
#endif