[PATCH 14/21] ath10k: Add tx/rx bytes, cycle counters to ethtool stats.
greearb at candelatech.com
greearb at candelatech.com
Mon May 9 16:11:08 PDT 2016
From: Ben Greear <greearb at candelatech.com>
The firmware does not offer tx/rx bytes counters, so just keep track of
it in the driver.
For the cycle counters:
Note these counters are since the chip reset, though the counters
wrap often. When cycle-counters counter overflows on
certain hardware, it will right shift all 4 of the
related registers to the right by one bit (basically,
divide by two). Since you have no idea what the others
were at when cycle-counter wrapped, you must simply
ignore any sample where cycle-counter wraps, and set
new baseline values to calculate diffs against next
time.
Hardware with this funny wrap logic will cause the
d_flags 'counter' to have bit 0x1 set, so that is how
user-space can know how to deal with this.
Signed-off-by: Ben Greear <greearb at candelatech.com>
---
drivers/net/wireless/ath/ath10k/core.h | 3 +++
drivers/net/wireless/ath/ath10k/debug.c | 22 +++++++++++++++++-----
drivers/net/wireless/ath/ath10k/htt_rx.c | 3 +++
drivers/net/wireless/ath/ath10k/htt_tx.c | 22 +++++++++++++++++-----
4 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index c4f649f..1a75e2e 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -466,6 +466,9 @@ struct ath10k_debug {
struct ath10k_dbglog_entry_storage dbglog_entry_data;
struct ath10k_fw_crash_data *fw_crash_data;
+
+ u64 tx_bytes; /* counter, firmware does not offer this stat */
+ u64 rx_bytes; /* counter, firmware does not offer this stat */
};
enum ath10k_state {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 54a2194..684a39d 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1442,11 +1442,15 @@ exit:
/* This generally cooresponds to the debugfs fw_stats file */
static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx_pkts_nic",
- "tx_bytes_nic",
+ "tx_bytes_nic", /* from driver, firmware does not keep this stat. */
"rx_pkts_nic",
- "rx_bytes_nic",
+ "rx_bytes_nic", /* from driver, firmware does not keep this stat. */
"d_noise_floor",
- "d_cycle_count",
+ "d_cycle_count", /* this is duty cycle counter, basically channel-time. 88MHz clock */
+ "d_tx_cycle_count", /* tx cycle count */
+ "d_rx_cycle_count", /* rx cycle count */
+ "d_busy_count", /* Total channel busy time cycles (called 'clear' by firmware) */
+ "d_flags", /* 0x1: hw has shifted cycle-count wrap, see ath10k_hw_fill_survey_time */
"d_phy_error",
"d_rts_bad",
"d_rts_good",
@@ -1518,6 +1522,7 @@ void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
static const struct ath10k_fw_stats_pdev zero_stats = {};
const struct ath10k_fw_stats_pdev *pdev_stats;
int i = 0, ret;
+ u64 d_flags = 0;
mutex_lock(&ar->conf_mutex);
@@ -1541,12 +1546,19 @@ void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
spin_lock_bh(&ar->data_lock);
+ if (ar->hw_params.has_shifted_cc_wraparound)
+ d_flags |= 0x1;
+
data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
- data[i++] = 0; /* tx bytes */
+ data[i++] = ar->debug.tx_bytes;
data[i++] = pdev_stats->htt_mpdus;
- data[i++] = 0; /* rx bytes */
+ data[i++] = ar->debug.rx_bytes;
data[i++] = pdev_stats->ch_noise_floor;
data[i++] = pdev_stats->cycle_count;
+ data[i++] = pdev_stats->tx_frame_count;
+ data[i++] = pdev_stats->rx_frame_count;
+ data[i++] = pdev_stats->rx_clear_count; /* yes, this appears to actually be 'busy' count */
+ data[i++] = d_flags; /* give user-space a chance to decode cycle counters */
data[i++] = pdev_stats->phy_err_count;
data[i++] = pdev_stats->rts_bad;
data[i++] = pdev_stats->rts_good;
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index cc979a4..47da904 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1379,6 +1379,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
}
skb_queue_walk(amsdu, msdu) {
+#ifdef CONFIG_ATH10K_DEBUGFS
+ ar->debug.rx_bytes += msdu->len;
+#endif
ath10k_htt_rx_h_csum_offload(msdu);
ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
is_decrypted);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 6269c61..06ec995 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -769,6 +769,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int len = 0;
int msdu_id = -1;
int res;
+ int skb_len;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
len += sizeof(cmd->hdr);
@@ -795,7 +796,8 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
goto err_free_msdu_id;
}
- skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
+ skb_len = msdu->len;
+ skb_cb->paddr = dma_map_single(dev, msdu->data, skb_len,
DMA_TO_DEVICE);
res = dma_mapping_error(dev, skb_cb->paddr);
if (res) {
@@ -809,16 +811,20 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_MGMT_TX;
cmd->mgmt_tx.msdu_paddr = __cpu_to_le32(ATH10K_SKB_CB(msdu)->paddr);
- cmd->mgmt_tx.len = __cpu_to_le32(msdu->len);
+ cmd->mgmt_tx.len = __cpu_to_le32(skb_len);
cmd->mgmt_tx.desc_id = __cpu_to_le32(msdu_id);
cmd->mgmt_tx.vdev_id = __cpu_to_le32(vdev_id);
memcpy(cmd->mgmt_tx.hdr, msdu->data,
- min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN));
+ min_t(int, skb_len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN));
res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
if (res)
goto err_unmap_msdu;
+#ifdef CONFIG_ATH10K_DEBUGFS
+ ar->debug.tx_bytes += skb_len;
+#endif
+
return 0;
err_unmap_msdu:
@@ -852,6 +858,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
u8 flags0 = 0;
u16 msdu_id, flags1 = 0;
u16 freq = 0;
+ int skb_len;
u32 frags_paddr = 0;
u32 txbuf_paddr;
struct htt_msdu_ext_desc *ext_desc = NULL;
@@ -990,13 +997,14 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
__cpu_to_le32(HTT_INVALID_PEERID);
}
+ skb_len = msdu->len;
trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu freq %hu\n",
- flags0, flags1, msdu->len, msdu_id, frags_paddr,
+ flags0, flags1, skb_len, msdu_id, frags_paddr,
(u32)skb_cb->paddr, vdev_id, tid, freq);
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
- msdu->data, msdu->len);
+ msdu->data, skb_len);
trace_ath10k_tx_hdr(ar, msdu->data, msdu->len);
trace_ath10k_tx_payload(ar, msdu->data, msdu->len);
@@ -1021,6 +1029,10 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
if (res)
goto err_unmap_msdu;
+#ifdef CONFIG_ATH10K_DEBUGFS
+ ar->debug.tx_bytes += skb_len;
+#endif
+
return 0;
err_unmap_msdu:
--
2.4.3
More information about the ath10k
mailing list