Преглед изворни кода

qcacld-3.0: Add support to send action frame in HE TB PPDU

Add support to configure the FW to send the action frame in
HE trigger based PPDU.

Change-Id: Ie6df5b1cb40c7f1b18a9e86f90b4b8f44ba7bf6b
CRs-Fixed: 2311413
Kiran Kumar Lokere пре 6 година
родитељ
комит
ee205778c7

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

@@ -5184,6 +5184,8 @@ wlan_hdd_wifi_test_config_policy[
 			.type = NLA_FLAG},
 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU] = {
 			.type = NLA_U8},
+		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU] = {
+			.type = NLA_U8},
 };
 
 /**
@@ -6564,6 +6566,14 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 			sme_config_su_ppdu_queue(adapter->session_id, false);
 	}
 
+	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU;
+	if (tb[cmd_id]) {
+		cfg_val = nla_get_u8(tb[cmd_id]);
+		hdd_debug("Configure Action frame Tx in TB PPDU %d", cfg_val);
+		sme_config_action_tx_in_tb_ppdu(hdd_ctx->mac_handle,
+						adapter->session_id, cfg_val);
+	}
+
 	if (update_sme_cfg)
 		sme_update_config(mac_handle, sme_config);
 

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

@@ -5189,6 +5189,22 @@ typedef void (*hw_mode_transition_cb)(uint32_t old_hw_mode_index,
 		struct policy_mgr_vdev_mac_map *vdev_mac_map);
 typedef void (*antenna_mode_cb)(uint32_t status, void *context);
 
+/**
+ * struct cfg_action_frm_tb_ppdu - action frame TB PPDU cfg
+ * @vdev_id - vdev id
+ * @cfg - enable/disable
+ * @frm_len - frame length
+ * @data - frame data
+ *
+ * This structure is used to cfg action frame tb ppdu.
+ */
+struct cfg_action_frm_tb_ppdu {
+	uint8_t vdev_id;
+	uint8_t cfg;
+	uint8_t frm_len;
+	uint8_t *data;
+};
+
 /**
  * struct sir_nss_update_request
  * @msgType: nss update msg type

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

@@ -232,6 +232,7 @@ enum eWniMsgTypes {
 	WNI_SME_UPDATE_MU_EDCA_PARAMS,
 	eWNI_SME_CSA_RESTART_REQ,
 	eWNI_SME_CSA_RESTART_RSP,
+	WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU,
 	eWNI_SME_MSG_TYPES_END
 };
 

+ 17 - 0
core/mac/src/cfg/cfgUtil/dot11f.frms

@@ -467,6 +467,16 @@ FF ba_start_seq_ctrl(2)
     }
 }
 
+FF vendor_oui (3)
+{
+    oui_data[3];
+}
+
+FF vendor_action_subtype (1)
+{
+    subtype, 1;
+}
+
 IE addba_extn_element(EID_ADDBA_EXTN_ELEMENT)
 {
     {
@@ -4324,6 +4334,13 @@ FRAME delba_req
     FF    Reason;
 }
 
+FRAME vendor_action_frame
+{
+    FF    Category;
+    FF    vendor_oui;
+    FF    vendor_action_subtype;
+}
+
 // Local Variables:
 // mode: c++
 // fill-column: 77

+ 53 - 1
core/mac/src/include/dot11f.h

@@ -26,7 +26,7 @@
  *
  *
  * This file was automatically generated by 'framesc'
- * Tue Sep 18 11:47:29 2018 from the following file(s):
+ * Thu Sep 27 15:54:27 2018 from the following file(s):
  *
  * dot11f.frms
  *
@@ -672,6 +672,32 @@ void dot11f_pack_ff_p2p_action_subtype(tpAniSirGlobal,
 				       uint8_t *);
 
 
+typedef struct sDot11fFfvendor_action_subtype {
+	uint8_t subtype;
+} tDot11fFfvendor_action_subtype;
+
+#define DOT11F_FF_VENDOR_ACTION_SUBTYPE_LEN (1)
+
+void dot11f_unpack_ff_vendor_action_subtype(tpAniSirGlobal, uint8_t *,
+					    tDot11fFfvendor_action_subtype *);
+
+void dot11f_pack_ff_vendor_action_subtype(tpAniSirGlobal,
+					  tDot11fFfvendor_action_subtype *,
+					  uint8_t *);
+
+
+typedef struct sDot11fFfvendor_oui {
+	uint8_t oui_data[3];
+} tDot11fFfvendor_oui;
+
+#define DOT11F_FF_VENDOR_OUI_LEN (3)
+
+void dot11f_unpack_ff_vendor_oui(tpAniSirGlobal, uint8_t *,
+				 tDot11fFfvendor_oui *);
+
+void dot11f_pack_ff_vendor_oui(tpAniSirGlobal, tDot11fFfvendor_oui *,
+			       uint8_t *);
+
 /*********************************************************************
  * TLVs                                                              *
  ********************************************************************/
