diff options
author | Michael Buesch <mb@bu3sch.de> | 2008-03-07 09:50:02 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-03-07 16:02:59 -0500 |
commit | 57df40d278df552ad5fb4926fa05d06065c8150c (patch) | |
tree | 6c5e7219869c53a606b1c597484da2f6a1751f62 | |
parent | b27faf8ebf256429df8851477e02609448c0781f (diff) |
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 @@ | |||
38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
39 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
40 | #include <linux/etherdevice.h> | 40 | #include <linux/etherdevice.h> |
41 | #include <asm/div64.h> | ||
41 | 42 | ||
42 | 43 | ||
43 | /* 32bit DMA ops. */ | 44 | /* 32bit DMA ops. */ |
@@ -878,6 +879,17 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
878 | goto out; | 879 | goto out; |
879 | } | 880 | } |
880 | 881 | ||
882 | #define divide(a, b) ({ \ | ||
883 | typeof(a) __a = a; \ | ||
884 | do_div(__a, b); \ | ||
885 | __a; \ | ||
886 | }) | ||
887 | |||
888 | #define modulo(a, b) ({ \ | ||
889 | typeof(a) __a = a; \ | ||
890 | do_div(__a, b); \ | ||
891 | }) | ||
892 | |||
881 | /* Main cleanup function. */ | 893 | /* Main cleanup function. */ |
882 | static void b43_destroy_dmaring(struct b43_dmaring *ring, | 894 | static void b43_destroy_dmaring(struct b43_dmaring *ring, |
883 | const char *ringname) | 895 | const char *ringname) |
@@ -885,9 +897,34 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring, | |||
885 | if (!ring) | 897 | if (!ring) |
886 | return; | 898 | return; |
887 | 899 | ||
888 | b43dbg(ring->dev->wl, "DMA-%u %s max used slots: %d/%d\n", | 900 | #ifdef CONFIG_B43_DEBUG |
889 | (unsigned int)(ring->type), ringname, | 901 | { |
890 | ring->max_used_slots, ring->nr_slots); | 902 | /* Print some statistics. */ |
903 | u64 failed_packets = ring->nr_failed_tx_packets; | ||
904 | u64 succeed_packets = ring->nr_succeed_tx_packets; | ||
905 | u64 nr_packets = failed_packets + succeed_packets; | ||
906 | u64 permille_failed = 0, average_tries = 0; | ||
907 | |||
908 | if (nr_packets) | ||
909 | permille_failed = divide(failed_packets * 1000, nr_packets); | ||
910 | if (nr_packets) | ||
911 | average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets); | ||
912 | |||
913 | b43dbg(ring->dev->wl, "DMA-%u %s: " | ||
914 | "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, " | ||
915 | "Average tries %llu.%02llu\n", | ||
916 | (unsigned int)(ring->type), ringname, | ||
917 | ring->max_used_slots, | ||
918 | ring->nr_slots, | ||
919 | (unsigned long long)failed_packets, | ||
920 | (unsigned long long)succeed_packets, | ||
921 | (unsigned long long)divide(permille_failed, 10), | ||
922 | (unsigned long long)modulo(permille_failed, 10), | ||
923 | (unsigned long long)divide(average_tries, 100), | ||
924 | (unsigned long long)modulo(average_tries, 100)); | ||
925 | } | ||
926 | #endif /* DEBUG */ | ||
927 | |||
891 | /* Device IRQs are disabled prior entering this function, | 928 | /* Device IRQs are disabled prior entering this function, |
892 | * so no need to take care of concurrency with rx handler stuff. | 929 | * so no need to take care of concurrency with rx handler stuff. |
893 | */ | 930 | */ |
@@ -1270,6 +1307,38 @@ out_unlock: | |||
1270 | return err; | 1307 | return err; |
1271 | } | 1308 | } |
1272 | 1309 | ||
1310 | static void b43_fill_txstatus_report(struct b43_dmaring *ring, | ||
1311 | struct ieee80211_tx_status *report, | ||
1312 | const struct b43_txstatus *status) | ||
1313 | { | ||
1314 | bool frame_failed = 0; | ||
1315 | |||
1316 | if (status->acked) { | ||
1317 | /* The frame was ACKed. */ | ||
1318 | report->flags |= IEEE80211_TX_STATUS_ACK; | ||
1319 | } else { | ||
1320 | /* The frame was not ACKed... */ | ||
1321 | if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) { | ||
1322 | /* ...but we expected an ACK. */ | ||
1323 | frame_failed = 1; | ||
1324 | report->excessive_retries = 1; | ||
1325 | } | ||
1326 | } | ||
1327 | if (status->frame_count == 0) { | ||
1328 | /* The frame was not transmitted at all. */ | ||
1329 | report->retry_count = 0; | ||
1330 | } else { | ||
1331 | report->retry_count = status->frame_count - 1; | ||
1332 | #ifdef CONFIG_B43_DEBUG | ||
1333 | if (frame_failed) | ||
1334 | ring->nr_failed_tx_packets++; | ||
1335 | else | ||
1336 | ring->nr_succeed_tx_packets++; | ||
1337 | ring->nr_total_packet_tries += status->frame_count; | ||
1338 | #endif /* DEBUG */ | ||
1339 | } | ||
1340 | } | ||
1341 | |||
1273 | void b43_dma_handle_txstatus(struct b43_wldev *dev, | 1342 | void b43_dma_handle_txstatus(struct b43_wldev *dev, |
1274 | const struct b43_txstatus *status) | 1343 | const struct b43_txstatus *status) |
1275 | { | 1344 | { |
@@ -1304,18 +1373,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1304 | * status of the transmission. | 1373 | * status of the transmission. |
1305 | * Some fields of txstat are already filled in dma_tx(). | 1374 | * Some fields of txstat are already filled in dma_tx(). |
1306 | */ | 1375 | */ |
1307 | if (status->acked) { | 1376 | b43_fill_txstatus_report(ring, &(meta->txstat), status); |
1308 | meta->txstat.flags |= IEEE80211_TX_STATUS_ACK; | ||
1309 | } else { | ||
1310 | if (!(meta->txstat.control.flags | ||
1311 | & IEEE80211_TXCTL_NO_ACK)) | ||
1312 | meta->txstat.excessive_retries = 1; | ||
1313 | } | ||
1314 | if (status->frame_count == 0) { | ||
1315 | /* The frame was not transmitted at all. */ | ||
1316 | meta->txstat.retry_count = 0; | ||
1317 | } else | ||
1318 | meta->txstat.retry_count = status->frame_count - 1; | ||
1319 | ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, | 1377 | ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, |
1320 | &(meta->txstat)); | 1378 | &(meta->txstat)); |
1321 | /* skb is freed by ieee80211_tx_status_irqsafe() */ | 1379 | /* 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 { | |||
256 | int max_used_slots; | 256 | int max_used_slots; |
257 | /* Last time we injected a ring overflow. */ | 257 | /* Last time we injected a ring overflow. */ |
258 | unsigned long last_injected_overflow; | 258 | unsigned long last_injected_overflow; |
259 | #endif /* CONFIG_B43_DEBUG */ | 259 | /* Statistics: Number of successfully transmitted packets */ |
260 | u64 nr_succeed_tx_packets; | ||
261 | /* Statistics: Number of failed TX packets */ | ||
262 | u64 nr_failed_tx_packets; | ||
263 | /* Statistics: Total number of TX plus all retries. */ | ||
264 | u64 nr_total_packet_tries; | ||
265 | #endif /* CONFIG_B43_DEBUG */ | ||
260 | }; | 266 | }; |
261 | 267 | ||
262 | static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) | 268 | static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) |