Skip to content

Commit

Permalink
ath11k: report rssi of each chain to mac80211 for QCA6390/WCN6855
Browse files Browse the repository at this point in the history
Command "iw wls1 station dump" does not show each chain's rssi currently.

If the rssi of each chain from mon status which parsed in function
ath11k_hal_rx_parse_mon_status_tlv() is invalid, then ath11k send
wmi cmd WMI_REQUEST_STATS_CMDID with flag WMI_REQUEST_RSSI_PER_CHAIN_STAT
to firmware, and parse the rssi of chain in wmi WMI_UPDATE_STATS_EVENTID,
then report them to mac80211.

WMI_REQUEST_STATS_CMDID is only sent when CONFIG_ATH11K_DEBUGFS is set,
it is only called by ath11k_mac_op_sta_statistics(). It does not effect
performance and power consumption. Because after STATION connected to
AP, it is only called every 6 seconds by NetworkManager in below stack.

[  797.005587] CPU: 0 PID: 701 Comm: NetworkManager Tainted: G        W  OE     5.13.0-rc6-wt-ath+ #2
[  797.005596] Hardware name: LENOVO 418065C/418065C, BIOS 83ET63WW (1.33 ) 07/29/2011
[  797.005600] RIP: 0010:ath11k_mac_op_sta_statistics+0x2f/0x1b0 [ath11k]
[  797.005644] Code: 41 56 41 55 4c 8d aa 58 01 00 00 41 54 55 48 89 d5 53 48 8b 82 58 01 00 00 48 89 cb 4c 8b 70 20 49 8b 06 4c 8b a0 90 08 00 00 <0f> 0b 48 8b 82 b8 01 00 00 48 ba 00 00 00 00 01 00 00 00 48 89 81
[  797.005651] RSP: 0018:ffffb1fc80a4b890 EFLAGS: 00010282
[  797.005658] RAX: ffff8a5726200000 RBX: ffffb1fc80a4b958 RCX: ffffb1fc80a4b958
[  797.005664] RDX: ffff8a5726a609f0 RSI: ffff8a581247f598 RDI: ffff8a5702878800
[  797.005668] RBP: ffff8a5726a609f0 R08: 0000000000000000 R09: 0000000000000000
[  797.005672] R10: 0000000000000000 R11: 0000000000000007 R12: 02dd68024f75f480
[  797.005676] R13: ffff8a5726a60b48 R14: ffff8a5702879f40 R15: ffff8a5726a60000
[  797.005681] FS:  00007f632c52a380(0000) GS:ffff8a583a200000(0000) knlGS:0000000000000000
[  797.005687] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  797.005692] CR2: 00007fb025d69000 CR3: 00000001124f6005 CR4: 00000000000606f0
[  797.005698] Call Trace:
[  797.005710]  sta_set_sinfo+0xa7/0xb80 [mac80211]
[  797.005820]  ieee80211_get_station+0x50/0x70 [mac80211]
[  797.005925]  nl80211_get_station+0xd1/0x200 [cfg80211]
[  797.006045]  genl_family_rcv_msg_doit.isra.15+0x111/0x140
[  797.006059]  genl_rcv_msg+0xe6/0x1e0
[  797.006065]  ? nl80211_dump_station+0x220/0x220 [cfg80211]
[  797.006223]  ? nl80211_send_station.isra.72+0xf50/0xf50 [cfg80211]
[  797.006348]  ? genl_family_rcv_msg_doit.isra.15+0x140/0x140
[  797.006355]  netlink_rcv_skb+0xb9/0xf0
[  797.006363]  genl_rcv+0x24/0x40
[  797.006369]  netlink_unicast+0x18e/0x290
[  797.006375]  netlink_sendmsg+0x30f/0x450
[  797.006382]  sock_sendmsg+0x5b/0x60
[  797.006393]  ____sys_sendmsg+0x219/0x240
[  797.006403]  ? copy_msghdr_from_user+0x5c/0x90
[  797.006413]  ? ____sys_recvmsg+0xf5/0x190
[  797.006422]  ___sys_sendmsg+0x88/0xd0
[  797.006432]  ? copy_msghdr_from_user+0x5c/0x90
[  797.006443]  ? ___sys_recvmsg+0x9e/0xd0
[  797.006454]  ? __fget_files+0x58/0x90
[  797.006461]  ? __fget_light+0x2d/0x70
[  797.006466]  ? do_epoll_wait+0xce/0x720
[  797.006476]  ? __sys_sendmsg+0x63/0xa0
[  797.006485]  __sys_sendmsg+0x63/0xa0
[  797.006497]  do_syscall_64+0x3c/0xb0
[  797.006509]  entry_SYSCALL_64_after_hwframe+0x44/0xae
[  797.006519] RIP: 0033:0x7f632d99912d
[  797.006526] Code: 28 89 54 24 1c 48 89 74 24 10 89 7c 24 08 e8 ca ee ff ff 8b 54 24 1c 48 8b 74 24 10 41 89 c0 8b 7c 24 08 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 2f 44 89 c7 48 89 44 24 08 e8 fe ee ff ff 48
[  797.006533] RSP: 002b:00007ffd80808c00 EFLAGS: 00000293 ORIG_RAX: 000000000000002e
[  797.006540] RAX: ffffffffffffffda RBX: 0000563dab99d840 RCX: 00007f632d99912d
[  797.006545] RDX: 0000000000000000 RSI: 00007ffd80808c50 RDI: 000000000000000b
[  797.006549] RBP: 00007ffd80808c50 R08: 0000000000000000 R09: 0000000000001000
[  797.006552] R10: 0000563dab96f010 R11: 0000000000000293 R12: 0000563dab99d840
[  797.006556] R13: 0000563dabbb28c0 R14: 00007f632dad4280 R15: 0000563dabab11c0
[  797.006563] ---[ end trace c9dcf08920c9945c ]---

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01230-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-02892.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20211215090944.19729-1-quic_wgong@quicinc.com
  • Loading branch information