@@ -11184,4 +11210,30 @@ uint32_t dot11f_get_packed_p2p_oper_chan_change_confirmSize(tpAniSirGlobal pCtx,
 } /* End extern "C". */
 #endif /* C++ */
 
+typedef struct sDot11fvendor_action_frame{
+	tDot11fFfCategory                     Category;
+	tDot11fFfvendor_oui                   vendor_oui;
+	tDot11fFfvendor_action_subtype        vendor_action_subtype;
+} tDot11fvendor_action_frame;
+
+#define DOT11F_VENDOR_ACTION_FRAME (52)
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* C++ */
+
+uint32_t dot11f_unpack_vendor_action_frame(tpAniSirGlobal pCtx,
+	uint8_t *pBuf, uint32_t nBuf,
+	tDot11fvendor_action_frame * pFrm, bool append_ie);
+uint32_t dot11f_pack_vendor_action_frame(tpAniSirGlobal pCtx,
+	tDot11fvendor_action_frame *pFrm, uint8_t *pBuf,
+	uint32_t nBuf, uint32_t *pnConsumed);
+uint32_t dot11f_get_packed_vendor_action_frameSize(tpAniSirGlobal pCtx,
+	tDot11fvendor_action_frame *pFrm,
+	uint32_t *pnNeeded);
+
+#ifdef __cplusplus
+} /* End extern "C". */
+#endif /* C++ */
+
 #endif /* DOT11F_H */

+ 13 - 1
core/mac/src/include/sir_params.h

@@ -205,6 +205,18 @@ struct sir_mgmt_msg {
 	uint8_t *data;
 };
 
+/**
+ * struct sir_cfg_action_frm_tb_ppdu - cfg to set action frame in he tb ppdu
+ * @type: Message type
+ * @session_id: session id
+ * @cfg: enable/disable cfg
+ */
+struct sir_cfg_action_frm_tb_ppdu {
+	uint16_t type;
+	uint8_t session_id;
+	uint8_t cfg;
+};
+
 /* ******************************************* *
 *                                             *
 *         SIRIUS MESSAGE TYPES                *
@@ -682,7 +694,7 @@ struct sir_mgmt_msg {
 #define SIR_HAL_GET_ROAM_SCAN_STATS         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 399)
 #define SIR_HAL_SEND_AP_VDEV_UP             (SIR_HAL_ITC_MSG_TYPES_BEGIN + 400)
 #define SIR_HAL_SEND_BCN_RSP                (SIR_HAL_ITC_MSG_TYPES_BEGIN + 401)
-
+#define SIR_HAL_CFG_VENDOR_ACTION_TB_PPDU   (SIR_HAL_ITC_MSG_TYPES_BEGIN + 402)
 #define SIR_HAL_MSG_TYPES_END               (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
 /* CFG message types */

+ 1 - 0
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -1654,6 +1654,7 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx,
 	case eWNI_SME_SET_ADDBA_ACCEPT:
 	case eWNI_SME_UPDATE_EDCA_PROFILE:
 	case WNI_SME_UPDATE_MU_EDCA_PARAMS:
+	case WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU:
 		/* These messages are from HDD.No need to respond to HDD */
 		lim_process_normal_hdd_msg(mac_ctx, msg, false);
 		break;

