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
);
58 #ifdef CONFIG_ATH6KL_DEBUG
60 #define REG_OUTPUT_LEN_PER_LINE 25
61 #define REGTYPE_STR_LEN 100
63 struct ath6kl_diag_reg_info
{
69 static const struct ath6kl_diag_reg_info diag_reg
[] = {
70 { 0x20000, 0x200fc, "General DMA and Rx registers" },
71 { 0x28000, 0x28900, "MAC PCU register & keycache" },
72 { 0x20800, 0x20a40, "QCU" },
73 { 0x21000, 0x212f0, "DCU" },
74 { 0x4000, 0x42e4, "RTC" },
75 { 0x540000, 0x540000 + (256 * 1024), "RAM" },
76 { 0x29800, 0x2B210, "Base Band" },
77 { 0x1C000, 0x1C748, "Analog" },
80 void ath6kl_dump_registers(struct ath6kl_device
*dev
,
81 struct ath6kl_irq_proc_registers
*irq_proc_reg
,
82 struct ath6kl_irq_enable_reg
*irq_enable_reg
)
85 ath6kl_dbg(ATH6KL_DBG_ANY
, ("<------- Register Table -------->\n"));
87 if (irq_proc_reg
!= NULL
) {
88 ath6kl_dbg(ATH6KL_DBG_ANY
,
89 "Host Int status: 0x%x\n",
90 irq_proc_reg
->host_int_status
);
91 ath6kl_dbg(ATH6KL_DBG_ANY
,
92 "CPU Int status: 0x%x\n",
93 irq_proc_reg
->cpu_int_status
);
94 ath6kl_dbg(ATH6KL_DBG_ANY
,
95 "Error Int status: 0x%x\n",
96 irq_proc_reg
->error_int_status
);
97 ath6kl_dbg(ATH6KL_DBG_ANY
,
98 "Counter Int status: 0x%x\n",
99 irq_proc_reg
->counter_int_status
);
100 ath6kl_dbg(ATH6KL_DBG_ANY
,
101 "Mbox Frame: 0x%x\n",
102 irq_proc_reg
->mbox_frame
);
103 ath6kl_dbg(ATH6KL_DBG_ANY
,
104 "Rx Lookahead Valid: 0x%x\n",
105 irq_proc_reg
->rx_lkahd_valid
);
106 ath6kl_dbg(ATH6KL_DBG_ANY
,
107 "Rx Lookahead 0: 0x%x\n",
108 irq_proc_reg
->rx_lkahd
[0]);
109 ath6kl_dbg(ATH6KL_DBG_ANY
,
110 "Rx Lookahead 1: 0x%x\n",
111 irq_proc_reg
->rx_lkahd
[1]);
113 if (dev
->ar
->mbox_info
.gmbox_addr
!= 0) {
115 * If the target supports GMBOX hardware, dump some
118 ath6kl_dbg(ATH6KL_DBG_ANY
,
119 "GMBOX Host Int status 2: 0x%x\n",
120 irq_proc_reg
->host_int_status2
);
121 ath6kl_dbg(ATH6KL_DBG_ANY
,
122 "GMBOX RX Avail: 0x%x\n",
123 irq_proc_reg
->gmbox_rx_avail
);
124 ath6kl_dbg(ATH6KL_DBG_ANY
,
125 "GMBOX lookahead alias 0: 0x%x\n",
126 irq_proc_reg
->rx_gmbox_lkahd_alias
[0]);
127 ath6kl_dbg(ATH6KL_DBG_ANY
,
128 "GMBOX lookahead alias 1: 0x%x\n",
129 irq_proc_reg
->rx_gmbox_lkahd_alias
[1]);
134 if (irq_enable_reg
!= NULL
) {
135 ath6kl_dbg(ATH6KL_DBG_ANY
,
136 "Int status Enable: 0x%x\n",
137 irq_enable_reg
->int_status_en
);
138 ath6kl_dbg(ATH6KL_DBG_ANY
, "Counter Int status Enable: 0x%x\n",
139 irq_enable_reg
->cntr_int_status_en
);
141 ath6kl_dbg(ATH6KL_DBG_ANY
, "<------------------------------->\n");
144 static void dump_cred_dist(struct htc_endpoint_credit_dist
*ep_dist
)
146 ath6kl_dbg(ATH6KL_DBG_CREDIT
,
147 "--- endpoint: %d svc_id: 0x%X ---\n",
148 ep_dist
->endpoint
, ep_dist
->svc_id
);
149 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " dist_flags : 0x%X\n",
150 ep_dist
->dist_flags
);
151 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_norm : %d\n",
153 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_min : %d\n",
155 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " credits : %d\n",
157 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_assngd : %d\n",
158 ep_dist
->cred_assngd
);
159 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " seek_cred : %d\n",
161 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_sz : %d\n",
163 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_per_msg : %d\n",
164 ep_dist
->cred_per_msg
);
165 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_to_dist : %d\n",
166 ep_dist
->cred_to_dist
);
167 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " txq_depth : %d\n",
168 get_queue_depth(&ep_dist
->htc_ep
->txq
));
169 ath6kl_dbg(ATH6KL_DBG_CREDIT
,
170 "----------------------------------\n");
173 /* FIXME: move to htc.c */
174 void dump_cred_dist_stats(struct htc_target
*target
)
176 struct htc_endpoint_credit_dist
*ep_list
;
178 if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_CREDIT
))
181 list_for_each_entry(ep_list
, &target
->cred_dist_list
, list
)
182 dump_cred_dist(ep_list
);
184 ath6kl_dbg(ATH6KL_DBG_CREDIT
,
185 "credit distribution total %d free %d\n",
186 target
->credit_info
->total_avail_credits
,
187 target
->credit_info
->cur_free_credits
);
190 static int ath6kl_debugfs_open(struct inode
*inode
, struct file
*file
)
192 file
->private_data
= inode
->i_private
;
196 void ath6kl_debug_war(struct ath6kl
*ar
, enum ath6kl_war war
)
199 case ATH6KL_WAR_INVALID_RATE
:
200 ar
->debug
.war_stats
.invalid_rate
++;
205 static ssize_t
read_file_war_stats(struct file
*file
, char __user
*user_buf
,
206 size_t count
, loff_t
*ppos
)
208 struct ath6kl
*ar
= file
->private_data
;
210 unsigned int len
= 0, buf_len
= 1500;
213 buf
= kzalloc(buf_len
, GFP_KERNEL
);
217 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
218 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
220 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n\n",
221 "=================");
222 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10u\n",
223 "Invalid rates", ar
->debug
.war_stats
.invalid_rate
);
225 if (WARN_ON(len
> buf_len
))
228 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
234 static const struct file_operations fops_war_stats
= {
235 .read
= read_file_war_stats
,
236 .open
= ath6kl_debugfs_open
,
237 .owner
= THIS_MODULE
,
238 .llseek
= default_llseek
,
241 static void ath6kl_debug_fwlog_add(struct ath6kl
*ar
, const void *buf
,
244 struct circ_buf
*fwlog
= &ar
->debug
.fwlog_buf
;
248 /* entries must all be equal size */
249 if (WARN_ON(buf_len
!= ATH6KL_FWLOG_SLOT_SIZE
))
252 space
= CIRC_SPACE(fwlog
->head
, fwlog
->tail
, ATH6KL_FWLOG_SIZE
);
254 /* discard oldest slot */
255 fwlog
->tail
= (fwlog
->tail
+ ATH6KL_FWLOG_SLOT_SIZE
) &
256 (ATH6KL_FWLOG_SIZE
- 1);
258 for (i
= 0; i
< buf_len
; i
+= space
) {
259 space
= CIRC_SPACE_TO_END(fwlog
->head
, fwlog
->tail
,
262 if ((size_t) space
> buf_len
- i
)
265 memcpy(&fwlog
->buf
[fwlog
->head
], buf
, space
);
266 fwlog
->head
= (fwlog
->head
+ space
) & (ATH6KL_FWLOG_SIZE
- 1);
271 void ath6kl_debug_fwlog_event(struct ath6kl
*ar
, const void *buf
, size_t len
)
273 struct ath6kl_fwlog_slot
*slot
= ar
->debug
.fwlog_tmp
;
276 if (WARN_ON(len
> ATH6KL_FWLOG_PAYLOAD_SIZE
))
279 spin_lock_bh(&ar
->debug
.fwlog_lock
);
281 slot
->timestamp
= cpu_to_le32(jiffies
);
282 slot
->length
= cpu_to_le32(len
);
283 memcpy(slot
->payload
, buf
, len
);
285 slot_len
= sizeof(*slot
) + len
;
287 if (slot_len
< ATH6KL_FWLOG_SLOT_SIZE
)
288 memset(slot
->payload
+ len
, 0,
289 ATH6KL_FWLOG_SLOT_SIZE
- slot_len
);
291 ath6kl_debug_fwlog_add(ar
, slot
, ATH6KL_FWLOG_SLOT_SIZE
);
293 spin_unlock_bh(&ar
->debug
.fwlog_lock
);
296 static bool ath6kl_debug_fwlog_empty(struct ath6kl
*ar
)
298 return CIRC_CNT(ar
->debug
.fwlog_buf
.head
,
299 ar
->debug
.fwlog_buf
.tail
,
300 ATH6KL_FWLOG_SLOT_SIZE
) == 0;
303 static ssize_t
ath6kl_fwlog_read(struct file
*file
, char __user
*user_buf
,
304 size_t count
, loff_t
*ppos
)
306 struct ath6kl
*ar
= file
->private_data
;
307 struct circ_buf
*fwlog
= &ar
->debug
.fwlog_buf
;
308 size_t len
= 0, buf_len
= count
;
313 buf
= vmalloc(buf_len
);
317 /* read undelivered logs from firmware */
318 ath6kl_read_fwlogs(ar
);
320 spin_lock_bh(&ar
->debug
.fwlog_lock
);
322 while (len
< buf_len
&& !ath6kl_debug_fwlog_empty(ar
)) {
323 ccnt
= CIRC_CNT_TO_END(fwlog
->head
, fwlog
->tail
,
326 if ((size_t) ccnt
> buf_len
- len
)
327 ccnt
= buf_len
- len
;
329 memcpy(buf
+ len
, &fwlog
->buf
[fwlog
->tail
], ccnt
);
332 fwlog
->tail
= (fwlog
->tail
+ ccnt
) &
333 (ATH6KL_FWLOG_SIZE
- 1);
336 spin_unlock_bh(&ar
->debug
.fwlog_lock
);
338 if (WARN_ON(len
> buf_len
))
341 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
348 static const struct file_operations fops_fwlog
= {
349 .open
= ath6kl_debugfs_open
,
350 .read
= ath6kl_fwlog_read
,
351 .owner
= THIS_MODULE
,
352 .llseek
= default_llseek
,
355 static ssize_t
ath6kl_fwlog_mask_read(struct file
*file
, char __user
*user_buf
,
356 size_t count
, loff_t
*ppos
)
358 struct ath6kl
*ar
= file
->private_data
;
362 len
= snprintf(buf
, sizeof(buf
), "0x%x\n", ar
->debug
.fwlog_mask
);
364 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
367 static ssize_t
ath6kl_fwlog_mask_write(struct file
*file
,
368 const char __user
*user_buf
,
369 size_t count
, loff_t
*ppos
)
371 struct ath6kl
*ar
= file
->private_data
;
374 ret
= kstrtou32_from_user(user_buf
, count
, 0, &ar
->debug
.fwlog_mask
);
378 ret
= ath6kl_wmi_config_debug_module_cmd(ar
->wmi
,
379 ATH6KL_FWLOG_VALID_MASK
,
380 ar
->debug
.fwlog_mask
);
387 static const struct file_operations fops_fwlog_mask
= {
388 .open
= ath6kl_debugfs_open
,
389 .read
= ath6kl_fwlog_mask_read
,
390 .write
= ath6kl_fwlog_mask_write
,
391 .owner
= THIS_MODULE
,
392 .llseek
= default_llseek
,
395 static ssize_t
read_file_tgt_stats(struct file
*file
, char __user
*user_buf
,
396 size_t count
, loff_t
*ppos
)
398 struct ath6kl
*ar
= file
->private_data
;
399 struct ath6kl_vif
*vif
;
400 struct target_stats
*tgt_stats
;
402 unsigned int len
= 0, buf_len
= 1500;
407 vif
= ath6kl_vif_first(ar
);
411 tgt_stats
= &vif
->target_stats
;
413 buf
= kzalloc(buf_len
, GFP_KERNEL
);
417 if (down_interruptible(&ar
->sem
)) {
422 set_bit(STATS_UPDATE_PEND
, &vif
->flags
);
424 if (ath6kl_wmi_get_stats_cmd(ar
->wmi
, 0)) {
430 left
= wait_event_interruptible_timeout(ar
->event_wq
,
431 !test_bit(STATS_UPDATE_PEND
,
432 &vif
->flags
), WMI_TIMEOUT
);
441 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
442 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
444 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n\n",
445 "=================");
446 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
447 "Ucast packets", tgt_stats
->tx_ucast_pkt
);
448 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
449 "Bcast packets", tgt_stats
->tx_bcast_pkt
);
450 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
451 "Ucast byte", tgt_stats
->tx_ucast_byte
);
452 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
453 "Bcast byte", tgt_stats
->tx_bcast_byte
);
454 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
455 "Rts success cnt", tgt_stats
->tx_rts_success_cnt
);
456 for (i
= 0; i
< 4; i
++)
457 len
+= scnprintf(buf
+ len
, buf_len
- len
,
458 "%18s %d %10llu\n", "PER on ac",
459 i
, tgt_stats
->tx_pkt_per_ac
[i
]);
460 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
461 "Error", tgt_stats
->tx_err
);
462 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
463 "Fail count", tgt_stats
->tx_fail_cnt
);
464 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
465 "Retry count", tgt_stats
->tx_retry_cnt
);
466 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
467 "Multi retry cnt", tgt_stats
->tx_mult_retry_cnt
);
468 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
469 "Rts fail cnt", tgt_stats
->tx_rts_fail_cnt
);
470 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s %10llu\n\n",
471 "TKIP counter measure used",
472 tgt_stats
->tkip_cnter_measures_invoked
);
474 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
476 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
477 "=================");
479 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
480 "Ucast packets", tgt_stats
->rx_ucast_pkt
);
481 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
482 "Ucast Rate", tgt_stats
->rx_ucast_rate
);
483 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
484 "Bcast packets", tgt_stats
->rx_bcast_pkt
);
485 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
486 "Ucast byte", tgt_stats
->rx_ucast_byte
);
487 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
488 "Bcast byte", tgt_stats
->rx_bcast_byte
);
489 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
490 "Fragmented pkt", tgt_stats
->rx_frgment_pkt
);
491 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
492 "Error", tgt_stats
->rx_err
);
493 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
494 "CRC Err", tgt_stats
->rx_crc_err
);
495 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
496 "Key chache miss", tgt_stats
->rx_key_cache_miss
);
497 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
498 "Decrypt Err", tgt_stats
->rx_decrypt_err
);
499 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
500 "Duplicate frame", tgt_stats
->rx_dupl_frame
);
501 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
502 "Tkip Mic failure", tgt_stats
->tkip_local_mic_fail
);
503 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
504 "TKIP format err", tgt_stats
->tkip_fmt_err
);
505 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
506 "CCMP format Err", tgt_stats
->ccmp_fmt_err
);
507 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n\n",
508 "CCMP Replay Err", tgt_stats
->ccmp_replays
);
510 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
511 "Misc Target stats");
512 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
513 "=================");
514 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
515 "Beacon Miss count", tgt_stats
->cs_bmiss_cnt
);
516 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
517 "Num Connects", tgt_stats
->cs_connect_cnt
);
518 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
519 "Num disconnects", tgt_stats
->cs_discon_cnt
);
520 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
521 "Beacon avg rssi", tgt_stats
->cs_ave_beacon_rssi
);
526 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
532 static const struct file_operations fops_tgt_stats
= {
533 .read
= read_file_tgt_stats
,
534 .open
= ath6kl_debugfs_open
,
535 .owner
= THIS_MODULE
,
536 .llseek
= default_llseek
,
539 #define print_credit_info(fmt_str, ep_list_field) \
540 (len += scnprintf(buf + len, buf_len - len, fmt_str, \
541 ep_list->ep_list_field))
542 #define CREDIT_INFO_DISPLAY_STRING_LEN 200
543 #define CREDIT_INFO_LEN 128
545 static ssize_t
read_file_credit_dist_stats(struct file
*file
,
546 char __user
*user_buf
,
547 size_t count
, loff_t
*ppos
)
549 struct ath6kl
*ar
= file
->private_data
;
550 struct htc_target
*target
= ar
->htc_target
;
551 struct htc_endpoint_credit_dist
*ep_list
;
553 unsigned int buf_len
, len
= 0;
556 buf_len
= CREDIT_INFO_DISPLAY_STRING_LEN
+
557 get_queue_depth(&target
->cred_dist_list
) * CREDIT_INFO_LEN
;
558 buf
= kzalloc(buf_len
, GFP_KERNEL
);
562 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s%5d\n",
563 "Total Avail Credits: ",
564 target
->credit_info
->total_avail_credits
);
565 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s%5d\n",
567 target
->credit_info
->cur_free_credits
);
569 len
+= scnprintf(buf
+ len
, buf_len
- len
,
570 " Epid Flags Cred_norm Cred_min Credits Cred_assngd"
571 " Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
574 list_for_each_entry(ep_list
, &target
->cred_dist_list
, list
) {
575 print_credit_info(" %2d", endpoint
);
576 print_credit_info("%10x", dist_flags
);
577 print_credit_info("%8d", cred_norm
);
578 print_credit_info("%9d", cred_min
);
579 print_credit_info("%9d", credits
);
580 print_credit_info("%10d", cred_assngd
);
581 print_credit_info("%13d", seek_cred
);
582 print_credit_info("%12d", cred_sz
);
583 print_credit_info("%9d", cred_per_msg
);
584 print_credit_info("%14d", cred_to_dist
);
585 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%12d\n",
586 get_queue_depth(&ep_list
->htc_ep
->txq
));
592 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
597 static const struct file_operations fops_credit_dist_stats
= {
598 .read
= read_file_credit_dist_stats
,
599 .open
= ath6kl_debugfs_open
,
600 .owner
= THIS_MODULE
,
601 .llseek
= default_llseek
,
604 static unsigned int print_endpoint_stat(struct htc_target
*target
, char *buf
,
605 unsigned int buf_len
, unsigned int len
,
606 int offset
, const char *name
)
609 struct htc_endpoint_stats
*ep_st
;
612 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%s:", name
);
613 for (i
= 0; i
< ENDPOINT_MAX
; i
++) {
614 ep_st
= &target
->endpoint
[i
].ep_st
;
615 counter
= ((u32
*) ep_st
) + (offset
/ 4);
616 len
+= scnprintf(buf
+ len
, buf_len
- len
, " %u", *counter
);
618 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
623 static ssize_t
ath6kl_endpoint_stats_read(struct file
*file
,
624 char __user
*user_buf
,
625 size_t count
, loff_t
*ppos
)
627 struct ath6kl
*ar
= file
->private_data
;
628 struct htc_target
*target
= ar
->htc_target
;
630 unsigned int buf_len
, len
= 0;
633 buf_len
= sizeof(struct htc_endpoint_stats
) / sizeof(u32
) *
634 (25 + ENDPOINT_MAX
* 11);
635 buf
= kmalloc(buf_len
, GFP_KERNEL
);
639 #define EPSTAT(name) \
640 len = print_endpoint_stat(target, buf, buf_len, len, \
641 offsetof(struct htc_endpoint_stats, name), \
643 EPSTAT(cred_low_indicate
);
645 EPSTAT(tx_pkt_bundled
);
649 EPSTAT(cred_rpt_from_rx
);
650 EPSTAT(cred_rpt_from_other
);
651 EPSTAT(cred_rpt_ep0
);
652 EPSTAT(cred_from_rx
);
653 EPSTAT(cred_from_other
);
654 EPSTAT(cred_from_ep0
);
660 EPSTAT(rx_bundle_lkahd
);
661 EPSTAT(rx_bundle_from_hdr
);
662 EPSTAT(rx_alloc_thresh_hit
);
663 EPSTAT(rxalloc_thresh_byte
);
669 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
674 static ssize_t
ath6kl_endpoint_stats_write(struct file
*file
,
675 const char __user
*user_buf
,
676 size_t count
, loff_t
*ppos
)
678 struct ath6kl
*ar
= file
->private_data
;
679 struct htc_target
*target
= ar
->htc_target
;
682 struct htc_endpoint_stats
*ep_st
;
684 ret
= kstrtou32_from_user(user_buf
, count
, 0, &val
);
688 for (i
= 0; i
< ENDPOINT_MAX
; i
++) {
689 ep_st
= &target
->endpoint
[i
].ep_st
;
690 memset(ep_st
, 0, sizeof(*ep_st
));
697 static const struct file_operations fops_endpoint_stats
= {
698 .open
= ath6kl_debugfs_open
,
699 .read
= ath6kl_endpoint_stats_read
,
700 .write
= ath6kl_endpoint_stats_write
,
701 .owner
= THIS_MODULE
,
702 .llseek
= default_llseek
,
705 static unsigned long ath6kl_get_num_reg(void)
708 unsigned long n_reg
= 0;
710 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++)
712 (diag_reg
[i
].reg_end
- diag_reg
[i
].reg_start
) / 4 + 1;
717 static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr
)
721 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++) {
722 if (reg_addr
>= diag_reg
[i
].reg_start
&&
723 reg_addr
<= diag_reg
[i
].reg_end
)
730 static ssize_t
ath6kl_regread_read(struct file
*file
, char __user
*user_buf
,
731 size_t count
, loff_t
*ppos
)
733 struct ath6kl
*ar
= file
->private_data
;
735 unsigned int len
= 0;
737 if (ar
->debug
.dbgfs_diag_reg
)
738 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "0x%x\n",
739 ar
->debug
.dbgfs_diag_reg
);
741 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
742 "All diag registers\n");
744 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
747 static ssize_t
ath6kl_regread_write(struct file
*file
,
748 const char __user
*user_buf
,
749 size_t count
, loff_t
*ppos
)
751 struct ath6kl
*ar
= file
->private_data
;
754 unsigned long reg_addr
;
756 len
= min(count
, sizeof(buf
) - 1);
757 if (copy_from_user(buf
, user_buf
, len
))
762 if (strict_strtoul(buf
, 0, ®_addr
))
765 if ((reg_addr
% 4) != 0)
768 if (reg_addr
&& !ath6kl_dbg_is_diag_reg_valid(reg_addr
))
771 ar
->debug
.dbgfs_diag_reg
= reg_addr
;
776 static const struct file_operations fops_diag_reg_read
= {
777 .read
= ath6kl_regread_read
,
778 .write
= ath6kl_regread_write
,
779 .open
= ath6kl_debugfs_open
,
780 .owner
= THIS_MODULE
,
781 .llseek
= default_llseek
,
784 static int ath6kl_regdump_open(struct inode
*inode
, struct file
*file
)
786 struct ath6kl
*ar
= inode
->i_private
;
788 unsigned long int reg_len
;
789 unsigned int len
= 0, n_reg
;
794 /* Dump all the registers if no register is specified */
795 if (!ar
->debug
.dbgfs_diag_reg
)
796 n_reg
= ath6kl_get_num_reg();
800 reg_len
= n_reg
* REG_OUTPUT_LEN_PER_LINE
;
802 reg_len
+= REGTYPE_STR_LEN
;
804 buf
= vmalloc(reg_len
);
809 addr
= ar
->debug
.dbgfs_diag_reg
;
811 status
= ath6kl_diag_read32(ar
,
812 TARG_VTOP(ar
->target_type
, addr
),
817 len
+= scnprintf(buf
+ len
, reg_len
- len
,
818 "0x%06x 0x%08x\n", addr
, le32_to_cpu(reg_val
));
822 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++) {
823 len
+= scnprintf(buf
+ len
, reg_len
- len
,
824 "%s\n", diag_reg
[i
].reg_info
);
825 for (addr
= diag_reg
[i
].reg_start
;
826 addr
<= diag_reg
[i
].reg_end
; addr
+= 4) {
827 status
= ath6kl_diag_read32(ar
,
828 TARG_VTOP(ar
->target_type
, addr
),
833 len
+= scnprintf(buf
+ len
, reg_len
- len
,
835 addr
, le32_to_cpu(reg_val
));
840 file
->private_data
= buf
;
844 ath6kl_warn("Unable to read memory:%u\n", addr
);
849 static ssize_t
ath6kl_regdump_read(struct file
*file
, char __user
*user_buf
,
850 size_t count
, loff_t
*ppos
)
852 u8
*buf
= file
->private_data
;
853 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, strlen(buf
));
856 static int ath6kl_regdump_release(struct inode
*inode
, struct file
*file
)
858 vfree(file
->private_data
);
862 static const struct file_operations fops_reg_dump
= {
863 .open
= ath6kl_regdump_open
,
864 .read
= ath6kl_regdump_read
,
865 .release
= ath6kl_regdump_release
,
866 .owner
= THIS_MODULE
,
867 .llseek
= default_llseek
,
870 static ssize_t
ath6kl_lrssi_roam_write(struct file
*file
,
871 const char __user
*user_buf
,
872 size_t count
, loff_t
*ppos
)
874 struct ath6kl
*ar
= file
->private_data
;
875 unsigned long lrssi_roam_threshold
;
879 len
= min(count
, sizeof(buf
) - 1);
880 if (copy_from_user(buf
, user_buf
, len
))
884 if (strict_strtoul(buf
, 0, &lrssi_roam_threshold
))
887 ar
->lrssi_roam_threshold
= lrssi_roam_threshold
;
889 ath6kl_wmi_set_roam_lrssi_cmd(ar
->wmi
, ar
->lrssi_roam_threshold
);
894 static ssize_t
ath6kl_lrssi_roam_read(struct file
*file
,
895 char __user
*user_buf
,
896 size_t count
, loff_t
*ppos
)
898 struct ath6kl
*ar
= file
->private_data
;
902 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->lrssi_roam_threshold
);
904 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
907 static const struct file_operations fops_lrssi_roam_threshold
= {
908 .read
= ath6kl_lrssi_roam_read
,
909 .write
= ath6kl_lrssi_roam_write
,
910 .open
= ath6kl_debugfs_open
,
911 .owner
= THIS_MODULE
,
912 .llseek
= default_llseek
,
915 static ssize_t
ath6kl_regwrite_read(struct file
*file
,
916 char __user
*user_buf
,
917 size_t count
, loff_t
*ppos
)
919 struct ath6kl
*ar
= file
->private_data
;
921 unsigned int len
= 0;
923 len
= scnprintf(buf
, sizeof(buf
), "Addr: 0x%x Val: 0x%x\n",
924 ar
->debug
.diag_reg_addr_wr
, ar
->debug
.diag_reg_val_wr
);
926 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
929 static ssize_t
ath6kl_regwrite_write(struct file
*file
,
930 const char __user
*user_buf
,
931 size_t count
, loff_t
*ppos
)
933 struct ath6kl
*ar
= file
->private_data
;
936 unsigned int len
= 0;
937 u32 reg_addr
, reg_val
;
939 len
= min(count
, sizeof(buf
) - 1);
940 if (copy_from_user(buf
, user_buf
, len
))
946 token
= strsep(&sptr
, "=");
950 if (kstrtou32(token
, 0, ®_addr
))
953 if (!ath6kl_dbg_is_diag_reg_valid(reg_addr
))
956 if (kstrtou32(sptr
, 0, ®_val
))
959 ar
->debug
.diag_reg_addr_wr
= reg_addr
;
960 ar
->debug
.diag_reg_val_wr
= reg_val
;
962 if (ath6kl_diag_write32(ar
, ar
->debug
.diag_reg_addr_wr
,
963 cpu_to_le32(ar
->debug
.diag_reg_val_wr
)))
969 static const struct file_operations fops_diag_reg_write
= {
970 .read
= ath6kl_regwrite_read
,
971 .write
= ath6kl_regwrite_write
,
972 .open
= ath6kl_debugfs_open
,
973 .owner
= THIS_MODULE
,
974 .llseek
= default_llseek
,
977 int ath6kl_debug_roam_tbl_event(struct ath6kl
*ar
, const void *buf
,
980 const struct wmi_target_roam_tbl
*tbl
;
983 if (len
< sizeof(*tbl
))
986 tbl
= (const struct wmi_target_roam_tbl
*) buf
;
987 num_entries
= le16_to_cpu(tbl
->num_entries
);
988 if (sizeof(*tbl
) + num_entries
* sizeof(struct wmi_bss_roam_info
) >
992 if (ar
->debug
.roam_tbl
== NULL
||
993 ar
->debug
.roam_tbl_len
< (unsigned int) len
) {
994 kfree(ar
->debug
.roam_tbl
);
995 ar
->debug
.roam_tbl
= kmalloc(len
, GFP_ATOMIC
);
996 if (ar
->debug
.roam_tbl
== NULL
)
1000 memcpy(ar
->debug
.roam_tbl
, buf
, len
);
1001 ar
->debug
.roam_tbl_len
= len
;
1003 if (test_bit(ROAM_TBL_PEND
, &ar
->flag
)) {
1004 clear_bit(ROAM_TBL_PEND
, &ar
->flag
);
1005 wake_up(&ar
->event_wq
);
1011 static ssize_t
ath6kl_roam_table_read(struct file
*file
, char __user
*user_buf
,
1012 size_t count
, loff_t
*ppos
)
1014 struct ath6kl
*ar
= file
->private_data
;
1017 struct wmi_target_roam_tbl
*tbl
;
1020 unsigned int len
, buf_len
;
1023 if (down_interruptible(&ar
->sem
))
1026 set_bit(ROAM_TBL_PEND
, &ar
->flag
);
1028 ret
= ath6kl_wmi_get_roam_tbl_cmd(ar
->wmi
);
1034 left
= wait_event_interruptible_timeout(
1035 ar
->event_wq
, !test_bit(ROAM_TBL_PEND
, &ar
->flag
), WMI_TIMEOUT
);
1041 if (ar
->debug
.roam_tbl
== NULL
)
1044 tbl
= (struct wmi_target_roam_tbl
*) ar
->debug
.roam_tbl
;
1045 num_entries
= le16_to_cpu(tbl
->num_entries
);
1047 buf_len
= 100 + num_entries
* 100;
1048 buf
= kzalloc(buf_len
, GFP_KERNEL
);
1052 len
+= scnprintf(buf
+ len
, buf_len
- len
,
1054 "# roam_util bssid rssi rssidt last_rssi util bias\n",
1055 le16_to_cpu(tbl
->roam_mode
));
1057 for (i
= 0; i
< num_entries
; i
++) {
1058 struct wmi_bss_roam_info
*info
= &tbl
->info
[i
];
1059 len
+= scnprintf(buf
+ len
, buf_len
- len
,
1060 "%d %pM %d %d %d %d %d\n",
1061 a_sle32_to_cpu(info
->roam_util
), info
->bssid
,
1062 info
->rssi
, info
->rssidt
, info
->last_rssi
,
1063 info
->util
, info
->bias
);
1069 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1075 static const struct file_operations fops_roam_table
= {
1076 .read
= ath6kl_roam_table_read
,
1077 .open
= ath6kl_debugfs_open
,
1078 .owner
= THIS_MODULE
,
1079 .llseek
= default_llseek
,
1082 static ssize_t
ath6kl_force_roam_write(struct file
*file
,
1083 const char __user
*user_buf
,
1084 size_t count
, loff_t
*ppos
)
1086 struct ath6kl
*ar
= file
->private_data
;
1094 len
= min(count
, sizeof(buf
) - 1);
1095 if (copy_from_user(buf
, user_buf
, len
))
1099 if (sscanf(buf
, "%02x:%02x:%02x:%02x:%02x:%02x",
1100 &addr
[0], &addr
[1], &addr
[2], &addr
[3], &addr
[4], &addr
[5])
1103 for (i
= 0; i
< ETH_ALEN
; i
++)
1106 ret
= ath6kl_wmi_force_roam_cmd(ar
->wmi
, bssid
);
1113 static const struct file_operations fops_force_roam
= {
1114 .write
= ath6kl_force_roam_write
,
1115 .open
= ath6kl_debugfs_open
,
1116 .owner
= THIS_MODULE
,
1117 .llseek
= default_llseek
,
1120 static ssize_t
ath6kl_roam_mode_write(struct file
*file
,
1121 const char __user
*user_buf
,
1122 size_t count
, loff_t
*ppos
)
1124 struct ath6kl
*ar
= file
->private_data
;
1128 enum wmi_roam_mode mode
;
1130 len
= min(count
, sizeof(buf
) - 1);
1131 if (copy_from_user(buf
, user_buf
, len
))
1134 if (len
> 0 && buf
[len
- 1] == '\n')
1135 buf
[len
- 1] = '\0';
1137 if (strcasecmp(buf
, "default") == 0)
1138 mode
= WMI_DEFAULT_ROAM_MODE
;
1139 else if (strcasecmp(buf
, "bssbias") == 0)
1140 mode
= WMI_HOST_BIAS_ROAM_MODE
;
1141 else if (strcasecmp(buf
, "lock") == 0)
1142 mode
= WMI_LOCK_BSS_MODE
;
1146 ret
= ath6kl_wmi_set_roam_mode_cmd(ar
->wmi
, mode
);
1153 static const struct file_operations fops_roam_mode
= {
1154 .write
= ath6kl_roam_mode_write
,
1155 .open
= ath6kl_debugfs_open
,
1156 .owner
= THIS_MODULE
,
1157 .llseek
= default_llseek
,
1160 void ath6kl_debug_set_keepalive(struct ath6kl
*ar
, u8 keepalive
)
1162 ar
->debug
.keepalive
= keepalive
;
1165 static ssize_t
ath6kl_keepalive_read(struct file
*file
, char __user
*user_buf
,
1166 size_t count
, loff_t
*ppos
)
1168 struct ath6kl
*ar
= file
->private_data
;
1172 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->debug
.keepalive
);
1174 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1177 static ssize_t
ath6kl_keepalive_write(struct file
*file
,
1178 const char __user
*user_buf
,
1179 size_t count
, loff_t
*ppos
)
1181 struct ath6kl
*ar
= file
->private_data
;
1185 ret
= kstrtou8_from_user(user_buf
, count
, 0, &val
);
1189 ret
= ath6kl_wmi_set_keepalive_cmd(ar
->wmi
, 0, val
);
1196 static const struct file_operations fops_keepalive
= {
1197 .open
= ath6kl_debugfs_open
,
1198 .read
= ath6kl_keepalive_read
,
1199 .write
= ath6kl_keepalive_write
,
1200 .owner
= THIS_MODULE
,
1201 .llseek
= default_llseek
,
1204 void ath6kl_debug_set_disconnect_timeout(struct ath6kl
*ar
, u8 timeout
)
1206 ar
->debug
.disc_timeout
= timeout
;
1209 static ssize_t
ath6kl_disconnect_timeout_read(struct file
*file
,
1210 char __user
*user_buf
,
1211 size_t count
, loff_t
*ppos
)
1213 struct ath6kl
*ar
= file
->private_data
;
1217 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->debug
.disc_timeout
);
1219 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1222 static ssize_t
ath6kl_disconnect_timeout_write(struct file
*file
,
1223 const char __user
*user_buf
,
1224 size_t count
, loff_t
*ppos
)
1226 struct ath6kl
*ar
= file
->private_data
;
1230 ret
= kstrtou8_from_user(user_buf
, count
, 0, &val
);
1234 ret
= ath6kl_wmi_disctimeout_cmd(ar
->wmi
, 0, val
);
1241 static const struct file_operations fops_disconnect_timeout
= {
1242 .open
= ath6kl_debugfs_open
,
1243 .read
= ath6kl_disconnect_timeout_read
,
1244 .write
= ath6kl_disconnect_timeout_write
,
1245 .owner
= THIS_MODULE
,
1246 .llseek
= default_llseek
,
1249 static ssize_t
ath6kl_create_qos_write(struct file
*file
,
1250 const char __user
*user_buf
,
1251 size_t count
, loff_t
*ppos
)
1254 struct ath6kl
*ar
= file
->private_data
;
1255 struct ath6kl_vif
*vif
;
1259 struct wmi_create_pstream_cmd pstream
;
1263 vif
= ath6kl_vif_first(ar
);
1267 len
= min(count
, sizeof(buf
) - 1);
1268 if (copy_from_user(buf
, user_buf
, len
))
1273 token
= strsep(&sptr
, " ");
1276 if (kstrtou8(token
, 0, &pstream
.user_pri
))
1279 token
= strsep(&sptr
, " ");
1282 if (kstrtou8(token
, 0, &pstream
.traffic_direc
))
1285 token
= strsep(&sptr
, " ");
1288 if (kstrtou8(token
, 0, &pstream
.traffic_class
))
1291 token
= strsep(&sptr
, " ");
1294 if (kstrtou8(token
, 0, &pstream
.traffic_type
))
1297 token
= strsep(&sptr
, " ");
1300 if (kstrtou8(token
, 0, &pstream
.voice_psc_cap
))
1303 token
= strsep(&sptr
, " ");
1306 if (kstrtou32(token
, 0, &val32
))
1308 pstream
.min_service_int
= cpu_to_le32(val32
);
1310 token
= strsep(&sptr
, " ");
1313 if (kstrtou32(token
, 0, &val32
))
1315 pstream
.max_service_int
= cpu_to_le32(val32
);
1317 token
= strsep(&sptr
, " ");
1320 if (kstrtou32(token
, 0, &val32
))
1322 pstream
.inactivity_int
= cpu_to_le32(val32
);
1324 token
= strsep(&sptr
, " ");
1327 if (kstrtou32(token
, 0, &val32
))
1329 pstream
.suspension_int
= cpu_to_le32(val32
);
1331 token
= strsep(&sptr
, " ");
1334 if (kstrtou32(token
, 0, &val32
))
1336 pstream
.service_start_time
= cpu_to_le32(val32
);
1338 token
= strsep(&sptr
, " ");
1341 if (kstrtou8(token
, 0, &pstream
.tsid
))
1344 token
= strsep(&sptr
, " ");
1347 if (kstrtou16(token
, 0, &val16
))
1349 pstream
.nominal_msdu
= cpu_to_le16(val16
);
1351 token
= strsep(&sptr
, " ");
1354 if (kstrtou16(token
, 0, &val16
))
1356 pstream
.max_msdu
= cpu_to_le16(val16
);
1358 token
= strsep(&sptr
, " ");
1361 if (kstrtou32(token
, 0, &val32
))
1363 pstream
.min_data_rate
= cpu_to_le32(val32
);
1365 token
= strsep(&sptr
, " ");
1368 if (kstrtou32(token
, 0, &val32
))
1370 pstream
.mean_data_rate
= cpu_to_le32(val32
);
1372 token
= strsep(&sptr
, " ");
1375 if (kstrtou32(token
, 0, &val32
))
1377 pstream
.peak_data_rate
= cpu_to_le32(val32
);
1379 token
= strsep(&sptr
, " ");
1382 if (kstrtou32(token
, 0, &val32
))
1384 pstream
.max_burst_size
= cpu_to_le32(val32
);
1386 token
= strsep(&sptr
, " ");
1389 if (kstrtou32(token
, 0, &val32
))
1391 pstream
.delay_bound
= cpu_to_le32(val32
);
1393 token
= strsep(&sptr
, " ");
1396 if (kstrtou32(token
, 0, &val32
))
1398 pstream
.min_phy_rate
= cpu_to_le32(val32
);
1400 token
= strsep(&sptr
, " ");
1403 if (kstrtou32(token
, 0, &val32
))
1405 pstream
.sba
= cpu_to_le32(val32
);
1407 token
= strsep(&sptr
, " ");
1410 if (kstrtou32(token
, 0, &val32
))
1412 pstream
.medium_time
= cpu_to_le32(val32
);
1414 ath6kl_wmi_create_pstream_cmd(ar
->wmi
, vif
->fw_vif_idx
, &pstream
);
1419 static const struct file_operations fops_create_qos
= {
1420 .write
= ath6kl_create_qos_write
,
1421 .open
= ath6kl_debugfs_open
,
1422 .owner
= THIS_MODULE
,
1423 .llseek
= default_llseek
,
1426 static ssize_t
ath6kl_delete_qos_write(struct file
*file
,
1427 const char __user
*user_buf
,
1428 size_t count
, loff_t
*ppos
)
1431 struct ath6kl
*ar
= file
->private_data
;
1432 struct ath6kl_vif
*vif
;
1439 vif
= ath6kl_vif_first(ar
);
1443 len
= min(count
, sizeof(buf
) - 1);
1444 if (copy_from_user(buf
, user_buf
, len
))
1449 token
= strsep(&sptr
, " ");
1452 if (kstrtou8(token
, 0, &traffic_class
))
1455 token
= strsep(&sptr
, " ");
1458 if (kstrtou8(token
, 0, &tsid
))
1461 ath6kl_wmi_delete_pstream_cmd(ar
->wmi
, vif
->fw_vif_idx
,
1462 traffic_class
, tsid
);
1467 static const struct file_operations fops_delete_qos
= {
1468 .write
= ath6kl_delete_qos_write
,
1469 .open
= ath6kl_debugfs_open
,
1470 .owner
= THIS_MODULE
,
1471 .llseek
= default_llseek
,
1474 static ssize_t
ath6kl_bgscan_int_write(struct file
*file
,
1475 const char __user
*user_buf
,
1476 size_t count
, loff_t
*ppos
)
1478 struct ath6kl
*ar
= file
->private_data
;
1483 len
= min(count
, sizeof(buf
) - 1);
1484 if (copy_from_user(buf
, user_buf
, len
))
1488 if (kstrtou16(buf
, 0, &bgscan_int
))
1491 if (bgscan_int
== 0)
1492 bgscan_int
= 0xffff;
1494 ath6kl_wmi_scanparams_cmd(ar
->wmi
, 0, 0, 0, bgscan_int
, 0, 0, 0, 3,
1500 static const struct file_operations fops_bgscan_int
= {
1501 .write
= ath6kl_bgscan_int_write
,
1502 .open
= ath6kl_debugfs_open
,
1503 .owner
= THIS_MODULE
,
1504 .llseek
= default_llseek
,
1507 static ssize_t
ath6kl_listen_int_write(struct file
*file
,
1508 const char __user
*user_buf
,
1509 size_t count
, loff_t
*ppos
)
1511 struct ath6kl
*ar
= file
->private_data
;
1512 u16 listen_int_t
, listen_int_b
;
1517 len
= min(count
, sizeof(buf
) - 1);
1518 if (copy_from_user(buf
, user_buf
, len
))
1524 token
= strsep(&sptr
, " ");
1528 if (kstrtou16(token
, 0, &listen_int_t
))
1531 if (kstrtou16(sptr
, 0, &listen_int_b
))
1534 if ((listen_int_t
< 15) || (listen_int_t
> 5000))
1537 if ((listen_int_b
< 1) || (listen_int_b
> 50))
1540 ar
->listen_intvl_t
= listen_int_t
;
1541 ar
->listen_intvl_b
= listen_int_b
;
1543 ath6kl_wmi_listeninterval_cmd(ar
->wmi
, 0, ar
->listen_intvl_t
,
1544 ar
->listen_intvl_b
);
1549 static ssize_t
ath6kl_listen_int_read(struct file
*file
,
1550 char __user
*user_buf
,
1551 size_t count
, loff_t
*ppos
)
1553 struct ath6kl
*ar
= file
->private_data
;
1557 len
= scnprintf(buf
, sizeof(buf
), "%u %u\n", ar
->listen_intvl_t
,
1558 ar
->listen_intvl_b
);
1560 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1563 static const struct file_operations fops_listen_int
= {
1564 .read
= ath6kl_listen_int_read
,
1565 .write
= ath6kl_listen_int_write
,
1566 .open
= ath6kl_debugfs_open
,
1567 .owner
= THIS_MODULE
,
1568 .llseek
= default_llseek
,
1571 static ssize_t
ath6kl_power_params_write(struct file
*file
,
1572 const char __user
*user_buf
,
1573 size_t count
, loff_t
*ppos
)
1575 struct ath6kl
*ar
= file
->private_data
;
1577 unsigned int len
= 0;
1579 u16 idle_period
, ps_poll_num
, dtim
,
1582 len
= min(count
, sizeof(buf
) - 1);
1583 if (copy_from_user(buf
, user_buf
, len
))
1588 token
= strsep(&sptr
, " ");
1591 if (kstrtou16(token
, 0, &idle_period
))
1594 token
= strsep(&sptr
, " ");
1597 if (kstrtou16(token
, 0, &ps_poll_num
))
1600 token
= strsep(&sptr
, " ");
1603 if (kstrtou16(token
, 0, &dtim
))
1606 token
= strsep(&sptr
, " ");
1609 if (kstrtou16(token
, 0, &tx_wakeup
))
1612 token
= strsep(&sptr
, " ");
1615 if (kstrtou16(token
, 0, &num_tx
))
1618 ath6kl_wmi_pmparams_cmd(ar
->wmi
, 0, idle_period
, ps_poll_num
,
1619 dtim
, tx_wakeup
, num_tx
, 0);
1624 static const struct file_operations fops_power_params
= {
1625 .write
= ath6kl_power_params_write
,
1626 .open
= ath6kl_debugfs_open
,
1627 .owner
= THIS_MODULE
,
1628 .llseek
= default_llseek
,
1631 int ath6kl_debug_init(struct ath6kl
*ar
)
1633 ar
->debug
.fwlog_buf
.buf
= vmalloc(ATH6KL_FWLOG_SIZE
);
1634 if (ar
->debug
.fwlog_buf
.buf
== NULL
)
1637 ar
->debug
.fwlog_tmp
= kmalloc(ATH6KL_FWLOG_SLOT_SIZE
, GFP_KERNEL
);
1638 if (ar
->debug
.fwlog_tmp
== NULL
) {
1639 vfree(ar
->debug
.fwlog_buf
.buf
);
1643 spin_lock_init(&ar
->debug
.fwlog_lock
);
1646 * Actually we are lying here but don't know how to read the mask
1647 * value from the firmware.
1649 ar
->debug
.fwlog_mask
= 0;
1651 ar
->debugfs_phy
= debugfs_create_dir("ath6kl",
1652 ar
->wiphy
->debugfsdir
);
1653 if (!ar
->debugfs_phy
) {
1654 vfree(ar
->debug
.fwlog_buf
.buf
);
1655 kfree(ar
->debug
.fwlog_tmp
);
1659 debugfs_create_file("tgt_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1662 debugfs_create_file("credit_dist_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1663 &fops_credit_dist_stats
);
1665 debugfs_create_file("endpoint_stats", S_IRUSR
| S_IWUSR
,
1666 ar
->debugfs_phy
, ar
, &fops_endpoint_stats
);
1668 debugfs_create_file("fwlog", S_IRUSR
, ar
->debugfs_phy
, ar
,
1671 debugfs_create_file("fwlog_mask", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
,
1672 ar
, &fops_fwlog_mask
);
1674 debugfs_create_file("reg_addr", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
, ar
,
1675 &fops_diag_reg_read
);
1677 debugfs_create_file("reg_dump", S_IRUSR
, ar
->debugfs_phy
, ar
,
1680 debugfs_create_file("lrssi_roam_threshold", S_IRUSR
| S_IWUSR
,
1681 ar
->debugfs_phy
, ar
, &fops_lrssi_roam_threshold
);
1683 debugfs_create_file("reg_write", S_IRUSR
| S_IWUSR
,
1684 ar
->debugfs_phy
, ar
, &fops_diag_reg_write
);
1686 debugfs_create_file("war_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1689 debugfs_create_file("roam_table", S_IRUSR
, ar
->debugfs_phy
, ar
,
1692 debugfs_create_file("force_roam", S_IWUSR
, ar
->debugfs_phy
, ar
,
1695 debugfs_create_file("roam_mode", S_IWUSR
, ar
->debugfs_phy
, ar
,
1698 debugfs_create_file("keepalive", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
, ar
,
1701 debugfs_create_file("disconnect_timeout", S_IRUSR
| S_IWUSR
,
1702 ar
->debugfs_phy
, ar
, &fops_disconnect_timeout
);
1704 debugfs_create_file("create_qos", S_IWUSR
, ar
->debugfs_phy
, ar
,
1707 debugfs_create_file("delete_qos", S_IWUSR
, ar
->debugfs_phy
, ar
,
1710 debugfs_create_file("bgscan_interval", S_IWUSR
,
1711 ar
->debugfs_phy
, ar
, &fops_bgscan_int
);
1713 debugfs_create_file("power_params", S_IWUSR
, ar
->debugfs_phy
, ar
,
1714 &fops_power_params
);
1719 void ath6kl_debug_cleanup(struct ath6kl
*ar
)
1721 vfree(ar
->debug
.fwlog_buf
.buf
);
1722 kfree(ar
->debug
.fwlog_tmp
);
1723 kfree(ar
->debug
.roam_tbl
);