diff options
author | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-09-27 16:33:28 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-09-28 12:03:47 -0400 |
commit | 9a7308341b71f3c5e88e6a30f9d6a1cfb3bc2b4f (patch) | |
tree | dda46b7616fe1866d1efa07fc5cee5330be7e783 /drivers | |
parent | 1b4304da0adcc31727da3ee7f89dd180f4e65473 (diff) |
ath6kl: silence "invalid rate" warning
For some reason firmware is sending invalid rates when we try to
query current bitrate from ath6kl_get_station() and a warning is issued:
[ 3810.415720] ath6kl: invalid rate: 1935633515
[ 3811.105493] ath6kl: invalid rate: 1935633515
[ 3811.556063] ath6kl: invalid rate: 1935633515
As the warning happens way too often, convert the warning to a debug
message once we have a proper fix. But to make it easy to follow
how often the problem appears, add a debugfs to print
various statistics about workarounds and make this issue the first WAR.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/debug.c | 48 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/debug.h | 9 |
4 files changed, 64 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index c84f53d6523b..8d9fbd4a62b7 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -1365,7 +1365,9 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
1365 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 1365 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
1366 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | 1366 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; |
1367 | } else { | 1367 | } else { |
1368 | ath6kl_warn("invalid rate: %d\n", rate); | 1368 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1369 | "invalid rate from stats: %d\n", rate); | ||
1370 | ath6kl_debug_war(ar, ATH6KL_WAR_INVALID_RATE); | ||
1369 | return 0; | 1371 | return 0; |
1370 | } | 1372 | } |
1371 | 1373 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 9ecf22bd4fc9..6d8a4845baaf 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -525,6 +525,10 @@ struct ath6kl { | |||
525 | unsigned int dbgfs_diag_reg; | 525 | unsigned int dbgfs_diag_reg; |
526 | u32 diag_reg_addr_wr; | 526 | u32 diag_reg_addr_wr; |
527 | u32 diag_reg_val_wr; | 527 | u32 diag_reg_val_wr; |
528 | |||
529 | struct { | ||
530 | unsigned int invalid_rate; | ||
531 | } war_stats; | ||
528 | } debug; | 532 | } debug; |
529 | #endif /* CONFIG_ATH6KL_DEBUG */ | 533 | #endif /* CONFIG_ATH6KL_DEBUG */ |
530 | }; | 534 | }; |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 4fc83ccbf8bd..5237369cd521 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -192,6 +192,51 @@ static int ath6kl_debugfs_open(struct inode *inode, struct file *file) | |||
192 | return 0; | 192 | return 0; |
193 | } | 193 | } |
194 | 194 | ||
195 | void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) | ||
196 | { | ||
197 | switch (war) { | ||
198 | case ATH6KL_WAR_INVALID_RATE: | ||
199 | ar->debug.war_stats.invalid_rate++; | ||
200 | break; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | static ssize_t read_file_war_stats(struct file *file, char __user *user_buf, | ||
205 | size_t count, loff_t *ppos) | ||
206 | { | ||
207 | struct ath6kl *ar = file->private_data; | ||
208 | char *buf; | ||
209 | unsigned int len = 0, buf_len = 1500; | ||
210 | ssize_t ret_cnt; | ||
211 | |||
212 | buf = kzalloc(buf_len, GFP_KERNEL); | ||
213 | if (!buf) | ||
214 | return -ENOMEM; | ||
215 | |||
216 | len += scnprintf(buf + len, buf_len - len, "\n"); | ||
217 | len += scnprintf(buf + len, buf_len - len, "%25s\n", | ||
218 | "Workaround stats"); | ||
219 | len += scnprintf(buf + len, buf_len - len, "%25s\n\n", | ||
220 | "================="); | ||
221 | len += scnprintf(buf + len, buf_len - len, "%20s %10u\n", | ||
222 | "Invalid rates", ar->debug.war_stats.invalid_rate); | ||
223 | |||
224 | if (WARN_ON(len > buf_len)) | ||
225 | len = buf_len; | ||
226 | |||
227 | ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
228 | |||
229 | kfree(buf); | ||
230 | return ret_cnt; | ||
231 | } | ||
232 | |||
233 | static const struct file_operations fops_war_stats = { | ||
234 | .read = read_file_war_stats, | ||
235 | .open = ath6kl_debugfs_open, | ||
236 | .owner = THIS_MODULE, | ||
237 | .llseek = default_llseek, | ||
238 | }; | ||
239 | |||
195 | static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf, | 240 | static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf, |
196 | size_t buf_len) | 241 | size_t buf_len) |
197 | { | 242 | { |
@@ -873,6 +918,9 @@ int ath6kl_debug_init(struct ath6kl *ar) | |||
873 | debugfs_create_file("reg_write", S_IRUSR | S_IWUSR, | 918 | debugfs_create_file("reg_write", S_IRUSR | S_IWUSR, |
874 | ar->debugfs_phy, ar, &fops_diag_reg_write); | 919 | ar->debugfs_phy, ar, &fops_diag_reg_write); |
875 | 920 | ||
921 | debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar, | ||
922 | &fops_war_stats); | ||
923 | |||
876 | return 0; | 924 | return 0; |
877 | } | 925 | } |
878 | 926 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 89bf8e1138a3..91f4bc35f968 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -52,6 +52,10 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...) | |||
52 | 52 | ||
53 | #define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) | 53 | #define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) |
54 | 54 | ||
55 | enum ath6kl_war { | ||
56 | ATH6KL_WAR_INVALID_RATE, | ||
57 | }; | ||
58 | |||
55 | #ifdef CONFIG_ATH6KL_DEBUG | 59 | #ifdef CONFIG_ATH6KL_DEBUG |
56 | #define ath6kl_dbg(mask, fmt, ...) \ | 60 | #define ath6kl_dbg(mask, fmt, ...) \ |
57 | ({ \ | 61 | ({ \ |
@@ -79,6 +83,7 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, | |||
79 | struct ath6kl_irq_enable_reg *irq_en_reg); | 83 | struct ath6kl_irq_enable_reg *irq_en_reg); |
80 | void dump_cred_dist_stats(struct htc_target *target); | 84 | void dump_cred_dist_stats(struct htc_target *target); |
81 | void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len); | 85 | void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len); |
86 | void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war); | ||
82 | int ath6kl_debug_init(struct ath6kl *ar); | 87 | int ath6kl_debug_init(struct ath6kl *ar); |
83 | void ath6kl_debug_cleanup(struct ath6kl *ar); | 88 | void ath6kl_debug_cleanup(struct ath6kl *ar); |
84 | 89 | ||
@@ -110,6 +115,10 @@ static inline void ath6kl_debug_fwlog_event(struct ath6kl *ar, | |||
110 | { | 115 | { |
111 | } | 116 | } |
112 | 117 | ||
118 | static inline void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) | ||
119 | { | ||
120 | } | ||
121 | |||
113 | static inline int ath6kl_debug_init(struct ath6kl *ar) | 122 | static inline int ath6kl_debug_init(struct ath6kl *ar) |
114 | { | 123 | { |
115 | return 0; | 124 | return 0; |