aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h5
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.c121
2 files changed, 41 insertions, 85 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index c4d66e066dc9..9a58214135b9 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -652,10 +652,9 @@ struct ath6kl {
652 652
653#ifdef CONFIG_ATH6KL_DEBUG 653#ifdef CONFIG_ATH6KL_DEBUG
654 struct { 654 struct {
655 struct circ_buf fwlog_buf; 655 struct sk_buff_head fwlog_queue;
656 spinlock_t fwlog_lock;
657 void *fwlog_tmp;
658 u32 fwlog_mask; 656 u32 fwlog_mask;
657
659 unsigned int dbgfs_diag_reg; 658 unsigned int dbgfs_diag_reg;
660 u32 diag_reg_addr_wr; 659 u32 diag_reg_addr_wr;
661 u32 diag_reg_val_wr; 660 u32 diag_reg_val_wr;
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index d832058816fe..98b5f15f622e 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -16,7 +16,7 @@
16 16
17#include "core.h" 17#include "core.h"
18 18
19#include <linux/circ_buf.h> 19#include <linux/skbuff.h>
20#include <linux/fs.h> 20#include <linux/fs.h>
21#include <linux/vmalloc.h> 21#include <linux/vmalloc.h>
22#include <linux/export.h> 22#include <linux/export.h>
@@ -32,9 +32,8 @@ struct ath6kl_fwlog_slot {
32 u8 payload[0]; 32 u8 payload[0];
33}; 33};
34 34
35#define ATH6KL_FWLOG_SIZE 32768 35#define ATH6KL_FWLOG_MAX_ENTRIES 20
36#define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \ 36
37 ATH6KL_FWLOG_PAYLOAD_SIZE)
38#define ATH6KL_FWLOG_VALID_MASK 0x1ffff 37#define ATH6KL_FWLOG_VALID_MASK 0x1ffff
39 38
40int ath6kl_printk(const char *level, const char *fmt, ...) 39int ath6kl_printk(const char *level, const char *fmt, ...)
@@ -268,105 +267,77 @@ static const struct file_operations fops_war_stats = {
268 .llseek = default_llseek, 267 .llseek = default_llseek,
269}; 268};
270 269
271static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf,
272 size_t buf_len)
273{
274 struct circ_buf *fwlog = &ar->debug.fwlog_buf;
275 size_t space;
276 int i;
277
278 /* entries must all be equal size */
279 if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE))
280 return;
281
282 space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE);
283 if (space < buf_len)
284 /* discard oldest slot */
285 fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) &
286 (ATH6KL_FWLOG_SIZE - 1);
287
288 for (i = 0; i < buf_len; i += space) {
289 space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail,
290 ATH6KL_FWLOG_SIZE);
291
292 if ((size_t) space > buf_len - i)
293 space = buf_len - i;
294
295 memcpy(&fwlog->buf[fwlog->head], buf, space);
296 fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1);
297 }
298
299}
300
301void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len) 270void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
302{ 271{
303 struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp; 272 struct ath6kl_fwlog_slot *slot;
273 struct sk_buff *skb;
304 size_t slot_len; 274 size_t slot_len;
305 275
306 if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) 276 if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
307 return; 277 return;
308 278
309 spin_lock_bh(&ar->debug.fwlog_lock); 279 slot_len = sizeof(*slot) + len;
310 280
281 skb = alloc_skb(slot_len, GFP_KERNEL);
282 if (!skb)
283 return;
284
285 slot = (struct ath6kl_fwlog_slot *) skb_put(skb, slot_len);
311 slot->timestamp = cpu_to_le32(jiffies); 286 slot->timestamp = cpu_to_le32(jiffies);
312 slot->length = cpu_to_le32(len); 287 slot->length = cpu_to_le32(len);
313 memcpy(slot->payload, buf, len); 288 memcpy(slot->payload, buf, len);
314 289
315 slot_len = sizeof(*slot) + len; 290 spin_lock(&ar->debug.fwlog_queue.lock);
316 291
317 if (slot_len < ATH6KL_FWLOG_SLOT_SIZE) 292 __skb_queue_tail(&ar->debug.fwlog_queue, skb);
318 memset(slot->payload + len, 0,
319 ATH6KL_FWLOG_SLOT_SIZE - slot_len);
320 293
321 ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE); 294 /* drop oldest entries */
295 while (skb_queue_len(&ar->debug.fwlog_queue) >
296 ATH6KL_FWLOG_MAX_ENTRIES) {
297 skb = __skb_dequeue(&ar->debug.fwlog_queue);
298 kfree_skb(skb);
299 }
322 300
323 spin_unlock_bh(&ar->debug.fwlog_lock); 301 spin_unlock(&ar->debug.fwlog_queue.lock);
324}
325 302
326static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar) 303 return;
327{
328 return CIRC_CNT(ar->debug.fwlog_buf.head,
329 ar->debug.fwlog_buf.tail,
330 ATH6KL_FWLOG_SLOT_SIZE) == 0;
331} 304}
332 305
333static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf, 306static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
334 size_t count, loff_t *ppos) 307 size_t count, loff_t *ppos)
335{ 308{
336 struct ath6kl *ar = file->private_data; 309 struct ath6kl *ar = file->private_data;
337 struct circ_buf *fwlog = &ar->debug.fwlog_buf; 310 struct sk_buff *skb;
338 size_t len = 0, buf_len = count;
339 ssize_t ret_cnt; 311 ssize_t ret_cnt;
312 size_t len = 0;
340 char *buf; 313 char *buf;
341 int ccnt;
342 314
343 buf = vmalloc(buf_len); 315 buf = vmalloc(count);
344 if (!buf) 316 if (!buf)
345 return -ENOMEM; 317 return -ENOMEM;
346 318
347 /* read undelivered logs from firmware */ 319 /* read undelivered logs from firmware */
348 ath6kl_read_fwlogs(ar); 320 ath6kl_read_fwlogs(ar);
349 321
350 spin_lock_bh(&ar->debug.fwlog_lock); 322 spin_lock(&ar->debug.fwlog_queue.lock);
351 323
352 while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) { 324 while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) {
353 ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail, 325 if (skb->len > count - len) {
354 ATH6KL_FWLOG_SIZE); 326 /* not enough space, put skb back and leave */
327 __skb_queue_head(&ar->debug.fwlog_queue, skb);
328 break;
329 }
355 330
356 if ((size_t) ccnt > buf_len - len)
357 ccnt = buf_len - len;
358 331
359 memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt); 332 memcpy(buf + len, skb->data, skb->len);
360 len += ccnt; 333 len += skb->len;
361 334
362 fwlog->tail = (fwlog->tail + ccnt) & 335 kfree_skb(skb);
363 (ATH6KL_FWLOG_SIZE - 1);
364 } 336 }
365 337
366 spin_unlock_bh(&ar->debug.fwlog_lock); 338 spin_unlock(&ar->debug.fwlog_queue.lock);
367 339
368 if (WARN_ON(len > buf_len)) 340 /* FIXME: what to do if len == 0? */
369 len = buf_len;
370 341
371 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 342 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
372 343
@@ -1651,17 +1622,7 @@ static const struct file_operations fops_power_params = {
1651 1622
1652int ath6kl_debug_init(struct ath6kl *ar) 1623int ath6kl_debug_init(struct ath6kl *ar)
1653{ 1624{
1654 ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE); 1625 skb_queue_head_init(&ar->debug.fwlog_queue);
1655 if (ar->debug.fwlog_buf.buf == NULL)
1656 return -ENOMEM;
1657
1658 ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL);
1659 if (ar->debug.fwlog_tmp == NULL) {
1660 vfree(ar->debug.fwlog_buf.buf);
1661 return -ENOMEM;
1662 }
1663
1664 spin_lock_init(&ar->debug.fwlog_lock);
1665 1626
1666 /* 1627 /*
1667 * Actually we are lying here but don't know how to read the mask 1628 * Actually we are lying here but don't know how to read the mask
@@ -1671,11 +1632,8 @@ int ath6kl_debug_init(struct ath6kl *ar)
1671 1632
1672 ar->debugfs_phy = debugfs_create_dir("ath6kl", 1633 ar->debugfs_phy = debugfs_create_dir("ath6kl",
1673 ar->wiphy->debugfsdir); 1634 ar->wiphy->debugfsdir);
1674 if (!ar->debugfs_phy) { 1635 if (!ar->debugfs_phy)
1675 vfree(ar->debug.fwlog_buf.buf);
1676 kfree(ar->debug.fwlog_tmp);
1677 return -ENOMEM; 1636 return -ENOMEM;
1678 }
1679 1637
1680 debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, 1638 debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
1681 &fops_tgt_stats); 1639 &fops_tgt_stats);
@@ -1742,8 +1700,7 @@ int ath6kl_debug_init(struct ath6kl *ar)
1742 1700
1743void ath6kl_debug_cleanup(struct ath6kl *ar) 1701void ath6kl_debug_cleanup(struct ath6kl *ar)
1744{ 1702{
1745 vfree(ar->debug.fwlog_buf.buf); 1703 skb_queue_purge(&ar->debug.fwlog_queue);
1746 kfree(ar->debug.fwlog_tmp);
1747 kfree(ar->debug.roam_tbl); 1704 kfree(ar->debug.roam_tbl);
1748} 1705}
1749 1706