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: Ben Greear <greearb@candelatech.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
a5a0bca1d8
commit
150721894e
@ -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,
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
#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 {
|
|||||||
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 {
|
|||||||
* @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 {
|
|||||||
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);
|
|||||||
|
|
||||||
#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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
* 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)
|
|||||||
* 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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
/* 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)
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user