2 * Copyright (c) 2004-2011 Atheros Communications Inc.
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.
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.
19 #include <linux/circ_buf.h>
21 #include <linux/vmalloc.h>
22 #include <linux/export.h>
27 struct ath6kl_fwlog_slot {
31 /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */
35 #define ATH6KL_FWLOG_SIZE 32768
36 #define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \
37 ATH6KL_FWLOG_PAYLOAD_SIZE)
38 #define ATH6KL_FWLOG_VALID_MASK 0x1ffff
40 int ath6kl_printk(const char *level, const char *fmt, ...)
51 rtn = printk("%sath6kl: %pV", level, &vaf);
57 EXPORT_SYMBOL(ath6kl_printk);
59 #ifdef CONFIG_ATH6KL_DEBUG
61 void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...)
66 if (!(debug_mask & mask))
74 ath6kl_printk(KERN_DEBUG, "%pV", &vaf);
78 EXPORT_SYMBOL(ath6kl_dbg);
80 void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
81 const char *msg, const char *prefix,
82 const void *buf, size_t len)
84 if (debug_mask & mask) {
86 ath6kl_dbg(mask, "%s\n", msg);
88 print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
91 EXPORT_SYMBOL(ath6kl_dbg_dump);
93 #define REG_OUTPUT_LEN_PER_LINE 25
94 #define REGTYPE_STR_LEN 100
96 struct ath6kl_diag_reg_info {
102 static const struct ath6kl_diag_reg_info diag_reg[] = {
103 { 0x20000, 0x200fc, "General DMA and Rx registers" },
104 { 0x28000, 0x28900, "MAC PCU register & keycache" },
105 { 0x20800, 0x20a40, "QCU" },
106 { 0x21000, 0x212f0, "DCU" },
107 { 0x4000, 0x42e4, "RTC" },
108 { 0x540000, 0x540000 + (256 * 1024), "RAM" },
109 { 0x29800, 0x2B210, "Base Band" },
110 { 0x1C000, 0x1C748, "Analog" },
113 void ath6kl_dump_registers(struct ath6kl_device *dev,
114 struct ath6kl_irq_proc_registers *irq_proc_reg,
115 struct ath6kl_irq_enable_reg *irq_enable_reg)
118 ath6kl_dbg(ATH6KL_DBG_IRQ, ("<------- Register Table -------->\n"));
120 if (irq_proc_reg != NULL) {
121 ath6kl_dbg(ATH6KL_DBG_IRQ,
122 "Host Int status: 0x%x\n",
123 irq_proc_reg->host_int_status);
124 ath6kl_dbg(ATH6KL_DBG_IRQ,
125 "CPU Int status: 0x%x\n",
126 irq_proc_reg->cpu_int_status);
127 ath6kl_dbg(ATH6KL_DBG_IRQ,
128 "Error Int status: 0x%x\n",
129 irq_proc_reg->error_int_status);
130 ath6kl_dbg(ATH6KL_DBG_IRQ,
131 "Counter Int status: 0x%x\n",
132 irq_proc_reg->counter_int_status);
133 ath6kl_dbg(ATH6KL_DBG_IRQ,
134 "Mbox Frame: 0x%x\n",
135 irq_proc_reg->mbox_frame);
136 ath6kl_dbg(ATH6KL_DBG_IRQ,
137 "Rx Lookahead Valid: 0x%x\n",
138 irq_proc_reg->rx_lkahd_valid);
139 ath6kl_dbg(ATH6KL_DBG_IRQ,
140 "Rx Lookahead 0: 0x%x\n",
141 irq_proc_reg->rx_lkahd[0]);
142 ath6kl_dbg(ATH6KL_DBG_IRQ,
143 "Rx Lookahead 1: 0x%x\n",
144 irq_proc_reg->rx_lkahd[1]);
146 if (dev->ar->mbox_info.gmbox_addr != 0) {
148 * If the target supports GMBOX hardware, dump some
151 ath6kl_dbg(ATH6KL_DBG_IRQ,
152 "GMBOX Host Int status 2: 0x%x\n",
153 irq_proc_reg->host_int_status2);
154 ath6kl_dbg(ATH6KL_DBG_IRQ,
155 "GMBOX RX Avail: 0x%x\n",
156 irq_proc_reg->gmbox_rx_avail);
157 ath6kl_dbg(ATH6KL_DBG_IRQ,
158 "GMBOX lookahead alias 0: 0x%x\n",
159 irq_proc_reg->rx_gmbox_lkahd_alias[0]);
160 ath6kl_dbg(ATH6KL_DBG_IRQ,
161 "GMBOX lookahead alias 1: 0x%x\n",
162 irq_proc_reg->rx_gmbox_lkahd_alias[1]);
167 if (irq_enable_reg != NULL) {
168 ath6kl_dbg(ATH6KL_DBG_IRQ,
169 "Int status Enable: 0x%x\n",
170 irq_enable_reg->int_status_en);
171 ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n",
172 irq_enable_reg->cntr_int_status_en);
174 ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n");
177 static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist)
179 ath6kl_dbg(ATH6KL_DBG_CREDIT,
180 "--- endpoint: %d svc_id: 0x%X ---\n",
181 ep_dist->endpoint, ep_dist->svc_id);
182 ath6kl_dbg(ATH6KL_DBG_CREDIT, " dist_flags : 0x%X\n",
183 ep_dist->dist_flags);
184 ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_norm : %d\n",
186 ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_min : %d\n",
188 ath6kl_dbg(ATH6KL_DBG_CREDIT, " credits : %d\n",
190 ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_assngd : %d\n",
191 ep_dist->cred_assngd);
192 ath6kl_dbg(ATH6KL_DBG_CREDIT, " seek_cred : %d\n",
194 ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_sz : %d\n",
196 ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_per_msg : %d\n",
197 ep_dist->cred_per_msg);
198 ath6kl_dbg(ATH6KL_DBG_CREDIT, " cred_to_dist : %d\n",
199 ep_dist->cred_to_dist);
200 ath6kl_dbg(ATH6KL_DBG_CREDIT, " txq_depth : %d\n",
201 get_queue_depth(&ep_dist->htc_ep->txq));
202 ath6kl_dbg(ATH6KL_DBG_CREDIT,
203 "----------------------------------\n");
206 /* FIXME: move to htc.c */
207 void dump_cred_dist_stats(struct htc_target *target)
209 struct htc_endpoint_credit_dist *ep_list;
211 list_for_each_entry(ep_list, &target->cred_dist_list, list)
212 dump_cred_dist(ep_list);
214 ath6kl_dbg(ATH6KL_DBG_CREDIT,
215 "credit distribution total %d free %d\n",
216 target->credit_info->total_avail_credits,
217 target->credit_info->cur_free_credits);
220 static int ath6kl_debugfs_open(struct inode *inode, struct file *file)
222 file->private_data = inode->i_private;
226 void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
229 case ATH6KL_WAR_INVALID_RATE:
230 ar->debug.war_stats.invalid_rate++;
235 static ssize_t read_file_war_stats(struct file *file, char __user *user_buf,
236 size_t count, loff_t *ppos)
238 struct ath6kl *ar = file->private_data;
240 unsigned int len = 0, buf_len = 1500;
243 buf = kzalloc(buf_len, GFP_KERNEL);
247 len += scnprintf(buf + len, buf_len - len, "\n");
248 len += scnprintf(buf + len, buf_len - len, "%25s\n",
250 len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
251 "=================");
252 len += scnprintf(buf + len, buf_len - len, "%20s %10u\n",
253 "Invalid rates", ar->debug.war_stats.invalid_rate);
255 if (WARN_ON(len > buf_len))
258 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
264 static const struct file_operations fops_war_stats = {
265 .read = read_file_war_stats,
266 .open = ath6kl_debugfs_open,
267 .owner = THIS_MODULE,
268 .llseek = default_llseek,
271 static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf,
274 struct circ_buf *fwlog = &ar->debug.fwlog_buf;
278 /* entries must all be equal size */
279 if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE))
282 space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE);
284 /* discard oldest slot */
285 fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) &
286 (ATH6KL_FWLOG_SIZE - 1);
288 for (i = 0; i < buf_len; i += space) {
289 space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail,
292 if ((size_t) space > buf_len - i)
295 memcpy(&fwlog->buf[fwlog->head], buf, space);
296 fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1);
301 void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
303 struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp;
306 if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
309 spin_lock_bh(&ar->debug.fwlog_lock);
311 slot->timestamp = cpu_to_le32(jiffies);
312 slot->length = cpu_to_le32(len);
313 memcpy(slot->payload, buf, len);
315 slot_len = sizeof(*slot) + len;
317 if (slot_len < ATH6KL_FWLOG_SLOT_SIZE)
318 memset(slot->payload + len, 0,
319 ATH6KL_FWLOG_SLOT_SIZE - slot_len);
321 ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE);
323 spin_unlock_bh(&ar->debug.fwlog_lock);
326 static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar)
328 return CIRC_CNT(ar->debug.fwlog_buf.head,
329 ar->debug.fwlog_buf.tail,
330 ATH6KL_FWLOG_SLOT_SIZE) == 0;
333 static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
334 size_t count, loff_t *ppos)
336 struct ath6kl *ar = file->private_data;
337 struct circ_buf *fwlog = &ar->debug.fwlog_buf;
338 size_t len = 0, buf_len = count;
343 buf = vmalloc(buf_len);
347 /* read undelivered logs from firmware */
348 ath6kl_read_fwlogs(ar);
350 spin_lock_bh(&ar->debug.fwlog_lock);
352 while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) {
353 ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail,
356 if ((size_t) ccnt > buf_len - len)
357 ccnt = buf_len - len;
359 memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt);
362 fwlog->tail = (fwlog->tail + ccnt) &
363 (ATH6KL_FWLOG_SIZE - 1);
366 spin_unlock_bh(&ar->debug.fwlog_lock);
368 if (WARN_ON(len > buf_len))
371 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
378 static const struct file_operations fops_fwlog = {
379 .open = ath6kl_debugfs_open,
380 .read = ath6kl_fwlog_read,
381 .owner = THIS_MODULE,
382 .llseek = default_llseek,
385 static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf,
386 size_t count, loff_t *ppos)
388 struct ath6kl *ar = file->private_data;
392 len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask);
394 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
397 static ssize_t ath6kl_fwlog_mask_write(struct file *file,
398 const char __user *user_buf,
399 size_t count, loff_t *ppos)
401 struct ath6kl *ar = file->private_data;
404 ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask);
408 ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi,
409 ATH6KL_FWLOG_VALID_MASK,
410 ar->debug.fwlog_mask);
417 static const struct file_operations fops_fwlog_mask = {
418 .open = ath6kl_debugfs_open,
419 .read = ath6kl_fwlog_mask_read,
420 .write = ath6kl_fwlog_mask_write,
421 .owner = THIS_MODULE,
422 .llseek = default_llseek,
425 static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
426 size_t count, loff_t *ppos)
428 struct ath6kl *ar = file->private_data;
429 struct ath6kl_vif *vif;
430 struct target_stats *tgt_stats;
432 unsigned int len = 0, buf_len = 1500;
437 vif = ath6kl_vif_first(ar);
441 tgt_stats = &vif->target_stats;
443 buf = kzalloc(buf_len, GFP_KERNEL);
447 if (down_interruptible(&ar->sem)) {
452 set_bit(STATS_UPDATE_PEND, &vif->flags);
454 if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) {
460 left = wait_event_interruptible_timeout(ar->event_wq,
461 !test_bit(STATS_UPDATE_PEND,
462 &vif->flags), WMI_TIMEOUT);
471 len += scnprintf(buf + len, buf_len - len, "\n");
472 len += scnprintf(buf + len, buf_len - len, "%25s\n",
474 len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
475 "=================");
476 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
477 "Ucast packets", tgt_stats->tx_ucast_pkt);
478 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
479 "Bcast packets", tgt_stats->tx_bcast_pkt);
480 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
481 "Ucast byte", tgt_stats->tx_ucast_byte);
482 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
483 "Bcast byte", tgt_stats->tx_bcast_byte);
484 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
485 "Rts success cnt", tgt_stats->tx_rts_success_cnt);
486 for (i = 0; i < 4; i++)
487 len += scnprintf(buf + len, buf_len - len,
488 "%18s %d %10llu\n", "PER on ac",
489 i, tgt_stats->tx_pkt_per_ac[i]);
490 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
491 "Error", tgt_stats->tx_err);
492 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
493 "Fail count", tgt_stats->tx_fail_cnt);
494 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
495 "Retry count", tgt_stats->tx_retry_cnt);
496 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
497 "Multi retry cnt", tgt_stats->tx_mult_retry_cnt);
498 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
499 "Rts fail cnt", tgt_stats->tx_rts_fail_cnt);
500 len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n",
501 "TKIP counter measure used",
502 tgt_stats->tkip_cnter_measures_invoked);
504 len += scnprintf(buf + len, buf_len - len, "%25s\n",
506 len += scnprintf(buf + len, buf_len - len, "%25s\n",
507 "=================");
509 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
510 "Ucast packets", tgt_stats->rx_ucast_pkt);
511 len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
512 "Ucast Rate", tgt_stats->rx_ucast_rate);
513 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
514 "Bcast packets", tgt_stats->rx_bcast_pkt);
515 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
516 "Ucast byte", tgt_stats->rx_ucast_byte);
517 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
518 "Bcast byte", tgt_stats->rx_bcast_byte);
519 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
520 "Fragmented pkt", tgt_stats->rx_frgment_pkt);
521 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
522 "Error", tgt_stats->rx_err);
523 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
524 "CRC Err", tgt_stats->rx_crc_err);
525 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
526 "Key chache miss", tgt_stats->rx_key_cache_miss);
527 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
528 "Decrypt Err", tgt_stats->rx_decrypt_err);
529 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
530 "Duplicate frame", tgt_stats->rx_dupl_frame);
531 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
532 "Tkip Mic failure", tgt_stats->tkip_local_mic_fail);
533 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
534 "TKIP format err", tgt_stats->tkip_fmt_err);
535 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
536 "CCMP format Err", tgt_stats->ccmp_fmt_err);
537 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
538 "CCMP Replay Err", tgt_stats->ccmp_replays);
540 len += scnprintf(buf + len, buf_len - len, "%25s\n",
541 "Misc Target stats");
542 len += scnprintf(buf + len, buf_len - len, "%25s\n",
543 "=================");
544 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
545 "Beacon Miss count", tgt_stats->cs_bmiss_cnt);
546 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
547 "Num Connects", tgt_stats->cs_connect_cnt);
548 len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
549 "Num disconnects", tgt_stats->cs_discon_cnt);
550 len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
551 "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi);
556 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
562 static const struct file_operations fops_tgt_stats = {
563 .read = read_file_tgt_stats,
564 .open = ath6kl_debugfs_open,
565 .owner = THIS_MODULE,
566 .llseek = default_llseek,
569 #define print_credit_info(fmt_str, ep_list_field) \
570 (len += scnprintf(buf + len, buf_len - len, fmt_str, \
571 ep_list->ep_list_field))
572 #define CREDIT_INFO_DISPLAY_STRING_LEN 200
573 #define CREDIT_INFO_LEN 128
575 static ssize_t read_file_credit_dist_stats(struct file *file,
576 char __user *user_buf,
577 size_t count, loff_t *ppos)
579 struct ath6kl *ar = file->private_data;
580 struct htc_target *target = ar->htc_target;
581 struct htc_endpoint_credit_dist *ep_list;
583 unsigned int buf_len, len = 0;
586 buf_len = CREDIT_INFO_DISPLAY_STRING_LEN +
587 get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN;
588 buf = kzalloc(buf_len, GFP_KERNEL);
592 len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
593 "Total Avail Credits: ",
594 target->credit_info->total_avail_credits);
595 len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
597 target->credit_info->cur_free_credits);
599 len += scnprintf(buf + len, buf_len - len,
600 " Epid Flags Cred_norm Cred_min Credits Cred_assngd"
601 " Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
604 list_for_each_entry(ep_list, &target->cred_dist_list, list) {
605 print_credit_info(" %2d", endpoint);
606 print_credit_info("%10x", dist_flags);
607 print_credit_info("%8d", cred_norm);
608 print_credit_info("%9d", cred_min);
609 print_credit_info("%9d", credits);
610 print_credit_info("%10d", cred_assngd);
611 print_credit_info("%13d", seek_cred);
612 print_credit_info("%12d", cred_sz);
613 print_credit_info("%9d", cred_per_msg);
614 print_credit_info("%14d", cred_to_dist);
615 len += scnprintf(buf + len, buf_len - len, "%12d\n",
616 get_queue_depth(&ep_list->htc_ep->txq));
622 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
627 static const struct file_operations fops_credit_dist_stats = {
628 .read = read_file_credit_dist_stats,
629 .open = ath6kl_debugfs_open,
630 .owner = THIS_MODULE,
631 .llseek = default_llseek,
634 static unsigned int print_endpoint_stat(struct htc_target *target, char *buf,
635 unsigned int buf_len, unsigned int len,
636 int offset, const char *name)
639 struct htc_endpoint_stats *ep_st;
642 len += scnprintf(buf + len, buf_len - len, "%s:", name);
643 for (i = 0; i < ENDPOINT_MAX; i++) {
644 ep_st = &target->endpoint[i].ep_st;
645 counter = ((u32 *) ep_st) + (offset / 4);
646 len += scnprintf(buf + len, buf_len - len, " %u", *counter);
648 len += scnprintf(buf + len, buf_len - len, "\n");
653 static ssize_t ath6kl_endpoint_stats_read(struct file *file,
654 char __user *user_buf,
655 size_t count, loff_t *ppos)
657 struct ath6kl *ar = file->private_data;
658 struct htc_target *target = ar->htc_target;
660 unsigned int buf_len, len = 0;
663 buf_len = sizeof(struct htc_endpoint_stats) / sizeof(u32) *
664 (25 + ENDPOINT_MAX * 11);
665 buf = kmalloc(buf_len, GFP_KERNEL);
669 #define EPSTAT(name) \
670 len = print_endpoint_stat(target, buf, buf_len, len, \
671 offsetof(struct htc_endpoint_stats, name), \
673 EPSTAT(cred_low_indicate);
675 EPSTAT(tx_pkt_bundled);
679 EPSTAT(cred_rpt_from_rx);
680 EPSTAT(cred_rpt_from_other);
681 EPSTAT(cred_rpt_ep0);
682 EPSTAT(cred_from_rx);
683 EPSTAT(cred_from_other);
684 EPSTAT(cred_from_ep0);
690 EPSTAT(rx_bundle_lkahd);
691 EPSTAT(rx_bundle_from_hdr);
692 EPSTAT(rx_alloc_thresh_hit);
693 EPSTAT(rxalloc_thresh_byte);
699 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
704 static ssize_t ath6kl_endpoint_stats_write(struct file *file,
705 const char __user *user_buf,
706 size_t count, loff_t *ppos)
708 struct ath6kl *ar = file->private_data;
709 struct htc_target *target = ar->htc_target;
712 struct htc_endpoint_stats *ep_st;
714 ret = kstrtou32_from_user(user_buf, count, 0, &val);
718 for (i = 0; i < ENDPOINT_MAX; i++) {
719 ep_st = &target->endpoint[i].ep_st;
720 memset(ep_st, 0, sizeof(*ep_st));
727 static const struct file_operations fops_endpoint_stats = {
728 .open = ath6kl_debugfs_open,
729 .read = ath6kl_endpoint_stats_read,
730 .write = ath6kl_endpoint_stats_write,
731 .owner = THIS_MODULE,
732 .llseek = default_llseek,
735 static unsigned long ath6kl_get_num_reg(void)
738 unsigned long n_reg = 0;
740 for (i = 0; i < ARRAY_SIZE(diag_reg); i++)
742 (diag_reg[i].reg_end - diag_reg[i].reg_start) / 4 + 1;
747 static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr)
751 for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
752 if (reg_addr >= diag_reg[i].reg_start &&
753 reg_addr <= diag_reg[i].reg_end)
760 static ssize_t ath6kl_regread_read(struct file *file, char __user *user_buf,
761 size_t count, loff_t *ppos)
763 struct ath6kl *ar = file->private_data;
765 unsigned int len = 0;
767 if (ar->debug.dbgfs_diag_reg)
768 len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n",
769 ar->debug.dbgfs_diag_reg);
771 len += scnprintf(buf + len, sizeof(buf) - len,
772 "All diag registers\n");
774 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
777 static ssize_t ath6kl_regread_write(struct file *file,
778 const char __user *user_buf,
779 size_t count, loff_t *ppos)
781 struct ath6kl *ar = file->private_data;
784 unsigned long reg_addr;
786 len = min(count, sizeof(buf) - 1);
787 if (copy_from_user(buf, user_buf, len))
792 if (strict_strtoul(buf, 0, ®_addr))
795 if ((reg_addr % 4) != 0)
798 if (reg_addr && !ath6kl_dbg_is_diag_reg_valid(reg_addr))
801 ar->debug.dbgfs_diag_reg = reg_addr;
806 static const struct file_operations fops_diag_reg_read = {
807 .read = ath6kl_regread_read,
808 .write = ath6kl_regread_write,
809 .open = ath6kl_debugfs_open,
810 .owner = THIS_MODULE,
811 .llseek = default_llseek,
814 static int ath6kl_regdump_open(struct inode *inode, struct file *file)
816 struct ath6kl *ar = inode->i_private;
818 unsigned long int reg_len;
819 unsigned int len = 0, n_reg;
824 /* Dump all the registers if no register is specified */
825 if (!ar->debug.dbgfs_diag_reg)
826 n_reg = ath6kl_get_num_reg();
830 reg_len = n_reg * REG_OUTPUT_LEN_PER_LINE;
832 reg_len += REGTYPE_STR_LEN;
834 buf = vmalloc(reg_len);
839 addr = ar->debug.dbgfs_diag_reg;
841 status = ath6kl_diag_read32(ar,
842 TARG_VTOP(ar->target_type, addr),
847 len += scnprintf(buf + len, reg_len - len,
848 "0x%06x 0x%08x\n", addr, le32_to_cpu(reg_val));
852 for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
853 len += scnprintf(buf + len, reg_len - len,
854 "%s\n", diag_reg[i].reg_info);
855 for (addr = diag_reg[i].reg_start;
856 addr <= diag_reg[i].reg_end; addr += 4) {
857 status = ath6kl_diag_read32(ar,
858 TARG_VTOP(ar->target_type, addr),
863 len += scnprintf(buf + len, reg_len - len,
865 addr, le32_to_cpu(reg_val));
870 file->private_data = buf;
874 ath6kl_warn("Unable to read memory:%u\n", addr);
879 static ssize_t ath6kl_regdump_read(struct file *file, char __user *user_buf,
880 size_t count, loff_t *ppos)
882 u8 *buf = file->private_data;
883 return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
886 static int ath6kl_regdump_release(struct inode *inode, struct file *file)
888 vfree(file->private_data);
892 static const struct file_operations fops_reg_dump = {
893 .open = ath6kl_regdump_open,
894 .read = ath6kl_regdump_read,
895 .release = ath6kl_regdump_release,
896 .owner = THIS_MODULE,
897 .llseek = default_llseek,
900 static ssize_t ath6kl_lrssi_roam_write(struct file *file,
901 const char __user *user_buf,
902 size_t count, loff_t *ppos)
904 struct ath6kl *ar = file->private_data;
905 unsigned long lrssi_roam_threshold;
909 len = min(count, sizeof(buf) - 1);
910 if (copy_from_user(buf, user_buf, len))
914 if (strict_strtoul(buf, 0, &lrssi_roam_threshold))
917 ar->lrssi_roam_threshold = lrssi_roam_threshold;
919 ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold);
924 static ssize_t ath6kl_lrssi_roam_read(struct file *file,
925 char __user *user_buf,
926 size_t count, loff_t *ppos)
928 struct ath6kl *ar = file->private_data;
932 len = snprintf(buf, sizeof(buf), "%u\n", ar->lrssi_roam_threshold);
934 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
937 static const struct file_operations fops_lrssi_roam_threshold = {
938 .read = ath6kl_lrssi_roam_read,
939 .write = ath6kl_lrssi_roam_write,
940 .open = ath6kl_debugfs_open,
941 .owner = THIS_MODULE,
942 .llseek = default_llseek,
945 static ssize_t ath6kl_regwrite_read(struct file *file,
946 char __user *user_buf,
947 size_t count, loff_t *ppos)
949 struct ath6kl *ar = file->private_data;
951 unsigned int len = 0;
953 len = scnprintf(buf, sizeof(buf), "Addr: 0x%x Val: 0x%x\n",
954 ar->debug.diag_reg_addr_wr, ar->debug.diag_reg_val_wr);
956 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
959 static ssize_t ath6kl_regwrite_write(struct file *file,
960 const char __user *user_buf,
961 size_t count, loff_t *ppos)
963 struct ath6kl *ar = file->private_data;
966 unsigned int len = 0;
967 u32 reg_addr, reg_val;
969 len = min(count, sizeof(buf) - 1);
970 if (copy_from_user(buf, user_buf, len))
976 token = strsep(&sptr, "=");
980 if (kstrtou32(token, 0, ®_addr))
983 if (!ath6kl_dbg_is_diag_reg_valid(reg_addr))
986 if (kstrtou32(sptr, 0, ®_val))
989 ar->debug.diag_reg_addr_wr = reg_addr;
990 ar->debug.diag_reg_val_wr = reg_val;
992 if (ath6kl_diag_write32(ar, ar->debug.diag_reg_addr_wr,
993 cpu_to_le32(ar->debug.diag_reg_val_wr)))
999 static const struct file_operations fops_diag_reg_write = {
1000 .read = ath6kl_regwrite_read,
1001 .write = ath6kl_regwrite_write,
1002 .open = ath6kl_debugfs_open,
1003 .owner = THIS_MODULE,
1004 .llseek = default_llseek,
1007 int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
1010 const struct wmi_target_roam_tbl *tbl;
1013 if (len < sizeof(*tbl))
1016 tbl = (const struct wmi_target_roam_tbl *) buf;
1017 num_entries = le16_to_cpu(tbl->num_entries);
1018 if (sizeof(*tbl) + num_entries * sizeof(struct wmi_bss_roam_info) >
1022 if (ar->debug.roam_tbl == NULL ||
1023 ar->debug.roam_tbl_len < (unsigned int) len) {
1024 kfree(ar->debug.roam_tbl);
1025 ar->debug.roam_tbl = kmalloc(len, GFP_ATOMIC);
1026 if (ar->debug.roam_tbl == NULL)
1030 memcpy(ar->debug.roam_tbl, buf, len);
1031 ar->debug.roam_tbl_len = len;
1033 if (test_bit(ROAM_TBL_PEND, &ar->flag)) {
1034 clear_bit(ROAM_TBL_PEND, &ar->flag);
1035 wake_up(&ar->event_wq);
1041 static ssize_t ath6kl_roam_table_read(struct file *file, char __user *user_buf,
1042 size_t count, loff_t *ppos)
1044 struct ath6kl *ar = file->private_data;
1047 struct wmi_target_roam_tbl *tbl;
1050 unsigned int len, buf_len;
1053 if (down_interruptible(&ar->sem))
1056 set_bit(ROAM_TBL_PEND, &ar->flag);
1058 ret = ath6kl_wmi_get_roam_tbl_cmd(ar->wmi);
1064 left = wait_event_interruptible_timeout(
1065 ar->event_wq, !test_bit(ROAM_TBL_PEND, &ar->flag), WMI_TIMEOUT);
1071 if (ar->debug.roam_tbl == NULL)
1074 tbl = (struct wmi_target_roam_tbl *) ar->debug.roam_tbl;
1075 num_entries = le16_to_cpu(tbl->num_entries);
1077 buf_len = 100 + num_entries * 100;
1078 buf = kzalloc(buf_len, GFP_KERNEL);
1082 len += scnprintf(buf + len, buf_len - len,
1084 "# roam_util bssid rssi rssidt last_rssi util bias\n",
1085 le16_to_cpu(tbl->roam_mode));
1087 for (i = 0; i < num_entries; i++) {
1088 struct wmi_bss_roam_info *info = &tbl->info[i];
1089 len += scnprintf(buf + len, buf_len - len,
1090 "%d %pM %d %d %d %d %d\n",
1091 a_sle32_to_cpu(info->roam_util), info->bssid,
1092 info->rssi, info->rssidt, info->last_rssi,
1093 info->util, info->bias);
1099 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1105 static const struct file_operations fops_roam_table = {
1106 .read = ath6kl_roam_table_read,
1107 .open = ath6kl_debugfs_open,
1108 .owner = THIS_MODULE,
1109 .llseek = default_llseek,
1112 static ssize_t ath6kl_force_roam_write(struct file *file,
1113 const char __user *user_buf,
1114 size_t count, loff_t *ppos)
1116 struct ath6kl *ar = file->private_data;
1124 len = min(count, sizeof(buf) - 1);
1125 if (copy_from_user(buf, user_buf, len))
1129 if (sscanf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
1130 &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5])
1133 for (i = 0; i < ETH_ALEN; i++)
1136 ret = ath6kl_wmi_force_roam_cmd(ar->wmi, bssid);
1143 static const struct file_operations fops_force_roam = {
1144 .write = ath6kl_force_roam_write,
1145 .open = ath6kl_debugfs_open,
1146 .owner = THIS_MODULE,
1147 .llseek = default_llseek,
1150 static ssize_t ath6kl_roam_mode_write(struct file *file,
1151 const char __user *user_buf,
1152 size_t count, loff_t *ppos)
1154 struct ath6kl *ar = file->private_data;
1158 enum wmi_roam_mode mode;
1160 len = min(count, sizeof(buf) - 1);
1161 if (copy_from_user(buf, user_buf, len))
1164 if (len > 0 && buf[len - 1] == '\n')
1165 buf[len - 1] = '\0';
1167 if (strcasecmp(buf, "default") == 0)
1168 mode = WMI_DEFAULT_ROAM_MODE;
1169 else if (strcasecmp(buf, "bssbias") == 0)
1170 mode = WMI_HOST_BIAS_ROAM_MODE;
1171 else if (strcasecmp(buf, "lock") == 0)
1172 mode = WMI_LOCK_BSS_MODE;
1176 ret = ath6kl_wmi_set_roam_mode_cmd(ar->wmi, mode);
1183 static const struct file_operations fops_roam_mode = {
1184 .write = ath6kl_roam_mode_write,
1185 .open = ath6kl_debugfs_open,
1186 .owner = THIS_MODULE,
1187 .llseek = default_llseek,
1190 void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive)
1192 ar->debug.keepalive = keepalive;
1195 static ssize_t ath6kl_keepalive_read(struct file *file, char __user *user_buf,
1196 size_t count, loff_t *ppos)
1198 struct ath6kl *ar = file->private_data;
1202 len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.keepalive);
1204 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1207 static ssize_t ath6kl_keepalive_write(struct file *file,
1208 const char __user *user_buf,
1209 size_t count, loff_t *ppos)
1211 struct ath6kl *ar = file->private_data;
1215 ret = kstrtou8_from_user(user_buf, count, 0, &val);
1219 ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, 0, val);
1226 static const struct file_operations fops_keepalive = {
1227 .open = ath6kl_debugfs_open,
1228 .read = ath6kl_keepalive_read,
1229 .write = ath6kl_keepalive_write,
1230 .owner = THIS_MODULE,
1231 .llseek = default_llseek,
1234 void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout)
1236 ar->debug.disc_timeout = timeout;
1239 static ssize_t ath6kl_disconnect_timeout_read(struct file *file,
1240 char __user *user_buf,
1241 size_t count, loff_t *ppos)
1243 struct ath6kl *ar = file->private_data;
1247 len = snprintf(buf, sizeof(buf), "%u\n", ar->debug.disc_timeout);
1249 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1252 static ssize_t ath6kl_disconnect_timeout_write(struct file *file,
1253 const char __user *user_buf,
1254 size_t count, loff_t *ppos)
1256 struct ath6kl *ar = file->private_data;
1260 ret = kstrtou8_from_user(user_buf, count, 0, &val);
1264 ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, 0, val);
1271 static const struct file_operations fops_disconnect_timeout = {
1272 .open = ath6kl_debugfs_open,
1273 .read = ath6kl_disconnect_timeout_read,
1274 .write = ath6kl_disconnect_timeout_write,
1275 .owner = THIS_MODULE,
1276 .llseek = default_llseek,
1279 static ssize_t ath6kl_create_qos_write(struct file *file,
1280 const char __user *user_buf,
1281 size_t count, loff_t *ppos)
1284 struct ath6kl *ar = file->private_data;
1285 struct ath6kl_vif *vif;
1289 struct wmi_create_pstream_cmd pstream;
1293 vif = ath6kl_vif_first(ar);
1297 len = min(count, sizeof(buf) - 1);
1298 if (copy_from_user(buf, user_buf, len))
1303 token = strsep(&sptr, " ");
1306 if (kstrtou8(token, 0, &pstream.user_pri))
1309 token = strsep(&sptr, " ");
1312 if (kstrtou8(token, 0, &pstream.traffic_direc))
1315 token = strsep(&sptr, " ");
1318 if (kstrtou8(token, 0, &pstream.traffic_class))
1321 token = strsep(&sptr, " ");
1324 if (kstrtou8(token, 0, &pstream.traffic_type))
1327 token = strsep(&sptr, " ");
1330 if (kstrtou8(token, 0, &pstream.voice_psc_cap))
1333 token = strsep(&sptr, " ");
1336 if (kstrtou32(token, 0, &val32))
1338 pstream.min_service_int = cpu_to_le32(val32);
1340 token = strsep(&sptr, " ");
1343 if (kstrtou32(token, 0, &val32))
1345 pstream.max_service_int = cpu_to_le32(val32);
1347 token = strsep(&sptr, " ");
1350 if (kstrtou32(token, 0, &val32))
1352 pstream.inactivity_int = cpu_to_le32(val32);
1354 token = strsep(&sptr, " ");
1357 if (kstrtou32(token, 0, &val32))
1359 pstream.suspension_int = cpu_to_le32(val32);
1361 token = strsep(&sptr, " ");
1364 if (kstrtou32(token, 0, &val32))
1366 pstream.service_start_time = cpu_to_le32(val32);
1368 token = strsep(&sptr, " ");
1371 if (kstrtou8(token, 0, &pstream.tsid))
1374 token = strsep(&sptr, " ");
1377 if (kstrtou16(token, 0, &val16))
1379 pstream.nominal_msdu = cpu_to_le16(val16);
1381 token = strsep(&sptr, " ");
1384 if (kstrtou16(token, 0, &val16))
1386 pstream.max_msdu = cpu_to_le16(val16);
1388 token = strsep(&sptr, " ");
1391 if (kstrtou32(token, 0, &val32))
1393 pstream.min_data_rate = cpu_to_le32(val32);
1395 token = strsep(&sptr, " ");
1398 if (kstrtou32(token, 0, &val32))
1400 pstream.mean_data_rate = cpu_to_le32(val32);
1402 token = strsep(&sptr, " ");
1405 if (kstrtou32(token, 0, &val32))
1407 pstream.peak_data_rate = cpu_to_le32(val32);
1409 token = strsep(&sptr, " ");
1412 if (kstrtou32(token, 0, &val32))
1414 pstream.max_burst_size = cpu_to_le32(val32);
1416 token = strsep(&sptr, " ");
1419 if (kstrtou32(token, 0, &val32))
1421 pstream.delay_bound = cpu_to_le32(val32);
1423 token = strsep(&sptr, " ");
1426 if (kstrtou32(token, 0, &val32))
1428 pstream.min_phy_rate = cpu_to_le32(val32);
1430 token = strsep(&sptr, " ");
1433 if (kstrtou32(token, 0, &val32))
1435 pstream.sba = cpu_to_le32(val32);
1437 token = strsep(&sptr, " ");
1440 if (kstrtou32(token, 0, &val32))
1442 pstream.medium_time = cpu_to_le32(val32);
1444 pstream.nominal_phy = le32_to_cpu(pstream.min_phy_rate) / 1000000;
1446 ath6kl_wmi_create_pstream_cmd(ar->wmi, vif->fw_vif_idx, &pstream);
1451 static const struct file_operations fops_create_qos = {
1452 .write = ath6kl_create_qos_write,
1453 .open = ath6kl_debugfs_open,
1454 .owner = THIS_MODULE,
1455 .llseek = default_llseek,
1458 static ssize_t ath6kl_delete_qos_write(struct file *file,
1459 const char __user *user_buf,
1460 size_t count, loff_t *ppos)
1463 struct ath6kl *ar = file->private_data;
1464 struct ath6kl_vif *vif;
1471 vif = ath6kl_vif_first(ar);
1475 len = min(count, sizeof(buf) - 1);
1476 if (copy_from_user(buf, user_buf, len))
1481 token = strsep(&sptr, " ");
1484 if (kstrtou8(token, 0, &traffic_class))
1487 token = strsep(&sptr, " ");
1490 if (kstrtou8(token, 0, &tsid))
1493 ath6kl_wmi_delete_pstream_cmd(ar->wmi, vif->fw_vif_idx,
1494 traffic_class, tsid);
1499 static const struct file_operations fops_delete_qos = {
1500 .write = ath6kl_delete_qos_write,
1501 .open = ath6kl_debugfs_open,
1502 .owner = THIS_MODULE,
1503 .llseek = default_llseek,
1506 static ssize_t ath6kl_bgscan_int_write(struct file *file,
1507 const char __user *user_buf,
1508 size_t count, loff_t *ppos)
1510 struct ath6kl *ar = file->private_data;
1515 len = min(count, sizeof(buf) - 1);
1516 if (copy_from_user(buf, user_buf, len))
1520 if (kstrtou16(buf, 0, &bgscan_int))
1523 if (bgscan_int == 0)
1524 bgscan_int = 0xffff;
1526 ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3,
1532 static const struct file_operations fops_bgscan_int = {
1533 .write = ath6kl_bgscan_int_write,
1534 .open = ath6kl_debugfs_open,
1535 .owner = THIS_MODULE,
1536 .llseek = default_llseek,
1539 static ssize_t ath6kl_listen_int_write(struct file *file,
1540 const char __user *user_buf,
1541 size_t count, loff_t *ppos)
1543 struct ath6kl *ar = file->private_data;
1544 struct ath6kl_vif *vif;
1545 u16 listen_interval;
1549 vif = ath6kl_vif_first(ar);
1553 len = min(count, sizeof(buf) - 1);
1554 if (copy_from_user(buf, user_buf, len))
1558 if (kstrtou16(buf, 0, &listen_interval))
1561 if ((listen_interval < 1) || (listen_interval > 50))
1564 ar->listen_intvl_b = listen_interval;
1565 ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 0,
1566 ar->listen_intvl_b);
1571 static ssize_t ath6kl_listen_int_read(struct file *file,
1572 char __user *user_buf,
1573 size_t count, loff_t *ppos)
1575 struct ath6kl *ar = file->private_data;
1579 len = scnprintf(buf, sizeof(buf), "%u\n", ar->listen_intvl_b);
1581 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1584 static const struct file_operations fops_listen_int = {
1585 .read = ath6kl_listen_int_read,
1586 .write = ath6kl_listen_int_write,
1587 .open = ath6kl_debugfs_open,
1588 .owner = THIS_MODULE,
1589 .llseek = default_llseek,
1592 static ssize_t ath6kl_power_params_write(struct file *file,
1593 const char __user *user_buf,
1594 size_t count, loff_t *ppos)
1596 struct ath6kl *ar = file->private_data;
1598 unsigned int len = 0;
1600 u16 idle_period, ps_poll_num, dtim,
1603 len = min(count, sizeof(buf) - 1);
1604 if (copy_from_user(buf, user_buf, len))
1609 token = strsep(&sptr, " ");
1612 if (kstrtou16(token, 0, &idle_period))
1615 token = strsep(&sptr, " ");
1618 if (kstrtou16(token, 0, &ps_poll_num))
1621 token = strsep(&sptr, " ");
1624 if (kstrtou16(token, 0, &dtim))
1627 token = strsep(&sptr, " ");
1630 if (kstrtou16(token, 0, &tx_wakeup))
1633 token = strsep(&sptr, " ");
1636 if (kstrtou16(token, 0, &num_tx))
1639 ath6kl_wmi_pmparams_cmd(ar->wmi, 0, idle_period, ps_poll_num,
1640 dtim, tx_wakeup, num_tx, 0);
1645 static const struct file_operations fops_power_params = {
1646 .write = ath6kl_power_params_write,
1647 .open = ath6kl_debugfs_open,
1648 .owner = THIS_MODULE,
1649 .llseek = default_llseek,
1652 int ath6kl_debug_init(struct ath6kl *ar)
1654 ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
1655 if (ar->debug.fwlog_buf.buf == NULL)
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);
1664 spin_lock_init(&ar->debug.fwlog_lock);
1667 * Actually we are lying here but don't know how to read the mask
1668 * value from the firmware.
1670 ar->debug.fwlog_mask = 0;
1672 ar->debugfs_phy = debugfs_create_dir("ath6kl",
1673 ar->wiphy->debugfsdir);
1674 if (!ar->debugfs_phy) {
1675 vfree(ar->debug.fwlog_buf.buf);
1676 kfree(ar->debug.fwlog_tmp);
1680 debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
1683 debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
1684 &fops_credit_dist_stats);
1686 debugfs_create_file("endpoint_stats", S_IRUSR | S_IWUSR,
1687 ar->debugfs_phy, ar, &fops_endpoint_stats);
1689 debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
1692 debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy,
1693 ar, &fops_fwlog_mask);
1695 debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
1696 &fops_diag_reg_read);
1698 debugfs_create_file("reg_dump", S_IRUSR, ar->debugfs_phy, ar,
1701 debugfs_create_file("lrssi_roam_threshold", S_IRUSR | S_IWUSR,
1702 ar->debugfs_phy, ar, &fops_lrssi_roam_threshold);
1704 debugfs_create_file("reg_write", S_IRUSR | S_IWUSR,
1705 ar->debugfs_phy, ar, &fops_diag_reg_write);
1707 debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar,
1710 debugfs_create_file("roam_table", S_IRUSR, ar->debugfs_phy, ar,
1713 debugfs_create_file("force_roam", S_IWUSR, ar->debugfs_phy, ar,
1716 debugfs_create_file("roam_mode", S_IWUSR, ar->debugfs_phy, ar,
1719 debugfs_create_file("keepalive", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
1722 debugfs_create_file("disconnect_timeout", S_IRUSR | S_IWUSR,
1723 ar->debugfs_phy, ar, &fops_disconnect_timeout);
1725 debugfs_create_file("create_qos", S_IWUSR, ar->debugfs_phy, ar,
1728 debugfs_create_file("delete_qos", S_IWUSR, ar->debugfs_phy, ar,
1731 debugfs_create_file("bgscan_interval", S_IWUSR,
1732 ar->debugfs_phy, ar, &fops_bgscan_int);
1734 debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR,
1735 ar->debugfs_phy, ar, &fops_listen_int);
1737 debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar,
1738 &fops_power_params);
1743 void ath6kl_debug_cleanup(struct ath6kl *ar)
1745 vfree(ar->debug.fwlog_buf.buf);
1746 kfree(ar->debug.fwlog_tmp);
1747 kfree(ar->debug.roam_tbl);