Wen Gong authored and Kalle Valo committed Dec 20, 2021
1 parent a5d862d commit b488c76
Show file tree
Hide file tree
Showing 11 changed files with 284 additions and 34 deletions.
6 changes: 6 additions & 0 deletions drivers/net/wireless/ath/ath11k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
.wakeup_mhi = false,
.supports_rssi_stats = false,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
Expand Down Expand Up @@ -149,6 +150,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
.wakeup_mhi = false,
.supports_rssi_stats = false,
},
{
.name = "qca6390 hw2.0",
Expand Down Expand Up @@ -206,6 +208,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
.wakeup_mhi = true,
.supports_rssi_stats = true,
},
{
.name = "qcn9074 hw1.0",
Expand Down Expand Up @@ -263,6 +266,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_dynamic_smps_6ghz = true,
.alloc_cacheable_memory = true,
.wakeup_mhi = false,
.supports_rssi_stats = false,
},
{
.name = "wcn6855 hw2.0",
Expand Down Expand Up @@ -320,6 +324,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
.wakeup_mhi = true,
.supports_rssi_stats = true,
},
{
.name = "wcn6855 hw2.1",
Expand Down Expand Up @@ -376,6 +381,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
.wakeup_mhi = true,
.supports_rssi_stats = true,
},
};

