Przeglądaj źródła

qcacld-3.0: [11AX] Add support for vendor commands

Add support for vendor commands to query HE capabilities.

Add support to include HE capabilities in wma_handle as received
from FW to be sent to userspace when queried via vendor sub command.

Change-Id: Icbf141bd1e0646346c2b18aabf3dfb3590d853d7
CRs-Fixed: 1073481
Krishna Kumaar Natarajan 8 lat temu
rodzic
commit
f567650ade

+ 60 - 0
core/hdd/inc/wlan_hdd_he.h

@@ -35,6 +35,40 @@ struct sap_Config;
 #define HE_CAP_OUI_SIZE 4
 
 #ifdef WLAN_FEATURE_11AX
+/**
+ * enum qca_wlan_vendor_attr_get_he_capabilities - attributes for HE caps.
+ *						  vendor command.
+ * @QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_INVALID - invalid
+ * @QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED - to check if HE capabilities is supported
+ * @QCA_WLAN_VENDOR_ATTR_PHY_CAPAB - to get HE PHY capabilities
+ * @QCA_WLAN_VENDOR_ATTR_MAC_CAPAB - to get HE MAC capabilities
+ * @QCA_WLAN_VENDOR_ATTR_HE_MCS - to get HE MCS
+ * @QCA_WLAN_VENDOR_ATTR_NUM_SS - to get NUM SS
+ * @QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK - to get RU index mask
+ * @QCA_WLAN_VENDOR_ATTR_RU_COUNT - to get RU count,
+ * @QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD - to get PPE Threshold,
+ * @QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST - next to last valid enum
+ * @QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX - max value supported
+ *
+ * enum values are used for NL attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES sub command.
+ */
+enum qca_wlan_vendor_attr_get_he_capabilities {
+	QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_INVALID = 0,
+	QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED,
+	QCA_WLAN_VENDOR_ATTR_PHY_CAPAB,
+	QCA_WLAN_VENDOR_ATTR_MAC_CAPAB,
+	QCA_WLAN_VENDOR_ATTR_HE_MCS,
+	QCA_WLAN_VENDOR_ATTR_NUM_SS = 5,
+	QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK,
+	QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD,
+
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX =
+	QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST - 1,
+};
+
 void hdd_update_tgt_he_cap(struct hdd_context_s *hdd_ctx,
 			   struct wma_tgt_cfg *cfg);
 void wlan_hdd_check_11ax_support(struct beacon_data_s *beacon,
@@ -43,6 +77,28 @@ void hdd_he_print_ini_config(hdd_context_t *hdd_ctx);
 int hdd_update_he_cap_in_cfg(hdd_context_t *hdd_ctx);
 void hdd_he_set_sme_config(tSmeConfigParams *sme_config,
 			   struct hdd_config *config);
+
+/**
+ * wlan_hdd_cfg80211_get_he_cap() - get HE Capabilities
+ * @wiphy: Pointer to wiphy
+ * @wdev: Pointer to wdev
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 if success, non-zero for failure
+ */
+int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy,
+				 struct wireless_dev *wdev, const void *data,
+				 int data_len);
+#define FEATURE_11AX_VENDOR_COMMANDS					\
+{									\
+	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
+	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES,	\
+	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
+		 WIPHY_VENDOR_CMD_NEED_NETDEV,				\
+	.doit = wlan_hdd_cfg80211_get_he_cap				\
+},
+
 #else
 static inline void hdd_update_tgt_he_cap(struct hdd_context_s *hdd_ctx,
 					 struct wma_tgt_cfg *cfg)
@@ -67,5 +123,9 @@ static inline void hdd_he_set_sme_config(tSmeConfigParams *sme_config,
 					 struct hdd_config *config)
 {
 }
+
+/* dummy definition */
+#define FEATURE_11AX_VENDOR_COMMANDS
+
 #endif
 #endif /* if !defined(WLAN_HDD_HE_H)*/

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

@@ -100,6 +100,7 @@
 #include "wlan_hdd_nan_datapath.h"
 #include "wlan_hdd_disa.h"
 #include "wlan_hdd_request_manager.h"
+#include "wlan_hdd_he.h"
 
 #include <cdp_txrx_cmn.h>
 #include <cdp_txrx_misc.h>
