| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- From: Manikanta Pubbisetty <[email protected]>
- Date: Wed, 28 Oct 2015 21:38:33 +0200
- Subject: [PATCH] ath10k: add fw_stats support to 10.4 firmware
- This patch adds support for getting firmware debug stats in 10.4 fw.
- Signed-off-by: Manikanta Pubbisetty <[email protected]>
- Signed-off-by: Tamizh chelvam <[email protected]>
- Signed-off-by: Kalle Valo <[email protected]>
- ---
- --- a/drivers/net/wireless/ath/ath10k/core.h
- +++ b/drivers/net/wireless/ath/ath10k/core.h
- @@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev {
- s32 hw_queued;
- s32 hw_reaped;
- s32 underrun;
- + u32 hw_paused;
- s32 tx_abort;
- s32 mpdus_requed;
- u32 tx_ko;
- @@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev {
- u32 pdev_resets;
- u32 phy_underrun;
- u32 txop_ovf;
- + u32 seq_posted;
- + u32 seq_failed_queueing;
- + u32 seq_completed;
- + u32 seq_restarted;
- + u32 mu_seq_posted;
- + u32 mpdus_sw_flush;
- + u32 mpdus_hw_filter;
- + u32 mpdus_truncated;
- + u32 mpdus_ack_failed;
- + u32 mpdus_expired;
-
- /* PDEV RX stats */
- s32 mid_ppdu_route_change;
- @@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev {
- s32 phy_errs;
- s32 phy_err_drop;
- s32 mpdu_errs;
- + s32 rx_ovfl_errs;
- };
-
- struct ath10k_fw_stats {
- --- a/drivers/net/wireless/ath/ath10k/wmi.c
- +++ b/drivers/net/wireless/ath/ath10k/wmi.c
- @@ -2479,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const
- dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
- }
-
- +static void
- +ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src,
- + struct ath10k_fw_stats_pdev *dst)
- +{
- + dst->comp_queued = __le32_to_cpu(src->comp_queued);
- + dst->comp_delivered = __le32_to_cpu(src->comp_delivered);
- + dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued);
- + dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued);
- + dst->wmm_drop = __le32_to_cpu(src->wmm_drop);
- + dst->local_enqued = __le32_to_cpu(src->local_enqued);
- + dst->local_freed = __le32_to_cpu(src->local_freed);
- + dst->hw_queued = __le32_to_cpu(src->hw_queued);
- + dst->hw_reaped = __le32_to_cpu(src->hw_reaped);
- + dst->underrun = __le32_to_cpu(src->underrun);
- + dst->tx_abort = __le32_to_cpu(src->tx_abort);
- + dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed);
- + dst->tx_ko = __le32_to_cpu(src->tx_ko);
- + dst->data_rc = __le32_to_cpu(src->data_rc);
- + dst->self_triggers = __le32_to_cpu(src->self_triggers);
- + dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure);
- + dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err);
- + dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry);
- + dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout);
- + dst->pdev_resets = __le32_to_cpu(src->pdev_resets);
- + dst->phy_underrun = __le32_to_cpu(src->phy_underrun);
- + dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
- + dst->hw_paused = __le32_to_cpu(src->hw_paused);
- + dst->seq_posted = __le32_to_cpu(src->seq_posted);
- + dst->seq_failed_queueing =
- + __le32_to_cpu(src->seq_failed_queueing);
- + dst->seq_completed = __le32_to_cpu(src->seq_completed);
- + dst->seq_restarted = __le32_to_cpu(src->seq_restarted);
- + dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted);
- + dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush);
- + dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
- + dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated);
- + dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed);
- + dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
- + dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired);
- +}
- +
- void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
- struct ath10k_fw_stats_pdev *dst)
- {
- @@ -2789,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_
- return 0;
- }
-
- +static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
- + struct sk_buff *skb,
- + struct ath10k_fw_stats *stats)
- +{
- + const struct wmi_10_2_stats_event *ev = (void *)skb->data;
- + u32 num_pdev_stats;
- + u32 num_pdev_ext_stats;
- + u32 num_vdev_stats;
- + u32 num_peer_stats;
- + int i;
- +
- + if (!skb_pull(skb, sizeof(*ev)))
- + return -EPROTO;
- +
- + num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
- + num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
- + num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
- + num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
- +
- + for (i = 0; i < num_pdev_stats; i++) {
- + const struct wmi_10_4_pdev_stats *src;
- + struct ath10k_fw_stats_pdev *dst;
- +
- + src = (void *)skb->data;
- + if (!skb_pull(skb, sizeof(*src)))
- + return -EPROTO;
- +
- + dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
- + if (!dst)
- + continue;
- +
- + ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
- + ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst);
- + ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
- + dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs);
- + ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
- +
- + list_add_tail(&dst->list, &stats->pdevs);
- + }
- +
- + for (i = 0; i < num_pdev_ext_stats; i++) {
- + const struct wmi_10_2_pdev_ext_stats *src;
- +
- + src = (void *)skb->data;
- + if (!skb_pull(skb, sizeof(*src)))
- + return -EPROTO;
- +
- + /* FIXME: expose values to userspace
- + *
- + * Note: Even though this loop seems to do nothing it is
- + * required to parse following sub-structures properly.
- + */
- + }
- +
- + /* fw doesn't implement vdev stats */
- +
- + for (i = 0; i < num_peer_stats; i++) {
- + const struct wmi_10_4_peer_stats *src;
- + struct ath10k_fw_stats_peer *dst;
- +
- + src = (void *)skb->data;
- + if (!skb_pull(skb, sizeof(*src)))
- + return -EPROTO;
- +
- + dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
- + if (!dst)
- + continue;
- +
- + ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
- + dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
- + dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
- + dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
- + /* FIXME: expose 10.4 specific values */
- +
- + list_add_tail(&dst->list, &stats->peers);
- + }
- +
- + return 0;
- +}
- +
- void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb)
- {
- ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
- @@ -4935,6 +5056,9 @@ static void ath10k_wmi_10_4_op_rx(struct
- ath10k_dbg(ar, ATH10K_DBG_WMI,
- "received event id %d not implemented\n", id);
- break;
- + case WMI_10_4_UPDATE_STATS_EVENTID:
- + ath10k_wmi_event_update_stats(ar, skb);
- + break;
- default:
- ath10k_warn(ar, "Unknown eventid: %d\n", id);
- break;
- @@ -7022,6 +7146,90 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_c
- return skb;
- }
-
- +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
- + struct ath10k_fw_stats *fw_stats,
- + char *buf)
- +{
- + u32 len = 0;
- + u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
- + const struct ath10k_fw_stats_pdev *pdev;
- + const struct ath10k_fw_stats_vdev *vdev;
- + const struct ath10k_fw_stats_peer *peer;
- + size_t num_peers;
- + size_t num_vdevs;
- +
- + spin_lock_bh(&ar->data_lock);
- +
- + pdev = list_first_entry_or_null(&fw_stats->pdevs,
- + struct ath10k_fw_stats_pdev, list);
- + if (!pdev) {
- + ath10k_warn(ar, "failed to get pdev stats\n");
- + goto unlock;
- + }
- +
- + num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
- + num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
- +
- + ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
- + ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
- + ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
- +
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "HW paused", pdev->hw_paused);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "Seqs posted", pdev->seq_posted);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "Seqs failed queueing", pdev->seq_failed_queueing);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "Seqs completed", pdev->seq_completed);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "Seqs restarted", pdev->seq_restarted);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "MU Seqs posted", pdev->mu_seq_posted);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "MPDUs SW flushed", pdev->mpdus_sw_flush);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "MPDUs HW filtered", pdev->mpdus_hw_filter);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "MPDUs truncated", pdev->mpdus_truncated);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "MPDUs receive no ACK", pdev->mpdus_ack_failed);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "MPDUs expired", pdev->mpdus_expired);
- +
- + ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
- + len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- + "Num Rx Overflow errors", pdev->rx_ovfl_errs);
- +
- + len += scnprintf(buf + len, buf_len - len, "\n");
- + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
- + "ath10k VDEV stats", num_vdevs);
- + len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- + "=================");
- +
- + list_for_each_entry(vdev, &fw_stats->vdevs, list) {
- + ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
- + }
- +
- + len += scnprintf(buf + len, buf_len - len, "\n");
- + len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
- + "ath10k PEER stats", num_peers);
- + len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
- + "=================");
- +
- + list_for_each_entry(peer, &fw_stats->peers, list) {
- + ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
- + }
- +
- +unlock:
- + spin_unlock_bh(&ar->data_lock);
- +
- + if (len >= buf_len)
- + buf[len - 1] = 0;
- + else
- + buf[len] = 0;
- +}
- +
- static const struct wmi_ops wmi_ops = {
- .rx = ath10k_wmi_op_rx,
- .map_svc = wmi_main_svc_map,
- @@ -7292,6 +7500,7 @@ static const struct wmi_ops wmi_10_4_ops
- .rx = ath10k_wmi_10_4_op_rx,
- .map_svc = wmi_10_4_svc_map,
-
- + .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats,
- .pull_scan = ath10k_wmi_op_pull_scan_ev,
- .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev,
- .pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev,
- @@ -7341,9 +7550,11 @@ static const struct wmi_ops wmi_10_4_ops
- .gen_addba_send = ath10k_wmi_op_gen_addba_send,
- .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
- .gen_delba_send = ath10k_wmi_op_gen_delba_send,
- + .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
-
- /* shared with 10.2 */
- .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
- + .gen_request_stats = ath10k_wmi_op_gen_request_stats,
- };
-
- int ath10k_wmi_attach(struct ath10k *ar)
- --- a/drivers/net/wireless/ath/ath10k/wmi.h
- +++ b/drivers/net/wireless/ath/ath10k/wmi.h
- @@ -3866,6 +3866,111 @@ struct wmi_pdev_stats_tx {
- __le32 txop_ovf;
- } __packed;
-
- +struct wmi_10_4_pdev_stats_tx {
- + /* Num HTT cookies queued to dispatch list */
- + __le32 comp_queued;
- +
- + /* Num HTT cookies dispatched */
- + __le32 comp_delivered;
- +
- + /* Num MSDU queued to WAL */
- + __le32 msdu_enqued;
- +
- + /* Num MPDU queue to WAL */
- + __le32 mpdu_enqued;
- +
- + /* Num MSDUs dropped by WMM limit */
- + __le32 wmm_drop;
- +
- + /* Num Local frames queued */
- + __le32 local_enqued;
- +
- + /* Num Local frames done */
- + __le32 local_freed;
- +
- + /* Num queued to HW */
- + __le32 hw_queued;
- +
- + /* Num PPDU reaped from HW */
- + __le32 hw_reaped;
- +
- + /* Num underruns */
- + __le32 underrun;
- +
- + /* HW Paused. */
- + __le32 hw_paused;
- +
- + /* Num PPDUs cleaned up in TX abort */
- + __le32 tx_abort;
- +
- + /* Num MPDUs requed by SW */
- + __le32 mpdus_requed;
- +
- + /* excessive retries */
- + __le32 tx_ko;
- +
- + /* data hw rate code */
- + __le32 data_rc;
- +
- + /* Scheduler self triggers */
- + __le32 self_triggers;
- +
- + /* frames dropped due to excessive sw retries */
- + __le32 sw_retry_failure;
- +
- + /* illegal rate phy errors */
- + __le32 illgl_rate_phy_err;
- +
- + /* wal pdev continuous xretry */
- + __le32 pdev_cont_xretry;
- +
- + /* wal pdev tx timeouts */
- + __le32 pdev_tx_timeout;
- +
- + /* wal pdev resets */
- + __le32 pdev_resets;
- +
- + /* frames dropped due to non-availability of stateless TIDs */
- + __le32 stateless_tid_alloc_failure;
- +
- + __le32 phy_underrun;
- +
- + /* MPDU is more than txop limit */
- + __le32 txop_ovf;
- +
- + /* Number of Sequences posted */
- + __le32 seq_posted;
- +
- + /* Number of Sequences failed queueing */
- + __le32 seq_failed_queueing;
- +
- + /* Number of Sequences completed */
- + __le32 seq_completed;
- +
- + /* Number of Sequences restarted */
- + __le32 seq_restarted;
- +
- + /* Number of MU Sequences posted */
- + __le32 mu_seq_posted;
- +
- + /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */
- + __le32 mpdus_sw_flush;
- +
- + /* Num MPDUs filtered by HW, all filter condition (TTL expired) */
- + __le32 mpdus_hw_filter;
- +
- + /* Num MPDUs truncated by PDG
- + * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw)
- + */
- + __le32 mpdus_truncated;
- +
- + /* Num MPDUs that was tried but didn't receive ACK or BA */
- + __le32 mpdus_ack_failed;
- +
- + /* Num MPDUs that was dropped due to expiry. */
- + __le32 mpdus_expired;
- +} __packed;
- +
- struct wmi_pdev_stats_rx {
- /* Cnts any change in ring routing mid-ppdu */
- __le32 mid_ppdu_route_change;
- @@ -4039,6 +4144,16 @@ struct wmi_10_2_pdev_stats {
- struct wmi_pdev_stats_extra extra;
- } __packed;
-
- +struct wmi_10_4_pdev_stats {
- + struct wmi_pdev_stats_base base;
- + struct wmi_10_4_pdev_stats_tx tx;
- + struct wmi_pdev_stats_rx rx;
- + __le32 rx_ovfl_errs;
- + struct wmi_pdev_stats_mem mem;
- + __le32 sram_free_size;
- + struct wmi_pdev_stats_extra extra;
- +} __packed;
- +
- /*
- * VDEV statistics
- * TODO: add all VDEV stats here
- @@ -4080,6 +4195,23 @@ struct wmi_10_2_4_peer_stats {
- __le32 unknown_value; /* FIXME: what is this word? */
- } __packed;
-
- +struct wmi_10_4_peer_stats {
- + struct wmi_mac_addr peer_macaddr;
- + __le32 peer_rssi;
- + __le32 peer_rssi_seq_num;
- + __le32 peer_tx_rate;
- + __le32 peer_rx_rate;
- + __le32 current_per;
- + __le32 retries;
- + __le32 tx_rate_count;
- + __le32 max_4ms_frame_len;
- + __le32 total_sub_frames;
- + __le32 tx_bytes;
- + __le32 num_pkt_loss_overflow[4];
- + __le32 num_pkt_loss_excess_retry[4];
- + __le32 peer_rssi_changed;
- +} __packed;
- +
- struct wmi_10_2_pdev_ext_stats {
- __le32 rx_rssi_comb;
- __le32 rx_rssi[4];
- @@ -6201,5 +6333,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(str
- char *buf);
- size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
- size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
- +void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
- + struct ath10k_fw_stats *fw_stats,
- + char *buf);
-
- #endif /* _WMI_H_ */
|