Explorar el Código

qcacld-3.0: Add extended IBSS feature on qcacld-3.0

Add extended IBSS feature on qcacld-3.0

Change-Id: I7faaf646df363a74954defbef103afbb4b72af92
CRs-Fixed: 766181
Rajeev Kumar hace 9 años
padre
commit
8e3e283a82

+ 3 - 0
core/hdd/inc/wlan_hdd_assoc.h

@@ -52,6 +52,9 @@
 /* Timeout (in ms) for Link to Up before Registering Station */
 #define ASSOC_LINKUP_TIMEOUT 60
 
+/* Timeout in ms for peer info request commpletion */
+#define IBSS_PEER_INFO_REQ_TIMOEUT 1000
+
 /* Type Declarations */
 /**
  * typedef eConnectionState - Connection states

+ 29 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -637,6 +637,29 @@ typedef struct hdd_cfg80211_state_s {
 	eP2PActionFrameState actionFrmState;
 } hdd_cfg80211_state_t;
 
+
+/*---------------------------------------------------------------------------
+   hdd_ibss_peer_info_params_t
+   ---------------------------------------------------------------------------*/
+typedef struct {
+	uint8_t staIdx;         /* StaIdx */
+	uint32_t txRate;        /* Current Tx Rate */
+	uint32_t mcsIndex;      /* MCS Index */
+	uint32_t txRateFlags;   /* TxRate Flags */
+	int8_t rssi;            /* RSSI */
+} hdd_ibss_peer_info_params_t;
+
+typedef struct {
+	/** Request status */
+	uint32_t status;
+
+	/** Number of peers */
+	uint8_t numIBSSPeers;
+
+	/** Peer Info parameters */
+	hdd_ibss_peer_info_params_t ibssPeerList[MAX_IBSS_PEERS];
+} hdd_ibss_peer_info_t;
+
 struct hdd_station_ctx {
 	/** Handle to the Wireless Extension State */
 	hdd_wext_state_t WextState;
@@ -663,6 +686,7 @@ struct hdd_station_ctx {
 
 	/*Save the wep/wpa-none keys */
 	tCsrRoamSetKey ibss_enc_key;
+	hdd_ibss_peer_info_t ibss_peer_info;
 
 	bool hdd_ReassocScenario;
 
@@ -906,6 +930,8 @@ struct hdd_adapter_s {
 	QDF_STATUS tdlsAddStaStatus;
 #endif
 
+	struct completion ibss_peer_info_comp;
+
 	/* Track whether the linkup handling is needed  */
 	bool isLinkUpSvcNeeded;
 
@@ -1415,6 +1441,9 @@ int wlan_hdd_validate_context(hdd_context_t *pHddCtx);
 bool hdd_is_valid_mac_address(const uint8_t *pMacAddr);
 QDF_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx);
 
+struct qdf_mac_addr *
+hdd_wlan_get_ibss_mac_addr_from_staid(hdd_adapter_t *pAdapter,
+				      uint8_t staIdx);
 void hdd_checkandupdate_phymode(hdd_context_t *pHddCtx);
 
 #ifdef MSM_PLATFORM

+ 17 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -9546,6 +9546,7 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
 	int status;
 	QDF_STATUS hal_status;
 	unsigned long rc;
+	tSirUpdateIE updateIE;
 
 	ENTER();
 
@@ -9578,6 +9579,22 @@ static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
 		       FL("BSS Type is not set to IBSS"));
 		return -EINVAL;
 	}
+	/* Clearing add IE of beacon */
+	qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
+		     sizeof(tSirMacAddr));
+	updateIE.smeSessionId = pAdapter->sessionId;
+	updateIE.ieBufferlength = 0;
+	updateIE.pAdditionIEBuffer = NULL;
+	updateIE.append = true;
+	updateIE.notify = true;
+	if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
+			      &updateIE,
+			      eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
+		hddLog(LOGE, FL("Could not pass on PROBE_RSP_BCN data to PE"));
+	}
+
+	/* Reset WNI_CFG_PROBE_RSP Flags */
+	wlan_hdd_reset_prob_rspies(pAdapter);
 
 	/* Issue Disconnect request */
 	INIT_COMPLETION(pAdapter->disconnect_comp_var);

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1183 - 31
core/hdd/src/wlan_hdd_ioctl.c


+ 51 - 0
core/hdd/src/wlan_hdd_main.c

@@ -146,6 +146,8 @@ static int wlan_hdd_inited;
  */
 DEFINE_SPINLOCK(hdd_context_lock);
 
+#define WLAN_NLINK_CESIUM 30
+
 static qdf_wake_lock_t wlan_wake_lock;
 
 #define WOW_MAX_FILTER_LISTS 1
@@ -1619,6 +1621,45 @@ static void hdd_uninit(struct net_device *dev)
 	cds_ssr_unprotect(__func__);
 }
 
+static int hdd_open_cesium_nl_sock(void)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	struct netlink_kernel_cfg cfg = {
+		.groups = WLAN_NLINK_MCAST_GRP_ID,
+		.input = NULL
+	};
+#endif
+	int ret = 0;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+	cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
+						   THIS_MODULE,
+#endif
+						   &cfg);
+#else
+	cesium_nl_srv_sock = netlink_kernel_create(&init_net, WLAN_NLINK_CESIUM,
+						   WLAN_NLINK_MCAST_GRP_ID,
+						   NULL, NULL, THIS_MODULE);
+#endif
+
+	if (cesium_nl_srv_sock == NULL) {
+		hddLog(QDF_TRACE_LEVEL_ERROR,
+		       FL("NLINK:  cesium netlink_kernel_create failed"));
+		ret = -ECONNREFUSED;
+	}
+
+	return ret;
+}
+
+static void hdd_close_cesium_nl_sock(void)
+{
+	if (NULL != cesium_nl_srv_sock) {
+		netlink_kernel_release(cesium_nl_srv_sock);
+		cesium_nl_srv_sock = NULL;
+	}
+}
+
 /**
  * __hdd_set_mac_address() - set the user specified mac address
  * @dev:	Pointer to the net device.
@@ -1889,6 +1930,7 @@ static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx,
 		init_completion(&adapter->tdls_mgmt_comp);
 		init_completion(&adapter->tdls_link_establish_req_comp);
 #endif
+		init_completion(&adapter->ibss_peer_info_comp);
 		init_completion(&adapter->change_country_code);
 
 
@@ -3832,6 +3874,8 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx)
 
 	hdd_close_all_adapters(hdd_ctx, false);
 
+	hdd_close_cesium_nl_sock();
+
 	hdd_ipa_cleanup(hdd_ctx);
 
 	/* Free up RoC request queue and flush workqueue */
@@ -5680,6 +5724,11 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc)
 		goto err_nl_srv;
 	}
 
+	if (hdd_open_cesium_nl_sock() < 0) {
+		hdd_alert("hdd_open_cesium_nl_sock failed");
+		goto err_nl_srv;
+	}
+
 	/*
 	 * Action frame registered in one adapter which will
 	 * applicable to all interfaces
@@ -5832,6 +5881,8 @@ err_nl_srv:
 		/* Proceed and complete the clean up */
 	}
 
+	hdd_close_cesium_nl_sock();
+
 err_close_adapter:
 	hdd_release_rtnl_lock();
 

+ 255 - 4
core/hdd/src/wlan_hdd_wext.c

