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
This commit is contained in:
Krishna Kumaar Natarajan 2017-03-06 10:28:44 -08:00 • committed by Sandeep Puligilla
commit f567650ade
7 changed files with 235 additions and 0 deletions

View file

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

View file

@ -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)) || \

View file

@ -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;
}

View file

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

View file

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

View file

@ -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)
{

View file

@ -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;
}