2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <linux/skbuff.h>
22 #include <linux/vmalloc.h>
23 #include <linux/export.h>
28 struct ath6kl_fwlog_slot
{
32 /* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */
36 #define ATH6KL_FWLOG_MAX_ENTRIES 20
38 #define ATH6KL_FWLOG_VALID_MASK 0x1ffff
40 int ath6kl_printk(const char *level
, const char *fmt
, ...)
51 rtn
= printk("%sath6kl: %pV", level
, &vaf
);
57 EXPORT_SYMBOL(ath6kl_printk
);
59 int ath6kl_info(const char *fmt
, ...)
61 struct va_format vaf
= {
69 ret
= ath6kl_printk(KERN_INFO
, "%pV", &vaf
);
70 trace_ath6kl_log_info(&vaf
);
75 EXPORT_SYMBOL(ath6kl_info
);
77 int ath6kl_err(const char *fmt
, ...)
79 struct va_format vaf
= {
87 ret
= ath6kl_printk(KERN_ERR
, "%pV", &vaf
);
88 trace_ath6kl_log_err(&vaf
);
93 EXPORT_SYMBOL(ath6kl_err
);
95 int ath6kl_warn(const char *fmt
, ...)
97 struct va_format vaf
= {
105 ret
= ath6kl_printk(KERN_WARNING
, "%pV", &vaf
);
106 trace_ath6kl_log_warn(&vaf
);
111 EXPORT_SYMBOL(ath6kl_warn
);
113 #ifdef CONFIG_ATH6KL_DEBUG
115 void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask
, const char *fmt
, ...)
117 struct va_format vaf
;
125 if (debug_mask
& mask
)
126 ath6kl_printk(KERN_DEBUG
, "%pV", &vaf
);
128 trace_ath6kl_log_dbg(mask
, &vaf
);
132 EXPORT_SYMBOL(ath6kl_dbg
);
134 void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask
,
135 const char *msg
, const char *prefix
,
136 const void *buf
, size_t len
)
138 if (debug_mask
& mask
) {
140 ath6kl_dbg(mask
, "%s\n", msg
);
142 print_hex_dump_bytes(prefix
, DUMP_PREFIX_OFFSET
, buf
, len
);
145 /* tracing code doesn't like null strings :/ */
146 trace_ath6kl_log_dbg_dump(msg
? msg
: "", prefix
? prefix
: "",
149 EXPORT_SYMBOL(ath6kl_dbg_dump
);
151 #define REG_OUTPUT_LEN_PER_LINE 25
152 #define REGTYPE_STR_LEN 100
154 struct ath6kl_diag_reg_info
{
157 const char *reg_info
;
160 static const struct ath6kl_diag_reg_info diag_reg
[] = {
161 { 0x20000, 0x200fc, "General DMA and Rx registers" },
162 { 0x28000, 0x28900, "MAC PCU register & keycache" },
163 { 0x20800, 0x20a40, "QCU" },
164 { 0x21000, 0x212f0, "DCU" },
165 { 0x4000, 0x42e4, "RTC" },
166 { 0x540000, 0x540000 + (256 * 1024), "RAM" },
167 { 0x29800, 0x2B210, "Base Band" },
168 { 0x1C000, 0x1C748, "Analog" },
171 void ath6kl_dump_registers(struct ath6kl_device
*dev
,
172 struct ath6kl_irq_proc_registers
*irq_proc_reg
,
173 struct ath6kl_irq_enable_reg
*irq_enable_reg
)
176 ath6kl_dbg(ATH6KL_DBG_IRQ
, ("<------- Register Table -------->\n"));
178 if (irq_proc_reg
!= NULL
) {
179 ath6kl_dbg(ATH6KL_DBG_IRQ
,
180 "Host Int status: 0x%x\n",
181 irq_proc_reg
->host_int_status
);
182 ath6kl_dbg(ATH6KL_DBG_IRQ
,
183 "CPU Int status: 0x%x\n",
184 irq_proc_reg
->cpu_int_status
);
185 ath6kl_dbg(ATH6KL_DBG_IRQ
,
186 "Error Int status: 0x%x\n",
187 irq_proc_reg
->error_int_status
);
188 ath6kl_dbg(ATH6KL_DBG_IRQ
,
189 "Counter Int status: 0x%x\n",
190 irq_proc_reg
->counter_int_status
);
191 ath6kl_dbg(ATH6KL_DBG_IRQ
,
192 "Mbox Frame: 0x%x\n",
193 irq_proc_reg
->mbox_frame
);
194 ath6kl_dbg(ATH6KL_DBG_IRQ
,
195 "Rx Lookahead Valid: 0x%x\n",
196 irq_proc_reg
->rx_lkahd_valid
);
197 ath6kl_dbg(ATH6KL_DBG_IRQ
,
198 "Rx Lookahead 0: 0x%x\n",
199 irq_proc_reg
->rx_lkahd
[0]);
200 ath6kl_dbg(ATH6KL_DBG_IRQ
,
201 "Rx Lookahead 1: 0x%x\n",
202 irq_proc_reg
->rx_lkahd
[1]);
204 if (dev
->ar
->mbox_info
.gmbox_addr
!= 0) {
206 * If the target supports GMBOX hardware, dump some
209 ath6kl_dbg(ATH6KL_DBG_IRQ
,
210 "GMBOX Host Int status 2: 0x%x\n",
211 irq_proc_reg
->host_int_status2
);
212 ath6kl_dbg(ATH6KL_DBG_IRQ
,
213 "GMBOX RX Avail: 0x%x\n",
214 irq_proc_reg
->gmbox_rx_avail
);
215 ath6kl_dbg(ATH6KL_DBG_IRQ
,
216 "GMBOX lookahead alias 0: 0x%x\n",
217 irq_proc_reg
->rx_gmbox_lkahd_alias
[0]);
218 ath6kl_dbg(ATH6KL_DBG_IRQ
,
219 "GMBOX lookahead alias 1: 0x%x\n",
220 irq_proc_reg
->rx_gmbox_lkahd_alias
[1]);
225 if (irq_enable_reg
!= NULL
) {
226 ath6kl_dbg(ATH6KL_DBG_IRQ
,
227 "Int status Enable: 0x%x\n",
228 irq_enable_reg
->int_status_en
);
229 ath6kl_dbg(ATH6KL_DBG_IRQ
, "Counter Int status Enable: 0x%x\n",
230 irq_enable_reg
->cntr_int_status_en
);
232 ath6kl_dbg(ATH6KL_DBG_IRQ
, "<------------------------------->\n");
235 static void dump_cred_dist(struct htc_endpoint_credit_dist
*ep_dist
)
237 ath6kl_dbg(ATH6KL_DBG_CREDIT
,
238 "--- endpoint: %d svc_id: 0x%X ---\n",
239 ep_dist
->endpoint
, ep_dist
->svc_id
);
240 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " dist_flags : 0x%X\n",
241 ep_dist
->dist_flags
);
242 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_norm : %d\n",
244 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_min : %d\n",
246 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " credits : %d\n",
248 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_assngd : %d\n",
249 ep_dist
->cred_assngd
);
250 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " seek_cred : %d\n",
252 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_sz : %d\n",
254 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_per_msg : %d\n",
255 ep_dist
->cred_per_msg
);
256 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " cred_to_dist : %d\n",
257 ep_dist
->cred_to_dist
);
258 ath6kl_dbg(ATH6KL_DBG_CREDIT
, " txq_depth : %d\n",
259 get_queue_depth(&ep_dist
->htc_ep
->txq
));
260 ath6kl_dbg(ATH6KL_DBG_CREDIT
,
261 "----------------------------------\n");
264 /* FIXME: move to htc.c */
265 void dump_cred_dist_stats(struct htc_target
*target
)
267 struct htc_endpoint_credit_dist
*ep_list
;
269 list_for_each_entry(ep_list
, &target
->cred_dist_list
, list
)
270 dump_cred_dist(ep_list
);
272 ath6kl_dbg(ATH6KL_DBG_CREDIT
,
273 "credit distribution total %d free %d\n",
274 target
->credit_info
->total_avail_credits
,
275 target
->credit_info
->cur_free_credits
);
278 void ath6kl_debug_war(struct ath6kl
*ar
, enum ath6kl_war war
)
281 case ATH6KL_WAR_INVALID_RATE
:
282 ar
->debug
.war_stats
.invalid_rate
++;
287 static ssize_t
read_file_war_stats(struct file
*file
, char __user
*user_buf
,
288 size_t count
, loff_t
*ppos
)
290 struct ath6kl
*ar
= file
->private_data
;
292 unsigned int len
= 0, buf_len
= 1500;
295 buf
= kzalloc(buf_len
, GFP_KERNEL
);
299 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
300 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
302 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n\n",
303 "=================");
304 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10u\n",
305 "Invalid rates", ar
->debug
.war_stats
.invalid_rate
);
307 if (WARN_ON(len
> buf_len
))
310 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
316 static const struct file_operations fops_war_stats
= {
317 .read
= read_file_war_stats
,
319 .owner
= THIS_MODULE
,
320 .llseek
= default_llseek
,
323 void ath6kl_debug_fwlog_event(struct ath6kl
*ar
, const void *buf
, size_t len
)
325 struct ath6kl_fwlog_slot
*slot
;
329 if (WARN_ON(len
> ATH6KL_FWLOG_PAYLOAD_SIZE
))
332 slot_len
= sizeof(*slot
) + ATH6KL_FWLOG_PAYLOAD_SIZE
;
334 skb
= alloc_skb(slot_len
, GFP_KERNEL
);
338 slot
= (struct ath6kl_fwlog_slot
*) skb_put(skb
, slot_len
);
339 slot
->timestamp
= cpu_to_le32(jiffies
);
340 slot
->length
= cpu_to_le32(len
);
341 memcpy(slot
->payload
, buf
, len
);
343 /* Need to pad each record to fixed length ATH6KL_FWLOG_PAYLOAD_SIZE */
344 memset(slot
->payload
+ len
, 0, ATH6KL_FWLOG_PAYLOAD_SIZE
- len
);
346 spin_lock(&ar
->debug
.fwlog_queue
.lock
);
348 __skb_queue_tail(&ar
->debug
.fwlog_queue
, skb
);
349 complete(&ar
->debug
.fwlog_completion
);
351 /* drop oldest entries */
352 while (skb_queue_len(&ar
->debug
.fwlog_queue
) >
353 ATH6KL_FWLOG_MAX_ENTRIES
) {
354 skb
= __skb_dequeue(&ar
->debug
.fwlog_queue
);
358 spin_unlock(&ar
->debug
.fwlog_queue
.lock
);
363 static int ath6kl_fwlog_open(struct inode
*inode
, struct file
*file
)
365 struct ath6kl
*ar
= inode
->i_private
;
367 if (ar
->debug
.fwlog_open
)
370 ar
->debug
.fwlog_open
= true;
372 file
->private_data
= inode
->i_private
;
376 static int ath6kl_fwlog_release(struct inode
*inode
, struct file
*file
)
378 struct ath6kl
*ar
= inode
->i_private
;
380 ar
->debug
.fwlog_open
= false;
385 static ssize_t
ath6kl_fwlog_read(struct file
*file
, char __user
*user_buf
,
386 size_t count
, loff_t
*ppos
)
388 struct ath6kl
*ar
= file
->private_data
;
394 buf
= vmalloc(count
);
398 /* read undelivered logs from firmware */
399 ath6kl_read_fwlogs(ar
);
401 spin_lock(&ar
->debug
.fwlog_queue
.lock
);
403 while ((skb
= __skb_dequeue(&ar
->debug
.fwlog_queue
))) {
404 if (skb
->len
> count
- len
) {
405 /* not enough space, put skb back and leave */
406 __skb_queue_head(&ar
->debug
.fwlog_queue
, skb
);
411 memcpy(buf
+ len
, skb
->data
, skb
->len
);
417 spin_unlock(&ar
->debug
.fwlog_queue
.lock
);
419 /* FIXME: what to do if len == 0? */
421 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
428 static const struct file_operations fops_fwlog
= {
429 .open
= ath6kl_fwlog_open
,
430 .release
= ath6kl_fwlog_release
,
431 .read
= ath6kl_fwlog_read
,
432 .owner
= THIS_MODULE
,
433 .llseek
= default_llseek
,
436 static ssize_t
ath6kl_fwlog_block_read(struct file
*file
,
437 char __user
*user_buf
,
441 struct ath6kl
*ar
= file
->private_data
;
444 size_t len
= 0, not_copied
;
448 buf
= vmalloc(count
);
452 spin_lock(&ar
->debug
.fwlog_queue
.lock
);
454 if (skb_queue_len(&ar
->debug
.fwlog_queue
) == 0) {
455 /* we must init under queue lock */
456 init_completion(&ar
->debug
.fwlog_completion
);
458 spin_unlock(&ar
->debug
.fwlog_queue
.lock
);
460 ret
= wait_for_completion_interruptible(
461 &ar
->debug
.fwlog_completion
);
462 if (ret
== -ERESTARTSYS
) {
467 spin_lock(&ar
->debug
.fwlog_queue
.lock
);
470 while ((skb
= __skb_dequeue(&ar
->debug
.fwlog_queue
))) {
471 if (skb
->len
> count
- len
) {
472 /* not enough space, put skb back and leave */
473 __skb_queue_head(&ar
->debug
.fwlog_queue
, skb
);
478 memcpy(buf
+ len
, skb
->data
, skb
->len
);
484 spin_unlock(&ar
->debug
.fwlog_queue
.lock
);
486 /* FIXME: what to do if len == 0? */
488 not_copied
= copy_to_user(user_buf
, buf
, len
);
489 if (not_copied
!= 0) {
504 static const struct file_operations fops_fwlog_block
= {
505 .open
= ath6kl_fwlog_open
,
506 .release
= ath6kl_fwlog_release
,
507 .read
= ath6kl_fwlog_block_read
,
508 .owner
= THIS_MODULE
,
509 .llseek
= default_llseek
,
512 static ssize_t
ath6kl_fwlog_mask_read(struct file
*file
, char __user
*user_buf
,
513 size_t count
, loff_t
*ppos
)
515 struct ath6kl
*ar
= file
->private_data
;
519 len
= snprintf(buf
, sizeof(buf
), "0x%x\n", ar
->debug
.fwlog_mask
);
521 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
524 static ssize_t
ath6kl_fwlog_mask_write(struct file
*file
,
525 const char __user
*user_buf
,
526 size_t count
, loff_t
*ppos
)
528 struct ath6kl
*ar
= file
->private_data
;
531 ret
= kstrtou32_from_user(user_buf
, count
, 0, &ar
->debug
.fwlog_mask
);
535 ret
= ath6kl_wmi_config_debug_module_cmd(ar
->wmi
,
536 ATH6KL_FWLOG_VALID_MASK
,
537 ar
->debug
.fwlog_mask
);
544 static const struct file_operations fops_fwlog_mask
= {
546 .read
= ath6kl_fwlog_mask_read
,
547 .write
= ath6kl_fwlog_mask_write
,
548 .owner
= THIS_MODULE
,
549 .llseek
= default_llseek
,
552 static ssize_t
read_file_tgt_stats(struct file
*file
, char __user
*user_buf
,
553 size_t count
, loff_t
*ppos
)
555 struct ath6kl
*ar
= file
->private_data
;
556 struct ath6kl_vif
*vif
;
557 struct target_stats
*tgt_stats
;
559 unsigned int len
= 0, buf_len
= 1500;
564 vif
= ath6kl_vif_first(ar
);
568 tgt_stats
= &vif
->target_stats
;
570 buf
= kzalloc(buf_len
, GFP_KERNEL
);
574 if (down_interruptible(&ar
->sem
)) {
579 set_bit(STATS_UPDATE_PEND
, &vif
->flags
);
581 if (ath6kl_wmi_get_stats_cmd(ar
->wmi
, 0)) {
587 left
= wait_event_interruptible_timeout(ar
->event_wq
,
588 !test_bit(STATS_UPDATE_PEND
,
589 &vif
->flags
), WMI_TIMEOUT
);
598 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
599 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
601 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n\n",
602 "=================");
603 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
604 "Ucast packets", tgt_stats
->tx_ucast_pkt
);
605 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
606 "Bcast packets", tgt_stats
->tx_bcast_pkt
);
607 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
608 "Ucast byte", tgt_stats
->tx_ucast_byte
);
609 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
610 "Bcast byte", tgt_stats
->tx_bcast_byte
);
611 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
612 "Rts success cnt", tgt_stats
->tx_rts_success_cnt
);
613 for (i
= 0; i
< 4; i
++)
614 len
+= scnprintf(buf
+ len
, buf_len
- len
,
615 "%18s %d %10llu\n", "PER on ac",
616 i
, tgt_stats
->tx_pkt_per_ac
[i
]);
617 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
618 "Error", tgt_stats
->tx_err
);
619 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
620 "Fail count", tgt_stats
->tx_fail_cnt
);
621 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
622 "Retry count", tgt_stats
->tx_retry_cnt
);
623 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
624 "Multi retry cnt", tgt_stats
->tx_mult_retry_cnt
);
625 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
626 "Rts fail cnt", tgt_stats
->tx_rts_fail_cnt
);
627 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s %10llu\n\n",
628 "TKIP counter measure used",
629 tgt_stats
->tkip_cnter_measures_invoked
);
631 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
633 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
634 "=================");
636 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
637 "Ucast packets", tgt_stats
->rx_ucast_pkt
);
638 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
639 "Ucast Rate", tgt_stats
->rx_ucast_rate
);
640 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
641 "Bcast packets", tgt_stats
->rx_bcast_pkt
);
642 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
643 "Ucast byte", tgt_stats
->rx_ucast_byte
);
644 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
645 "Bcast byte", tgt_stats
->rx_bcast_byte
);
646 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
647 "Fragmented pkt", tgt_stats
->rx_frgment_pkt
);
648 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
649 "Error", tgt_stats
->rx_err
);
650 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
651 "CRC Err", tgt_stats
->rx_crc_err
);
652 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
653 "Key chache miss", tgt_stats
->rx_key_cache_miss
);
654 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
655 "Decrypt Err", tgt_stats
->rx_decrypt_err
);
656 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
657 "Duplicate frame", tgt_stats
->rx_dupl_frame
);
658 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
659 "Tkip Mic failure", tgt_stats
->tkip_local_mic_fail
);
660 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
661 "TKIP format err", tgt_stats
->tkip_fmt_err
);
662 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
663 "CCMP format Err", tgt_stats
->ccmp_fmt_err
);
664 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n\n",
665 "CCMP Replay Err", tgt_stats
->ccmp_replays
);
667 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
668 "Misc Target stats");
669 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s\n",
670 "=================");
671 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
672 "Beacon Miss count", tgt_stats
->cs_bmiss_cnt
);
673 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
674 "Num Connects", tgt_stats
->cs_connect_cnt
);
675 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10llu\n",
676 "Num disconnects", tgt_stats
->cs_discon_cnt
);
677 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
678 "Beacon avg rssi", tgt_stats
->cs_ave_beacon_rssi
);
679 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
680 "ARP pkt received", tgt_stats
->arp_received
);
681 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
682 "ARP pkt matched", tgt_stats
->arp_matched
);
683 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%20s %10d\n",
684 "ARP pkt replied", tgt_stats
->arp_replied
);
689 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
695 static const struct file_operations fops_tgt_stats
= {
696 .read
= read_file_tgt_stats
,
698 .owner
= THIS_MODULE
,
699 .llseek
= default_llseek
,
702 #define print_credit_info(fmt_str, ep_list_field) \
703 (len += scnprintf(buf + len, buf_len - len, fmt_str, \
704 ep_list->ep_list_field))
705 #define CREDIT_INFO_DISPLAY_STRING_LEN 200
706 #define CREDIT_INFO_LEN 128
708 static ssize_t
read_file_credit_dist_stats(struct file
*file
,
709 char __user
*user_buf
,
710 size_t count
, loff_t
*ppos
)
712 struct ath6kl
*ar
= file
->private_data
;
713 struct htc_target
*target
= ar
->htc_target
;
714 struct htc_endpoint_credit_dist
*ep_list
;
716 unsigned int buf_len
, len
= 0;
719 buf_len
= CREDIT_INFO_DISPLAY_STRING_LEN
+
720 get_queue_depth(&target
->cred_dist_list
) * CREDIT_INFO_LEN
;
721 buf
= kzalloc(buf_len
, GFP_KERNEL
);
725 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s%5d\n",
726 "Total Avail Credits: ",
727 target
->credit_info
->total_avail_credits
);
728 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%25s%5d\n",
730 target
->credit_info
->cur_free_credits
);
732 len
+= scnprintf(buf
+ len
, buf_len
- len
,
733 " Epid Flags Cred_norm Cred_min Credits Cred_assngd"
734 " Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
737 list_for_each_entry(ep_list
, &target
->cred_dist_list
, list
) {
738 print_credit_info(" %2d", endpoint
);
739 print_credit_info("%10x", dist_flags
);
740 print_credit_info("%8d", cred_norm
);
741 print_credit_info("%9d", cred_min
);
742 print_credit_info("%9d", credits
);
743 print_credit_info("%10d", cred_assngd
);
744 print_credit_info("%13d", seek_cred
);
745 print_credit_info("%12d", cred_sz
);
746 print_credit_info("%9d", cred_per_msg
);
747 print_credit_info("%14d", cred_to_dist
);
748 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%12d\n",
749 get_queue_depth(&ep_list
->htc_ep
->txq
));
755 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
760 static const struct file_operations fops_credit_dist_stats
= {
761 .read
= read_file_credit_dist_stats
,
763 .owner
= THIS_MODULE
,
764 .llseek
= default_llseek
,
767 static unsigned int print_endpoint_stat(struct htc_target
*target
, char *buf
,
768 unsigned int buf_len
, unsigned int len
,
769 int offset
, const char *name
)
772 struct htc_endpoint_stats
*ep_st
;
775 len
+= scnprintf(buf
+ len
, buf_len
- len
, "%s:", name
);
776 for (i
= 0; i
< ENDPOINT_MAX
; i
++) {
777 ep_st
= &target
->endpoint
[i
].ep_st
;
778 counter
= ((u32
*) ep_st
) + (offset
/ 4);
779 len
+= scnprintf(buf
+ len
, buf_len
- len
, " %u", *counter
);
781 len
+= scnprintf(buf
+ len
, buf_len
- len
, "\n");
786 static ssize_t
ath6kl_endpoint_stats_read(struct file
*file
,
787 char __user
*user_buf
,
788 size_t count
, loff_t
*ppos
)
790 struct ath6kl
*ar
= file
->private_data
;
791 struct htc_target
*target
= ar
->htc_target
;
793 unsigned int buf_len
, len
= 0;
796 buf_len
= sizeof(struct htc_endpoint_stats
) / sizeof(u32
) *
797 (25 + ENDPOINT_MAX
* 11);
798 buf
= kmalloc(buf_len
, GFP_KERNEL
);
802 #define EPSTAT(name) \
804 len = print_endpoint_stat(target, buf, buf_len, len, \
805 offsetof(struct htc_endpoint_stats, \
810 EPSTAT(cred_low_indicate
);
812 EPSTAT(tx_pkt_bundled
);
816 EPSTAT(cred_rpt_from_rx
);
817 EPSTAT(cred_rpt_from_other
);
818 EPSTAT(cred_rpt_ep0
);
819 EPSTAT(cred_from_rx
);
820 EPSTAT(cred_from_other
);
821 EPSTAT(cred_from_ep0
);
827 EPSTAT(rx_bundle_lkahd
);
828 EPSTAT(rx_bundle_from_hdr
);
829 EPSTAT(rx_alloc_thresh_hit
);
830 EPSTAT(rxalloc_thresh_byte
);
836 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
841 static ssize_t
ath6kl_endpoint_stats_write(struct file
*file
,
842 const char __user
*user_buf
,
843 size_t count
, loff_t
*ppos
)
845 struct ath6kl
*ar
= file
->private_data
;
846 struct htc_target
*target
= ar
->htc_target
;
849 struct htc_endpoint_stats
*ep_st
;
851 ret
= kstrtou32_from_user(user_buf
, count
, 0, &val
);
855 for (i
= 0; i
< ENDPOINT_MAX
; i
++) {
856 ep_st
= &target
->endpoint
[i
].ep_st
;
857 memset(ep_st
, 0, sizeof(*ep_st
));
864 static const struct file_operations fops_endpoint_stats
= {
866 .read
= ath6kl_endpoint_stats_read
,
867 .write
= ath6kl_endpoint_stats_write
,
868 .owner
= THIS_MODULE
,
869 .llseek
= default_llseek
,
872 static unsigned long ath6kl_get_num_reg(void)
875 unsigned long n_reg
= 0;
877 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++)
879 (diag_reg
[i
].reg_end
- diag_reg
[i
].reg_start
) / 4 + 1;
884 static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr
)
888 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++) {
889 if (reg_addr
>= diag_reg
[i
].reg_start
&&
890 reg_addr
<= diag_reg
[i
].reg_end
)
897 static ssize_t
ath6kl_regread_read(struct file
*file
, char __user
*user_buf
,
898 size_t count
, loff_t
*ppos
)
900 struct ath6kl
*ar
= file
->private_data
;
902 unsigned int len
= 0;
904 if (ar
->debug
.dbgfs_diag_reg
)
905 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
, "0x%x\n",
906 ar
->debug
.dbgfs_diag_reg
);
908 len
+= scnprintf(buf
+ len
, sizeof(buf
) - len
,
909 "All diag registers\n");
911 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
914 static ssize_t
ath6kl_regread_write(struct file
*file
,
915 const char __user
*user_buf
,
916 size_t count
, loff_t
*ppos
)
918 struct ath6kl
*ar
= file
->private_data
;
919 unsigned long reg_addr
;
921 if (kstrtoul_from_user(user_buf
, count
, 0, ®_addr
))
924 if ((reg_addr
% 4) != 0)
927 if (reg_addr
&& !ath6kl_dbg_is_diag_reg_valid(reg_addr
))
930 ar
->debug
.dbgfs_diag_reg
= reg_addr
;
935 static const struct file_operations fops_diag_reg_read
= {
936 .read
= ath6kl_regread_read
,
937 .write
= ath6kl_regread_write
,
939 .owner
= THIS_MODULE
,
940 .llseek
= default_llseek
,
943 static int ath6kl_regdump_open(struct inode
*inode
, struct file
*file
)
945 struct ath6kl
*ar
= inode
->i_private
;
947 unsigned long int reg_len
;
948 unsigned int len
= 0, n_reg
;
953 /* Dump all the registers if no register is specified */
954 if (!ar
->debug
.dbgfs_diag_reg
)
955 n_reg
= ath6kl_get_num_reg();
959 reg_len
= n_reg
* REG_OUTPUT_LEN_PER_LINE
;
961 reg_len
+= REGTYPE_STR_LEN
;
963 buf
= vmalloc(reg_len
);
968 addr
= ar
->debug
.dbgfs_diag_reg
;
970 status
= ath6kl_diag_read32(ar
,
971 TARG_VTOP(ar
->target_type
, addr
),
976 len
+= scnprintf(buf
+ len
, reg_len
- len
,
977 "0x%06x 0x%08x\n", addr
, le32_to_cpu(reg_val
));
981 for (i
= 0; i
< ARRAY_SIZE(diag_reg
); i
++) {
982 len
+= scnprintf(buf
+ len
, reg_len
- len
,
983 "%s\n", diag_reg
[i
].reg_info
);
984 for (addr
= diag_reg
[i
].reg_start
;
985 addr
<= diag_reg
[i
].reg_end
; addr
+= 4) {
986 status
= ath6kl_diag_read32(ar
,
987 TARG_VTOP(ar
->target_type
, addr
),
992 len
+= scnprintf(buf
+ len
, reg_len
- len
,
994 addr
, le32_to_cpu(reg_val
));
999 file
->private_data
= buf
;
1003 ath6kl_warn("Unable to read memory:%u\n", addr
);
1008 static ssize_t
ath6kl_regdump_read(struct file
*file
, char __user
*user_buf
,
1009 size_t count
, loff_t
*ppos
)
1011 u8
*buf
= file
->private_data
;
1012 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, strlen(buf
));
1015 static int ath6kl_regdump_release(struct inode
*inode
, struct file
*file
)
1017 vfree(file
->private_data
);
1021 static const struct file_operations fops_reg_dump
= {
1022 .open
= ath6kl_regdump_open
,
1023 .read
= ath6kl_regdump_read
,
1024 .release
= ath6kl_regdump_release
,
1025 .owner
= THIS_MODULE
,
1026 .llseek
= default_llseek
,
1029 static ssize_t
ath6kl_lrssi_roam_write(struct file
*file
,
1030 const char __user
*user_buf
,
1031 size_t count
, loff_t
*ppos
)
1033 struct ath6kl
*ar
= file
->private_data
;
1034 unsigned long lrssi_roam_threshold
;
1036 if (kstrtoul_from_user(user_buf
, count
, 0, &lrssi_roam_threshold
))
1039 ar
->lrssi_roam_threshold
= lrssi_roam_threshold
;
1041 ath6kl_wmi_set_roam_lrssi_cmd(ar
->wmi
, ar
->lrssi_roam_threshold
);
1046 static ssize_t
ath6kl_lrssi_roam_read(struct file
*file
,
1047 char __user
*user_buf
,
1048 size_t count
, loff_t
*ppos
)
1050 struct ath6kl
*ar
= file
->private_data
;
1054 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->lrssi_roam_threshold
);
1056 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1059 static const struct file_operations fops_lrssi_roam_threshold
= {
1060 .read
= ath6kl_lrssi_roam_read
,
1061 .write
= ath6kl_lrssi_roam_write
,
1062 .open
= simple_open
,
1063 .owner
= THIS_MODULE
,
1064 .llseek
= default_llseek
,
1067 static ssize_t
ath6kl_regwrite_read(struct file
*file
,
1068 char __user
*user_buf
,
1069 size_t count
, loff_t
*ppos
)
1071 struct ath6kl
*ar
= file
->private_data
;
1073 unsigned int len
= 0;
1075 len
= scnprintf(buf
, sizeof(buf
), "Addr: 0x%x Val: 0x%x\n",
1076 ar
->debug
.diag_reg_addr_wr
, ar
->debug
.diag_reg_val_wr
);
1078 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1081 static ssize_t
ath6kl_regwrite_write(struct file
*file
,
1082 const char __user
*user_buf
,
1083 size_t count
, loff_t
*ppos
)
1085 struct ath6kl
*ar
= file
->private_data
;
1088 unsigned int len
= 0;
1089 u32 reg_addr
, reg_val
;
1091 len
= min(count
, sizeof(buf
) - 1);
1092 if (copy_from_user(buf
, user_buf
, len
))
1098 token
= strsep(&sptr
, "=");
1102 if (kstrtou32(token
, 0, ®_addr
))
1105 if (!ath6kl_dbg_is_diag_reg_valid(reg_addr
))
1108 if (kstrtou32(sptr
, 0, ®_val
))
1111 ar
->debug
.diag_reg_addr_wr
= reg_addr
;
1112 ar
->debug
.diag_reg_val_wr
= reg_val
;
1114 if (ath6kl_diag_write32(ar
, ar
->debug
.diag_reg_addr_wr
,
1115 cpu_to_le32(ar
->debug
.diag_reg_val_wr
)))
1121 static const struct file_operations fops_diag_reg_write
= {
1122 .read
= ath6kl_regwrite_read
,
1123 .write
= ath6kl_regwrite_write
,
1124 .open
= simple_open
,
1125 .owner
= THIS_MODULE
,
1126 .llseek
= default_llseek
,
1129 int ath6kl_debug_roam_tbl_event(struct ath6kl
*ar
, const void *buf
,
1132 const struct wmi_target_roam_tbl
*tbl
;
1135 if (len
< sizeof(*tbl
))
1138 tbl
= (const struct wmi_target_roam_tbl
*) buf
;
1139 num_entries
= le16_to_cpu(tbl
->num_entries
);
1140 if (sizeof(*tbl
) + num_entries
* sizeof(struct wmi_bss_roam_info
) >
1144 if (ar
->debug
.roam_tbl
== NULL
||
1145 ar
->debug
.roam_tbl_len
< (unsigned int) len
) {
1146 kfree(ar
->debug
.roam_tbl
);
1147 ar
->debug
.roam_tbl
= kmalloc(len
, GFP_ATOMIC
);
1148 if (ar
->debug
.roam_tbl
== NULL
)
1152 memcpy(ar
->debug
.roam_tbl
, buf
, len
);
1153 ar
->debug
.roam_tbl_len
= len
;
1155 if (test_bit(ROAM_TBL_PEND
, &ar
->flag
)) {
1156 clear_bit(ROAM_TBL_PEND
, &ar
->flag
);
1157 wake_up(&ar
->event_wq
);
1163 static ssize_t
ath6kl_roam_table_read(struct file
*file
, char __user
*user_buf
,
1164 size_t count
, loff_t
*ppos
)
1166 struct ath6kl
*ar
= file
->private_data
;
1169 struct wmi_target_roam_tbl
*tbl
;
1172 unsigned int len
, buf_len
;
1175 if (down_interruptible(&ar
->sem
))
1178 set_bit(ROAM_TBL_PEND
, &ar
->flag
);
1180 ret
= ath6kl_wmi_get_roam_tbl_cmd(ar
->wmi
);
1186 left
= wait_event_interruptible_timeout(
1187 ar
->event_wq
, !test_bit(ROAM_TBL_PEND
, &ar
->flag
), WMI_TIMEOUT
);
1193 if (ar
->debug
.roam_tbl
== NULL
)
1196 tbl
= (struct wmi_target_roam_tbl
*) ar
->debug
.roam_tbl
;
1197 num_entries
= le16_to_cpu(tbl
->num_entries
);
1199 buf_len
= 100 + num_entries
* 100;
1200 buf
= kzalloc(buf_len
, GFP_KERNEL
);
1204 len
+= scnprintf(buf
+ len
, buf_len
- len
,
1206 "# roam_util bssid rssi rssidt last_rssi util bias\n",
1207 le16_to_cpu(tbl
->roam_mode
));
1209 for (i
= 0; i
< num_entries
; i
++) {
1210 struct wmi_bss_roam_info
*info
= &tbl
->info
[i
];
1211 len
+= scnprintf(buf
+ len
, buf_len
- len
,
1212 "%d %pM %d %d %d %d %d\n",
1213 a_sle32_to_cpu(info
->roam_util
), info
->bssid
,
1214 info
->rssi
, info
->rssidt
, info
->last_rssi
,
1215 info
->util
, info
->bias
);
1221 ret_cnt
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1227 static const struct file_operations fops_roam_table
= {
1228 .read
= ath6kl_roam_table_read
,
1229 .open
= simple_open
,
1230 .owner
= THIS_MODULE
,
1231 .llseek
= default_llseek
,
1234 static ssize_t
ath6kl_force_roam_write(struct file
*file
,
1235 const char __user
*user_buf
,
1236 size_t count
, loff_t
*ppos
)
1238 struct ath6kl
*ar
= file
->private_data
;
1244 len
= min(count
, sizeof(buf
) - 1);
1245 if (copy_from_user(buf
, user_buf
, len
))
1249 if (!mac_pton(buf
, bssid
))
1252 ret
= ath6kl_wmi_force_roam_cmd(ar
->wmi
, bssid
);
1259 static const struct file_operations fops_force_roam
= {
1260 .write
= ath6kl_force_roam_write
,
1261 .open
= simple_open
,
1262 .owner
= THIS_MODULE
,
1263 .llseek
= default_llseek
,
1266 static ssize_t
ath6kl_roam_mode_write(struct file
*file
,
1267 const char __user
*user_buf
,
1268 size_t count
, loff_t
*ppos
)
1270 struct ath6kl
*ar
= file
->private_data
;
1274 enum wmi_roam_mode mode
;
1276 len
= min(count
, sizeof(buf
) - 1);
1277 if (copy_from_user(buf
, user_buf
, len
))
1280 if (len
> 0 && buf
[len
- 1] == '\n')
1281 buf
[len
- 1] = '\0';
1283 if (strcasecmp(buf
, "default") == 0)
1284 mode
= WMI_DEFAULT_ROAM_MODE
;
1285 else if (strcasecmp(buf
, "bssbias") == 0)
1286 mode
= WMI_HOST_BIAS_ROAM_MODE
;
1287 else if (strcasecmp(buf
, "lock") == 0)
1288 mode
= WMI_LOCK_BSS_MODE
;
1292 ret
= ath6kl_wmi_set_roam_mode_cmd(ar
->wmi
, mode
);
1299 static const struct file_operations fops_roam_mode
= {
1300 .write
= ath6kl_roam_mode_write
,
1301 .open
= simple_open
,
1302 .owner
= THIS_MODULE
,
1303 .llseek
= default_llseek
,
1306 void ath6kl_debug_set_keepalive(struct ath6kl
*ar
, u8 keepalive
)
1308 ar
->debug
.keepalive
= keepalive
;
1311 static ssize_t
ath6kl_keepalive_read(struct file
*file
, char __user
*user_buf
,
1312 size_t count
, loff_t
*ppos
)
1314 struct ath6kl
*ar
= file
->private_data
;
1318 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->debug
.keepalive
);
1320 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1323 static ssize_t
ath6kl_keepalive_write(struct file
*file
,
1324 const char __user
*user_buf
,
1325 size_t count
, loff_t
*ppos
)
1327 struct ath6kl
*ar
= file
->private_data
;
1331 ret
= kstrtou8_from_user(user_buf
, count
, 0, &val
);
1335 ret
= ath6kl_wmi_set_keepalive_cmd(ar
->wmi
, 0, val
);
1342 static const struct file_operations fops_keepalive
= {
1343 .open
= simple_open
,
1344 .read
= ath6kl_keepalive_read
,
1345 .write
= ath6kl_keepalive_write
,
1346 .owner
= THIS_MODULE
,
1347 .llseek
= default_llseek
,
1350 void ath6kl_debug_set_disconnect_timeout(struct ath6kl
*ar
, u8 timeout
)
1352 ar
->debug
.disc_timeout
= timeout
;
1355 static ssize_t
ath6kl_disconnect_timeout_read(struct file
*file
,
1356 char __user
*user_buf
,
1357 size_t count
, loff_t
*ppos
)
1359 struct ath6kl
*ar
= file
->private_data
;
1363 len
= snprintf(buf
, sizeof(buf
), "%u\n", ar
->debug
.disc_timeout
);
1365 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1368 static ssize_t
ath6kl_disconnect_timeout_write(struct file
*file
,
1369 const char __user
*user_buf
,
1370 size_t count
, loff_t
*ppos
)
1372 struct ath6kl
*ar
= file
->private_data
;
1376 ret
= kstrtou8_from_user(user_buf
, count
, 0, &val
);
1380 ret
= ath6kl_wmi_disctimeout_cmd(ar
->wmi
, 0, val
);
1387 static const struct file_operations fops_disconnect_timeout
= {
1388 .open
= simple_open
,
1389 .read
= ath6kl_disconnect_timeout_read
,
1390 .write
= ath6kl_disconnect_timeout_write
,
1391 .owner
= THIS_MODULE
,
1392 .llseek
= default_llseek
,
1395 static ssize_t
ath6kl_create_qos_write(struct file
*file
,
1396 const char __user
*user_buf
,
1397 size_t count
, loff_t
*ppos
)
1400 struct ath6kl
*ar
= file
->private_data
;
1401 struct ath6kl_vif
*vif
;
1405 struct wmi_create_pstream_cmd pstream
;
1409 vif
= ath6kl_vif_first(ar
);
1413 len
= min(count
, sizeof(buf
) - 1);
1414 if (copy_from_user(buf
, user_buf
, len
))
1419 token
= strsep(&sptr
, " ");
1422 if (kstrtou8(token
, 0, &pstream
.user_pri
))
1425 token
= strsep(&sptr
, " ");
1428 if (kstrtou8(token
, 0, &pstream
.traffic_direc
))
1431 token
= strsep(&sptr
, " ");
1434 if (kstrtou8(token
, 0, &pstream
.traffic_class
))
1437 token
= strsep(&sptr
, " ");
1440 if (kstrtou8(token
, 0, &pstream
.traffic_type
))
1443 token
= strsep(&sptr
, " ");
1446 if (kstrtou8(token
, 0, &pstream
.voice_psc_cap
))
1449 token
= strsep(&sptr
, " ");
1452 if (kstrtou32(token
, 0, &val32
))
1454 pstream
.min_service_int
= cpu_to_le32(val32
);
1456 token
= strsep(&sptr
, " ");
1459 if (kstrtou32(token
, 0, &val32
))
1461 pstream
.max_service_int
= cpu_to_le32(val32
);
1463 token
= strsep(&sptr
, " ");
1466 if (kstrtou32(token
, 0, &val32
))
1468 pstream
.inactivity_int
= cpu_to_le32(val32
);
1470 token
= strsep(&sptr
, " ");
1473 if (kstrtou32(token
, 0, &val32
))
1475 pstream
.suspension_int
= cpu_to_le32(val32
);
1477 token
= strsep(&sptr
, " ");
1480 if (kstrtou32(token
, 0, &val32
))
1482 pstream
.service_start_time
= cpu_to_le32(val32
);
1484 token
= strsep(&sptr
, " ");
1487 if (kstrtou8(token
, 0, &pstream
.tsid
))
1490 token
= strsep(&sptr
, " ");
1493 if (kstrtou16(token
, 0, &val16
))
1495 pstream
.nominal_msdu
= cpu_to_le16(val16
);
1497 token
= strsep(&sptr
, " ");
1500 if (kstrtou16(token
, 0, &val16
))
1502 pstream
.max_msdu
= cpu_to_le16(val16
);
1504 token
= strsep(&sptr
, " ");
1507 if (kstrtou32(token
, 0, &val32
))
1509 pstream
.min_data_rate
= cpu_to_le32(val32
);
1511 token
= strsep(&sptr
, " ");
1514 if (kstrtou32(token
, 0, &val32
))
1516 pstream
.mean_data_rate
= cpu_to_le32(val32
);
1518 token
= strsep(&sptr
, " ");
1521 if (kstrtou32(token
, 0, &val32
))
1523 pstream
.peak_data_rate
= cpu_to_le32(val32
);
1525 token
= strsep(&sptr
, " ");
1528 if (kstrtou32(token
, 0, &val32
))
1530 pstream
.max_burst_size
= cpu_to_le32(val32
);
1532 token
= strsep(&sptr
, " ");
1535 if (kstrtou32(token
, 0, &val32
))
1537 pstream
.delay_bound
= cpu_to_le32(val32
);
1539 token
= strsep(&sptr
, " ");
1542 if (kstrtou32(token
, 0, &val32
))
1544 pstream
.min_phy_rate
= cpu_to_le32(val32
);
1546 token
= strsep(&sptr
, " ");
1549 if (kstrtou32(token
, 0, &val32
))
1551 pstream
.sba
= cpu_to_le32(val32
);
1553 token
= strsep(&sptr
, " ");
1556 if (kstrtou32(token
, 0, &val32
))
1558 pstream
.medium_time
= cpu_to_le32(val32
);
1560 pstream
.nominal_phy
= le32_to_cpu(pstream
.min_phy_rate
) / 1000000;
1562 ath6kl_wmi_create_pstream_cmd(ar
->wmi
, vif
->fw_vif_idx
, &pstream
);
1567 static const struct file_operations fops_create_qos
= {
1568 .write
= ath6kl_create_qos_write
,
1569 .open
= simple_open
,
1570 .owner
= THIS_MODULE
,
1571 .llseek
= default_llseek
,
1574 static ssize_t
ath6kl_delete_qos_write(struct file
*file
,
1575 const char __user
*user_buf
,
1576 size_t count
, loff_t
*ppos
)
1579 struct ath6kl
*ar
= file
->private_data
;
1580 struct ath6kl_vif
*vif
;
1587 vif
= ath6kl_vif_first(ar
);
1591 len
= min(count
, sizeof(buf
) - 1);
1592 if (copy_from_user(buf
, user_buf
, len
))
1597 token
= strsep(&sptr
, " ");
1600 if (kstrtou8(token
, 0, &traffic_class
))
1603 token
= strsep(&sptr
, " ");
1606 if (kstrtou8(token
, 0, &tsid
))
1609 ath6kl_wmi_delete_pstream_cmd(ar
->wmi
, vif
->fw_vif_idx
,
1610 traffic_class
, tsid
);
1615 static const struct file_operations fops_delete_qos
= {
1616 .write
= ath6kl_delete_qos_write
,
1617 .open
= simple_open
,
1618 .owner
= THIS_MODULE
,
1619 .llseek
= default_llseek
,
1622 static ssize_t
ath6kl_bgscan_int_write(struct file
*file
,
1623 const char __user
*user_buf
,
1624 size_t count
, loff_t
*ppos
)
1626 struct ath6kl
*ar
= file
->private_data
;
1627 struct ath6kl_vif
*vif
;
1632 vif
= ath6kl_vif_first(ar
);
1636 len
= min(count
, sizeof(buf
) - 1);
1637 if (copy_from_user(buf
, user_buf
, len
))
1641 if (kstrtou16(buf
, 0, &bgscan_int
))
1644 if (bgscan_int
== 0)
1645 bgscan_int
= 0xffff;
1647 vif
->bg_scan_period
= bgscan_int
;
1649 ath6kl_wmi_scanparams_cmd(ar
->wmi
, 0, 0, 0, bgscan_int
, 0, 0, 0, 3,
1655 static const struct file_operations fops_bgscan_int
= {
1656 .write
= ath6kl_bgscan_int_write
,
1657 .open
= simple_open
,
1658 .owner
= THIS_MODULE
,
1659 .llseek
= default_llseek
,
1662 static ssize_t
ath6kl_listen_int_write(struct file
*file
,
1663 const char __user
*user_buf
,
1664 size_t count
, loff_t
*ppos
)
1666 struct ath6kl
*ar
= file
->private_data
;
1667 struct ath6kl_vif
*vif
;
1668 u16 listen_interval
;
1672 vif
= ath6kl_vif_first(ar
);
1676 len
= min(count
, sizeof(buf
) - 1);
1677 if (copy_from_user(buf
, user_buf
, len
))
1681 if (kstrtou16(buf
, 0, &listen_interval
))
1684 if ((listen_interval
< 15) || (listen_interval
> 3000))
1687 vif
->listen_intvl_t
= listen_interval
;
1688 ath6kl_wmi_listeninterval_cmd(ar
->wmi
, vif
->fw_vif_idx
,
1689 vif
->listen_intvl_t
, 0);
1694 static ssize_t
ath6kl_listen_int_read(struct file
*file
,
1695 char __user
*user_buf
,
1696 size_t count
, loff_t
*ppos
)
1698 struct ath6kl
*ar
= file
->private_data
;
1699 struct ath6kl_vif
*vif
;
1703 vif
= ath6kl_vif_first(ar
);
1707 len
= scnprintf(buf
, sizeof(buf
), "%u\n", vif
->listen_intvl_t
);
1709 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
1712 static const struct file_operations fops_listen_int
= {
1713 .read
= ath6kl_listen_int_read
,
1714 .write
= ath6kl_listen_int_write
,
1715 .open
= simple_open
,
1716 .owner
= THIS_MODULE
,
1717 .llseek
= default_llseek
,
1720 static ssize_t
ath6kl_power_params_write(struct file
*file
,
1721 const char __user
*user_buf
,
1722 size_t count
, loff_t
*ppos
)
1724 struct ath6kl
*ar
= file
->private_data
;
1726 unsigned int len
= 0;
1728 u16 idle_period
, ps_poll_num
, dtim
,
1731 len
= min(count
, sizeof(buf
) - 1);
1732 if (copy_from_user(buf
, user_buf
, len
))
1737 token
= strsep(&sptr
, " ");
1740 if (kstrtou16(token
, 0, &idle_period
))
1743 token
= strsep(&sptr
, " ");
1746 if (kstrtou16(token
, 0, &ps_poll_num
))
1749 token
= strsep(&sptr
, " ");
1752 if (kstrtou16(token
, 0, &dtim
))
1755 token
= strsep(&sptr
, " ");
1758 if (kstrtou16(token
, 0, &tx_wakeup
))
1761 token
= strsep(&sptr
, " ");
1764 if (kstrtou16(token
, 0, &num_tx
))
1767 ath6kl_wmi_pmparams_cmd(ar
->wmi
, 0, idle_period
, ps_poll_num
,
1768 dtim
, tx_wakeup
, num_tx
, 0);
1773 static const struct file_operations fops_power_params
= {
1774 .write
= ath6kl_power_params_write
,
1775 .open
= simple_open
,
1776 .owner
= THIS_MODULE
,
1777 .llseek
= default_llseek
,
1780 void ath6kl_debug_init(struct ath6kl
*ar
)
1782 skb_queue_head_init(&ar
->debug
.fwlog_queue
);
1783 init_completion(&ar
->debug
.fwlog_completion
);
1786 * Actually we are lying here but don't know how to read the mask
1787 * value from the firmware.
1789 ar
->debug
.fwlog_mask
= 0;
1793 * Initialisation needs to happen in two stages as fwlog events can come
1794 * before cfg80211 is initialised, and debugfs depends on cfg80211
1797 int ath6kl_debug_init_fs(struct ath6kl
*ar
)
1799 ar
->debugfs_phy
= debugfs_create_dir("ath6kl",
1800 ar
->wiphy
->debugfsdir
);
1801 if (!ar
->debugfs_phy
)
1804 debugfs_create_file("tgt_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1807 if (ar
->hif_type
== ATH6KL_HIF_TYPE_SDIO
)
1808 debugfs_create_file("credit_dist_stats", S_IRUSR
,
1809 ar
->debugfs_phy
, ar
,
1810 &fops_credit_dist_stats
);
1812 debugfs_create_file("endpoint_stats", S_IRUSR
| S_IWUSR
,
1813 ar
->debugfs_phy
, ar
, &fops_endpoint_stats
);
1815 debugfs_create_file("fwlog", S_IRUSR
, ar
->debugfs_phy
, ar
,
1818 debugfs_create_file("fwlog_block", S_IRUSR
, ar
->debugfs_phy
, ar
,
1821 debugfs_create_file("fwlog_mask", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
,
1822 ar
, &fops_fwlog_mask
);
1824 debugfs_create_file("reg_addr", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
, ar
,
1825 &fops_diag_reg_read
);
1827 debugfs_create_file("reg_dump", S_IRUSR
, ar
->debugfs_phy
, ar
,
1830 debugfs_create_file("lrssi_roam_threshold", S_IRUSR
| S_IWUSR
,
1831 ar
->debugfs_phy
, ar
, &fops_lrssi_roam_threshold
);
1833 debugfs_create_file("reg_write", S_IRUSR
| S_IWUSR
,
1834 ar
->debugfs_phy
, ar
, &fops_diag_reg_write
);
1836 debugfs_create_file("war_stats", S_IRUSR
, ar
->debugfs_phy
, ar
,
1839 debugfs_create_file("roam_table", S_IRUSR
, ar
->debugfs_phy
, ar
,
1842 debugfs_create_file("force_roam", S_IWUSR
, ar
->debugfs_phy
, ar
,
1845 debugfs_create_file("roam_mode", S_IWUSR
, ar
->debugfs_phy
, ar
,
1848 debugfs_create_file("keepalive", S_IRUSR
| S_IWUSR
, ar
->debugfs_phy
, ar
,
1851 debugfs_create_file("disconnect_timeout", S_IRUSR
| S_IWUSR
,
1852 ar
->debugfs_phy
, ar
, &fops_disconnect_timeout
);
1854 debugfs_create_file("create_qos", S_IWUSR
, ar
->debugfs_phy
, ar
,
1857 debugfs_create_file("delete_qos", S_IWUSR
, ar
->debugfs_phy
, ar
,
1860 debugfs_create_file("bgscan_interval", S_IWUSR
,
1861 ar
->debugfs_phy
, ar
, &fops_bgscan_int
);
1863 debugfs_create_file("listen_interval", S_IRUSR
| S_IWUSR
,
1864 ar
->debugfs_phy
, ar
, &fops_listen_int
);
1866 debugfs_create_file("power_params", S_IWUSR
, ar
->debugfs_phy
, ar
,
1867 &fops_power_params
);
1872 void ath6kl_debug_cleanup(struct ath6kl
*ar
)
1874 skb_queue_purge(&ar
->debug
.fwlog_queue
);
1875 complete(&ar
->debug
.fwlog_completion
);
1876 kfree(ar
->debug
.roam_tbl
);