Commit 68185a4b authored by Ben Greear's avatar Ben Greear Committed by John W. Linville

ath9k_htc: Add ethtool stats support.

This provides some of the same info found in
the ath9k_htc debugfs through the standard ethtool stats API.

This logic is only supported when ath9k_htc debugfs kernel
feature is enabled, since that is the only time stats
are actually gathered.
Signed-off-by: default avatarBen Greear <greearb@candelatech.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 156652bb
...@@ -234,10 +234,15 @@ static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, ...@@ -234,10 +234,15 @@ static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev,
struct sk_buff *skb; struct sk_buff *skb;
while ((skb = __skb_dequeue(queue)) != NULL) { while ((skb = __skb_dequeue(queue)) != NULL) {
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
int ln = skb->len;
#endif
ath9k_htc_txcompletion_cb(hif_dev->htc_handle, ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
skb, txok); skb, txok);
if (txok) if (txok) {
TX_STAT_INC(skb_success); TX_STAT_INC(skb_success);
TX_STAT_ADD(skb_success_bytes, ln);
}
else else
TX_STAT_INC(skb_failed); TX_STAT_INC(skb_failed);
} }
...@@ -620,6 +625,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, ...@@ -620,6 +625,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
err: err:
for (i = 0; i < pool_index; i++) { for (i = 0; i < pool_index; i++) {
RX_STAT_ADD(skb_completed_bytes, skb_pool[i]->len);
ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
skb_pool[i]->len, USB_WLAN_RX_PIPE); skb_pool[i]->len, USB_WLAN_RX_PIPE);
RX_STAT_INC(skb_completed); RX_STAT_INC(skb_completed);
......
...@@ -324,7 +324,9 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) ...@@ -324,7 +324,9 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
#ifdef CONFIG_ATH9K_HTC_DEBUGFS #ifdef CONFIG_ATH9K_HTC_DEBUGFS
#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
#define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a)
#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++)
#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c += a)
#define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ #define CAB_STAT_INC priv->debug.tx_stats.cab_queued++
#define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
...@@ -337,6 +339,7 @@ struct ath_tx_stats { ...@@ -337,6 +339,7 @@ struct ath_tx_stats {
u32 buf_completed; u32 buf_completed;
u32 skb_queued; u32 skb_queued;
u32 skb_success; u32 skb_success;
u32 skb_success_bytes;
u32 skb_failed; u32 skb_failed;
u32 cab_queued; u32 cab_queued;
u32 queue_stats[IEEE80211_NUM_ACS]; u32 queue_stats[IEEE80211_NUM_ACS];
...@@ -345,6 +348,7 @@ struct ath_tx_stats { ...@@ -345,6 +348,7 @@ struct ath_tx_stats {
struct ath_rx_stats { struct ath_rx_stats {
u32 skb_allocated; u32 skb_allocated;
u32 skb_completed; u32 skb_completed;
u32 skb_completed_bytes;
u32 skb_dropped; u32 skb_dropped;
u32 err_crc; u32 err_crc;
u32 err_decrypt_crc; u32 err_decrypt_crc;
...@@ -362,10 +366,20 @@ struct ath9k_debug { ...@@ -362,10 +366,20 @@ struct ath9k_debug {
struct ath_rx_stats rx_stats; struct ath_rx_stats rx_stats;
}; };
void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 sset, u8 *data);
int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, int sset);
void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ethtool_stats *stats, u64 *data);
#else #else
#define TX_STAT_INC(c) do { } while (0) #define TX_STAT_INC(c) do { } while (0)
#define TX_STAT_ADD(c, a) do { } while (0)
#define RX_STAT_INC(c) do { } while (0) #define RX_STAT_INC(c) do { } while (0)
#define RX_STAT_ADD(c, a) do { } while (0)
#define CAB_STAT_INC do { } while (0) #define CAB_STAT_INC do { } while (0)
#define TX_QSTAT_INC(c) do { } while (0) #define TX_QSTAT_INC(c) do { } while (0)
......
...@@ -902,6 +902,87 @@ static const struct file_operations fops_modal_eeprom = { ...@@ -902,6 +902,87 @@ static const struct file_operations fops_modal_eeprom = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
/* Ethtool support for get-stats */
#define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
static const char ath9k_htc_gstrings_stats[][ETH_GSTRING_LEN] = {
"tx_pkts_nic",
"tx_bytes_nic",
"rx_pkts_nic",
"rx_bytes_nic",
AMKSTR(d_tx_pkts),
"d_rx_crc_err",
"d_rx_decrypt_crc_err",
"d_rx_phy_err",
"d_rx_mic_err",
"d_rx_pre_delim_crc_err",
"d_rx_post_delim_crc_err",
"d_rx_decrypt_busy_err",
"d_rx_phyerr_radar",
"d_rx_phyerr_ofdm_timing",
"d_rx_phyerr_cck_timing",
};
#define ATH9K_HTC_SSTATS_LEN ARRAY_SIZE(ath9k_htc_gstrings_stats)
void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 sset, u8 *data)
{
if (sset == ETH_SS_STATS)
memcpy(data, *ath9k_htc_gstrings_stats,
sizeof(ath9k_htc_gstrings_stats));
}
int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, int sset)
{
if (sset == ETH_SS_STATS)
return ATH9K_HTC_SSTATS_LEN;
return 0;
}
#define STXBASE priv->debug.tx_stats
#define SRXBASE priv->debug.rx_stats
#define ASTXQ(a) \
data[i++] = STXBASE.a[IEEE80211_AC_BE]; \
data[i++] = STXBASE.a[IEEE80211_AC_BK]; \
data[i++] = STXBASE.a[IEEE80211_AC_VI]; \
data[i++] = STXBASE.a[IEEE80211_AC_VO]
void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ethtool_stats *stats, u64 *data)
{
struct ath9k_htc_priv *priv = hw->priv;
int i = 0;
data[i++] = STXBASE.skb_success;
data[i++] = STXBASE.skb_success_bytes;
data[i++] = SRXBASE.skb_completed;
data[i++] = SRXBASE.skb_completed_bytes;
ASTXQ(queue_stats);
data[i++] = SRXBASE.err_crc;
data[i++] = SRXBASE.err_decrypt_crc;
data[i++] = SRXBASE.err_phy;
data[i++] = SRXBASE.err_mic;
data[i++] = SRXBASE.err_pre_delim;
data[i++] = SRXBASE.err_post_delim;
data[i++] = SRXBASE.err_decrypt_busy;
data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_RADAR];
data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_OFDM_TIMING];
data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_CCK_TIMING];
WARN_ON(i != ATH9K_HTC_SSTATS_LEN);
}
int ath9k_htc_init_debug(struct ath_hw *ah) int ath9k_htc_init_debug(struct ath_hw *ah)
{ {
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
......
...@@ -1837,4 +1837,10 @@ struct ieee80211_ops ath9k_htc_ops = { ...@@ -1837,4 +1837,10 @@ struct ieee80211_ops ath9k_htc_ops = {
.set_bitrate_mask = ath9k_htc_set_bitrate_mask, .set_bitrate_mask = ath9k_htc_set_bitrate_mask,
.get_stats = ath9k_htc_get_stats, .get_stats = ath9k_htc_get_stats,
.get_antenna = ath9k_htc_get_antenna, .get_antenna = ath9k_htc_get_antenna,
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
.get_et_sset_count = ath9k_htc_get_et_sset_count,
.get_et_stats = ath9k_htc_get_et_stats,
.get_et_strings = ath9k_htc_get_et_strings,
#endif
}; };
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