Commit 5326849a authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: fix fw stats processing

If stat data exceeds wmi-htc buffer limits
firmware splits it into many wmi stats update
events which are delivered in a ping-pong fashion
triggered by wmi stats request command.

Since there's only an implicit start-of-data and
no end-of-data indications the driver has to
perform some trickery to get complete stat data.

kvalo: use %zu to fix a compiler warning and fix a typo in a comment
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent fb2e9c0c
......@@ -117,13 +117,17 @@ struct ath10k_wmi {
};
struct ath10k_fw_stats_peer {
struct list_head list;
u8 peer_macaddr[ETH_ALEN];
u32 peer_rssi;
u32 peer_tx_rate;
u32 peer_rx_rate; /* 10x only */
};
struct ath10k_fw_stats {
struct ath10k_fw_stats_pdev {
struct list_head list;
/* PDEV stats */
s32 ch_noise_floor;
u32 tx_frame_count;
......@@ -178,15 +182,11 @@ struct ath10k_fw_stats {
s32 phy_errs;
s32 phy_err_drop;
s32 mpdu_errs;
};
/* VDEV STATS */
/* PEER STATS */
u8 peers;
struct ath10k_fw_stats_peer peer_stat[TARGET_NUM_PEERS];
/* TODO: Beacon filter stats */
struct ath10k_fw_stats {
struct list_head pdevs;
struct list_head peers;
};
struct ath10k_dfs_stats {
......@@ -294,6 +294,7 @@ struct ath10k_debug {
struct ath10k_fw_stats fw_stats;
struct completion fw_stats_complete;
bool fw_stats_done;
DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
unsigned long htt_stats_mask;
......
This diff is collapsed.
......@@ -1330,7 +1330,7 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
}
static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
struct ath10k_fw_stats *dst)
struct ath10k_fw_stats_pdev *dst)
{
const struct wal_dbg_tx_stats *tx = &src->wal.tx;
const struct wal_dbg_rx_stats *rx = &src->wal.rx;
......@@ -1405,26 +1405,38 @@ static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar,
num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
if (num_pdev_stats) {
for (i = 0; i < num_pdev_stats; i++) {
const struct wmi_pdev_stats *src;
struct ath10k_fw_stats_pdev *dst;
src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
ath10k_wmi_pull_pdev_stats(src, stats);
dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
if (!dst)
continue;
ath10k_wmi_pull_pdev_stats(src, dst);
list_add_tail(&dst->list, &stats->pdevs);
}
/* fw doesn't implement vdev stats */
for (i = 0; i < num_peer_stats; i++) {
const struct wmi_peer_stats *src;
struct ath10k_fw_stats_peer *dst;
src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
ath10k_wmi_pull_peer_stats(src, &stats->peer_stat[i]);
dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
if (!dst)
continue;
ath10k_wmi_pull_peer_stats(src, dst);
list_add_tail(&dst->list, &stats->peers);
}
return 0;
......@@ -1445,36 +1457,49 @@ static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar,
num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
if (num_pdev_stats) {
for (i = 0; i < num_pdev_stats; i++) {
const struct wmi_10x_pdev_stats *src;
struct ath10k_fw_stats_pdev *dst;
src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
ath10k_wmi_pull_pdev_stats(&src->old, stats);
dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
if (!dst)
continue;
ath10k_wmi_pull_pdev_stats(&src->old, dst);
dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad);
dst->rts_bad = __le32_to_cpu(src->rts_bad);
dst->rts_good = __le32_to_cpu(src->rts_good);
dst->fcs_bad = __le32_to_cpu(src->fcs_bad);
dst->no_beacons = __le32_to_cpu(src->no_beacons);
dst->mib_int_count = __le32_to_cpu(src->mib_int_count);
stats->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad);
stats->rts_bad = __le32_to_cpu(src->rts_bad);
stats->rts_good = __le32_to_cpu(src->rts_good);
stats->fcs_bad = __le32_to_cpu(src->fcs_bad);
stats->no_beacons = __le32_to_cpu(src->no_beacons);
stats->mib_int_count = __le32_to_cpu(src->mib_int_count);
list_add_tail(&dst->list, &stats->pdevs);
}
/* fw doesn't implement vdev stats */
for (i = 0; i < num_peer_stats; i++) {
const struct wmi_10x_peer_stats *src;
struct ath10k_fw_stats_peer *dst;
src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
ath10k_wmi_pull_peer_stats(&src->old, &stats->peer_stat[i]);
dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
if (!dst)
continue;
ath10k_wmi_pull_peer_stats(&src->old, dst);
dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
stats->peer_stat[i].peer_rx_rate =
__le32_to_cpu(src->peer_rx_rate);
list_add_tail(&dst->list, &stats->peers);
}
return 0;
......
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