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 { ...@@ -117,13 +117,17 @@ struct ath10k_wmi {
}; };
struct ath10k_fw_stats_peer { struct ath10k_fw_stats_peer {
struct list_head list;
u8 peer_macaddr[ETH_ALEN]; u8 peer_macaddr[ETH_ALEN];
u32 peer_rssi; u32 peer_rssi;
u32 peer_tx_rate; u32 peer_tx_rate;
u32 peer_rx_rate; /* 10x only */ u32 peer_rx_rate; /* 10x only */
}; };
struct ath10k_fw_stats { struct ath10k_fw_stats_pdev {
struct list_head list;
/* PDEV stats */ /* PDEV stats */
s32 ch_noise_floor; s32 ch_noise_floor;
u32 tx_frame_count; u32 tx_frame_count;
...@@ -178,15 +182,11 @@ struct ath10k_fw_stats { ...@@ -178,15 +182,11 @@ struct ath10k_fw_stats {
s32 phy_errs; s32 phy_errs;
s32 phy_err_drop; s32 phy_err_drop;
s32 mpdu_errs; s32 mpdu_errs;
};
/* VDEV STATS */ struct ath10k_fw_stats {
struct list_head pdevs;
/* PEER STATS */ struct list_head peers;
u8 peers;
struct ath10k_fw_stats_peer peer_stat[TARGET_NUM_PEERS];
/* TODO: Beacon filter stats */
}; };
struct ath10k_dfs_stats { struct ath10k_dfs_stats {
...@@ -294,6 +294,7 @@ struct ath10k_debug { ...@@ -294,6 +294,7 @@ struct ath10k_debug {
struct ath10k_fw_stats fw_stats; struct ath10k_fw_stats fw_stats;
struct completion fw_stats_complete; struct completion fw_stats_complete;
bool fw_stats_done;
DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX); DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
unsigned long htt_stats_mask; 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) ...@@ -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, 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_tx_stats *tx = &src->wal.tx;
const struct wal_dbg_rx_stats *rx = &src->wal.rx; 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, ...@@ -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_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
num_peer_stats = __le32_to_cpu(ev->num_peer_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; const struct wmi_pdev_stats *src;
struct ath10k_fw_stats_pdev *dst;
src = (void *)skb->data; src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src))) if (!skb_pull(skb, sizeof(*src)))
return -EPROTO; 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 */ /* fw doesn't implement vdev stats */
for (i = 0; i < num_peer_stats; i++) { for (i = 0; i < num_peer_stats; i++) {
const struct wmi_peer_stats *src; const struct wmi_peer_stats *src;
struct ath10k_fw_stats_peer *dst;
src = (void *)skb->data; src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src))) if (!skb_pull(skb, sizeof(*src)))
return -EPROTO; 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; return 0;
...@@ -1445,36 +1457,49 @@ static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar, ...@@ -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_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
num_peer_stats = __le32_to_cpu(ev->num_peer_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; const struct wmi_10x_pdev_stats *src;
struct ath10k_fw_stats_pdev *dst;
src = (void *)skb->data; src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src))) if (!skb_pull(skb, sizeof(*src)))
return -EPROTO; 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); list_add_tail(&dst->list, &stats->pdevs);
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);
} }
/* fw doesn't implement vdev stats */ /* fw doesn't implement vdev stats */
for (i = 0; i < num_peer_stats; i++) { for (i = 0; i < num_peer_stats; i++) {
const struct wmi_10x_peer_stats *src; const struct wmi_10x_peer_stats *src;
struct ath10k_fw_stats_peer *dst;
src = (void *)skb->data; src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src))) if (!skb_pull(skb, sizeof(*src)))
return -EPROTO; 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 = list_add_tail(&dst->list, &stats->peers);
__le32_to_cpu(src->peer_rx_rate);
} }
return 0; 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