diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 7fb3f985589f..603b864ad554 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -386,6 +386,7 @@ struct ath11k_sta { u64 rx_duration; u64 tx_duration; u8 rssi_comb; + s8 rssi_beacon; s8 chain_signal[IEEE80211_MAX_CHAINS]; struct ath11k_htt_tx_stats *tx_stats; struct ath11k_rx_peer_stats *rx_stats; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index ef4859a5887b..f135a3dd2f4e 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -7811,6 +7811,9 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, { struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv; struct ath11k *ar = arsta->arvif->ar; + s8 signal; + bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT, + ar->ab->wmi_ab.svc_map); sinfo->rx_duration = arsta->rx_duration; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION); @@ -7843,9 +7846,22 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true); } - /* TODO: Use real NF instead of default one. */ - sinfo->signal = arsta->rssi_comb + ATH11K_DEFAULT_NOISE_FLOOR; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); + signal = arsta->rssi_comb; + if (!signal && + arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA && + ar->ab->hw_params.supports_rssi_stats && + !(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0, + WMI_REQUEST_VDEV_STAT))) + signal = arsta->rssi_beacon; + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, + "mac sta statistics db2dbm %u rssi comb %d rssi beacon %d\n", + db2dbm, arsta->rssi_comb, arsta->rssi_beacon); + + if (signal) { + sinfo->signal = db2dbm ? signal : signal + ATH11K_DEFAULT_NOISE_FLOOR; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); + } } static const struct ieee80211_ops ath11k_ops = { diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index b7bdc37f24fd..6d92bb9483be 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -5639,7 +5639,11 @@ static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab, { struct ath11k_fw_stats *stats = parse->stats; const struct wmi_stats_event *ev = parse->ev; - int i; + struct ath11k *ar; + struct ath11k_vif *arvif; + struct ieee80211_sta *sta; + struct ath11k_sta *arsta; + int i, ret = 0; const void *data = ptr; if (!ev) { @@ -5649,13 +5653,19 @@ static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab, stats->stats_id = 0; + rcu_read_lock(); + + ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id); + for (i = 0; i < ev->num_pdev_stats; i++) { const struct wmi_pdev_stats *src; struct ath11k_fw_stats_pdev *dst; src = data; - if (len < sizeof(*src)) - return -EPROTO; + if (len < sizeof(*src)) { + ret = -EPROTO; + goto exit; + } stats->stats_id = WMI_REQUEST_PDEV_STAT; @@ -5677,11 +5687,30 @@ static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab, struct ath11k_fw_stats_vdev *dst; src = data; - if (len < sizeof(*src)) - return -EPROTO; + if (len < sizeof(*src)) { + ret = -EPROTO; + goto exit; + } stats->stats_id = WMI_REQUEST_VDEV_STAT; + arvif = ath11k_mac_get_arvif(ar, src->vdev_id); + if (arvif) { + sta = ieee80211_find_sta_by_ifaddr(ar->hw, + arvif->bssid, + NULL); + if (sta) { + arsta = (struct ath11k_sta *)sta->drv_priv; + arsta->rssi_beacon = src->beacon_snr; + ath11k_dbg(ab, ATH11K_DBG_WMI, + "wmi stats vdev id %d snr %d\n", + src->vdev_id, src->beacon_snr); + } else { + ath11k_warn(ab, "not found station for bssid %pM\n", + arvif->bssid); + } + } + data += sizeof(*src); len -= sizeof(*src); @@ -5698,8 +5727,10 @@ static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab, struct ath11k_fw_stats_bcn *dst; src = data; - if (len < sizeof(*src)) - return -EPROTO; + if (len < sizeof(*src)) { + ret = -EPROTO; + goto exit; + } stats->stats_id = WMI_REQUEST_BCN_STAT; @@ -5714,7 +5745,9 @@ static int ath11k_wmi_tlv_fw_stats_data_parse(struct ath11k_base *ab, list_add_tail(&dst->list, &stats->bcn); } - return 0; +exit: + rcu_read_unlock(); + return ret; } static int ath11k_wmi_tlv_fw_stats_parse(struct ath11k_base *ab,