qcacld-3.0: [11AX] Add support in WMA to receive HE Capabilities

Add support in WMA to receive and store HE capabilities coming
from extended service ready event.

Add support to receive HE capabilities, convert into OTA type of
internal host structure and pass it to the uppper layer as target
config. Add utility funciton for the conversion as well.

Change-Id: If0ceeb3db74be6cf6893b8e74c710863bab8b41b
CRs-Fixed: 1073481
diff --git a/Kbuild b/Kbuild
index 29013de..5d04d9c 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1236,6 +1236,9 @@
 ifeq ($(CONFIG_MPC_UT_FRAMEWORK),y)
 WMA_OBJS +=	$(WMA_SRC_DIR)/wma_utils_ut.o
 endif
+ifeq ($(CONFIG_WLAN_FEATURE_11AX), y)
+WMA_OBJS+=	$(WMA_SRC_DIR)/wma_he.o
+endif
 
 ############## PLD ##########
 PLD_DIR := core/pld
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index e70cc61..af33223 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -6873,4 +6873,31 @@
 	enum wow_interface_pause interface_pause;
 	enum wow_resume_trigger resume_trigger;
 };
+
+#ifdef WLAN_FEATURE_11AX
+/* HE Op Mask is based on the HE Operation definition in the D1.0 spec */
+#define HE_OP_BSS_COLOR_MASK (0x3F << 0)
+#define HE_OP_DEF_PE_DUR_MASK (0x07 << 6)
+#define HE_OP_TWT_REQ_MASK (0x01 << 9)
+#define HE_OP_RTS_THRES_MASK (0x3FF << 10)
+#define HE_OP_PART_BSS_COLOR_MASK (0x01 << 20)
+#define HE_OP_MAXBSSID_IND_MASK (0xFF << 21)
+#define HE_OP_TX_BSSIX_IND_MASK (0x01 << 29)
+#define HE_OP_BSS_COLOR_DIS_MASK (0x01 << 30)
+#define HE_OP_DUAL_BEACON_MASK (0x01 << 31)
+
+#define HE_RU_ALLOC_INDX0_MASK (0x01 << 0)
+#define HE_RU_ALLOC_INDX1_MASK (0x01 << 1)
+#define HE_RU_ALLOC_INDX2_MASK (0x01 << 2)
+#define HE_RU_ALLOC_INDX3_MASK (0x01 << 3)
+
+/* 3 bits for NSS and 4 bits for RU Index */
+#define HE_PPET_NSS_LEN 3
+#define HE_PEPT_RU_IDX_LEN 4
+#define HE_PPET_NSS_RU_LEN (HE_PPET_NSS_LEN + HE_PEPT_RU_IDX_LEN)
+#define HE_PPET_SIZE 3
+#define HE_BYTE_SIZE 8
+
+#endif
+
 #endif /* __SIR_API_H */
diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h
index 88c171e..44e63be 100644
--- a/core/mac/src/include/sir_params.h
+++ b/core/mac/src/include/sir_params.h
@@ -70,8 +70,34 @@
 } ePhyChanBondState;
 
 #define MAX_BONDED_CHANNELS 8
