diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/debug.c | 154 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/debug.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/init.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/target.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.c | 1 |
6 files changed, 181 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index cfbbad9feb9e..319e768d9ad6 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/rtnetlink.h> | 21 | #include <linux/rtnetlink.h> |
22 | #include <linux/firmware.h> | 22 | #include <linux/firmware.h> |
23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | #include <linux/circ_buf.h> | ||
24 | #include <net/cfg80211.h> | 25 | #include <net/cfg80211.h> |
25 | #include "htc.h" | 26 | #include "htc.h" |
26 | #include "wmi.h" | 27 | #include "wmi.h" |
@@ -467,6 +468,14 @@ struct ath6kl { | |||
467 | u32 send_action_id; | 468 | u32 send_action_id; |
468 | bool probe_req_report; | 469 | bool probe_req_report; |
469 | u16 next_chan; | 470 | u16 next_chan; |
471 | |||
472 | #ifdef CONFIG_ATH6KL_DEBUG | ||
473 | struct { | ||
474 | struct circ_buf fwlog_buf; | ||
475 | spinlock_t fwlog_lock; | ||
476 | void *fwlog_tmp; | ||
477 | } debug; | ||
478 | #endif /* CONFIG_ATH6KL_DEBUG */ | ||
470 | }; | 479 | }; |
471 | 480 | ||
472 | static inline void *ath6kl_priv(struct net_device *dev) | 481 | static inline void *ath6kl_priv(struct net_device *dev) |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 2b462876cec1..b2706da58149 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -15,7 +15,23 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "core.h" | 17 | #include "core.h" |
18 | |||
19 | #include <linux/circ_buf.h> | ||
20 | |||
18 | #include "debug.h" | 21 | #include "debug.h" |
22 | #include "target.h" | ||
23 | |||
24 | struct ath6kl_fwlog_slot { | ||
25 | __le32 timestamp; | ||
26 | __le32 length; | ||
27 | |||
28 | /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */ | ||
29 | u8 payload[0]; | ||
30 | }; | ||
31 | |||
32 | #define ATH6KL_FWLOG_SIZE 32768 | ||
33 | #define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \ | ||
34 | ATH6KL_FWLOG_PAYLOAD_SIZE) | ||
19 | 35 | ||
20 | int ath6kl_printk(const char *level, const char *fmt, ...) | 36 | int ath6kl_printk(const char *level, const char *fmt, ...) |
21 | { | 37 | { |
@@ -153,6 +169,117 @@ static int ath6kl_debugfs_open(struct inode *inode, struct file *file) | |||
153 | return 0; | 169 | return 0; |
154 | } | 170 | } |
155 | 171 | ||
172 | static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf, | ||
173 | size_t buf_len) | ||
174 | { | ||
175 | struct circ_buf *fwlog = &ar->debug.fwlog_buf; | ||
176 | size_t space; | ||
177 | int i; | ||
178 | |||
179 | /* entries must all be equal size */ | ||
180 | if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE)) | ||
181 | return; | ||
182 | |||
183 | space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE); | ||
184 | if (space < buf_len) | ||
185 | /* discard oldest slot */ | ||
186 | fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) & | ||
187 | (ATH6KL_FWLOG_SIZE - 1); | ||
188 | |||
189 | for (i = 0; i < buf_len; i += space) { | ||
190 | space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail, | ||
191 | ATH6KL_FWLOG_SIZE); | ||
192 | |||
193 | if ((size_t) space > buf_len - i) | ||
194 | space = buf_len - i; | ||
195 | |||
196 | memcpy(&fwlog->buf[fwlog->head], buf, space); | ||
197 | fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1); | ||
198 | } | ||
199 | |||
200 | } | ||
201 | |||
202 | void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len) | ||
203 | { | ||
204 | struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp; | ||
205 | size_t slot_len; | ||
206 | |||
207 | if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) | ||
208 | return; | ||
209 | |||
210 | spin_lock_bh(&ar->debug.fwlog_lock); | ||
211 | |||
212 | slot->timestamp = cpu_to_le32(jiffies); | ||
213 | slot->length = cpu_to_le32(len); | ||
214 | memcpy(slot->payload, buf, len); | ||
215 | |||
216 | slot_len = sizeof(*slot) + len; | ||
217 | |||
218 | if (slot_len < ATH6KL_FWLOG_SLOT_SIZE) | ||
219 | memset(slot->payload + len, 0, | ||
220 | ATH6KL_FWLOG_SLOT_SIZE - slot_len); | ||
221 | |||
222 | ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE); | ||
223 | |||
224 | spin_unlock_bh(&ar->debug.fwlog_lock); | ||
225 | } | ||
226 | |||
227 | static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar) | ||
228 | { | ||
229 | return CIRC_CNT(ar->debug.fwlog_buf.head, | ||
230 | ar->debug.fwlog_buf.tail, | ||
231 | ATH6KL_FWLOG_SLOT_SIZE) == 0; | ||
232 | } | ||
233 | |||
234 | static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf, | ||
235 | size_t count, loff_t *ppos) | ||
236 | { | ||
237 | struct ath6kl *ar = file->private_data; | ||
238 | struct circ_buf *fwlog = &ar->debug.fwlog_buf; | ||
239 | size_t len = 0, buf_len = count; | ||
240 | ssize_t ret_cnt; | ||
241 | char *buf; | ||
242 | int ccnt; | ||
243 | |||
244 | buf = vmalloc(buf_len); | ||
245 | if (!buf) | ||
246 | return -ENOMEM; | ||
247 | |||
248 | spin_lock_bh(&ar->debug.fwlog_lock); | ||
249 | |||
250 | while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) { | ||
251 | ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail, | ||
252 | ATH6KL_FWLOG_SIZE); | ||
253 | |||
254 | if ((size_t) ccnt > buf_len - len) | ||
255 | ccnt = buf_len - len; | ||
256 | |||
257 | memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt); | ||
258 | len += ccnt; | ||
259 | |||
260 | fwlog->tail = (fwlog->tail + ccnt) & | ||
261 | (ATH6KL_FWLOG_SIZE - 1); | ||
262 | } | ||
263 | |||
264 | spin_unlock_bh(&ar->debug.fwlog_lock); | ||
265 | |||
266 | if (WARN_ON(len > buf_len)) | ||
267 | len = buf_len; | ||
268 | |||
269 | ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
270 | |||
271 | vfree(buf); | ||
272 | |||
273 | return ret_cnt; | ||
274 | } | ||
275 | |||
276 | static const struct file_operations fops_fwlog = { | ||
277 | .open = ath6kl_debugfs_open, | ||
278 | .read = ath6kl_fwlog_read, | ||
279 | .owner = THIS_MODULE, | ||
280 | .llseek = default_llseek, | ||
281 | }; | ||
282 | |||
156 | static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, | 283 | static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, |
157 | size_t count, loff_t *ppos) | 284 | size_t count, loff_t *ppos) |
158 | { | 285 | { |
@@ -358,10 +485,25 @@ static const struct file_operations fops_credit_dist_stats = { | |||
358 | 485 | ||
359 | int ath6kl_debug_init(struct ath6kl *ar) | 486 | int ath6kl_debug_init(struct ath6kl *ar) |
360 | { | 487 | { |
488 | ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE); | ||
489 | if (ar->debug.fwlog_buf.buf == NULL) | ||
490 | return -ENOMEM; | ||
491 | |||
492 | ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL); | ||
493 | if (ar->debug.fwlog_tmp == NULL) { | ||
494 | vfree(ar->debug.fwlog_buf.buf); | ||
495 | return -ENOMEM; | ||
496 | } | ||
497 | |||
498 | spin_lock_init(&ar->debug.fwlog_lock); | ||
499 | |||
361 | ar->debugfs_phy = debugfs_create_dir("ath6kl", | 500 | ar->debugfs_phy = debugfs_create_dir("ath6kl", |
362 | ar->wdev->wiphy->debugfsdir); | 501 | ar->wdev->wiphy->debugfsdir); |
363 | if (!ar->debugfs_phy) | 502 | if (!ar->debugfs_phy) { |
503 | vfree(ar->debug.fwlog_buf.buf); | ||
504 | kfree(ar->debug.fwlog_tmp); | ||
364 | return -ENOMEM; | 505 | return -ENOMEM; |
506 | } | ||
365 | 507 | ||
366 | debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, | 508 | debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, |
367 | &fops_tgt_stats); | 509 | &fops_tgt_stats); |
@@ -369,6 +511,16 @@ int ath6kl_debug_init(struct ath6kl *ar) | |||
369 | debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar, | 511 | debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar, |
370 | &fops_credit_dist_stats); | 512 | &fops_credit_dist_stats); |
371 | 513 | ||
514 | debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar, | ||
515 | &fops_fwlog); | ||
516 | |||
372 | return 0; | 517 | return 0; |
373 | } | 518 | } |
519 | |||
520 | void ath6kl_debug_cleanup(struct ath6kl *ar) | ||
521 | { | ||
522 | vfree(ar->debug.fwlog_buf.buf); | ||
523 | kfree(ar->debug.fwlog_tmp); | ||
524 | } | ||
525 | |||
374 | #endif | 526 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index e8c9ea9ce02c..f0d64711b410 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -78,7 +78,10 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, | |||
78 | struct ath6kl_irq_proc_registers *irq_proc_reg, | 78 | struct ath6kl_irq_proc_registers *irq_proc_reg, |
79 | struct ath6kl_irq_enable_reg *irq_en_reg); | 79 | struct ath6kl_irq_enable_reg *irq_en_reg); |
80 | void dump_cred_dist_stats(struct htc_target *target); | 80 | void dump_cred_dist_stats(struct htc_target *target); |
81 | void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len); | ||
81 | int ath6kl_debug_init(struct ath6kl *ar); | 82 | int ath6kl_debug_init(struct ath6kl *ar); |
83 | void ath6kl_debug_cleanup(struct ath6kl *ar); | ||
84 | |||
82 | #else | 85 | #else |
83 | static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, | 86 | static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, |
84 | const char *fmt, ...) | 87 | const char *fmt, ...) |
@@ -101,9 +104,19 @@ static inline void ath6kl_dump_registers(struct ath6kl_device *dev, | |||
101 | static inline void dump_cred_dist_stats(struct htc_target *target) | 104 | static inline void dump_cred_dist_stats(struct htc_target *target) |
102 | { | 105 | { |
103 | } | 106 | } |
107 | |||
108 | void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len) | ||
109 | { | ||
110 | } | ||
111 | |||
104 | static inline int ath6kl_debug_init(struct ath6kl *ar) | 112 | static inline int ath6kl_debug_init(struct ath6kl *ar) |
105 | { | 113 | { |
106 | return 0; | 114 | return 0; |
107 | } | 115 | } |
116 | |||
117 | void ath6kl_debug_cleanup(struct ath6kl *ar) | ||
118 | { | ||
119 | } | ||
120 | |||
108 | #endif | 121 | #endif |
109 | #endif | 122 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 96953be5cd73..a638c3c9b79b 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -1389,6 +1389,8 @@ void ath6kl_destroy(struct net_device *dev, unsigned int unregister) | |||
1389 | 1389 | ||
1390 | ath6kl_bmi_cleanup(ar); | 1390 | ath6kl_bmi_cleanup(ar); |
1391 | 1391 | ||
1392 | ath6kl_debug_cleanup(ar); | ||
1393 | |||
1392 | if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) { | 1394 | if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) { |
1393 | unregister_netdev(dev); | 1395 | unregister_netdev(dev); |
1394 | clear_bit(NETDEV_REGISTERED, &ar->flag); | 1396 | clear_bit(NETDEV_REGISTERED, &ar->flag); |
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h index 53e2c786f8e3..6c66a08e1793 100644 --- a/drivers/net/wireless/ath/ath6kl/target.h +++ b/drivers/net/wireless/ath/ath6kl/target.h | |||
@@ -340,4 +340,7 @@ struct host_interest { | |||
340 | #define AR6004_REV1_BOARD_DATA_ADDRESS 0x435400 | 340 | #define AR6004_REV1_BOARD_DATA_ADDRESS 0x435400 |
341 | #define AR6004_REV1_BOARD_EXT_DATA_ADDRESS 0x437000 | 341 | #define AR6004_REV1_BOARD_EXT_DATA_ADDRESS 0x437000 |
342 | #define AR6004_REV1_RAM_RESERVE_SIZE 11264 | 342 | #define AR6004_REV1_RAM_RESERVE_SIZE 11264 |
343 | |||
344 | #define ATH6KL_FWLOG_PAYLOAD_SIZE 1500 | ||
345 | |||
343 | #endif | 346 | #endif |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index c34e36806dac..954d5e18e888 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -2903,6 +2903,7 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) | |||
2903 | case WMIX_HB_CHALLENGE_RESP_EVENTID: | 2903 | case WMIX_HB_CHALLENGE_RESP_EVENTID: |
2904 | break; | 2904 | break; |
2905 | case WMIX_DBGLOG_EVENTID: | 2905 | case WMIX_DBGLOG_EVENTID: |
2906 | ath6kl_debug_fwlog_event(wmi->parent_dev, datap, len); | ||
2906 | break; | 2907 | break; |
2907 | default: | 2908 | default: |
2908 | ath6kl_err("unknown cmd id 0x%x\n", id); | 2909 | ath6kl_err("unknown cmd id 0x%x\n", id); |