@@ -10074,6 +10075,7 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
 #ifdef WLAN_UMAC_CONVERGENCE
 	COMMON_VENDOR_COMMANDS
 #endif
+	FEATURE_11AX_VENDOR_COMMANDS
 };
 
 #if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \

+ 116 - 0
core/hdd/src/wlan_hdd_he.c

@@ -25,6 +25,7 @@
 
 #include "wlan_hdd_main.h"
 #include "wlan_hdd_he.h"
+#include "wma_he.h"
 
 /**
  * hdd_he_wni_cfg_to_string() - return string conversion of HE WNI CFG
@@ -336,3 +337,118 @@ void hdd_he_set_sme_config(tSmeConfigParams *sme_config,
 	sme_config->csrConfig.enable_ul_ofdma = config->enable_ul_ofdma;
 	sme_config->csrConfig.enable_ul_mimo = config->enable_ul_mimo;
 }
+
+/*
+ * __wlan_hdd_cfg80211_get_he_cap() - get HE Capabilities
+ * @wiphy: Pointer to wiphy
+ * @wdev: Pointer to wdev
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 if success, non-zero for failure
+ */
+static int
+__wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy,
+			       struct wireless_dev *wdev,
+			       const void *data,
+			       int data_len)
+{
+	hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+	int ret;
+	QDF_STATUS status;
+	struct sk_buff *reply_skb;
+	uint32_t nl_buf_len;
+	struct he_capability he_cap;
+	uint8_t he_supported = 0;
+
+	ENTER();
+	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (0 != ret)
+		return ret;
+
+	nl_buf_len = NLMSG_HDRLEN;
+	if (sme_is_feature_supported_by_fw(DOT11AX)) {
+		he_supported = 1;
+
+		status = wma_get_he_capabilities(&he_cap);
+		if (QDF_STATUS_SUCCESS != status)
+			return -EINVAL;
+	} else {
+		hdd_info("11AX: HE not supported, send only QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED");
+	}
+
+	if (he_supported) {
+		nl_buf_len += NLA_HDRLEN + sizeof(he_supported) +
+			      NLA_HDRLEN + sizeof(he_cap.phy_cap) +
+			      NLA_HDRLEN + sizeof(he_cap.mac_cap) +
+			      NLA_HDRLEN + sizeof(he_cap.mcs) +
+			      NLA_HDRLEN + sizeof(he_cap.ppet.numss_m1) +
+			      NLA_HDRLEN + sizeof(he_cap.ppet.ru_bit_mask) +
+			      NLA_HDRLEN +
+				sizeof(he_cap.ppet.ppet16_ppet8_ru3_ru0);
+	} else {
+		nl_buf_len += NLA_HDRLEN + sizeof(he_supported);
+	}
+
+	hdd_info("11AX: he_supported: %d", he_supported);
+
+	reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
+
+	if (!reply_skb) {
+		hdd_err("Allocate reply_skb failed");
+		return -EINVAL;
+	}
+
+	if (nla_put_u8(reply_skb,
+		       QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED, he_supported))
+		goto nla_put_failure;
+
+	/* No need to populate other attributes if HE is not supported */
+	if (0 == he_supported)
+		goto end;
+
+	if (nla_put_u32(reply_skb,
+			QCA_WLAN_VENDOR_ATTR_MAC_CAPAB, he_cap.mac_cap) ||
+	    nla_put_u32(reply_skb,
+			QCA_WLAN_VENDOR_ATTR_HE_MCS, he_cap.mcs) ||
+	    nla_put_u32(reply_skb,
+			QCA_WLAN_VENDOR_ATTR_NUM_SS, he_cap.ppet.numss_m1) ||
+	    nla_put_u32(reply_skb,
+			QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK,
+			he_cap.ppet.ru_bit_mask) ||
+	    nla_put(reply_skb,
+		    QCA_WLAN_VENDOR_ATTR_PHY_CAPAB,
+		    sizeof(u32) * HE_MAX_PHY_CAP_SIZE, he_cap.phy_cap) ||
+	    nla_put(reply_skb, QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD,
+		    sizeof(u32) * PSOC_HOST_MAX_NUM_SS,
+		    he_cap.ppet.ppet16_ppet8_ru3_ru0))
+		goto nla_put_failure;
+end:
+	ret = cfg80211_vendor_cmd_reply(reply_skb);
+	EXIT();
+	return ret;
+
+nla_put_failure:
+	hdd_err("nla put fail");
+	kfree_skb(reply_skb);
+	return -EINVAL;
+}
+
+int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy,
+				 struct wireless_dev *wdev,
+				 const void *data,
+				 int data_len)
+{
+	int ret;
+
+	cds_ssr_protect(__func__);
+	ret = __wlan_hdd_cfg80211_get_he_cap(wiphy, wdev, data, data_len);
+	cds_ssr_unprotect(__func__);
+
+	return ret;
+}

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