-
-typedef enum {
+/**
+ * enum cap_bitmap - bit field for FW capability
+ * MCC - indicate MCC
+ * P2P - indicate P2P
+ * DOT11AC - indicate 11AC
+ * SLM_SESSIONIZATION - indicate SLM_SESSIONIZATION
+ * DOT11AC_OPMODE - indicate 11ac opmode
+ * SAP32STA - indicate SAP32STA
+ * TDLS - indicate TDLS
+ * P2P_GO_NOA_DECOUPLE_INIT_SCAN - indicate P2P_GO_NOA_DECOUPLE_INIT_SCAN
+ * WLANACTIVE_OFFLOAD - indicate active offload
+ * EXTENDED_SCAN - indicate extended scan
+ * PNO - indicate PNO
+ * NAN - indicate NAN
+ * RTT - indicate RTT
+ * DOT11AX - indicate 11ax
+ * WOW - indicate WOW
+ * WLAN_ROAM_SCAN_OFFLOAD - indicate Roam scan offload
+ * IBSS_HEARTBEAT_OFFLOAD - indicate IBSS HB offload
+ * WLAN_PERIODIC_TX_PTRN - indicate WLAN_PERIODIC_TX_PTRN
+ * ADVANCE_TDLS - indicate advanced TDLS
+ * TDLS_OFF_CHANNEL - indicate TDLS off channel
+ *
+ * This definition is independent of any other modules.
+ * We can use any unused numbers.
+ */
+#define MAX_SUPPORTED_FEATURE 32
+enum cap_bitmap {
 	MCC = 0,
 	P2P = 1,
 	DOT11AC = 2,
@@ -91,6 +117,7 @@
 	NAN = 11,
 #endif
 	RTT = 12,
+	DOT11AX = 13,
 	WOW = 22,
 	WLAN_ROAM_SCAN_OFFLOAD = 23,
 	IBSS_HEARTBEAT_OFFLOAD = 26,
@@ -100,8 +127,8 @@
 	TDLS_OFF_CHANNEL = 30,
 #endif
 
-	/* MAX_FEATURE_SUPPORTED = 128 */
-} placeHolderInCapBitmap;
+	/* MAX_FEATURE_SUPPORTED = 32 */
+};
 
 typedef enum eSriLinkState {
 	eSIR_LINK_IDLE_STATE = 0,
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index 20d4a18..63d4222 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -679,7 +679,7 @@
 bool sme_get_is_ft_feature_enabled(tHalHandle hHal);
 QDF_STATUS sme_update_roam_scan_offload_enabled(tHalHandle hHal,
 		bool nRoamScanOffloadEnabled);
-uint8_t sme_is_feature_supported_by_fw(uint8_t featEnumValue);
+bool sme_is_feature_supported_by_fw(enum cap_bitmap feature);
 #ifdef FEATURE_WLAN_TDLS
 QDF_STATUS sme_send_tdls_link_establish_params(tHalHandle hHal,
 		uint8_t sessionId,
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 68b81b7..1a4c0ac 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -9567,16 +9567,15 @@
 	return pMac->roam.configParam.isFastTransitionEnabled;
 }
 
-/* ---------------------------------------------------------------------------
-    \fn sme_is_feature_supported_by_fw
-    \brief  Check if an feature is enabled by FW
-
-    \param  feattEnumValue - Enumeration value from placeHolderInCapBitmap
-   \- return 1/0 (true/false)
-    -------------------------------------------------------------------------*/
-uint8_t sme_is_feature_supported_by_fw(uint8_t featEnumValue)
+/**
+ * sme_is_feature_supported_by_fw() - check if feature is supported by FW
+ * @feature: enum value of requested feature.
+ *
+ * Retrun: 1 if supported; 0 otherwise
+ */
+bool sme_is_feature_supported_by_fw(enum cap_bitmap feature)
 {
-	return IS_FEATURE_SUPPORTED_BY_FW(featEnumValue);
+	return IS_FEATURE_SUPPORTED_BY_FW(feature);
 }
 
 #ifdef FEATURE_WLAN_TDLS
diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h
index 92e0b6c..4ad2ba6 100644
--- a/core/wma/inc/wma_api.h
+++ b/core/wma/inc/wma_api.h
@@ -153,7 +153,8 @@
 
 void *wma_get_beacon_buffer_by_vdev_id(uint8_t vdev_id, uint32_t *buffer_size);
 
-uint8_t wma_get_fw_wlan_feat_caps(uint8_t featEnumValue);
+bool wma_get_fw_wlan_feat_caps(enum cap_bitmap feature);
+void wma_set_fw_wlan_feat_caps(enum cap_bitmap feature);
 tSirRetStatus wma_post_ctrl_msg(tpAniSirGlobal pMac,
 				struct scheduler_msg *pMsg);
 
diff --git a/core/wma/inc/wma_he.h b/core/wma/inc/wma_he.h
new file mode 100644
index 0000000..01b9baf
--- /dev/null
+++ b/core/wma/inc/wma_he.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * 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.
+ */
+
+#ifndef __WMA_HE_H
+#define __WMA_HE_H
+
+#include "wma.h"
+#include "sir_api.h"
+
+#ifdef WLAN_FEATURE_11AX
+void wma_print_he_cap(tDot11fIEvendor_he_cap *he_cap);
+void wma_print_he_ppet(wmi_ppe_threshold *ppet);
+void wma_print_he_phy_cap(uint32_t *phy_cap);
+void wma_print_he_mac_cap(uint32_t mac_cap);
+void wma_update_target_ext_he_cap(tp_wma_handle wma_handle,
+	struct wma_tgt_cfg *tgt_cfg);
+void wma_he_update_tgt_services(tp_wma_handle wma,
+				struct wma_tgt_services *cfg);
+#else
+static inline void wma_print_he_cap(tDot11fIEvendor_he_cap *he_cap)
+{
+}
+
+static inline void wma_print_he_ppet(wmi_ppe_threshold *ppet)
+{
+}
+
+static inline void wma_print_he_phy_cap(uint32_t *phy_cap)
+{
+}
+
+static inline void wma_print_he_mac_cap(uint32_t mac_cap)
+{
+}
+
+static inline void wma_update_target_ext_he_cap(tp_wma_handle wma_handle,
+						struct wma_tgt_cfg *tgt_cfg)
+{
+}
+
+static inline void wma_he_update_tgt_services(tp_wma_handle wma,
+					      struct wma_tgt_services *cfg)
+{
+	cfg->en_11ax = false;
+	return;
+}
+
+#endif
+
+#endif /* __WMA_HE_H */
diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h
index 5ce91f3..a201535 100644
--- a/core/wma/inc/wma_tgt_cfg.h
+++ b/core/wma/inc/wma_tgt_cfg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -44,6 +44,7 @@
  * @en_tdls_uapsd_buf_sta: enable sta tdls uapsd buf
  * @en_tdls_uapsd_sleep_sta: enable sta tdls uapsd sleep
  * @en_roam_offload: enable roam offload
+ * @en_11ax: enable 11ax
  */
 struct wma_tgt_services {
 	uint32_t sta_power_save;
@@ -67,6 +68,7 @@
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 	bool en_roam_offload;
 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
+	bool en_11ax;
 };
 
 /**
@@ -149,6 +151,7 @@
  * @egap_support: enhanced green ap support
  * @nan_datapath_enabled: nan data path support
  * @bool is_ra_rate_limit_enabled: RA filter support
+ * @he_cap: HE capability received from FW
  */
 struct wma_tgt_cfg {
 	uint32_t target_fw_version;
@@ -178,5 +181,8 @@
 #endif
 	bool sub_20_support;
 	uint16_t wmi_max_len;
+#ifdef WLAN_FEATURE_11AX
+	tDot11fIEvendor_he_cap he_cap;
+#endif
 };
 #endif /* WMA_TGT_CFG_H */
diff --git a/core/wma/src/wma_he.c b/core/wma/src/wma_he.c
new file mode 100644
index 0000000..c3968bc
--- /dev/null
+++ b/core/wma/src/wma_he.c
@@ -0,0 +1,760 @@
+/*
+ * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ *
+ * 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.
+ */
+
+/**
+ * DOC: wma_he.c
+ *
+ * WLAN Host Device Driver 802.11ax - High Efficiency Implementation
+ */
+
+#include "wma_he.h"
+#include "wmi_unified_api.h"
+#include "cds_utils.h"
+
+/**
+ * wma_he_ppet_merge() - Merge PPET8 and PPET16 for a given ru and nss
+ * @host_ppet: pointer to dot11f array
+ * @byte_idx_p: pointer to byte index position where ppet should be added
+ * @used_p: pointer to used position
+ * @ppet: incoming PPET to be merged
+ *
+ * This function does the actual packing of dot11f structure. Split the
+ * incoming PPET(3 bits) to fit into an octet. If there are more than
+ * 3 bits available in a given byte_idx no splitting is required.
+ *
+ * Return: None
+ */
+static void wma_he_ppet_merge(uint8_t *host_ppet, int *byte_idx_p, int *used_p,
+			      uint8_t ppet)
+{
+	int byte_idx = *byte_idx_p, used = *used_p;
+	int lshift, rshift;
+
+	WMA_LOGI(FL("byte_idx=%d used=%d ppet=%04x"), *byte_idx_p, *used_p,
+		    ppet);
+	WMA_LOGI(FL("start host_ppet = %04x"), host_ppet[byte_idx]);
+	if (used <= (HE_BYTE_SIZE - HE_PPET_SIZE)) {
+		/* Enough space to fit the incoming PPET */
+		lshift = used;
+		host_ppet[byte_idx] |= (ppet << lshift);
+		used += HE_PPET_SIZE;
+		if (used == HE_BYTE_SIZE) {
+			WMA_LOGI(FL("end1 host_ppet = %04x"),
+				 host_ppet[byte_idx]);
+			used = 0;
+			byte_idx++;
+		}
+	} else {
+		/* Need to split the PPET */
+		lshift = used;
+		rshift = HE_BYTE_SIZE - used;
+		host_ppet[byte_idx] |= (ppet << lshift);
+		WMA_LOGI(FL("end1 host_ppet = %04x"), host_ppet[byte_idx]);
+		byte_idx++;
+		used = 0;
+		host_ppet[byte_idx] |= (ppet >> rshift);
+		used +=  HE_PPET_SIZE - rshift;
+	}
+
+	WMA_LOGI(FL("end host_ppet = %04x"), host_ppet[byte_idx]);
+	*byte_idx_p = byte_idx;
+	*used_p = used;
+}
+
+/**
+ * wma_he_find_ppet() - Helper function for PPET conversion
+ * @ppet: pointer to fw array
+ * @nss: Number of NSS
+ * @ru: Number of RU
+ * @host_ppet: pointer to dot11f array
+ * @req_byte: Number of bytes in dot11f array
+ *
+ * This function retrieves PPET16/PPET8 pair for combination of NSS/RU
+ * and try to pack them in the OTA type dot11f structure by calling
+ * wma_he_ppet_merge.
+ *
+ * Return: None
+ */
+static void wma_he_find_ppet(uint32_t *ppet, int nss, int ru,
+			     uint8_t *host_ppet, int req_byte)
+{
+	int byte_idx = 0, used, i, j;
+	uint8_t ppet16, ppet8;
+
+	WMA_LOGI(FL("nss: %d ru: %d req_byte: %d\n"), nss, ru, req_byte);
+	/* NSS and RU_IDX are already populated */
+	used = HE_PPET_NSS_RU_LEN;
+
+	for (i = 0; i < nss; i++) {
+		for (j = 1; j <= ru; j++) {
+			ppet16 = WMI_GET_PPET16(ppet, j, i);
+			ppet8 = WMI_GET_PPET8(ppet, j, i);
+			WMA_LOGI(FL("ppet16 (nss:%d ru:%d): %04x"),
+				 i, j, ppet16);
+			WMA_LOGI(FL("ppet8 (nss:%d ru:%d): %04x"),
+				 i, j, ppet8);
+			wma_he_ppet_merge(host_ppet, &byte_idx, &used, ppet16);
+			wma_he_ppet_merge(host_ppet, &byte_idx, &used, ppet8);
+		}
+	}
+
+}
+
+/**
+ * wma_convert_he_ppet() - convert WMI ppet structure to dot11f structure
+ * @he_ppet: pointer to dot11f ppet structure
+ * @ppet: pointer to FW ppet structure
+ *
+ * PPET info coming from FW is stored as described in WMI definition. Convert
+ * that into equivalent dot11f structure.
+ *
+ * Return: None
+ */
+static void wma_convert_he_ppet(tDot11fIEppe_threshold *he_ppet,
+				wmi_ppe_threshold *ppet)
+{
+	int bits, req_byte;
+	uint8_t *host_ppet, ru_count, mask;
+
+	if (!ppet) {
+		WMA_LOGE(FL("PPET is NULL"));
+		he_ppet->present = false;
+		return;
+	}
+
+	he_ppet->present = true;
+	he_ppet->nss_count = ppet->numss_m1;
+	he_ppet->ru_idx_mask = ppet->ru_mask;
+
+	mask = he_ppet->ru_idx_mask;
+	for (ru_count = 0; mask; mask >>= 1)
+		if (mask & 0x01)
+			ru_count++;
+
+	/*
+	 * there will be two PPET for each NSS/RU pair
+	 * PPET8 and PPET16, hence HE_PPET_SIZE * 2 bits for PPET
+	 */
+	bits = HE_PPET_NSS_RU_LEN + ((he_ppet->nss_count + 1) * ru_count) *
+				     (HE_PPET_SIZE * 2);
+
+	req_byte = (bits / HE_BYTE_SIZE) + 1;
+
+	host_ppet = qdf_mem_malloc(sizeof(*host_ppet) * req_byte);
+	if (!host_ppet) {
+		WMA_LOGE(FL("mem alloc failed for host_ppet"));
+		he_ppet->present = false;
+		return;
+	}
+
+	wma_he_find_ppet(ppet->ppet16_ppet8_ru3_ru0, he_ppet->nss_count + 1,
+			 ru_count, host_ppet, req_byte);
+
+	he_ppet->ppet_b1 = (host_ppet[0] << HE_PPET_NSS_RU_LEN);
+
+	/*
+	 * req_byte calculates total bytes, num_ppet stores only the bytes
+	 * going into ppet data member in he_ppet. -1 to exclude the byte
+	 * storing nss/ru and first PPET16.
+	 */
+	he_ppet->num_ppet = req_byte - 1;
+	if (he_ppet->num_ppet > 0)
+		qdf_mem_copy(he_ppet->ppet, &host_ppet[1], he_ppet->num_ppet);
+
+	qdf_mem_free(host_ppet);
+}
+
+/**
+ * wma_convert_he_cap() - convert HE capabilities into dot11f structure
+ * @he_cap: pointer to dot11f structure
+ * @mac_cap: Received HE MAC capability
+ * @phy_cap: Received HE PHY capability
+ * @ppet: Received HE PPE threshold
+ * @mcs: Max MCS supported (Tx/Rx)
+ * @nss: Max NSS supported (Tx/Rx)
+ *
+ * This function converts various HE capability received as part of extended
+ * service ready event into dot11f structure. GET macros are defined at WMI
+ * layer, use them to unpack the incoming FW capability.
+ *
+ * Return: None
+ */
+static void wma_convert_he_cap(tDot11fIEvendor_he_cap *he_cap, uint32_t mac_cap,
+			       uint32_t *phy_cap, wmi_ppe_threshold *ppet,
+			       uint8_t mcs, uint8_t nss)
+{
+	he_cap->present = true;
+
+	/* HE MAC capabilities */
+	he_cap->htc_he = WMI_HECAP_MAC_HECTRL_GET(mac_cap);
+	he_cap->twt_request = WMI_HECAP_MAC_TWTREQ_GET(mac_cap);
+	he_cap->twt_responder = WMI_HECAP_MAC_TWTRSP_GET(mac_cap);
+	he_cap->fragmentation =  WMI_HECAP_MAC_HEFRAG_GET(mac_cap);
+	he_cap->max_num_frag_msdu = WMI_HECAP_MAC_MAXFRAGMSDU_GET(mac_cap);
+	he_cap->min_frag_size = WMI_HECAP_MAC_MINFRAGSZ_GET(mac_cap);
+	he_cap->trigger_frm_mac_pad = WMI_HECAP_MAC_TRIGPADDUR_GET(mac_cap);
+	he_cap->multi_tid_aggr = WMI_HECAP_MAC_ACKMTIDAMPDU_GET(mac_cap);
+	he_cap->he_link_adaptation = WMI_HECAP_MAC_HELKAD_GET(mac_cap);
+	he_cap->all_ack = WMI_HECAP_MAC_AACK_GET(mac_cap);
+	he_cap->ul_mu_rsp_sched = WMI_HECAP_MAC_ULMURSP_GET(mac_cap);
+	he_cap->a_bsr = WMI_HECAP_MAC_BSR_GET(mac_cap);
+	he_cap->broadcast_twt = WMI_HECAP_MAC_BCSTTWT_GET(mac_cap);
+	he_cap->ba_32bit_bitmap = WMI_HECAP_MAC_32BITBA_GET(mac_cap);
+	he_cap->mu_cascade = WMI_HECAP_MAC_MUCASCADE_GET(mac_cap);
+	he_cap->ack_enabled_multitid = WMI_HECAP_MAC_ACKMTIDAMPDU_GET(mac_cap);
+	he_cap->dl_mu_ba = WMI_HECAP_MAC_GROUPMSTABA_GET(mac_cap);
+	he_cap->omi_a_ctrl = WMI_HECAP_MAC_OMI_GET(mac_cap);
+	he_cap->ofdma_ra = WMI_HECAP_MAC_OFDMARA_GET(mac_cap);
+	he_cap->max_ampdu_len = WMI_HECAP_MAC_MAXAMPDULEN_EXP_GET(mac_cap);
+	he_cap->amsdu_frag = WMI_HECAP_MAC_AMSDUFRAG_GET(mac_cap);
+	he_cap->flex_twt_sched = WMI_HECAP_MAC_FLEXTWT_GET(mac_cap);
+	he_cap->rx_ctrl_frame = WMI_HECAP_MAC_MBSS_GET(mac_cap);
+	he_cap->bsrp_ampdu_aggr = WMI_HECAP_MAC_BSRPAMPDU_GET(mac_cap);
+	he_cap->qtp = WMI_HECAP_MAC_QTP_GET(mac_cap);
+	he_cap->a_bqr = WMI_HECAP_MAC_ABQR_GET(mac_cap);
+
+	/* HE PHY capabilities */
+	he_cap->dual_band = WMI_HECAP_PHY_DB_GET(phy_cap);
+	he_cap->chan_width = WMI_HECAP_PHY_CBW_GET(phy_cap);
+	he_cap->rx_pream_puncturing = WMI_HECAP_PHY_PREAMBLEPUNCRX_GET(phy_cap);
+	he_cap->device_class = WMI_HECAP_PHY_COD_GET(phy_cap);
+	he_cap->ldpc_coding = WMI_HECAP_PHY_LDPC_GET(phy_cap);
+	he_cap->he_ltf_gi_ppdu = WMI_HECAP_PHY_LTFGIFORHE_GET(phy_cap);
+	he_cap->he_ltf_gi_ndp = WMI_HECAP_PHY_LTFGIFORNDP_GET(phy_cap);
+	he_cap->stbc = (WMI_HECAP_PHY_RXSTBC_GET(phy_cap) << 1) |
+			WMI_HECAP_PHY_TXSTBC_GET(phy_cap);
+	he_cap->doppler = (WMI_HECAP_PHY_RXDOPPLER_GET(phy_cap) << 1) |
+				WMI_HECAP_PHY_TXDOPPLER_GET(phy_cap);
+	he_cap->ul_mu = WMI_HECAP_PHY_UL_MU_MIMO_GET(phy_cap);
+	he_cap->dcm_enc_tx = WMI_HECAP_PHY_DCMTX_GET(phy_cap);
+	he_cap->dcm_enc_rx = WMI_HECAP_PHY_DCMRX_GET(phy_cap);
+	he_cap->ul_he_mu = WMI_HECAP_PHY_ULHEMU_GET(phy_cap);
+	he_cap->su_beamformer = WMI_HECAP_PHY_SUBFMR_GET(phy_cap);
+	he_cap->su_beamformee = WMI_HECAP_PHY_SUBFME_GET(phy_cap);
+	he_cap->mu_beamformer = WMI_HECAP_PHY_MUBFMR_GET(phy_cap);
+	he_cap->bfee_sts_lt_80 = WMI_HECAP_PHY_SUBFMESTS_GET(phy_cap);
+	he_cap->nsts_tol_lt_80 = WMI_HECAP_PHY_NSTSLT80MHZ_GET(phy_cap);
+	he_cap->bfee_sta_gt_80 = WMI_HECAP_PHY_BFMESTSGT80MHZ_GET(phy_cap);
+	he_cap->nsts_tot_gt_80 = WMI_HECAP_PHY_NSTSGT80MHZ_GET(phy_cap);
+	he_cap->num_sounding_lt_80 = WMI_HECAP_PHY_NUMSOUNDLT80MHZ_GET(phy_cap);
+	he_cap->num_sounding_gt_80 = WMI_HECAP_PHY_NUMSOUNDGT80MHZ_GET(phy_cap);
+	he_cap->su_feedback_tone16 =
+		WMI_HECAP_PHY_NG16SUFEEDBACKLT80_GET(phy_cap);
+	he_cap->mu_feedback_tone16 =
+		WMI_HECAP_PHY_NG16MUFEEDBACKGT80_GET(phy_cap);
+	he_cap->codebook_su = WMI_HECAP_PHY_CODBK42SU_GET(phy_cap);
+	he_cap->codebook_mu = WMI_HECAP_PHY_CODBK75MU_GET(phy_cap);
+	he_cap->beamforming_feedback =
+		WMI_HECAP_PHY_BFFEEDBACKTRIG_GET(phy_cap);
+	he_cap->he_er_su_ppdu = WMI_HECAP_PHY_HEERSU_GET(phy_cap);
+	he_cap->dl_mu_mimo_part_bw =
+		WMI_HECAP_PHY_DLMUMIMOPARTIALBW_GET(phy_cap);
+	he_cap->ppet_present = WMI_HECAP_PHY_PETHRESPRESENT_GET(phy_cap);
+	he_cap->srp = WMI_HECAP_PHY_SRPSPRESENT_GET(phy_cap);
+	he_cap->power_boost = WMI_HECAP_PHY_PWRBOOSTAR_GET(phy_cap);
+	he_cap->he_ltf_gi_4x = WMI_HECAP_PHY_4XLTFAND800NSECSGI_GET(phy_cap);
+
+	he_cap->nss_supported = nss - 1;
+	he_cap->mcs_supported = mcs;
+	/* For Draft 1.0, following fields will be zero */
+	he_cap->tx_bw_bitmap = 0;
+	he_cap->rx_bw_bitmap = 0;
+
+	wma_convert_he_ppet(&he_cap->ppe_threshold, ppet);
+}
+
+/**
+ * wma_derive_ext_he_cap() - Derive HE caps based on given value
+ * @wma_handle: pointer to wma_handle
+ * @he_cap: pointer to given HE caps to be filled
+ * @new_he_cap: new HE cap info provided.
+ *
+ * This function takes the value provided in and combines it wht the incoming
+ * HE capability. After decoding, what ever value it gets,
+ * it takes the union(max) or intersection(min) with previously derived values.
+ * Currently, intersection(min) is taken for all the capabilities.
+ *
+ * Return: none
+ */
+static void wma_derive_ext_he_cap(t_wma_handle *wma_handle,
+		tDot11fIEvendor_he_cap *he_cap, tDot11fIEvendor_he_cap *new_cap)
+{
+	if (!he_cap->present) {
+		/* First time update, copy the capability as is */
+		qdf_mem_copy(he_cap, new_cap, sizeof(*he_cap));
+		he_cap->present = true;
+	} else {
+		/* Take union(max) or intersection(min) of the capabilities */
+		he_cap->htc_he = QDF_MIN(he_cap->htc_he, new_cap->htc_he);
+		he_cap->twt_request = QDF_MIN(he_cap->twt_request,
+					new_cap->twt_request);
+		he_cap->twt_responder = QDF_MIN(he_cap->twt_responder,
+						new_cap->twt_responder);
+		he_cap->fragmentation = QDF_MIN(he_cap->fragmentation,
+						new_cap->fragmentation);
+		he_cap->max_num_frag_msdu = QDF_MIN(he_cap->max_num_frag_msdu,
+						new_cap->max_num_frag_msdu);
+		he_cap->min_frag_size = QDF_MIN(he_cap->min_frag_size,
+						new_cap->min_frag_size);
+		he_cap->trigger_frm_mac_pad =
+			QDF_MIN(he_cap->trigger_frm_mac_pad,
+				new_cap->trigger_frm_mac_pad);
+		he_cap->multi_tid_aggr = QDF_MIN(he_cap->multi_tid_aggr,
+						new_cap->multi_tid_aggr);
+		he_cap->he_link_adaptation = QDF_MIN(he_cap->he_link_adaptation,
+						new_cap->he_link_adaptation);
+		he_cap->all_ack = QDF_MIN(he_cap->all_ack,
+						new_cap->all_ack);
+		he_cap->ul_mu_rsp_sched = QDF_MIN(he_cap->ul_mu_rsp_sched,
+						new_cap->ul_mu_rsp_sched);
+		he_cap->a_bsr = QDF_MIN(he_cap->a_bsr,
+						new_cap->a_bsr);
+		he_cap->broadcast_twt = QDF_MIN(he_cap->broadcast_twt,
+						new_cap->broadcast_twt);
+		he_cap->ba_32bit_bitmap = QDF_MIN(he_cap->ba_32bit_bitmap,
+						new_cap->ba_32bit_bitmap);
+		he_cap->mu_cascade = QDF_MIN(he_cap->mu_cascade,
+						new_cap->mu_cascade);
+		he_cap->ack_enabled_multitid =
+			QDF_MIN(he_cap->ack_enabled_multitid,
+				new_cap->ack_enabled_multitid);
+		he_cap->dl_mu_ba = QDF_MIN(he_cap->dl_mu_ba,
+						new_cap->dl_mu_ba);
+		he_cap->omi_a_ctrl = QDF_MIN(he_cap->omi_a_ctrl,
+						new_cap->omi_a_ctrl);
+		he_cap->ofdma_ra = QDF_MIN(he_cap->ofdma_ra,
+						new_cap->ofdma_ra);
+		he_cap->max_ampdu_len = QDF_MIN(he_cap->max_ampdu_len,
+						new_cap->max_ampdu_len);
+		he_cap->amsdu_frag = QDF_MIN(he_cap->amsdu_frag,
+						new_cap->amsdu_frag);
+		he_cap->flex_twt_sched = QDF_MIN(he_cap->flex_twt_sched,
+						new_cap->flex_twt_sched);
+		he_cap->rx_ctrl_frame = QDF_MIN(he_cap->rx_ctrl_frame,
+						new_cap->rx_ctrl_frame);
+		he_cap->bsrp_ampdu_aggr = QDF_MIN(he_cap->bsrp_ampdu_aggr,
+						new_cap->bsrp_ampdu_aggr);
+		he_cap->qtp = QDF_MIN(he_cap->qtp, new_cap->qtp);
+		he_cap->a_bqr = QDF_MIN(he_cap->a_bqr, new_cap->a_bqr);
+
+		/* Remaining capabilities are not captured here.
+		 * Intersect only the required capability
+		 */
+	}
+}
+
+/**
+ * @wma_print_he_cap() - Print HE capabilities
+ * @he_cap: pointer to HE Capability
+ *
+ * Received HE capabilities are converted into dot11f structure.
+ * This function will print all the HE capabilities as stored
+ * in the dot11f structure.
+ *
+ * Return: None
+ */
+void wma_print_he_cap(tDot11fIEvendor_he_cap *he_cap)
+{
+	if (!he_cap->present) {
+		WMA_LOGI(FL("HE Capabilities not present"));
+		return;
+	}
+
+	WMA_LOGI(FL("HE Capabilities:"));
+
+	/* HE MAC capabilities */
+	WMA_LOGI("\tHTC-HE conrol: 0x%01x", he_cap->htc_he);
+	WMA_LOGI("\tTWT Requestor support: 0x%01x", he_cap->twt_request);
+	WMA_LOGI("\tTWT Responder support: 0x%01x", he_cap->twt_responder);
+	WMA_LOGI("\tFragmentation support: 0x%02x", he_cap->fragmentation);
+	WMA_LOGI("\tMax no.of frag MSDUs: 0x%03x", he_cap->max_num_frag_msdu);
+	WMA_LOGI("\tMin. frag size: 0x%02x", he_cap->min_frag_size);
+	WMA_LOGI("\tTrigger MAC pad duration: 0x%02x",
+			he_cap->trigger_frm_mac_pad);
+	WMA_LOGI("\tMulti-TID aggr support: 0x%03x", he_cap->multi_tid_aggr);
+	WMA_LOGI("\tLink adaptation: 0x%02x", he_cap->he_link_adaptation);
+	WMA_LOGI("\tAll ACK support: 0x%01x", he_cap->all_ack);
+	WMA_LOGI("\tUL MU resp. scheduling: 0x%01x", he_cap->ul_mu_rsp_sched);
+	WMA_LOGI("\tA-Buff status report: 0x%01x", he_cap->a_bsr);
+	WMA_LOGI("\tBroadcast TWT support: 0x%01x", he_cap->broadcast_twt);
+	WMA_LOGI("\t32bit BA bitmap support: 0x%01x", he_cap->ba_32bit_bitmap);
+	WMA_LOGI("\tMU Cascading support: 0x%01x", he_cap->mu_cascade);
+	WMA_LOGI("\tACK enabled Multi-TID: 0x%01x",
+			he_cap->ack_enabled_multitid);
+	WMA_LOGI("\tMulti-STA BA in DL MU: 0x%01x", he_cap->dl_mu_ba);
+	WMA_LOGI("\tOMI A-Control support: 0x%01x", he_cap->omi_a_ctrl);
+	WMA_LOGI("\tOFDMA RA support: 0x%01x", he_cap->ofdma_ra);
+	WMA_LOGI("\tMax A-MPDU Length: 0x%02x", he_cap->max_ampdu_len);
+	WMA_LOGI("\tA-MSDU Fragmentation: 0x%01x", he_cap->amsdu_frag);
+	WMA_LOGI("\tFlex. TWT sched support: 0x%01x", he_cap->flex_twt_sched);
+	WMA_LOGI("\tRx Ctrl frame to MBSS: 0x%01x", he_cap->rx_ctrl_frame);
+	WMA_LOGI("\tBSRP A-MPDU Aggregation: 0x%01x", he_cap->bsrp_ampdu_aggr);
+	WMA_LOGI("\tQuite Time Period support: 0x%01x", he_cap->qtp);
+	WMA_LOGI("\tA-BQR support: 0x%01x", he_cap->a_bqr);
+
+	/* HE PHY capabilities */
+	WMA_LOGI("\tDual band support: 0x%01x", he_cap->dual_band);
+	WMA_LOGI("\tChannel width support: 0x%07x", he_cap->chan_width);
+	WMA_LOGI("\tPreamble puncturing Rx: 0x%04x",
+			he_cap->rx_pream_puncturing);
+	WMA_LOGI("\tClass of device: 0x%01x", he_cap->device_class);
+	WMA_LOGI("\tLDPC coding support: 0x%01x", he_cap->ldpc_coding);
+	WMA_LOGI("\tLTF and GI for HE PPDUs: 0x%02x", he_cap->he_ltf_gi_ppdu);
+	WMA_LOGI("\tLTF and GI for NDP: 0x%02x", he_cap->he_ltf_gi_ndp);
+	WMA_LOGI("\tSTBC Tx & Rx support: 0x%02x", he_cap->stbc);
+	WMA_LOGI("\tDoppler support: 0x%02x", he_cap->doppler);
+	WMA_LOGI("\tUL MU: 0x%02x", he_cap->ul_mu);
+	WMA_LOGI("\tDCM encoding Tx: 0x%03x", he_cap->dcm_enc_tx);
+	WMA_LOGI("\tDCM encoding Tx: 0x%03x", he_cap->dcm_enc_rx);
+	WMA_LOGI("\tHE MU PPDU payload support: 0x%01x", he_cap->ul_he_mu);
+	WMA_LOGI("\tSU Beamformer: 0x%01x", he_cap->su_beamformer);
+	WMA_LOGI("\tSU Beamformee: 0x%01x", he_cap->su_beamformee);
+	WMA_LOGI("\tMU Beamformer: 0x%01x", he_cap->mu_beamformer);
+	WMA_LOGI("\tBeamformee STS for <= 80Mhz: 0x%03x",
+			he_cap->bfee_sts_lt_80);
+	WMA_LOGI("\tNSTS total for <= 80Mhz: 0x%03x", he_cap->nsts_tol_lt_80);
+	WMA_LOGI("\tBeamformee STS for > 80Mhz: 0x%03x",
+			he_cap->bfee_sta_gt_80);
+	WMA_LOGI("\tNSTS total for > 80Mhz: 0x%03x", he_cap->nsts_tot_gt_80);
+	WMA_LOGI("\tNo. of sounding dim <= 80Mhz: 0x%03x",
+			he_cap->num_sounding_lt_80);
+	WMA_LOGI("\tNo. of sounding dim > 80Mhz: 0x%03x",
+			he_cap->num_sounding_gt_80);
+	WMA_LOGI("\tNg=16 for SU feedback support: 0x%01x",
+			he_cap->su_feedback_tone16);
+	WMA_LOGI("\tNg=16 for MU feedback support: 0x%01x",
+			he_cap->mu_feedback_tone16);
+	WMA_LOGI("\tCodebook size for SU: 0x%01x", he_cap->codebook_su);
+	WMA_LOGI("\tCodebook size for MU: 0x%01x ", he_cap->codebook_mu);
+	WMA_LOGI("\tBeamforming trigger w/ Trigger: 0x%01x",
+			he_cap->beamforming_feedback);
+	WMA_LOGI("\tHE ER SU PPDU payload: 0x%01x", he_cap->he_er_su_ppdu);
+	WMA_LOGI("\tDL MUMIMO on partial BW: 0x%01x",
+			he_cap->dl_mu_mimo_part_bw);
+	WMA_LOGI("\tPPET present: 0x%01x", he_cap->ppet_present);
+	WMA_LOGI("\tSRP based SR-support: 0x%01x", he_cap->srp);
+	WMA_LOGI("\tPower boost factor: 0x%01x", he_cap->power_boost);
+	WMA_LOGI("\t4x HE LTF support: 0x%01x", he_cap->he_ltf_gi_4x);
+
+	WMA_LOGI("\tHighest NSS supported: 0x%03x", he_cap->nss_supported);
+	WMA_LOGI("\tHighest MCS supported: 0x%03x", he_cap->mcs_supported);
+	WMA_LOGI("\tTX BW bitmap: 0x%05x", he_cap->tx_bw_bitmap);
+	WMA_LOGI("\tRX BW bitmap: 0x%05x ", he_cap->rx_bw_bitmap);
+
+	/* HE PPET */
+	WMA_LOGI("\tNSS: %d", he_cap->ppe_threshold.nss_count + 1);
+	WMA_LOGI("\tRU Index mask: 0x%04x", he_cap->ppe_threshold.ru_idx_mask);
+	WMA_LOGI("\tnum_ppet: %d", he_cap->ppe_threshold.num_ppet);
+	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
+		he_cap->ppe_threshold.ppet, he_cap->ppe_threshold.num_ppet);
+}
+
+/**
+ * wma_print_he_ppet() - Prints HE PPE Threshold
+ * @ppet: PPE Threshold
+ *
+ * This function prints HE PPE Threshold as received from FW.
+ * Refer to the definition of wmi_ppe_threshold to understand
+ * how PPE thresholds are packed by FW for a given NSS and RU.
+ *
+ * Return: none
+ */
+void wma_print_he_ppet(wmi_ppe_threshold *ppet)
+{
+	int numss, ru_count, ru_mask, i, j;
+
+	if (!ppet) {
+		WMA_LOGI(FL("PPET is NULL"));
+		return;
+	}
+
+	numss = ppet->numss_m1 + 1;
+	ru_mask = ppet->ru_mask;
+
+	WMA_LOGI(FL("HE PPET: ru_idx_mask: %04x"), ru_mask);
+	for (ru_count = 0; ru_mask; ru_mask >>= 1)
+		if (ru_mask & 0x1)
+			ru_count++;
+
+	if (ru_count > 0) {
+		WMA_LOGI(FL("PPET has following RU INDEX,"));
+		if (ppet->ru_mask & HE_RU_ALLOC_INDX0_MASK)
+			WMA_LOGI("\tRU ALLOCATION INDEX 0");
+		if (ppet->ru_mask & HE_RU_ALLOC_INDX1_MASK)
+			WMA_LOGI("\tRU ALLOCATION INDEX 1");
+		if (ppet->ru_mask & HE_RU_ALLOC_INDX2_MASK)
+			WMA_LOGI("\tRU ALLOCATION INDEX 2");
+		if (ppet->ru_mask & HE_RU_ALLOC_INDX3_MASK)
+			WMA_LOGI("\tRU ALLOCATION INDEX 3");
+	}
+
+	WMA_LOGI(FL("HE PPET: nss: %d, ru_count: %d"), numss, ru_count);
+
+	for (i = 0; i < numss; i++) {
+		WMA_LOGI("PPET for NSS[%d]", i);
+		for (j = 1; j <= ru_count; j++) {
+			WMA_LOGI("\tNSS[%d],RU[%d]: PPET16: %02x PPET8: %02x",
+			    i, j,
+			    WMI_GET_PPET16(ppet->ppet16_ppet8_ru3_ru0, j, i),
+			    WMI_GET_PPET8(ppet->ppet16_ppet8_ru3_ru0, j, i));
+		}
+	}
+
+}
+
+/**
+ * wma_print_he_phy_cap() - Print HE PHY Capability
+ * @phy_cap: pointer to PHY Capability
+ *
+ * This function prints HE PHY Capability received from FW.
+ *
+ * Return: none
+ */
+void wma_print_he_phy_cap(uint32_t *phy_cap)
+{
+	WMA_LOGI(FL("HE PHY Capabilities:"));
+
+	WMA_LOGI("\tDual band support: 0x%01x",
+		WMI_HECAP_PHY_DB_GET(phy_cap));
+	WMA_LOGI("\tChannel width support: 0x%07x",
+		WMI_HECAP_PHY_CBW_GET(phy_cap));
+	WMA_LOGI("\tPreamble puncturing Rx: 0x%04x",
+		WMI_HECAP_PHY_PREAMBLEPUNCRX_GET(phy_cap));
+	WMA_LOGI("\tClass of device: 0x%01x", WMI_HECAP_PHY_COD_GET(phy_cap));
+	WMA_LOGI("\tLDPC coding support: 0x%01x",
+		WMI_HECAP_PHY_LDPC_GET(phy_cap));
+	WMA_LOGI("\tLTF and GI for HE PPDUs: 0x%02x",
+		WMI_HECAP_PHY_LTFGIFORHE_GET(phy_cap));
+	WMA_LOGI("\tLTF and GI for NDP: 0x%02x",
+		WMI_HECAP_PHY_LTFGIFORNDP_GET(phy_cap));
+	WMA_LOGI("\tSTBC Tx & Rx support: 0x%02x",
+			(WMI_HECAP_PHY_RXSTBC_GET(phy_cap) << 1) |
+			 WMI_HECAP_PHY_TXSTBC_GET(phy_cap));
+	WMA_LOGI("\tDoppler support: 0x%02x",
+			(WMI_HECAP_PHY_RXDOPPLER_GET(phy_cap) << 1) |
+			 WMI_HECAP_PHY_TXDOPPLER_GET(phy_cap));
+	WMA_LOGI("\tUL MU: 0x%02x", WMI_HECAP_PHY_UL_MU_MIMO_GET(phy_cap));
+	WMA_LOGI("\tDCM encoding Tx: 0x%03x", WMI_HECAP_PHY_DCMTX_GET(phy_cap));
+	WMA_LOGI("\tDCM encoding Tx: 0x%03x", WMI_HECAP_PHY_DCMRX_GET(phy_cap));
+	WMA_LOGI("\tHE MU PPDU payload support: 0x%01x",
+		WMI_HECAP_PHY_ULHEMU_GET(phy_cap));
+	WMA_LOGI("\tSU Beamformer: 0x%01x", WMI_HECAP_PHY_SUBFMR_GET(phy_cap));
+	WMA_LOGI("\tSU Beamformee: 0x%01x", WMI_HECAP_PHY_SUBFME_GET(phy_cap));
+	WMA_LOGI("\tMU Beamformer: 0x%01x", WMI_HECAP_PHY_MUBFMR_GET(phy_cap));
+	WMA_LOGI("\tBeamformee STS for <= 80Mhz: 0x%03x",
+			WMI_HECAP_PHY_SUBFMESTS_GET(phy_cap));
+	WMA_LOGI("\tNSTS total for <= 80Mhz: 0x%03x",
+		WMI_HECAP_PHY_NSTSLT80MHZ_GET(phy_cap));
+	WMA_LOGI("\tBeamformee STS for > 80Mhz: 0x%03x",
+		WMI_HECAP_PHY_BFMESTSGT80MHZ_GET(phy_cap));
+	WMA_LOGI("\tNSTS total for > 80Mhz: 0x%03x",
+		WMI_HECAP_PHY_NSTSGT80MHZ_GET(phy_cap));
+	WMA_LOGI("\tNo. of sounding dim <= 80Mhz: 0x%03x",
+		WMI_HECAP_PHY_NUMSOUNDLT80MHZ_GET(phy_cap));
+	WMA_LOGI("\tNo. of sounding dim > 80Mhz: 0x%03x",
+		WMI_HECAP_PHY_NUMSOUNDGT80MHZ_GET(phy_cap));
+	WMA_LOGI("\tNg=16 for SU feedback support: 0x%01x",
+		WMI_HECAP_PHY_NG16SUFEEDBACKLT80_GET(phy_cap));
+	WMA_LOGI("\tNg=16 for MU feedback support: 0x%01x",
+		WMI_HECAP_PHY_NG16MUFEEDBACKGT80_GET(phy_cap));
+	WMA_LOGI("\tCodebook size for SU: 0x%01x",
+		WMI_HECAP_PHY_CODBK42SU_GET(phy_cap));
+	WMA_LOGI("\tCodebook size for MU: 0x%01x ",
+		WMI_HECAP_PHY_CODBK75MU_GET(phy_cap));
+	WMA_LOGI("\tBeamforming trigger w/ Trigger: 0x%01x",
+		WMI_HECAP_PHY_BFFEEDBACKTRIG_GET(phy_cap));
+	WMA_LOGI("\tHE ER SU PPDU payload: 0x%01x",
+		WMI_HECAP_PHY_HEERSU_GET(phy_cap));
+	WMA_LOGI("\tDL MUMIMO on partial BW: 0x%01x",
+		WMI_HECAP_PHY_DLMUMIMOPARTIALBW_GET(phy_cap));
+	WMA_LOGI("\tPPET present: 0x%01x", WMI_HECAP_PHY_PADDING_GET(phy_cap));
+	WMA_LOGI("\tSRP based SR-support: 0x%01x",
+		WMI_HECAP_PHY_SRPSPRESENT_GET(phy_cap));
+	WMA_LOGI("\tPower boost factor: 0x%01x",
+		WMI_HECAP_PHY_PWRBOOSTAR_GET(phy_cap));
+	WMA_LOGI("\t4x HE LTF support: 0x%01x",
+		WMI_HECAP_PHY_4XLTFAND800NSECSGI_GET(phy_cap));
+}
+
+/**
+ * wma_print_he_mac_cap() - Print HE MAC Capability
+ * @mac_cap: MAC Capability
+ *
+ * This function prints HE MAC Capability received from FW.
+ *
+ * Return: none
+ */
+void wma_print_he_mac_cap(uint32_t mac_cap)
+{
+	WMA_LOGI(FL("HE MAC Capabilities:"));
+
+	WMA_LOGI("\tHTC-HE conrol: 0x%01x", WMI_HECAP_MAC_HECTRL_GET(mac_cap));
+	WMA_LOGI("\tTWT Requestor support: 0x%01x",
+			WMI_HECAP_MAC_TWTREQ_GET(mac_cap));
+	WMA_LOGI("\tTWT Responder support: 0x%01x",
+			WMI_HECAP_MAC_TWTRSP_GET(mac_cap));
+	WMA_LOGI("\tFragmentation support: 0x%02x",
+			WMI_HECAP_MAC_HEFRAG_GET(mac_cap));
+	WMA_LOGI("\tMax no.of frag MSDUs: 0x%03x",
+			WMI_HECAP_MAC_MAXFRAGMSDU_GET(mac_cap));
+	WMA_LOGI("\tMin. frag size: 0x%02x",
+			WMI_HECAP_MAC_MINFRAGSZ_GET(mac_cap));
+	WMA_LOGI("\tTrigger MAC pad duration: 0x%02x",
+			WMI_HECAP_MAC_TRIGPADDUR_GET(mac_cap));
+	WMA_LOGI("\tMulti-TID aggr support: 0x%03x",
+			WMI_HECAP_MAC_ACKMTIDAMPDU_GET(mac_cap));
+	WMA_LOGI("\tLink adaptation: 0x%02x",
+			WMI_HECAP_MAC_HELKAD_GET(mac_cap));
+	WMA_LOGI("\tAll ACK support: 0x%01x",
+			WMI_HECAP_MAC_AACK_GET(mac_cap));
+	WMA_LOGI("\tUL MU resp. scheduling: 0x%01x",
+			WMI_HECAP_MAC_ULMURSP_GET(mac_cap));
+	WMA_LOGI("\tA-Buff status report: 0x%01x",
+			WMI_HECAP_MAC_BSR_GET(mac_cap));
+	WMA_LOGI("\tBroadcast TWT support: 0x%01x",
+			WMI_HECAP_MAC_BCSTTWT_GET(mac_cap));
+	WMA_LOGI("\t32bit BA bitmap support: 0x%01x",
+			WMI_HECAP_MAC_32BITBA_GET(mac_cap));
+	WMA_LOGI("\tMU Cascading support: 0x%01x",
+			WMI_HECAP_MAC_MUCASCADE_GET(mac_cap));
+	WMA_LOGI("\tACK enabled Multi-TID: 0x%01x",
+			WMI_HECAP_MAC_ACKMTIDAMPDU_GET(mac_cap));
+	WMA_LOGI("\tMulti-STA BA in DL MU: 0x%01x",
+			WMI_HECAP_MAC_GROUPMSTABA_GET(mac_cap));
+	WMA_LOGI("\tOMI A-Control support: 0x%01x",
+			WMI_HECAP_MAC_OMI_GET(mac_cap));
+	WMA_LOGI("\tOFDMA RA support: 0x%01x",
+			WMI_HECAP_MAC_OFDMARA_GET(mac_cap));
+	WMA_LOGI("\tMax A-MPDU Length: 0x%02x",
+		WMI_HECAP_MAC_MAXAMPDULEN_EXP_GET(mac_cap));
+	WMA_LOGI("\tA-MSDU Fragmentation: 0x%01x",
+		WMI_HECAP_MAC_AMSDUFRAG_GET(mac_cap));
+	WMA_LOGI("\tFlex. TWT sched support: 0x%01x",
+		WMI_HECAP_MAC_FLEXTWT_GET(mac_cap));
+	WMA_LOGI("\tRx Ctrl frame to MBSS: 0x%01x",
+			WMI_HECAP_MAC_MBSS_GET(mac_cap));
+	WMA_LOGI("\tBSRP A-MPDU Aggregation: 0x%01x",
+		WMI_HECAP_MAC_BSRPAMPDU_GET(mac_cap));
+	WMA_LOGI("\tQuite Time Period support: 0x%01x",
+		WMI_HECAP_MAC_QTP_GET(mac_cap));
+	WMA_LOGI("\tA-BQR support: 0x%01x", WMI_HECAP_MAC_ABQR_GET(mac_cap));
+}
+
+/**
+ * wma_update_target_ext_he_cap() - Update HE caps with given extended cap
+ * @wma_handle: pointer to wma_handle
+ * @tgt_cfg: Target config
+ *
+ * This function loop through each hardware mode and for each hardware mode
+ * again it loop through each MAC/PHY and pull the caps 2G and 5G specific
+ * HE caps and derives the final cap.
+ *
+ * Return: none
+ *
+ */
+void wma_update_target_ext_he_cap(tp_wma_handle wma_handle,
+				  struct wma_tgt_cfg *tgt_cfg)
+{
+	tDot11fIEvendor_he_cap *he_cap = &tgt_cfg->he_cap;
+	int i, j = 0, max_mac;
+	uint32_t he_mac;
+	uint32_t he_phy[WMI_MAX_HECAP_PHY_SIZE];
+	wmi_ppe_threshold he_ppet;
+	struct extended_caps *phy_caps;
+	WMI_MAC_PHY_CAPABILITIES *mac_cap;
+	tDot11fIEvendor_he_cap he_cap_mac0 = {0}, he_cap_mac1 = {0};
+	tDot11fIEvendor_he_cap tmp_he_cap = {0};
+	uint8_t mcs, nss;
+
+	if (!wma_handle ||
+		(0 == wma_handle->phy_caps.num_hw_modes.num_hw_modes)) {
+		WMA_LOGE(FL("No extended HE cap for current SOC"));
+		he_cap->present = false;
+		return;
+	}
+
+	if (!tgt_cfg->services.en_11ax) {
+		WMA_LOGI(FL("Target does not support 11AX"));
+		he_cap->present = false;
+		return;
+	}
+
+	phy_caps = &wma_handle->phy_caps;
+	for (i = 0; i < phy_caps->num_hw_modes.num_hw_modes; i++) {
+		if (phy_caps->each_hw_mode_cap[i].phy_id_map == PHY1_PHY2)
+			max_mac = j + 2;
+		else
+			max_mac = j + 1;
+		for ( ; j < max_mac; j++) {
+			mac_cap = &phy_caps->each_phy_cap_per_hwmode[j];
+			he_mac = mac_cap->he_cap_info_2G;
+			qdf_mem_copy(he_phy, mac_cap->he_cap_phy_info_2G,
+				     WMI_MAX_HECAP_PHY_SIZE * 4);
+			he_ppet = mac_cap->he_ppet2G;
+			mcs = mac_cap->he_supp_mcs_2G;
+			nss = (mac_cap->tx_chain_mask_2G >
+				mac_cap->rx_chain_mask_2G) ?
+					mac_cap->tx_chain_mask_2G :
+					mac_cap->rx_chain_mask_2G;
+			wma_convert_he_cap(&he_cap_mac0, he_mac, he_phy,
+					   &he_ppet, mcs, nss);
+			if (he_cap_mac0.present)
+				wma_derive_ext_he_cap(wma_handle, &tmp_he_cap,
+					&he_cap_mac0);
+
+			he_mac = mac_cap->he_cap_info_5G;
+			qdf_mem_copy(he_phy, mac_cap->he_cap_phy_info_5G,
+				     WMI_MAX_HECAP_PHY_SIZE * 4);
+			he_ppet = mac_cap->he_ppet5G;
+			mcs = mac_cap->he_supp_mcs_5G;
+			nss = (mac_cap->tx_chain_mask_5G >
+				mac_cap->rx_chain_mask_5G) ?
+					mac_cap->tx_chain_mask_5G :
+					mac_cap->rx_chain_mask_5G;
+			wma_convert_he_cap(&he_cap_mac1, he_mac, he_phy,
+					   &he_ppet, mcs, nss);
+			if (he_cap_mac1.present)
+				wma_derive_ext_he_cap(wma_handle, &tmp_he_cap,
+					&he_cap_mac1);
+		}
+	}
+
+	qdf_mem_copy(he_cap, &tmp_he_cap, sizeof(*he_cap));
+	wma_print_he_cap(he_cap);
+}
+
+/*
+ * wma_he_update_tgt_services() - update tgt cfg to indicate 11ax support
+ * @wma: pointer to WMA handle
+ * @cfg: pointer to WMA target services
+ *
+ * Based on WMI SERVICES information, enable 11ax support and set DOT11AX bit
+ * in feature caps bitmap.
+ *
+ * Return: None
+ */
+void wma_he_update_tgt_services(tp_wma_handle wma, struct wma_tgt_services *cfg)
+{
+	if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, WMI_SERVICE_11AX)) {
+		cfg->en_11ax = true;
+		wma_set_fw_wlan_feat_caps(DOT11AX);
+		WMA_LOGI(FL("11ax is enabled"));
+	} else {
+		WMA_LOGI(FL("11ax is not enabled"));
+	}
+}
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 4b2fef8..94c1767 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -85,6 +85,7 @@
 #include "target_if.h"
 #include "wlan_global_lmac_if_api.h"
 #include "target_if_pmo.h"
+#include "wma_he.h"
 
 #include <cdp_txrx_handle.h>
 #define WMA_LOG_COMPLETION_TIMER 10000 /* 10 seconds */
@@ -95,13 +96,24 @@
 
 /**
  * wma_get_fw_wlan_feat_caps() - get fw feature capablity
- * @featEnumValue: feature enum value
+ * @feature: feature enum value
  *
  * Return: true/false
  */
-uint8_t wma_get_fw_wlan_feat_caps(uint8_t featEnumValue)
+bool wma_get_fw_wlan_feat_caps(enum cap_bitmap feature)
 {
-	return (g_fw_wlan_feat_caps & (1 << featEnumValue)) ? true : false;
+	return (g_fw_wlan_feat_caps & (1 << feature)) ? true : false;
+}
+
+/**
+ * wma_set_fw_wlan_feat_caps() - set fw feature capablity
+ * @feature: feature enum value
+ *
+ * Return: None
+ */
+void wma_set_fw_wlan_feat_caps(enum cap_bitmap feature)
+{
+	g_fw_wlan_feat_caps |= (1 << feature);
 }
 
 /**
@@ -3842,6 +3854,8 @@
 		WMA_LOGI("%s: TX_MSDU_ID_OLD_PARTITION=%d", __func__,
 				HTT_TX_IPA_MSDU_ID_SPACE_BEGIN);
 	}
+
+	wma_he_update_tgt_services(wh, cfg);
 }
 
 /**
@@ -4307,6 +4321,8 @@
 	wma_update_target_ext_ht_cap(wma_handle, &tgt_cfg.ht_cap);
 	wma_update_target_ext_vht_cap(wma_handle, &tgt_cfg.vht_cap);
 
+	wma_update_target_ext_he_cap(wma_handle, &tgt_cfg);
+
 	tgt_cfg.target_fw_version = wma_handle->target_fw_version;
 	tgt_cfg.target_fw_vers_ext = wma_handle->target_fw_vers_ext;
 #ifdef WLAN_FEATURE_LPSS
@@ -4978,6 +4994,72 @@
 	return status;
 }
 
+/**
+ * wma_print_mac_phy_capabilities() - Prints MAC PHY capabilities
+ * @cap: pointer to WMI_MAC_PHY_CAPABILITIES
+ * @index: MAC_PHY index
+ *
+ * Return: none
+ */
+static void wma_print_mac_phy_capabilities(WMI_MAC_PHY_CAPABILITIES *cap,
+					   int index)
+{
+	uint32_t mac_2G, mac_5G;
+	uint32_t phy_2G[WMI_MAX_HECAP_PHY_SIZE];
+	uint32_t phy_5G[WMI_MAX_HECAP_PHY_SIZE];
+	wmi_ppe_threshold ppet_2G, ppet_5G;
+
+	WMA_LOGI("\t: index [%d]", index);
+	WMA_LOGI("\t: cap for hw_mode_id[%d]", cap->hw_mode_id);
+	WMA_LOGI("\t: pdev_id[%d]", cap->pdev_id);
+	WMA_LOGI("\t: phy_id[%d]", cap->phy_id);
+	WMA_LOGI("\t: supports_11b[%d]",
+		WMI_SUPPORT_11B_GET(cap->supported_flags));
+	WMA_LOGI("\t: supports_11g[%d]",
+		WMI_SUPPORT_11G_GET(cap->supported_flags));
+	WMA_LOGI("\t: supports_11a[%d]",
+		WMI_SUPPORT_11A_GET(cap->supported_flags));
+	WMA_LOGI("\t: supports_11n[%d]",
+		WMI_SUPPORT_11N_GET(cap->supported_flags));
+	WMA_LOGI("\t: supports_11ac[%d]",
+		WMI_SUPPORT_11AC_GET(cap->supported_flags));
+	WMA_LOGI("\t: supports_11ax[%d]",
+		WMI_SUPPORT_11AX_GET(cap->supported_flags));
+	WMA_LOGI("\t: supported_flags[%d]", cap->supported_flags);
+	WMA_LOGI("\t: supported_bands[%d]", cap->supported_bands);
+	WMA_LOGI("\t: ampdu_density[%d]", cap->ampdu_density);
+	WMA_LOGI("\t: max_bw_supported_2G[%d]", cap->max_bw_supported_2G);
+	WMA_LOGI("\t: ht_cap_info_2G[%d]", cap->ht_cap_info_2G);
+	WMA_LOGI("\t: vht_cap_info_2G[%d]", cap->vht_cap_info_2G);
+	WMA_LOGI("\t: vht_supp_mcs_2G[%d]", cap->vht_supp_mcs_2G);
+	WMA_LOGI("\t: tx_chain_mask_2G[%d]", cap->tx_chain_mask_2G);
+	WMA_LOGI("\t: rx_chain_mask_2G[%d]", cap->rx_chain_mask_2G);
+	WMA_LOGI("\t: max_bw_supported_5G[%d]", cap->max_bw_supported_5G);
+	WMA_LOGI("\t: ht_cap_info_5G[%d]", cap->ht_cap_info_5G);
+	WMA_LOGI("\t: vht_cap_info_5G[%d]", cap->vht_cap_info_5G);
+	WMA_LOGI("\t: vht_supp_mcs_5G[%d]", cap->vht_supp_mcs_5G);
+	WMA_LOGI("\t: tx_chain_mask_5G[%d]", cap->tx_chain_mask_5G);
+	WMA_LOGI("\t: rx_chain_mask_5G[%d]", cap->rx_chain_mask_5G);
+	WMA_LOGI("\t: he_cap_info_2G[%08x]", cap->he_cap_info_2G);
+	WMA_LOGI("\t: he_supp_mcs_2G[%08x]", cap->he_supp_mcs_2G);
+	WMA_LOGI("\t: he_cap_info_5G[%08x]", cap->he_cap_info_5G);
+	WMA_LOGI("\t: he_supp_mcs_5G[%08x]", cap->he_supp_mcs_5G);
+	mac_2G = cap->he_cap_info_2G;
+	mac_5G = cap->he_cap_info_5G;
+	qdf_mem_copy(phy_2G, cap->he_cap_phy_info_2G,
+		     WMI_MAX_HECAP_PHY_SIZE * 4);
+	qdf_mem_copy(phy_5G, cap->he_cap_phy_info_5G,
+		     WMI_MAX_HECAP_PHY_SIZE * 4);
+	ppet_2G = cap->he_ppet2G;
+	ppet_5G = cap->he_ppet5G;
+
+	wma_print_he_mac_cap(mac_2G);
+	wma_print_he_phy_cap(phy_2G);
+	wma_print_he_ppet(&ppet_2G);
+	wma_print_he_mac_cap(mac_5G);
+	wma_print_he_phy_cap(phy_5G);
+	wma_print_he_ppet(&ppet_5G);
+}
 
 /**
  * wma_print_populate_soc_caps() - Prints all the caps populated per hw mode
@@ -5009,55 +5091,7 @@
 
 		for ( ; j < max_mac; j++) {
 			tmp = &wma_handle->phy_caps.each_phy_cap_per_hwmode[j];
-			WMA_LOGI("\t: index j[%d]", j);
-			WMA_LOGI("\t: cap for hw_mode_id[%d]", tmp->hw_mode_id);
-			WMA_LOGI("\t: pdev_id[%d]", tmp->pdev_id);
-			WMA_LOGI("\t: phy_id[%d]", tmp->phy_id);
-			WMA_LOGI("\t: supports_11b[%d]",
-				WMI_SUPPORT_11B_GET(tmp->supported_flags));
-			WMA_LOGI("\t: supports_11g[%d]",
-				WMI_SUPPORT_11G_GET(tmp->supported_flags));
-			WMA_LOGI("\t: supports_11a[%d]",
-				WMI_SUPPORT_11A_GET(tmp->supported_flags));
-			WMA_LOGI("\t: supports_11n[%d]",
-				WMI_SUPPORT_11N_GET(tmp->supported_flags));
-			WMA_LOGI("\t: supports_11ac[%d]",
-				WMI_SUPPORT_11AC_GET(tmp->supported_flags));
-			WMA_LOGI("\t: supports_11ax[%d]",
-				WMI_SUPPORT_11AX_GET(tmp->supported_flags));
-			WMA_LOGI("\t: supported_flags[%d]",
-					tmp->supported_flags);
-			WMA_LOGI("\t: supported_bands[%d]",
-					tmp->supported_bands);
-			WMA_LOGI("\t: ampdu_density[%d]",
-					tmp->ampdu_density);
-			WMA_LOGI("\t: max_bw_supported_2G[%d]",
-					tmp->max_bw_supported_2G);
-			WMA_LOGI("\t: ht_cap_info_2G[%d]", tmp->ht_cap_info_2G);
-			WMA_LOGI("\t: vht_cap_info_2G[%d]",
-					tmp->vht_cap_info_2G);
-			WMA_LOGI("\t: he_cap_info_2G[%d]", tmp->he_cap_info_2G);
-			WMA_LOGI("\t: vht_supp_mcs_2G[%d]",
-					tmp->vht_supp_mcs_2G);
-			WMA_LOGI("\t: he_supp_mcs_2G[%d]", tmp->he_supp_mcs_2G);
-			WMA_LOGI("\t: tx_chain_mask_2G[%d]",
-					tmp->tx_chain_mask_2G);
-			WMA_LOGI("\t: rx_chain_mask_2G[%d]",
-					tmp->rx_chain_mask_2G);
-			WMA_LOGI("\t: max_bw_supported_5G[%d]",
-					tmp->max_bw_supported_5G);
-			WMA_LOGI("\t: ht_cap_info_5G[%d]",
-					tmp->ht_cap_info_5G);
-			WMA_LOGI("\t: vht_cap_info_5G[%d]",
-					tmp->vht_cap_info_5G);
-			WMA_LOGI("\t: he_cap_info_5G[%d]", tmp->he_cap_info_5G);
-			WMA_LOGI("\t: vht_supp_mcs_5G[%d]",
-					tmp->vht_supp_mcs_5G);
-			WMA_LOGI("\t: he_supp_mcs_5G[%d]", tmp->he_supp_mcs_5G);
-			WMA_LOGI("\t: tx_chain_mask_5G[%d]",
-					tmp->tx_chain_mask_5G);
-			WMA_LOGI("\t: rx_chain_mask_5G[%d]",
-					tmp->rx_chain_mask_5G);
+			wma_print_mac_phy_capabilities(tmp, j);
 		}
 	}
 	WMA_LOGI("%s: <====== HW mode cap printing ends ======>\n", __func__);