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/skbuff.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_MAX_ENTRIES 20
37 #define ATH6KL_FWLOG_VALID_MASK 0x1ffff
39 int ath6kl_printk(const char *level
, const char *fmt
, ...)
50 rtn
= printk("%sath6kl: %pV", level
, &vaf
);
56 EXPORT_SYMBOL(ath6kl_printk
);
58 #ifdef CONFIG_ATH6KL_DEBUG
60 void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask
, const char *fmt
, ...)
65 if (!(debug_mask
& mask
))
73 ath6kl_printk(KERN_DEBUG
, "%pV", &vaf
);
77 EXPORT_SYMBOL(ath6kl_dbg
);
79 void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask
,
80 const char *msg
, const char *prefix
,
81 const void *buf
, size_t len
)
83 if (debug_mask
& mask
) {
85 ath6kl_dbg(mask
, "%s\n", msg
);
87 print_hex_dump_bytes(prefix
, DUMP_PREFIX_OFFSET
, buf
, len
);
90 EXPORT_SYMBOL(ath6kl_dbg_dump
);
92 #define REG_OUTPUT_LEN_PER_LINE 25
93 #define REGTYPE_STR_LEN 100
95 struct ath6kl_diag_reg_info
{
101 static const struct ath6kl_diag_reg_info diag_reg
[] = {
102 { 0x20000, 0x200fc, "General DMA and Rx registers" },
103 { 0x28000, 0x28900, "MAC PCU register & keycache" },
104 { 0x20800, 0x20a40, "QCU" },
105 { 0x21000, 0x212f0, "DCU" },
106 { 0x4000, 0x42e4, "RTC" },
107 { 0x540000, 0x540000 + (256 * 1024), "RAM" },
108 { 0x29800, 0x2B210, "Base Band" },
109 { 0x1C000, 0x1C748, "Analog" },
112 void ath6kl_dump_registers(struct ath6kl_device
*dev
,
113 struct ath6kl_irq_proc_registers
*irq_proc_reg
,
114 struct ath6kl_irq_enable_reg
*irq_enable_reg
)
117 ath6kl_dbg(ATH6KL_DBG_IRQ
, ("<------- Register Table -------->\n"));
119 if (irq_proc_reg
!= NULL
) {
120 ath6kl_dbg(ATH6KL_DBG_IRQ
,
121 "Host Int status: 0x%x\n",
122 irq_proc_reg
->host_int_status
);
123 ath6kl_dbg(ATH6KL_DBG_IRQ
,
124 "CPU Int status: 0x%x\n",
125 irq_proc_reg
->cpu_int_status
);
126 ath6kl_dbg(ATH6KL_DBG_IRQ
,
127 "Error Int status: 0x%x\n",
128 irq_proc_reg
->error_int_status
);
129 ath6kl_dbg(ATH6KL_DBG_IRQ
,
130 "Counter Int status: 0x%x\n",
131 irq_proc_reg
->counter_int_status
);
132 ath6kl_dbg(ATH6KL_DBG_IRQ
,
133 "Mbox Frame: 0x%x\n",
134 irq_proc_reg
->mbox_frame
);
135 ath6kl_dbg(ATH6KL_DBG_IRQ
,
136 "Rx Lookahead Valid: 0x%x\n",
137 irq_proc_reg
->rx_lkahd_valid
);
138 ath6kl_dbg(ATH6KL_DBG_IRQ
,
139 "Rx Lookahead 0: 0x%x\n",
140 irq_proc_reg
->rx_lkahd
[0]);
141 ath6kl_dbg(ATH6KL_DBG_IRQ
,
142 "Rx Lookahead 1: 0x%x\n",
143 irq_proc_reg
->rx_lkahd
[1]);
145 if (dev
->ar
->mbox_info
.gmbox_addr
!= 0) {
147 * If the target supports GMBOX hardware, dump some
150 ath6kl_dbg(ATH6KL_DBG_IRQ
,
151 "GMBOX Host Int status 2: 0x%x\n",
152 irq_proc_reg
->host_int_status2
);
153 ath6kl_dbg(ATH6KL_DBG_IRQ
,
154 "GMBOX RX Avail: 0x%x\n",
155 irq_proc_reg
->gmbox_rx_avail
);
156 ath6kl_dbg(ATH6KL_DBG_IRQ
,
157 "GMBOX lookahead alias 0: 0x%x\n",
158 irq_proc_reg
->rx_gmbox_lkahd_alias
[0]);
159 ath6kl_dbg(ATH6KL_DBG_IRQ
,
160 "GMBOX lookahead alias 1: 0x%x\n",
161 irq_proc_reg
->rx_gmbox_lkahd_alias
[1]);
166 if (irq_enable_reg
!= NULL
) {
167 ath6kl_dbg(ATH6KL_DBG_IRQ
,
168 "Int status Enable: 0x%x\n",
169 irq_enable_reg
->int_status_en
);
170 ath6kl_dbg(ATH6KL_DBG_IRQ
, "Counter Int status Enable: 0x%x\n",
171 irq_enable_reg
->cntr_int_status_en
);
173 ath6kl_dbg(ATH6KL_DBG_IRQ
, "<------------------------------->\n");
176 static void dump_cred_dist(struct htc_endpoint_credit_dist
*ep_dist
)
178 ath6kl_dbg(ATH6KL_DBG_CREDIT
,
179 "--- endpoint: %d svc_id: 0x%X ---\n",
180 ep_dist
->endpoint
, ep_dist
->svc_id
);
181 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " dist_flags : 0x%X\n",
182 ep_dist
->dist_flags
);
183 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_norm : %d\n",
185 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_min : %d\n",
187 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " credits : %d\n",
189 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_assngd : %d\n",
190 ep_dist
->cred_assngd
);
191 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " seek_cred : %d\n",
193 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_sz : %d\n",
195 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_per_msg : %d\n",
196 ep_dist
->cred_per_msg
);
197 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_to_dist : %d\n",
198 ep_dist
->cred_to_dist
);
199 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " txq_depth : %d\n",
200 get_queue_depth(&ep_dist
->htc_ep
->txq
));
201 ath6kl_dbg(ATH6KL_DBG_CREDIT
,
202 "----------------------------------\n");
205 /* FIXME: move to htc.c */
206 void dump_cred_dist_stats(struct htc_target
*target
)
208 struct htc_endpoint_credit_dist
*ep_list
;
210 list_for_each_entry(ep_list
, &target
->cred_dist_list
, list
)
211 dump_cred_dist(ep_list
);
213 ath6kl_dbg(ATH6KL_DBG_CREDIT
,
214 "credit distribution total %d free %d\n",
215 target
->credit_info
->total_avail_credits
,
216 target
->credit_info
->cur_free_credits
);
219 static int ath6kl_debugfs_open(struct inode
*inode
, struct file
*file
)
221 file
->private_data
= inode
->i_private
;
225 void ath6kl_debug_war(struct ath6kl
*ar
, enum ath6kl_war war
)
228 case ATH6KL_WAR_INVALID_RATE
:
229 ar
->debug
.war_stats
.invalid_rate
++;
234 static ssize_t
read_file_war_stats(struct file
*file
, char __user
*user_buf
,
235 size_t count
, loff_t
*ppos
)
237 struct ath6kl
*ar
= file
->private_data
;
239 unsigned int len
= 0, buf_len
= 1500;
242 buf
= kzalloc(buf_len
, GFP_KERNEL
);
246 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
247 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
249 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n\n",
250 "=================");
251 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10u\n",
252 "Invalid rates", ar
->debug
.war_stats
.invalid_rate
);
254 if (WARN_ON(len
> buf_len
))
257 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
263 static const struct file_operations fops_war_stats
= {
264 .read
= read_file_war_stats
,
265 .open
= ath6kl_debugfs_open
,
266 .owner
= THIS_MODULE
,
267 .llseek
= default_llseek
,
270 void ath6kl_debug_fwlog_event(struct ath6kl
*ar
, const void *buf
, size_t len
)
272 struct ath6kl_fwlog_slot
*slot
;
276 if (WARN_ON(len
> ATH6KL_FWLOG_PAYLOAD_SIZE
))
279 slot_len
= sizeof(*slot
) + len
;
281 skb
= alloc_skb(slot_len
, GFP_KERNEL
);
285 slot
= (struct ath6kl_fwlog_slot
*) skb_put(skb
, slot_len
);
286 slot
->timestamp
= cpu_to_le32(jiffies
);
287 slot
->length
= cpu_to_le32(len
);
288 memcpy(slot
->payload
, buf
, len
);
290 spin_lock(&ar
->debug
.fwlog_queue
.lock
);
292 __skb_queue_tail(&ar
->debug
.fwlog_queue
, skb
);
293 complete(&ar
->debug
.fwlog_completion
);
295 /* drop oldest entries */
296 while (skb_queue_len(&ar
->debug
.fwlog_queue
) >
297 ATH6KL_FWLOG_MAX_ENTRIES
) {
298 skb
= __skb_dequeue(&ar
->debug
.fwlog_queue
);
302 spin_unlock(&ar
->debug
.fwlog_queue
.lock
);
307 static int ath6kl_fwlog_open(struct inode
*inode
, struct file
*file
)
309 struct ath6kl
*ar
= inode
->i_private
;
311 if (ar
->debug
.fwlog_open
)
314 ar
->debug
.fwlog_open
= true;
316 file
->private_data
= inode
->i_private
;
320 static int ath6kl_fwlog_release(struct inode
*inode
, struct file
*file
)
322 struct ath6kl
*ar
= inode
->i_private
;
324 ar
->debug
.fwlog_open
= false;
329 static ssize_t
ath6kl_fwlog_read(struct file
*file
, char __user
*user_buf
,
330 size_t count
, loff_t
*ppos
)
332 struct ath6kl
*ar
= file
->private_data
;
338 buf
= vmalloc(count
);
342 /* read undelivered logs from firmware */
343 ath6kl_read_fwlogs(ar
);
345 spin_lock(&ar
->debug
.fwlog_queue
.lock
);
347 while ((skb
= __skb_dequeue(&ar
->debug
.fwlog_queue
))) {
348 if (skb
->len
> count
- len
) {
349 /* not enough space, put skb back and leave */
350 __skb_queue_head(&ar
->debug
.fwlog_queue
, skb
);
355 memcpy(buf
+ len
, skb
->data
, skb
->len
);
361 spin_unlock(&ar
->debug
.fwlog_queue
.lock
);
363 /* FIXME: what to do if len == 0? */
365 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
372 static const struct file_operations fops_fwlog
= {
373 .open
= ath6kl_fwlog_open
,
374 .release
= ath6kl_fwlog_release
,
375 .read
= ath6kl_fwlog_read
,
376 .owner
= THIS_MODULE
,
377 .llseek
= default_llseek
,
380 static ssize_t
ath6kl_fwlog_block_read(struct file
*file
,
381 char __user
*user_buf
,
385 struct ath6kl
*ar
= file
->private_data
;
388 size_t len
= 0, not_copied
;
392 buf
= vmalloc(count
);
396 spin_lock(&ar
->debug
.fwlog_queue
.lock
);
398 if (skb_queue_len(&ar
->debug
.fwlog_queue
) == 0) {
399 /* we must init under queue lock */
400 init_completion(&ar
->debug
.fwlog_completion
);
402 spin_unlock(&ar
->debug
.fwlog_queue
.lock
);
404 ret
= wait_for_completion_interruptible(
405 &ar
->debug
.fwlog_completion
);
406 if (ret
== -ERESTARTSYS
)
409 spin_lock(&ar
->debug
.fwlog_queue
.lock
);
412 while ((skb
= __skb_dequeue(&ar
->debug
.fwlog_queue
))) {
413 if (skb
->len
> count
- len
) {
414 /* not enough space, put skb back and leave */
415 __skb_queue_head(&ar
->debug
.fwlog_queue
, skb
);
420 memcpy(buf
+ len
, skb
->data
, skb
->len
);
426 spin_unlock(&ar
->debug
.fwlog_queue
.lock
);
428 /* FIXME: what to do if len == 0? */
430 not_copied
= copy_to_user(user_buf
, buf
, len
);
431 if (not_copied
!= 0) {
446 static const struct file_operations fops_fwlog_block
= {
447 .open
= ath6kl_fwlog_open
,
448 .release
= ath6kl_fwlog_release
,
449 .read
= ath6kl_fwlog_block_read
,
450 .owner
= THIS_MODULE
,
451 .llseek
= default_llseek
,
454 static ssize_t
ath6kl_fwlog_mask_read(struct file
*file
, char __user
*user_buf
,
455 size_t count
, loff_t
*ppos
)
457 struct ath6kl
*ar
= file
->private_data
;
461 len
= snprintf(buf
, sizeof(buf
), "0x%x\n", ar
->debug
.fwlog_mask
);
463 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
466 static ssize_t
ath6kl_fwlog_mask_write(struct file
*file
,
467 const char __user
*user_buf
,
468 size_t count
, loff_t
*ppos
)
470 struct ath6kl
*ar
= file
->private_data
;
473 ret
= kstrtou32_from_user(user_buf
, count
, 0, &ar
->debug
.fwlog_mask
);
477 ret
= ath6kl_wmi_config_debug_module_cmd(ar
->wmi
,
478 ATH6KL_FWLOG_VALID_MASK
,
479 ar
->debug
.fwlog_mask
);
486 static const struct file_operations fops_fwlog_mask
= {
487 .open
= ath6kl_debugfs_open
,
488 .read
= ath6kl_fwlog_mask_read
,
489 .write
= ath6kl_fwlog_mask_write
,
490 .owner
= THIS_MODULE
,
491 .llseek
= default_llseek
,
494 static ssize_t
read_file_tgt_stats(struct file
*file
, char __user
*user_buf
,
495 size_t count
, loff_t
*ppos
)
497 struct ath6kl
*ar
= file
->private_data
;
498 struct ath6kl_vif
*vif
;
499 struct target_stats
*tgt_stats
;
501 unsigned int len
= 0, buf_len
= 1500;
506 vif
= ath6kl_vif_first(ar
);
510 tgt_stats
= &vif
->target_stats
;
512 buf
= kzalloc(buf_len
, GFP_KERNEL
);
516 if (down_interruptible(&ar
->sem
)) {
521 set_bit(STATS_UPDATE_PEND
, &vif
->flags
);
523 if (ath6kl_wmi_get_stats_cmd(ar
->wmi
, 0)) {
529 left
= wait_event_interruptible_timeout(ar
->event_wq
,
530 !test_bit(STATS_UPDATE_PEND
,
531 &vif
->flags
), WMI_TIMEOUT
);
540 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
541 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
543 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n\n",
544 "=================");
545 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
546 "Ucast packets", tgt_stats
->tx_ucast_pkt
);
547 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
548 "Bcast packets", tgt_stats
->tx_bcast_pkt
);
549 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
550 "Ucast byte", tgt_stats
->tx_ucast_byte
);
551 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
552 "Bcast byte", tgt_stats
->tx_bcast_byte
);
553 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
554 "Rts success cnt", tgt_stats
->tx_rts_success_cnt
);
555 for (i
= 0; i
< 4; i
++)
556 len
+= scnprintf(buf
+ len
, buf_len
- len
,
557 "%18s %d %10llu\n", "PER on ac",
558 i
, tgt_stats
->tx_pkt_per_ac
[i
]);
559 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
560 "Error", tgt_stats
->tx_err
);
561 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
562 "Fail count", tgt_stats
->tx_fail_cnt
);
563 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
564 "Retry count", tgt_stats
->tx_retry_cnt
);
565 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
566 "Multi retry cnt", tgt_stats
->tx_mult_retry_cnt
);
567 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
568 "Rts fail cnt", tgt_stats
->tx_rts_fail_cnt
);
569 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s %10llu\n\n",
570 "TKIP counter measure used",
571 tgt_stats
->tkip_cnter_measures_invoked
);
573 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
575 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
576 "=================");
578 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
579 "Ucast packets", tgt_stats
->rx_ucast_pkt
);
580 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
581 "Ucast Rate", tgt_stats
->rx_ucast_rate
);
582 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
583 "Bcast packets", tgt_stats
->rx_bcast_pkt
);
584 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
585 "Ucast byte", tgt_stats
->rx_ucast_byte
);
586 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
587 "Bcast byte", tgt_stats
->rx_bcast_byte
);
588 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
589 "Fragmented pkt", tgt_stats
->rx_frgment_pkt
);
590 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
591 "Error", tgt_stats
->rx_err
);
592 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
593 "CRC Err", tgt_stats
->rx_crc_err
);
594 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
595 "Key chache miss", tgt_stats
->rx_key_cache_miss
);
596 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
597 "Decrypt Err", tgt_stats
->rx_decrypt_err
);
598 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
599 "Duplicate frame", tgt_stats
->rx_dupl_frame
);
600 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
601 "Tkip Mic failure", tgt_stats
->tkip_local_mic_fail
);
602 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
603 "TKIP format err", tgt_stats
->tkip_fmt_err
);
604 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
605 "CCMP format Err", tgt_stats
->ccmp_fmt_err
);
606 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n\n",
607 "CCMP Replay Err", tgt_stats
->ccmp_replays
);
609 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
610 "Misc Target stats");
611 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
612 "=================");
613 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
614 "Beacon Miss count", tgt_stats
->cs_bmiss_cnt
);
615 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
616 "Num Connects", tgt_stats
->cs_connect_cnt
);
617 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
618 "Num disconnects", tgt_stats
->cs_discon_cnt
);
619 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
620 "Beacon avg rssi", tgt_stats
->cs_ave_beacon_rssi
);
625 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
631 static const struct file_operations fops_tgt_stats
= {
632 .read
= read_file_tgt_stats
,
633 .open
= ath6kl_debugfs_open
,
634 .owner
= THIS_MODULE
,
635 .llseek
= default_llseek
,
638 #define print_credit_info(fmt_str, ep_list_field) \
639 (len += scnprintf(buf + len, buf_len - len, fmt_str, \
640 ep_list->ep_list_field))
641 #define CREDIT_INFO_DISPLAY_STRING_LEN 200
642 #define CREDIT_INFO_LEN 128
644 static ssize_t
read_file_credit_dist_stats(struct file
*file
,
645 char __user
*user_buf
,
646 size_t count
, loff_t
*ppos
)
648 struct ath6kl
*ar
= file
->private_data
;
649 struct htc_target
*target
= ar
->htc_target
;
650 struct htc_endpoint_credit_dist
*ep_list
;
652 unsigned int buf_len
, len
= 0;
655 buf_len
= CREDIT_INFO_DISPLAY_STRING_LEN
+
656 get_queue_depth(&target
->cred_dist_list
) * CREDIT_INFO_LEN
;
657 buf
= kzalloc(buf_len
, GFP_KERNEL
);
661 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s%5d\n",
662 "Total Avail Credits: ",
663 target
->credit_info
->total_avail_credits
);
664 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s%5d\n",
666 target
->credit_info
->cur_free_credits
);
668 len
+= scnprintf(buf
+ len
, buf_len
- len
,
669 " Epid Flags Cred_norm Cred_min Credits Cred_assngd"
670 " Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
673 list_for_each_entry(ep_list
, &target
->cred_dist_list
, list
) {
674 print_credit_info(" %2d", endpoint
);
675 print_credit_info("%10x", dist_flags
);
676 print_credit_info("%8d", cred_norm
);
677 print_credit_info("%9d", cred_min
);
678 print_credit_info("%9d", credits
);
679 print_credit_info("%10d", cred_assngd
);
680 print_credit_info("%13d", seek_cred
);
681 print_credit_info("%12d", cred_sz
);
682 print_credit_info("%9d", cred_per_msg
);
683 print_credit_info("%14d", cred_to_dist
);
684 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%12d\n",
685 get_queue_depth(&ep_list
->htc_ep
->txq
));
691 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
696 static const struct file_operations fops_credit_dist_stats
= {
697 .read
= read_file_credit_dist_stats
,
698 .open
= ath6kl_debugfs_open
,
699 .owner
= THIS_MODULE
,
700 .llseek
= default_llseek
,
703 static unsigned int print_endpoint_stat(struct htc_target
*target
, char *buf
,
704 unsigned int buf_len
, unsigned int len
,
705 int offset
, const char *name
)
708 struct htc_endpoint_stats
*ep_st
;
711 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%s:", name
);
712 for (i
= 0; i
< ENDPOINT_MAX
; i
++) {
713 ep_st
= &target
->endpoint
[i
].ep_st
;
714 counter
= ((u32
*) ep_st
) + (offset
/ 4);
715 len
+= scnprintf(buf
+ len
, buf_len
- len
, " %u", *counter
);
717 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
722 static ssize_t
ath6kl_endpoint_stats_read(struct file
*file
,
723 char __user
*user_buf
,
724 size_t count
, loff_t
*ppos
)
726 struct ath6kl
*ar
= file
->private_data
;
727 struct htc_target
*target
= ar
->htc_target
;
729 unsigned int buf_len
, len
= 0;
732 buf_len
= sizeof(struct htc_endpoint_stats
) / sizeof(u32
) *
733 (25 + ENDPOINT_MAX
* 11);
734 buf
= kmalloc(buf_len
, GFP_KERNEL
);
738 #define EPSTAT(name) \
739 len = print_endpoint_stat(target, buf, buf_len, len, \
740 offsetof(struct htc_endpoint_stats, name), \
742 EPSTAT(cred_low_indicate
);
744 EPSTAT(tx_pkt_bundled
);
748 EPSTAT(cred_rpt_from_rx
);
749 EPSTAT(cred_rpt_from_other
);
750 EPSTAT(cred_rpt_ep0
);
751 EPSTAT(cred_from_rx
);
752 EPSTAT(cred_from_other
);
753 EPSTAT(cred_from_ep0
);
759 EPSTAT(rx_bundle_lkahd
);
760 EPSTAT(rx_bundle_from_hdr
);
761 EPSTAT(rx_alloc_thresh_hit
);
762 EPSTAT(rxalloc_thresh_byte
);
768 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
773 static ssize_t
ath6kl_endpoint_stats_write(struct file
*file
,
774 const char __user
*user_buf
,
775 size_t count
, loff_t
*ppos
)
777 struct ath6kl
*ar
= file
->private_data
;
778 struct htc_target
*target
= ar
->htc_target
;
781 struct htc_endpoint_stats
*ep_st
;
783 ret
= kstrtou32_from_user(user_buf
, count
, 0, &val
);
787 for (i
= 0; i
< ENDPOINT_MAX
; i
++) {
788 ep_st
= &target
->endpoint
[i
].ep_st
;
789 memset(ep_st
, 0, sizeof(*ep_st
));
796 static const struct file_operations fops_endpoint_stats
= {
797 .open
= ath6kl_debugfs_open
,
798 .read
= ath6kl_endpoint_stats_read
,
799 .write
= ath6kl_endpoint_stats_write
,
800 .owner
= THIS_MODULE
,
801 .llseek
= default_llseek
,
804 static unsigned long ath6kl_get_num_reg(void)
807 unsigned long n_reg
= 0;
809 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++)
811 (diag_reg
[i
].reg_end
- diag_reg
[i
].reg_start
) / 4 + 1;
816 static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr
)
820 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++) {
821 if (reg_addr
>= diag_reg
[i
].reg_start
&&
822 reg_addr
<= diag_reg
[i
].reg_end
)
829 static ssize_t
ath6kl_regread_read(struct file
*file
, char __user
*user_buf
,
830 size_t count
, loff_t
*ppos
)
832 struct ath6kl
*ar
= file
->private_data
;
834 unsigned int len
= 0;
836 if (ar
->debug
.dbgfs_diag_reg
)
837 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "0x%x\n",
838 ar
->debug
.dbgfs_diag_reg
);
840 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
841 "All diag registers\n");
843 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
846 static ssize_t
ath6kl_regread_write(struct file
*file
,
847 const char __user
*user_buf
,
848 size_t count
, loff_t
*ppos
)
850 struct ath6kl
*ar
= file
->private_data
;
853 unsigned long reg_addr
;
855 len
= min(count
, sizeof(buf
) - 1);
856 if (copy_from_user(buf
, user_buf
, len
))
861 if (strict_strtoul(buf
, 0, ®_addr
))
864 if ((reg_addr
% 4) != 0)
867 if (reg_addr
&& !ath6kl_dbg_is_diag_reg_valid(reg_addr
))
870 ar
->debug
.dbgfs_diag_reg
= reg_addr
;
875 static const struct file_operations fops_diag_reg_read
= {
876 .read
= ath6kl_regread_read
,
877 .write
= ath6kl_regread_write
,
878 .open
= ath6kl_debugfs_open
,
879 .owner
= THIS_MODULE
,
880 .llseek
= default_llseek
,
883 static int ath6kl_regdump_open(struct inode
*inode
, struct file
*file
)
885 struct ath6kl
*ar
= inode
->i_private
;
887 unsigned long int reg_len
;
888 unsigned int len
= 0, n_reg
;
893 /* Dump all the registers if no register is specified */
894 if (!ar
->debug
.dbgfs_diag_reg
)
895 n_reg
= ath6kl_get_num_reg();
899 reg_len
= n_reg
* REG_OUTPUT_LEN_PER_LINE
;
901 reg_len
+= REGTYPE_STR_LEN
;
903 buf
= vmalloc(reg_len
);
908 addr
= ar
->debug
.dbgfs_diag_reg
;
910 status
= ath6kl_diag_read32(ar
,
911 TARG_VTOP(ar
->target_type
, addr
),
916 len
+= scnprintf(buf
+ len
, reg_len
- len
,
917 "0x%06x 0x%08x\n", addr
, le32_to_cpu(reg_val
));
921 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++) {
922 len
+= scnprintf(buf
+ len
, reg_len
- len
,
923 "%s\n", diag_reg
[i
].reg_info
);
924 for (addr
= diag_reg
[i
].reg_start
;
925 addr
<= diag_reg
[i
].reg_end
; addr
+= 4) {
926 status
= ath6kl_diag_read32(ar
,
927 TARG_VTOP(ar
->target_type
, addr
),
932 len
+= scnprintf(buf
+ len
, reg_len
- len
,
934 addr
, le32_to_cpu(reg_val
));
939 file
->private_data
= buf
;
943 ath6kl_warn("Unable to read memory:%u\n", addr
);
948 static ssize_t
ath6kl_regdump_read(struct file
*file
, char __user
*user_buf
,
949 size_t count
, loff_t
*ppos
)
951 u8
*buf
= file
->private_data
;
952 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, strlen(buf
));
955 static int ath6kl_regdump_release(struct inode
*inode
, struct file
*file
)
957 vfree(file
->private_data
);
961 static const struct file_operations fops_reg_dump
= {
962 .open
= ath6kl_regdump_open
,
963 .read
= ath6kl_regdump_read
,
964 .release
= ath6kl_regdump_release
,
965 .owner
= THIS_MODULE
,
966 .llseek
= default_llseek
,
969 static ssize_t
ath6kl_lrssi_roam_write(struct file
*file
,
970 const char __user
*user_buf
,
971 size_t count
, loff_t
*ppos
)
973 struct ath6kl
*ar
= file
->private_data
;
974 unsigned long lrssi_roam_threshold
;
978 len
= min(count
, sizeof(buf
) - 1);
979 if (copy_from_user(buf
, user_buf
, len
))
983 if (strict_strtoul(buf
, 0, &lrssi_roam_threshold
))
986 ar
->lrssi_roam_threshold
= lrssi_roam_threshold
;
988 ath6kl_wmi_set_roam_lrssi_cmd(ar
->wmi
, ar
->lrssi_roam_threshold
);
993 static ssize_t
ath6kl_lrssi_roam_read(struct file
*file
,
994 char __user
*user_buf
,
995 size_t count
, loff_t
*ppos
)
997 struct ath6kl
*ar
= file
->private_data
;
1001 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->lrssi_roam_threshold
);
1003 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1006 static const struct file_operations fops_lrssi_roam_threshold
= {
1007 .read
= ath6kl_lrssi_roam_read
,
1008 .write
= ath6kl_lrssi_roam_write
,
1009 .open
= ath6kl_debugfs_open
,
1010 .owner
= THIS_MODULE
,
1011 .llseek
= default_llseek
,
1014 static ssize_t
ath6kl_regwrite_read(struct file
*file
,
1015 char __user
*user_buf
,
1016 size_t count
, loff_t
*ppos
)
1018 struct ath6kl
*ar
= file
->private_data
;
1020 unsigned int len
= 0;
1022 len
= scnprintf(buf
, sizeof(buf
), "Addr: 0x%x Val: 0x%x\n",
1023 ar
->debug
.diag_reg_addr_wr
, ar
->debug
.diag_reg_val_wr
);
1025 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1028 static ssize_t
ath6kl_regwrite_write(struct file
*file
,
1029 const char __user
*user_buf
,
1030 size_t count
, loff_t
*ppos
)
1032 struct ath6kl
*ar
= file
->private_data
;
1035 unsigned int len
= 0;
1036 u32 reg_addr
, reg_val
;
1038 len
= min(count
, sizeof(buf
) - 1);
1039 if (copy_from_user(buf
, user_buf
, len
))
1045 token
= strsep(&sptr
, "=");
1049 if (kstrtou32(token
, 0, ®_addr
))
1052 if (!ath6kl_dbg_is_diag_reg_valid(reg_addr
))
1055 if (kstrtou32(sptr
, 0, ®_val
))
1058 ar
->debug
.diag_reg_addr_wr
= reg_addr
;
1059 ar
->debug
.diag_reg_val_wr
= reg_val
;
1061 if (ath6kl_diag_write32(ar
, ar
->debug
.diag_reg_addr_wr
,
1062 cpu_to_le32(ar
->debug
.diag_reg_val_wr
)))
1068 static const struct file_operations fops_diag_reg_write
= {
1069 .read
= ath6kl_regwrite_read
,
1070 .write
= ath6kl_regwrite_write
,
1071 .open
= ath6kl_debugfs_open
,
1072 .owner
= THIS_MODULE
,
1073 .llseek
= default_llseek
,
1076 int ath6kl_debug_roam_tbl_event(struct ath6kl
*ar
, const void *buf
,
1079 const struct wmi_target_roam_tbl
*tbl
;
1082 if (len
< sizeof(*tbl
))
1085 tbl
= (const struct wmi_target_roam_tbl
*) buf
;
1086 num_entries
= le16_to_cpu(tbl
->num_entries
);
1087 if (sizeof(*tbl
) + num_entries
* sizeof(struct wmi_bss_roam_info
) >
1091 if (ar
->debug
.roam_tbl
== NULL
||
1092 ar
->debug
.roam_tbl_len
< (unsigned int) len
) {
1093 kfree(ar
->debug
.roam_tbl
);
1094 ar
->debug
.roam_tbl
= kmalloc(len
, GFP_ATOMIC
);
1095 if (ar
->debug
.roam_tbl
== NULL
)
1099 memcpy(ar
->debug
.roam_tbl
, buf
, len
);
1100 ar
->debug
.roam_tbl_len
= len
;
1102 if (test_bit(ROAM_TBL_PEND
, &ar
->flag
)) {
1103 clear_bit(ROAM_TBL_PEND
, &ar
->flag
);
1104 wake_up(&ar
->event_wq
);
1110 static ssize_t
ath6kl_roam_table_read(struct file
*file
, char __user
*user_buf
,
1111 size_t count
, loff_t
*ppos
)
1113 struct ath6kl
*ar
= file
->private_data
;
1116 struct wmi_target_roam_tbl
*tbl
;
1119 unsigned int len
, buf_len
;
1122 if (down_interruptible(&ar
->sem
))
1125 set_bit(ROAM_TBL_PEND
, &ar
->flag
);
1127 ret
= ath6kl_wmi_get_roam_tbl_cmd(ar
->wmi
);
1133 left
= wait_event_interruptible_timeout(
1134 ar
->event_wq
, !test_bit(ROAM_TBL_PEND
, &ar
->flag
), WMI_TIMEOUT
);
1140 if (ar
->debug
.roam_tbl
== NULL
)
1143 tbl
= (struct wmi_target_roam_tbl
*) ar
->debug
.roam_tbl
;
1144 num_entries
= le16_to_cpu(tbl
->num_entries
);
1146 buf_len
= 100 + num_entries
* 100;
1147 buf
= kzalloc(buf_len
, GFP_KERNEL
);
1151 len
+= scnprintf(buf
+ len
, buf_len
- len
,
1153 "# roam_util bssid rssi rssidt last_rssi util bias\n",
1154 le16_to_cpu(tbl
->roam_mode
));
1156 for (i
= 0; i
< num_entries
; i
++) {
1157 struct wmi_bss_roam_info
*info
= &tbl
->info
[i
];
1158 len
+= scnprintf(buf
+ len
, buf_len
- len
,
1159 "%d %pM %d %d %d %d %d\n",
1160 a_sle32_to_cpu(info
->roam_util
), info
->bssid
,
1161 info
->rssi
, info
->rssidt
, info
->last_rssi
,
1162 info
->util
, info
->bias
);
1168 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1174 static const struct file_operations fops_roam_table
= {
1175 .read
= ath6kl_roam_table_read
,
1176 .open
= ath6kl_debugfs_open
,
1177 .owner
= THIS_MODULE
,
1178 .llseek
= default_llseek
,
1181 static ssize_t
ath6kl_force_roam_write(struct file
*file
,
1182 const char __user
*user_buf
,
1183 size_t count
, loff_t
*ppos
)
1185 struct ath6kl
*ar
= file
->private_data
;
1193 len
= min(count
, sizeof(buf
) - 1);
1194 if (copy_from_user(buf
, user_buf
, len
))
1198 if (sscanf(buf
, "%02x:%02x:%02x:%02x:%02x:%02x",
1199 &addr
[0], &addr
[1], &addr
[2], &addr
[3], &addr
[4], &addr
[5])
1202 for (i
= 0; i
< ETH_ALEN
; i
++)
1205 ret
= ath6kl_wmi_force_roam_cmd(ar
->wmi
, bssid
);
1212 static const struct file_operations fops_force_roam
= {
1213 .write
= ath6kl_force_roam_write
,
1214 .open
= ath6kl_debugfs_open
,
1215 .owner
= THIS_MODULE
,
1216 .llseek
= default_llseek
,
1219 static ssize_t
ath6kl_roam_mode_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 enum wmi_roam_mode mode
;
1229 len
= min(count
, sizeof(buf
) - 1);
1230 if (copy_from_user(buf
, user_buf
, len
))
1233 if (len
> 0 && buf
[len
- 1] == '\n')
1234 buf
[len
- 1] = '\0';
1236 if (strcasecmp(buf
, "default") == 0)
1237 mode
= WMI_DEFAULT_ROAM_MODE
;
1238 else if (strcasecmp(buf
, "bssbias") == 0)
1239 mode
= WMI_HOST_BIAS_ROAM_MODE
;
1240 else if (strcasecmp(buf
, "lock") == 0)
1241 mode
= WMI_LOCK_BSS_MODE
;
1245 ret
= ath6kl_wmi_set_roam_mode_cmd(ar
->wmi
, mode
);
1252 static const struct file_operations fops_roam_mode
= {
1253 .write
= ath6kl_roam_mode_write
,
1254 .open
= ath6kl_debugfs_open
,
1255 .owner
= THIS_MODULE
,
1256 .llseek
= default_llseek
,
1259 void ath6kl_debug_set_keepalive(struct ath6kl
*ar
, u8 keepalive
)
1261 ar
->debug
.keepalive
= keepalive
;
1264 static ssize_t
ath6kl_keepalive_read(struct file
*file
, char __user
*user_buf
,
1265 size_t count
, loff_t
*ppos
)
1267 struct ath6kl
*ar
= file
->private_data
;
1271 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->debug
.keepalive
);
1273 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1276 static ssize_t
ath6kl_keepalive_write(struct file
*file
,
1277 const char __user
*user_buf
,
1278 size_t count
, loff_t
*ppos
)
1280 struct ath6kl
*ar
= file
->private_data
;
1284 ret
= kstrtou8_from_user(user_buf
, count
, 0, &val
);
1288 ret
= ath6kl_wmi_set_keepalive_cmd(ar
->wmi
, 0, val
);
1295 static const struct file_operations fops_keepalive
= {
1296 .open
= ath6kl_debugfs_open
,
1297 .read
= ath6kl_keepalive_read
,
1298 .write
= ath6kl_keepalive_write
,
1299 .owner
= THIS_MODULE
,
1300 .llseek
= default_llseek
,
1303 void ath6kl_debug_set_disconnect_timeout(struct ath6kl
*ar
, u8 timeout
)
1305 ar
->debug
.disc_timeout
= timeout
;
1308 static ssize_t
ath6kl_disconnect_timeout_read(struct file
*file
,
1309 char __user
*user_buf
,
1310 size_t count
, loff_t
*ppos
)
1312 struct ath6kl
*ar
= file
->private_data
;
1316 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->debug
.disc_timeout
);
1318 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1321 static ssize_t
ath6kl_disconnect_timeout_write(struct file
*file
,
1322 const char __user
*user_buf
,
1323 size_t count
, loff_t
*ppos
)
1325 struct ath6kl
*ar
= file
->private_data
;
1329 ret
= kstrtou8_from_user(user_buf
, count
, 0, &val
);
1333 ret
= ath6kl_wmi_disctimeout_cmd(ar
->wmi
, 0, val
);
1340 static const struct file_operations fops_disconnect_timeout
= {
1341 .open
= ath6kl_debugfs_open
,
1342 .read
= ath6kl_disconnect_timeout_read
,
1343 .write
= ath6kl_disconnect_timeout_write
,
1344 .owner
= THIS_MODULE
,
1345 .llseek
= default_llseek
,
1348 static ssize_t
ath6kl_create_qos_write(struct file
*file
,
1349 const char __user
*user_buf
,
1350 size_t count
, loff_t
*ppos
)
1353 struct ath6kl
*ar
= file
->private_data
;
1354 struct ath6kl_vif
*vif
;
1358 struct wmi_create_pstream_cmd pstream
;
1362 vif
= ath6kl_vif_first(ar
);
1366 len
= min(count
, sizeof(buf
) - 1);
1367 if (copy_from_user(buf
, user_buf
, len
))
1372 token
= strsep(&sptr
, " ");
1375 if (kstrtou8(token
, 0, &pstream
.user_pri
))
1378 token
= strsep(&sptr
, " ");
1381 if (kstrtou8(token
, 0, &pstream
.traffic_direc
))
1384 token
= strsep(&sptr
, " ");
1387 if (kstrtou8(token
, 0, &pstream
.traffic_class
))
1390 token
= strsep(&sptr
, " ");
1393 if (kstrtou8(token
, 0, &pstream
.traffic_type
))
1396 token
= strsep(&sptr
, " ");
1399 if (kstrtou8(token
, 0, &pstream
.voice_psc_cap
))
1402 token
= strsep(&sptr
, " ");
1405 if (kstrtou32(token
, 0, &val32
))
1407 pstream
.min_service_int
= cpu_to_le32(val32
);
1409 token
= strsep(&sptr
, " ");
1412 if (kstrtou32(token
, 0, &val32
))
1414 pstream
.max_service_int
= cpu_to_le32(val32
);
1416 token
= strsep(&sptr
, " ");
1419 if (kstrtou32(token
, 0, &val32
))
1421 pstream
.inactivity_int
= cpu_to_le32(val32
);
1423 token
= strsep(&sptr
, " ");
1426 if (kstrtou32(token
, 0, &val32
))
1428 pstream
.suspension_int
= cpu_to_le32(val32
);
1430 token
= strsep(&sptr
, " ");
1433 if (kstrtou32(token
, 0, &val32
))
1435 pstream
.service_start_time
= cpu_to_le32(val32
);
1437 token
= strsep(&sptr
, " ");
1440 if (kstrtou8(token
, 0, &pstream
.tsid
))
1443 token
= strsep(&sptr
, " ");
1446 if (kstrtou16(token
, 0, &val16
))
1448 pstream
.nominal_msdu
= cpu_to_le16(val16
);
1450 token
= strsep(&sptr
, " ");
1453 if (kstrtou16(token
, 0, &val16
))
1455 pstream
.max_msdu
= cpu_to_le16(val16
);
1457 token
= strsep(&sptr
, " ");
1460 if (kstrtou32(token
, 0, &val32
))
1462 pstream
.min_data_rate
= cpu_to_le32(val32
);
1464 token
= strsep(&sptr
, " ");
1467 if (kstrtou32(token
, 0, &val32
))
1469 pstream
.mean_data_rate
= cpu_to_le32(val32
);
1471 token
= strsep(&sptr
, " ");
1474 if (kstrtou32(token
, 0, &val32
))
1476 pstream
.peak_data_rate
= cpu_to_le32(val32
);
1478 token
= strsep(&sptr
, " ");
1481 if (kstrtou32(token
, 0, &val32
))
1483 pstream
.max_burst_size
= cpu_to_le32(val32
);
1485 token
= strsep(&sptr
, " ");
1488 if (kstrtou32(token
, 0, &val32
))
1490 pstream
.delay_bound
= cpu_to_le32(val32
);
1492 token
= strsep(&sptr
, " ");
1495 if (kstrtou32(token
, 0, &val32
))
1497 pstream
.min_phy_rate
= cpu_to_le32(val32
);
1499 token
= strsep(&sptr
, " ");
1502 if (kstrtou32(token
, 0, &val32
))
1504 pstream
.sba
= cpu_to_le32(val32
);
1506 token
= strsep(&sptr
, " ");
1509 if (kstrtou32(token
, 0, &val32
))
1511 pstream
.medium_time
= cpu_to_le32(val32
);
1513 pstream
.nominal_phy
= le32_to_cpu(pstream
.min_phy_rate
) / 1000000;
1515 ath6kl_wmi_create_pstream_cmd(ar
->wmi
, vif
->fw_vif_idx
, &pstream
);
1520 static const struct file_operations fops_create_qos
= {
1521 .write
= ath6kl_create_qos_write
,
1522 .open
= ath6kl_debugfs_open
,
1523 .owner
= THIS_MODULE
,
1524 .llseek
= default_llseek
,
1527 static ssize_t
ath6kl_delete_qos_write(struct file
*file
,
1528 const char __user
*user_buf
,
1529 size_t count
, loff_t
*ppos
)
1532 struct ath6kl
*ar
= file
->private_data
;
1533 struct ath6kl_vif
*vif
;
1540 vif
= ath6kl_vif_first(ar
);
1544 len
= min(count
, sizeof(buf
) - 1);
1545 if (copy_from_user(buf
, user_buf
, len
))
1550 token
= strsep(&sptr
, " ");
1553 if (kstrtou8(token
, 0, &traffic_class
))
1556 token
= strsep(&sptr
, " ");
1559 if (kstrtou8(token
, 0, &tsid
))
1562 ath6kl_wmi_delete_pstream_cmd(ar
->wmi
, vif
->fw_vif_idx
,
1563 traffic_class
, tsid
);
1568 static const struct file_operations fops_delete_qos
= {
1569 .write
= ath6kl_delete_qos_write
,
1570 .open
= ath6kl_debugfs_open
,
1571 .owner
= THIS_MODULE
,
1572 .llseek
= default_llseek
,
1575 static ssize_t
ath6kl_bgscan_int_write(struct file
*file
,
1576 const char __user
*user_buf
,
1577 size_t count
, loff_t
*ppos
)
1579 struct ath6kl
*ar
= file
->private_data
;
1584 len
= min(count
, sizeof(buf
) - 1);
1585 if (copy_from_user(buf
, user_buf
, len
))
1589 if (kstrtou16(buf
, 0, &bgscan_int
))
1592 if (bgscan_int
== 0)
1593 bgscan_int
= 0xffff;
1595 ath6kl_wmi_scanparams_cmd(ar
->wmi
, 0, 0, 0, bgscan_int
, 0, 0, 0, 3,
1601 static const struct file_operations fops_bgscan_int
= {
1602 .write
= ath6kl_bgscan_int_write
,
1603 .open
= ath6kl_debugfs_open
,
1604 .owner
= THIS_MODULE
,
1605 .llseek
= default_llseek
,
1608 static ssize_t
ath6kl_listen_int_write(struct file
*file
,
1609 const char __user
*user_buf
,
1610 size_t count
, loff_t
*ppos
)
1612 struct ath6kl
*ar
= file
->private_data
;
1613 struct ath6kl_vif
*vif
;
1614 u16 listen_interval
;
1618 vif
= ath6kl_vif_first(ar
);
1622 len
= min(count
, sizeof(buf
) - 1);
1623 if (copy_from_user(buf
, user_buf
, len
))
1627 if (kstrtou16(buf
, 0, &listen_interval
))
1630 if ((listen_interval
< 1) || (listen_interval
> 50))
1633 ar
->listen_intvl_b
= listen_interval
;
1634 ath6kl_wmi_listeninterval_cmd(ar
->wmi
, vif
->fw_vif_idx
, 0,
1635 ar
->listen_intvl_b
);
1640 static ssize_t
ath6kl_listen_int_read(struct file
*file
,
1641 char __user
*user_buf
,
1642 size_t count
, loff_t
*ppos
)
1644 struct ath6kl
*ar
= file
->private_data
;
1648 len
= scnprintf(buf
, sizeof(buf
), "%u\n", ar
->listen_intvl_b
);
1650 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1653 static const struct file_operations fops_listen_int
= {
1654 .read
= ath6kl_listen_int_read
,
1655 .write
= ath6kl_listen_int_write
,
1656 .open
= ath6kl_debugfs_open
,
1657 .owner
= THIS_MODULE
,
1658 .llseek
= default_llseek
,
1661 static ssize_t
ath6kl_power_params_write(struct file
*file
,
1662 const char __user
*user_buf
,
1663 size_t count
, loff_t
*ppos
)
1665 struct ath6kl
*ar
= file
->private_data
;
1667 unsigned int len
= 0;
1669 u16 idle_period
, ps_poll_num
, dtim
,
1672 len
= min(count
, sizeof(buf
) - 1);
1673 if (copy_from_user(buf
, user_buf
, len
))
1678 token
= strsep(&sptr
, " ");
1681 if (kstrtou16(token
, 0, &idle_period
))
1684 token
= strsep(&sptr
, " ");
1687 if (kstrtou16(token
, 0, &ps_poll_num
))
1690 token
= strsep(&sptr
, " ");
1693 if (kstrtou16(token
, 0, &dtim
))
1696 token
= strsep(&sptr
, " ");
1699 if (kstrtou16(token
, 0, &tx_wakeup
))
1702 token
= strsep(&sptr
, " ");
1705 if (kstrtou16(token
, 0, &num_tx
))
1708 ath6kl_wmi_pmparams_cmd(ar
->wmi
, 0, idle_period
, ps_poll_num
,
1709 dtim
, tx_wakeup
, num_tx
, 0);
1714 static const struct file_operations fops_power_params
= {
1715 .write
= ath6kl_power_params_write
,
1716 .open
= ath6kl_debugfs_open
,
1717 .owner
= THIS_MODULE
,
1718 .llseek
= default_llseek
,
1721 int ath6kl_debug_init(struct ath6kl
*ar
)
1723 skb_queue_head_init(&ar
->debug
.fwlog_queue
);
1724 init_completion(&ar
->debug
.fwlog_completion
);
1727 * Actually we are lying here but don't know how to read the mask
1728 * value from the firmware.
1730 ar
->debug
.fwlog_mask
= 0;
1732 ar
->debugfs_phy
= debugfs_create_dir("ath6kl",
1733 ar
->wiphy
->debugfsdir
);
1734 if (!ar
->debugfs_phy
)
1737 debugfs_create_file("tgt_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1740 debugfs_create_file("credit_dist_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1741 &fops_credit_dist_stats
);
1743 debugfs_create_file("endpoint_stats", S_IRUSR
| S_IWUSR
,
1744 ar
->debugfs_phy
, ar
, &fops_endpoint_stats
);
1746 debugfs_create_file("fwlog", S_IRUSR
, ar
->debugfs_phy
, ar
,
1749 debugfs_create_file("fwlog_block", S_IRUSR
, ar
->debugfs_phy
, ar
,
1752 debugfs_create_file("fwlog_mask", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
,
1753 ar
, &fops_fwlog_mask
);
1755 debugfs_create_file("reg_addr", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
, ar
,
1756 &fops_diag_reg_read
);
1758 debugfs_create_file("reg_dump", S_IRUSR
, ar
->debugfs_phy
, ar
,
1761 debugfs_create_file("lrssi_roam_threshold", S_IRUSR
| S_IWUSR
,
1762 ar
->debugfs_phy
, ar
, &fops_lrssi_roam_threshold
);
1764 debugfs_create_file("reg_write", S_IRUSR
| S_IWUSR
,
1765 ar
->debugfs_phy
, ar
, &fops_diag_reg_write
);
1767 debugfs_create_file("war_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1770 debugfs_create_file("roam_table", S_IRUSR
, ar
->debugfs_phy
, ar
,
1773 debugfs_create_file("force_roam", S_IWUSR
, ar
->debugfs_phy
, ar
,
1776 debugfs_create_file("roam_mode", S_IWUSR
, ar
->debugfs_phy
, ar
,
1779 debugfs_create_file("keepalive", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
, ar
,
1782 debugfs_create_file("disconnect_timeout", S_IRUSR
| S_IWUSR
,
1783 ar
->debugfs_phy
, ar
, &fops_disconnect_timeout
);
1785 debugfs_create_file("create_qos", S_IWUSR
, ar
->debugfs_phy
, ar
,
1788 debugfs_create_file("delete_qos", S_IWUSR
, ar
->debugfs_phy
, ar
,
1791 debugfs_create_file("bgscan_interval", S_IWUSR
,
1792 ar
->debugfs_phy
, ar
, &fops_bgscan_int
);
1794 debugfs_create_file("listen_interval", S_IRUSR
| S_IWUSR
,
1795 ar
->debugfs_phy
, ar
, &fops_listen_int
);
1797 debugfs_create_file("power_params", S_IWUSR
, ar
->debugfs_phy
, ar
,
1798 &fops_power_params
);
1803 void ath6kl_debug_cleanup(struct ath6kl
*ar
)
1805 skb_queue_purge(&ar
->debug
.fwlog_queue
);
1806 kfree(ar
->debug
.roam_tbl
);