summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/wcn36xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/wcn36xx')
-rw-r--r--drivers/net/wireless/ath/wcn36xx/hal.h7
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c160
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c98
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.h2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/txrx.c29
-rw-r--r--drivers/net/wireless/ath/wcn36xx/txrx.h1
6 files changed, 207 insertions, 90 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h
index 2a1db9756fd5..46a49f0a51b3 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -2626,7 +2626,12 @@ enum tx_rate_info {
HAL_TX_RATE_SGI = 0x8,
/* Rate with Long guard interval */
- HAL_TX_RATE_LGI = 0x10
+ HAL_TX_RATE_LGI = 0x10,
+
+ /* VHT rates */
+ HAL_TX_RATE_VHT20 = 0x20,
+ HAL_TX_RATE_VHT40 = 0x40,
+ HAL_TX_RATE_VHT80 = 0x80,
};
struct ani_global_class_a_stats_info {
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 95ea7d040d8c..e34d3d0b7082 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -192,70 +192,74 @@ static inline u8 get_sta_index(struct ieee80211_vif *vif,
sta_priv->sta_index;
}
+#define DEFINE(s) [s] = #s
+
static const char * const wcn36xx_caps_names[] = {
- "MCC", /* 0 */
- "P2P", /* 1 */
- "DOT11AC", /* 2 */
- "SLM_SESSIONIZATION", /* 3 */
- "DOT11AC_OPMODE", /* 4 */
- "SAP32STA", /* 5 */
- "TDLS", /* 6 */
- "P2P_GO_NOA_DECOUPLE_INIT_SCAN",/* 7 */
- "WLANACTIVE_OFFLOAD", /* 8 */
- "BEACON_OFFLOAD", /* 9 */
- "SCAN_OFFLOAD", /* 10 */
- "ROAM_OFFLOAD", /* 11 */
- "BCN_MISS_OFFLOAD", /* 12 */
- "STA_POWERSAVE", /* 13 */
- "STA_ADVANCED_PWRSAVE", /* 14 */
- "AP_UAPSD", /* 15 */
- "AP_DFS", /* 16 */
- "BLOCKACK", /* 17 */
- "PHY_ERR", /* 18 */
- "BCN_FILTER", /* 19 */
- "RTT", /* 20 */
- "RATECTRL", /* 21 */
- "WOW", /* 22 */
- "WLAN_ROAM_SCAN_OFFLOAD", /* 23 */
- "SPECULATIVE_PS_POLL", /* 24 */
- "SCAN_SCH", /* 25 */
- "IBSS_HEARTBEAT_OFFLOAD", /* 26 */
- "WLAN_SCAN_OFFLOAD", /* 27 */
- "WLAN_PERIODIC_TX_PTRN", /* 28 */
- "ADVANCE_TDLS", /* 29 */
- "BATCH_SCAN", /* 30 */
- "FW_IN_TX_PATH", /* 31 */
- "EXTENDED_NSOFFLOAD_SLOT", /* 32 */
- "CH_SWITCH_V1", /* 33 */
- "HT40_OBSS_SCAN", /* 34 */
- "UPDATE_CHANNEL_LIST", /* 35 */
- "WLAN_MCADDR_FLT", /* 36 */
- "WLAN_CH144", /* 37 */
- "NAN", /* 38 */
- "TDLS_SCAN_COEXISTENCE", /* 39 */
- "LINK_LAYER_STATS_MEAS", /* 40 */
- "MU_MIMO", /* 41 */
- "EXTENDED_SCAN", /* 42 */
- "DYNAMIC_WMM_PS", /* 43 */
- "MAC_SPOOFED_SCAN", /* 44 */
- "BMU_ERROR_GENERIC_RECOVERY", /* 45 */
- "DISA", /* 46 */
- "FW_STATS", /* 47 */
- "WPS_PRBRSP_TMPL", /* 48 */
- "BCN_IE_FLT_DELTA", /* 49 */
- "TDLS_OFF_CHANNEL", /* 51 */
- "RTT3", /* 52 */
- "MGMT_FRAME_LOGGING", /* 53 */
- "ENHANCED_TXBD_COMPLETION", /* 54 */
- "LOGGING_ENHANCEMENT", /* 55 */
- "EXT_SCAN_ENHANCED", /* 56 */
- "MEMORY_DUMP_SUPPORTED", /* 57 */
- "PER_PKT_STATS_SUPPORTED", /* 58 */
- "EXT_LL_STAT", /* 60 */
- "WIFI_CONFIG", /* 61 */
- "ANTENNA_DIVERSITY_SELECTION", /* 62 */
+ DEFINE(MCC),
+ DEFINE(P2P),
+ DEFINE(DOT11AC),
+ DEFINE(SLM_SESSIONIZATION),
+ DEFINE(DOT11AC_OPMODE),
+ DEFINE(SAP32STA),
+ DEFINE(TDLS),
+ DEFINE(P2P_GO_NOA_DECOUPLE_INIT_SCAN),
+ DEFINE(WLANACTIVE_OFFLOAD),
+ DEFINE(BEACON_OFFLOAD),
+ DEFINE(SCAN_OFFLOAD),
+ DEFINE(ROAM_OFFLOAD),
+ DEFINE(BCN_MISS_OFFLOAD),
+ DEFINE(STA_POWERSAVE),
+ DEFINE(STA_ADVANCED_PWRSAVE),
+ DEFINE(AP_UAPSD),
+ DEFINE(AP_DFS),
+ DEFINE(BLOCKACK),
+ DEFINE(PHY_ERR),
+ DEFINE(BCN_FILTER),
+ DEFINE(RTT),
+ DEFINE(RATECTRL),
+ DEFINE(WOW),
+ DEFINE(WLAN_ROAM_SCAN_OFFLOAD),
+ DEFINE(SPECULATIVE_PS_POLL),
+ DEFINE(SCAN_SCH),
+ DEFINE(IBSS_HEARTBEAT_OFFLOAD),
+ DEFINE(WLAN_SCAN_OFFLOAD),
+ DEFINE(WLAN_PERIODIC_TX_PTRN),
+ DEFINE(ADVANCE_TDLS),
+ DEFINE(BATCH_SCAN),
+ DEFINE(FW_IN_TX_PATH),
+ DEFINE(EXTENDED_NSOFFLOAD_SLOT),
+ DEFINE(CH_SWITCH_V1),
+ DEFINE(HT40_OBSS_SCAN),
+ DEFINE(UPDATE_CHANNEL_LIST),
+ DEFINE(WLAN_MCADDR_FLT),
+ DEFINE(WLAN_CH144),
+ DEFINE(NAN),
+ DEFINE(TDLS_SCAN_COEXISTENCE),
+ DEFINE(LINK_LAYER_STATS_MEAS),
+ DEFINE(MU_MIMO),
+ DEFINE(EXTENDED_SCAN),
+ DEFINE(DYNAMIC_WMM_PS),
+ DEFINE(MAC_SPOOFED_SCAN),
+ DEFINE(BMU_ERROR_GENERIC_RECOVERY),
+ DEFINE(DISA),
+ DEFINE(FW_STATS),
+ DEFINE(WPS_PRBRSP_TMPL),
+ DEFINE(BCN_IE_FLT_DELTA),
+ DEFINE(TDLS_OFF_CHANNEL),
+ DEFINE(RTT3),
+ DEFINE(MGMT_FRAME_LOGGING),
+ DEFINE(ENHANCED_TXBD_COMPLETION),
+ DEFINE(LOGGING_ENHANCEMENT),
+ DEFINE(EXT_SCAN_ENHANCED),
+ DEFINE(MEMORY_DUMP_SUPPORTED),
+ DEFINE(PER_PKT_STATS_SUPPORTED),
+ DEFINE(EXT_LL_STAT),
+ DEFINE(WIFI_CONFIG),
+ DEFINE(ANTENNA_DIVERSITY_SELECTION),
};
+#undef DEFINE
+
static const char *wcn36xx_get_cap_name(enum place_holder_in_cap_bitmap x)
{
if (x >= ARRAY_SIZE(wcn36xx_caps_names))
@@ -788,7 +792,7 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
int i, size;
u16 *rates_table;
struct wcn36xx_sta *sta_priv = wcn36xx_sta_to_priv(sta);
- u32 rates = sta->supp_rates[band];
+ u32 rates = sta->deflink.supp_rates[band];
memset(&sta_priv->supported_rates, 0,
sizeof(sta_priv->supported_rates));
@@ -814,20 +818,20 @@ static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
}
}
- if (sta->ht_cap.ht_supported) {
- BUILD_BUG_ON(sizeof(sta->ht_cap.mcs.rx_mask) >
- sizeof(sta_priv->supported_rates.supported_mcs_set));
+ if (sta->deflink.ht_cap.ht_supported) {
+ BUILD_BUG_ON(sizeof(sta->deflink.ht_cap.mcs.rx_mask) >
+ sizeof(sta_priv->supported_rates.supported_mcs_set));
memcpy(sta_priv->supported_rates.supported_mcs_set,
- sta->ht_cap.mcs.rx_mask,
- sizeof(sta->ht_cap.mcs.rx_mask));
+ sta->deflink.ht_cap.mcs.rx_mask,
+ sizeof(sta->deflink.ht_cap.mcs.rx_mask));
}
- if (sta->vht_cap.vht_supported) {
+ if (sta->deflink.vht_cap.vht_supported) {
sta_priv->supported_rates.op_rate_mode = STA_11ac;
sta_priv->supported_rates.vht_rx_mcs_map =
- sta->vht_cap.vht_mcs.rx_mcs_map;
+ sta->deflink.vht_cap.vht_mcs.rx_mcs_map;
sta_priv->supported_rates.vht_tx_mcs_map =
- sta->vht_cap.vht_mcs.tx_mcs_map;
+ sta->deflink.vht_cap.vht_mcs.tx_mcs_map;
}
}
@@ -1400,6 +1404,21 @@ static int wcn36xx_get_survey(struct ieee80211_hw *hw, int idx,
return 0;
}
+static void wcn36xx_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, struct station_info *sinfo)
+{
+ struct wcn36xx *wcn;
+ u8 sta_index;
+ int status;
+
+ wcn = hw->priv;
+ sta_index = get_sta_index(vif, wcn36xx_sta_to_priv(sta));
+ status = wcn36xx_smd_get_stats(wcn, sta_index, HAL_GLOBAL_CLASS_A_STATS_INFO, sinfo);
+
+ if (status)
+ wcn36xx_err("wcn36xx_smd_get_stats failed\n");
+}
+
static const struct ieee80211_ops wcn36xx_ops = {
.start = wcn36xx_start,
.stop = wcn36xx_stop,
@@ -1423,6 +1442,7 @@ static const struct ieee80211_ops wcn36xx_ops = {
.set_rts_threshold = wcn36xx_set_rts_threshold,
.sta_add = wcn36xx_sta_add,
.sta_remove = wcn36xx_sta_remove,
+ .sta_statistics = wcn36xx_sta_statistics,
.ampdu_action = wcn36xx_ampdu_action,
#if IS_ENABLED(CONFIG_IPV6)
.ipv6_addr_change = wcn36xx_ipv6_addr_change,
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 59ad332156ae..7ac9a1e6f768 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -208,9 +208,9 @@ static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
{
if (NL80211_BAND_5GHZ == WCN36XX_BAND(wcn))
bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
- else if (sta && sta->ht_cap.ht_supported)
+ else if (sta && sta->deflink.ht_cap.ht_supported)
bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
- else if (sta && (sta->supp_rates[NL80211_BAND_2GHZ] & 0x7f))
+ else if (sta && (sta->deflink.supp_rates[NL80211_BAND_2GHZ] & 0x7f))
bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
else
bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
@@ -225,9 +225,10 @@ static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct wcn36xx_hal_config_bss_params *bss_params)
{
- if (sta && sta->ht_cap.ht_supported) {
- unsigned long caps = sta->ht_cap.cap;
- bss_params->ht = sta->ht_cap.ht_supported;
+ if (sta && sta->deflink.ht_cap.ht_supported) {
+ unsigned long caps = sta->deflink.ht_cap.cap;
+
+ bss_params->ht = sta->deflink.ht_cap.ht_supported;
bss_params->tx_channel_width_set = is_cap_supported(caps,
IEEE80211_HT_CAP_SUP_WIDTH_20_40);
bss_params->lsig_tx_op_protection_full_support =
@@ -250,23 +251,24 @@ wcn36xx_smd_set_bss_vht_params(struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct wcn36xx_hal_config_bss_params_v1 *bss)
{
- if (sta && sta->vht_cap.vht_supported)
+ if (sta && sta->deflink.vht_cap.vht_supported)
bss->vht_capable = 1;
}
static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
struct wcn36xx_hal_config_sta_params *sta_params)
{
- if (sta->ht_cap.ht_supported) {
- unsigned long caps = sta->ht_cap.cap;
- sta_params->ht_capable = sta->ht_cap.ht_supported;
+ if (sta->deflink.ht_cap.ht_supported) {
+ unsigned long caps = sta->deflink.ht_cap.cap;
+
+ sta_params->ht_capable = sta->deflink.ht_cap.ht_supported;
sta_params->tx_channel_width_set = is_cap_supported(caps,
IEEE80211_HT_CAP_SUP_WIDTH_20_40);
sta_params->lsig_txop_protection = is_cap_supported(caps,
IEEE80211_HT_CAP_LSIG_TXOP_PROT);
- sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor;
- sta_params->max_ampdu_density = sta->ht_cap.ampdu_density;
+ sta_params->max_ampdu_size = sta->deflink.ht_cap.ampdu_factor;
+ sta_params->max_ampdu_density = sta->deflink.ht_cap.ampdu_density;
/* max_amsdu_size: 1 : 3839 bytes, 0 : 7935 bytes (max) */
sta_params->max_amsdu_size = !is_cap_supported(caps,
IEEE80211_HT_CAP_MAX_AMSDU);
@@ -287,10 +289,10 @@ static void wcn36xx_smd_set_sta_vht_params(struct wcn36xx *wcn,
struct ieee80211_sta *sta,
struct wcn36xx_hal_config_sta_params_v1 *sta_params)
{
- if (sta->vht_cap.vht_supported) {
- unsigned long caps = sta->vht_cap.cap;
+ if (sta->deflink.vht_cap.vht_supported) {
+ unsigned long caps = sta->deflink.vht_cap.cap;
- sta_params->vht_capable = sta->vht_cap.vht_supported;
+ sta_params->vht_capable = sta->deflink.vht_cap.vht_supported;
sta_params->vht_ldpc_enabled =
is_cap_supported(caps, IEEE80211_VHT_CAP_RXLDPC);
if (get_feat_caps(wcn->fw_feat_caps, MU_MIMO)) {
@@ -308,9 +310,10 @@ static void wcn36xx_smd_set_sta_vht_params(struct wcn36xx *wcn,
static void wcn36xx_smd_set_sta_ht_ldpc_params(struct ieee80211_sta *sta,
struct wcn36xx_hal_config_sta_params_v1 *sta_params)
{
- if (sta->ht_cap.ht_supported) {
+ if (sta->deflink.ht_cap.ht_supported) {
sta_params->ht_ldpc_enabled =
- is_cap_supported(sta->ht_cap.cap, IEEE80211_HT_CAP_LDPC_CODING);
+ is_cap_supported(sta->deflink.ht_cap.cap,
+ IEEE80211_HT_CAP_LDPC_CODING);
}
}
@@ -2627,6 +2630,62 @@ out:
return ret;
}
+int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask,
+ struct station_info *sinfo)
+{
+ struct wcn36xx_hal_stats_req_msg msg_body;
+ struct wcn36xx_hal_stats_rsp_msg *rsp;
+ void *rsp_body;
+ int ret;
+
+ if (stats_mask & ~HAL_GLOBAL_CLASS_A_STATS_INFO) {
+ wcn36xx_err("stats_mask 0x%x contains unimplemented types\n",
+ stats_mask);
+ return -EINVAL;
+ }
+
+ mutex_lock(&wcn->hal_mutex);
+ INIT_HAL_MSG(msg_body, WCN36XX_HAL_GET_STATS_REQ);
+
+ msg_body.sta_id = sta_index;
+ msg_body.stats_mask = stats_mask;
+
+ PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
+
+ ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
+ if (ret) {
+ wcn36xx_err("sending hal_get_stats failed\n");
+ goto out;
+ }
+
+ ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
+ if (ret) {
+ wcn36xx_err("hal_get_stats response failed err=%d\n", ret);
+ goto out;
+ }
+
+ rsp = (struct wcn36xx_hal_stats_rsp_msg *)wcn->hal_buf;
+ rsp_body = (wcn->hal_buf + sizeof(struct wcn36xx_hal_stats_rsp_msg));
+
+ if (rsp->stats_mask != stats_mask) {
+ wcn36xx_err("stats_mask 0x%x differs from requested 0x%x\n",
+ rsp->stats_mask, stats_mask);
+ goto out;
+ }
+
+ if (rsp->stats_mask & HAL_GLOBAL_CLASS_A_STATS_INFO) {
+ struct ani_global_class_a_stats_info *stats_info = rsp_body;
+
+ wcn36xx_process_tx_rate(stats_info, &sinfo->txrate);
+ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+ rsp_body += sizeof(struct ani_global_class_a_stats_info);
+ }
+out:
+ mutex_unlock(&wcn->hal_mutex);
+
+ return ret;
+}
+
static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info)
{
struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate;
@@ -3092,9 +3151,9 @@ static int wcn36xx_smd_gtk_offload_get_info_rsp(struct wcn36xx *wcn,
cpu_to_le64(rsp->key_replay_counter);
ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
(void *)&replay_ctr, GFP_KERNEL);
- wcn36xx_dbg(WCN36XX_DBG_HAL,
- "GTK replay counter increment %llu\n",
- rsp->key_replay_counter);
+ wcn36xx_dbg(WCN36XX_DBG_HAL,
+ "GTK replay counter increment %llu\n",
+ rsp->key_replay_counter);
}
wcn36xx_dbg(WCN36XX_DBG_HAL,
@@ -3316,6 +3375,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
case WCN36XX_HAL_ADD_BA_SESSION_RSP:
case WCN36XX_HAL_ADD_BA_RSP:
case WCN36XX_HAL_DEL_BA_RSP:
+ case WCN36XX_HAL_GET_STATS_RSP:
case WCN36XX_HAL_TRIGGER_BA_RSP:
case WCN36XX_HAL_UPDATE_CFG_RSP:
case WCN36XX_HAL_JOIN_RSP:
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index 957cfa87fbde..3fd598ac2a27 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -138,6 +138,8 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id);
int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index);
int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn);
+int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask,
+ struct station_info *sinfo);
int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value);
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c
index df749b114568..8da3955995b6 100644
--- a/drivers/net/wireless/ath/wcn36xx/txrx.c
+++ b/drivers/net/wireless/ath/wcn36xx/txrx.c
@@ -699,3 +699,32 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
return ret;
}
+
+void wcn36xx_process_tx_rate(struct ani_global_class_a_stats_info *stats, struct rate_info *info)
+{
+ /* tx_rate is in units of 500kbps; mac80211 wants them in 100kbps */
+ if (stats->tx_rate_flags & HAL_TX_RATE_LEGACY)
+ info->legacy = stats->tx_rate * 5;
+
+ info->flags = 0;
+ info->mcs = stats->mcs_index;
+ info->nss = 1;
+
+ if (stats->tx_rate_flags & (HAL_TX_RATE_HT20 | HAL_TX_RATE_HT40))
+ info->flags |= RATE_INFO_FLAGS_MCS;
+
+ if (stats->tx_rate_flags & (HAL_TX_RATE_VHT20 | HAL_TX_RATE_VHT40 | HAL_TX_RATE_VHT80))
+ info->flags |= RATE_INFO_FLAGS_VHT_MCS;
+
+ if (stats->tx_rate_flags & HAL_TX_RATE_SGI)
+ info->flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+ if (stats->tx_rate_flags & (HAL_TX_RATE_HT20 | HAL_TX_RATE_VHT20))
+ info->bw = RATE_INFO_BW_20;
+
+ if (stats->tx_rate_flags & (HAL_TX_RATE_HT40 | HAL_TX_RATE_VHT40))
+ info->bw = RATE_INFO_BW_40;
+
+ if (stats->tx_rate_flags & HAL_TX_RATE_VHT80)
+ info->bw = RATE_INFO_BW_80;
+}
diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.h b/drivers/net/wireless/ath/wcn36xx/txrx.h
index b54311ffde9c..fb0d6cabd52b 100644
--- a/drivers/net/wireless/ath/wcn36xx/txrx.h
+++ b/drivers/net/wireless/ath/wcn36xx/txrx.h
@@ -164,5 +164,6 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb);
int wcn36xx_start_tx(struct wcn36xx *wcn,
struct wcn36xx_sta *sta_priv,
struct sk_buff *skb);
+void wcn36xx_process_tx_rate(struct ani_global_class_a_stats_info *stats, struct rate_info *info);
#endif /* _TXRX_H_ */