@@ -307,7 +307,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = {
 #define WE_GET_11W_INFO      9
 #endif
 #define WE_GET_STATES        10
-
+#define WE_GET_IBSS_STA_INFO 11
 #define WE_GET_PHYMODE       12
 #ifdef FEATURE_OEM_DATA_SUPPORT
 #define WE_GET_OEM_DATA_CAP  13
@@ -318,7 +318,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = {
 /* Private ioctls and their sub-ioctls */
 #define WLAN_PRIV_SET_NONE_GET_NONE   (SIOCIWFIRSTPRIV + 6)
 #define WE_SET_REASSOC_TRIGGER     8
-
+#define WE_IBSS_GET_PEER_INFO_ALL 10
 #define WE_DUMP_AGC_START          11
 #define WE_DUMP_AGC                12
 #define WE_DUMP_CHANINFO_START     13
@@ -341,7 +341,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = {
 #ifdef FEATURE_WLAN_TDLS
 #define WE_TDLS_CONFIG_PARAMS   5
 #endif
-
+#define WE_IBSS_GET_PEER_INFO   6
 #define WE_UNIT_TEST_CMD   7
 
 #define WE_MTRACE_DUMP_CMD    8
@@ -766,6 +766,194 @@ error:
 	return;
 }
 
+/**
+ * hdd_get_ibss_peer_info_cb() - IBSS Peer Info Callback
+ * @pUserData: user context originally passed to SME; we pass hdd adapter
+ * @pPeerInfoRsp: IBSS Peer information
+ *
+ * Return: None
+ */
+void hdd_get_ibss_peer_info_cb(void *pUserData, void *pPeerInfoRsp)
+{
+	hdd_adapter_t *pAdapter = (hdd_adapter_t *) pUserData;
+	hdd_ibss_peer_info_t *pPeerInfo = (hdd_ibss_peer_info_t *) pPeerInfoRsp;
+	hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+	uint8_t i;
+
+	if (NULL != pPeerInfo && QDF_STATUS_SUCCESS == pPeerInfo->status) {
+		pStaCtx->ibss_peer_info.status = pPeerInfo->status;
+		pStaCtx->ibss_peer_info.numIBSSPeers = pPeerInfo->numIBSSPeers;
+		for (i = 0; i < pPeerInfo->numIBSSPeers; i++) {
+			memcpy(&pStaCtx->ibss_peer_info.ibssPeerList[i],
+			       &pPeerInfo->ibssPeerList[i],
+			       sizeof(hdd_ibss_peer_info_params_t));
+		}
+	} else {
+		QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
+			  "%s] PEER_INFO_CMD_STATUS is not SUCCESS", __func__);
+	}
+
+	complete(&pAdapter->ibss_peer_info_comp);
+}
+
+/**
+ * hdd_wlan_get_ibss_mac_addr_from_staid() - Get IBSS MAC address
+ * @pAdapter: Adapter upon which the IBSS client is active
+ * @staIdx: Station index of the IBSS peer
+ *
+ * Return: a pointer to the MAC address of the IBSS peer if the peer is
+ *	   found, otherwise %NULL.
+ */
+struct qdf_mac_addr *
+hdd_wlan_get_ibss_mac_addr_from_staid(hdd_adapter_t *pAdapter,
+				      uint8_t staIdx)
+{
+	uint8_t idx;
+	hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+	for (idx = 0; idx < MAX_IBSS_PEERS; idx++) {
+		if (0 != pHddStaCtx->conn_info.staId[idx] &&
+		    staIdx == pHddStaCtx->conn_info.staId[idx]) {
+			return &pHddStaCtx->conn_info.peerMacAddress[idx];
+		}
+	}
+	return NULL;
+}
+
+/**
+ * hdd_wlan_get_ibss_peer_info() - Print IBSS peer information
+ * @pAdapter: Adapter upon which the IBSS client is active
+ * @staIdx: Station index of the IBSS peer
+ *
+ * Return: QDF_STATUS_STATUS if the peer was found and displayed,
+ * otherwise an appropriate QDF_STATUS_E_* failure code.
+ */
+QDF_STATUS hdd_wlan_get_ibss_peer_info(hdd_adapter_t *pAdapter, uint8_t staIdx)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+	hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+	hdd_ibss_peer_info_t *pPeerInfo = &pStaCtx->ibss_peer_info;
+
+	status =
+		sme_request_ibss_peer_info(hHal, pAdapter, hdd_get_ibss_peer_info_cb,
+					   false, staIdx);
+
+	INIT_COMPLETION(pAdapter->ibss_peer_info_comp);
+
+	if (QDF_STATUS_SUCCESS == status) {
+		unsigned long rc;
+		rc = wait_for_completion_timeout
+			     (&pAdapter->ibss_peer_info_comp,
+			     msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
+		if (!rc) {
+			hddLog(QDF_TRACE_LEVEL_ERROR,
+			       FL("failed wait on ibss_peer_info_comp"));
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		/** Print the peer info */
+		pr_info("pPeerInfo->numIBSSPeers = %d ",
+			pPeerInfo->numIBSSPeers);
+		pr_info
+			("============================================================");
+		{
+			struct qdf_mac_addr *macAddr =
+				hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
+								      staIdx);
+			uint32_t txRateMbps =
+				((pPeerInfo->ibssPeerList[0].txRate) * 500 * 1000) /
+				1000000;
+
+			if (NULL != macAddr) {
+				pr_info("PEER ADDR :" MAC_ADDRESS_STR
+					" TxRate: %d Mbps  RSSI: %d",
+					MAC_ADDR_ARRAY(macAddr->bytes),
+					(int)txRateMbps,
+					(int)pPeerInfo->ibssPeerList[0].rssi);
+			} else {
+				QDF_TRACE(QDF_MODULE_ID_HDD,
+					  QDF_TRACE_LEVEL_ERROR,
+					  " ERROR: PEER MAC ADDRESS NOT FOUND ");
+			}
+		}
+	} else {
+		hddLog(QDF_TRACE_LEVEL_WARN,
+		       "%s: Warning: sme_request_ibss_peer_info Request failed",
+		       __func__);
+	}
+
+	return status;
+}
+
+/**
+ * hdd_wlan_get_ibss_peer_info_all() - Print all IBSS peers
+ * @pAdapter: Adapter upon which the IBSS clients are active
+ *
+ * Return: QDF_STATUS_STATUS if the peer information was retrieved and
+ * displayed, otherwise an appropriate QDF_STATUS_E_* failure code.
+ */
+QDF_STATUS hdd_wlan_get_ibss_peer_info_all(hdd_adapter_t *pAdapter)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
+	hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+	hdd_ibss_peer_info_t *pPeerInfo = &pStaCtx->ibss_peer_info;
+	int i;
+
+	status =
+		sme_request_ibss_peer_info(hHal, pAdapter, hdd_get_ibss_peer_info_cb,
+					   true, 0xFF);
+	INIT_COMPLETION(pAdapter->ibss_peer_info_comp);
+
+	if (QDF_STATUS_SUCCESS == status) {
+		unsigned long rc;
+		rc = wait_for_completion_timeout
+			     (&pAdapter->ibss_peer_info_comp,
+			     msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT));
+		if (!rc) {
+			hddLog(QDF_TRACE_LEVEL_ERROR,
+			       FL("failed wait on ibss_peer_info_comp"));
+			return QDF_STATUS_E_FAILURE;
+		}
+
+		/** Print the peer info */
+		pr_info("pPeerInfo->numIBSSPeers = %d ",
+			(int)pPeerInfo->numIBSSPeers);
+		pr_info
+			("============================================================");
+		for (i = 0; i < pPeerInfo->numIBSSPeers; i++) {
+			uint8_t staIdx = pPeerInfo->ibssPeerList[i].staIdx;
+			struct qdf_mac_addr *macAddr =
+				hdd_wlan_get_ibss_mac_addr_from_staid(pAdapter,
+								      staIdx);
+			uint32_t txRateMbps =
+				((pPeerInfo->ibssPeerList[0].txRate) * 500 * 1000) /
+				1000000;
+
+			pr_info("STAIDX:%d ",
+				(int)pPeerInfo->ibssPeerList[i].staIdx);
+			if (NULL != macAddr) {
+				pr_info(" PEER ADDR :" MAC_ADDRESS_STR
+					" TxRate: %d Mbps RSSI: %d",
+					MAC_ADDR_ARRAY(macAddr->bytes),
+					(int)txRateMbps,
+					(int)pPeerInfo->ibssPeerList[i].rssi);
+			} else {
+				QDF_TRACE(QDF_MODULE_ID_HDD,
+					  QDF_TRACE_LEVEL_ERROR,
+					  " ERROR: PEER MAC ADDRESS NOT FOUND ");
+			}
+		}
+	} else {
+		hddLog(QDF_TRACE_LEVEL_WARN,
+		       "%s: Warning: sme_request_ibss_peer_info Request failed",
+		       __func__);
+	}
+
+	return status;
+}
+
 /**
  * hdd_wlan_get_rts_threshold() - Get RTS threshold
  * @pAdapter: adapter upon which the request was received
@@ -7260,6 +7448,39 @@ static int __iw_get_char_setnone(struct net_device *dev,
 		break;
 	}
 #endif
+	case WE_GET_IBSS_STA_INFO:
+	{
+		hdd_station_ctx_t *pHddStaCtx =
+			WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+		int idx = 0;
+		int length = 0, buf = 0;
+
+		for (idx = 0; idx < MAX_IBSS_PEERS; idx++) {
+			if (0 != pHddStaCtx->conn_info.staId[idx]) {
+				buf = snprintf
+					      ((extra + length),
+					      WE_MAX_STR_LEN - length,
+					      "\n%d .%02x:%02x:%02x:%02x:%02x:%02x\n",
+					      pHddStaCtx->conn_info.staId[idx],
+					      pHddStaCtx->conn_info.
+					      peerMacAddress[idx].bytes[0],
+					      pHddStaCtx->conn_info.
+					      peerMacAddress[idx].bytes[1],
+					      pHddStaCtx->conn_info.
+					      peerMacAddress[idx].bytes[2],
+					      pHddStaCtx->conn_info.
+					      peerMacAddress[idx].bytes[3],
+					      pHddStaCtx->conn_info.
+					      peerMacAddress[idx].bytes[4],
+					      pHddStaCtx->conn_info.
+					      peerMacAddress[idx].bytes[5]
+					      );
+				length += buf;
+			}
+		}
+		wrqu->data.length = strlen(extra) + 1;
+		break;
+	}
 	case WE_GET_PHYMODE:
 	{
 		bool ch_bond24 = false, ch_bond5g = false;
@@ -7470,6 +7691,12 @@ static int __iw_setnone_getnone(struct net_device *dev,
 				0, DBG_CMD);
 		break;
 
+	case WE_IBSS_GET_PEER_INFO_ALL:
+	{
+		hdd_wlan_get_ibss_peer_info_all(adapter);
+		break;
+	}
+
 	case WE_SET_REASSOC_TRIGGER:
 	{
 		hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
@@ -7628,6 +7855,12 @@ static int __iw_set_var_ints_getnone(struct net_device *dev,
 	hddLog(LOG1, FL("Received length %d"), wrqu->data.length);
 
 	switch (sub_cmd) {
+	case WE_IBSS_GET_PEER_INFO:
+	{
+		pr_info("Station ID = %d\n", apps_args[0]);
+		hdd_wlan_get_ibss_peer_info(pAdapter, apps_args[0]);
+	}
+	break;
 
 	case WE_P2P_NOA_CMD:
 	{
@@ -10424,7 +10657,12 @@ static const struct iw_priv_args we_private_args[] = {
 		"getPMFInfo"
 	},
 #endif
-
+	{
+		WE_GET_IBSS_STA_INFO,
+		0,
+		IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN,
+		"getIbssSTAs"
+	},
 	{WE_GET_PHYMODE,
 	 0,
 	 IW_PRIV_TYPE_CHAR | WE_MAX_STR_LEN,
@@ -10446,6 +10684,13 @@ static const struct iw_priv_args we_private_args[] = {
 	 0,
 	 ""},
 
+	/* handlers for sub-ioctl */
+	{
+		WE_IBSS_GET_PEER_INFO_ALL,
+		0,
+		0,
+		"ibssPeerInfoAll"
+	},
 	{WE_GET_RECOVERY_STAT,
 	 0,
 	 0,
@@ -10501,6 +10746,12 @@ static const struct iw_priv_args we_private_args[] = {
 	 0,
 	 ""},
 
+	/* handlers for sub-ioctl */
+	{WE_IBSS_GET_PEER_INFO,
+	 IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
+	 0,
+	 "ibssPeerInfo"},
+
 	/* handlers for sub-ioctl */
 	{WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD,
 	 IW_PRIV_TYPE_INT | MAX_VAR_ARGS,

+ 43 - 0
core/mac/inc/sir_api.h

@@ -1770,6 +1770,13 @@ typedef struct sAniDHCPStopInd {
 	struct qdf_mac_addr peerMacAddr;
 } tAniDHCPInd, *tpAniDHCPInd;
 
+typedef struct sAniTXFailMonitorInd {
+	uint16_t msgType;       /* message type is same as the request type */
+	uint16_t msgLen;        /* length of the entire request */
+	uint8_t tx_fail_count;
+	void *txFailIndCallback;
+} tAniTXFailMonitorInd, *tpAniTXFailMonitorInd;
+
 typedef enum eTxRateInfo {
 	eHAL_TX_RATE_LEGACY = 0x1,      /* Legacy rates */
 	eHAL_TX_RATE_HT20 = 0x2,        /* HT20 rates */
@@ -3683,6 +3690,41 @@ typedef struct sSirDelPeriodicTxPtrn {
 	uint8_t ucPtrnId;       /* Pattern ID */
 } tSirDelPeriodicTxPtrn, *tpSirDelPeriodicTxPtrn;
 
+/*---------------------------------------------------------------------------
+* tSirIbssGetPeerInfoReqParams
+*--------------------------------------------------------------------------*/
+typedef struct {
+	bool allPeerInfoReqd;   /* If set, all IBSS peers stats are reported */
+	uint8_t staIdx;         /* If allPeerInfoReqd is not set, only stats */
+	/* of peer with staIdx is reported */
+} tSirIbssGetPeerInfoReqParams, *tpSirIbssGetPeerInfoReqParams;
+
+/*---------------------------------------------------------------------------
+* tSirIbssGetPeerInfoParams
+*--------------------------------------------------------------------------*/
+typedef struct {
+	uint8_t staIdx;         /* StaIdx */
+	uint32_t txRate;        /* Tx Rate */
+	uint32_t mcsIndex;      /* MCS Index */
+	uint32_t txRateFlags;   /* TxRate Flags */
+	int8_t rssi;            /* RSSI */
+} tSirIbssPeerInfoParams;
+
+typedef struct {
+	uint32_t status;
+	uint8_t numPeers;
+	tSirIbssPeerInfoParams peerInfoParams[32];
+} tSirPeerInfoRspParams, *tpSirIbssPeerInfoRspParams;
+
+/*---------------------------------------------------------------------------
+* tSirIbssGetPeerInfoRspParams
+*--------------------------------------------------------------------------*/
+typedef struct {
+	uint16_t mesgType;
+	uint16_t mesgLen;
+	tSirPeerInfoRspParams ibssPeerInfoRspParams;
+} tSirIbssGetPeerInfoRspParams, *tpSirIbssGetPeerInfoRspParams;
+
 typedef struct {
 	uint16_t mesgType;
 	uint16_t mesgLen;
@@ -3817,6 +3859,7 @@ typedef struct sSirModifyIE {
 	uint8_t ieIDLen;        /*ie length as per spec */
 	uint16_t ieBufferlength;
 	uint8_t *pIEBuffer;
+	int32_t oui_length;
 
 } tSirModifyIE, *tpSirModifyIE;
 

+ 1 - 0
core/mac/inc/wni_api.h

@@ -181,6 +181,7 @@ enum eWniMsgTypes {
 	eWNI_SME_LPHB_IND,
 #endif /* FEATURE_WLAN_LPHB */
 
+	eWNI_SME_IBSS_PEER_INFO_RSP,
 	eWNI_SME_GET_TSM_STATS_REQ,
 	eWNI_SME_GET_TSM_STATS_RSP,
 	eWNI_SME_TSM_IE_IND,

+ 10 - 0
core/mac/src/include/sir_params.h

@@ -427,6 +427,9 @@ typedef struct sSirMbMsgP2p {
 #define SIR_HAL_SOC_DUAL_MAC_CFG_REQ       (SIR_HAL_ITC_MSG_TYPES_BEGIN + 154)
 #define SIR_HAL_SOC_DUAL_MAC_CFG_RESP      (SIR_HAL_ITC_MSG_TYPES_BEGIN + 155)
 
+/* For IBSS peer info related messages */
+#define SIR_HAL_IBSS_PEER_INFO_REQ         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 158)
+
 #define SIR_HAL_RATE_UPDATE_IND            (SIR_HAL_ITC_MSG_TYPES_BEGIN + 159)
 
 #define SIR_HAL_FLUSH_LOG_TO_FW            (SIR_HAL_ITC_MSG_TYPES_BEGIN + 160)
@@ -449,6 +452,8 @@ typedef struct sSirMbMsgP2p {
 #define SIR_HAL_SET_MAX_TX_POWER_PER_BAND_REQ \
 					    (SIR_HAL_ITC_MSG_TYPES_BEGIN + 170)
 
+#define SIR_HAL_TX_FAIL_MONITOR_IND         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 171)
+
 #define SIR_HAL_UPDATE_MEMBERSHIP           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 172)
 #define SIR_HAL_UPDATE_USERPOS              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 173)
 
@@ -464,6 +469,11 @@ typedef struct sSirMbMsgP2p {
 #define SIR_HAL_BEACON_TX_SUCCESS_IND       (SIR_HAL_ITC_MSG_TYPES_BEGIN + 179)
 #define SIR_HAL_DFS_RADAR_IND               (SIR_HAL_ITC_MSG_TYPES_BEGIN + 180)
 
+#define SIR_HAL_IBSS_CESIUM_ENABLE_IND      (SIR_HAL_ITC_MSG_TYPES_BEGIN + 181)
+
+#define SIR_HAL_RMC_ENABLE_IND              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 182)
+#define SIR_HAL_RMC_DISABLE_IND             (SIR_HAL_ITC_MSG_TYPES_BEGIN + 183)
+#define SIR_HAL_RMC_ACTION_PERIOD_IND       (SIR_HAL_ITC_MSG_TYPES_BEGIN + 184)
 #define SIR_HAL_INIT_THERMAL_INFO_CMD       (SIR_HAL_ITC_MSG_TYPES_BEGIN + 185)
 #define SIR_HAL_SET_THERMAL_LEVEL           (SIR_HAL_ITC_MSG_TYPES_BEGIN + 186)
 

+ 54 - 1
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -106,7 +106,10 @@ static void lim_update_add_ie_buffer(tpAniSirGlobal pMac,
 				     uint8_t **pDstData_buff,
 				     uint16_t *pDstDataLen,
 				     uint8_t *pSrcData_buff, uint16_t srcDataLen);
-
+static bool lim_update_ibss_prop_add_ies(tpAniSirGlobal pMac,
+					 uint8_t **pDstData_buff,
+					 uint16_t *pDstDataLen,
+					 tSirModifyIE *pModifyIE);
 static void lim_process_modify_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg);
 
 static void lim_process_update_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg);
@@ -5177,6 +5180,44 @@ lim_update_add_ie_buffer(tpAniSirGlobal pMac,
 
 }
 
+/**
+ * lim_update_ibss_prop_add_ies() - update IBSS prop IE
+ * @pMac          : Pointer to Global MAC structure
+ * @pDstData_buff : A pointer to pointer of  dst buffer
+ * @pDstDataLen  :  A pointer to pointer of  dst buffer length
+ * @pModifyIE    :  A pointer to tSirModifyIE
+ *
+ * This function replaces previous ibss prop_ie with new ibss prop_ie.
+ *
+ * Return:
+ *  True or false depending upon whether IE is updated or not
+ */
+static bool
+lim_update_ibss_prop_add_ies(tpAniSirGlobal pMac, uint8_t **pDstData_buff,
+			     uint16_t *pDstDataLen, tSirModifyIE *pModifyIE)
+{
+	int32_t  oui_length;
+	uint8_t  *ibss_ie = NULL;
+
+	ibss_ie = pModifyIE->pIEBuffer;
+	oui_length = pModifyIE->oui_length;
+
+	if ((0 == oui_length) || (NULL == ibss_ie)) {
+		PELOGE(lim_log(pMac, LOGE,
+			FL("Invalid set IBSS vendor IE command length %d "),
+			oui_length);)
+		return false;
+	}
+
+	lim_update_add_ie_buffer(pMac,
+				 pDstData_buff,
+				 pDstDataLen,
+				 pModifyIE->pIEBuffer,
+				 pModifyIE->ieBufferlength);
+
+	return true;
+}
+
 /*
 * lim_process_modify_add_ies() - process modify additional IE req.
 *
@@ -5228,6 +5269,12 @@ static void lim_process_modify_add_ies(tpAniSirGlobal mac_ctx,
 	switch (modify_add_ies->updateType) {
 	case eUPDATE_IE_PROBE_RESP:
 		/* Probe resp */
+		if (LIM_IS_IBSS_ROLE(session_entry)) {
+			lim_update_ibss_prop_add_ies(mac_ctx,
+				&add_ie_params->probeRespData_buff,
+				&add_ie_params->probeRespDataLen,
+				&modify_add_ies->modifyIE);
+		}
 		break;
 	case eUPDATE_IE_ASSOC_RESP:
 		/* assoc resp IE */
@@ -5241,6 +5288,12 @@ static void lim_process_modify_add_ies(tpAniSirGlobal mac_ctx,
 		break;
 	case eUPDATE_IE_PROBE_BCN:
 		/*probe beacon IE */
+		if (LIM_IS_IBSS_ROLE(session_entry)) {
+			ret = lim_update_ibss_prop_add_ies(mac_ctx,
+				&add_ie_params->probeRespBCNData_buff,
+				&add_ie_params->probeRespBCNDataLen,
+				&modify_add_ies->modifyIE);
+		}
 		if (ret == true && modify_add_ies->modifyIE.notify) {
 			lim_handle_param_update(mac_ctx,
 					modify_add_ies->updateType);

+ 6 - 0
core/mac/src/sys/legacy/src/utils/src/mac_trace.c

@@ -489,6 +489,12 @@ uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg)
 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
 		CASE_RETURN_STRING(WMA_SET_AUTO_SHUTDOWN_TIMER_REQ);
 #endif
+		CASE_RETURN_STRING(WMA_IBSS_CESIUM_ENABLE_IND);
+		CASE_RETURN_STRING(WMA_GET_IBSS_PEER_INFO_REQ);
+		CASE_RETURN_STRING(WMA_TX_FAIL_MONITOR_IND);
+		CASE_RETURN_STRING(WMA_RMC_ENABLE_IND);
+		CASE_RETURN_STRING(WMA_RMC_DISABLE_IND);
+		CASE_RETURN_STRING(WMA_RMC_ACTION_PERIOD_IND);
 		CASE_RETURN_STRING(WMA_INIT_THERMAL_INFO_CMD);
 		CASE_RETURN_STRING(WMA_SET_THERMAL_LEVEL);
 		CASE_RETURN_STRING(WMA_SET_SAP_INTRABSS_DIS);

+ 4 - 0
core/sme/inc/csr_api.h

@@ -479,6 +479,8 @@ typedef enum {
 	eCSR_ROAM_UNPROT_MGMT_FRAME_IND,
 #endif
 
+	eCSR_ROAM_IBSS_PEER_INFO_COMPLETE,
+
 #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
 	eCSR_ROAM_TSM_IE_IND,
 	eCSR_ROAM_CCKM_PREAUTH_NOTIFY,
@@ -583,6 +585,8 @@ typedef enum {
 	eCSR_ROAM_RESULT_TDLS_SHOULD_PEER_DISCONNECTED,
 #endif
 
+	eCSR_ROAM_RESULT_IBSS_PEER_INFO_SUCCESS,
+	eCSR_ROAM_RESULT_IBSS_PEER_INFO_FAILED,
 	eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND,
 	eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS,
 	eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE,

+ 10 - 0
core/sme/inc/sme_api.h

@@ -421,6 +421,9 @@ QDF_STATUS sme_change_country_code(tHalHandle hHal,
 		tAniBool sendRegHint);
 QDF_STATUS sme_generic_change_country_code(tHalHandle hHal,
 					   uint8_t *pCountry);
+QDF_STATUS sme_tx_fail_monitor_start_stop_ind(tHalHandle hHal,
+		uint8_t tx_fail_count,
+		void *txFailIndCallback);
 QDF_STATUS sme_dhcp_start_ind(tHalHandle hHal,
 		uint8_t device_mode,
 		uint8_t *macAddr, uint8_t sessionId);
@@ -717,6 +720,13 @@ QDF_STATUS sme_roam_del_pmkid_from_cache(tHalHandle hHal, uint8_t sessionId,
 		const uint8_t *pBSSId, bool flush_cache);
 void sme_get_command_q_status(tHalHandle hHal);
 
+QDF_STATUS sme_enable_rmc(tHalHandle hHal, uint32_t sessionId);
+QDF_STATUS sme_disable_rmc(tHalHandle hHal, uint32_t sessionId);
+QDF_STATUS sme_send_rmc_action_period(tHalHandle hHal, uint32_t sessionId);
+QDF_STATUS sme_request_ibss_peer_info(tHalHandle hHal, void *pUserData,
+	pIbssPeerInfoCb peerInfoCbk, bool allPeerInfoReqd, uint8_t staIdx);
+QDF_STATUS sme_send_cesium_enable_ind(tHalHandle hHal, uint32_t sessionId);
+
 /*
  * SME API to enable/disable idle mode powersave
  * This should be called only if powersave offload

+ 10 - 0
core/sme/inc/sme_internal.h

@@ -103,6 +103,15 @@ typedef enum eSmeState {
 #define SME_IS_START(pMac)  (SME_STATE_STOP != (pMac)->sme.state)
 #define SME_IS_READY(pMac)  (SME_STATE_READY == (pMac)->sme.state)
 
+/* HDD Callback function */
+typedef void (*pIbssPeerInfoCb)(void *pUserData, void *infoParam);
+
+/* Peer info */
+typedef struct tagSmePeerInfoHddCbkInfo {
+	void *pUserData;
+	pIbssPeerInfoCb peerInfoCbk;
+} tSmePeerInfoHddCbkInfo;
+
 typedef struct sStatsExtEvent {
 	uint32_t vdev_id;
 	uint32_t event_data_len;
@@ -156,6 +165,7 @@ typedef struct tagSmeStruct {
 	tDblLinkList smeScanCmdPendingList;
 	/* active scan command list */
 	tDblLinkList smeScanCmdActiveList;
+	tSmePeerInfoHddCbkInfo peerInfoParams;
 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
 	host_event_wlan_status_payload_type eventPayload;
 #endif

+ 266 - 1
core/sme/src/common/sme_api.c

@@ -2092,6 +2092,28 @@ QDF_STATUS sme_set_ese_beacon_request(tHalHandle hHal, const uint8_t sessionId,
 
 #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
 
+QDF_STATUS sme_ibss_peer_info_response_handleer(tHalHandle hHal,
+						tpSirIbssGetPeerInfoRspParams
+						pIbssPeerInfoParams)
+{
+	tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+
+	if (NULL == pMac) {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_FATAL,
+			  "%s: pMac is null", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	if (pMac->sme.peerInfoParams.peerInfoCbk == NULL) {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+			  "%s: HDD callback is null", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	pMac->sme.peerInfoParams.peerInfoCbk(pMac->sme.peerInfoParams.pUserData,
+					     &pIbssPeerInfoParams->
+					     ibssPeerInfoRspParams);
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * sme_process_fw_mem_dump_rsp - process fw memory dump response from WMA
  *
@@ -2457,7 +2479,17 @@ QDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg)
 		qdf_mem_free(pMsg->bodyptr);
 		break;
 #endif /* FEATURE_WLAN_LPHB */
-
+	case eWNI_SME_IBSS_PEER_INFO_RSP:
+		if (pMsg->bodyptr) {
+			sme_ibss_peer_info_response_handleer(pMac,
+							     pMsg->
+							     bodyptr);
+			qdf_mem_free(pMsg->bodyptr);
+		} else {
+			sms_log(pMac, LOGE, FL("Empty message for %d"),
+				pMsg->type);
+		}
+		break;
 	case eWNI_SME_READY_TO_SUSPEND_IND:
 		if (pMsg->bodyptr) {
 			sme_process_ready_to_suspend(pMac, pMsg->bodyptr);
@@ -5334,6 +5366,60 @@ QDF_STATUS sme_dhcp_stop_ind(tHalHandle hHal,
 	return status;
 }
 
+/*---------------------------------------------------------------------------
+
+    \fn sme_TXFailMonitorStopInd
+
+    \brief API to signal the FW to start monitoring TX failures
+
+    \return QDF_STATUS  SUCCESS.
+
+			FAILURE or RESOURCES  The API finished and failed.
+   --------------------------------------------------------------------------*/
+QDF_STATUS sme_tx_fail_monitor_start_stop_ind(tHalHandle hHal, uint8_t tx_fail_count,
+					      void *txFailIndCallback)
+{
+	QDF_STATUS status;
+	QDF_STATUS qdf_status;
+	tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+	cds_msg_t cds_message;
+	tAniTXFailMonitorInd *pMsg;
+
+	status = sme_acquire_global_lock(&pMac->sme);
+	if (QDF_STATUS_SUCCESS == status) {
+		pMsg = (tAniTXFailMonitorInd *)
+		       qdf_mem_malloc(sizeof(tAniTXFailMonitorInd));
+		if (NULL == pMsg) {
+			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+				  "%s: Failed to allocate memory", __func__);
+			sme_release_global_lock(&pMac->sme);
+			return QDF_STATUS_E_NOMEM;
+		}
+
+		pMsg->msgType = WMA_TX_FAIL_MONITOR_IND;
+		pMsg->msgLen = (uint16_t) sizeof(tAniTXFailMonitorInd);
+
+		/* tx_fail_count = 0 should disable the Monitoring in FW */
+		pMsg->tx_fail_count = tx_fail_count;
+		pMsg->txFailIndCallback = txFailIndCallback;
+
+		cds_message.type = WMA_TX_FAIL_MONITOR_IND;
+		cds_message.bodyptr = pMsg;
+		cds_message.reserved = 0;
+
+		qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
+		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+				  "%s: Post TX Fail monitor Start MSG fail",
+				  __func__);
+			qdf_mem_free(pMsg);
+			status = QDF_STATUS_E_FAILURE;
+		}
+		sme_release_global_lock(&pMac->sme);
+	}
+	return status;
+}
+
 /* ---------------------------------------------------------------------------
     \fn sme_set_cfg_privacy
     \brief  API to set configure privacy parameters
@@ -10643,6 +10729,185 @@ sme_del_periodic_tx_ptrn(tHalHandle hal,
 	return status;
 }
 
+/**
+  * sme_enable_rmc() - enables RMC
+  * @hHal : Pointer to global HAL handle
+  * @sessionId : Session ID
+  *
+  * Return: QDF_STATUS
+  */
+QDF_STATUS sme_enable_rmc(tHalHandle hHal, uint32_t sessionId)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+	cds_msg_t cds_message;
+	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
+
+	sms_log(pMac, LOG1, FL("enable RMC"));
+	status = sme_acquire_global_lock(&pMac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		cds_message.bodyptr = NULL;
+		cds_message.type = WMA_RMC_ENABLE_IND;
+		qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
+		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+				  "%s: failed to post message to WMA",
+				  __func__);
+			status = QDF_STATUS_E_FAILURE;
+		}
+		sme_release_global_lock(&pMac->sme);
+	}
+	return status;
+}
+
+/**
+  * sme_disable_rmc() - disables RMC
+  * @hHal : Pointer to global HAL handle
+  * @sessionId : Session ID
+  *
+  * Return: QDF_STATUS
+  */
+QDF_STATUS sme_disable_rmc(tHalHandle hHal, uint32_t sessionId)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+	cds_msg_t cds_message;
+	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
+
+	sms_log(pMac, LOG1, FL("disable RMC"));
+	status = sme_acquire_global_lock(&pMac->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		cds_message.bodyptr = NULL;
+		cds_message.type = WMA_RMC_DISABLE_IND;
+		qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
+		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+				  "%s: failed to post message to WMA",
+				  __func__);
+			status = QDF_STATUS_E_FAILURE;
+		}
+		sme_release_global_lock(&pMac->sme);
+	}
+	return status;
+}
+
+/**
+  * sme_send_rmc_action_period() - sends RMC action period param to target
+  * @hHal : Pointer to global HAL handle
+  * @sessionId : Session ID
+  *
+  * Return: QDF_STATUS
+  */
+QDF_STATUS sme_send_rmc_action_period(tHalHandle hHal, uint32_t sessionId)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
+	tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+	cds_msg_t cds_message;
+
+	status = sme_acquire_global_lock(&pMac->sme);
+	if (QDF_STATUS_SUCCESS == status) {
+		cds_message.bodyptr = NULL;
+		cds_message.type = WMA_RMC_ACTION_PERIOD_IND;
+		qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
+		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+				  "%s: failed to post message to WMA",
+				  __func__);
+			status = QDF_STATUS_E_FAILURE;
+		}
+		sme_release_global_lock(&pMac->sme);
+	}
+
+	return status;
+}
+
+/**
+  * sme_request_ibss_peer_info() -  request ibss peer info
+  * @hHal : Pointer to global HAL handle
+  * @pUserData : Pointer to user data
+  * @peerInfoCbk : Peer info callback
+  * @allPeerInfoReqd : All peer info required or not
+  * @staIdx : sta index
+  *
+  * Return:  QDF_STATUS
+  */
+QDF_STATUS sme_request_ibss_peer_info(tHalHandle hHal, void *pUserData,
+				      pIbssPeerInfoCb peerInfoCbk,
+				      bool allPeerInfoReqd, uint8_t staIdx)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
+	tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+	cds_msg_t cds_message;
+	tSirIbssGetPeerInfoReqParams *pIbssInfoReqParams;
+
+	status = sme_acquire_global_lock(&pMac->sme);
+	if (QDF_STATUS_SUCCESS == status) {
+		pMac->sme.peerInfoParams.peerInfoCbk = peerInfoCbk;
+		pMac->sme.peerInfoParams.pUserData = pUserData;
+
+		pIbssInfoReqParams = (tSirIbssGetPeerInfoReqParams *)
+				     qdf_mem_malloc(sizeof(tSirIbssGetPeerInfoReqParams));
+		if (NULL == pIbssInfoReqParams) {
+			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+				  "%s: Not able to allocate memory for dhcp start",
+				  __func__);
+			sme_release_global_lock(&pMac->sme);
+			return QDF_STATUS_E_NOMEM;
+		}
+		pIbssInfoReqParams->allPeerInfoReqd = allPeerInfoReqd;
+		pIbssInfoReqParams->staIdx = staIdx;
+
+		cds_message.type = WMA_GET_IBSS_PEER_INFO_REQ;
+		cds_message.bodyptr = pIbssInfoReqParams;
+		cds_message.reserved = 0;
+
+		qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
+		if (QDF_STATUS_SUCCESS != qdf_status) {
+			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+				  "%s: Post WMA_GET_IBSS_PEER_INFO_REQ MSG failed",
+				  __func__);
+			qdf_mem_free(pIbssInfoReqParams);
+			qdf_status = QDF_STATUS_E_FAILURE;
+		}
+		sme_release_global_lock(&pMac->sme);
+	}
+
+	return qdf_status;
+}
+
+/* ---------------------------------------------------------------------------
+    \fn sme_send_cesium_enable_ind
+    \brief  Used to send proprietary cesium enable indication to fw
+    \param  hHal
+    \param  sessionId
+   \- return QDF_STATUS
+    -------------------------------------------------------------------------*/
+QDF_STATUS sme_send_cesium_enable_ind(tHalHandle hHal, uint32_t sessionId)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
+	tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+	cds_msg_t cds_message;
+
+	status = sme_acquire_global_lock(&pMac->sme);
+	if (QDF_STATUS_SUCCESS == status) {
+		cds_message.bodyptr = NULL;
+		cds_message.type = WMA_IBSS_CESIUM_ENABLE_IND;
+		qdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
+		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+				  "%s: failed to post message to WMA",
+				  __func__);
+			status = QDF_STATUS_E_FAILURE;
+		}
+		sme_release_global_lock(&pMac->sme);
+	}
+
+	return status;
+}
+
 void sme_get_command_q_status(tHalHandle hHal)
 {
 	tSmeCmd *pTempCmd = NULL;

+ 1 - 0
core/sme/src/csr/csr_api_roam.c

@@ -18103,6 +18103,7 @@ csr_roam_modify_add_ies(tpAniSirGlobal pMac,
 	pModifyAddIEInd->modifyIE.ieIDLen = pModifyIE->ieIDLen;
 	pModifyAddIEInd->modifyIE.pIEBuffer = pLocalBuffer;
 	pModifyAddIEInd->modifyIE.ieBufferlength = pModifyIE->ieBufferlength;
+	pModifyAddIEInd->modifyIE.oui_length = pModifyIE->oui_length;
 
 	pModifyAddIEInd->updateType = updateType;
 

+ 5 - 1
core/wma/inc/wma.h

@@ -383,6 +383,8 @@ static const t_probeTime_dwellTime
 	{28, 8}                 /* 10 SSID */
 };
 
+typedef void (*txFailIndCallback)(uint8_t *peer_mac, uint8_t seqNo);
+
 /**
  * enum t_wma_drv_type - wma driver type
  * @WMA_DRIVER_TYPE_PRODUCTION: production driver type
@@ -1265,7 +1267,7 @@ typedef struct {
 	uint8_t ibss_started;
 	tSetBssKeyParams ibsskey_info;
 	struct ieee80211com *dfs_ic;
-
+	txFailIndCallback hddTxFailCb;
 #ifdef FEATURE_WLAN_SCAN_PNO
 	qdf_wake_lock_t pno_wake_lock;
 #endif
@@ -1292,6 +1294,8 @@ typedef struct {
 	uint8_t staMaxLIModDtim;
 	uint8_t staModDtim;
 	uint8_t staDynamicDtim;
+	uint8_t enable_mhf_offload;
+	unsigned long last_mhf_entries_timestamp;
 	int32_t dfs_pri_multiplier;
 	uint32_t hw_bd_id;
 	uint32_t hw_bd_info[HW_BD_INFO_SIZE];

+ 23 - 0
core/wma/inc/wma_internal.h

@@ -101,6 +101,9 @@
 #define WMI_MAX_HOST_CREDITS 2
 #define WMI_WOW_REQUIRED_CREDITS 1
 
+#define WMI_MAX_MHF_ENTRIES 32
+
+
 #define MAX_HT_MCS_IDX 8
 #define MAX_VHT_MCS_IDX 10
 #define INVALID_MCS_IDX 255
@@ -795,6 +798,12 @@ QDF_STATUS wma_set_thermal_mgmt(tp_wma_handle wma_handle,
 int wma_thermal_mgmt_evt_handler(void *handle, uint8_t *event,
 					uint32_t len);
 
+int wma_ibss_peer_info_event_handler(void *handle, uint8_t *data,
+					    uint32_t len);
+
+int wma_fast_tx_fail_event_handler(void *handle, uint8_t *data,
+					  uint32_t len);
+
 /*
  * wma_utils.c functions declarations
  */
@@ -1017,6 +1026,20 @@ QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
 				     tpSirHostOffloadReq pHostOffloadParams,
 				     bool bArpOnly);
 
+QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma);
+
+QDF_STATUS wma_process_get_peer_info_req
+	(tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq);
+
+QDF_STATUS wma_process_tx_fail_monitor_ind
+	(tp_wma_handle wma, tAniTXFailMonitorInd *pReq);
+
+QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma);
+
+QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma);
+
+QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma);
+
 QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,
 						tSirAddPeriodicTxPtrn *
 						pAddPeriodicTxPtrnParams);

+ 12 - 0
core/wma/inc/wma_types.h

@@ -303,6 +303,8 @@
 #define WMA_DHCP_START_IND              SIR_HAL_DHCP_START_IND
 #define WMA_DHCP_STOP_IND               SIR_HAL_DHCP_STOP_IND
 
+#define WMA_TX_FAIL_MONITOR_IND         SIR_HAL_TX_FAIL_MONITOR_IND
+
 #define WMA_HIDDEN_SSID_VDEV_RESTART    SIR_HAL_HIDE_SSID_VDEV_RESTART
 
 #ifdef WLAN_FEATURE_GTK_OFFLOAD
@@ -358,6 +360,14 @@
 
 #define WMA_INIT_THERMAL_INFO_CMD   SIR_HAL_INIT_THERMAL_INFO_CMD
 #define WMA_SET_THERMAL_LEVEL       SIR_HAL_SET_THERMAL_LEVEL
