diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h index af178d612dad..dd80ca27750a 100644 --- a/core/hdd/inc/wlan_hdd_assoc.h +++ b/core/hdd/inc/wlan_hdd_assoc.h @@ -170,6 +170,8 @@ struct hdd_conn_flag { * @auth_time: last authentication established time * @connect_time: last association established time * @ch_width: channel width of operating channel + * @max_tx_bitrate: Max tx bitrate supported by the AP + * to which currently sta is connected. */ struct hdd_connection_info { eConnectionState conn_state; @@ -206,6 +208,7 @@ struct hdd_connection_info { char auth_time[HDD_TIME_STRING_LEN]; char connect_time[HDD_TIME_STRING_LEN]; enum phy_ch_width ch_width; + struct rate_info max_tx_bitrate; }; /* Forward declarations */ diff --git a/core/hdd/src/wlan_hdd_station_info.c b/core/hdd/src/wlan_hdd_station_info.c index 9876b5cf78f3..b559de0f7121 100644 --- a/core/hdd/src/wlan_hdd_station_info.c +++ b/core/hdd/src/wlan_hdd_station_info.c @@ -320,9 +320,12 @@ static int32_t hdd_add_tx_bitrate(struct sk_buff *skb, } /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */ - bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx-> - cache_conn_info.txrate); - + if (hdd_conn_is_connected(hdd_sta_ctx)) + bitrate = cfg80211_calculate_bitrate( + &hdd_sta_ctx->cache_conn_info.max_tx_bitrate); + else + bitrate = cfg80211_calculate_bitrate( + &hdd_sta_ctx->cache_conn_info.txrate); /* report 16-bit bitrate only if we can */ bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0; @@ -356,6 +359,53 @@ fail: return -EINVAL; } +/** + * hdd_get_max_tx_bitrate() - Get the max tx bitrate of the AP + * @hdd_ctx: hdd context + * @adapter: hostapd interface + * + * THis function gets the MAX supported rate by AP and cache + * it into connection info structure + * + * Return: None + */ +static void hdd_get_max_tx_bitrate(struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter) +{ + struct station_info sinfo; + uint8_t tx_rate_flags, tx_mcs_index, tx_nss = 1; + uint16_t my_tx_rate; + struct hdd_station_ctx *hdd_sta_ctx; + + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + + qdf_mem_zero(&sinfo, sizeof(struct station_info)); + + sinfo.signal = adapter->rssi; + tx_rate_flags = adapter->hdd_stats.class_a_stat.tx_rx_rate_flags; + tx_mcs_index = adapter->hdd_stats.class_a_stat.tx_mcs_index; + my_tx_rate = adapter->hdd_stats.class_a_stat.tx_rate; + + if (!(tx_rate_flags & TX_RATE_LEGACY)) { + tx_nss = adapter->hdd_stats.class_a_stat.tx_nss; + if (tx_nss > 1 && + policy_mgr_is_current_hwmode_dbs(hdd_ctx->psoc) && + !policy_mgr_is_hw_dbs_2x2_capable(hdd_ctx->psoc)) { + hdd_debug("Hw mode is DBS, Reduce nss(%d) to 1", + tx_nss); + tx_nss--; + } + } + if (hdd_report_max_rate(hdd_ctx->mac_handle, &sinfo, + tx_rate_flags, tx_mcs_index, + my_tx_rate, tx_nss)) { + hdd_sta_ctx->cache_conn_info.max_tx_bitrate = sinfo.txrate; + hdd_debug("Reporting max tx rate flags %d mcs %d nss %d bw %d", + sinfo.txrate.flags, sinfo.txrate.mcs, + sinfo.txrate.nss, sinfo.txrate.bw); + } +} + /** * hdd_add_sta_info() - add station info attribute * @skb: pointer to sk buff @@ -365,10 +415,18 @@ fail: * Return: Success(0) or reason code for failure */ static int32_t hdd_add_sta_info(struct sk_buff *skb, - struct hdd_station_ctx *hdd_sta_ctx, + struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter, int idx) { struct nlattr *nla_attr; + struct hdd_station_ctx *hdd_sta_ctx; + + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (!hdd_sta_ctx) { + hdd_err("Invalid sta ctx"); + goto fail; + } nla_attr = nla_nest_start(skb, idx); if (!nla_attr) { @@ -381,6 +439,9 @@ static int32_t hdd_add_sta_info(struct sk_buff *skb, hdd_err("put fail"); goto fail; } + if (hdd_conn_is_connected(hdd_sta_ctx)) + hdd_get_max_tx_bitrate(hdd_ctx, adapter); + if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE)) { hdd_err("hdd_add_tx_bitrate failed"); goto fail; @@ -432,9 +493,17 @@ fail: */ static int32_t hdd_add_link_standard_info(struct sk_buff *skb, - struct hdd_station_ctx *hdd_sta_ctx, int idx) + struct hdd_context *hdd_ctx, + struct hdd_adapter *adapter, int idx) { struct nlattr *nla_attr; + struct hdd_station_ctx *hdd_sta_ctx; + + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (!hdd_sta_ctx) { + hdd_err("Invalid sta ctx"); + goto fail; + } nla_attr = nla_nest_start(skb, idx); if (!nla_attr) { @@ -459,7 +528,7 @@ hdd_add_link_standard_info(struct sk_buff *skb, goto fail; } - if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO)) { + if (hdd_add_sta_info(skb, hdd_ctx, adapter, NL80211_ATTR_STA_INFO)) { hdd_err("hdd_add_sta_info failed"); goto fail; } @@ -558,7 +627,7 @@ static int hdd_get_station_info(struct hdd_context *hdd_ctx, return -ENOMEM; } - if (hdd_add_link_standard_info(skb, hdd_sta_ctx, + if (hdd_add_link_standard_info(skb, hdd_ctx, adapter, LINK_INFO_STANDARD_NL80211_ATTR)) { hdd_err("put fail"); goto fail; diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c index 3472db354433..37f7df3d6840 100644 --- a/core/hdd/src/wlan_hdd_stats.c +++ b/core/hdd/src/wlan_hdd_stats.c @@ -3935,24 +3935,11 @@ static int wlan_hdd_get_station_remote(struct wiphy *wiphy, return status; } -/** - * hdd_report_max_rate() - Fill the max rate stats in the station info structure - * to be sent to the userspace. - * - * @mac_handle: The mac handle - * @sinfo: The station_info struct to be filled - * @tx_rate_flags: The TX rate flags computed from tx rate - * @tx_mcs_index; The TX mcs index computed from tx rate - * @my_tx_rate: The tx_rate from fw stats - * @tx_nss: The TX NSS from fw stats - * - * Return: 0 for success - */ -static int hdd_report_max_rate(mac_handle_t mac_handle, - struct station_info *sinfo, - uint8_t tx_rate_flags, - uint8_t tx_mcs_index, - uint16_t my_tx_rate, uint8_t tx_nss) +int hdd_report_max_rate(mac_handle_t mac_handle, + struct station_info *sinfo, + uint8_t tx_rate_flags, + uint8_t tx_mcs_index, + uint16_t my_tx_rate, uint8_t tx_nss) { uint8_t i, j, rssidx; uint16_t max_rate = 0; diff --git a/core/hdd/src/wlan_hdd_stats.h b/core/hdd/src/wlan_hdd_stats.h index bf5d8fc83d8b..6d38d5711dea 100644 --- a/core/hdd/src/wlan_hdd_stats.h +++ b/core/hdd/src/wlan_hdd_stats.h @@ -464,4 +464,24 @@ int wlan_hdd_get_temperature(struct hdd_adapter *adapter, int *temperature); * Return: none */ void wlan_hdd_display_txrx_stats(struct hdd_context *hdd_ctx); + +/** + * hdd_report_max_rate() - Fill the max rate stats in the station info structure + * to be sent to the userspace. + * + * @mac_handle: The mac handle + * @sinfo: The station_info struct to be filled + * @tx_rate_flags: The TX rate flags computed from tx rate + * @tx_mcs_index; The TX mcs index computed from tx rate + * @my_tx_rate: The tx_rate from fw stats + * @tx_nss: The TX NSS from fw stats + * + * Return: 0 for success + */ +int hdd_report_max_rate(mac_handle_t mac_handle, + struct station_info *sinfo, + uint8_t tx_rate_flags, + uint8_t tx_mcs_index, + uint16_t my_tx_rate, uint8_t tx_nss); + #endif /* end #if !defined(WLAN_HDD_STATS_H) */