Expand Down
5 changes: 5 additions & 0 deletions drivers/net/wireless/ath/ath11k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ struct ath11k_sta {
u64 rx_duration;
u64 tx_duration;
u8 rssi_comb;
s8 chain_signal[IEEE80211_MAX_CHAINS];
struct ath11k_htt_tx_stats *tx_stats;
struct ath11k_rx_peer_stats *rx_stats;

Expand Down Expand Up @@ -416,6 +417,10 @@ enum ath11k_state {
/* Antenna noise floor */
#define ATH11K_DEFAULT_NOISE_FLOOR -95

#define ATH11K_INVALID_RSSI_FULL -1

#define ATH11K_INVALID_RSSI_EMPTY -128

struct ath11k_fw_stats {
struct dentry *debugfs_fwstats;
u32 pdev_id;
Expand Down
37 changes: 37 additions & 0 deletions drivers/net/wireless/ath/ath11k/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb
goto complete;
}

if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) {
ar->debug.fw_stats_done = true;
goto complete;
}

if (stats.stats_id == WMI_REQUEST_VDEV_STAT) {
if (list_empty(&stats.vdevs)) {
ath11k_warn(ab, "empty vdev stats");
Expand Down Expand Up @@ -229,6 +234,38 @@ static int ath11k_debugfs_fw_stats_request(struct ath11k *ar,
return 0;
}

int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
u32 vdev_id, u32 stats_id)
{
struct ath11k_base *ab = ar->ab;
struct stats_request_params req_param;
int ret;

mutex_lock(&ar->conf_mutex);

if (ar->state != ATH11K_STATE_ON) {
ret = -ENETDOWN;
goto err_unlock;
}

req_param.pdev_id = pdev_id;
req_param.vdev_id = vdev_id;
req_param.stats_id = stats_id;

ret = ath11k_debugfs_fw_stats_request(ar, &req_param);
if (ret)
ath11k_warn(ab, "failed to request fw stats: %d\n", ret);

ath11k_dbg(ab, ATH11K_DBG_WMI,
"debug get fw stat pdev id %d vdev id %d stats id 0x%x\n",
pdev_id, vdev_id, stats_id);

err_unlock:
mutex_unlock(&ar->conf_mutex);

return ret;
}

static int ath11k_open_pdev_stats(struct inode *inode, struct file *file)
{
struct ath11k *ar = inode->i_private;
Expand Down
8 changes: 8 additions & 0 deletions drivers/net/wireless/ath/ath11k/debugfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ void ath11k_debugfs_unregister(struct ath11k *ar);
void ath11k_debugfs_fw_stats_process(struct ath11k_base *ab, struct sk_buff *skb);

void ath11k_debugfs_fw_stats_init(struct ath11k *ar);
int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id,
u32 vdev_id, u32 stats_id);

static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar)
{
Expand Down Expand Up @@ -216,6 +218,12 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
return 0;
}

static inline int ath11k_debugfs_get_fw_stats(struct ath11k *ar,
u32 pdev_id, u32 vdev_id, u32 stats_id)
{
return 0;
}

#endif /* CONFIG_MAC80211_DEBUGFS*/

#endif /* _ATH11K_DEBUGFS_H_ */
8 changes: 8 additions & 0 deletions drivers/net/wireless/ath/ath11k/dp_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2768,6 +2768,7 @@ static void ath11k_dp_rx_update_peer_stats(struct ath11k_sta *arsta,
{
struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
u32 num_msdu;
int i;

if (!rx_stats)
return;
Expand Down Expand Up @@ -2829,6 +2830,13 @@ static void ath11k_dp_rx_update_peer_stats(struct ath11k_sta *arsta,
rx_stats->ru_alloc_cnt[ppdu_info->ru_alloc] += num_msdu;

arsta->rssi_comb = ppdu_info->rssi_comb;

BUILD_BUG_ON(ARRAY_SIZE(arsta->chain_signal) >
ARRAY_SIZE(ppdu_info->rssi_chain_pri20));

for (i = 0; i < ARRAY_SIZE(arsta->chain_signal); i++)
arsta->chain_signal[i] = ppdu_info->rssi_chain_pri20[i];

rx_stats->rx_duration += ppdu_info->rx_duration;
arsta->rx_duration = rx_stats->rx_duration;
}
Expand Down
11 changes: 11 additions & 0 deletions drivers/net/wireless/ath/ath11k/hal_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,9 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
break;
}
case HAL_PHYRX_RSSI_LEGACY: {
int i;
bool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
ab->wmi_ab.svc_map);
struct hal_rx_phyrx_rssi_legacy_info *rssi =
(struct hal_rx_phyrx_rssi_legacy_info *)tlv_data;

Expand All @@ -1089,6 +1092,14 @@ ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,
ppdu_info->rssi_comb =
FIELD_GET(HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB,
__le32_to_cpu(rssi->info0));

if (db2dbm) {
for (i = 0; i < ARRAY_SIZE(rssi->preamble); i++) {
ppdu_info->rssi_chain_pri20[i] =
le32_get_bits(rssi->preamble[i].rssi_2040,
HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20);
}
}
break;
}
case HAL_RX_MPDU_START: {
Expand Down
12 changes: 11 additions & 1 deletion drivers/net/wireless/ath/ath11k/hal_rx.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct hal_rx_mon_ppdu_info {
u8 ldpc;
u8 beamformed;
u8 rssi_comb;
u8 rssi_chain_pri20[HAL_RX_MAX_NSS];
u8 tid;
u8 dcm;
u8 ru_alloc;
Expand Down Expand Up @@ -262,8 +263,17 @@ struct hal_rx_he_sig_b2_ofdma_info {

#define HAL_RX_PHYRX_RSSI_LEGACY_INFO_INFO1_RSSI_COMB GENMASK(15, 8)

#define HAL_RX_PHYRX_RSSI_PREAMBLE_PRI20 GENMASK(7, 0)

struct hal_rx_phyrx_chain_rssi {
__le32 rssi_2040;
__le32 rssi_80;
} __packed;

struct hal_rx_phyrx_rssi_legacy_info {
__le32 rsvd[35];
__le32 rsvd[3];
struct hal_rx_phyrx_chain_rssi pre_rssi[HAL_RX_MAX_NSS];
struct hal_rx_phyrx_chain_rssi preamble[HAL_RX_MAX_NSS];
__le32 info0;
} __packed;

Expand Down
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath11k/hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ struct ath11k_hw_params {
bool supports_dynamic_smps_6ghz;
bool alloc_cacheable_memory;
bool wakeup_mhi;
bool supports_rssi_stats;
};

struct ath11k_hw_ops {
Expand Down
40 changes: 40 additions & 0 deletions drivers/net/wireless/ath/ath11k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -7775,12 +7775,42 @@ static int ath11k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
return ret;
}

static void ath11k_mac_put_chain_rssi(struct station_info *sinfo,
struct ath11k_sta *arsta,
char *pre,
bool clear)
{
struct ath11k *ar = arsta->arvif->ar;
int i;
s8 rssi;

for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
sinfo->chains &= ~BIT(i);
rssi = arsta->chain_signal[i];
if (clear)
arsta->chain_signal[i] = ATH11K_INVALID_RSSI_FULL;

ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
"mac sta statistics %s rssi[%d] %d\n", pre, i, rssi);

if (rssi != ATH11K_DEFAULT_NOISE_FLOOR &&
rssi != ATH11K_INVALID_RSSI_FULL &&
rssi != ATH11K_INVALID_RSSI_EMPTY &&
rssi != 0) {
sinfo->chain_signal[i] = rssi;
sinfo->chains |= BIT(i);
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
}
}
}

static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct station_info *sinfo)
{
struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
struct ath11k *ar = arsta->arvif->ar;

sinfo->rx_duration = arsta->rx_duration;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
Expand All @@ -7803,6 +7833,16 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
}

ath11k_mac_put_chain_rssi(sinfo, arsta, "ppdu", false);

if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_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_RSSI_PER_CHAIN_STAT)) {
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);
Expand Down
Loading

0 comments on commit b488c76

Please sign in to comment.