+#define WMA_RMC_ENABLE_IND          SIR_HAL_RMC_ENABLE_IND
+#define WMA_RMC_DISABLE_IND         SIR_HAL_RMC_DISABLE_IND
+#define WMA_RMC_ACTION_PERIOD_IND   SIR_HAL_RMC_ACTION_PERIOD_IND
+
+/* IBSS peer info related message */
+#define WMA_GET_IBSS_PEER_INFO_REQ  SIR_HAL_IBSS_PEER_INFO_REQ
+
+#define WMA_IBSS_CESIUM_ENABLE_IND  SIR_HAL_IBSS_CESIUM_ENABLE_IND
 
 #ifdef FEATURE_WLAN_TDLS
 #define WMA_UPDATE_FW_TDLS_STATE          SIR_HAL_UPDATE_FW_TDLS_STATE
@@ -584,6 +594,8 @@ typedef void (*pWMATxRxCompFunc)(void *pContext, void *pData,
 /* parameter 2 - txComplete status : 1- success, 0 - failure. */
 typedef QDF_STATUS (*pWMAAckFnTxComp)(tpAniSirGlobal, uint32_t);
 
+typedef void (*wma_txFailIndCallback)(uint8_t *, uint8_t);
+
 /* generic callback for updating parameters from target to UMAC */
 typedef void (*wma_tgt_cfg_cb)(void *context, void *param);
 

+ 146 - 0
core/wma/src/wma_data.c

@@ -1976,6 +1976,152 @@ int wma_thermal_mgmt_evt_handler(void *handle, uint8_t *event,
 	return 0;
 }
 
+/**
+ * wma_ibss_peer_info_event_handler() - IBSS peer info event handler
+ * @handle: wma handle
+ * @data: event data
+ * @len: length of data
+ *
+ * This function handles IBSS peer info event from FW.
+ *
+ * Return: 0 for success or error code
+ */
+int wma_ibss_peer_info_event_handler(void *handle, uint8_t *data,
+					    uint32_t len)
+{
+	cds_msg_t cds_msg;
+	wmi_peer_info *peer_info;
+	ol_txrx_pdev_handle pdev;
+	struct ol_txrx_peer_t *peer;
+	tSirIbssPeerInfoParams *pSmeRsp;
+	uint32_t count, num_peers, status;
+	tSirIbssGetPeerInfoRspParams *pRsp;
+	WMI_PEER_INFO_EVENTID_param_tlvs *param_tlvs;
+	wmi_peer_info_event_fixed_param *fix_param;
+	uint8_t peer_mac[IEEE80211_ADDR_LEN], staIdx;
+
+	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+	if (NULL == pdev) {
+		WMA_LOGE("%s: could not get pdev context", __func__);
+		return 0;
+	}
+
+	param_tlvs = (WMI_PEER_INFO_EVENTID_param_tlvs *) data;
+	fix_param = param_tlvs->fixed_param;
+	peer_info = param_tlvs->peer_info;
+	num_peers = fix_param->num_peers;
+	status = 0;
+
+	WMA_LOGE("%s: num_peers %d", __func__, num_peers);
+
+	pRsp = qdf_mem_malloc(sizeof(tSirIbssGetPeerInfoRspParams));
+	if (NULL == pRsp) {
+		WMA_LOGE("%s: could not allocate memory for ibss peer info rsp len %zu",
+			__func__, sizeof(tSirIbssGetPeerInfoRspParams));
+		return 0;
+	}
+
+	/*sanity check */
+	if ((num_peers > 32) || (NULL == peer_info)) {
+		WMA_LOGE("%s: Invalid event data from target num_peers %d peer_info %p",
+			__func__, num_peers, peer_info);
+		status = 1;
+		goto send_response;
+	}
+
+	for (count = 0; count < num_peers; count++) {
+		pSmeRsp = &pRsp->ibssPeerInfoRspParams.peerInfoParams[count];
+
+		WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_info->peer_mac_address,
+					   peer_mac);
+		peer = ol_txrx_find_peer_by_addr(pdev, peer_mac, &staIdx);
+		if (NULL == peer) {
+			WMA_LOGE("%s: peer 0x:%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x does not"
+				" exist could not populate response", __func__,
+				peer_mac[0], peer_mac[1], peer_mac[2],
+				peer_mac[3], peer_mac[4], peer_mac[5]);
+
+			pSmeRsp->staIdx = 0xff; /*fill invalid staIdx */
+			peer_info++;
+			continue;
+		}
+		pSmeRsp->staIdx = staIdx;
+		pSmeRsp->mcsIndex = 0;
+		pSmeRsp->rssi = peer_info->rssi + WMA_TGT_NOISE_FLOOR_DBM;
+		pSmeRsp->txRate = peer_info->data_rate;
+		pSmeRsp->txRateFlags = 0;
+
+		WMA_LOGE("%s: peer 0x:%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x staIdx %d "
+			"rssi %d txRate %d", __func__, peer_mac[0], peer_mac[1],
+			peer_mac[2], peer_mac[3], peer_mac[4], peer_mac[5],
+			staIdx, pSmeRsp->rssi, pSmeRsp->txRate);
+
+		peer_info++;
+	}
+
+send_response:
+	/* message header */
+	pRsp->mesgType = eWNI_SME_IBSS_PEER_INFO_RSP;
+	pRsp->mesgLen = sizeof(tSirIbssGetPeerInfoRspParams);
+	pRsp->ibssPeerInfoRspParams.status = status;
+	pRsp->ibssPeerInfoRspParams.numPeers = num_peers;
+
+	/* cds message wrapper */
+	cds_msg.type = eWNI_SME_IBSS_PEER_INFO_RSP;
+	cds_msg.bodyptr = (void *)pRsp;
+	cds_msg.bodyval = 0;
+
+	if (QDF_STATUS_SUCCESS !=
+	    cds_mq_post_message(CDS_MQ_ID_SME, (cds_msg_t *) &cds_msg)) {
+		WMA_LOGE("%s: could not post peer info rsp msg to SME",
+			 __func__);
+		/* free the mem and return */
+		qdf_mem_free((void *)pRsp);
+	}
+
+	return 0;
+}
+
+/**
+ * wma_fast_tx_fail_event_handler() -tx failure event handler
+ * @handle: wma handle
+ * @data: event data
+ * @len: data length
+ *
+ * Handle fast tx failure indication event from FW
+ *
+ * Return: 0 for success or error code.
+ */
+int wma_fast_tx_fail_event_handler(void *handle, uint8_t *data,
+					  uint32_t len)
+{
+	uint8_t tx_fail_cnt;
+	uint8_t peer_mac[IEEE80211_ADDR_LEN];
+	tp_wma_handle wma = (tp_wma_handle) handle;
+	WMI_PEER_TX_FAIL_CNT_THR_EVENTID_param_tlvs *param_tlvs;
+	wmi_peer_tx_fail_cnt_thr_event_fixed_param *fix_param;
+
+	param_tlvs = (WMI_PEER_TX_FAIL_CNT_THR_EVENTID_param_tlvs *) data;
+	fix_param = param_tlvs->fixed_param;
+
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&fix_param->peer_mac_address, peer_mac);
+	WMA_LOGE("%s: received fast tx failure event for peer"
+		 "  0x:%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x seq No %d", __func__,
+		 peer_mac[0], peer_mac[1], peer_mac[2], peer_mac[3],
+		 peer_mac[4], peer_mac[5], fix_param->seq_no);
+
+	tx_fail_cnt = fix_param->seq_no;
+
+	/*call HDD callback */
+	if (NULL != wma->hddTxFailCb) {
+		wma->hddTxFailCb(peer_mac, tx_fail_cnt);
+	} else {
+		WMA_LOGE("%s: HDD callback is %p", __func__, wma->hddTxFailCb);
+	}
+
+	return 0;
+}
+
 /**
  * wma_decap_to_8023() - Decapsulate to 802.3 format
  * @msdu: skb buffer

+ 319 - 0
core/wma/src/wma_features.c

@@ -4323,6 +4323,325 @@ QDF_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * wma_process_cesium_enable_ind() - enables cesium functionality in target
+ * @wma: wma handle
+ *
+ * Return: QDF status
+ */
+QDF_STATUS wma_process_cesium_enable_ind(tp_wma_handle wma)
+{
+	QDF_STATUS ret;
+	int32_t vdev_id;
+
+	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
+	if (vdev_id < 0) {
+		WMA_LOGE("%s: IBSS vdev does not exist could not enable cesium",
+			 __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* Send enable cesium command to target */
+	WMA_LOGE("Enable cesium in target for vdevId %d ", vdev_id);
+	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
+				 WMI_VDEV_PARAM_ENABLE_RMC, 1);
+	if (ret) {
+		WMA_LOGE("Enable cesium failed for vdevId %d", vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wma_process_get_peer_info_req() - sends get peer info cmd to target
+ * @wma: wma handle
+ * @preq: get peer info request
+ *
+ * Return: QDF status
+ */
+QDF_STATUS wma_process_get_peer_info_req
+	(tp_wma_handle wma, tSirIbssGetPeerInfoReqParams *pReq)
+{
+	int32_t ret;
+	uint8_t *p;
+	uint16_t len;
+	wmi_buf_t buf;
+	int32_t vdev_id;
+	ol_txrx_pdev_handle pdev;
+	struct ol_txrx_peer_t *peer;
+	uint8_t peer_mac[IEEE80211_ADDR_LEN];
+	wmi_peer_info_req_cmd_fixed_param *p_get_peer_info_cmd;
+	uint8_t bcast_mac[IEEE80211_ADDR_LEN] = { 0xff, 0xff, 0xff,
+						  0xff, 0xff, 0xff };
+
+	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
+	if (vdev_id < 0) {
+		WMA_LOGE("%s: IBSS vdev does not exist could not get peer info",
+			 __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+	if (NULL == pdev) {
+		WMA_LOGE("%s: Failed to get pdev context", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (0xFF == pReq->staIdx) {
+		/*get info for all peers */
+		qdf_mem_copy(peer_mac, bcast_mac, IEEE80211_ADDR_LEN);
+	} else {
+		/*get info for a single peer */
+		peer = ol_txrx_peer_find_by_local_id(pdev, pReq->staIdx);
+		if (!peer) {
+			WMA_LOGE("%s: Failed to get peer handle using peer id %d",
+				__func__, pReq->staIdx);
+			return QDF_STATUS_E_FAILURE;
+		}
+		WMA_LOGE("%s: staIdx %d peer mac: 0x%2x:0x%2x:0x%2x:0x%2x:0x%2x:0x%2x",
+			__func__, pReq->staIdx, peer->mac_addr.raw[0],
+			peer->mac_addr.raw[1], peer->mac_addr.raw[2],
+			peer->mac_addr.raw[3], peer->mac_addr.raw[4],
+			peer->mac_addr.raw[5]);
+		qdf_mem_copy(peer_mac, peer->mac_addr.raw, IEEE80211_ADDR_LEN);
+	}
+
+	len = sizeof(wmi_peer_info_req_cmd_fixed_param);
+	buf = wmi_buf_alloc(wma->wmi_handle, len);
+	if (!buf) {
+		WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	p = (uint8_t *) wmi_buf_data(buf);
+	qdf_mem_zero(p, len);
+	p_get_peer_info_cmd = (wmi_peer_info_req_cmd_fixed_param *) p;
+
+	WMITLV_SET_HDR(&p_get_peer_info_cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_peer_info_req_cmd_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN
+			       (wmi_peer_info_req_cmd_fixed_param));
+
+	p_get_peer_info_cmd->vdev_id = vdev_id;
+	WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_mac,
+				   &p_get_peer_info_cmd->peer_mac_address);
+
+	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
+				   WMI_PEER_INFO_REQ_CMDID);
+
+	WMA_LOGE("IBSS get peer info cmd sent len: %d, vdev %d"
+		 " command id: %d, status: %d", len,
+		 p_get_peer_info_cmd->vdev_id, WMI_PEER_INFO_REQ_CMDID, ret);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wma_process_tx_fail_monitor_ind() - sends tx fail monitor cmd to target
+ * @wma: wma handle
+ * @pReq: tx fail monitor command params
+ *
+ * Return: QDF status
+ */
+QDF_STATUS wma_process_tx_fail_monitor_ind
+	(tp_wma_handle wma, tAniTXFailMonitorInd *pReq)
+{
+	QDF_STATUS ret;
+	int32_t vdev_id;
+
+	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
+	if (vdev_id < 0) {
+		WMA_LOGE("%s: IBSS vdev does not exist could not send fast tx fail"
+			" monitor indication message to target", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	/* Send enable cesium command to target */
+	WMA_LOGE("send fast tx fail monitor ind cmd target for vdevId %d val %d",
+		vdev_id, pReq->tx_fail_count);
+
+	if (0 == pReq->tx_fail_count) {
+		wma->hddTxFailCb = NULL;
+	} else {
+		wma->hddTxFailCb = pReq->txFailIndCallback;
+	}
+	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
+				 WMI_VDEV_PARAM_SET_IBSS_TX_FAIL_CNT_THR,
+				 pReq->tx_fail_count);
+	if (ret) {
+		WMA_LOGE("tx fail monitor failed for vdevId %d", vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wma_process_rmc_enable_ind() - enables RMC functionality in target
+ * @wma: wma handle
+ *
+ * Return: QDF status
+ */
+QDF_STATUS wma_process_rmc_enable_ind(tp_wma_handle wma)
+{
+	int ret;
+	uint8_t *p;
+	uint16_t len;
+	wmi_buf_t buf;
+	int32_t vdev_id;
+	wmi_rmc_set_mode_cmd_fixed_param *p_rmc_enable_cmd;
+
+	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
+	if (vdev_id < 0) {
+		WMA_LOGE("%s: IBSS vdev does not exist could not enable RMC",
+			 __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
+	buf = wmi_buf_alloc(wma->wmi_handle, len);
+	if (!buf) {
+		WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	p = (uint8_t *) wmi_buf_data(buf);
+	qdf_mem_zero(p, len);
+	p_rmc_enable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
+
+	WMITLV_SET_HDR(&p_rmc_enable_cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN
+			       (wmi_rmc_set_mode_cmd_fixed_param));
+
+	p_rmc_enable_cmd->vdev_id = vdev_id;
+	p_rmc_enable_cmd->enable_rmc = WMI_RMC_MODE_ENABLED;
+
+	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
+				   WMI_RMC_SET_MODE_CMDID);
+
+	WMA_LOGE("Enable RMC cmd sent len: %d, vdev %d" " command id: %d,"
+		 " status: %d", len, p_rmc_enable_cmd->vdev_id,
+		 WMI_RMC_SET_MODE_CMDID, ret);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wma_process_rmc_disable_ind() - disables rmc functionality in target
+ * @wma: wma handle
+ *
+ * Return: QDF status
+ */
+QDF_STATUS wma_process_rmc_disable_ind(tp_wma_handle wma)
+{
+	int ret;
+	uint8_t *p;
+	uint16_t len;
+	wmi_buf_t buf;
+	int32_t vdev_id;
+	wmi_rmc_set_mode_cmd_fixed_param *p_rmc_disable_cmd;
+
+	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
+	if (vdev_id < 0) {
+		WMA_LOGE("%s: IBSS vdev does not exist could not disable RMC",
+			 __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	len = sizeof(wmi_rmc_set_mode_cmd_fixed_param);
+	buf = wmi_buf_alloc(wma->wmi_handle, len);
+	if (!buf) {
+		WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	p = (uint8_t *) wmi_buf_data(buf);
+	qdf_mem_zero(p, len);
+	p_rmc_disable_cmd = (wmi_rmc_set_mode_cmd_fixed_param *) p;
+
+	WMITLV_SET_HDR(&p_rmc_disable_cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_rmc_set_mode_cmd_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN
+			       (wmi_rmc_set_mode_cmd_fixed_param));
+
+	p_rmc_disable_cmd->vdev_id = vdev_id;
+	p_rmc_disable_cmd->enable_rmc = WMI_RMC_MODE_DISABLED;
+
+	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
+				   WMI_RMC_SET_MODE_CMDID);
+
+	WMA_LOGE("Disable RMC cmd sent len: %d, vdev %d" " command id: %d,"
+		 " status: %d", len, p_rmc_disable_cmd->vdev_id,
+		 WMI_RMC_SET_MODE_CMDID, ret);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wma_process_rmc_action_period_ind() - sends RMC action period to target
+ * @wma: wma handle
+ *
+ * Return: QDF status
+ */
+QDF_STATUS wma_process_rmc_action_period_ind(tp_wma_handle wma)
+{
+	int ret;
+	uint8_t *p;
+	uint16_t len;
+	uint32_t val;
+	wmi_buf_t buf;
+	int32_t vdev_id;
+	wmi_rmc_set_action_period_cmd_fixed_param *p_rmc_cmd;
+	struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
+
+	if (NULL == mac) {
+		WMA_LOGE("%s: MAC mac does not exist", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	vdev_id = wma_find_vdev_by_type(wma, WMI_VDEV_TYPE_IBSS);
+	if (vdev_id < 0) {
+		WMA_LOGE("%s: IBSS vdev does not exist could not send"
+			 " RMC action period to target", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	len = sizeof(wmi_rmc_set_action_period_cmd_fixed_param);
+	buf = wmi_buf_alloc(wma->wmi_handle, len);
+	if (!buf) {
+		WMA_LOGE("%s %d: No WMI resource!", __func__, __LINE__);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	p = (uint8_t *) wmi_buf_data(buf);
+	qdf_mem_zero(p, len);
+	p_rmc_cmd = (wmi_rmc_set_action_period_cmd_fixed_param *) p;
+
+	WMITLV_SET_HDR(&p_rmc_cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_rmc_set_action_period_cmd_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN
+			       (wmi_rmc_set_action_period_cmd_fixed_param));
+
+	if (wlan_cfg_get_int(mac, WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY, &val)
+	    != eSIR_SUCCESS) {
+		WMA_LOGE("Failed to get value for RMC action period using default");
+		val = WNI_CFG_RMC_ACTION_PERIOD_FREQUENCY_STADEF;
+	}
+
+	p_rmc_cmd->vdev_id = vdev_id;
+	p_rmc_cmd->periodicity_msec = val;
+
+	ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
+				   WMI_RMC_SET_ACTION_PERIOD_CMDID);
+
+	WMA_LOGE("RMC action period %d cmd sent len: %d, vdev %d"
+		 " command id: %d, status: %d", p_rmc_cmd->periodicity_msec,
+		 len, p_rmc_cmd->vdev_id, WMI_RMC_SET_ACTION_PERIOD_CMDID, ret);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * wma_process_add_periodic_tx_ptrn_ind - add periodic tx ptrn
  * @handle: wma handle

+ 52 - 0
core/wma/src/wma_main.c

@@ -2695,6 +2695,34 @@ QDF_STATUS wma_start(void *cds_ctx)
 		goto end;
 #endif /* QCA_WIFI_FTM */
 
+	if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
+				   WMI_SERVICE_RMC)) {
+
+		WMA_LOGD("FW supports cesium network, registering event handlers");
+
+		status = wmi_unified_register_event_handler(wma_handle->wmi_handle,
+							   WMI_PEER_INFO_EVENTID,
+							   wma_ibss_peer_info_event_handler,
+							   WMA_RX_SERIALIZER_CTX);
+		if (status) {
+			WMA_LOGE("Failed to register ibss peer info event cb");
+			qdf_status = QDF_STATUS_E_FAILURE;
+			goto end;
+		}
+
+		status = wmi_unified_register_event_handler(wma_handle->wmi_handle,
+							   WMI_PEER_TX_FAIL_CNT_THR_EVENTID,
+							   wma_fast_tx_fail_event_handler,
+							   WMA_RX_SERIALIZER_CTX);
+		if (status) {
+			WMA_LOGE("Failed to register peer fast tx failure event cb");
+			qdf_status = QDF_STATUS_E_FAILURE;
+			goto end;
+		}
+	} else {
+		WMA_LOGE("Target does not support cesium network");
+	}
+
 	qdf_status = wma_tx_attach(wma_handle);
 	if (qdf_status != QDF_STATUS_SUCCESS) {
 		WMA_LOGP("%s: Failed to register tx management", __func__);
@@ -4860,6 +4888,30 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg)
 		qdf_mem_free(msg->bodyptr);
 		break;
 
+	case WMA_IBSS_CESIUM_ENABLE_IND:
+		wma_process_cesium_enable_ind(wma_handle);
+		break;
+	case WMA_GET_IBSS_PEER_INFO_REQ:
+		wma_process_get_peer_info_req(wma_handle,
+					      (tSirIbssGetPeerInfoReqParams *)
+					      msg->bodyptr);
+		qdf_mem_free(msg->bodyptr);
+		break;
+	case WMA_TX_FAIL_MONITOR_IND:
+		wma_process_tx_fail_monitor_ind(wma_handle,
+				(tAniTXFailMonitorInd *) msg->bodyptr);
+		qdf_mem_free(msg->bodyptr);
+		break;
+
+	case WMA_RMC_ENABLE_IND:
+		wma_process_rmc_enable_ind(wma_handle);
+		break;
+	case WMA_RMC_DISABLE_IND:
+		wma_process_rmc_disable_ind(wma_handle);
+		break;
+	case WMA_RMC_ACTION_PERIOD_IND:
+		wma_process_rmc_action_period_ind(wma_handle);
+		break;
 	case WMA_INIT_THERMAL_INFO_CMD:
 		wma_process_init_thermal_info(wma_handle,
 					      (t_thermal_mgmt *) msg->bodyptr);

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio