2 * Copyright (c) 2012 Qualcomm Atheros, 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.
17 #include <linux/module.h>
18 #include <linux/debugfs.h>
19 #include <linux/seq_file.h>
20 #include <linux/pci.h>
21 #include <linux/rtnetlink.h>
22 #include <linux/power_supply.h>
27 /* Nasty hack. Better have per device instances */
29 static u32 dbg_txdesc_index
;
30 static u32 dbg_vring_index
; /* 24+ for Rx, 0..23 for Tx */
32 static void wil_print_vring(struct seq_file
*s
, struct wil6210_priv
*wil
,
33 const char *name
, struct vring
*vring
,
36 void __iomem
*x
= wmi_addr(wil
, vring
->hwtail
);
38 seq_printf(s
, "VRING %s = {\n", name
);
39 seq_printf(s
, " pa = %pad\n", &vring
->pa
);
40 seq_printf(s
, " va = 0x%p\n", vring
->va
);
41 seq_printf(s
, " size = %d\n", vring
->size
);
42 seq_printf(s
, " swtail = %d\n", vring
->swtail
);
43 seq_printf(s
, " swhead = %d\n", vring
->swhead
);
44 seq_printf(s
, " hwtail = [0x%08x] -> ", vring
->hwtail
);
46 seq_printf(s
, "0x%08x\n", ioread32(x
));
48 seq_printf(s
, "???\n");
50 if (vring
->va
&& (vring
->size
< 1025)) {
52 for (i
= 0; i
< vring
->size
; i
++) {
53 volatile struct vring_tx_desc
*d
= &vring
->va
[i
].tx
;
54 if ((i
% 64) == 0 && (i
!= 0))
56 seq_printf(s
, "%c", (d
->dma
.status
& BIT(0)) ?
57 _s
: (vring
->ctx
[i
].skb
? _h
: 'h'));
64 static int wil_vring_debugfs_show(struct seq_file
*s
, void *data
)
67 struct wil6210_priv
*wil
= s
->private;
69 wil_print_vring(s
, wil
, "rx", &wil
->vring_rx
, 'S', '_');
71 for (i
= 0; i
< ARRAY_SIZE(wil
->vring_tx
); i
++) {
72 struct vring
*vring
= &(wil
->vring_tx
[i
]);
73 struct vring_tx_data
*txdata
= &wil
->vring_tx_data
[i
];
76 int cid
= wil
->vring2cid_tid
[i
][0];
77 int tid
= wil
->vring2cid_tid
[i
][1];
78 u32 swhead
= vring
->swhead
;
79 u32 swtail
= vring
->swtail
;
80 int used
= (vring
->size
+ swhead
- swtail
)
82 int avail
= vring
->size
- used
- 1;
84 /* performance monitoring */
85 cycles_t now
= get_cycles();
86 cycles_t idle
= txdata
->idle
* 100;
87 cycles_t total
= now
- txdata
->begin
;
93 snprintf(name
, sizeof(name
), "tx_%2d", i
);
95 seq_printf(s
, "\n%pM CID %d TID %d [%3d|%3d] idle %3d%%\n",
96 wil
->sta
[cid
].addr
, cid
, tid
, used
, avail
,
99 wil_print_vring(s
, wil
, name
, vring
, '_', 'H');
106 static int wil_vring_seq_open(struct inode
*inode
, struct file
*file
)
108 return single_open(file
, wil_vring_debugfs_show
, inode
->i_private
);
111 static const struct file_operations fops_vring
= {
112 .open
= wil_vring_seq_open
,
113 .release
= single_release
,
118 static void wil_print_ring(struct seq_file
*s
, const char *prefix
,
121 struct wil6210_priv
*wil
= s
->private;
122 struct wil6210_mbox_ring r
;
126 wil_memcpy_fromio_32(&r
, off
, sizeof(r
));
127 wil_mbox_ring_le2cpus(&r
);
129 * we just read memory block from NIC. This memory may be
130 * garbage. Check validity before using it.
132 rsize
= r
.size
/ sizeof(struct wil6210_mbox_ring_desc
);
134 seq_printf(s
, "ring %s = {\n", prefix
);
135 seq_printf(s
, " base = 0x%08x\n", r
.base
);
136 seq_printf(s
, " size = 0x%04x bytes -> %d entries\n", r
.size
, rsize
);
137 seq_printf(s
, " tail = 0x%08x\n", r
.tail
);
138 seq_printf(s
, " head = 0x%08x\n", r
.head
);
139 seq_printf(s
, " entry size = %d\n", r
.entry_size
);
141 if (r
.size
% sizeof(struct wil6210_mbox_ring_desc
)) {
142 seq_printf(s
, " ??? size is not multiple of %zd, garbage?\n",
143 sizeof(struct wil6210_mbox_ring_desc
));
147 if (!wmi_addr(wil
, r
.base
) ||
148 !wmi_addr(wil
, r
.tail
) ||
149 !wmi_addr(wil
, r
.head
)) {
150 seq_printf(s
, " ??? pointers are garbage?\n");
154 for (i
= 0; i
< rsize
; i
++) {
155 struct wil6210_mbox_ring_desc d
;
156 struct wil6210_mbox_hdr hdr
;
157 size_t delta
= i
* sizeof(d
);
158 void __iomem
*x
= wil
->csr
+ HOSTADDR(r
.base
) + delta
;
160 wil_memcpy_fromio_32(&d
, x
, sizeof(d
));
162 seq_printf(s
, " [%2x] %s %s%s 0x%08x", i
,
164 (r
.tail
- r
.base
== delta
) ? "t" : " ",
165 (r
.head
- r
.base
== delta
) ? "h" : " ",
166 le32_to_cpu(d
.addr
));
167 if (0 == wmi_read_hdr(wil
, d
.addr
, &hdr
)) {
168 u16 len
= le16_to_cpu(hdr
.len
);
169 seq_printf(s
, " -> %04x %04x %04x %02x\n",
170 le16_to_cpu(hdr
.seq
), len
,
171 le16_to_cpu(hdr
.type
), hdr
.flags
);
172 if (len
<= MAX_MBOXITEM_SIZE
) {
174 char printbuf
[16 * 3 + 2];
175 unsigned char databuf
[MAX_MBOXITEM_SIZE
];
176 void __iomem
*src
= wmi_buffer(wil
, d
.addr
) +
177 sizeof(struct wil6210_mbox_hdr
);
179 * No need to check @src for validity -
180 * we already validated @d.addr while
183 wil_memcpy_fromio_32(databuf
, src
, len
);
185 int l
= min(len
- n
, 16);
186 hex_dump_to_buffer(databuf
+ n
, l
,
190 seq_printf(s
, " : %s\n", printbuf
);
199 seq_printf(s
, "}\n");
202 static int wil_mbox_debugfs_show(struct seq_file
*s
, void *data
)
204 struct wil6210_priv
*wil
= s
->private;
206 wil_print_ring(s
, "tx", wil
->csr
+ HOST_MBOX
+
207 offsetof(struct wil6210_mbox_ctl
, tx
));
208 wil_print_ring(s
, "rx", wil
->csr
+ HOST_MBOX
+
209 offsetof(struct wil6210_mbox_ctl
, rx
));
214 static int wil_mbox_seq_open(struct inode
*inode
, struct file
*file
)
216 return single_open(file
, wil_mbox_debugfs_show
, inode
->i_private
);
219 static const struct file_operations fops_mbox
= {
220 .open
= wil_mbox_seq_open
,
221 .release
= single_release
,
226 static int wil_debugfs_iomem_x32_set(void *data
, u64 val
)
228 iowrite32(val
, (void __iomem
*)data
);
229 wmb(); /* make sure write propagated to HW */
234 static int wil_debugfs_iomem_x32_get(void *data
, u64
*val
)
236 *val
= ioread32((void __iomem
*)data
);
241 DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32
, wil_debugfs_iomem_x32_get
,
242 wil_debugfs_iomem_x32_set
, "0x%08llx\n");
244 static struct dentry
*wil_debugfs_create_iomem_x32(const char *name
,
246 struct dentry
*parent
,
249 return debugfs_create_file(name
, mode
, parent
, (void * __force
)value
,
253 static int wil_debugfs_ulong_set(void *data
, u64 val
)
255 *(ulong
*)data
= val
;
258 static int wil_debugfs_ulong_get(void *data
, u64
*val
)
260 *val
= *(ulong
*)data
;
263 DEFINE_SIMPLE_ATTRIBUTE(wil_fops_ulong
, wil_debugfs_ulong_get
,
264 wil_debugfs_ulong_set
, "%llu\n");
266 static struct dentry
*wil_debugfs_create_ulong(const char *name
, umode_t mode
,
267 struct dentry
*parent
,
270 return debugfs_create_file(name
, mode
, parent
, value
, &wil_fops_ulong
);
273 static int wil6210_debugfs_create_ISR(struct wil6210_priv
*wil
,
275 struct dentry
*parent
, u32 off
)
277 struct dentry
*d
= debugfs_create_dir(name
, parent
);
279 if (IS_ERR_OR_NULL(d
))
282 wil_debugfs_create_iomem_x32("ICC", S_IRUGO
| S_IWUSR
, d
,
284 wil_debugfs_create_iomem_x32("ICR", S_IRUGO
| S_IWUSR
, d
,
286 wil_debugfs_create_iomem_x32("ICM", S_IRUGO
| S_IWUSR
, d
,
288 wil_debugfs_create_iomem_x32("ICS", S_IWUSR
, d
,
289 wil
->csr
+ off
+ 12);
290 wil_debugfs_create_iomem_x32("IMV", S_IRUGO
| S_IWUSR
, d
,
291 wil
->csr
+ off
+ 16);
292 wil_debugfs_create_iomem_x32("IMS", S_IWUSR
, d
,
293 wil
->csr
+ off
+ 20);
294 wil_debugfs_create_iomem_x32("IMC", S_IWUSR
, d
,
295 wil
->csr
+ off
+ 24);
300 static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv
*wil
,
301 struct dentry
*parent
)
303 struct dentry
*d
= debugfs_create_dir("PSEUDO_ISR", parent
);
305 if (IS_ERR_OR_NULL(d
))
308 wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO
, d
, wil
->csr
+
309 HOSTADDR(RGF_DMA_PSEUDO_CAUSE
));
310 wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO
, d
, wil
->csr
+
311 HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW
));
312 wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO
, d
, wil
->csr
+
313 HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW
));
318 static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv
*wil
,
319 struct dentry
*parent
)
321 struct dentry
*d
= debugfs_create_dir("ITR_CNT", parent
);
323 if (IS_ERR_OR_NULL(d
))
326 wil_debugfs_create_iomem_x32("TRSH", S_IRUGO
| S_IWUSR
, d
, wil
->csr
+
327 HOSTADDR(RGF_DMA_ITR_CNT_TRSH
));
328 wil_debugfs_create_iomem_x32("DATA", S_IRUGO
| S_IWUSR
, d
, wil
->csr
+
329 HOSTADDR(RGF_DMA_ITR_CNT_DATA
));
330 wil_debugfs_create_iomem_x32("CTL", S_IRUGO
| S_IWUSR
, d
, wil
->csr
+
331 HOSTADDR(RGF_DMA_ITR_CNT_CRL
));
336 static int wil_memread_debugfs_show(struct seq_file
*s
, void *data
)
338 struct wil6210_priv
*wil
= s
->private;
339 void __iomem
*a
= wmi_buffer(wil
, cpu_to_le32(mem_addr
));
342 seq_printf(s
, "[0x%08x] = 0x%08x\n", mem_addr
, ioread32(a
));
344 seq_printf(s
, "[0x%08x] = INVALID\n", mem_addr
);
349 static int wil_memread_seq_open(struct inode
*inode
, struct file
*file
)
351 return single_open(file
, wil_memread_debugfs_show
, inode
->i_private
);
354 static const struct file_operations fops_memread
= {
355 .open
= wil_memread_seq_open
,
356 .release
= single_release
,
361 static ssize_t
wil_read_file_ioblob(struct file
*file
, char __user
*user_buf
,
362 size_t count
, loff_t
*ppos
)
364 enum { max_count
= 4096 };
365 struct debugfs_blob_wrapper
*blob
= file
->private_data
;
367 size_t available
= blob
->size
;
374 if (pos
>= available
|| !count
)
377 if (count
> available
- pos
)
378 count
= available
- pos
;
379 if (count
> max_count
)
382 buf
= kmalloc(count
, GFP_KERNEL
);
386 wil_memcpy_fromio_32(buf
, (const volatile void __iomem
*)blob
->data
+
389 ret
= copy_to_user(user_buf
, buf
, count
);
400 static const struct file_operations fops_ioblob
= {
401 .read
= wil_read_file_ioblob
,
403 .llseek
= default_llseek
,
407 struct dentry
*wil_debugfs_create_ioblob(const char *name
,
409 struct dentry
*parent
,
410 struct debugfs_blob_wrapper
*blob
)
412 return debugfs_create_file(name
, mode
, parent
, blob
, &fops_ioblob
);
415 static ssize_t
wil_write_file_reset(struct file
*file
, const char __user
*buf
,
416 size_t len
, loff_t
*ppos
)
418 struct wil6210_priv
*wil
= file
->private_data
;
419 struct net_device
*ndev
= wil_to_ndev(wil
);
423 * this code does NOT sync device state with the rest of system
424 * use with care, debug only!!!
428 ndev
->flags
&= ~IFF_UP
;
435 static const struct file_operations fops_reset
= {
436 .write
= wil_write_file_reset
,
439 /*---write channel 1..4 to rxon for it, 0 to rxoff---*/
440 static ssize_t
wil_write_file_rxon(struct file
*file
, const char __user
*buf
,
441 size_t len
, loff_t
*ppos
)
443 struct wil6210_priv
*wil
= file
->private_data
;
448 char *kbuf
= kmalloc(len
+ 1, GFP_KERNEL
);
451 if (copy_from_user(kbuf
, buf
, len
)) {
457 rc
= kstrtol(kbuf
, 0, &channel
);
462 if ((channel
< 0) || (channel
> 4)) {
463 wil_err(wil
, "Invalid channel %ld\n", channel
);
469 rc
= wmi_set_channel(wil
, (int)channel
);
474 rc
= wmi_rxon(wil
, on
);
481 static const struct file_operations fops_rxon
= {
482 .write
= wil_write_file_rxon
,
486 /* Write mgmt frame to this file to send it */
487 static ssize_t
wil_write_file_txmgmt(struct file
*file
, const char __user
*buf
,
488 size_t len
, loff_t
*ppos
)
490 struct wil6210_priv
*wil
= file
->private_data
;
491 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
492 struct wireless_dev
*wdev
= wil_to_wdev(wil
);
493 struct cfg80211_mgmt_tx_params params
;
496 void *frame
= kmalloc(len
, GFP_KERNEL
);
500 if (copy_from_user(frame
, buf
, len
))
505 params
.chan
= wdev
->preset_chandef
.chan
;
507 rc
= wil_cfg80211_mgmt_tx(wiphy
, wdev
, ¶ms
, NULL
);
510 wil_info(wil
, "%s() -> %d\n", __func__
, rc
);
515 static const struct file_operations fops_txmgmt
= {
516 .write
= wil_write_file_txmgmt
,
520 /* Write WMI command (w/o mbox header) to this file to send it
521 * WMI starts from wil6210_mbox_hdr_wmi header
523 static ssize_t
wil_write_file_wmi(struct file
*file
, const char __user
*buf
,
524 size_t len
, loff_t
*ppos
)
526 struct wil6210_priv
*wil
= file
->private_data
;
527 struct wil6210_mbox_hdr_wmi
*wmi
;
529 int cmdlen
= len
- sizeof(struct wil6210_mbox_hdr_wmi
);
536 wmi
= kmalloc(len
, GFP_KERNEL
);
540 rc
= simple_write_to_buffer(wmi
, len
, ppos
, buf
, len
);
545 cmdid
= le16_to_cpu(wmi
->id
);
547 rc1
= wmi_send(wil
, cmdid
, cmd
, cmdlen
);
550 wil_info(wil
, "%s(0x%04x[%d]) -> %d\n", __func__
, cmdid
, cmdlen
, rc1
);
555 static const struct file_operations fops_wmi
= {
556 .write
= wil_write_file_wmi
,
560 static void wil_seq_hexdump(struct seq_file
*s
, void *p
, int len
,
563 char printbuf
[16 * 3 + 2];
566 int l
= min(len
- i
, 16);
567 hex_dump_to_buffer(p
+ i
, l
, 16, 1, printbuf
,
568 sizeof(printbuf
), false);
569 seq_printf(s
, "%s%s\n", prefix
, printbuf
);
574 static void wil_seq_print_skb(struct seq_file
*s
, struct sk_buff
*skb
)
577 int len
= skb_headlen(skb
);
579 int nr_frags
= skb_shinfo(skb
)->nr_frags
;
581 seq_printf(s
, " len = %d\n", len
);
582 wil_seq_hexdump(s
, p
, len
, " : ");
585 seq_printf(s
, " nr_frags = %d\n", nr_frags
);
586 for (i
= 0; i
< nr_frags
; i
++) {
587 const struct skb_frag_struct
*frag
=
588 &skb_shinfo(skb
)->frags
[i
];
590 len
= skb_frag_size(frag
);
591 p
= skb_frag_address_safe(frag
);
592 seq_printf(s
, " [%2d] : len = %d\n", i
, len
);
593 wil_seq_hexdump(s
, p
, len
, " : ");
598 /*---------Tx/Rx descriptor------------*/
599 static int wil_txdesc_debugfs_show(struct seq_file
*s
, void *data
)
601 struct wil6210_priv
*wil
= s
->private;
603 bool tx
= (dbg_vring_index
< WIL6210_MAX_TX_RINGS
);
605 vring
= &(wil
->vring_tx
[dbg_vring_index
]);
607 vring
= &wil
->vring_rx
;
611 seq_printf(s
, "No Tx[%2d] VRING\n", dbg_vring_index
);
613 seq_puts(s
, "No Rx VRING\n");
617 if (dbg_txdesc_index
< vring
->size
) {
618 /* use struct vring_tx_desc for Rx as well,
619 * only field used, .dma.length, is the same
621 volatile struct vring_tx_desc
*d
=
622 &(vring
->va
[dbg_txdesc_index
].tx
);
623 volatile u32
*u
= (volatile u32
*)d
;
624 struct sk_buff
*skb
= vring
->ctx
[dbg_txdesc_index
].skb
;
627 seq_printf(s
, "Tx[%2d][%3d] = {\n", dbg_vring_index
,
630 seq_printf(s
, "Rx[%3d] = {\n", dbg_txdesc_index
);
631 seq_printf(s
, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
632 u
[0], u
[1], u
[2], u
[3]);
633 seq_printf(s
, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
634 u
[4], u
[5], u
[6], u
[7]);
635 seq_printf(s
, " SKB = 0x%p\n", skb
);
639 wil_seq_print_skb(s
, skb
);
642 seq_printf(s
, "}\n");
645 seq_printf(s
, "[%2d] TxDesc index (%d) >= size (%d)\n",
646 dbg_vring_index
, dbg_txdesc_index
,
649 seq_printf(s
, "RxDesc index (%d) >= size (%d)\n",
650 dbg_txdesc_index
, vring
->size
);
656 static int wil_txdesc_seq_open(struct inode
*inode
, struct file
*file
)
658 return single_open(file
, wil_txdesc_debugfs_show
, inode
->i_private
);
661 static const struct file_operations fops_txdesc
= {
662 .open
= wil_txdesc_seq_open
,
663 .release
= single_release
,
668 /*---------beamforming------------*/
669 static int wil_bf_debugfs_show(struct seq_file
*s
, void *data
)
671 struct wil6210_priv
*wil
= s
->private;
675 "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n",
676 wil
->stats
.tsf
, wil
->stats
.bf_mcs
,
677 wil
->stats
.my_rx_sector
, wil
->stats
.my_tx_sector
,
678 wil
->stats
.peer_rx_sector
, wil
->stats
.peer_tx_sector
);
682 static int wil_bf_seq_open(struct inode
*inode
, struct file
*file
)
684 return single_open(file
, wil_bf_debugfs_show
, inode
->i_private
);
687 static const struct file_operations fops_bf
= {
688 .open
= wil_bf_seq_open
,
689 .release
= single_release
,
693 /*---------SSID------------*/
694 static ssize_t
wil_read_file_ssid(struct file
*file
, char __user
*user_buf
,
695 size_t count
, loff_t
*ppos
)
697 struct wil6210_priv
*wil
= file
->private_data
;
698 struct wireless_dev
*wdev
= wil_to_wdev(wil
);
700 return simple_read_from_buffer(user_buf
, count
, ppos
,
701 wdev
->ssid
, wdev
->ssid_len
);
704 static ssize_t
wil_write_file_ssid(struct file
*file
, const char __user
*buf
,
705 size_t count
, loff_t
*ppos
)
707 struct wil6210_priv
*wil
= file
->private_data
;
708 struct wireless_dev
*wdev
= wil_to_wdev(wil
);
709 struct net_device
*ndev
= wil_to_ndev(wil
);
712 wil_err(wil
, "Unable to set SSID substring from [%d]\n",
717 if (count
> sizeof(wdev
->ssid
)) {
718 wil_err(wil
, "SSID too long, len = %d\n", (int)count
);
721 if (netif_running(ndev
)) {
722 wil_err(wil
, "Unable to change SSID on running interface\n");
726 wdev
->ssid_len
= count
;
727 return simple_write_to_buffer(wdev
->ssid
, wdev
->ssid_len
, ppos
,
731 static const struct file_operations fops_ssid
= {
732 .read
= wil_read_file_ssid
,
733 .write
= wil_write_file_ssid
,
737 /*---------temp------------*/
738 static void print_temp(struct seq_file
*s
, const char *prefix
, u32 t
)
743 seq_printf(s
, "%s N/A\n", prefix
);
746 seq_printf(s
, "%s %d.%03d\n", prefix
, t
/ 1000, t
% 1000);
751 static int wil_temp_debugfs_show(struct seq_file
*s
, void *data
)
753 struct wil6210_priv
*wil
= s
->private;
756 int rc
= wmi_get_temperature(wil
, &t_m
, &t_r
);
758 seq_printf(s
, "Failed\n");
762 print_temp(s
, "T_mac =", t_m
);
763 print_temp(s
, "T_radio =", t_r
);
768 static int wil_temp_seq_open(struct inode
*inode
, struct file
*file
)
770 return single_open(file
, wil_temp_debugfs_show
, inode
->i_private
);
773 static const struct file_operations fops_temp
= {
774 .open
= wil_temp_seq_open
,
775 .release
= single_release
,
780 /*---------freq------------*/
781 static int wil_freq_debugfs_show(struct seq_file
*s
, void *data
)
783 struct wil6210_priv
*wil
= s
->private;
784 struct wireless_dev
*wdev
= wil_to_wdev(wil
);
785 u16 freq
= wdev
->chandef
.chan
? wdev
->chandef
.chan
->center_freq
: 0;
787 seq_printf(s
, "Freq = %d\n", freq
);
792 static int wil_freq_seq_open(struct inode
*inode
, struct file
*file
)
794 return single_open(file
, wil_freq_debugfs_show
, inode
->i_private
);
797 static const struct file_operations fops_freq
= {
798 .open
= wil_freq_seq_open
,
799 .release
= single_release
,
804 /*---------link------------*/
805 static int wil_link_debugfs_show(struct seq_file
*s
, void *data
)
807 struct wil6210_priv
*wil
= s
->private;
808 struct station_info sinfo
;
811 for (i
= 0; i
< ARRAY_SIZE(wil
->sta
); i
++) {
812 struct wil_sta_info
*p
= &wil
->sta
[i
];
813 char *status
= "unknown";
818 case wil_sta_conn_pending
:
821 case wil_sta_connected
:
822 status
= "connected";
825 seq_printf(s
, "[%d] %pM %s%s\n", i
, p
->addr
, status
,
826 (p
->data_port_open
? " data_port_open" : ""));
828 if (p
->status
== wil_sta_connected
) {
829 rc
= wil_cid_fill_sinfo(wil
, i
, &sinfo
);
833 seq_printf(s
, " Tx_mcs = %d\n", sinfo
.txrate
.mcs
);
834 seq_printf(s
, " Rx_mcs = %d\n", sinfo
.rxrate
.mcs
);
835 seq_printf(s
, " SQ = %d\n", sinfo
.signal
);
842 static int wil_link_seq_open(struct inode
*inode
, struct file
*file
)
844 return single_open(file
, wil_link_debugfs_show
, inode
->i_private
);
847 static const struct file_operations fops_link
= {
848 .open
= wil_link_seq_open
,
849 .release
= single_release
,
854 /*---------info------------*/
855 static int wil_info_debugfs_show(struct seq_file
*s
, void *data
)
857 struct wil6210_priv
*wil
= s
->private;
858 struct net_device
*ndev
= wil_to_ndev(wil
);
859 int is_ac
= power_supply_is_system_supplied();
860 int rx
= atomic_xchg(&wil
->isr_count_rx
, 0);
861 int tx
= atomic_xchg(&wil
->isr_count_tx
, 0);
862 static ulong rxf_old
, txf_old
;
863 ulong rxf
= ndev
->stats
.rx_packets
;
864 ulong txf
= ndev
->stats
.tx_packets
;
867 /* >0 : AC; 0 : battery; <0 : error */
868 seq_printf(s
, "AC powered : %d\n", is_ac
);
869 seq_printf(s
, "Rx irqs:packets : %8d : %8ld\n", rx
, rxf
- rxf_old
);
870 seq_printf(s
, "Tx irqs:packets : %8d : %8ld\n", tx
, txf
- txf_old
);
875 #define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \
876 " " __stringify(x) : ""
878 for (i
= 0; i
< ndev
->num_tx_queues
; i
++) {
879 struct netdev_queue
*txq
= netdev_get_tx_queue(ndev
, i
);
880 unsigned long state
= txq
->state
;
882 seq_printf(s
, "Tx queue[%i] state : 0x%lx%s%s%s\n", i
, state
,
883 CHECK_QSTATE(DRV_XOFF
),
884 CHECK_QSTATE(STACK_XOFF
),
892 static int wil_info_seq_open(struct inode
*inode
, struct file
*file
)
894 return single_open(file
, wil_info_debugfs_show
, inode
->i_private
);
897 static const struct file_operations fops_info
= {
898 .open
= wil_info_seq_open
,
899 .release
= single_release
,
904 /*---------Station matrix------------*/
905 static void wil_print_rxtid(struct seq_file
*s
, struct wil_tid_ampdu_rx
*r
)
908 u16 index
= ((r
->head_seq_num
- r
->ssn
) & 0xfff) % r
->buf_size
;
909 seq_printf(s
, "0x%03x [", r
->head_seq_num
);
910 for (i
= 0; i
< r
->buf_size
; i
++) {
912 seq_printf(s
, "%c", r
->reorder_buf
[i
] ? 'O' : '|');
914 seq_printf(s
, "%c", r
->reorder_buf
[i
] ? '*' : '_');
916 seq_printf(s
, "] last drop 0x%03x\n", r
->ssn_last_drop
);
919 static int wil_sta_debugfs_show(struct seq_file
*s
, void *data
)
921 struct wil6210_priv
*wil
= s
->private;
924 for (i
= 0; i
< ARRAY_SIZE(wil
->sta
); i
++) {
925 struct wil_sta_info
*p
= &wil
->sta
[i
];
926 char *status
= "unknown";
931 case wil_sta_conn_pending
:
934 case wil_sta_connected
:
935 status
= "connected";
938 seq_printf(s
, "[%d] %pM %s%s\n", i
, p
->addr
, status
,
939 (p
->data_port_open
? " data_port_open" : ""));
941 if (p
->status
== wil_sta_connected
) {
942 for (tid
= 0; tid
< WIL_STA_TID_NUM
; tid
++) {
943 struct wil_tid_ampdu_rx
*r
= p
->tid_rx
[tid
];
945 seq_printf(s
, "[%2d] ", tid
);
946 wil_print_rxtid(s
, r
);
955 static int wil_sta_seq_open(struct inode
*inode
, struct file
*file
)
957 return single_open(file
, wil_sta_debugfs_show
, inode
->i_private
);
960 static const struct file_operations fops_sta
= {
961 .open
= wil_sta_seq_open
,
962 .release
= single_release
,
968 static void wil6210_debugfs_init_blobs(struct wil6210_priv
*wil
,
974 for (i
= 0; i
< ARRAY_SIZE(fw_mapping
); i
++) {
975 struct debugfs_blob_wrapper
*blob
= &wil
->blobs
[i
];
976 const struct fw_map
*map
= &fw_mapping
[i
];
981 blob
->data
= (void * __force
)wil
->csr
+ HOSTADDR(map
->host
);
982 blob
->size
= map
->to
- map
->from
;
983 snprintf(name
, sizeof(name
), "blob_%s", map
->name
);
984 wil_debugfs_create_ioblob(name
, S_IRUGO
, dbg
, blob
);
988 int wil6210_debugfs_init(struct wil6210_priv
*wil
)
990 struct dentry
*dbg
= wil
->debug
= debugfs_create_dir(WIL_NAME
,
991 wil_to_wiphy(wil
)->debugfsdir
);
993 if (IS_ERR_OR_NULL(dbg
))
996 debugfs_create_file("mbox", S_IRUGO
, dbg
, wil
, &fops_mbox
);
997 debugfs_create_file("vrings", S_IRUGO
, dbg
, wil
, &fops_vring
);
998 debugfs_create_file("stations", S_IRUGO
, dbg
, wil
, &fops_sta
);
999 debugfs_create_file("desc", S_IRUGO
, dbg
, wil
, &fops_txdesc
);
1000 debugfs_create_u32("desc_index", S_IRUGO
| S_IWUSR
, dbg
,
1002 debugfs_create_u32("vring_index", S_IRUGO
| S_IWUSR
, dbg
,
1005 debugfs_create_file("bf", S_IRUGO
, dbg
, wil
, &fops_bf
);
1006 debugfs_create_file("ssid", S_IRUGO
| S_IWUSR
, dbg
, wil
, &fops_ssid
);
1007 debugfs_create_u32("secure_pcp", S_IRUGO
| S_IWUSR
, dbg
,
1009 wil_debugfs_create_ulong("status", S_IRUGO
| S_IWUSR
, dbg
,
1011 debugfs_create_u32("fw_version", S_IRUGO
, dbg
, &wil
->fw_version
);
1012 debugfs_create_x32("hw_version", S_IRUGO
, dbg
, &wil
->hw_version
);
1014 wil6210_debugfs_create_ISR(wil
, "USER_ICR", dbg
,
1015 HOSTADDR(RGF_USER_USER_ICR
));
1016 wil6210_debugfs_create_ISR(wil
, "DMA_EP_TX_ICR", dbg
,
1017 HOSTADDR(RGF_DMA_EP_TX_ICR
));
1018 wil6210_debugfs_create_ISR(wil
, "DMA_EP_RX_ICR", dbg
,
1019 HOSTADDR(RGF_DMA_EP_RX_ICR
));
1020 wil6210_debugfs_create_ISR(wil
, "DMA_EP_MISC_ICR", dbg
,
1021 HOSTADDR(RGF_DMA_EP_MISC_ICR
));
1022 wil6210_debugfs_create_pseudo_ISR(wil
, dbg
);
1023 wil6210_debugfs_create_ITR_CNT(wil
, dbg
);
1025 wil_debugfs_create_iomem_x32("RGF_USER_USAGE_1", S_IRUGO
, dbg
,
1027 HOSTADDR(RGF_USER_USAGE_1
));
1028 debugfs_create_u32("mem_addr", S_IRUGO
| S_IWUSR
, dbg
, &mem_addr
);
1029 debugfs_create_file("mem_val", S_IRUGO
, dbg
, wil
, &fops_memread
);
1031 debugfs_create_file("reset", S_IWUSR
, dbg
, wil
, &fops_reset
);
1032 debugfs_create_file("rxon", S_IWUSR
, dbg
, wil
, &fops_rxon
);
1033 debugfs_create_file("tx_mgmt", S_IWUSR
, dbg
, wil
, &fops_txmgmt
);
1034 debugfs_create_file("wmi_send", S_IWUSR
, dbg
, wil
, &fops_wmi
);
1035 debugfs_create_file("temp", S_IRUGO
, dbg
, wil
, &fops_temp
);
1036 debugfs_create_file("freq", S_IRUGO
, dbg
, wil
, &fops_freq
);
1037 debugfs_create_file("link", S_IRUGO
, dbg
, wil
, &fops_link
);
1038 debugfs_create_file("info", S_IRUGO
, dbg
, wil
, &fops_info
);
1040 wil6210_debugfs_init_blobs(wil
, dbg
);
1045 void wil6210_debugfs_remove(struct wil6210_priv
*wil
)
1047 debugfs_remove_recursive(wil
->debug
);