+ 17 - 0
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -3809,6 +3809,19 @@ static void lim_process_sme_update_mu_edca_params(tpAniSirGlobal mac_ctx,
 		pe_err("Self entry missing in Hash Table");
 }
 
+static void
+lim_process_sme_cfg_action_frm_in_tb_ppdu(struct mac_context *mac_ctx,
+					  struct  sir_cfg_action_frm_tb_ppdu
+					  *msg)
+{
+	if (!msg) {
+		pe_err("Buffer is NULL");
+		return;
+	}
+
+	lim_send_action_frm_tb_ppdu_cfg(mac_ctx, msg->session_id, msg->cfg);
+}
+
 static void lim_process_sme_update_config(tpAniSirGlobal mac_ctx,
 					  struct update_config *msg)
 {
@@ -5112,6 +5125,10 @@ bool lim_process_sme_req_messages(tpAniSirGlobal pMac,
 	case WNI_SME_UPDATE_MU_EDCA_PARAMS:
 		lim_process_sme_update_mu_edca_params(pMac, pMsg->bodyval);
 		break;
+	case WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU:
+		lim_process_sme_cfg_action_frm_in_tb_ppdu(pMac,
+				(struct  sir_cfg_action_frm_tb_ppdu *)pMsgBuf);
+		break;
 	default:
 		qdf_mem_free((void *)pMsg->bodyptr);
 		pMsg->bodyptr = NULL;

+ 84 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -6273,6 +6273,90 @@ void lim_merge_extcap_struct(tDot11fIEExtCap *dst,
 		dst->present = 1;
 }
 
+/**
+ * lim_send_action_frm_tb_ppdu_cfg_flush_cb() - flush TB PPDU cfg msg
+ * @msg: Message pointer
+ *
+ * Flushes the send action frame in HE TB PPDU configuration message.
+ *
+ * Return: None
+ */
+static void lim_send_action_frm_tb_ppdu_cfg_flush_cb(struct scheduler_msg *msg)
+{
+	if (msg->bodyptr) {
+		qdf_mem_free(msg->bodyptr);
+		msg->bodyptr = NULL;
+	}
+}
+
+/**
+ * lim_send_action_frm_tb_ppdu_cfg() - sets action frame in TB PPDU cfg to FW
+ * @mac_ctx: global MAC context
+ * @session_id: SME session id
+ * @cfg: config setting
+ *
+ * Preapres the vendor action frame and send action frame in HE TB PPDU
+ * configuration to FW.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS lim_send_action_frm_tb_ppdu_cfg(struct mac_context *mac_ctx,
+					   uint32_t session_id,
+					   uint8_t cfg)
+{
+	tDot11fvendor_action_frame *frm;
+	uint8_t frm_len = sizeof(*frm);
+	tpPESession session;
+	struct cfg_action_frm_tb_ppdu *cfg_msg;
+	struct scheduler_msg msg = {0};
+	uint8_t *data_buf;
+
+	session = pe_find_session_by_sme_session_id(mac_ctx, session_id);
+
+	if (!session) {
+		pe_err("pe session does not exist for sme session id %d",
+		       session_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	data_buf = qdf_mem_malloc(frm_len + sizeof(*cfg_msg));
+	if (!data_buf)
+		return QDF_STATUS_E_FAILURE;
+
+	cfg_msg = (struct cfg_action_frm_tb_ppdu *)data_buf;
+
+	frm = (tDot11fvendor_action_frame *)(data_buf + sizeof(*cfg_msg));
+
+	frm->Category.category = SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY;
+
+	frm->vendor_oui.oui_data[0] = 0x00;
+	frm->vendor_oui.oui_data[1] = 0xA0;
+	frm->vendor_oui.oui_data[2] = 0xC6;
+
+	frm->vendor_action_subtype.subtype = 0xFF;
+
+	cfg_msg->vdev_id = session_id;
+	cfg_msg->cfg = cfg;
+	cfg_msg->frm_len = frm_len;
+	cfg_msg->data = (uint8_t *)frm;
+
+	msg.type = WMA_CFG_VENDOR_ACTION_TB_PPDU;
+	msg.bodyptr = cfg_msg;
+	msg.reserved = 0;
+	msg.flush_callback = lim_send_action_frm_tb_ppdu_cfg_flush_cb;
+
+	if (QDF_STATUS_SUCCESS !=
+		scheduler_post_message(QDF_MODULE_ID_PE,
+				       QDF_MODULE_ID_WMA,
+				       QDF_MODULE_ID_WMA, &msg)) {
+		pe_err("Not able to post WMA_SET_IE_INFO to WDA");
+		qdf_mem_free(data_buf);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * lim_get_80Mhz_center_channel - finds 80 Mhz center channel
  *

+ 15 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -750,6 +750,21 @@ QDF_STATUS lim_send_ext_cap_ie(tpAniSirGlobal mac_ctx, uint32_t session_id,
 QDF_STATUS lim_send_ies_per_band(tpAniSirGlobal mac_ctx,
 				 tpPESession session, uint8_t vdev_id);
 
+/**
+ * lim_send_action_frm_tb_ppdu_cfg() - sets action frame in TB PPDU cfg to FW
+ * @mac_ctx: global MAC context
+ * @session_id: SME session id
+ * @cfg: config setting
+ *
+ * Preapres the vendor action frame and send action frame in HE TB PPDU
+ * configuration to FW.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS lim_send_action_frm_tb_ppdu_cfg(struct mac_context *mac_ctx,
+					   uint32_t session_id,
+					   uint8_t cfg);
+
 QDF_STATUS lim_strip_extcap_ie(tpAniSirGlobal mac_ctx, uint8_t *addn_ie,
 			  uint16_t *addn_ielen, uint8_t *extracted_extcap);
 void lim_update_extcap_struct(tpAniSirGlobal mac_ctx, uint8_t *buf,

+ 111 - 1
core/mac/src/sys/legacy/src/utils/src/dot11f.c

@@ -24,7 +24,7 @@
  *
  *
  * This file was automatically generated by 'framesc'
- * Tue Sep 18 11:47:29 2018 from the following file(s):
+ * Thu Sep 27 15:54:27 2018 from the following file(s):
  *
  * dot11f.frms
  *
@@ -860,6 +860,26 @@ void dot11f_unpack_ff_p2p_action_subtype(tpAniSirGlobal pCtx,
 
 #define SigFfp2p_action_subtype (0x0025)
 
+void dot11f_unpack_ff_vendor_action_subtype(tpAniSirGlobal pCtx,
+					    uint8_t *pBuf,
+					    tDot11fFfvendor_action_subtype *pDst)
+{
+	pDst->subtype = *pBuf;
+	(void)pCtx;
+} /* End dot11f_unpack_ff_vendor_action_subtype. */
+
+#define SigFfvendor_action_subtype (0x0026)
+
+void dot11f_unpack_ff_vendor_oui(tpAniSirGlobal pCtx,
+				 uint8_t *pBuf,
+				 tDot11fFfvendor_oui *pDst)
+{
+	DOT11F_MEMCPY(pCtx, pDst->oui_data, pBuf, 3);
+	(void)pCtx;
+} /* End dot11f_unpack_ff_vendor_oui. */
+
+#define SigFfvendor_oui (0x0027)
+
 uint32_t dot11f_unpack_tlv_authorized_ma_cs(tpAniSirGlobal pCtx,
 					  uint8_t *pBuf,
 					  uint16_t tlvlen,
@@ -12615,6 +12635,35 @@ uint32_t dot11f_unpack_p2p_oper_chan_change_confirm(tpAniSirGlobal pCtx,
 
 } /* End dot11f_unpack_p2p_oper_chan_change_confirm. */
 
+static const tFFDefn FFS_vendor_action_frame[] = {
+	{ "Category", offsetof(tDot11fvendor_action_frame, Category),
+	SigFfCategory, DOT11F_FF_CATEGORY_LEN, },
+	{ "vendor_oui", offsetof(tDot11fvendor_action_frame, vendor_oui),
+	SigFfvendor_oui, DOT11F_FF_VENDOR_OUI_LEN, },
+	{ "vendor_action_subtype", offsetof(tDot11fvendor_action_frame,
+	vendor_action_subtype), SigFfvendor_action_subtype,
+	DOT11F_FF_VENDOR_ACTION_SUBTYPE_LEN, },
+	{ NULL, 0, 0, 0,},
+};
+
+static const tIEDefn IES_vendor_action_frame[] = {
+	{0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, },};
+
+uint32_t dot11f_unpack_vendor_action_frame(tpAniSirGlobal pCtx,
+		uint8_t *pBuf, uint32_t nBuf,
+		tDot11fvendor_action_frame *pFrm, bool append_ie)
+{
+	uint32_t i = 0;
+	uint32_t status = 0;
+	status = unpack_core(pCtx, pBuf, nBuf,
+		      FFS_vendor_action_frame, IES_vendor_action_frame,
+		      (uint8_t *)pFrm, sizeof(*pFrm), append_ie);
+
+	(void)i;
+	return status;
+
+} /* End dot11f_unpack_vendor_action_frame. */
+
 /**
  * Note: If @append_ie is set TRUE, pFrm will not be reset to zero,
  * but parsed IE's would be populated to pFrm with already
@@ -12853,6 +12902,16 @@ static uint32_t unpack_core(tpAniSirGlobal pCtx,
 			    pBufRemaining, (tDot11fFfp2p_action_subtype *)
 			    (pFrm + pFf->offset));
 			break;
+		case SigFfvendor_action_subtype:
+			dot11f_unpack_ff_vendor_action_subtype(pCtx,
+			    pBufRemaining, (tDot11fFfvendor_action_subtype *)
+			    (pFrm + pFf->offset));
+			break;
+		case SigFfvendor_oui:
+			dot11f_unpack_ff_vendor_oui(pCtx,
+			    pBufRemaining, (tDot11fFfvendor_oui *)
+			    (pFrm + pFf->offset));
+			break;
 		default:
 			FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR: I don'"
 				   "t know about the FF signature %d-- this is most "
@@ -16309,6 +16368,16 @@ uint32_t dot11f_get_packed_p2p_oper_chan_change_confirmSize(tpAniSirGlobal pCtx,
 	return status;
 } /* End dot11f_get_packed_p2p_oper_chan_change_confirmSize. */
 
+uint32_t dot11f_get_packed_vendor_action_frameSize(tpAniSirGlobal pCtx,
+	tDot11fvendor_action_frame *pFrm, uint32_t *pnNeeded)
+{
+	uint32_t status = 0;
+	*pnNeeded = 5;
+	status = get_packed_size_core(pCtx, (uint8_t *)pFrm, pnNeeded,
+				      IES_vendor_action_frame);
+	return status;
+} /* End dot11f_get_packed_vendor_action_frameSize. */
+
 static uint32_t get_packed_size_core(tpAniSirGlobal pCtx,
 				      uint8_t *pFrm,
 				      uint32_t *pnNeeded,
@@ -18151,6 +18220,22 @@ void dot11f_pack_ff_p2p_action_subtype(tpAniSirGlobal pCtx,
 	(void)pCtx;
 } /* End dot11f_pack_ff_p2p_action_subtype. */
 
+void dot11f_pack_ff_vendor_action_subtype(tpAniSirGlobal pCtx,
+					  tDot11fFfvendor_action_subtype *pSrc,
+					  uint8_t *pBuf)
+{
+	*pBuf = pSrc->subtype;
+	(void)pCtx;
+} /* End dot11f_pack_ff_vendor_action_subtype. */
+
+void dot11f_pack_ff_vendor_oui(tpAniSirGlobal pCtx,
+			       tDot11fFfvendor_oui *pSrc,
+			       uint8_t *pBuf)
+{
+	DOT11F_MEMCPY(pCtx, pBuf, pSrc->oui_data, 3);
+	(void)pCtx;
+} /* End dot11f_pack_ff_vendor_oui. */
+
 uint32_t dot11f_pack_tlv_authorized_ma_cs(tpAniSirGlobal pCtx,
 					tDot11fTLVAuthorizedMACs *pSrc,
 					uint8_t *pBuf,
@@ -27494,6 +27579,21 @@ uint32_t dot11f_pack_p2p_oper_chan_change_confirm(tpAniSirGlobal pCtx,
 
 } /* End dot11f_unpack_p2p_oper_chan_change_confirm. */
 
+uint32_t dot11f_pack_vendor_action_frame(tpAniSirGlobal pCtx,
+	tDot11fvendor_action_frame *pFrm,
+	uint8_t *pBuf, uint32_t nBuf, uint32_t *pnConsumed)
+{
+	uint32_t i = 0;
+	uint32_t status = 0;
+	(void)i;
+	*pnConsumed = 0U;
+	status = pack_core(pCtx, (uint8_t *)pFrm, pBuf, nBuf, pnConsumed,
+			   FFS_vendor_action_frame, IES_vendor_action_frame);
+
+	return status;
+
+} /* End dot11f_unpack_vendor_action_frame. */
+
 static uint32_t pack_core(tpAniSirGlobal pCtx,
 			   uint8_t *pSrc,
 			   uint8_t *pBuf,
@@ -27714,6 +27814,16 @@ static uint32_t pack_core(tpAniSirGlobal pCtx,
 				pCtx, (tDot11fFfp2p_action_subtype *)
 				(pSrc + pFf->offset), pBufRemaining);
 			break;
+		case SigFfvendor_action_subtype:
+			dot11f_pack_ff_vendor_action_subtype(
+				pCtx, (tDot11fFfvendor_action_subtype *)
+				(pSrc + pFf->offset), pBufRemaining);
+			break;
+		case SigFfvendor_oui:
+			dot11f_pack_ff_vendor_oui(
+				pCtx, (tDot11fFfvendor_oui *)
+				(pSrc + pFf->offset), pBufRemaining);
+			break;
 		default:
 			FRAMES_LOG1(pCtx, FRLOGE, FRFL("INTERNAL ERROR-- I don"
 				"'t know about the Fixed Field %d; this is most l"

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

@@ -2813,6 +2813,16 @@ int sme_send_he_om_ctrl_nss_update(mac_handle_t mac_handle, uint8_t session_id,
 
 void sme_reset_he_om_ctrl(mac_handle_t mac_handle);
 
+/**
+ * sme_config_action_tx_in_tb_ppdu() - Sends action frame in TB PPDU cfg to FW
+ * @mac_handle: Pointer to MAC handle
+ * @session_id: SME session id
+ * @cfg_val: configuration setting value
+ *
+ * Return: 0 on success else err code
+ */
+int sme_config_action_tx_in_tb_ppdu(mac_handle_t mac_handle, uint8_t session_id,
+				    uint8_t cfg_val);
 /**
  * sme_set_usr_cfg_mu_edca() - sets the user cfg MU EDCA params flag
  * @mac_handle: Opaque handle to the global MAC context
@@ -2939,6 +2949,13 @@ static inline void sme_reset_he_om_ctrl(mac_handle_t mac_handle)
 {
 }
 
+static inline int sme_config_action_tx_in_tb_ppdu(mac_handle_t mac_handle,
+						  uint8_t session_id,
+						  uint8_t cfg_val)
+{
+	return 0;
+}
+
 static inline void sme_set_usr_cfg_mu_edca(mac_handle_t mac_handle, bool val)
 {
 }

+ 37 - 0
core/sme/src/common/sme_api.c

@@ -13330,6 +13330,43 @@ void sme_reset_he_om_ctrl(mac_handle_t mac_handle)
 	mac_ctx->he_om_ctrl_cfg_nss = 0;
 }
 
+int sme_config_action_tx_in_tb_ppdu(mac_handle_t mac_handle, uint8_t session_id,
+				    uint8_t cfg_val)
+{
+	QDF_STATUS status;
+	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
+	struct scheduler_msg msg = {0};
+	struct sir_cfg_action_frm_tb_ppdu *cfg_msg;
+
+	if (!csr_is_conn_state_connected_infra(mac_ctx, session_id)) {
+		sme_info("STA not in connected state Session_id: %d",
+			 session_id);
+		return -EINVAL;
+	}
+
+	cfg_msg = qdf_mem_malloc(sizeof(*cfg_msg));
+
+	if (!cfg_msg)
+		return -EIO;
+
+	cfg_msg->type = WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU;
+	cfg_msg->session_id = session_id;
+	cfg_msg->cfg = cfg_val;
+
+	msg.bodyptr = cfg_msg;
+	msg.type = WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU;
+	status = scheduler_post_message(QDF_MODULE_ID_SME, QDF_MODULE_ID_PE,
+					QDF_MODULE_ID_PE, &msg);
+	if (QDF_STATUS_SUCCESS != status) {
+		sme_err("Failed to send CFG_ACTION_FRAME_IN_TB_PPDU to PE %d",
+			status);
+		qdf_mem_free(cfg_msg);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 int sme_update_he_tx_bfee_nsts(mac_handle_t mac_handle, uint8_t session_id,
 			       uint8_t cfg_val)
 {

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

@@ -1269,6 +1269,9 @@ int wma_rssi_breached_event_handler(void *handle,
 }
 #endif /* FEATURE_RSSI_MONITOR */
 
+QDF_STATUS wma_process_cfg_action_frm_tb_ppdu(tp_wma_handle wma,
+				   struct cfg_action_frm_tb_ppdu *cfg_info);
+
 QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma,
 				   struct vdev_ie_info *ie_info);
 int wma_peer_assoc_conf_handler(void *handle, uint8_t *cmd_param_info,

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

@@ -454,6 +454,7 @@
 #define WMA_OBSS_COLOR_COLLISION_REQ         SIR_HAL_OBSS_COLOR_COLLISION_REQ
 #define WMA_OBSS_COLOR_COLLISION_INFO        SIR_HAL_OBSS_COLOR_COLLISION_INFO
 
+#define WMA_CFG_VENDOR_ACTION_TB_PPDU        SIR_HAL_CFG_VENDOR_ACTION_TB_PPDU
 #define WMA_GET_ROAM_SCAN_STATS              SIR_HAL_GET_ROAM_SCAN_STATS
 
 /* Bit 6 will be used to control BD rate for Management frames */

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

@@ -4303,6 +4303,34 @@ end_tdls_peer_state:
 }
 #endif /* FEATURE_WLAN_TDLS */
 
+/*
+ * wma_process_cfg_action_frm_tb_ppdu() - action frame TB PPDU cfg to firmware
+ * @wma:                Pointer to WMA handle
+ * @cfg_info:       Pointer for cfg info
+ *
+ * Return: QDF_STATUS_SUCCESS for success otherwise failure
+ *
+ */
+QDF_STATUS wma_process_cfg_action_frm_tb_ppdu(tp_wma_handle wma,
+				   struct cfg_action_frm_tb_ppdu *cfg_info)
+{
+	struct cfg_action_frm_tb_ppdu_param cmd = {0};
+
+	if (!wma) {
+		WMA_LOGE(FL("WMA pointer is NULL"));
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	cmd.frm_len = cfg_info->frm_len;
+	cmd.cfg = cfg_info->cfg;
+	cmd.data = cfg_info->data;
+
+	WMA_LOGD(FL("cfg: %d, frm_len: %d"),
+		 cfg_info->cfg, cfg_info->frm_len);
+
+	return wmi_unified_cfg_action_frm_tb_ppdu_cmd(wma->wmi_handle, &cmd);
+}
+
 
 /*
  * wma_process_set_ie_info() - Function to send IE info to firmware

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

@@ -8476,6 +8476,10 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg)
 			(struct vdev_ie_info *)msg->bodyptr);
 		qdf_mem_free(msg->bodyptr);
 		break;
+	case WMA_CFG_VENDOR_ACTION_TB_PPDU:
+		wma_process_cfg_action_frm_tb_ppdu(wma_handle, msg->bodyptr);
+		qdf_mem_free(msg->bodyptr);
+		break;
 	case SIR_HAL_SOC_ANTENNA_MODE_REQ:
 		wma_send_pdev_set_antenna_mode(wma_handle,
 			(struct sir_antenna_mode_param *)msg->bodyptr);