Commit 1b3fdb50 authored by Rajkumar Manoharan's avatar Rajkumar Manoharan Committed by Kalle Valo

ath10k: fix vdev stats for 10.4 firmware

Currently vdev stats displayed in fw_stats are applicable
only for TLV based firmware and fix it for 10.4 firmware
as of now. The vdev stats in 10.4 firmware is split into two
parts (vdev_stats, vdev_stats_extended). The actual stats
are captured only in extended vdev stats. In order to enable
vdev stats, appropriate feature bit will be set on extended
resource config. As FTM related counters are available only on
newer 10.4 based firmware, these counters will be displayed
only on valid data.
Signed-off-by: default avatarRajkumar Manoharan <rmanohar@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 91493e8e
...@@ -2041,7 +2041,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ...@@ -2041,7 +2041,8 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS; ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
ar->num_tids = TARGET_10_4_TGT_NUM_TIDS; ar->num_tids = TARGET_10_4_TGT_NUM_TIDS;
ar->fw_stats_req_mask = WMI_10_4_STAT_PEER | ar->fw_stats_req_mask = WMI_10_4_STAT_PEER |
WMI_10_4_STAT_PEER_EXTD; WMI_10_4_STAT_PEER_EXTD |
WMI_10_4_STAT_VDEV_EXTD;
ar->max_spatial_stream = ar->hw_params.max_spatial_stream; ar->max_spatial_stream = ar->hw_params.max_spatial_stream;
ar->max_num_tdls_vdevs = TARGET_10_4_NUM_TDLS_VDEVS; ar->max_num_tdls_vdevs = TARGET_10_4_NUM_TDLS_VDEVS;
...@@ -2282,6 +2283,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, ...@@ -2282,6 +2283,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
if (ath10k_peer_stats_enabled(ar)) if (ath10k_peer_stats_enabled(ar))
val = WMI_10_4_PEER_STATS; val = WMI_10_4_PEER_STATS;
/* Enable vdev stats by default */
val |= WMI_10_4_VDEV_STATS;
if (test_bit(WMI_SERVICE_BSS_CHANNEL_INFO_64, ar->wmi.svc_map)) if (test_bit(WMI_SERVICE_BSS_CHANNEL_INFO_64, ar->wmi.svc_map))
val |= WMI_10_4_BSS_CHANNEL_INFO_64; val |= WMI_10_4_BSS_CHANNEL_INFO_64;
......
...@@ -222,6 +222,27 @@ struct ath10k_fw_stats_vdev { ...@@ -222,6 +222,27 @@ struct ath10k_fw_stats_vdev {
u32 beacon_rssi_history[10]; u32 beacon_rssi_history[10];
}; };
struct ath10k_fw_stats_vdev_extd {
struct list_head list;
u32 vdev_id;
u32 ppdu_aggr_cnt;
u32 ppdu_noack;
u32 mpdu_queued;
u32 ppdu_nonaggr_cnt;
u32 mpdu_sw_requeued;
u32 mpdu_suc_retry;
u32 mpdu_suc_multitry;
u32 mpdu_fail_retry;
u32 tx_ftm_suc;
u32 tx_ftm_suc_retry;
u32 tx_ftm_fail;
u32 rx_ftmr_cnt;
u32 rx_ftmr_dup_cnt;
u32 rx_iftmr_cnt;
u32 rx_iftmr_dup_cnt;
};
struct ath10k_fw_stats_pdev { struct ath10k_fw_stats_pdev {
struct list_head list; struct list_head list;
......
...@@ -2708,6 +2708,28 @@ ath10k_wmi_10_4_pull_peer_stats(const struct wmi_10_4_peer_stats *src, ...@@ -2708,6 +2708,28 @@ ath10k_wmi_10_4_pull_peer_stats(const struct wmi_10_4_peer_stats *src,
dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
} }
static void
ath10k_wmi_10_4_pull_vdev_stats(const struct wmi_vdev_stats_extd *src,
struct ath10k_fw_stats_vdev_extd *dst)
{
dst->vdev_id = __le32_to_cpu(src->vdev_id);
dst->ppdu_aggr_cnt = __le32_to_cpu(src->ppdu_aggr_cnt);
dst->ppdu_noack = __le32_to_cpu(src->ppdu_noack);
dst->mpdu_queued = __le32_to_cpu(src->mpdu_queued);
dst->ppdu_nonaggr_cnt = __le32_to_cpu(src->ppdu_nonaggr_cnt);
dst->mpdu_sw_requeued = __le32_to_cpu(src->mpdu_sw_requeued);
dst->mpdu_suc_retry = __le32_to_cpu(src->mpdu_suc_retry);
dst->mpdu_suc_multitry = __le32_to_cpu(src->mpdu_suc_multitry);
dst->mpdu_fail_retry = __le32_to_cpu(src->mpdu_fail_retry);
dst->tx_ftm_suc = __le32_to_cpu(src->tx_ftm_suc);
dst->tx_ftm_suc_retry = __le32_to_cpu(src->tx_ftm_suc_retry);
dst->tx_ftm_fail = __le32_to_cpu(src->tx_ftm_fail);
dst->rx_ftmr_cnt = __le32_to_cpu(src->rx_ftmr_cnt);
dst->rx_ftmr_dup_cnt = __le32_to_cpu(src->rx_ftmr_dup_cnt);
dst->rx_iftmr_cnt = __le32_to_cpu(src->rx_iftmr_cnt);
dst->rx_iftmr_dup_cnt = __le32_to_cpu(src->rx_iftmr_dup_cnt);
}
static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar, static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar,
struct sk_buff *skb, struct sk_buff *skb,
struct ath10k_fw_stats *stats) struct ath10k_fw_stats *stats)
...@@ -3047,7 +3069,16 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, ...@@ -3047,7 +3069,16 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
*/ */
} }
/* fw doesn't implement vdev stats */ for (i = 0; i < num_vdev_stats; i++) {
const struct wmi_vdev_stats *src;
/* Ignore vdev stats here as it has only vdev id. Actual vdev
* stats will be retrieved from vdev extended stats.
*/
src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
}
for (i = 0; i < num_peer_stats; i++) { for (i = 0; i < num_peer_stats; i++) {
const struct wmi_10_4_peer_stats *src; const struct wmi_10_4_peer_stats *src;
...@@ -3079,9 +3110,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, ...@@ -3079,9 +3110,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
*/ */
} }
if ((stats_id & WMI_10_4_STAT_PEER_EXTD) == 0) if (stats_id & WMI_10_4_STAT_PEER_EXTD) {
return 0;
stats->extended = true; stats->extended = true;
for (i = 0; i < num_peer_stats; i++) { for (i = 0; i < num_peer_stats; i++) {
...@@ -3096,10 +3125,29 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, ...@@ -3096,10 +3125,29 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
if (!dst) if (!dst)
continue; continue;
ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); ether_addr_copy(dst->peer_macaddr,
src->peer_macaddr.addr);
dst->rx_duration = __le32_to_cpu(src->rx_duration); dst->rx_duration = __le32_to_cpu(src->rx_duration);
list_add_tail(&dst->list, &stats->peers_extd); list_add_tail(&dst->list, &stats->peers_extd);
} }
}
if (stats_id & WMI_10_4_STAT_VDEV_EXTD) {
for (i = 0; i < num_vdev_stats; i++) {
const struct wmi_vdev_stats_extd *src;
struct ath10k_fw_stats_vdev_extd *dst;
src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
if (!dst)
continue;
ath10k_wmi_10_4_pull_vdev_stats(src, dst);
list_add_tail(&dst->list, &stats->vdevs);
}
}
return 0; return 0;
} }
...@@ -8004,6 +8052,72 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, ...@@ -8004,6 +8052,72 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
return skb; return skb;
} }
static void
ath10k_wmi_fw_vdev_stats_extd_fill(const struct ath10k_fw_stats_vdev_extd *vdev,
char *buf, u32 *length)
{
u32 len = *length;
u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
u32 val;
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"vdev id", vdev->vdev_id);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"ppdu aggr count", vdev->ppdu_aggr_cnt);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"ppdu noack", vdev->ppdu_noack);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"mpdu queued", vdev->mpdu_queued);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"ppdu nonaggr count", vdev->ppdu_nonaggr_cnt);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"mpdu sw requeued", vdev->mpdu_sw_requeued);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"mpdu success retry", vdev->mpdu_suc_retry);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"mpdu success multitry", vdev->mpdu_suc_multitry);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"mpdu fail retry", vdev->mpdu_fail_retry);
val = vdev->tx_ftm_suc;
if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"tx ftm success",
MS(val, WMI_VDEV_STATS_FTM_COUNT));
val = vdev->tx_ftm_suc_retry;
if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"tx ftm success retry",
MS(val, WMI_VDEV_STATS_FTM_COUNT));
val = vdev->tx_ftm_fail;
if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"tx ftm fail",
MS(val, WMI_VDEV_STATS_FTM_COUNT));
val = vdev->rx_ftmr_cnt;
if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"rx ftm request count",
MS(val, WMI_VDEV_STATS_FTM_COUNT));
val = vdev->rx_ftmr_dup_cnt;
if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"rx ftm request dup count",
MS(val, WMI_VDEV_STATS_FTM_COUNT));
val = vdev->rx_iftmr_cnt;
if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"rx initial ftm req count",
MS(val, WMI_VDEV_STATS_FTM_COUNT));
val = vdev->rx_iftmr_dup_cnt;
if (val & WMI_VDEV_STATS_FTM_COUNT_VALID)
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
"rx initial ftm req dup cnt",
MS(val, WMI_VDEV_STATS_FTM_COUNT));
len += scnprintf(buf + len, buf_len - len, "\n");
*length = len;
}
void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
struct ath10k_fw_stats *fw_stats, struct ath10k_fw_stats *fw_stats,
char *buf) char *buf)
...@@ -8011,7 +8125,7 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, ...@@ -8011,7 +8125,7 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
u32 len = 0; u32 len = 0;
u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
const struct ath10k_fw_stats_pdev *pdev; const struct ath10k_fw_stats_pdev *pdev;
const struct ath10k_fw_stats_vdev *vdev; const struct ath10k_fw_stats_vdev_extd *vdev;
const struct ath10k_fw_stats_peer *peer; const struct ath10k_fw_stats_peer *peer;
size_t num_peers; size_t num_peers;
size_t num_vdevs; size_t num_vdevs;
...@@ -8064,9 +8178,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, ...@@ -8064,9 +8178,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
"ath10k VDEV stats", num_vdevs); "ath10k VDEV stats", num_vdevs);
len += scnprintf(buf + len, buf_len - len, "%30s\n\n", len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
"================="); "=================");
list_for_each_entry(vdev, &fw_stats->vdevs, list) { list_for_each_entry(vdev, &fw_stats->vdevs, list) {
ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len); ath10k_wmi_fw_vdev_stats_extd_fill(vdev, buf, &len);
} }
len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "\n");
......
...@@ -4413,6 +4413,7 @@ enum wmi_10_4_stats_id { ...@@ -4413,6 +4413,7 @@ enum wmi_10_4_stats_id {
WMI_10_4_STAT_AP = BIT(1), WMI_10_4_STAT_AP = BIT(1),
WMI_10_4_STAT_INST = BIT(2), WMI_10_4_STAT_INST = BIT(2),
WMI_10_4_STAT_PEER_EXTD = BIT(3), WMI_10_4_STAT_PEER_EXTD = BIT(3),
WMI_10_4_STAT_VDEV_EXTD = BIT(4),
}; };
struct wlan_inst_rssi_args { struct wlan_inst_rssi_args {
...@@ -4552,12 +4553,36 @@ struct wmi_10_4_pdev_stats { ...@@ -4552,12 +4553,36 @@ struct wmi_10_4_pdev_stats {
/* /*
* VDEV statistics * VDEV statistics
* TODO: add all VDEV stats here
*/ */
#define WMI_VDEV_STATS_FTM_COUNT_VALID BIT(31)
#define WMI_VDEV_STATS_FTM_COUNT_LSB 0
#define WMI_VDEV_STATS_FTM_COUNT_MASK 0x7fffffff
struct wmi_vdev_stats { struct wmi_vdev_stats {
__le32 vdev_id; __le32 vdev_id;
} __packed; } __packed;
struct wmi_vdev_stats_extd {
__le32 vdev_id;
__le32 ppdu_aggr_cnt;
__le32 ppdu_noack;
__le32 mpdu_queued;
__le32 ppdu_nonaggr_cnt;
__le32 mpdu_sw_requeued;
__le32 mpdu_suc_retry;
__le32 mpdu_suc_multitry;
__le32 mpdu_fail_retry;
__le32 tx_ftm_suc;
__le32 tx_ftm_suc_retry;
__le32 tx_ftm_fail;
__le32 rx_ftmr_cnt;
__le32 rx_ftmr_dup_cnt;
__le32 rx_iftmr_cnt;
__le32 rx_iftmr_dup_cnt;
__le32 reserved[6];
} __packed;
/* /*
* peer statistics. * peer statistics.
* TODO: add more stats * TODO: add more stats
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment