Wlan: Extended IBSS feature on prima
Changes to enable extended IBSS feature on prima open
source branch.
Change-Id: Iacaad2627d241fa6b71717d0cfbba960f0fd5d5f
CRs-Fixed: 766181
diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h
index be90e1f..d4e503e 100644
--- a/CORE/MAC/inc/aniGlobal.h
+++ b/CORE/MAC/inc/aniGlobal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -92,6 +92,8 @@
#endif
#include "p2p_Api.h"
+#include "limRMC.h"
+
#if defined WLAN_FEATURE_VOWIFI_11R
#include <limFTDefs.h>
#endif
@@ -1049,6 +1051,9 @@
v_BOOL_t isTdlsPowerSaveProhibited;
#endif
tANI_U8 fScanOffload;
+#ifdef WLAN_FEATURE_RMC
+ tLimRmcContext rmcContext;
+#endif /* WLAN_FEATURE_RMC */
tANI_U8 isCoalesingInIBSSAllowed;
tANI_U32 fEnableDebugLog;
tANI_U32 fDeferIMPSTime;
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 6399687..ce299dd 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -2312,6 +2312,16 @@
} tAniDHCPInd, *tpAniDHCPInd;
+#ifdef WLAN_FEATURE_RMC
+typedef struct sAniTXFailMonitorInd
+{
+ tANI_U16 msgType; // message type is same as the request type
+ tANI_U16 msgLen; // length of the entire request
+ tANI_U8 tx_fail_count;
+ void *txFailIndCallback;
+} tAniTXFailMonitorInd, *tpAniTXFailMonitorInd;
+#endif /* WLAN_FEATURE_RMC */
+
typedef struct sAniSummaryStatsInfo
{
tANI_U32 retry_cnt[4]; //Total number of packets(per AC) that were successfully transmitted with retries
@@ -4674,10 +4684,10 @@
* 0 implies MCAST RA, positive value implies fixed rate,
* -1 implies ignore this param
*/
- tANI_S32 reliableMcastDataRate;//unit Mbpsx10
+ tANI_S32 rmcDataRate;//unit Mbpsx10
/* TX flag to differentiate between HT20, HT40 etc */
- tTxrateinfoflags reliableMcastDataRateTxFlag;
+ tTxrateinfoflags rmcDataRateTxFlag;
/*
* MCAST(or BCAST) fixed data rate in 2.4 GHz, unit Mbpsx10,
@@ -4699,6 +4709,102 @@
} tSirRateUpdateInd, *tpSirRateUpdateInd;
+#ifdef WLAN_FEATURE_RMC
+
+#define SIR_RMC_NUM_MAX_RULERS 8 /* HAL_NUM_MAX_RULERS */
+typedef struct sSirSetRMCReq
+{
+ tANI_U16 msgType;
+ tANI_U16 msgLen;
+ tSirMacAddr mcastTransmitter;
+} tSirSetRMCReq, *tpSirSetRMCReq;
+
+typedef struct sSirRMCInfo
+{
+ tANI_U32 dialogToken;
+ tANI_U8 action;
+ tSirMacAddr mcastRuler;
+} tSirRMCInfo, *tpSirRMCInfo;
+
+typedef struct sSirRmcRulerSelectInd
+{
+ tANI_U16 status;
+ tSirMacAddr mcastTransmitter;
+ tSirMacAddr mcastGroup;
+ tSirMacAddr ruler[SIR_RMC_NUM_MAX_RULERS];
+} tSirRmcRulerSelectInd, *tpSirRmcRulerSelectInd;
+
+typedef struct sSirRmcBecomeRulerInd
+{
+ tANI_U16 status;
+ tSirMacAddr mcastTransmitter;
+ tSirMacAddr mcastGroup;
+} tSirRmcBecomeRulerInd, *tpSirRmcBecomeRulerInd;
+
+typedef struct sSirRmcRulerReq
+{
+ // Common for all types are requests
+ tANI_U16 msgType; // message type is same as the request type
+ tANI_U16 msgLen; // length of the entire request
+ tANI_U8 cmd; // tRulerReqCmdType
+ tSirMacAddr mcastTransmitter;
+ tSirMacAddr mcastGroup;
+ tSirMacAddr blacklist[SIR_RMC_NUM_MAX_RULERS];
+} tSirRmcRulerReq, *tpSirRmcRulerReq;
+
+typedef struct sSirRmcUpdateInd
+{
+ // Common for all types are requests
+ tANI_U16 msgType; // message type is same as the request type
+ tANI_U16 msgLen; // length of the entire request
+ tANI_U8 indication; // trulerUpdateIndType
+ tANI_U8 role; // tRoleType
+ tSirMacAddr mcastTransmitter;
+ tSirMacAddr mcastGroup;
+ tSirMacAddr mcastRuler;
+ tSirMacAddr ruler[SIR_RMC_NUM_MAX_RULERS];
+} tSirRmcUpdateInd, *tpSirRmcUpdateInd;
+
+/*---------------------------------------------------------------------------
+* tSirIbssGetPeerInfoReqParams
+*--------------------------------------------------------------------------*/
+typedef struct
+{
+ tANI_BOOLEAN allPeerInfoReqd; // If set, all IBSS peers stats are reported
+ tANI_U8 staIdx; // If allPeerInfoReqd is not set, only stats
+ // of peer with staIdx is reported
+}tSirIbssGetPeerInfoReqParams, *tpSirIbssGetPeerInfoReqParams;
+
+/*---------------------------------------------------------------------------
+* tSirIbssGetPeerInfoParams
+*--------------------------------------------------------------------------*/
+typedef struct
+{
+ tANI_U8 staIdx; //StaIdx
+ tANI_U32 txRate; //Tx Rate
+ tANI_U32 mcsIndex; //MCS Index
+ tANI_U32 txRateFlags; //TxRate Flags
+ tANI_S8 rssi; //RSSI
+}tSirIbssPeerInfoParams;
+
+typedef struct
+{
+ tANI_U32 status;
+ tANI_U8 numPeers;
+ tSirIbssPeerInfoParams peerInfoParams[32];
+}tSirPeerInfoRspParams, *tpSirIbssPeerInfoRspParams;
+
+/*---------------------------------------------------------------------------
+* tSirIbssGetPeerInfoRspParams
+*--------------------------------------------------------------------------*/
+typedef struct
+{
+ tANI_U16 mesgType;
+ tANI_U16 mesgLen;
+ tSirPeerInfoRspParams ibssPeerInfoRspParams;
+} tSirIbssGetPeerInfoRspParams, *tpSirIbssGetPeerInfoRspParams;
+#endif /* WLAN_FEATURE_RMC */
+
#ifdef FEATURE_WLAN_BATCH_SCAN
// Set batch scan resposne from FW
typedef struct
diff --git a/CORE/MAC/inc/sirMacProtDef.h b/CORE/MAC/inc/sirMacProtDef.h
index bf8efd3..b635693 100644
--- a/CORE/MAC/inc/sirMacProtDef.h
+++ b/CORE/MAC/inc/sirMacProtDef.h
@@ -2448,6 +2448,18 @@
} __ani_attr_packed tSirMacVendorSpecificFrameHdr, *tpSirMacVendorSpecificFrameHdr;
#endif
+#ifdef WLAN_FEATURE_RMC
+typedef __ani_attr_pre_packed struct sSirMacIbssExtNetworkFrameHdr
+{
+ tANI_U8 category;
+ tANI_U8 Oui[3];
+ tANI_U8 MagicCode[6];
+ tANI_U8 version;
+ tANI_U8 actionID;
+ tANI_U32 dialogToken;
+} __ani_attr_packed tSirMacIbssExtNetworkFrameHdr, *tpSirMacIbssExtNetworkFrameHdr;
+#endif /* WLAN_FEATURE_RMC */
+
typedef __ani_attr_pre_packed struct sSirMacVendorSpecificPublicActionFrameHdr
{
tANI_U8 category;
@@ -2879,6 +2891,24 @@
#define SIR_MAC_MIN_IE_LEN 2 // Minimum IE length for IE validation
+#ifdef WLAN_FEATURE_RMC
+
+// RMC action codes
+#define SIR_MAC_RMC_ENABLE_REQ 0
+#define SIR_MAC_RMC_DISABLE_REQ 1
+#define SIR_MAC_RMC_RULER_INFORM_SELECTED 2
+#define SIR_MAC_RMC_RULER_INFORM_CANCELLED 3
+
+// RMC protocol version
+#define SIR_MAC_RMC_VER 0x01
+
+// Organization Identifier
+#define SIR_MAC_RMC_OUI "\x00\x16\x32"
+#define SIR_MAC_RMC_OUI_SIZE 3
+
+#define SIR_MAC_RMC_MCAST_ADDRESS "\x01\x00\x5E\x00\x02\x0A"
+
+#endif /* WLAN_FEATURE_RMC */
#define SIR_MAC_TI_TYPE_REASSOC_DEADLINE 1
#define SIR_MAC_TI_TYPE_KEY_LIFETIME 2
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index 466d8f9..4c22db5 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -359,7 +359,11 @@
#ifdef FEATURE_WLAN_LPHB
eWNI_SME_LPHB_IND,
#endif /* FEATURE_WLAN_LPHB */
-
+#ifdef WLAN_FEATURE_RMC
+ eWNI_SME_ENABLE_RMC_REQ,
+ eWNI_SME_DISABLE_RMC_REQ,
+ eWNI_SME_IBSS_PEER_INFO_RSP,
+#endif /* WLAN_FEATURE_RMC */
eWNI_SME_GET_TSM_STATS_REQ,
eWNI_SME_GET_TSM_STATS_RSP,
eWNI_SME_TSM_IE_IND,
diff --git a/CORE/MAC/inc/wniCfg.h b/CORE/MAC/inc/wniCfg.h
index d9e4e5a..441caf0 100644
--- a/CORE/MAC/inc/wniCfg.h
+++ b/CORE/MAC/inc/wniCfg.h
@@ -340,12 +340,12 @@
WNI_CFG_FLEX_CONNECT_POWER_FACTOR,
WNI_CFG_ANTENNA_DIVESITY,
WNI_CFG_GO_LINK_MONITOR_TIMEOUT,
+ WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
WNI_CFG_ATH_DISABLE,
WNI_CFG_BTC_ACTIVE_WLAN_LEN,
WNI_CFG_BTC_ACTIVE_BT_LEN,
WNI_CFG_BTC_SAP_ACTIVE_WLAN_LEN,
WNI_CFG_BTC_SAP_ACTIVE_BT_LEN,
- WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
WNI_CFG_ASD_PROBE_INTERVAL,
WNI_CFG_ASD_TRIGGER_THRESHOLD,
WNI_CFG_ASD_RTT_RSSI_HYST_THRESHOLD,
@@ -1701,6 +1701,10 @@
#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMAX 50
#define WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STADEF 10
+#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN 100
+#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX 1000
+#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF 300
+
#define WNI_CFG_ATH_DISABLE_STAMIN 0
#define WNI_CFG_ATH_DISABLE_STAMAX 1
#define WNI_CFG_ATH_DISABLE_STADEF 0
@@ -1721,10 +1725,6 @@
#define WNI_CFG_BTC_SAP_ACTIVE_BT_LEN_STAMAX 250000
#define WNI_CFG_BTC_SAP_ACTIVE_BT_LEN_STADEF 30000
-#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN 0
-#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX 4294967295
-#define WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF 300
-
#define WNI_CFG_ASD_PROBE_INTERVAL_STAMIN 1
#define WNI_CFG_ASD_PROBE_INTERVAL_STAMAX 500
#define WNI_CFG_ASD_PROBE_INTERVAL_STADEF 50
diff --git a/CORE/MAC/src/cfg/cfgParamName.c b/CORE/MAC/src/cfg/cfgParamName.c
index b74ba4c..5fda170 100644
--- a/CORE/MAC/src/cfg/cfgParamName.c
+++ b/CORE/MAC/src/cfg/cfgParamName.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, 2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -341,12 +341,12 @@
(unsigned char *)"FLEX_CONNECT_POWER_FACTOR",
(unsigned char *)"ANTENNA_DIVESITY",
(unsigned char *)"GO_LINK_MONITOR_TIMEOUT",
+ (unsigned char *)"RMC_ACTION_PERIOD_FREQUENCY",
(unsigned char *)"ATH_DISABLE",
(unsigned char *)"BTC_ACTIVE_WLAN_LEN",
(unsigned char *)"BTC_ACTIVE_BT_LEN",
(unsigned char *)"BTC_SAP_ACTIVE_WLAN_LEN",
(unsigned char *)"BTC_SAP_ACTIVE_BT_LEN",
- (unsigned char *)"RMC_ACTION_PERIOD_FREQUENCY",
(unsigned char *)"ASD_PROBE_INTERVAL",
(unsigned char *)"ASD_TRIGGER_THRESHOLD",
(unsigned char *)"ASD_RTT_RSSI_HYST_THRESHOLD",
diff --git a/CORE/MAC/src/cfg/cfgProcMsg.c b/CORE/MAC/src/cfg/cfgProcMsg.c
index e25a798..ab7ed15 100644
--- a/CORE/MAC/src/cfg/cfgProcMsg.c
+++ b/CORE/MAC/src/cfg/cfgProcMsg.c
@@ -1440,6 +1440,12 @@
WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMIN,
WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STAMAX,
WNI_CFG_GO_LINK_MONITOR_TIMEOUT_STADEF},
+ {WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
+ CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_NTF_HAL,
+ WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN,
+ WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMAX,
+ WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF},
+
{WNI_CFG_ATH_DISABLE,
CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT,
WNI_CFG_ATH_DISABLE_STAMIN,
@@ -1465,11 +1471,6 @@
WNI_CFG_BTC_SAP_ACTIVE_BT_LEN_STAMIN,
WNI_CFG_BTC_SAP_ACTIVE_BT_LEN_STAMAX,
WNI_CFG_BTC_SAP_ACTIVE_BT_LEN_STADEF},
- {WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
- CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_NTF_HAL,
- WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STAMIN,
- 4294967295u,
- WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF},
{WNI_CFG_ASD_PROBE_INTERVAL,
CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT | CFG_CTL_NTF_HAL,
WNI_CFG_ASD_PROBE_INTERVAL_STAMIN,
diff --git a/CORE/MAC/src/cfg/cfgUtil/cfg.txt b/CORE/MAC/src/cfg/cfgUtil/cfg.txt
index 87aba50..c08458f 100644
--- a/CORE/MAC/src/cfg/cfgUtil/cfg.txt
+++ b/CORE/MAC/src/cfg/cfgUtil/cfg.txt
@@ -1,5 +1,5 @@
*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -4601,7 +4601,18 @@
*
*
-* ATH Enable/Disable
+* RMC action period frequency (milli seconds)
+*
+WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY I 4 7
+V RW NP
+HAL
+100 1000 300
+V RW NP
+HAL
+100 1000 300
+*
+*
+
*
WNI_CFG_ATH_DISABLE I 4 7
V RW NP
@@ -4658,18 +4669,6 @@
*
*
-* RMC action period frequency (milli seconds)
-*
-WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY I 4 7
-V RW NP
-HAL
-0 0xFFFFFFFF 300
-V RW NP
-HAL
-0 0xFFFFFFFF 300
-*
-*
-
* Rssi probe interval (milli seconds)
*
WNI_CFG_ASD_PROBE_INTERVAL I 4 7
diff --git a/CORE/MAC/src/cfg/cfgUtil/dot11f.frms b/CORE/MAC/src/cfg/cfgUtil/dot11f.frms
index 87bbc65..18c9889 100644
--- a/CORE/MAC/src/cfg/cfgUtil/dot11f.frms
+++ b/CORE/MAC/src/cfg/cfgUtil/dot11f.frms
@@ -419,6 +419,31 @@
ouiSubtype, 1;
}
+FF RMCOUI (3)
+{
+ oui[3];
+}
+
+FF MagicCode (6)
+{
+ magic[6];
+}
+
+FF RMCVersion (1)
+{
+ version, 1;
+}
+
+FF RMCDialogToken (4)
+{
+ token, 4;
+}
+
+FF Ruler (6)
+{
+ mac[6];
+}
+
FF VhtMembershipStatusArray(8) // 8.4.1.51
{
membershipStatusArray[8];
@@ -4242,6 +4267,17 @@
MANDIE QosMapSet;
}
+FRAME RMC
+{
+ FF Category;
+ FF RMCOUI;
+ FF MagicCode;
+ FF RMCVersion;
+ FF Action;
+ FF RMCDialogToken;
+ FF Ruler;
+}
+
FRAME VHTGidManagementActionFrame
{
FF Category;
diff --git a/CORE/MAC/src/include/dot11f.h b/CORE/MAC/src/include/dot11f.h
index e08fd48..32e6981 100644
--- a/CORE/MAC/src/include/dot11f.h
+++ b/CORE/MAC/src/include/dot11f.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -30,7 +30,7 @@
*
*
* This file was automatically generated by 'framesc'
- * Mon Nov 10 19:49:53 2014 from the following file(s):
+ * Wed Sep 9 10:17:04 2015 from the following file(s):
*
* dot11f.frms
*
@@ -316,6 +316,16 @@
void dot11fPackFfListenInterval(tpAniSirGlobal, tDot11fFfListenInterval*, tANI_U8*);
+typedef struct sDot11fFfMagicCode {
+ tANI_U8 magic[6];
+} tDot11fFfMagicCode;
+
+#define DOT11F_FF_MAGICCODE_LEN ( 6 )
+
+void dot11fUnpackFfMagicCode(tpAniSirGlobal, tANI_U8*, tDot11fFfMagicCode*);
+
+void dot11fPackFfMagicCode(tpAniSirGlobal, tDot11fFfMagicCode*, tANI_U8*);
+
typedef struct sDot11fFfMaxTxPower {
tANI_U8 maxTxPower;
} tDot11fFfMaxTxPower;
@@ -388,6 +398,36 @@
void dot11fPackFfRCPI(tpAniSirGlobal, tDot11fFfRCPI*, tANI_U8*);
+typedef struct sDot11fFfRMCDialogToken {
+ tANI_U32 token;
+} tDot11fFfRMCDialogToken;
+
+#define DOT11F_FF_RMCDIALOGTOKEN_LEN ( 4 )
+
+void dot11fUnpackFfRMCDialogToken(tpAniSirGlobal, tANI_U8*, tDot11fFfRMCDialogToken*);
+
+void dot11fPackFfRMCDialogToken(tpAniSirGlobal, tDot11fFfRMCDialogToken*, tANI_U8*);
+
+typedef struct sDot11fFfRMCOUI {
+ tANI_U8 oui[3];
+} tDot11fFfRMCOUI;
+
+#define DOT11F_FF_RMCOUI_LEN ( 3 )
+
+void dot11fUnpackFfRMCOUI(tpAniSirGlobal, tANI_U8*, tDot11fFfRMCOUI*);
+
+void dot11fPackFfRMCOUI(tpAniSirGlobal, tDot11fFfRMCOUI*, tANI_U8*);
+
+typedef struct sDot11fFfRMCVersion {
+ tANI_U8 version;
+} tDot11fFfRMCVersion;
+
+#define DOT11F_FF_RMCVERSION_LEN ( 1 )
+
+void dot11fUnpackFfRMCVersion(tpAniSirGlobal, tANI_U8*, tDot11fFfRMCVersion*);
+
+void dot11fPackFfRMCVersion(tpAniSirGlobal, tDot11fFfRMCVersion*, tANI_U8*);
+
typedef struct sDot11fFfRSNI {
tANI_U8 rsni;
} tDot11fFfRSNI;
@@ -408,6 +448,16 @@
void dot11fPackFfReason(tpAniSirGlobal, tDot11fFfReason*, tANI_U8*);
+typedef struct sDot11fFfRuler {
+ tANI_U8 mac[6];
+} tDot11fFfRuler;
+
+#define DOT11F_FF_RULER_LEN ( 6 )
+
+void dot11fUnpackFfRuler(tpAniSirGlobal, tANI_U8*, tDot11fFfRuler*);
+
+void dot11fPackFfRuler(tpAniSirGlobal, tDot11fFfRuler*, tANI_U8*);
+
typedef struct sDot11fFfRxAntennaId {
tANI_U8 antennaId;
} tDot11fFfRxAntennaId;
@@ -7298,6 +7348,30 @@
} /* End extern "C". */
#endif /* C++ */
+typedef struct sDot11fRMC{
+ tDot11fFfCategory Category;
+ tDot11fFfRMCOUI RMCOUI;
+ tDot11fFfMagicCode MagicCode;
+ tDot11fFfRMCVersion RMCVersion;
+ tDot11fFfAction Action;
+ tDot11fFfRMCDialogToken RMCDialogToken;
+ tDot11fFfRuler Ruler;
+} tDot11fRMC;
+
+#define DOT11F_RMC ( 41 )
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* C++ */
+
+tANI_U32 dot11fUnpackRMC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fRMC *pFrm);
+tANI_U32 dot11fPackRMC(tpAniSirGlobal pCtx, tDot11fRMC *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed);
+tANI_U32 dot11fGetPackedRMCSize(tpAniSirGlobal pCtx, tDot11fRMC *pFrm, tANI_U32 *pnNeeded);
+
+#ifdef __cplusplus
+} /* End extern "C". */
+#endif /* C++ */
+
typedef struct sDot11fRadioMeasurementReport{
tDot11fFfCategory Category;
tDot11fFfAction Action;
@@ -7306,7 +7380,7 @@
tDot11fIEMeasurementReport MeasurementReport[4];
} tDot11fRadioMeasurementReport;
-#define DOT11F_RADIOMEASUREMENTREPORT ( 41 )
+#define DOT11F_RADIOMEASUREMENTREPORT ( 42 )
#ifdef __cplusplus
extern "C" {
@@ -7329,7 +7403,7 @@
tDot11fIEMeasurementRequest MeasurementRequest[2];
} tDot11fRadioMeasurementRequest;
-#define DOT11F_RADIOMEASUREMENTREQUEST ( 42 )
+#define DOT11F_RADIOMEASUREMENTREQUEST ( 43 )
#ifdef __cplusplus
extern "C" {
@@ -7380,7 +7454,7 @@
tDot11fIEQosMapSet QosMapSet;
} tDot11fReAssocRequest;
-#define DOT11F_REASSOCREQUEST ( 43 )
+#define DOT11F_REASSOCREQUEST ( 44 )
#ifdef __cplusplus
extern "C" {
@@ -7430,7 +7504,7 @@
tDot11fIEQosMapSet QosMapSet;
} tDot11fReAssocResponse;
-#define DOT11F_REASSOCRESPONSE ( 44 )
+#define DOT11F_REASSOCRESPONSE ( 45 )
#ifdef __cplusplus
extern "C" {
@@ -7450,7 +7524,7 @@
tDot11fFfSMPowerModeSet SMPowerModeSet;
} tDot11fSMPowerSave;
-#define DOT11F_SMPOWERSAVE ( 45 )
+#define DOT11F_SMPOWERSAVE ( 46 )
#ifdef __cplusplus
extern "C" {
@@ -7470,7 +7544,7 @@
tDot11fFfTransactionId TransactionId;
} tDot11fSaQueryReq;
-#define DOT11F_SAQUERYREQ ( 46 )
+#define DOT11F_SAQUERYREQ ( 47 )
#ifdef __cplusplus
extern "C" {
@@ -7490,7 +7564,7 @@
tDot11fFfTransactionId TransactionId;
} tDot11fSaQueryRsp;
-#define DOT11F_SAQUERYRSP ( 47 )
+#define DOT11F_SAQUERYRSP ( 48 )
#ifdef __cplusplus
extern "C" {
@@ -7511,7 +7585,7 @@
tDot11fIELinkIdentifier LinkIdentifier;
} tDot11fTDLSDisReq;
-#define DOT11F_TDLSDISREQ ( 48 )
+#define DOT11F_TDLSDISREQ ( 49 )
#ifdef __cplusplus
extern "C" {
@@ -7545,7 +7619,7 @@
tDot11fIEVHTCaps VHTCaps;
} tDot11fTDLSDisRsp;
-#define DOT11F_TDLSDISRSP ( 49 )
+#define DOT11F_TDLSDISRSP ( 50 )
#ifdef __cplusplus
extern "C" {
@@ -7568,7 +7642,7 @@
tDot11fIEPUBufferStatus PUBufferStatus;
} tDot11fTDLSPeerTrafficInd;
-#define DOT11F_TDLSPEERTRAFFICIND ( 50 )
+#define DOT11F_TDLSPEERTRAFFICIND ( 51 )
#ifdef __cplusplus
extern "C" {
@@ -7589,7 +7663,7 @@
tDot11fIELinkIdentifier LinkIdentifier;
} tDot11fTDLSPeerTrafficRsp;
-#define DOT11F_TDLSPEERTRAFFICRSP ( 51 )
+#define DOT11F_TDLSPEERTRAFFICRSP ( 52 )
#ifdef __cplusplus
extern "C" {
@@ -7620,7 +7694,7 @@
tDot11fIEOperatingMode OperatingMode;
} tDot11fTDLSSetupCnf;
-#define DOT11F_TDLSSETUPCNF ( 52 )
+#define DOT11F_TDLSSETUPCNF ( 53 )
#ifdef __cplusplus
extern "C" {
@@ -7658,7 +7732,7 @@
tDot11fIEVHTCaps VHTCaps;
} tDot11fTDLSSetupReq;
-#define DOT11F_TDLSSETUPREQ ( 53 )
+#define DOT11F_TDLSSETUPREQ ( 54 )
#ifdef __cplusplus
extern "C" {
@@ -7698,7 +7772,7 @@
tDot11fIEOperatingMode OperatingMode;
} tDot11fTDLSSetupRsp;
-#define DOT11F_TDLSSETUPRSP ( 54 )
+#define DOT11F_TDLSSETUPRSP ( 55 )
#ifdef __cplusplus
extern "C" {
@@ -7720,7 +7794,7 @@
tDot11fIELinkIdentifier LinkIdentifier;
} tDot11fTDLSTeardown;
-#define DOT11F_TDLSTEARDOWN ( 55 )
+#define DOT11F_TDLSTEARDOWN ( 56 )
#ifdef __cplusplus
extern "C" {
@@ -7741,7 +7815,7 @@
tDot11fIETPCReport TPCReport;
} tDot11fTPCReport;
-#define DOT11F_TPCREPORT ( 56 )
+#define DOT11F_TPCREPORT ( 57 )
#ifdef __cplusplus
extern "C" {
@@ -7762,7 +7836,7 @@
tDot11fIETPCRequest TPCRequest;
} tDot11fTPCRequest;
-#define DOT11F_TPCREQUEST ( 57 )
+#define DOT11F_TPCREQUEST ( 58 )
#ifdef __cplusplus
extern "C" {
@@ -7783,7 +7857,7 @@
tDot11fFfVhtUserPositionArray VhtUserPositionArray;
} tDot11fVHTGidManagementActionFrame;
-#define DOT11F_VHTGIDMANAGEMENTACTIONFRAME ( 58 )
+#define DOT11F_VHTGIDMANAGEMENTACTIONFRAME ( 59 )
#ifdef __cplusplus
extern "C" {
@@ -7806,7 +7880,7 @@
tDot11fIEESETrafStrmRateSet ESETrafStrmRateSet;
} tDot11fWMMAddTSRequest;
-#define DOT11F_WMMADDTSREQUEST ( 59 )
+#define DOT11F_WMMADDTSREQUEST ( 60 )
#ifdef __cplusplus
extern "C" {
@@ -7829,7 +7903,7 @@
tDot11fIEESETrafStrmMet ESETrafStrmMet;
} tDot11fWMMAddTSResponse;
-#define DOT11F_WMMADDTSRESPONSE ( 60 )
+#define DOT11F_WMMADDTSRESPONSE ( 61 )
#ifdef __cplusplus
extern "C" {
@@ -7851,7 +7925,7 @@
tDot11fIEWMMTSPEC WMMTSPEC;
} tDot11fWMMDelTS;
-#define DOT11F_WMMDELTS ( 61 )
+#define DOT11F_WMMDELTS ( 62 )
#ifdef __cplusplus
extern "C" {
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 1bb4a91..052e04d 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -636,35 +636,51 @@
#define SIR_HAL_DHCP_STOP_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 205)
#define SIR_HAL_IBSS_PEER_INACTIVITY_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 206)
-#define SIR_HAL_LPHB_WAIT_EXPIRE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 207)
+#define SIR_HAL_LPHB_CONF_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 207)
+#define SIR_HAL_LPHB_WAIT_EXPIRE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 208)
-#define SIR_HAL_ADD_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 208)
-#define SIR_HAL_DEL_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 209)
+#define SIR_HAL_ADD_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 209)
+#define SIR_HAL_DEL_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 210)
-#ifdef FEATURE_WLAN_BATCH_SCAN
-#define SIR_HAL_SET_BATCH_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 210)
-#define SIR_HAL_SET_BATCH_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 211)
-#define SIR_HAL_STOP_BATCH_SCAN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 212)
-#define SIR_HAL_TRIGGER_BATCH_SCAN_RESULT_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 213)
-#endif
+#ifdef WLAN_FEATURE_RMC
+#define SIR_HAL_RMC_BECOME_RULER (SIR_HAL_ITC_MSG_TYPES_BEGIN + 211)
+#define SIR_HAL_RMC_RULER_SELECT_RESP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 212)
+#define SIR_HAL_RMC_RULER_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 213)
+#define SIR_HAL_RMC_UPDATE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 214)
+
+/* For IBSS peer info related messages */
+#define SIR_HAL_IBSS_PEER_INFO_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 215)
+#define SIR_HAL_IBSS_PEER_INFO_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 216)
+#endif /* WLAN_FEATURE_RMC */
#define SIR_HAL_RATE_UPDATE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 217)
-#define SIR_HAL_START_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 218)
-#define SIR_HAL_START_SCAN_OFFLOAD_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 219)
-#define SIR_HAL_UPDATE_CHAN_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 220)
-#define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_REQ \
- (SIR_HAL_ITC_MSG_TYPES_BEGIN + 221)
-#define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_RSP \
- (SIR_HAL_ITC_MSG_TYPES_BEGIN + 222)
+#ifdef FEATURE_WLAN_BATCH_SCAN
+#define SIR_HAL_SET_BATCH_SCAN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 218)
+#define SIR_HAL_SET_BATCH_SCAN_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 219)
+#define SIR_HAL_STOP_BATCH_SCAN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 220)
+#define SIR_HAL_TRIGGER_BATCH_SCAN_RESULT_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 221)
+#endif
+#define SIR_HAL_START_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 223)
+#define SIR_HAL_START_SCAN_OFFLOAD_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 224)
+#define SIR_HAL_UPDATE_CHAN_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 225)
+
+#ifdef WLAN_FEATURE_RMC
+#define SIR_HAL_TX_FAIL_MONITOR_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 226)
+#endif /* WLAN_FEATURE_RMC */
/* OBSS Scan start Indication to FW*/
#define SIR_HAL_HT40_OBSS_SCAN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN +227)
/* OBSS Scan stop Indication to FW*/
#define SIR_HAL_HT40_OBSS_STOP_SCAN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN +228)
-#define SIR_HAL_BCN_MISS_RATE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 229)
+#define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_REQ \
+ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 229)
+#define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_RSP \
+ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 230)
+
+#define SIR_HAL_BCN_MISS_RATE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 231)
#ifdef WLAN_FEATURE_LINK_LAYER_STATS
#define SIR_HAL_LL_STATS_CLEAR_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 232)
@@ -725,20 +741,18 @@
#define SIR_HAL_MON_START_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 269)
#define SIR_HAL_MON_STOP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 270)
#define SIR_HAL_FATAL_EVENT_LOGS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 271)
-#define SIR_HAL_LPHB_CONF_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 272)
-#define SIR_HAL_SEND_LOG_DONE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 273)
-#define SIR_HAL_LOST_LINK_PARAMS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 274)
-#define SIR_HAL_SEND_FREQ_RANGE_CONTROL_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 275)
-#define SIR_HAL_FW_MEM_DUMP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 276)
-#define SIR_HAL_RSSI_MON_START_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 277)
-#define SIR_HAL_RSSI_MON_STOP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 278)
-#define SIR_HAL_HIGH_PRIORITY_DATA_INFO_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 279)
-
-#define SIR_HAL_WIFI_CONFIG_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 280)
-#define SIR_HAL_START_OEM_DATA_REQ_IND_NEW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 281)
-#define SIR_HAL_START_OEM_DATA_RSP_IND_NEW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 282)
-#define SIR_HAL_ANTENNA_DIVERSITY_SELECTION_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 283)
-#define SIR_HAL_MODIFY_ROAM_PARAMS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 284)
+#define SIR_HAL_SEND_LOG_DONE_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 272)
+#define SIR_HAL_LOST_LINK_PARAMS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 273)
+#define SIR_HAL_SEND_FREQ_RANGE_CONTROL_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 274)
+#define SIR_HAL_FW_MEM_DUMP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 275)
+#define SIR_HAL_RSSI_MON_START_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 276)
+#define SIR_HAL_RSSI_MON_STOP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 277)
+#define SIR_HAL_HIGH_PRIORITY_DATA_INFO_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 278)
+#define SIR_HAL_WIFI_CONFIG_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 279)
+#define SIR_HAL_START_OEM_DATA_REQ_IND_NEW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 280)
+#define SIR_HAL_START_OEM_DATA_RSP_IND_NEW (SIR_HAL_ITC_MSG_TYPES_BEGIN + 281)
+#define SIR_HAL_ANTENNA_DIVERSITY_SELECTION_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 282)
+#define SIR_HAL_MODIFY_ROAM_PARAMS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 283)
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
// CFG message types
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index 99969da..84bbedc 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -762,6 +762,10 @@
limFTOpen(pMac);
#endif
+#ifdef WLAN_FEATURE_RMC
+ limRmcInit(pMac);
+#endif /* WLAN_FEATURE_RMC */
+
vos_list_init(&pMac->lim.gLimMgmtFrameRegistratinQueue);
#if 0
@@ -857,6 +861,10 @@
limCleanupMlm(pMac);
limCleanupLmm(pMac);
+#ifdef WLAN_FEATURE_RMC
+ limRmcCleanup(pMac);
+#endif /* WLAN_FEATURE_RMC */
+
// free up preAuth table
if (pMac->lim.gLimPreAuthTimerTable.pTable != NULL)
{
diff --git a/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c b/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c
index 51d5ed9..4ca42d3 100644
--- a/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c
+++ b/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -49,6 +49,9 @@
#include "limSendMessages.h"
#include "limSession.h"
#include "limIbssPeerMgmt.h"
+#ifdef WLAN_FEATURE_RMC
+#include "limRMC.h"
+#endif
/**
@@ -820,6 +823,10 @@
limIbssDelete(
tpAniSirGlobal pMac,tpPESession psessionEntry)
{
+#ifdef WLAN_FEATURE_RMC
+ limRmcIbssDelete(pMac);
+#endif /* WLAN_FEATURE_RMC */
+
limIbssDeleteAllPeers(pMac,psessionEntry);
ibss_coalesce_free(pMac);
@@ -1177,6 +1184,10 @@
ucUcastSig = pStaDs->ucUcastSig;
ucBcastSig = pStaDs->ucBcastSig;
+#ifdef WLAN_FEATURE_RMC
+ limRmcTransmitterDelete(pMac, pStaDs->staAddr);
+#endif /* WLAN_FEATURE_RMC */
+
/* Send DEL STA only if STA id is valid, mean ADD STA was
* success.
*/
@@ -1277,6 +1288,11 @@
pStaDs->ucUcastSig, pStaDs->ucBcastSig,
eWNI_SME_IBSS_NEW_PEER_IND,
psessionEntry->smeSessionId);
+
+#ifdef WLAN_FEATURE_RMC
+ limRmcTriggerRulerSelection(pMac, psessionEntry->selfMacAddr);
+#endif
+
vos_mem_free(pAddStaParams);
return eSIR_SUCCESS;
@@ -1692,6 +1708,10 @@
ucUcastSig = pStaDs->ucUcastSig;
ucBcastSig = pStaDs->ucBcastSig;
+#ifdef WLAN_FEATURE_RMC
+ limRmcTransmitterDelete(pMac, pStaDs->staAddr);
+#endif /* WLAN_FEATURE_RMC */
+
(void) limDelSta(pMac, pStaDs, false /*asynchronous*/,psessionEntry);
limDeleteDphHashEntry(pMac, pStaDs->staAddr, peerIdx,psessionEntry);
limReleasePeerIdx(pMac, peerIdx, psessionEntry);
diff --git a/CORE/MAC/src/pe/lim/limLogDump.c b/CORE/MAC/src/pe/lim/limLogDump.c
index 8c642b8..9280c7d 100644
--- a/CORE/MAC/src/pe/lim/limLogDump.c
+++ b/CORE/MAC/src/pe/lim/limLogDump.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -57,6 +57,10 @@
#endif
#include "smeInside.h"
#include "wlan_qct_wda.h"
+#ifdef WLAN_FEATURE_RMC
+#include "wlan_qct_tl.h"
+#include "limRMC.h"
+#endif
#include "wlan_qct_wdi_dts.h"
void WDA_TimerTrafficStatsInd(tWDA_CbContext *pWDA);
@@ -1208,7 +1212,7 @@
state = (tSirMacHTMIMOPowerSaveState) arg1;
pMBMsg = vos_mem_malloc(WNI_CFG_MB_HDR_LEN + sizeof(tSirMacHTMIMOPowerSaveState));
- if(NULL == pMBMsg)
+ if (NULL == pMBMsg)
{
p += log_sprintf( pMac,p, "pMBMsg is NULL\n");
return p;
@@ -2368,6 +2372,102 @@
}
#endif
+#ifdef WLAN_FEATURE_RMC
+
+static char *
+dump_lim_enable_rmc_data_path
+(
+ tpAniSirGlobal pMac,
+ tANI_U32 arg1,
+ tANI_U32 arg2,
+ tANI_U32 arg3,
+ tANI_U32 arg4,
+ char *p
+)
+{
+ v_MACADDR_t rmcTransmitterAddr;
+ v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
+
+ rmcTransmitterAddr.bytes[0] = (tANI_U8)((arg1 & 0xFF000000) >> 24);
+ rmcTransmitterAddr.bytes[1] = (tANI_U8)((arg1 & 0x00FF0000) >> 16);
+ rmcTransmitterAddr.bytes[2] = (tANI_U8)((arg1 & 0x0000FF00) >> 8);
+ rmcTransmitterAddr.bytes[3] = (tANI_U8)((arg1 & 0x000000FF));
+ rmcTransmitterAddr.bytes[4] = (tANI_U8)((arg2 & 0xFF000000) >> 24);
+ rmcTransmitterAddr.bytes[5] = (tANI_U8)((arg2 & 0x00FF0000) >> 16);
+
+ limLog(pMac, LOGE,
+ FL("Enable RMC data path for MCAST transmitter:" MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY( rmcTransmitterAddr.bytes));
+
+ /*Input format is in MAC address fromat for example
+ iwpriv wlan0 dump 0xaabbccdd 0xeeff0000 translates into enable RMC for
+ MAC address 0xaa:0xbb:0xcc:0xdd:0xee:0xff*/
+
+ /*Enable TL data path*/
+ WLANTL_EnableRMC( pVosContext, &rmcTransmitterAddr );
+
+ return p;
+}
+
+static char *
+dump_lim_disable_rmc_data_path
+(
+ tpAniSirGlobal pMac,
+ tANI_U32 arg1,
+ tANI_U32 arg2,
+ tANI_U32 arg3,
+ tANI_U32 arg4,
+ char *p
+)
+{
+ v_MACADDR_t rmcTransmitterAddr;
+ v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
+
+ rmcTransmitterAddr.bytes[0] = (tANI_U8)((arg1 & 0xFF000000) >> 24);
+ rmcTransmitterAddr.bytes[1] = (tANI_U8)((arg1 & 0x00FF0000) >> 16);
+ rmcTransmitterAddr.bytes[2] = (tANI_U8)((arg1 & 0x0000FF00) >> 8);
+ rmcTransmitterAddr.bytes[3] = (tANI_U8)((arg1 & 0x000000FF));
+ rmcTransmitterAddr.bytes[4] = (tANI_U8)((arg2 & 0xFF000000) >> 24);
+ rmcTransmitterAddr.bytes[5] = (tANI_U8)((arg2 & 0x00FF0000) >> 16);
+
+
+ limLog(pMac, LOGE,
+ FL("Disable RMC data path for MCAST transmitter:" MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY( rmcTransmitterAddr.bytes));
+
+ /*Input format is in MAC address fromat for example
+ iwpriv wlan0 dump 0xaabbccdd 0xeeff0000 translates into enable RMC for
+ MAC address 0xaa:0xbb:0xcc:0xdd:0xee:0xff*/
+
+ /*Disable TL data path*/
+ WLANTL_DisableRMC( pVosContext, &rmcTransmitterAddr );
+
+ return p;
+}
+
+static char *
+dump_lim_rmc_status(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2,
+ tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ limRmcDumpStatus(pMac);
+ return p;
+}
+
+static char *
+dump_set_mcast_dup_detect(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2,
+ tANI_U32 arg3, tANI_U32 arg4, char *p)
+{
+ v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
+ v_U8_t enable;
+
+ enable = (tANI_U8)arg1;
+
+ /* Enable or Disable Multicast Duplicate Detection */
+ WLANTL_SetMcastDuplicateDetection( pVosContext, enable);
+
+ return p;
+}
+#endif /* WLAN_FEATURE_RMC */
static char *
dump_set_max_probe_req(tpAniSirGlobal pMac, tANI_U32 arg1, tANI_U32 arg2,
@@ -2467,7 +2567,17 @@
{369, "PE.LIM: pkts/rateIdx: iwpriv wlan0 dump 368 <staId> <boolean to flush counter>", dump_lim_get_pkts_rcvd_per_rate_idx},
{370, "PE.LIM: pkts/rssi: : iwpriv wlan0 dump 369 <staId> <boolean to flush counter>", dump_lim_get_pkts_rcvd_per_rssi_values},
#endif
+#ifdef WLAN_FEATURE_RMC
+ {371, "PE.LIM: Enable RMC data path in TL for input MCAST addr",
+ dump_lim_enable_rmc_data_path },
+ {372, "PE.LIM: Disable RMC data path in TL for input MCAST addr",
+ dump_lim_disable_rmc_data_path },
+ {373, "PE.LIM: Dump RMC transmitter and ruler status", dump_lim_rmc_status },
+#endif /* WLAN_FEATURE_RMC */
{374, "PE.LIM: MAS RX stats MAC eff <MAC eff in percentage>", dump_limRateInfoBasedOnMacEff},
+#ifdef WLAN_FEATURE_RMC
+ {375, "PE.LIM: Enable(1)/Disable(0) RMC duplicate detection", dump_set_mcast_dup_detect },
+#endif /* WLAN_FEATURE_RMC */
{376, "PE.LIM: max number of probe per scan", dump_set_max_probe_req },
};
diff --git a/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
index ff2d70e..ddff1c1 100644
--- a/CORE/MAC/src/pe/lim/limProcessActionFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
@@ -59,6 +59,9 @@
#include "rrmApi.h"
#endif
#include "limSessionUtils.h"
+#ifdef WLAN_FEATURE_RMC
+#include "limRMC.h"
+#endif
#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
#include "eseApi.h"
@@ -2455,7 +2458,8 @@
}
break;
#endif
-#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) \
+ || defined (WLAN_FEATURE_RMC)
case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY:
{
tpSirMacVendorSpecificFrameHdr pVendorSpecific = (tpSirMacVendorSpecificFrameHdr) pActionHdr;
@@ -2479,6 +2483,57 @@
pRxPacketInfo,
psessionEntry, 0);
}
+#if defined (WLAN_FEATURE_RMC)
+ else if ((eLIM_STA_IN_IBSS_ROLE == psessionEntry->limSystemRole) &&
+ ((VOS_TRUE == vos_mem_compare(SIR_MAC_RMC_MCAST_ADDRESS,
+ &pHdr->da[0], sizeof(tSirMacAddr))) ||
+ (VOS_TRUE == vos_mem_compare(psessionEntry->selfMacAddr,
+ &pHdr->da[0], sizeof(tSirMacAddr)))) &&
+ vos_mem_compare(pVendorSpecific->Oui, SIR_MAC_RMC_OUI, 3))
+ {
+ tANI_U8 MagicCode[] =
+ { 0x4f, 0x58, 0x59, 0x47, 0x45, 0x4e };
+ tpSirMacIbssExtNetworkFrameHdr pIbssExtHdr =
+ (tpSirMacIbssExtNetworkFrameHdr) pActionHdr;
+
+ if (vos_mem_compare(pIbssExtHdr->MagicCode,
+ MagicCode, sizeof(MagicCode)) &&
+ pIbssExtHdr->version == SIR_MAC_RMC_VER )
+ {
+ switch (pIbssExtHdr->actionID)
+ {
+ default:
+ PELOGE(limLog(pMac, LOGE,
+ FL("Action RMC actionID %d not handled"),
+ pIbssExtHdr->actionID);)
+ break;
+ case SIR_MAC_RMC_RULER_INFORM_SELECTED:
+ limLog(pMac, LOG1,
+ FL("Action RMC RULER_INFORM_SELECTED."));
+ limProcessRMCMessages(pMac,
+ eLIM_RMC_OTA_RULER_INFORM_SELECTED,
+ (tANI_U32 *)pRxPacketInfo);
+ break;
+ case SIR_MAC_RMC_RULER_INFORM_CANCELLED:
+ limLog(pMac, LOG1,
+ FL("Action RMC RULER_INFORM_CANCELLED."));
+ limProcessRMCMessages(pMac,
+ eLIM_RMC_OTA_RULER_INFORM_CANCELLED,
+ (tANI_U32 *)pRxPacketInfo);
+ break;
+ }
+ }
+ else
+ {
+ limLog( pMac, LOG1,
+ FL("Dropping the vendor specific action frame in IBSS "
+ "mode because of Ibss Ext Magic mismatch "
+ MAC_ADDRESS_STR " or Version mismatch = %d"),
+ MAC_ADDR_ARRAY(pIbssExtHdr->MagicCode),
+ pIbssExtHdr->version );
+ }
+ }
+#endif /* WLAN_FEATURE_RMC */
else
{
limLog( pMac, LOG1,
@@ -2492,7 +2547,8 @@
}
}
break;
-#endif
+#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE ||
+ FEATURE_WLAN_LFR || WLAN_FEATURE_RMC */
case SIR_MAC_ACTION_PUBLIC_USAGE:
switch(pActionHdr->actionID) {
case SIR_MAC_ACTION_VENDOR_SPECIFIC:
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index a47669e..93cd651 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -75,6 +75,10 @@
#include "wmmApsd.h"
#endif
+#ifdef WLAN_FEATURE_RMC
+#include "limRMC.h"
+#endif
+
#include "vos_types.h"
#include "vos_packet.h"
#include "vos_memory.h"
@@ -1607,6 +1611,17 @@
limMsg->bodyptr = NULL;
break;
+#ifdef WLAN_FEATURE_RMC
+ case eWNI_SME_ENABLE_RMC_REQ:
+ case eWNI_SME_DISABLE_RMC_REQ:
+ /*
+ * These messages are from HDD
+ * No need to response to hdd
+ */
+ limProcessSmeReqMessages(pMac,limMsg);
+ break;
+#endif /* WLAN_FEATURE_RMC */
+
case SIR_HAL_P2P_NOA_START_IND:
{
tpPESession psessionEntry = &pMac->lim.gpSession[0];
@@ -2292,6 +2307,28 @@
limMsg->bodyptr = NULL;
break;
}
+#ifdef WLAN_FEATURE_RMC
+ case WDA_RMC_BECOME_RULER:
+ limProcessRMCMessages(pMac, eLIM_RMC_BECOME_RULER_RESP,
+ (void *)limMsg->bodyptr);
+ vos_mem_free((v_VOID_t*)limMsg->bodyptr);
+ limMsg->bodyptr = NULL;
+ break ;
+
+ case WDA_RMC_RULER_SELECT_RESP:
+ limProcessRMCMessages(pMac, eLIM_RMC_RULER_SELECT_RESP,
+ (void *)limMsg->bodyptr);
+ vos_mem_free((v_VOID_t*)limMsg->bodyptr);
+ limMsg->bodyptr = NULL;
+ break ;
+
+ case WDA_RMC_UPDATE_IND:
+ limProcessRMCMessages(pMac, eLIM_RMC_RULER_PICK_NEW,
+ (void *)limMsg->bodyptr);
+ vos_mem_free((v_VOID_t*)limMsg->bodyptr);
+ limMsg->bodyptr = NULL;
+ break ;
+#endif /* WLAN_FEATURE_RMC */
case WDA_SPOOF_MAC_ADDR_RSP:
limProcessMlmSpoofMacAddrRsp(pMac, (tSirRetStatus)limMsg->bodyval);
diff --git a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
index 3a33168..f1378bf 100644
--- a/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
+++ b/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c
@@ -59,6 +59,10 @@
#include "limApi.h"
#include "wmmApsd.h"
+#ifdef WLAN_FEATURE_RMC
+#include "limRMC.h"
+#endif
+
#include "sapApi.h"
#if defined WLAN_FEATURE_VOWIFI
@@ -5843,6 +5847,16 @@
limSendSetTxPowerReq(pMac, pMsgBuf);
break ;
+#ifdef WLAN_FEATURE_RMC
+ case eWNI_SME_ENABLE_RMC_REQ:
+ limProcessRMCMessages(pMac, eLIM_RMC_ENABLE_REQ, pMsgBuf);
+ break ;
+
+ case eWNI_SME_DISABLE_RMC_REQ:
+ limProcessRMCMessages(pMac, eLIM_RMC_DISABLE_REQ, pMsgBuf);
+ break ;
+#endif /* WLAN_FEATURE_RMC */
+
case eWNI_SME_MAC_SPOOF_ADDR_IND:
__limProcessSmeSpoofMacAddrRequest(pMac, pMsgBuf);
break ;
diff --git a/CORE/MAC/src/pe/lim/limRMC.c b/CORE/MAC/src/pe/lim/limRMC.c
new file mode 100644
index 0000000..86b302e
--- /dev/null
+++ b/CORE/MAC/src/pe/lim/limRMC.c
@@ -0,0 +1,1382 @@
+/*
+ * Copyright (c) 2013-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.
+ */
+
+/*
+ * This file limRMC.c contains the code
+ * for processing RMC messages
+ *
+ */
+#include "wniApi.h"
+#include "wniCfg.h"
+#include "cfgApi.h"
+#include "sirApi.h"
+#include "schApi.h"
+#include "utilsApi.h"
+#include "limUtils.h"
+#include "limTimerUtils.h"
+#include "limSendMessages.h"
+#include "limSendMessages.h"
+#include "limSession.h"
+#include "limSessionUtils.h"
+#include "wlan_qct_wda.h"
+#include "wlan_qct_tli.h"
+#include "limRMC.h"
+
+#ifdef WLAN_FEATURE_RMC
+
+static tANI_U8
+__rmcGroupHashFunction(tSirMacAddr transmitter)
+{
+ tANI_U16 hash;
+
+ /*
+ * Generate a hash using transmitter address
+ */
+ hash = transmitter[0] + transmitter[1] + transmitter[2] +
+ transmitter[3] + transmitter[4] + transmitter[5];
+
+ return hash & (RMC_MCAST_GROUPS_HASH_SIZE - 1);
+}
+
+
+static tLimRmcGroupContext *
+__rmcGroupLookupHashEntry(tpAniSirGlobal pMac, tSirMacAddr transmitter)
+{
+ tANI_U8 index;
+ tLimRmcGroupContext *entry;
+
+ index = __rmcGroupHashFunction(transmitter);
+
+ /* Pick the correct hash table based on role */
+ entry = pMac->rmcContext.rmcGroupRxHashTable[index];
+
+ PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Lookup:[%d] transmitter "
+ MAC_ADDRESS_STR ), index,
+ MAC_ADDR_ARRAY(transmitter));)
+ while (entry)
+ {
+ if (vos_mem_compare(transmitter, entry->transmitter,
+ sizeof(v_MACADDR_t)))
+ {
+ return entry;
+ }
+
+ entry = entry->next;
+ }
+
+ return NULL;
+}
+
+static tLimRmcGroupContext *
+__rmcGroupInsertHashEntry(tpAniSirGlobal pMac, tSirMacAddr transmitter)
+{
+ tANI_U8 index;
+ tLimRmcGroupContext *entry;
+ tLimRmcGroupContext **head;
+
+ index = __rmcGroupHashFunction(transmitter);
+
+ PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Insert:[%d] group " MAC_ADDRESS_STR
+ " transmitter " MAC_ADDRESS_STR), index,
+ MAC_ADDR_ARRAY(mcastGroupAddr),
+ MAC_ADDR_ARRAY(transmitter));)
+
+ head = &pMac->rmcContext.rmcGroupRxHashTable[index];
+
+ entry = __rmcGroupLookupHashEntry(pMac, transmitter);
+
+ if (entry)
+ {
+ /* If the entry exists, return it at the end */
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Hash Insert:"
+ MAC_ADDRESS_STR "exists"), MAC_ADDR_ARRAY(transmitter));)
+ }
+ else
+ {
+ entry = (tLimRmcGroupContext *)vos_mem_malloc(sizeof(*entry));
+
+ PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Insert:new entry %p"), entry);)
+
+ if (entry)
+ {
+ vos_mem_copy(entry->transmitter, transmitter, sizeof(tSirMacAddr));
+ entry->isRuler = eRMC_IS_NOT_A_RULER;
+
+ /* chain this entry */
+ entry->next = *head;
+ *head = entry;
+ }
+ else
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Hash Insert:" MAC_ADDRESS_STR
+ " alloc failed"), MAC_ADDR_ARRAY(transmitter));)
+ }
+ }
+
+ return entry;
+}
+
+/**
+ * __rmcGroupDeleteHashEntry()
+ *
+ *FUNCTION:
+ * This function is called to delete a RMC group entry
+ *
+ *LOGIC:
+ *
+ *ASSUMPTIONS:
+ * Should be called with lkRmcLock held.
+ *
+ *NOTE:
+ * Make sure (for the transmitter role) that the entry is
+ * not in the Pending Response queue.
+ *
+ * @param transmitter - address of multicast transmitter
+ *
+ * @return status
+ */
+static tSirRetStatus
+__rmcGroupDeleteHashEntry(tpAniSirGlobal pMac, tSirMacAddr transmitter)
+{
+ tSirRetStatus status = eSIR_FAILURE;
+ tANI_U8 index;
+ tLimRmcGroupContext *entry, *prev, **head;
+
+ index = __rmcGroupHashFunction(transmitter);
+
+ head = &pMac->rmcContext.rmcGroupRxHashTable[index];
+ entry = *head;
+ prev = NULL;
+
+ while (entry)
+ {
+ if (vos_mem_compare(transmitter, entry->transmitter,
+ sizeof(v_MACADDR_t)))
+ {
+ if (*head == entry)
+ {
+ *head = entry->next;
+ }
+ else
+ {
+ prev->next = entry->next;
+ }
+
+ PELOG1(limLog(pMac, LOG1, FL("RMC: Hash Delete: entry %p "
+ " transmitter " MAC_ADDRESS_STR), entry
+ MAC_ADDR_ARRAY(transmitter));)
+
+ /* free the group entry */
+ vos_mem_free(entry);
+
+ status = eSIR_SUCCESS;
+ break;
+ }
+
+ prev = entry;
+ entry = entry->next;
+ }
+
+ return status;
+}
+
+static void
+__rmcGroupDeleteAllEntries(tpAniSirGlobal pMac)
+{
+ tLimRmcGroupContext *entry, **head;
+ int index;
+
+ PELOG1(limLog(pMac, LOG1, FL("RMC: Hash_Delete_All"),);)
+
+ for (index = 0; index < RMC_MCAST_GROUPS_HASH_SIZE; index++)
+ {
+ head = &pMac->rmcContext.rmcGroupRxHashTable[index];
+
+ entry = *head;
+
+ while (entry)
+ {
+ *head = entry->next;
+ /* free the group entry */
+ vos_mem_free(entry);
+ entry = *head;
+ }
+ }
+}
+
+static void
+__limPostMsgRulerReq ( tpAniSirGlobal pMac,
+ tANI_U8 cmd,
+ tSirMacAddr mcastTransmitter)
+{
+ tSirMsgQ msg;
+ tSirRmcRulerReq *pRulerReq;
+
+ pRulerReq = vos_mem_malloc(sizeof(*pRulerReq));
+ if (NULL == pRulerReq)
+ {
+ limLog(pMac, LOGE, FL("AllocateMemory() failed"));
+ return;
+ }
+
+ pRulerReq->cmd = cmd;
+
+ vos_mem_copy(pRulerReq->mcastTransmitter, mcastTransmitter,
+ sizeof(tSirMacAddr));
+
+ /* Initialize black list */
+ vos_mem_zero(pRulerReq->blacklist, sizeof(pRulerReq->blacklist));
+
+ if (eRMC_SUGGEST_RULER_CMD == cmd)
+ {
+ /* TODO - Set the black list. */
+ }
+
+ msg.type = WDA_RMC_RULER_REQ;
+ msg.bodyptr = pRulerReq;
+ msg.bodyval = 0;
+
+ MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type));
+ if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
+ {
+ vos_mem_free(pRulerReq);
+ limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed"));
+ }
+
+ return;
+}
+
+static void
+__limPostMsgUpdateInd ( tpAniSirGlobal pMac,
+ tANI_U8 indication,
+ tANI_U8 role,
+ tSirMacAddr mcastTransmitter,
+ tSirMacAddr mcastRuler)
+{
+ tSirMsgQ msg;
+ tSirRmcUpdateInd *pUpdateInd;
+
+ pUpdateInd = vos_mem_malloc(sizeof(*pUpdateInd));
+ if ( NULL == pUpdateInd )
+ {
+ limLog(pMac, LOGE, FL("AllocateMemory() failed"));
+ return;
+ }
+
+ vos_mem_zero(pUpdateInd, sizeof(*pUpdateInd));
+
+ pUpdateInd->indication = indication;
+ pUpdateInd->role = role;
+
+ vos_mem_copy(pUpdateInd->mcastTransmitter,
+ mcastTransmitter, sizeof(tSirMacAddr));
+
+ vos_mem_copy(pUpdateInd->mcastRuler,
+ mcastRuler, sizeof(tSirMacAddr));
+
+ msg.type = WDA_RMC_UPDATE_IND;
+ msg.bodyptr = pUpdateInd;
+ msg.bodyval = 0;
+
+ MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type));
+ if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
+ {
+ vos_mem_free(pUpdateInd);
+ limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed"));
+ }
+
+ return;
+}
+
+static char *
+__limRulerMessageToString(eRmcMessageType msgType)
+{
+ switch (msgType)
+ {
+ default:
+ return "Invalid";
+ case eLIM_RMC_ENABLE_REQ:
+ return "RMC_ENABLE_REQ";
+ case eLIM_RMC_DISABLE_REQ:
+ return "RMC_DISABLE_REQ";
+ case eLIM_RMC_RULER_SELECT_RESP:
+ return "RMC_RULER_SELECT_RESP";
+ case eLIM_RMC_RULER_PICK_NEW:
+ return "RMC_RULER_PICK_NEW";
+ case eLIM_RMC_OTA_RULER_INFORM_ACK:
+ return "RMC_OTA_RULER_INFORM_ACK";
+ case eLIM_RMC_OTA_RULER_INFORM_SELECTED:
+ return "RMC_OTA_RULER_INFORM_SELECTED";
+ case eLIM_RMC_BECOME_RULER_RESP:
+ return "RMC_BECOME_RULER_RESP";
+ case eLIM_RMC_OTA_RULER_INFORM_CANCELLED:
+ return "RMC_OTA_RULER_INFORM_CANCELLED";
+ }
+}
+
+static char *
+__limRulerStateToString(eRmcRulerState state)
+{
+ switch (state)
+ {
+ default:
+ return "Invalid";
+ case eRMC_IS_NOT_A_RULER:
+ return "Device Not a Ruler";
+ case eRMC_RULER_PENDING:
+ return "Pending firmware resp";
+ case eRMC_IS_A_RULER:
+ return "Device is Ruler";
+ }
+}
+
+static char *
+__limMcastTxStateToString(eRmcMcastTxState state)
+{
+ switch (state)
+ {
+ default:
+ return "Invalid";
+ case eRMC_RULER_NOT_SELECTED:
+ return "Not Selected";
+ case eRMC_RULER_ENABLE_REQUESTED:
+ return "Enable Requested";
+ case eRMC_RULER_OTA_REQUEST_SENT:
+ return "OTA Request Sent";
+ case eRMC_RULER_ACTIVE:
+ return "Active";
+ }
+}
+
+/**
+ * __rmcRulerSelectTimerHandler()
+ *
+ *FUNCTION:
+ * This function is called upon timer expiry.
+ *
+ *
+ *ASSUMPTIONS:
+ * NA
+ *
+ *NOTE:
+ * Only one entry is processed for every invocation if this routine.
+ * This allows us to use a single timer and makes sure we do not
+ * timeout a request too early.
+ *
+ * @param param - Message corresponding to the timer that expired
+ *
+ * @return None
+ */
+
+void
+__rmcRulerSelectTimerHandler(void *pMacGlobal, tANI_U32 param)
+{
+ tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal;
+ tSirMacAddr zeroMacAddr = { 0, 0, 0, 0, 0, 0 };
+ tSirRetStatus status;
+ tSirRMCInfo RMC;
+ tpPESession psessionEntry;
+ tANI_U32 cfgValue;
+
+ /*
+ * This API relies on a single active IBSS session.
+ */
+ psessionEntry = limIsIBSSSessionActive(pMac);
+ if (NULL == psessionEntry)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC:__rmcRulerSelectTimerHandler:No active IBSS"));)
+ return;
+ }
+
+ if (wlan_cfgGetInt(pMac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
+ &cfgValue) != eSIR_SUCCESS)
+ {
+ /**
+ * Could not get Action Period Frequency value
+ * from CFG. Log error.
+ */
+ limLog(pMac, LOGE, FL("could not retrieve ActionPeriodFrequency"));
+ }
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+
+ if (pMac->rmcContext.rmcTimerValInTicks != cfgValue)
+ {
+ limLog(pMac, LOG1, FL("RMC RulerSelect timer value changed"));
+ if (tx_timer_change(&pMac->rmcContext.gRmcRulerSelectTimer,
+ cfgValue, 0) != TX_SUCCESS)
+ {
+ limLog(pMac, LOGE,
+ FL("Unable to change RulerSelect Timer val"));
+ }
+ pMac->rmcContext.rmcTimerValInTicks = cfgValue;
+ }
+
+ /*
+ * If we are in the scanning state then we need to return
+ * from this function without any further processing
+ */
+ if (eLIM_HAL_SCANNING_STATE == pMac->lim.gLimHalScanState)
+ {
+ limLog(pMac, LOG1, FL("In scanning state, can't send action frm"));
+ if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer) !=
+ TX_SUCCESS)
+ {
+ limLog(pMac, LOGE, FL("In scanning state, "
+ "couldn't activate RMC RulerSelect timer"));
+ }
+ return;
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("__rmcRulerSelectTimerHandler lock acquire failed"));
+ if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer)!= TX_SUCCESS)
+ {
+ limLog(pMac, LOGE, FL("could not activate RMC RulerSelect timer"));
+ }
+ return;
+ }
+
+ vos_mem_copy(&RMC.mcastRuler, &pMac->rmcContext.ruler,
+ sizeof(tSirMacAddr));
+
+ if (VOS_FALSE == vos_mem_compare(&zeroMacAddr,
+ &pMac->rmcContext.ruler, sizeof(tSirMacAddr)))
+ {
+ limLog(pMac, LOG1,
+ FL("RMC Periodic Ruler_Select Ruler " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pMac->rmcContext.ruler));
+ /*
+ * Re-arm timer
+ */
+ if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer)!=
+ TX_SUCCESS)
+ {
+ limLog(pMac, LOGE, FL("could not activate RMC Response timer"));
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS
+ (vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: __rmcRulerSelectTimerHandler lock release failed"));
+ }
+ }
+ else
+ {
+ limLog(pMac, LOGE,
+ FL("RMC Deactivating timer because no ruler was selected"));
+
+ if (!VOS_IS_STATUS_SUCCESS
+ (vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: __rmcRulerSelectTimerHandler lock release failed"));
+ }
+
+ return;
+ }
+
+ RMC.dialogToken = 0;
+ RMC.action = SIR_MAC_RMC_RULER_INFORM_SELECTED;
+
+ status = limSendRMCActionFrame(pMac,
+ SIR_MAC_RMC_MCAST_ADDRESS,
+ &RMC,
+ psessionEntry);
+
+ if (eSIR_FAILURE == status)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC:__rmcRulerSelectTimerHandler Action frame send failed"));)
+ }
+
+ return;
+}
+
+static void
+__limProcessRMCEnableRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+ tSirSetRMCReq *setRmcReq = (tSirSetRMCReq *)pMsgBuf;
+ tpPESession psessionEntry;
+
+ if (!setRmcReq)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Enable:NULL message") );)
+ return;
+ }
+
+ pMac->rmcContext.rmcEnabled = TRUE;
+
+ /*
+ * This API relies on a single active IBSS session.
+ */
+ psessionEntry = limIsIBSSSessionActive(pMac);
+ if (NULL == psessionEntry)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC:Enable RMC request no active IBSS"));)
+ pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED;
+ return;
+ }
+
+ /* Send RULER_REQ to f/w */
+ __limPostMsgRulerReq(pMac, eRMC_SUGGEST_RULER_CMD,
+ setRmcReq->mcastTransmitter);
+
+ pMac->rmcContext.state = eRMC_RULER_ENABLE_REQUESTED;
+}
+
+static void
+__limProcessRMCDisableRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+ tpPESession psessionEntry;
+ tSirRMCInfo RMC;
+ tSirSetRMCReq *setRmcReq = (tSirSetRMCReq *)pMsgBuf;
+ tSirRetStatus status;
+ v_PVOID_t pvosGCtx;
+ VOS_STATUS vos_status;
+ v_MACADDR_t vosMcastTransmitter;
+
+ pMac->rmcContext.rmcEnabled = FALSE;
+
+ /*
+ * This API relies on a single active IBSS session.
+ */
+ psessionEntry = limIsIBSSSessionActive(pMac);
+ if (NULL == psessionEntry)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Disable:No active IBSS"));)
+ return;
+ }
+
+ if (!setRmcReq)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Disable:NULL message") );)
+ return;
+ }
+
+ /* Cancel pending timer */
+ tx_timer_deactivate(&pMac->rmcContext.gRmcRulerSelectTimer);
+
+ vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0];
+ vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1];
+ vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2];
+ vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3];
+ vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4];
+ vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5];
+
+ pvosGCtx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac);
+ vos_status = WLANTL_DisableRMC(pvosGCtx, &vosMcastTransmitter);
+
+ if (VOS_STATUS_SUCCESS != vos_status)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC:Disable: TL disable failed"));)
+ }
+
+ if (pMac->rmcContext.state == eRMC_RULER_ACTIVE)
+ {
+ RMC.dialogToken = 0;
+ RMC.action = SIR_MAC_RMC_RULER_INFORM_CANCELLED;
+ vos_mem_copy(&RMC.mcastRuler, &pMac->rmcContext.ruler, sizeof(tSirMacAddr));
+
+ status = limSendRMCActionFrame(pMac, pMac->rmcContext.ruler,
+ &RMC, psessionEntry);
+ if (eSIR_FAILURE == status)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC:Disable: Action frame send failed"));)
+ }
+
+ pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED;
+ }
+
+ __limPostMsgUpdateInd(pMac, eRMC_RULER_CANCELLED, eRMC_TRANSMITTER_ROLE,
+ setRmcReq->mcastTransmitter, pMac->rmcContext.ruler);
+
+ vos_mem_zero(pMac->rmcContext.ruler, sizeof(tSirMacAddr));
+
+}
+
+static void
+__limProcessRMCRulerSelectResponse(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+ tSirRmcRulerSelectInd *pRmcRulerSelectInd;
+ tpPESession psessionEntry;
+ tSirRetStatus status;
+ v_PVOID_t pvosGCtx;
+ VOS_STATUS vos_status;
+ v_MACADDR_t vosMcastTransmitter;
+ tSirRMCInfo RMC;
+
+ if (NULL == pMsgBuf)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Select_Resp:NULL message"));)
+ return;
+ }
+
+ /*
+ * This API relies on a single active IBSS session.
+ */
+ psessionEntry = limIsIBSSSessionActive(pMac);
+ if (NULL == psessionEntry)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC:Ruler_Select_Resp:No active IBSS"));)
+ pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED;
+ return;
+ }
+
+ pRmcRulerSelectInd = (tSirRmcRulerSelectInd *)pMsgBuf;
+
+ if (pMac->rmcContext.state != eRMC_RULER_ENABLE_REQUESTED)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Select_Resp:Bad state %s"),
+ __limMcastTxStateToString(pMac->rmcContext.state) );)
+ return;
+ }
+
+ if (pRmcRulerSelectInd->status)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC:Ruler_Select_Resp:FW Status %d"),
+ pRmcRulerSelectInd->status);)
+ pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED;
+ return;
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE, FL("RMC:Ruler_Select_Resp:lock acquire failed"));
+ pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED;
+ return;
+ }
+
+ vos_mem_copy(&pMac->rmcContext.ruler, &pRmcRulerSelectInd->ruler[0],
+ sizeof(tSirMacAddr));
+
+ if (!VOS_IS_STATUS_SUCCESS
+ (vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE, FL("RMC: Ruler_Select_Resp: lock release failed"));
+ }
+
+ RMC.dialogToken = 0;
+ RMC.action = SIR_MAC_RMC_RULER_INFORM_SELECTED;
+ vos_mem_copy(&RMC.mcastRuler, &pRmcRulerSelectInd->ruler[0],
+ sizeof(tSirMacAddr));
+
+ PELOG1(limLog(pMac, LOG1, FL("RMC: Ruler_Select :ruler " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pRmcRulerSelectInd->ruler[0]));)
+
+ status = limSendRMCActionFrame(pMac,
+ SIR_MAC_RMC_MCAST_ADDRESS,
+ &RMC,
+ psessionEntry);
+
+ if (eSIR_FAILURE == status)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC: Ruler_Select_Resp: Action send failed"));)
+ }
+
+ __limPostMsgUpdateInd(pMac, eRMC_RULER_ACCEPTED, eRMC_TRANSMITTER_ROLE,
+ psessionEntry->selfMacAddr, pMac->rmcContext.ruler);
+
+ vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0];
+ vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1];
+ vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2];
+ vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3];
+ vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4];
+ vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5];
+
+ /* Enable TL */
+ pvosGCtx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac);
+ vos_status = WLANTL_EnableRMC(pvosGCtx, &vosMcastTransmitter);
+
+ pMac->rmcContext.state = eRMC_RULER_ACTIVE;
+
+ if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer)!= TX_SUCCESS)
+ {
+ limLog(pMac, LOGE,
+ FL("Ruler_Select_Resp:Activate RMC Response timer failed"));
+ }
+}
+
+static void
+__limProcessRMCRulerPickNew(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+ tSirRmcUpdateInd *pRmcUpdateInd;
+ tpPESession psessionEntry;
+ tSirRetStatus status;
+ tSirRMCInfo RMC;
+ v_PVOID_t pvosGCtx;
+ VOS_STATUS vos_status;
+ v_MACADDR_t vosMcastTransmitter;
+ tSirMacAddr zeroMacAddr = { 0, 0, 0, 0, 0, 0 };
+
+ if (NULL == pMsgBuf)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Pick_New:NULL message"));)
+ return;
+ }
+
+ /*
+ * This API relies on a single active IBSS session.
+ */
+ psessionEntry = limIsIBSSSessionActive(pMac);
+ if (NULL == psessionEntry)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Pick_New:No active IBSS"));)
+ return;
+ }
+
+ pvosGCtx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac);
+
+ pRmcUpdateInd = (tSirRmcUpdateInd *)pMsgBuf;
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE, FL("RMC:Ruler_Pick_New:lock acquire failed"));
+ return;
+ }
+
+
+ /* Fill out Action frame parameters */
+ RMC.dialogToken = 0;
+
+ if (VOS_FALSE == vos_mem_compare(&zeroMacAddr,
+ &pRmcUpdateInd->mcastRuler,
+ sizeof(tSirMacAddr)))
+ {
+
+ vos_mem_copy(&RMC.mcastRuler, &pRmcUpdateInd->mcastRuler,
+ sizeof(tSirMacAddr));
+
+ RMC.action = SIR_MAC_RMC_RULER_INFORM_CANCELLED;
+ status = limSendRMCActionFrame(pMac,
+ pRmcUpdateInd->mcastRuler,
+ &RMC, psessionEntry);
+ if (eSIR_FAILURE == status)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC:Ruler_Pick_New: Inform_Cancel Action send failed"));)
+ goto done;
+ }
+
+ vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0];
+ vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1];
+ vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2];
+ vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3];
+ vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4];
+ vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5];
+
+ vos_status = WLANTL_DisableRMC(pvosGCtx, &vosMcastTransmitter);
+
+ if (VOS_STATUS_SUCCESS != vos_status)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC:Ruler_Pick_New: TL disable failed"));)
+ }
+ }
+
+ vos_mem_copy(pMac->rmcContext.ruler, pRmcUpdateInd->ruler[0],
+ sizeof(tSirMacAddr));
+
+ pMac->rmcContext.state = eRMC_RULER_NOT_SELECTED;
+
+ if (VOS_TRUE == vos_mem_compare(&zeroMacAddr,
+ pMac->rmcContext.ruler,
+ sizeof(tSirMacAddr)))
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC:Ruler_Pick_New: No candidate rulers available"));)
+ goto done;
+ }
+
+
+ RMC.action = SIR_MAC_RMC_RULER_INFORM_SELECTED;
+ vos_mem_copy(&RMC.mcastRuler, &pMac->rmcContext.ruler,
+ sizeof(tSirMacAddr));
+ status = limSendRMCActionFrame(pMac, SIR_MAC_RMC_MCAST_ADDRESS,
+ &RMC, psessionEntry);
+ if (eSIR_FAILURE == status)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC:Ruler_Pick_New: Inform_Selected Action send failed"));)
+ goto done;
+ }
+
+ __limPostMsgUpdateInd(pMac, eRMC_RULER_ACCEPTED, eRMC_TRANSMITTER_ROLE,
+ psessionEntry->selfMacAddr, pMac->rmcContext.ruler);
+
+ vosMcastTransmitter.bytes[0] = psessionEntry->selfMacAddr[0];
+ vosMcastTransmitter.bytes[1] = psessionEntry->selfMacAddr[1];
+ vosMcastTransmitter.bytes[2] = psessionEntry->selfMacAddr[2];
+ vosMcastTransmitter.bytes[3] = psessionEntry->selfMacAddr[3];
+ vosMcastTransmitter.bytes[4] = psessionEntry->selfMacAddr[4];
+ vosMcastTransmitter.bytes[5] = psessionEntry->selfMacAddr[5];
+
+ /* Enable TL */
+ vos_status = WLANTL_EnableRMC(pvosGCtx, &vosMcastTransmitter);
+
+ if (VOS_STATUS_SUCCESS != vos_status)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC:Ruler_Pick_New: TL enable failed"));)
+ goto done;
+ }
+
+ pMac->rmcContext.state = eRMC_RULER_ACTIVE;
+
+ if (tx_timer_activate(&pMac->rmcContext.gRmcRulerSelectTimer)!= TX_SUCCESS)
+ {
+ limLog(pMac, LOGE,
+ FL("Ruler_Pick_New:Activate RMC Response timer failed"));
+ }
+
+done:
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: Ruler_Pick_New: lock release failed"));
+ }
+}
+
+static void
+__limProcessRMCRulerInformSelected(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+ tpSirMacMgmtHdr pHdr;
+ tANI_U8 *pFrameData;
+ tANI_U32 frameLen;
+ tLimRmcGroupContext *entry;
+ tpPESession psessionEntry;
+ tSirRetStatus status;
+
+ if (!pMsgBuf)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform:NULL msg"));)
+ return;
+ }
+
+ /*
+ * This API relies on a single active IBSS session.
+ */
+ psessionEntry = limIsIBSSSessionActive(pMac);
+ if (NULL == psessionEntry)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC:Become_Ruler_Resp:No active IBSS"));)
+ return;
+ }
+
+ /*
+ * Get the frame header
+ */
+ pHdr = WDA_GET_RX_MAC_HEADER((tANI_U8 *)pMsgBuf);
+
+ frameLen = WDA_GET_RX_PAYLOAD_LEN((tANI_U8 *)pMsgBuf);
+ if (frameLen < sizeof(tSirMacIbssExtNetworkFrameHdr))
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC: Ruler_Inform:Bad length %d "), frameLen);)
+ return;
+ }
+
+ pFrameData = WDA_GET_RX_MPDU_DATA((tANI_U8 *)pMsgBuf) +
+ sizeof(tSirMacIbssExtNetworkFrameHdr);
+
+ if (!pFrameData)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform:NULL data"));)
+ return;
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE, FL("RMC:Become_Ruler_Resp:lock acquire failed"));
+ return;
+ }
+
+ /*
+ * Check if this transmitter exists in our database.
+ */
+ entry = __rmcGroupLookupHashEntry(pMac, pHdr->sa);
+
+ if (VOS_FALSE == vos_mem_compare(pFrameData, psessionEntry->selfMacAddr,
+ sizeof(tSirMacAddr)))
+ {
+ if (entry)
+ {
+ PELOG1(limLog(pMac, LOG1,
+ FL("RMC: Ruler_Inform: Ruler Cancelled"));)
+
+ __limPostMsgUpdateInd(pMac, eRMC_RULER_CANCELLED,
+ eRMC_RULER_ROLE, pHdr->sa, psessionEntry->selfMacAddr);
+
+ /*
+ * Delete hash entry for this Group address.
+ */
+ status = __rmcGroupDeleteHashEntry(pMac, pHdr->sa);
+ if (eSIR_FAILURE == status)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC: Ruler_Inform:hash delete failed"));)
+ }
+ }
+ }
+ else
+ {
+ if (NULL == entry)
+ {
+ /* Add the transmitter address to the hash */
+ entry = __rmcGroupInsertHashEntry(pMac, pHdr->sa);
+ if (entry)
+ {
+ if (entry->isRuler != eRMC_RULER_PENDING)
+ {
+ __limPostMsgRulerReq(pMac, eRMC_BECOME_RULER_CMD,
+ pHdr->sa);
+ entry->isRuler = eRMC_RULER_PENDING;
+ }
+ }
+ else
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC: Ruler_Inform:Hash insert failed"));)
+ }
+
+ }
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: Ruler_Inform: lock release failed"));
+ }
+
+}
+
+static void
+__limProcessRMCBecomeRulerResp(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+ tSirRmcBecomeRulerInd *pRmcBecomeRulerInd;
+ tLimRmcGroupContext *entry;
+ tSirRetStatus status = eSIR_SUCCESS;
+
+ if (NULL == pMsgBuf)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Become_Ruler_Resp:NULL message"));)
+ return;
+ }
+
+ pRmcBecomeRulerInd = (tSirRmcBecomeRulerInd *)pMsgBuf;
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE, FL("RMC:Become_Ruler_Resp:lock acquire failed"));
+ return;
+ }
+
+ /*
+ * Find the entry for this Group Address.
+ */
+ entry = __rmcGroupLookupHashEntry(pMac,
+ pRmcBecomeRulerInd->mcastTransmitter);
+ if (NULL == entry)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Become_Ruler_Resp: No entry"));)
+ goto done;
+ }
+
+ if (pRmcBecomeRulerInd->status)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC:Become_Ruler_Resp:FW Status %d"),
+ pRmcBecomeRulerInd->status);)
+ status = eSIR_FAILURE;
+ goto done;
+ }
+
+ if (entry->isRuler != eRMC_RULER_PENDING)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Become_Ruler_Resp:Bad state: %s"),
+ __limRulerStateToString(entry->isRuler) );)
+ status = eSIR_FAILURE;
+ goto done;
+ }
+
+ entry->isRuler = eRMC_IS_A_RULER;
+
+done:
+ if (eSIR_FAILURE == status)
+ {
+ status = __rmcGroupDeleteHashEntry(pMac,
+ pRmcBecomeRulerInd->mcastTransmitter);
+ if (eSIR_FAILURE == status)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC: Become_Ruler_Resp:hash delete failed"));)
+ }
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: Become_Ruler_Resp: lock release failed"));
+ }
+
+ return;
+}
+
+static void
+__limProcessRMCRulerInformCancelled(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
+{
+ tpSirMacMgmtHdr pHdr;
+ tANI_U8 *pFrameData;
+ tANI_U32 frameLen;
+ tSirRetStatus status;
+ tLimRmcGroupContext *entry;
+ tpPESession psessionEntry;
+
+ if (!pMsgBuf)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform_Cancel:NULL msg"));)
+ return;
+ }
+
+ /*
+ * This API relies on a single active IBSS session.
+ */
+ psessionEntry = limIsIBSSSessionActive(pMac);
+ if (NULL == psessionEntry)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC:Ruler_Inform_Cancel:No active IBSS"));)
+ return;
+ }
+
+ pHdr = WDA_GET_RX_MAC_HEADER((tANI_U8 *)pMsgBuf);
+
+ frameLen = WDA_GET_RX_PAYLOAD_LEN((tANI_U8 *)pMsgBuf);
+ if (frameLen < sizeof(tSirMacIbssExtNetworkFrameHdr))
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC: Ruler_Inform:Bad length %d "), frameLen);)
+ return;
+ }
+
+ pFrameData = WDA_GET_RX_MPDU_DATA((tANI_U8 *)pMsgBuf) +
+ sizeof(tSirMacIbssExtNetworkFrameHdr);
+
+ if (!pFrameData)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform_Cancel:NULL data"));)
+ return;
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE, FL("RMC:Ruler_Inform_Cancel lock acquire failed"));
+ return;
+ }
+
+ /*
+ * Find the entry for this Group Address.
+ */
+ entry = __rmcGroupLookupHashEntry(pMac, pHdr->sa);
+ if (NULL == entry)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Ruler_Inform_Cancel: No entry"));)
+ goto done;
+ }
+
+ __limPostMsgUpdateInd(pMac, eRMC_RULER_CANCELLED,
+ eRMC_RULER_ROLE, pHdr->sa, psessionEntry->selfMacAddr);
+
+ /*
+ * Delete hash entry for this Group address.
+ */
+ status = __rmcGroupDeleteHashEntry(pMac, pHdr->sa);
+ if (eSIR_FAILURE == status)
+ {
+ PELOGE(limLog(pMac, LOGE,
+ FL("RMC: Ruler_Inform_Cancel:hash delete failed"));)
+ }
+
+done:
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: Ruler_Inform_Cancel: lock release failed"));
+ }
+ return;
+}
+
+void
+limProcessRMCMessages(tpAniSirGlobal pMac, eRmcMessageType msgType,
+ tANI_U32 *pMsgBuf)
+{
+
+ if (pMsgBuf == NULL)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: Buffer is Pointing to NULL"));)
+ return;
+ }
+
+ limLog(pMac, LOG1, FL("RMC: limProcessRMCMessages: %s"),
+ __limRulerMessageToString(msgType));
+
+ switch (msgType)
+ {
+ case eLIM_RMC_ENABLE_REQ:
+ __limProcessRMCEnableRequest(pMac, pMsgBuf);
+ break;
+
+ case eLIM_RMC_DISABLE_REQ:
+ __limProcessRMCDisableRequest(pMac, pMsgBuf);
+ break;
+
+ case eLIM_RMC_RULER_SELECT_RESP:
+ __limProcessRMCRulerSelectResponse(pMac, pMsgBuf);
+ break;
+
+ case eLIM_RMC_RULER_PICK_NEW:
+ __limProcessRMCRulerPickNew(pMac, pMsgBuf);
+ break;
+
+ case eLIM_RMC_OTA_RULER_INFORM_SELECTED:
+ __limProcessRMCRulerInformSelected(pMac, pMsgBuf);
+ break;
+
+ case eLIM_RMC_BECOME_RULER_RESP:
+ __limProcessRMCBecomeRulerResp(pMac, pMsgBuf);
+ break;
+
+ case eLIM_RMC_OTA_RULER_INFORM_CANCELLED:
+ __limProcessRMCRulerInformCancelled(pMac, pMsgBuf);
+ break;
+
+
+ default:
+ break;
+ } // switch (msgType)
+ return;
+} /*** end limProcessRMCMessages() ***/
+
+void
+limRmcInit(tpAniSirGlobal pMac)
+{
+ tANI_U32 cfgValue;
+
+ if (wlan_cfgGetInt(pMac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY,
+ &cfgValue) != eSIR_SUCCESS)
+ {
+ /**
+ * Could not get Action Period Frequency value
+ * from CFG. Log error.
+ */
+ limLog(pMac, LOGP, FL("could not retrieve ActionPeriodFrequency"));
+ }
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+
+ vos_mem_zero(&pMac->rmcContext, sizeof(pMac->rmcContext));
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_init(&pMac->rmcContext.lkRmcLock)))
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC lock init failed!"));)
+ }
+
+ if (tx_timer_create(&pMac->rmcContext.gRmcRulerSelectTimer,
+ "RMC RSP TIMEOUT",
+ __rmcRulerSelectTimerHandler,
+ 0 /* param */,
+ cfgValue, 0,
+ TX_NO_ACTIVATE) != TX_SUCCESS)
+ {
+ limLog(pMac, LOGE, FL("could not create RMC response timer"));
+ }
+
+ pMac->rmcContext.rmcTimerValInTicks = cfgValue;
+}
+
+void
+limRmcCleanup(tpAniSirGlobal pMac)
+{
+ limRmcIbssDelete(pMac);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_destroy(&pMac->rmcContext.lkRmcLock)))
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC lock destroy failed!"));)
+ }
+
+ tx_timer_delete(&pMac->rmcContext.gRmcRulerSelectTimer);
+}
+
+void
+limRmcTransmitterDelete(tpAniSirGlobal pMac, tSirMacAddr transmitter)
+{
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: limRMCTransmitterDelete lock acquire failed"));
+ return;
+ }
+
+ __rmcGroupDeleteHashEntry(pMac, transmitter);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: limRMCTransmitterDelete lock release failed"));
+ }
+
+ limLog(pMac, LOG1, FL("RMC: limRmcTransmitterDelete complete"));
+}
+
+void
+limRmcIbssDelete(tpAniSirGlobal pMac)
+{
+ tpPESession psessionEntry;
+ tSirMacAddr zeroMacAddr = { 0, 0, 0, 0, 0, 0 };
+
+ /*
+ * This API relies on a single active IBSS session.
+ */
+ psessionEntry = limIsIBSSSessionActive(pMac);
+ if (NULL == psessionEntry)
+ {
+ PELOGE(limLog(pMac, LOGE, FL("RMC: limRmcIbssDelete:No active IBSS"));)
+ return;
+ }
+
+ if (VOS_FALSE == vos_mem_compare(&zeroMacAddr,
+ &pMac->rmcContext.ruler, sizeof(tSirMacAddr)))
+ {
+ __limPostMsgUpdateInd(pMac, eRMC_RULER_CANCELLED,
+ eRMC_TRANSMITTER_ROLE, psessionEntry->selfMacAddr,
+ pMac->rmcContext.ruler);
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: limRmcIbssDelete lock acquire failed"));
+ return;
+ }
+
+ /* Cancel pending timer */
+ tx_timer_deactivate(&pMac->rmcContext.gRmcRulerSelectTimer);
+
+ /* Delete all entries from Ruler database. */
+ __rmcGroupDeleteAllEntries(pMac);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: limRmcIbssDelete lock release failed"));
+ }
+
+ limLog(pMac, LOG1, FL("RMC: limRmcIbssDelete complete"));
+}
+
+void
+limRmcDumpStatus(tpAniSirGlobal pMac)
+{
+ tLimRmcGroupContext *entry;
+ int index, count;
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: limRmcDumpStatus lock acquire failed"));
+ return;
+ }
+
+
+ limLog(pMac, LOGE, FL(" ----- RMC Transmitter Information ----- \n"));
+ limLog(pMac, LOGE,
+ FL(" Ruler Address | RMC State \n"));
+
+ if (pMac->rmcContext.state != eRMC_RULER_NOT_SELECTED)
+ {
+ limLog(pMac,LOGE, FL( MAC_ADDRESS_STR " | %s\n"),
+ MAC_ADDR_ARRAY(pMac->rmcContext.ruler),
+ __limMcastTxStateToString(pMac->rmcContext.state));
+ }
+
+ limLog( pMac,LOGE, FL(" ----- RMC Ruler Information ----- \n"));
+ limLog( pMac,LOGE, FL(" Transmitter Address\n"));
+
+ count = 0;
+ for (index = 0; index < RMC_MCAST_GROUPS_HASH_SIZE; index++)
+ {
+ entry = pMac->rmcContext.rmcGroupRxHashTable[index];
+
+ while (entry)
+ {
+ count++;
+ limLog( pMac,LOGE, FL("%d. " MAC_ADDRESS_STR " \n"),
+ count, MAC_ADDR_ARRAY(entry->transmitter));
+ entry = entry->next;
+ }
+ }
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_lock_release(&pMac->rmcContext.lkRmcLock)))
+ {
+ limLog(pMac, LOGE,
+ FL("RMC: limRmcDumpStatus lock release failed"));
+ }
+
+ return;
+
+}
+
+VOS_STATUS
+limRmcTriggerRulerSelection(tpAniSirGlobal pMac, tSirMacAddr macAddr)
+{
+ if ((TRUE == pMac->rmcContext.rmcEnabled) &&
+ (eRMC_RULER_NOT_SELECTED == pMac->rmcContext.state))
+ {
+ limLog(pMac, LOG1,
+ FL("Ruler selection trigerred in FW"));
+
+ __limPostMsgRulerReq(pMac, eRMC_SUGGEST_RULER_CMD, macAddr);
+
+ pMac->rmcContext.state = eRMC_RULER_ENABLE_REQUESTED;
+
+ return VOS_STATUS_SUCCESS;
+ }
+ else
+ {
+ limLog(pMac, LOG1,
+ FL("Could not trigger ruler selection: RMC state %d rmcEnabled %d"),
+ pMac->rmcContext.state, pMac->rmcContext.rmcEnabled);
+
+ return VOS_STATUS_E_FAILURE;
+ }
+}
+
+#endif /* WLAN_FEATURE_RMC */
diff --git a/CORE/MAC/src/pe/lim/limRMC.h b/CORE/MAC/src/pe/lim/limRMC.h
new file mode 100644
index 0000000..1ebf0de
--- /dev/null
+++ b/CORE/MAC/src/pe/lim/limRMC.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2013-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.
+ */
+
+/*
+ *
+ * Date: 08/15/13
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+#ifndef __LIM_RMC_H
+#define __LIM_RMC_H
+
+#ifdef WLAN_FEATURE_RMC
+
+typedef enum {
+ eLIM_RMC_ENABLE_REQ = 0,
+ eLIM_RMC_DISABLE_REQ = 1,
+ eLIM_RMC_BECOME_RULER_RESP = 2,
+ eLIM_RMC_RULER_SELECT_RESP = 3,
+ eLIM_RMC_RULER_PICK_NEW = 4,
+ eLIM_RMC_OTA_RULER_INFORM_CANCELLED = 5,
+ eLIM_RMC_OTA_RULER_INFORM_ACK = 6,
+ eLIM_RMC_OTA_RULER_INFORM_SELECTED = 7,
+} eRmcMessageType;
+
+typedef enum {
+ eRMC_RULER_NOT_SELECTED = 0,
+ eRMC_RULER_ENABLE_REQUESTED = 1,
+ eRMC_RULER_OTA_REQUEST_SENT = 2,
+ eRMC_RULER_ACTIVE = 3,
+} eRmcMcastTxState;
+
+typedef enum {
+ eRMC_IS_NOT_A_RULER = 0,
+ eRMC_RULER_PENDING = 1,
+ eRMC_IS_A_RULER = 2,
+} eRmcRulerState;
+
+enum {
+ eRMC_SUGGEST_RULER_CMD = 0,
+ eRMC_BECOME_RULER_CMD = 1,
+};
+
+enum {
+ eRMC_RULER_ACCEPTED = 0, //Host-->FW
+ eRMC_RULER_CANCELLED = 1, //Host-->FW
+ eRMC_RULER_PICK_NEW = 2, //FW-->Host
+};
+
+/* tRoleType; */
+typedef enum
+{
+ eRMC_RULER_ROLE,
+ eRMC_TRANSMITTER_ROLE,
+} eRmcRole;
+
+#define RMC_MCAST_GROUPS_HASH_SIZE 32
+
+typedef struct sLimRmcGroupContext
+{
+ tSirMacAddr transmitter;
+ eRmcRulerState isRuler;
+ struct sLimRmcGroupContext *next;
+} tLimRmcGroupContext, *tpLimRmcGroupContext;
+
+typedef struct sLimRmcContext
+{
+ tANI_BOOLEAN rmcEnabled;
+ tSirMacAddr ruler;
+ eRmcMcastTxState state;
+ TX_TIMER gRmcRulerSelectTimer;
+ tANI_U32 rmcTimerValInTicks;
+ vos_lock_t lkRmcLock;
+ tLimRmcGroupContext *rmcGroupRxHashTable[RMC_MCAST_GROUPS_HASH_SIZE];
+} tLimRmcContext, *tpLimRmcContext;
+
+
+void limRmcInit(tpAniSirGlobal pMac);
+void limRmcCleanup(tpAniSirGlobal pMac);
+void limRmcTransmitterDelete(tpAniSirGlobal pMac, tSirMacAddr transmitter);
+void limRmcIbssDelete(tpAniSirGlobal pMac);
+void limRmcDumpStatus(tpAniSirGlobal pMac);
+
+VOS_STATUS
+limRmcTriggerRulerSelection(tpAniSirGlobal pMac, tSirMacAddr macAddr);
+#endif /* WLAN_FEATURE_RMC */
+
+#endif /* __LIM_RMC_H */
diff --git a/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/CORE/MAC/src/pe/lim/limSendManagementFrames.c
index 8d40677..ab8e86c 100644
--- a/CORE/MAC/src/pe/lim/limSendManagementFrames.c
+++ b/CORE/MAC/src/pe/lim/limSendManagementFrames.c
@@ -7026,3 +7026,140 @@
return nSirStatus;
} // End limSendSaQueryResponseFrame
#endif
+
+#ifdef WLAN_FEATURE_RMC
+tSirRetStatus
+limSendRMCActionFrame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr,
+ tSirRMCInfo *pRMC,
+ tpPESession psessionEntry)
+{
+ tSirRetStatus nSirStatus;
+ tANI_U8 *pFrame;
+ tDot11fRMC RMC;
+ tANI_U32 nPayload, nBytes, nStatus;
+ tpSirMacMgmtHdr pMacHdr;
+ void *pPacket;
+ eHalStatus halstatus;
+ tANI_U8 txFlag = 0;
+ tANI_U8 MagicCode[] = { 0x4f, 0x58, 0x59, 0x47, 0x45, 0x4e };
+
+ if (NULL == psessionEntry)
+ {
+ return eSIR_FAILURE;
+ }
+
+ vos_mem_set(( tANI_U8* )&RMC, sizeof( RMC ), 0);
+
+ RMC.Action.action = pRMC->action;
+ RMC.RMCDialogToken.token = pRMC->dialogToken;
+ RMC.Category.category = SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY;
+ RMC.RMCVersion.version = SIR_MAC_RMC_VER;
+
+ vos_mem_copy(&RMC.RMCOUI.oui, SIR_MAC_RMC_OUI, SIR_MAC_RMC_OUI_SIZE);
+ vos_mem_copy(&RMC.MagicCode.magic, MagicCode, sizeof(MagicCode));
+
+ vos_mem_copy(&RMC.Ruler.mac, pRMC->mcastRuler, sizeof(tSirMacAddr));
+
+ nStatus = dot11fGetPackedRMCSize( pMac, &RMC, &nPayload );
+ if ( DOT11F_FAILED( nStatus ) )
+ {
+ limLog( pMac, LOGE, FL("Failed to calculate the packed size for "
+ "an RMC (0x%08x)."),
+ nStatus );
+ // We'll fall back on the worst case scenario:
+ nPayload = sizeof( tDot11fRMC );
+ }
+ else if ( DOT11F_WARNED( nStatus ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for an RMC Action Frame"
+ " (0x%08x)."), nStatus );
+ }
+
+ nBytes = nPayload + sizeof( tSirMacMgmtHdr );
+
+ halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( tANI_U16 )nBytes, ( void** ) &pFrame,
+ ( void** ) &pPacket );
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an RMC "
+ "Action Frame."), nBytes );
+ return eSIR_FAILURE;
+ }
+
+ // Paranoia:
+ vos_mem_set( pFrame, nBytes, 0 );
+
+ // Next, we fill out the buffer descriptor:
+ nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peerMacAddr,
+ psessionEntry->selfMacAddr);
+ if ( eSIR_SUCCESS != nSirStatus )
+ {
+ limLog( pMac, LOGE, FL("Failed to populate the buffer descriptor "
+ "for an RMC Action Frame (%d)."),
+ nSirStatus );
+ palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
+ ( void* ) pFrame, ( void* ) pPacket );
+ return nSirStatus;
+ }
+
+ // Update A3 with the BSSID
+ pMacHdr = ( tpSirMacMgmtHdr ) pFrame;
+ sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId);
+
+ // That done, pack the struct:
+ nStatus = dot11fPackRMC( pMac, &RMC,
+ pFrame + sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload );
+ if ( DOT11F_FAILED( nStatus ) )
+ {
+ limLog( pMac, LOGE, FL("Failed to pack an RMC "
+ "(0x%08x)."),
+ nStatus );
+ palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame,
+ ( void* ) pPacket );
+ return eSIR_FAILURE;
+ }
+ else if ( DOT11F_WARNED( nStatus ) )
+ {
+ limLog( pMac, LOGW, FL("There were warnings while packing "
+ "an RMC (0x%08x)."), nStatus );
+ }
+
+ limLog( pMac, LOG1, FL("Sending an RMC Action frame to "
+ MAC_ADDRESS_STR), MAC_ADDR_ARRAY(peerMacAddr));
+
+ /*
+ * With this masking, RMC action frames will be sent
+ * at self-sta rates for both 2G and 5G bands.
+ */
+ txFlag |= HAL_USE_SELF_STA_REQUESTED_MASK;
+
+ MTRACE(macTrace(pMac, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId,
+ pMacHdr->fc.subType));
+ // Queue RMC Action frame in high priority WQ
+ halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes,
+ HAL_TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
+ limTxComplete, pFrame, txFlag );
+ MTRACE(macTrace(pMac, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId,
+ halstatus));
+ if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
+ {
+ limLog( pMac, LOGE, FL( "*** Could not send an RMC Action frame"
+ " (%X) ***" ), halstatus );
+ //Pkt will be freed up by the callback
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+
+} // End limSendRMCActionFrame.
+
+#endif /* WLAN_FEATURE_RMC */
diff --git a/CORE/MAC/src/pe/lim/limTypes.h b/CORE/MAC/src/pe/lim/limTypes.h
index 04bbcc2..8747a4d 100644
--- a/CORE/MAC/src/pe/lim/limTypes.h
+++ b/CORE/MAC/src/pe/lim/limTypes.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -872,6 +872,15 @@
tSirRetStatus limSendSaQueryResponseFrame( tpAniSirGlobal pMac,
tANI_U8 *transId, tSirMacAddr peer,tpPESession psessionEntry);
#endif
+
+#ifdef WLAN_FEATURE_RMC
+void limProcessRMCMessages(tpAniSirGlobal pMac, eRmcMessageType msgType,
+ tANI_U32 *pMsgBuf);
+tSirRetStatus limSendRMCActionFrame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr, tSirRMCInfo *pRMC,
+ tpPESession psessionEntry);
+#endif /* WLAN_FEATURE_RMC */
+
// Inline functions
/**