@@ -6919,6 +6919,21 @@ struct wow_enable_params {
 #define HE_PPET_SIZE 3
 #define HE_BYTE_SIZE 8
 
+#define HE_MAX_PHY_CAP_SIZE 3
+
+/**
+ * struct he_capability - to store 11ax HE capabilities
+ * @phy_cap: HE PHY capabilities
+ * @mac_cap: HE MAC capabilities
+ * @mcs: HE MCS
+ * @ppet: HE PPE threshold
+ */
+struct he_capability {
+	uint32_t phy_cap[HE_MAX_PHY_CAP_SIZE];
+	uint32_t mac_cap;
+	uint32_t mcs;
+	struct wlan_psoc_host_ppe_threshold ppet;
+};
 #endif
 
 /**

+ 4 - 0
core/wma/inc/wma.h

@@ -1566,6 +1566,10 @@ typedef struct {
 	tp_wma_packetdump_cb wma_mgmt_tx_packetdump_cb;
 	tp_wma_packetdump_cb wma_mgmt_rx_packetdump_cb;
 	tSirLLStatsResults *link_stats_results;
+
+#ifdef WLAN_FEATURE_11AX
+	struct he_capability he_cap;
+#endif
 } t_wma_handle, *tp_wma_handle;
 
 /**

+ 13 - 0
core/wma/inc/wma_he.h

@@ -51,6 +51,19 @@ static inline bool wma_is_peer_he_capable(tpAddStaParams params)
 void wma_update_vdev_he_capable(struct wma_vdev_start_req *req,
 		tpSwitchChannelParams params);
 
+/**
+ * wma_get_he_capabilities() - Get HE capabilities from WMA
+ * @he_cap: Pointer to HE capabilities
+ *
+ * Currently HE capabilities are not updated in wma_handle. This
+ * is an interface for upper layer to query capabilities from WMA.
+ * When the real use case arise, update wma_handle with HE capabilities
+ * as required.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wma_get_he_capabilities(struct he_capability *he_cap);
+
 #else
 static inline void wma_print_he_cap(tDot11fIEvendor_he_cap *he_cap)
 {

+ 25 - 0
core/wma/src/wma_he.c

@@ -1096,3 +1096,28 @@ void wma_update_vdev_he_capable(struct wma_vdev_start_req *req,
 {
 	req->he_capable = params->he_capable;
 }
+
+QDF_STATUS wma_get_he_capabilities(struct he_capability *he_cap)
+{
+	tp_wma_handle wma_handle;
+
+	wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
+	if (!wma_handle) {
+		WMA_LOGE(FL("Invalid WMA handle"));
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	qdf_mem_copy(he_cap->phy_cap,
+		     &wma_handle->he_cap.phy_cap,
+		     WMI_MAX_HECAP_PHY_SIZE);
+	he_cap->mac_cap = wma_handle->he_cap.mac_cap;
+	he_cap->mcs = wma_handle->he_cap.mcs;
+
+	he_cap->ppet.numss_m1 = wma_handle->he_cap.ppet.numss_m1;
+	he_cap->ppet.ru_bit_mask = wma_handle->he_cap.ppet.ru_bit_mask;
+	qdf_mem_copy(&he_cap->ppet.ppet16_ppet8_ru3_ru0,
+		     &wma_handle->he_cap.ppet.ppet16_ppet8_ru3_ru0,
+		     WMI_MAX_NUM_SS);
+
+	return QDF_STATUS_SUCCESS;
+}