diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-03-07 17:50:02 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-08 00:02:59 +0300 |
commit | 57df40d278df552ad5fb4926fa05d06065c8150c (patch) | |
tree | 6c5e7219869c53a606b1c597484da2f6a1751f62 | |
parent | b27faf8ebf256429df8851477e02609448c0781f (diff) | |
download | linux-57df40d278df552ad5fb4926fa05d06065c8150c.tar.xz |
b43: Add TX statistics debugging counters
This adds a few debugging counters, that are useful for debugging the
"card does not transmit" or "connection is unstable" kind of problems.
It's also useful for tuning an RC algorithm.
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/b43/dma.c | 88 | ||||
-rw-r--r-- | drivers/net/wireless/b43/dma.h | 8 |
2 files changed, 80 insertions, 16 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3b1f0e76b9a4..8e9497c526af 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -38,6 +38,7 @@ #include <linux/delay.h> #include <linux/skbuff.h> #include <linux/etherdevice.h> +#include <asm/div64.h> /* 32bit DMA ops. */ @@ -878,6 +879,17 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, goto out; } +#define divide(a, b) ({ \ + typeof(a) __a = a; \ + do_div(__a, b); \ + __a; \ + }) + +#define modulo(a, b) ({ \ + typeof(a) __a = a; \ + do_div(__a, b); \ + }) + /* Main cleanup function. */ static void b43_destroy_dmaring(struct b43_dmaring *ring, const char *ringname) @@ -885,9 +897,34 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring, if (!ring) return; - b43dbg(ring->dev->wl, "DMA-%u %s max used slots: %d/%d\n", - (unsigned int)(ring->type), ringname, - ring->max_used_slots, ring->nr_slots); +#ifdef CONFIG_B43_DEBUG + { + /* Print some statistics. */ + u64 failed_packets = ring->nr_failed_tx_packets; + u64 succeed_packets = ring->nr_succeed_tx_packets; + u64 nr_packets = failed_packets + succeed_packets; + u64 permille_failed = 0, average_tries = 0; + + if (nr_packets) + permille_failed = divide(failed_packets * 1000, nr_packets); + if (nr_packets) + average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets); + + b43dbg(ring->dev->wl, "DMA-%u %s: " + "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, " + "Average tries %llu.%02llu\n", + (unsigned int)(ring->type), ringname, + ring->max_used_slots, + ring->nr_slots, + (unsigned long long)failed_packets, + (unsigned long long)succeed_packets, + (unsigned long long)divide(permille_failed, 10), + (unsigned long long)modulo(permille_failed, 10), + (unsigned long long)divide(average_tries, 100), + (unsigned long long)modulo(average_tries, 100)); + } +#endif /* DEBUG */ + /* Device IRQs are disabled prior entering this function, * so no need to take care of concurrency with rx handler stuff. */ @@ -1270,6 +1307,38 @@ out_unlock: return err; } +static void b43_fill_txstatus_report(struct b43_dmaring *ring, + struct ieee80211_tx_status *report, + const struct b43_txstatus *status) +{ + bool frame_failed = 0; + + if (status->acked) { + /* The frame was ACKed. */ + report->flags |= IEEE80211_TX_STATUS_ACK; + } else { + /* The frame was not ACKed... */ + if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) { + /* ...but we expected an ACK. */ + frame_failed = 1; + report->excessive_retries = 1; + } + } + if (status->frame_count == 0) { + /* The frame was not transmitted at all. */ + report->retry_count = 0; + } else { + report->retry_count = status->frame_count - 1; +#ifdef CONFIG_B43_DEBUG + if (frame_failed) + ring->nr_failed_tx_packets++; + else + ring->nr_succeed_tx_packets++; + ring->nr_total_packet_tries += status->frame_count; +#endif /* DEBUG */ + } +} + void b43_dma_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status) { @@ -1304,18 +1373,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, * status of the transmission. * Some fields of txstat are already filled in dma_tx(). */ - if (status->acked) { - meta->txstat.flags |= IEEE80211_TX_STATUS_ACK; - } else { - if (!(meta->txstat.control.flags - & IEEE80211_TXCTL_NO_ACK)) - meta->txstat.excessive_retries = 1; - } - if (status->frame_count == 0) { - /* The frame was not transmitted at all. */ - meta->txstat.retry_count = 0; - } else - meta->txstat.retry_count = status->frame_count - 1; + b43_fill_txstatus_report(ring, &(meta->txstat), status); ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, &(meta->txstat)); /* skb is freed by ieee80211_tx_status_irqsafe() */ diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 9336286d97a7..ea27085dec0e 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -256,7 +256,13 @@ struct b43_dmaring { int max_used_slots; /* Last time we injected a ring overflow. */ unsigned long last_injected_overflow; -#endif /* CONFIG_B43_DEBUG */ + /* Statistics: Number of successfully transmitted packets */ + u64 nr_succeed_tx_packets; + /* Statistics: Number of failed TX packets */ + u64 nr_failed_tx_packets; + /* Statistics: Total number of TX plus all retries. */ + u64 nr_total_packet_tries; +#endif /* CONFIG_B43_DEBUG */ }; static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) |