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

ath9k: Add more recv stats.

This adds counters in various places that can drop packets on
rx without otherwise incrementing a counter.  It also counts
some non-error cases, such as becons and fragments received.

Should help with figuring out where packets are (and are not)
dropped.
Signed-off-by: default avatarBen Greear <greearb@candelatech.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a5a0bca1
...@@ -916,6 +916,21 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, ...@@ -916,6 +916,21 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
len += snprintf(buf + len, size - len, len += snprintf(buf + len, size - len,
"%22s : %10u\n", "DECRYPT BUSY ERR", "%22s : %10u\n", "DECRYPT BUSY ERR",
sc->debug.stats.rxstats.decrypt_busy_err); sc->debug.stats.rxstats.decrypt_busy_err);
len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-LENGTH-ERR",
sc->debug.stats.rxstats.rx_len_err);
len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-OOM-ERR",
sc->debug.stats.rxstats.rx_oom_err);
len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-RATE-ERR",
sc->debug.stats.rxstats.rx_rate_err);
len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-DROP-RXFLUSH",
sc->debug.stats.rxstats.rx_drop_rxflush);
len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-TOO-MANY-FRAGS",
sc->debug.stats.rxstats.rx_too_many_frags_err);
PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING); PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING);
...@@ -950,6 +965,12 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, ...@@ -950,6 +965,12 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
len += snprintf(buf + len, size - len, len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-Bytes-All", "%22s : %10u\n", "RX-Bytes-All",
sc->debug.stats.rxstats.rx_bytes_all); sc->debug.stats.rxstats.rx_bytes_all);
len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-Beacons",
sc->debug.stats.rxstats.rx_beacons);
len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-Frags",
sc->debug.stats.rxstats.rx_frags);
if (len > size) if (len > size)
len = size; len = size;
...@@ -964,7 +985,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, ...@@ -964,7 +985,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
{ {
#define RX_STAT_INC(c) sc->debug.stats.rxstats.c++
#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
#define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\ #define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\
[sc->debug.rsidx].c) [sc->debug.rsidx].c)
...@@ -1010,7 +1030,6 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) ...@@ -1010,7 +1030,6 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
#endif #endif
#undef RX_STAT_INC
#undef RX_PHY_ERR_INC #undef RX_PHY_ERR_INC
#undef RX_SAMP_DBG #undef RX_SAMP_DBG
} }
......
...@@ -139,6 +139,8 @@ struct ath_tx_stats { ...@@ -139,6 +139,8 @@ struct ath_tx_stats {
u32 txfailed; u32 txfailed;
}; };
#define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++)
/** /**
* struct ath_rx_stats - RX Statistics * struct ath_rx_stats - RX Statistics
* @rx_pkts_all: No. of total frames received, including ones that * @rx_pkts_all: No. of total frames received, including ones that
...@@ -155,6 +157,13 @@ struct ath_tx_stats { ...@@ -155,6 +157,13 @@ struct ath_tx_stats {
* @post_delim_crc_err: Post-Frame delimiter CRC error detections * @post_delim_crc_err: Post-Frame delimiter CRC error detections
* @decrypt_busy_err: Decryption interruptions counter * @decrypt_busy_err: Decryption interruptions counter
* @phy_err_stats: Individual PHY error statistics * @phy_err_stats: Individual PHY error statistics
* @rx_len_err: No. of frames discarded due to bad length.
* @rx_oom_err: No. of frames dropped due to OOM issues.
* @rx_rate_err: No. of frames dropped due to rate errors.
* @rx_too_many_frags_err: Frames dropped due to too-many-frags received.
* @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH.
* @rx_beacons: No. of beacons received.
* @rx_frags: No. of rx-fragements received.
*/ */
struct ath_rx_stats { struct ath_rx_stats {
u32 rx_pkts_all; u32 rx_pkts_all;
...@@ -167,6 +176,13 @@ struct ath_rx_stats { ...@@ -167,6 +176,13 @@ struct ath_rx_stats {
u32 post_delim_crc_err; u32 post_delim_crc_err;
u32 decrypt_busy_err; u32 decrypt_busy_err;
u32 phy_err_stats[ATH9K_PHYERR_MAX]; u32 phy_err_stats[ATH9K_PHYERR_MAX];
u32 rx_len_err;
u32 rx_oom_err;
u32 rx_rate_err;
u32 rx_too_many_frags_err;
u32 rx_drop_rxflush;
u32 rx_beacons;
u32 rx_frags;
}; };
enum ath_reset_type { enum ath_reset_type {
...@@ -250,6 +266,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); ...@@ -250,6 +266,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
#else #else
#define RX_STAT_INC(c) /* NOP */
static inline int ath9k_init_debug(struct ath_hw *ah) static inline int ath9k_init_debug(struct ath_hw *ah)
{ {
return 0; return 0;
......
...@@ -824,15 +824,20 @@ static bool ath9k_rx_accept(struct ath_common *common, ...@@ -824,15 +824,20 @@ static bool ath9k_rx_accept(struct ath_common *common,
if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID) if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID)
rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
if (!rx_stats->rs_datalen) if (!rx_stats->rs_datalen) {
RX_STAT_INC(rx_len_err);
return false; return false;
}
/* /*
* rs_status follows rs_datalen so if rs_datalen is too large * rs_status follows rs_datalen so if rs_datalen is too large
* we can take a hint that hardware corrupted it, so ignore * we can take a hint that hardware corrupted it, so ignore
* those frames. * those frames.
*/ */
if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) {
RX_STAT_INC(rx_len_err);
return false; return false;
}
/* Only use error bits from the last fragment */ /* Only use error bits from the last fragment */
if (rx_stats->rs_more) if (rx_stats->rs_more)
...@@ -902,6 +907,7 @@ static int ath9k_process_rate(struct ath_common *common, ...@@ -902,6 +907,7 @@ static int ath9k_process_rate(struct ath_common *common,
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
enum ieee80211_band band; enum ieee80211_band band;
unsigned int i = 0; unsigned int i = 0;
struct ath_softc *sc = (struct ath_softc *) common->priv;
band = hw->conf.channel->band; band = hw->conf.channel->band;
sband = hw->wiphy->bands[band]; sband = hw->wiphy->bands[band];
...@@ -936,7 +942,7 @@ static int ath9k_process_rate(struct ath_common *common, ...@@ -936,7 +942,7 @@ static int ath9k_process_rate(struct ath_common *common,
ath_dbg(common, ANY, ath_dbg(common, ANY,
"unsupported hw bitrate detected 0x%02x using 1 Mbit\n", "unsupported hw bitrate detected 0x%02x using 1 Mbit\n",
rx_stats->rs_rate); rx_stats->rs_rate);
RX_STAT_INC(rx_rate_err);
return -EINVAL; return -EINVAL;
} }
...@@ -1823,10 +1829,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1823,10 +1829,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
rxs = IEEE80211_SKB_RXCB(hdr_skb); rxs = IEEE80211_SKB_RXCB(hdr_skb);
if (ieee80211_is_beacon(hdr->frame_control) && if (ieee80211_is_beacon(hdr->frame_control)) {
!is_zero_ether_addr(common->curbssid) && RX_STAT_INC(rx_beacons);
!compare_ether_addr(hdr->addr3, common->curbssid)) if (!is_zero_ether_addr(common->curbssid) &&
rs.is_mybeacon = true; !compare_ether_addr(hdr->addr3, common->curbssid))
rs.is_mybeacon = true;
else
rs.is_mybeacon = false;
}
else else
rs.is_mybeacon = false; rs.is_mybeacon = false;
...@@ -1836,8 +1846,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1836,8 +1846,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
* If we're asked to flush receive queue, directly * If we're asked to flush receive queue, directly
* chain it back at the queue without processing it. * chain it back at the queue without processing it.
*/ */
if (sc->sc_flags & SC_OP_RXFLUSH) if (sc->sc_flags & SC_OP_RXFLUSH) {
RX_STAT_INC(rx_drop_rxflush);
goto requeue_drop_frag; goto requeue_drop_frag;
}
memset(rxs, 0, sizeof(struct ieee80211_rx_status)); memset(rxs, 0, sizeof(struct ieee80211_rx_status));
...@@ -1867,8 +1879,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1867,8 +1879,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
* tell hardware it can give us a new frame using the old * tell hardware it can give us a new frame using the old
* skb and put it at the tail of the sc->rx.rxbuf list for * skb and put it at the tail of the sc->rx.rxbuf list for
* processing. */ * processing. */
if (!requeue_skb) if (!requeue_skb) {
RX_STAT_INC(rx_oom_err);
goto requeue_drop_frag; goto requeue_drop_frag;
}
/* Unmap the frame */ /* Unmap the frame */
dma_unmap_single(sc->dev, bf->bf_buf_addr, dma_unmap_single(sc->dev, bf->bf_buf_addr,
...@@ -1899,6 +1913,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1899,6 +1913,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
} }
if (rs.rs_more) { if (rs.rs_more) {
RX_STAT_INC(rx_frags);
/* /*
* rs_more indicates chained descriptors which can be * rs_more indicates chained descriptors which can be
* used to link buffers together for a sort of * used to link buffers together for a sort of
...@@ -1908,6 +1923,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1908,6 +1923,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
/* too many fragments - cannot handle frame */ /* too many fragments - cannot handle frame */
dev_kfree_skb_any(sc->rx.frag); dev_kfree_skb_any(sc->rx.frag);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
RX_STAT_INC(rx_too_many_frags_err);
skb = NULL; skb = NULL;
} }
sc->rx.frag = skb; sc->rx.frag = skb;
...@@ -1919,6 +1935,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ...@@ -1919,6 +1935,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) { if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
RX_STAT_INC(rx_oom_err);
goto requeue_drop_frag; goto requeue_drop_frag;
} }
......
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