blob: 239c092d3e11ecf058b6de46af489e4e19c64235 [file] [log] [blame]
Kalle Valobdcd8172011-07-18 00:22:30 +03001/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
Kalle Valobdf53962011-09-02 10:32:04 +030018
19#include <linux/circ_buf.h>
Kalle Valo939f1cc2011-09-02 10:32:04 +030020#include <linux/fs.h>
Kalle Valobdf53962011-09-02 10:32:04 +030021
Kalle Valobdcd8172011-07-18 00:22:30 +030022#include "debug.h"
Kalle Valobdf53962011-09-02 10:32:04 +030023#include "target.h"
24
25struct ath6kl_fwlog_slot {
26 __le32 timestamp;
27 __le32 length;
28
29 /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */
30 u8 payload[0];
31};
32
33#define ATH6KL_FWLOG_SIZE 32768
34#define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \
35 ATH6KL_FWLOG_PAYLOAD_SIZE)
Kalle Valo939f1cc2011-09-02 10:32:04 +030036#define ATH6KL_FWLOG_VALID_MASK 0x1ffff
Kalle Valobdcd8172011-07-18 00:22:30 +030037
38int ath6kl_printk(const char *level, const char *fmt, ...)
39{
40 struct va_format vaf;
41 va_list args;
42 int rtn;
43
44 va_start(args, fmt);
45
46 vaf.fmt = fmt;
47 vaf.va = &args;
48
49 rtn = printk("%sath6kl: %pV", level, &vaf);
50
51 va_end(args);
52
53 return rtn;
54}
55
56#ifdef CONFIG_ATH6KL_DEBUG
57void ath6kl_dump_registers(struct ath6kl_device *dev,
58 struct ath6kl_irq_proc_registers *irq_proc_reg,
59 struct ath6kl_irq_enable_reg *irq_enable_reg)
60{
61
62 ath6kl_dbg(ATH6KL_DBG_ANY, ("<------- Register Table -------->\n"));
63
64 if (irq_proc_reg != NULL) {
65 ath6kl_dbg(ATH6KL_DBG_ANY,
66 "Host Int status: 0x%x\n",
67 irq_proc_reg->host_int_status);
68 ath6kl_dbg(ATH6KL_DBG_ANY,
69 "CPU Int status: 0x%x\n",
70 irq_proc_reg->cpu_int_status);
71 ath6kl_dbg(ATH6KL_DBG_ANY,
72 "Error Int status: 0x%x\n",
73 irq_proc_reg->error_int_status);
74 ath6kl_dbg(ATH6KL_DBG_ANY,
75 "Counter Int status: 0x%x\n",
76 irq_proc_reg->counter_int_status);
77 ath6kl_dbg(ATH6KL_DBG_ANY,
78 "Mbox Frame: 0x%x\n",
79 irq_proc_reg->mbox_frame);
80 ath6kl_dbg(ATH6KL_DBG_ANY,
81 "Rx Lookahead Valid: 0x%x\n",
82 irq_proc_reg->rx_lkahd_valid);
83 ath6kl_dbg(ATH6KL_DBG_ANY,
84 "Rx Lookahead 0: 0x%x\n",
85 irq_proc_reg->rx_lkahd[0]);
86 ath6kl_dbg(ATH6KL_DBG_ANY,
87 "Rx Lookahead 1: 0x%x\n",
88 irq_proc_reg->rx_lkahd[1]);
89
90 if (dev->ar->mbox_info.gmbox_addr != 0) {
91 /*
92 * If the target supports GMBOX hardware, dump some
93 * additional state.
94 */
95 ath6kl_dbg(ATH6KL_DBG_ANY,
96 "GMBOX Host Int status 2: 0x%x\n",
97 irq_proc_reg->host_int_status2);
98 ath6kl_dbg(ATH6KL_DBG_ANY,
99 "GMBOX RX Avail: 0x%x\n",
100 irq_proc_reg->gmbox_rx_avail);
101 ath6kl_dbg(ATH6KL_DBG_ANY,
102 "GMBOX lookahead alias 0: 0x%x\n",
103 irq_proc_reg->rx_gmbox_lkahd_alias[0]);
104 ath6kl_dbg(ATH6KL_DBG_ANY,
105 "GMBOX lookahead alias 1: 0x%x\n",
106 irq_proc_reg->rx_gmbox_lkahd_alias[1]);
107 }
108
109 }
110
111 if (irq_enable_reg != NULL) {
112 ath6kl_dbg(ATH6KL_DBG_ANY,
113 "Int status Enable: 0x%x\n",
114 irq_enable_reg->int_status_en);
115 ath6kl_dbg(ATH6KL_DBG_ANY, "Counter Int status Enable: 0x%x\n",
116 irq_enable_reg->cntr_int_status_en);
117 }
118 ath6kl_dbg(ATH6KL_DBG_ANY, "<------------------------------->\n");
119}
120
121static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist)
122{
123 ath6kl_dbg(ATH6KL_DBG_ANY,
124 "--- endpoint: %d svc_id: 0x%X ---\n",
125 ep_dist->endpoint, ep_dist->svc_id);
126 ath6kl_dbg(ATH6KL_DBG_ANY, " dist_flags : 0x%X\n",
127 ep_dist->dist_flags);
128 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_norm : %d\n",
129 ep_dist->cred_norm);
130 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_min : %d\n",
131 ep_dist->cred_min);
132 ath6kl_dbg(ATH6KL_DBG_ANY, " credits : %d\n",
133 ep_dist->credits);
134 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_assngd : %d\n",
135 ep_dist->cred_assngd);
136 ath6kl_dbg(ATH6KL_DBG_ANY, " seek_cred : %d\n",
137 ep_dist->seek_cred);
138 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_sz : %d\n",
139 ep_dist->cred_sz);
140 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_per_msg : %d\n",
141 ep_dist->cred_per_msg);
142 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_to_dist : %d\n",
143 ep_dist->cred_to_dist);
144 ath6kl_dbg(ATH6KL_DBG_ANY, " txq_depth : %d\n",
145 get_queue_depth(&((struct htc_endpoint *)
146 ep_dist->htc_rsvd)->txq));
147 ath6kl_dbg(ATH6KL_DBG_ANY,
148 "----------------------------------\n");
149}
150
151void dump_cred_dist_stats(struct htc_target *target)
152{
153 struct htc_endpoint_credit_dist *ep_list;
154
155 if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_TRC))
156 return;
157
158 list_for_each_entry(ep_list, &target->cred_dist_list, list)
159 dump_cred_dist(ep_list);
160
161 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:%p dist:%p\n",
162 target->cred_dist_cntxt, NULL);
163 ath6kl_dbg(ATH6KL_DBG_TRC, "credit distribution, total : %d, free : %d\n",
164 target->cred_dist_cntxt->total_avail_credits,
165 target->cred_dist_cntxt->cur_free_credits);
166}
167
Vasanthakumar Thiagarajan03f68a92011-08-26 13:06:32 +0530168static int ath6kl_debugfs_open(struct inode *inode, struct file *file)
169{
170 file->private_data = inode->i_private;
171 return 0;
172}
173
Kalle Valobdf53962011-09-02 10:32:04 +0300174static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf,
175 size_t buf_len)
176{
177 struct circ_buf *fwlog = &ar->debug.fwlog_buf;
178 size_t space;
179 int i;
180
181 /* entries must all be equal size */
182 if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE))
183 return;
184
185 space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE);
186 if (space < buf_len)
187 /* discard oldest slot */
188 fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) &
189 (ATH6KL_FWLOG_SIZE - 1);
190
191 for (i = 0; i < buf_len; i += space) {
192 space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail,
193 ATH6KL_FWLOG_SIZE);
194
195 if ((size_t) space > buf_len - i)
196 space = buf_len - i;
197
198 memcpy(&fwlog->buf[fwlog->head], buf, space);
199 fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1);
200 }
201
202}
203
204void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
205{
206 struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp;
207 size_t slot_len;
208
209 if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
210 return;
211
212 spin_lock_bh(&ar->debug.fwlog_lock);
213
214 slot->timestamp = cpu_to_le32(jiffies);
215 slot->length = cpu_to_le32(len);
216 memcpy(slot->payload, buf, len);
217
218 slot_len = sizeof(*slot) + len;
219
220 if (slot_len < ATH6KL_FWLOG_SLOT_SIZE)
221 memset(slot->payload + len, 0,
222 ATH6KL_FWLOG_SLOT_SIZE - slot_len);
223
224 ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE);
225
226 spin_unlock_bh(&ar->debug.fwlog_lock);
227}
228
229static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar)
230{
231 return CIRC_CNT(ar->debug.fwlog_buf.head,
232 ar->debug.fwlog_buf.tail,
233 ATH6KL_FWLOG_SLOT_SIZE) == 0;
234}
235
236static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
237 size_t count, loff_t *ppos)
238{
239 struct ath6kl *ar = file->private_data;
240 struct circ_buf *fwlog = &ar->debug.fwlog_buf;
241 size_t len = 0, buf_len = count;
242 ssize_t ret_cnt;
243 char *buf;
244 int ccnt;
245
246 buf = vmalloc(buf_len);
247 if (!buf)
248 return -ENOMEM;
249
250 spin_lock_bh(&ar->debug.fwlog_lock);
251
252 while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) {
253 ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail,
254 ATH6KL_FWLOG_SIZE);
255
256 if ((size_t) ccnt > buf_len - len)
257 ccnt = buf_len - len;
258
259 memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt);
260 len += ccnt;
261
262 fwlog->tail = (fwlog->tail + ccnt) &
263 (ATH6KL_FWLOG_SIZE - 1);
264 }
265
266 spin_unlock_bh(&ar->debug.fwlog_lock);
267
268 if (WARN_ON(len > buf_len))
269 len = buf_len;
270
271 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
272
273 vfree(buf);
274
275 return ret_cnt;
276}
277
278static const struct file_operations fops_fwlog = {
279 .open = ath6kl_debugfs_open,
280 .read = ath6kl_fwlog_read,
281 .owner = THIS_MODULE,
282 .llseek = default_llseek,
283};
284
Kalle Valo939f1cc2011-09-02 10:32:04 +0300285static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf,
286 size_t count, loff_t *ppos)
287{
288 struct ath6kl *ar = file->private_data;
289 char buf[16];
290 int len;
291
292 len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask);
293
294 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
295}
296
297static ssize_t ath6kl_fwlog_mask_write(struct file *file,
298 const char __user *user_buf,
299 size_t count, loff_t *ppos)
300{
301 struct ath6kl *ar = file->private_data;
302 int ret;
303
304 ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask);
305 if (ret)
306 return ret;
307
308 ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi,
309 ATH6KL_FWLOG_VALID_MASK,
310 ar->debug.fwlog_mask);
311 if (ret)
312 return ret;
313
314 return count;
315}
316
317static const struct file_operations fops_fwlog_mask = {
318 .open = ath6kl_debugfs_open,
319 .read = ath6kl_fwlog_mask_read,
320 .write = ath6kl_fwlog_mask_write,
321 .owner = THIS_MODULE,
322 .llseek = default_llseek,
323};
324
Vasanthakumar Thiagarajan03f68a92011-08-26 13:06:32 +0530325static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
326 size_t count, loff_t *ppos)
327{
328 struct ath6kl *ar = file->private_data;
329 struct target_stats *tgt_stats = &ar->target_stats;
330 char *buf;
331 unsigned int len = 0, buf_len = 1500;
332 int i;
333 long left;
334 ssize_t ret_cnt;
335
336 buf = kzalloc(buf_len, GFP_KERNEL);
337 if (!buf)
338 return -ENOMEM;
339
340 if (down_interruptible(&ar->sem)) {
341 kfree(buf);
342 return -EBUSY;
343 }
344
345 set_bit(STATS_UPDATE_PEND, &ar->flag);
346
347 if (ath6kl_wmi_get_stats_cmd(ar->wmi)) {
348 up(&ar->sem);
349 kfree(buf);
350 return -EIO;
351 }
352
353 left = wait_event_interruptible_timeout(ar->event_wq,
354 !test_bit(STATS_UPDATE_PEND,
355 &ar->flag), WMI_TIMEOUT);
356
357 up(&ar->sem);
358
359 if (left <= 0) {
360 kfree(buf);
361 return -ETIMEDOUT;
362 }
363
364 len += scnprintf(buf + len, buf_len - len, "\n");
365 len += scnprintf(buf + len, buf_len - len, "%25s\n",
366 "Target Tx stats");
367 len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
368 "=================");
369 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
370 "Ucast packets", tgt_stats->tx_ucast_pkt);
371 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
372 "Bcast packets", tgt_stats->tx_bcast_pkt);
373 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
374 "Ucast byte", tgt_stats->tx_ucast_byte);
375 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
376 "Bcast byte", tgt_stats->tx_bcast_byte);
377 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
378 "Rts success cnt", tgt_stats->tx_rts_success_cnt);
379 for (i = 0; i < 4; i++)
380 len += scnprintf(buf + len, buf_len - len,
381 "%18s %d %10llu\n", "PER on ac",
382 i, tgt_stats->tx_pkt_per_ac[i]);
383 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
384 "Error", tgt_stats->tx_err);
385 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
386 "Fail count", tgt_stats->tx_fail_cnt);
387 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
388 "Retry count", tgt_stats->tx_retry_cnt);
389 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
390 "Multi retry cnt", tgt_stats->tx_mult_retry_cnt);
391 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
392 "Rts fail cnt", tgt_stats->tx_rts_fail_cnt);
393 len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n",
394 "TKIP counter measure used",
395 tgt_stats->tkip_cnter_measures_invoked);
396
397 len += scnprintf(buf + len, buf_len - len, "%25s\n",
398 "Target Rx stats");
399 len += scnprintf(buf + len, buf_len - len, "%25s\n",
400 "=================");
401
402 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
403 "Ucast packets", tgt_stats->rx_ucast_pkt);
404 len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
405 "Ucast Rate", tgt_stats->rx_ucast_rate);
406 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
407 "Bcast packets", tgt_stats->rx_bcast_pkt);
408 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
409 "Ucast byte", tgt_stats->rx_ucast_byte);
410 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
411 "Bcast byte", tgt_stats->rx_bcast_byte);
412 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
413 "Fragmented pkt", tgt_stats->rx_frgment_pkt);
414 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
415 "Error", tgt_stats->rx_err);
416 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
417 "CRC Err", tgt_stats->rx_crc_err);
418 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
419 "Key chache miss", tgt_stats->rx_key_cache_miss);
420 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
421 "Decrypt Err", tgt_stats->rx_decrypt_err);
422 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
423 "Duplicate frame", tgt_stats->rx_dupl_frame);
424 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
425 "Tkip Mic failure", tgt_stats->tkip_local_mic_fail);
426 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
427 "TKIP format err", tgt_stats->tkip_fmt_err);
428 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
429 "CCMP format Err", tgt_stats->ccmp_fmt_err);
430 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
431 "CCMP Replay Err", tgt_stats->ccmp_replays);
432
433 len += scnprintf(buf + len, buf_len - len, "%25s\n",
434 "Misc Target stats");
435 len += scnprintf(buf + len, buf_len - len, "%25s\n",
436 "=================");
437 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
438 "Beacon Miss count", tgt_stats->cs_bmiss_cnt);
439 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
440 "Num Connects", tgt_stats->cs_connect_cnt);
441 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
442 "Num disconnects", tgt_stats->cs_discon_cnt);
443 len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
444 "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi);
445
446 if (len > buf_len)
447 len = buf_len;
448
449 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
450
451 kfree(buf);
452 return ret_cnt;
453}
454
455static const struct file_operations fops_tgt_stats = {
456 .read = read_file_tgt_stats,
457 .open = ath6kl_debugfs_open,
458 .owner = THIS_MODULE,
459 .llseek = default_llseek,
460};
461
Vasanthakumar Thiagarajan78fc4852011-08-26 13:06:33 +0530462#define print_credit_info(fmt_str, ep_list_field) \
463 (len += scnprintf(buf + len, buf_len - len, fmt_str, \
464 ep_list->ep_list_field))
465#define CREDIT_INFO_DISPLAY_STRING_LEN 200
466#define CREDIT_INFO_LEN 128
467
468static ssize_t read_file_credit_dist_stats(struct file *file,
469 char __user *user_buf,
470 size_t count, loff_t *ppos)
471{
472 struct ath6kl *ar = file->private_data;
473 struct htc_target *target = ar->htc_target;
474 struct htc_endpoint_credit_dist *ep_list;
475 char *buf;
476 unsigned int buf_len, len = 0;
477 ssize_t ret_cnt;
478
479 buf_len = CREDIT_INFO_DISPLAY_STRING_LEN +
480 get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN;
481 buf = kzalloc(buf_len, GFP_KERNEL);
482 if (!buf)
483 return -ENOMEM;
484
485 len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
486 "Total Avail Credits: ",
487 target->cred_dist_cntxt->total_avail_credits);
488 len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
489 "Free credits :",
490 target->cred_dist_cntxt->cur_free_credits);
491
492 len += scnprintf(buf + len, buf_len - len,
493 " Epid Flags Cred_norm Cred_min Credits Cred_assngd"
494 " Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
495 " qdepth\n");
496
497 list_for_each_entry(ep_list, &target->cred_dist_list, list) {
498 print_credit_info(" %2d", endpoint);
499 print_credit_info("%10x", dist_flags);
500 print_credit_info("%8d", cred_norm);
501 print_credit_info("%9d", cred_min);
502 print_credit_info("%9d", credits);
503 print_credit_info("%10d", cred_assngd);
504 print_credit_info("%13d", seek_cred);
505 print_credit_info("%12d", cred_sz);
506 print_credit_info("%9d", cred_per_msg);
507 print_credit_info("%14d", cred_to_dist);
508 len += scnprintf(buf + len, buf_len - len, "%12d\n",
509 get_queue_depth(&((struct htc_endpoint *)
510 ep_list->htc_rsvd)->txq));
511 }
512
513 if (len > buf_len)
514 len = buf_len;
515
516 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
517 kfree(buf);
518 return ret_cnt;
519}
520
521static const struct file_operations fops_credit_dist_stats = {
522 .read = read_file_credit_dist_stats,
523 .open = ath6kl_debugfs_open,
524 .owner = THIS_MODULE,
525 .llseek = default_llseek,
526};
527
Vasanthakumar Thiagarajand999ba32011-08-26 13:06:31 +0530528int ath6kl_debug_init(struct ath6kl *ar)
529{
Kalle Valobdf53962011-09-02 10:32:04 +0300530 ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
531 if (ar->debug.fwlog_buf.buf == NULL)
532 return -ENOMEM;
533
534 ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL);
535 if (ar->debug.fwlog_tmp == NULL) {
536 vfree(ar->debug.fwlog_buf.buf);
537 return -ENOMEM;
538 }
539
540 spin_lock_init(&ar->debug.fwlog_lock);
541
Kalle Valo939f1cc2011-09-02 10:32:04 +0300542 /*
543 * Actually we are lying here but don't know how to read the mask
544 * value from the firmware.
545 */
546 ar->debug.fwlog_mask = 0;
547
Vasanthakumar Thiagarajand999ba32011-08-26 13:06:31 +0530548 ar->debugfs_phy = debugfs_create_dir("ath6kl",
549 ar->wdev->wiphy->debugfsdir);
Kalle Valobdf53962011-09-02 10:32:04 +0300550 if (!ar->debugfs_phy) {
551 vfree(ar->debug.fwlog_buf.buf);
552 kfree(ar->debug.fwlog_tmp);
Vasanthakumar Thiagarajand999ba32011-08-26 13:06:31 +0530553 return -ENOMEM;
Kalle Valobdf53962011-09-02 10:32:04 +0300554 }
Vasanthakumar Thiagarajand999ba32011-08-26 13:06:31 +0530555
Vasanthakumar Thiagarajan03f68a92011-08-26 13:06:32 +0530556 debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
557 &fops_tgt_stats);
558
Vasanthakumar Thiagarajan78fc4852011-08-26 13:06:33 +0530559 debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
560 &fops_credit_dist_stats);
561
Kalle Valobdf53962011-09-02 10:32:04 +0300562 debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
563 &fops_fwlog);
564
Kalle Valo939f1cc2011-09-02 10:32:04 +0300565 debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy,
566 ar, &fops_fwlog_mask);
567
Vasanthakumar Thiagarajand999ba32011-08-26 13:06:31 +0530568 return 0;
569}
Kalle Valobdf53962011-09-02 10:32:04 +0300570
571void ath6kl_debug_cleanup(struct ath6kl *ar)
572{
573 vfree(ar->debug.fwlog_buf.buf);
574 kfree(ar->debug.fwlog_tmp);
575}
576
Kalle Valobdcd8172011-07-18 00:22:30 +0300577#endif