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>
26 struct ath6kl_fwlog_slot
{
30 /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */
34 #define ATH6KL_FWLOG_SIZE 32768
35 #define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \
36 ATH6KL_FWLOG_PAYLOAD_SIZE)
37 #define ATH6KL_FWLOG_VALID_MASK 0x1ffff
39 int ath6kl_printk(const char *level
, const char *fmt
, ...)
50 rtn
= printk("%sath6kl: %pV", level
, &vaf
);
57 #ifdef CONFIG_ATH6KL_DEBUG
59 #define REG_OUTPUT_LEN_PER_LINE 25
60 #define REGTYPE_STR_LEN 100
62 struct ath6kl_diag_reg_info
{
68 static const struct ath6kl_diag_reg_info diag_reg
[] = {
69 { 0x20000, 0x200fc, "General DMA and Rx registers" },
70 { 0x28000, 0x28900, "MAC PCU register & keycache" },
71 { 0x20800, 0x20a40, "QCU" },
72 { 0x21000, 0x212f0, "DCU" },
73 { 0x4000, 0x42e4, "RTC" },
74 { 0x540000, 0x540000 + (256 * 1024), "RAM" },
75 { 0x29800, 0x2B210, "Base Band" },
76 { 0x1C000, 0x1C748, "Analog" },
79 void ath6kl_dump_registers(struct ath6kl_device
*dev
,
80 struct ath6kl_irq_proc_registers
*irq_proc_reg
,
81 struct ath6kl_irq_enable_reg
*irq_enable_reg
)
84 ath6kl_dbg(ATH6KL_DBG_ANY
, ("<------- Register Table -------->\n"));
86 if (irq_proc_reg
!= NULL
) {
87 ath6kl_dbg(ATH6KL_DBG_ANY
,
88 "Host Int status: 0x%x\n",
89 irq_proc_reg
->host_int_status
);
90 ath6kl_dbg(ATH6KL_DBG_ANY
,
91 "CPU Int status: 0x%x\n",
92 irq_proc_reg
->cpu_int_status
);
93 ath6kl_dbg(ATH6KL_DBG_ANY
,
94 "Error Int status: 0x%x\n",
95 irq_proc_reg
->error_int_status
);
96 ath6kl_dbg(ATH6KL_DBG_ANY
,
97 "Counter Int status: 0x%x\n",
98 irq_proc_reg
->counter_int_status
);
99 ath6kl_dbg(ATH6KL_DBG_ANY
,
100 "Mbox Frame: 0x%x\n",
101 irq_proc_reg
->mbox_frame
);
102 ath6kl_dbg(ATH6KL_DBG_ANY
,
103 "Rx Lookahead Valid: 0x%x\n",
104 irq_proc_reg
->rx_lkahd_valid
);
105 ath6kl_dbg(ATH6KL_DBG_ANY
,
106 "Rx Lookahead 0: 0x%x\n",
107 irq_proc_reg
->rx_lkahd
[0]);
108 ath6kl_dbg(ATH6KL_DBG_ANY
,
109 "Rx Lookahead 1: 0x%x\n",
110 irq_proc_reg
->rx_lkahd
[1]);
112 if (dev
->ar
->mbox_info
.gmbox_addr
!= 0) {
114 * If the target supports GMBOX hardware, dump some
117 ath6kl_dbg(ATH6KL_DBG_ANY
,
118 "GMBOX Host Int status 2: 0x%x\n",
119 irq_proc_reg
->host_int_status2
);
120 ath6kl_dbg(ATH6KL_DBG_ANY
,
121 "GMBOX RX Avail: 0x%x\n",
122 irq_proc_reg
->gmbox_rx_avail
);
123 ath6kl_dbg(ATH6KL_DBG_ANY
,
124 "GMBOX lookahead alias 0: 0x%x\n",
125 irq_proc_reg
->rx_gmbox_lkahd_alias
[0]);
126 ath6kl_dbg(ATH6KL_DBG_ANY
,
127 "GMBOX lookahead alias 1: 0x%x\n",
128 irq_proc_reg
->rx_gmbox_lkahd_alias
[1]);
133 if (irq_enable_reg
!= NULL
) {
134 ath6kl_dbg(ATH6KL_DBG_ANY
,
135 "Int status Enable: 0x%x\n",
136 irq_enable_reg
->int_status_en
);
137 ath6kl_dbg(ATH6KL_DBG_ANY
, "Counter Int status Enable: 0x%x\n",
138 irq_enable_reg
->cntr_int_status_en
);
140 ath6kl_dbg(ATH6KL_DBG_ANY
, "<------------------------------->\n");
143 static void dump_cred_dist(struct htc_endpoint_credit_dist
*ep_dist
)
145 ath6kl_dbg(ATH6KL_DBG_ANY
,
146 "--- endpoint: %d svc_id: 0x%X ---\n",
147 ep_dist
->endpoint
, ep_dist
->svc_id
);
148 ath6kl_dbg(ATH6KL_DBG_ANY
, " dist_flags : 0x%X\n",
149 ep_dist
->dist_flags
);
150 ath6kl_dbg(ATH6KL_DBG_ANY
, " cred_norm : %d\n",
152 ath6kl_dbg(ATH6KL_DBG_ANY
, " cred_min : %d\n",
154 ath6kl_dbg(ATH6KL_DBG_ANY
, " credits : %d\n",
156 ath6kl_dbg(ATH6KL_DBG_ANY
, " cred_assngd : %d\n",
157 ep_dist
->cred_assngd
);
158 ath6kl_dbg(ATH6KL_DBG_ANY
, " seek_cred : %d\n",
160 ath6kl_dbg(ATH6KL_DBG_ANY
, " cred_sz : %d\n",
162 ath6kl_dbg(ATH6KL_DBG_ANY
, " cred_per_msg : %d\n",
163 ep_dist
->cred_per_msg
);
164 ath6kl_dbg(ATH6KL_DBG_ANY
, " cred_to_dist : %d\n",
165 ep_dist
->cred_to_dist
);
166 ath6kl_dbg(ATH6KL_DBG_ANY
, " txq_depth : %d\n",
167 get_queue_depth(&((struct htc_endpoint
*)
168 ep_dist
->htc_rsvd
)->txq
));
169 ath6kl_dbg(ATH6KL_DBG_ANY
,
170 "----------------------------------\n");
173 void dump_cred_dist_stats(struct htc_target
*target
)
175 struct htc_endpoint_credit_dist
*ep_list
;
177 if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_TRC
))
180 list_for_each_entry(ep_list
, &target
->cred_dist_list
, list
)
181 dump_cred_dist(ep_list
);
183 ath6kl_dbg(ATH6KL_DBG_HTC
, "ctxt:%p dist:%p\n",
184 target
->cred_dist_cntxt
, NULL
);
185 ath6kl_dbg(ATH6KL_DBG_HTC
,
186 "credit distribution, total : %d, free : %d\n",
187 target
->cred_dist_cntxt
->total_avail_credits
,
188 target
->cred_dist_cntxt
->cur_free_credits
);
191 static int ath6kl_debugfs_open(struct inode
*inode
, struct file
*file
)
193 file
->private_data
= inode
->i_private
;
197 void ath6kl_debug_war(struct ath6kl
*ar
, enum ath6kl_war war
)
200 case ATH6KL_WAR_INVALID_RATE
:
201 ar
->debug
.war_stats
.invalid_rate
++;
206 static ssize_t
read_file_war_stats(struct file
*file
, char __user
*user_buf
,
207 size_t count
, loff_t
*ppos
)
209 struct ath6kl
*ar
= file
->private_data
;
211 unsigned int len
= 0, buf_len
= 1500;
214 buf
= kzalloc(buf_len
, GFP_KERNEL
);
218 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
219 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
221 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n\n",
222 "=================");
223 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10u\n",
224 "Invalid rates", ar
->debug
.war_stats
.invalid_rate
);
226 if (WARN_ON(len
> buf_len
))
229 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
235 static const struct file_operations fops_war_stats
= {
236 .read
= read_file_war_stats
,
237 .open
= ath6kl_debugfs_open
,
238 .owner
= THIS_MODULE
,
239 .llseek
= default_llseek
,
242 static void ath6kl_debug_fwlog_add(struct ath6kl
*ar
, const void *buf
,
245 struct circ_buf
*fwlog
= &ar
->debug
.fwlog_buf
;
249 /* entries must all be equal size */
250 if (WARN_ON(buf_len
!= ATH6KL_FWLOG_SLOT_SIZE
))
253 space
= CIRC_SPACE(fwlog
->head
, fwlog
->tail
, ATH6KL_FWLOG_SIZE
);
255 /* discard oldest slot */
256 fwlog
->tail
= (fwlog
->tail
+ ATH6KL_FWLOG_SLOT_SIZE
) &
257 (ATH6KL_FWLOG_SIZE
- 1);
259 for (i
= 0; i
< buf_len
; i
+= space
) {
260 space
= CIRC_SPACE_TO_END(fwlog
->head
, fwlog
->tail
,
263 if ((size_t) space
> buf_len
- i
)
266 memcpy(&fwlog
->buf
[fwlog
->head
], buf
, space
);
267 fwlog
->head
= (fwlog
->head
+ space
) & (ATH6KL_FWLOG_SIZE
- 1);
272 void ath6kl_debug_fwlog_event(struct ath6kl
*ar
, const void *buf
, size_t len
)
274 struct ath6kl_fwlog_slot
*slot
= ar
->debug
.fwlog_tmp
;
277 if (WARN_ON(len
> ATH6KL_FWLOG_PAYLOAD_SIZE
))
280 spin_lock_bh(&ar
->debug
.fwlog_lock
);
282 slot
->timestamp
= cpu_to_le32(jiffies
);
283 slot
->length
= cpu_to_le32(len
);
284 memcpy(slot
->payload
, buf
, len
);
286 slot_len
= sizeof(*slot
) + len
;
288 if (slot_len
< ATH6KL_FWLOG_SLOT_SIZE
)
289 memset(slot
->payload
+ len
, 0,
290 ATH6KL_FWLOG_SLOT_SIZE
- slot_len
);
292 ath6kl_debug_fwlog_add(ar
, slot
, ATH6KL_FWLOG_SLOT_SIZE
);
294 spin_unlock_bh(&ar
->debug
.fwlog_lock
);
297 static bool ath6kl_debug_fwlog_empty(struct ath6kl
*ar
)
299 return CIRC_CNT(ar
->debug
.fwlog_buf
.head
,
300 ar
->debug
.fwlog_buf
.tail
,
301 ATH6KL_FWLOG_SLOT_SIZE
) == 0;
304 static ssize_t
ath6kl_fwlog_read(struct file
*file
, char __user
*user_buf
,
305 size_t count
, loff_t
*ppos
)
307 struct ath6kl
*ar
= file
->private_data
;
308 struct circ_buf
*fwlog
= &ar
->debug
.fwlog_buf
;
309 size_t len
= 0, buf_len
= count
;
314 buf
= vmalloc(buf_len
);
318 /* read undelivered logs from firmware */
319 ath6kl_read_fwlogs(ar
);
321 spin_lock_bh(&ar
->debug
.fwlog_lock
);
323 while (len
< buf_len
&& !ath6kl_debug_fwlog_empty(ar
)) {
324 ccnt
= CIRC_CNT_TO_END(fwlog
->head
, fwlog
->tail
,
327 if ((size_t) ccnt
> buf_len
- len
)
328 ccnt
= buf_len
- len
;
330 memcpy(buf
+ len
, &fwlog
->buf
[fwlog
->tail
], ccnt
);
333 fwlog
->tail
= (fwlog
->tail
+ ccnt
) &
334 (ATH6KL_FWLOG_SIZE
- 1);
337 spin_unlock_bh(&ar
->debug
.fwlog_lock
);
339 if (WARN_ON(len
> buf_len
))
342 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
349 static const struct file_operations fops_fwlog
= {
350 .open
= ath6kl_debugfs_open
,
351 .read
= ath6kl_fwlog_read
,
352 .owner
= THIS_MODULE
,
353 .llseek
= default_llseek
,
356 static ssize_t
ath6kl_fwlog_mask_read(struct file
*file
, char __user
*user_buf
,
357 size_t count
, loff_t
*ppos
)
359 struct ath6kl
*ar
= file
->private_data
;
363 len
= snprintf(buf
, sizeof(buf
), "0x%x\n", ar
->debug
.fwlog_mask
);
365 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
368 static ssize_t
ath6kl_fwlog_mask_write(struct file
*file
,
369 const char __user
*user_buf
,
370 size_t count
, loff_t
*ppos
)
372 struct ath6kl
*ar
= file
->private_data
;
375 ret
= kstrtou32_from_user(user_buf
, count
, 0, &ar
->debug
.fwlog_mask
);
379 ret
= ath6kl_wmi_config_debug_module_cmd(ar
->wmi
,
380 ATH6KL_FWLOG_VALID_MASK
,
381 ar
->debug
.fwlog_mask
);
388 static const struct file_operations fops_fwlog_mask
= {
389 .open
= ath6kl_debugfs_open
,
390 .read
= ath6kl_fwlog_mask_read
,
391 .write
= ath6kl_fwlog_mask_write
,
392 .owner
= THIS_MODULE
,
393 .llseek
= default_llseek
,
396 static ssize_t
read_file_tgt_stats(struct file
*file
, char __user
*user_buf
,
397 size_t count
, loff_t
*ppos
)
399 struct ath6kl
*ar
= file
->private_data
;
400 /* TODO: Findout vif */
401 struct ath6kl_vif
*vif
= ar
->vif
;
402 struct target_stats
*tgt_stats
= &vif
->target_stats
;
404 unsigned int len
= 0, buf_len
= 1500;
409 buf
= kzalloc(buf_len
, GFP_KERNEL
);
413 if (down_interruptible(&ar
->sem
)) {
418 set_bit(STATS_UPDATE_PEND
, &vif
->flags
);
420 if (ath6kl_wmi_get_stats_cmd(ar
->wmi
)) {
426 left
= wait_event_interruptible_timeout(ar
->event_wq
,
427 !test_bit(STATS_UPDATE_PEND
,
428 &vif
->flags
), WMI_TIMEOUT
);
437 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
438 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
440 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n\n",
441 "=================");
442 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
443 "Ucast packets", tgt_stats
->tx_ucast_pkt
);
444 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
445 "Bcast packets", tgt_stats
->tx_bcast_pkt
);
446 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
447 "Ucast byte", tgt_stats
->tx_ucast_byte
);
448 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
449 "Bcast byte", tgt_stats
->tx_bcast_byte
);
450 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
451 "Rts success cnt", tgt_stats
->tx_rts_success_cnt
);
452 for (i
= 0; i
< 4; i
++)
453 len
+= scnprintf(buf
+ len
, buf_len
- len
,
454 "%18s %d %10llu\n", "PER on ac",
455 i
, tgt_stats
->tx_pkt_per_ac
[i
]);
456 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
457 "Error", tgt_stats
->tx_err
);
458 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
459 "Fail count", tgt_stats
->tx_fail_cnt
);
460 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
461 "Retry count", tgt_stats
->tx_retry_cnt
);
462 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
463 "Multi retry cnt", tgt_stats
->tx_mult_retry_cnt
);
464 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
465 "Rts fail cnt", tgt_stats
->tx_rts_fail_cnt
);
466 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s %10llu\n\n",
467 "TKIP counter measure used",
468 tgt_stats
->tkip_cnter_measures_invoked
);
470 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
472 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
473 "=================");
475 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
476 "Ucast packets", tgt_stats
->rx_ucast_pkt
);
477 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
478 "Ucast Rate", tgt_stats
->rx_ucast_rate
);
479 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
480 "Bcast packets", tgt_stats
->rx_bcast_pkt
);
481 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
482 "Ucast byte", tgt_stats
->rx_ucast_byte
);
483 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
484 "Bcast byte", tgt_stats
->rx_bcast_byte
);
485 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
486 "Fragmented pkt", tgt_stats
->rx_frgment_pkt
);
487 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
488 "Error", tgt_stats
->rx_err
);
489 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
490 "CRC Err", tgt_stats
->rx_crc_err
);
491 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
492 "Key chache miss", tgt_stats
->rx_key_cache_miss
);
493 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
494 "Decrypt Err", tgt_stats
->rx_decrypt_err
);
495 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
496 "Duplicate frame", tgt_stats
->rx_dupl_frame
);
497 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
498 "Tkip Mic failure", tgt_stats
->tkip_local_mic_fail
);
499 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
500 "TKIP format err", tgt_stats
->tkip_fmt_err
);
501 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
502 "CCMP format Err", tgt_stats
->ccmp_fmt_err
);
503 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n\n",
504 "CCMP Replay Err", tgt_stats
->ccmp_replays
);
506 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
507 "Misc Target stats");
508 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
509 "=================");
510 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
511 "Beacon Miss count", tgt_stats
->cs_bmiss_cnt
);
512 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
513 "Num Connects", tgt_stats
->cs_connect_cnt
);
514 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
515 "Num disconnects", tgt_stats
->cs_discon_cnt
);
516 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
517 "Beacon avg rssi", tgt_stats
->cs_ave_beacon_rssi
);
522 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
528 static const struct file_operations fops_tgt_stats
= {
529 .read
= read_file_tgt_stats
,
530 .open
= ath6kl_debugfs_open
,
531 .owner
= THIS_MODULE
,
532 .llseek
= default_llseek
,
535 #define print_credit_info(fmt_str, ep_list_field) \
536 (len += scnprintf(buf + len, buf_len - len, fmt_str, \
537 ep_list->ep_list_field))
538 #define CREDIT_INFO_DISPLAY_STRING_LEN 200
539 #define CREDIT_INFO_LEN 128
541 static ssize_t
read_file_credit_dist_stats(struct file
*file
,
542 char __user
*user_buf
,
543 size_t count
, loff_t
*ppos
)
545 struct ath6kl
*ar
= file
->private_data
;
546 struct htc_target
*target
= ar
->htc_target
;
547 struct htc_endpoint_credit_dist
*ep_list
;
549 unsigned int buf_len
, len
= 0;
552 buf_len
= CREDIT_INFO_DISPLAY_STRING_LEN
+
553 get_queue_depth(&target
->cred_dist_list
) * CREDIT_INFO_LEN
;
554 buf
= kzalloc(buf_len
, GFP_KERNEL
);
558 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s%5d\n",
559 "Total Avail Credits: ",
560 target
->cred_dist_cntxt
->total_avail_credits
);
561 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s%5d\n",
563 target
->cred_dist_cntxt
->cur_free_credits
);
565 len
+= scnprintf(buf
+ len
, buf_len
- len
,
566 " Epid Flags Cred_norm Cred_min Credits Cred_assngd"
567 " Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
570 list_for_each_entry(ep_list
, &target
->cred_dist_list
, list
) {
571 print_credit_info(" %2d", endpoint
);
572 print_credit_info("%10x", dist_flags
);
573 print_credit_info("%8d", cred_norm
);
574 print_credit_info("%9d", cred_min
);
575 print_credit_info("%9d", credits
);
576 print_credit_info("%10d", cred_assngd
);
577 print_credit_info("%13d", seek_cred
);
578 print_credit_info("%12d", cred_sz
);
579 print_credit_info("%9d", cred_per_msg
);
580 print_credit_info("%14d", cred_to_dist
);
581 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%12d\n",
582 get_queue_depth(&((struct htc_endpoint
*)
583 ep_list
->htc_rsvd
)->txq
));
589 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
594 static const struct file_operations fops_credit_dist_stats
= {
595 .read
= read_file_credit_dist_stats
,
596 .open
= ath6kl_debugfs_open
,
597 .owner
= THIS_MODULE
,
598 .llseek
= default_llseek
,
601 static unsigned int print_endpoint_stat(struct htc_target
*target
, char *buf
,
602 unsigned int buf_len
, unsigned int len
,
603 int offset
, const char *name
)
606 struct htc_endpoint_stats
*ep_st
;
609 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%s:", name
);
610 for (i
= 0; i
< ENDPOINT_MAX
; i
++) {
611 ep_st
= &target
->endpoint
[i
].ep_st
;
612 counter
= ((u32
*) ep_st
) + (offset
/ 4);
613 len
+= scnprintf(buf
+ len
, buf_len
- len
, " %u", *counter
);
615 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
620 static ssize_t
ath6kl_endpoint_stats_read(struct file
*file
,
621 char __user
*user_buf
,
622 size_t count
, loff_t
*ppos
)
624 struct ath6kl
*ar
= file
->private_data
;
625 struct htc_target
*target
= ar
->htc_target
;
627 unsigned int buf_len
, len
= 0;
630 buf_len
= sizeof(struct htc_endpoint_stats
) / sizeof(u32
) *
631 (25 + ENDPOINT_MAX
* 11);
632 buf
= kmalloc(buf_len
, GFP_KERNEL
);
636 #define EPSTAT(name) \
637 len = print_endpoint_stat(target, buf, buf_len, len, \
638 offsetof(struct htc_endpoint_stats, name), \
640 EPSTAT(cred_low_indicate
);
642 EPSTAT(tx_pkt_bundled
);
646 EPSTAT(cred_rpt_from_rx
);
647 EPSTAT(cred_rpt_from_other
);
648 EPSTAT(cred_rpt_ep0
);
649 EPSTAT(cred_from_rx
);
650 EPSTAT(cred_from_other
);
651 EPSTAT(cred_from_ep0
);
657 EPSTAT(rx_bundle_lkahd
);
658 EPSTAT(rx_bundle_from_hdr
);
659 EPSTAT(rx_alloc_thresh_hit
);
660 EPSTAT(rxalloc_thresh_byte
);
666 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
671 static ssize_t
ath6kl_endpoint_stats_write(struct file
*file
,
672 const char __user
*user_buf
,
673 size_t count
, loff_t
*ppos
)
675 struct ath6kl
*ar
= file
->private_data
;
676 struct htc_target
*target
= ar
->htc_target
;
679 struct htc_endpoint_stats
*ep_st
;
681 ret
= kstrtou32_from_user(user_buf
, count
, 0, &val
);
685 for (i
= 0; i
< ENDPOINT_MAX
; i
++) {
686 ep_st
= &target
->endpoint
[i
].ep_st
;
687 memset(ep_st
, 0, sizeof(*ep_st
));
694 static const struct file_operations fops_endpoint_stats
= {
695 .open
= ath6kl_debugfs_open
,
696 .read
= ath6kl_endpoint_stats_read
,
697 .write
= ath6kl_endpoint_stats_write
,
698 .owner
= THIS_MODULE
,
699 .llseek
= default_llseek
,
702 static unsigned long ath6kl_get_num_reg(void)
705 unsigned long n_reg
= 0;
707 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++)
709 (diag_reg
[i
].reg_end
- diag_reg
[i
].reg_start
) / 4 + 1;
714 static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr
)
718 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++) {
719 if (reg_addr
>= diag_reg
[i
].reg_start
&&
720 reg_addr
<= diag_reg
[i
].reg_end
)
727 static ssize_t
ath6kl_regread_read(struct file
*file
, char __user
*user_buf
,
728 size_t count
, loff_t
*ppos
)
730 struct ath6kl
*ar
= file
->private_data
;
732 unsigned int len
= 0;
734 if (ar
->debug
.dbgfs_diag_reg
)
735 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "0x%x\n",
736 ar
->debug
.dbgfs_diag_reg
);
738 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
739 "All diag registers\n");
741 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
744 static ssize_t
ath6kl_regread_write(struct file
*file
,
745 const char __user
*user_buf
,
746 size_t count
, loff_t
*ppos
)
748 struct ath6kl
*ar
= file
->private_data
;
751 unsigned long reg_addr
;
753 len
= min(count
, sizeof(buf
) - 1);
754 if (copy_from_user(buf
, user_buf
, len
))
759 if (strict_strtoul(buf
, 0, ®_addr
))
762 if ((reg_addr
% 4) != 0)
765 if (reg_addr
&& !ath6kl_dbg_is_diag_reg_valid(reg_addr
))
768 ar
->debug
.dbgfs_diag_reg
= reg_addr
;
773 static const struct file_operations fops_diag_reg_read
= {
774 .read
= ath6kl_regread_read
,
775 .write
= ath6kl_regread_write
,
776 .open
= ath6kl_debugfs_open
,
777 .owner
= THIS_MODULE
,
778 .llseek
= default_llseek
,
781 static int ath6kl_regdump_open(struct inode
*inode
, struct file
*file
)
783 struct ath6kl
*ar
= inode
->i_private
;
785 unsigned long int reg_len
;
786 unsigned int len
= 0, n_reg
;
791 /* Dump all the registers if no register is specified */
792 if (!ar
->debug
.dbgfs_diag_reg
)
793 n_reg
= ath6kl_get_num_reg();
797 reg_len
= n_reg
* REG_OUTPUT_LEN_PER_LINE
;
799 reg_len
+= REGTYPE_STR_LEN
;
801 buf
= vmalloc(reg_len
);
806 addr
= ar
->debug
.dbgfs_diag_reg
;
808 status
= ath6kl_diag_read32(ar
,
809 TARG_VTOP(ar
->target_type
, addr
),
814 len
+= scnprintf(buf
+ len
, reg_len
- len
,
815 "0x%06x 0x%08x\n", addr
, le32_to_cpu(reg_val
));
819 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++) {
820 len
+= scnprintf(buf
+ len
, reg_len
- len
,
821 "%s\n", diag_reg
[i
].reg_info
);
822 for (addr
= diag_reg
[i
].reg_start
;
823 addr
<= diag_reg
[i
].reg_end
; addr
+= 4) {
824 status
= ath6kl_diag_read32(ar
,
825 TARG_VTOP(ar
->target_type
, addr
),
830 len
+= scnprintf(buf
+ len
, reg_len
- len
,
832 addr
, le32_to_cpu(reg_val
));
837 file
->private_data
= buf
;
841 ath6kl_warn("Unable to read memory:%u\n", addr
);
846 static ssize_t
ath6kl_regdump_read(struct file
*file
, char __user
*user_buf
,
847 size_t count
, loff_t
*ppos
)
849 u8
*buf
= file
->private_data
;
850 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, strlen(buf
));
853 static int ath6kl_regdump_release(struct inode
*inode
, struct file
*file
)
855 vfree(file
->private_data
);
859 static const struct file_operations fops_reg_dump
= {
860 .open
= ath6kl_regdump_open
,
861 .read
= ath6kl_regdump_read
,
862 .release
= ath6kl_regdump_release
,
863 .owner
= THIS_MODULE
,
864 .llseek
= default_llseek
,
867 static ssize_t
ath6kl_lrssi_roam_write(struct file
*file
,
868 const char __user
*user_buf
,
869 size_t count
, loff_t
*ppos
)
871 struct ath6kl
*ar
= file
->private_data
;
872 unsigned long lrssi_roam_threshold
;
876 len
= min(count
, sizeof(buf
) - 1);
877 if (copy_from_user(buf
, user_buf
, len
))
881 if (strict_strtoul(buf
, 0, &lrssi_roam_threshold
))
884 ar
->lrssi_roam_threshold
= lrssi_roam_threshold
;
886 ath6kl_wmi_set_roam_lrssi_cmd(ar
->wmi
, ar
->lrssi_roam_threshold
);
891 static ssize_t
ath6kl_lrssi_roam_read(struct file
*file
,
892 char __user
*user_buf
,
893 size_t count
, loff_t
*ppos
)
895 struct ath6kl
*ar
= file
->private_data
;
899 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->lrssi_roam_threshold
);
901 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
904 static const struct file_operations fops_lrssi_roam_threshold
= {
905 .read
= ath6kl_lrssi_roam_read
,
906 .write
= ath6kl_lrssi_roam_write
,
907 .open
= ath6kl_debugfs_open
,
908 .owner
= THIS_MODULE
,
909 .llseek
= default_llseek
,
912 static ssize_t
ath6kl_regwrite_read(struct file
*file
,
913 char __user
*user_buf
,
914 size_t count
, loff_t
*ppos
)
916 struct ath6kl
*ar
= file
->private_data
;
918 unsigned int len
= 0;
920 len
= scnprintf(buf
, sizeof(buf
), "Addr: 0x%x Val: 0x%x\n",
921 ar
->debug
.diag_reg_addr_wr
, ar
->debug
.diag_reg_val_wr
);
923 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
926 static ssize_t
ath6kl_regwrite_write(struct file
*file
,
927 const char __user
*user_buf
,
928 size_t count
, loff_t
*ppos
)
930 struct ath6kl
*ar
= file
->private_data
;
933 unsigned int len
= 0;
934 u32 reg_addr
, reg_val
;
936 len
= min(count
, sizeof(buf
) - 1);
937 if (copy_from_user(buf
, user_buf
, len
))
943 token
= strsep(&sptr
, "=");
947 if (kstrtou32(token
, 0, ®_addr
))
950 if (!ath6kl_dbg_is_diag_reg_valid(reg_addr
))
953 if (kstrtou32(sptr
, 0, ®_val
))
956 ar
->debug
.diag_reg_addr_wr
= reg_addr
;
957 ar
->debug
.diag_reg_val_wr
= reg_val
;
959 if (ath6kl_diag_write32(ar
, ar
->debug
.diag_reg_addr_wr
,
960 cpu_to_le32(ar
->debug
.diag_reg_val_wr
)))
966 static const struct file_operations fops_diag_reg_write
= {
967 .read
= ath6kl_regwrite_read
,
968 .write
= ath6kl_regwrite_write
,
969 .open
= ath6kl_debugfs_open
,
970 .owner
= THIS_MODULE
,
971 .llseek
= default_llseek
,
974 int ath6kl_debug_roam_tbl_event(struct ath6kl
*ar
, const void *buf
,
977 const struct wmi_target_roam_tbl
*tbl
;
980 if (len
< sizeof(*tbl
))
983 tbl
= (const struct wmi_target_roam_tbl
*) buf
;
984 num_entries
= le16_to_cpu(tbl
->num_entries
);
985 if (sizeof(*tbl
) + num_entries
* sizeof(struct wmi_bss_roam_info
) >
989 if (ar
->debug
.roam_tbl
== NULL
||
990 ar
->debug
.roam_tbl_len
< (unsigned int) len
) {
991 kfree(ar
->debug
.roam_tbl
);
992 ar
->debug
.roam_tbl
= kmalloc(len
, GFP_ATOMIC
);
993 if (ar
->debug
.roam_tbl
== NULL
)
997 memcpy(ar
->debug
.roam_tbl
, buf
, len
);
998 ar
->debug
.roam_tbl_len
= len
;
1000 if (test_bit(ROAM_TBL_PEND
, &ar
->flag
)) {
1001 clear_bit(ROAM_TBL_PEND
, &ar
->flag
);
1002 wake_up(&ar
->event_wq
);
1008 static ssize_t
ath6kl_roam_table_read(struct file
*file
, char __user
*user_buf
,
1009 size_t count
, loff_t
*ppos
)
1011 struct ath6kl
*ar
= file
->private_data
;
1014 struct wmi_target_roam_tbl
*tbl
;
1017 unsigned int len
, buf_len
;
1020 if (down_interruptible(&ar
->sem
))
1023 set_bit(ROAM_TBL_PEND
, &ar
->flag
);
1025 ret
= ath6kl_wmi_get_roam_tbl_cmd(ar
->wmi
);
1031 left
= wait_event_interruptible_timeout(
1032 ar
->event_wq
, !test_bit(ROAM_TBL_PEND
, &ar
->flag
), WMI_TIMEOUT
);
1038 if (ar
->debug
.roam_tbl
== NULL
)
1041 tbl
= (struct wmi_target_roam_tbl
*) ar
->debug
.roam_tbl
;
1042 num_entries
= le16_to_cpu(tbl
->num_entries
);
1044 buf_len
= 100 + num_entries
* 100;
1045 buf
= kzalloc(buf_len
, GFP_KERNEL
);
1049 len
+= scnprintf(buf
+ len
, buf_len
- len
,
1051 "# roam_util bssid rssi rssidt last_rssi util bias\n",
1052 le16_to_cpu(tbl
->roam_mode
));
1054 for (i
= 0; i
< num_entries
; i
++) {
1055 struct wmi_bss_roam_info
*info
= &tbl
->info
[i
];
1056 len
+= scnprintf(buf
+ len
, buf_len
- len
,
1057 "%d %pM %d %d %d %d %d\n",
1058 a_sle32_to_cpu(info
->roam_util
), info
->bssid
,
1059 info
->rssi
, info
->rssidt
, info
->last_rssi
,
1060 info
->util
, info
->bias
);
1066 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1072 static const struct file_operations fops_roam_table
= {
1073 .read
= ath6kl_roam_table_read
,
1074 .open
= ath6kl_debugfs_open
,
1075 .owner
= THIS_MODULE
,
1076 .llseek
= default_llseek
,
1079 static ssize_t
ath6kl_force_roam_write(struct file
*file
,
1080 const char __user
*user_buf
,
1081 size_t count
, loff_t
*ppos
)
1083 struct ath6kl
*ar
= file
->private_data
;
1091 len
= min(count
, sizeof(buf
) - 1);
1092 if (copy_from_user(buf
, user_buf
, len
))
1096 if (sscanf(buf
, "%02x:%02x:%02x:%02x:%02x:%02x",
1097 &addr
[0], &addr
[1], &addr
[2], &addr
[3], &addr
[4], &addr
[5])
1100 for (i
= 0; i
< ETH_ALEN
; i
++)
1103 ret
= ath6kl_wmi_force_roam_cmd(ar
->wmi
, bssid
);
1110 static const struct file_operations fops_force_roam
= {
1111 .write
= ath6kl_force_roam_write
,
1112 .open
= ath6kl_debugfs_open
,
1113 .owner
= THIS_MODULE
,
1114 .llseek
= default_llseek
,
1117 static ssize_t
ath6kl_roam_mode_write(struct file
*file
,
1118 const char __user
*user_buf
,
1119 size_t count
, loff_t
*ppos
)
1121 struct ath6kl
*ar
= file
->private_data
;
1125 enum wmi_roam_mode mode
;
1127 len
= min(count
, sizeof(buf
) - 1);
1128 if (copy_from_user(buf
, user_buf
, len
))
1131 if (len
> 0 && buf
[len
- 1] == '\n')
1132 buf
[len
- 1] = '\0';
1134 if (strcasecmp(buf
, "default") == 0)
1135 mode
= WMI_DEFAULT_ROAM_MODE
;
1136 else if (strcasecmp(buf
, "bssbias") == 0)
1137 mode
= WMI_HOST_BIAS_ROAM_MODE
;
1138 else if (strcasecmp(buf
, "lock") == 0)
1139 mode
= WMI_LOCK_BSS_MODE
;
1143 ret
= ath6kl_wmi_set_roam_mode_cmd(ar
->wmi
, mode
);
1150 static const struct file_operations fops_roam_mode
= {
1151 .write
= ath6kl_roam_mode_write
,
1152 .open
= ath6kl_debugfs_open
,
1153 .owner
= THIS_MODULE
,
1154 .llseek
= default_llseek
,
1157 void ath6kl_debug_set_keepalive(struct ath6kl
*ar
, u8 keepalive
)
1159 ar
->debug
.keepalive
= keepalive
;
1162 static ssize_t
ath6kl_keepalive_read(struct file
*file
, char __user
*user_buf
,
1163 size_t count
, loff_t
*ppos
)
1165 struct ath6kl
*ar
= file
->private_data
;
1169 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->debug
.keepalive
);
1171 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1174 static ssize_t
ath6kl_keepalive_write(struct file
*file
,
1175 const char __user
*user_buf
,
1176 size_t count
, loff_t
*ppos
)
1178 struct ath6kl
*ar
= file
->private_data
;
1182 ret
= kstrtou8_from_user(user_buf
, count
, 0, &val
);
1186 ret
= ath6kl_wmi_set_keepalive_cmd(ar
->wmi
, val
);
1193 static const struct file_operations fops_keepalive
= {
1194 .open
= ath6kl_debugfs_open
,
1195 .read
= ath6kl_keepalive_read
,
1196 .write
= ath6kl_keepalive_write
,
1197 .owner
= THIS_MODULE
,
1198 .llseek
= default_llseek
,
1201 void ath6kl_debug_set_disconnect_timeout(struct ath6kl
*ar
, u8 timeout
)
1203 ar
->debug
.disc_timeout
= timeout
;
1206 static ssize_t
ath6kl_disconnect_timeout_read(struct file
*file
,
1207 char __user
*user_buf
,
1208 size_t count
, loff_t
*ppos
)
1210 struct ath6kl
*ar
= file
->private_data
;
1214 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->debug
.disc_timeout
);
1216 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1219 static ssize_t
ath6kl_disconnect_timeout_write(struct file
*file
,
1220 const char __user
*user_buf
,
1221 size_t count
, loff_t
*ppos
)
1223 struct ath6kl
*ar
= file
->private_data
;
1227 ret
= kstrtou8_from_user(user_buf
, count
, 0, &val
);
1231 ret
= ath6kl_wmi_disctimeout_cmd(ar
->wmi
, val
);
1238 static const struct file_operations fops_disconnect_timeout
= {
1239 .open
= ath6kl_debugfs_open
,
1240 .read
= ath6kl_disconnect_timeout_read
,
1241 .write
= ath6kl_disconnect_timeout_write
,
1242 .owner
= THIS_MODULE
,
1243 .llseek
= default_llseek
,
1246 static ssize_t
ath6kl_create_qos_write(struct file
*file
,
1247 const char __user
*user_buf
,
1248 size_t count
, loff_t
*ppos
)
1251 struct ath6kl
*ar
= file
->private_data
;
1255 struct wmi_create_pstream_cmd pstream
;
1259 len
= min(count
, sizeof(buf
) - 1);
1260 if (copy_from_user(buf
, user_buf
, len
))
1265 token
= strsep(&sptr
, " ");
1268 if (kstrtou8(token
, 0, &pstream
.user_pri
))
1271 token
= strsep(&sptr
, " ");
1274 if (kstrtou8(token
, 0, &pstream
.traffic_direc
))
1277 token
= strsep(&sptr
, " ");
1280 if (kstrtou8(token
, 0, &pstream
.traffic_class
))
1283 token
= strsep(&sptr
, " ");
1286 if (kstrtou8(token
, 0, &pstream
.traffic_type
))
1289 token
= strsep(&sptr
, " ");
1292 if (kstrtou8(token
, 0, &pstream
.voice_psc_cap
))
1295 token
= strsep(&sptr
, " ");
1298 if (kstrtou32(token
, 0, &val32
))
1300 pstream
.min_service_int
= cpu_to_le32(val32
);
1302 token
= strsep(&sptr
, " ");
1305 if (kstrtou32(token
, 0, &val32
))
1307 pstream
.max_service_int
= cpu_to_le32(val32
);
1309 token
= strsep(&sptr
, " ");
1312 if (kstrtou32(token
, 0, &val32
))
1314 pstream
.inactivity_int
= cpu_to_le32(val32
);
1316 token
= strsep(&sptr
, " ");
1319 if (kstrtou32(token
, 0, &val32
))
1321 pstream
.suspension_int
= cpu_to_le32(val32
);
1323 token
= strsep(&sptr
, " ");
1326 if (kstrtou32(token
, 0, &val32
))
1328 pstream
.service_start_time
= cpu_to_le32(val32
);
1330 token
= strsep(&sptr
, " ");
1333 if (kstrtou8(token
, 0, &pstream
.tsid
))
1336 token
= strsep(&sptr
, " ");
1339 if (kstrtou16(token
, 0, &val16
))
1341 pstream
.nominal_msdu
= cpu_to_le16(val16
);
1343 token
= strsep(&sptr
, " ");
1346 if (kstrtou16(token
, 0, &val16
))
1348 pstream
.max_msdu
= cpu_to_le16(val16
);
1350 token
= strsep(&sptr
, " ");
1353 if (kstrtou32(token
, 0, &val32
))
1355 pstream
.min_data_rate
= cpu_to_le32(val32
);
1357 token
= strsep(&sptr
, " ");
1360 if (kstrtou32(token
, 0, &val32
))
1362 pstream
.mean_data_rate
= cpu_to_le32(val32
);
1364 token
= strsep(&sptr
, " ");
1367 if (kstrtou32(token
, 0, &val32
))
1369 pstream
.peak_data_rate
= cpu_to_le32(val32
);
1371 token
= strsep(&sptr
, " ");
1374 if (kstrtou32(token
, 0, &val32
))
1376 pstream
.max_burst_size
= cpu_to_le32(val32
);
1378 token
= strsep(&sptr
, " ");
1381 if (kstrtou32(token
, 0, &val32
))
1383 pstream
.delay_bound
= cpu_to_le32(val32
);
1385 token
= strsep(&sptr
, " ");
1388 if (kstrtou32(token
, 0, &val32
))
1390 pstream
.min_phy_rate
= cpu_to_le32(val32
);
1392 token
= strsep(&sptr
, " ");
1395 if (kstrtou32(token
, 0, &val32
))
1397 pstream
.sba
= cpu_to_le32(val32
);
1399 token
= strsep(&sptr
, " ");
1402 if (kstrtou32(token
, 0, &val32
))
1404 pstream
.medium_time
= cpu_to_le32(val32
);
1406 ath6kl_wmi_create_pstream_cmd(ar
->wmi
, &pstream
);
1411 static const struct file_operations fops_create_qos
= {
1412 .write
= ath6kl_create_qos_write
,
1413 .open
= ath6kl_debugfs_open
,
1414 .owner
= THIS_MODULE
,
1415 .llseek
= default_llseek
,
1418 static ssize_t
ath6kl_delete_qos_write(struct file
*file
,
1419 const char __user
*user_buf
,
1420 size_t count
, loff_t
*ppos
)
1423 struct ath6kl
*ar
= file
->private_data
;
1430 len
= min(count
, sizeof(buf
) - 1);
1431 if (copy_from_user(buf
, user_buf
, len
))
1436 token
= strsep(&sptr
, " ");
1439 if (kstrtou8(token
, 0, &traffic_class
))
1442 token
= strsep(&sptr
, " ");
1445 if (kstrtou8(token
, 0, &tsid
))
1448 ath6kl_wmi_delete_pstream_cmd(ar
->wmi
, traffic_class
, tsid
);
1453 static const struct file_operations fops_delete_qos
= {
1454 .write
= ath6kl_delete_qos_write
,
1455 .open
= ath6kl_debugfs_open
,
1456 .owner
= THIS_MODULE
,
1457 .llseek
= default_llseek
,
1460 static ssize_t
ath6kl_bgscan_int_write(struct file
*file
,
1461 const char __user
*user_buf
,
1462 size_t count
, loff_t
*ppos
)
1464 struct ath6kl
*ar
= file
->private_data
;
1469 len
= min(count
, sizeof(buf
) - 1);
1470 if (copy_from_user(buf
, user_buf
, len
))
1474 if (kstrtou16(buf
, 0, &bgscan_int
))
1477 if (bgscan_int
== 0)
1478 bgscan_int
= 0xffff;
1480 ath6kl_wmi_scanparams_cmd(ar
->wmi
, 0, 0, bgscan_int
, 0, 0, 0, 3,
1486 static const struct file_operations fops_bgscan_int
= {
1487 .write
= ath6kl_bgscan_int_write
,
1488 .open
= ath6kl_debugfs_open
,
1489 .owner
= THIS_MODULE
,
1490 .llseek
= default_llseek
,
1493 int ath6kl_debug_init(struct ath6kl
*ar
)
1495 ar
->debug
.fwlog_buf
.buf
= vmalloc(ATH6KL_FWLOG_SIZE
);
1496 if (ar
->debug
.fwlog_buf
.buf
== NULL
)
1499 ar
->debug
.fwlog_tmp
= kmalloc(ATH6KL_FWLOG_SLOT_SIZE
, GFP_KERNEL
);
1500 if (ar
->debug
.fwlog_tmp
== NULL
) {
1501 vfree(ar
->debug
.fwlog_buf
.buf
);
1505 spin_lock_init(&ar
->debug
.fwlog_lock
);
1508 * Actually we are lying here but don't know how to read the mask
1509 * value from the firmware.
1511 ar
->debug
.fwlog_mask
= 0;
1513 ar
->debugfs_phy
= debugfs_create_dir("ath6kl",
1514 ar
->wiphy
->debugfsdir
);
1515 if (!ar
->debugfs_phy
) {
1516 vfree(ar
->debug
.fwlog_buf
.buf
);
1517 kfree(ar
->debug
.fwlog_tmp
);
1521 debugfs_create_file("tgt_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1524 debugfs_create_file("credit_dist_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1525 &fops_credit_dist_stats
);
1527 debugfs_create_file("endpoint_stats", S_IRUSR
| S_IWUSR
,
1528 ar
->debugfs_phy
, ar
, &fops_endpoint_stats
);
1530 debugfs_create_file("fwlog", S_IRUSR
, ar
->debugfs_phy
, ar
,
1533 debugfs_create_file("fwlog_mask", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
,
1534 ar
, &fops_fwlog_mask
);
1536 debugfs_create_file("reg_addr", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
, ar
,
1537 &fops_diag_reg_read
);
1539 debugfs_create_file("reg_dump", S_IRUSR
, ar
->debugfs_phy
, ar
,
1542 debugfs_create_file("lrssi_roam_threshold", S_IRUSR
| S_IWUSR
,
1543 ar
->debugfs_phy
, ar
, &fops_lrssi_roam_threshold
);
1545 debugfs_create_file("reg_write", S_IRUSR
| S_IWUSR
,
1546 ar
->debugfs_phy
, ar
, &fops_diag_reg_write
);
1548 debugfs_create_file("war_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1551 debugfs_create_file("roam_table", S_IRUSR
, ar
->debugfs_phy
, ar
,
1554 debugfs_create_file("force_roam", S_IWUSR
, ar
->debugfs_phy
, ar
,
1557 debugfs_create_file("roam_mode", S_IWUSR
, ar
->debugfs_phy
, ar
,
1560 debugfs_create_file("keepalive", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
, ar
,
1563 debugfs_create_file("disconnect_timeout", S_IRUSR
| S_IWUSR
,
1564 ar
->debugfs_phy
, ar
, &fops_disconnect_timeout
);
1566 debugfs_create_file("create_qos", S_IWUSR
, ar
->debugfs_phy
, ar
,
1569 debugfs_create_file("delete_qos", S_IWUSR
, ar
->debugfs_phy
, ar
,
1572 debugfs_create_file("bgscan_interval", S_IWUSR
,
1573 ar
->debugfs_phy
, ar
, &fops_bgscan_int
);
1578 void ath6kl_debug_cleanup(struct ath6kl
*ar
)
1580 vfree(ar
->debug
.fwlog_buf
.buf
);
1581 kfree(ar
->debug
.fwlog_tmp
);
1582 kfree(ar
->debug
.roam_tbl
);