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
 
 /**