2 * Copyright (c) 2012-2015 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>
29 /* Nasty hack. Better have per device instances */
31 static u32 dbg_txdesc_index
;
32 static u32 dbg_vring_index
; /* 24+ for Rx, 0..23 for Tx */
33 u32 vring_idle_trsh
= 16; /* HW fetches up to 16 descriptors at once */
47 enum dbg_off_type type
;
50 static void wil_print_vring(struct seq_file
*s
, struct wil6210_priv
*wil
,
51 const char *name
, struct vring
*vring
,
54 void __iomem
*x
= wmi_addr(wil
, vring
->hwtail
);
57 seq_printf(s
, "VRING %s = {\n", name
);
58 seq_printf(s
, " pa = %pad\n", &vring
->pa
);
59 seq_printf(s
, " va = 0x%p\n", vring
->va
);
60 seq_printf(s
, " size = %d\n", vring
->size
);
61 seq_printf(s
, " swtail = %d\n", vring
->swtail
);
62 seq_printf(s
, " swhead = %d\n", vring
->swhead
);
63 seq_printf(s
, " hwtail = [0x%08x] -> ", vring
->hwtail
);
66 seq_printf(s
, "0x%08x = %d\n", v
, v
);
71 if (vring
->va
&& (vring
->size
< 1025)) {
74 for (i
= 0; i
< vring
->size
; i
++) {
75 volatile struct vring_tx_desc
*d
= &vring
->va
[i
].tx
;
77 if ((i
% 64) == 0 && (i
!= 0))
79 seq_printf(s
, "%c", (d
->dma
.status
& BIT(0)) ?
80 _s
: (vring
->ctx
[i
].skb
? _h
: 'h'));
87 static int wil_vring_debugfs_show(struct seq_file
*s
, void *data
)
90 struct wil6210_priv
*wil
= s
->private;
92 wil_print_vring(s
, wil
, "rx", &wil
->vring_rx
, 'S', '_');
94 for (i
= 0; i
< ARRAY_SIZE(wil
->vring_tx
); i
++) {
95 struct vring
*vring
= &wil
->vring_tx
[i
];
96 struct vring_tx_data
*txdata
= &wil
->vring_tx_data
[i
];
99 int cid
= wil
->vring2cid_tid
[i
][0];
100 int tid
= wil
->vring2cid_tid
[i
][1];
101 u32 swhead
= vring
->swhead
;
102 u32 swtail
= vring
->swtail
;
103 int used
= (vring
->size
+ swhead
- swtail
)
105 int avail
= vring
->size
- used
- 1;
108 /* performance monitoring */
109 cycles_t now
= get_cycles();
110 uint64_t idle
= txdata
->idle
* 100;
111 uint64_t total
= now
- txdata
->begin
;
115 snprintf(sidle
, sizeof(sidle
), "%3d%%",
118 snprintf(sidle
, sizeof(sidle
), "N/A");
123 snprintf(name
, sizeof(name
), "tx_%2d", i
);
125 if (cid
< WIL6210_MAX_CID
)
127 "\n%pM CID %d TID %d 1x%s BACK([%u] %u TU A%s) [%3d|%3d] idle %s\n",
128 wil
->sta
[cid
].addr
, cid
, tid
,
129 txdata
->dot1x_open
? "+" : "-",
132 txdata
->agg_amsdu
? "+" : "-",
136 "\nBroadcast 1x%s [%3d|%3d] idle %s\n",
137 txdata
->dot1x_open
? "+" : "-",
140 wil_print_vring(s
, wil
, name
, vring
, '_', 'H');
147 static int wil_vring_seq_open(struct inode
*inode
, struct file
*file
)
149 return single_open(file
, wil_vring_debugfs_show
, inode
->i_private
);
152 static const struct file_operations fops_vring
= {
153 .open
= wil_vring_seq_open
,
154 .release
= single_release
,
159 static void wil_seq_hexdump(struct seq_file
*s
, void *p
, int len
,
162 seq_hex_dump(s
, prefix
, DUMP_PREFIX_NONE
, 16, 1, p
, len
, false);
165 static void wil_print_ring(struct seq_file
*s
, const char *prefix
,
168 struct wil6210_priv
*wil
= s
->private;
169 struct wil6210_mbox_ring r
;
173 wil_memcpy_fromio_32(&r
, off
, sizeof(r
));
174 wil_mbox_ring_le2cpus(&r
);
176 * we just read memory block from NIC. This memory may be
177 * garbage. Check validity before using it.
179 rsize
= r
.size
/ sizeof(struct wil6210_mbox_ring_desc
);
181 seq_printf(s
, "ring %s = {\n", prefix
);
182 seq_printf(s
, " base = 0x%08x\n", r
.base
);
183 seq_printf(s
, " size = 0x%04x bytes -> %d entries\n", r
.size
, rsize
);
184 seq_printf(s
, " tail = 0x%08x\n", r
.tail
);
185 seq_printf(s
, " head = 0x%08x\n", r
.head
);
186 seq_printf(s
, " entry size = %d\n", r
.entry_size
);
188 if (r
.size
% sizeof(struct wil6210_mbox_ring_desc
)) {
189 seq_printf(s
, " ??? size is not multiple of %zd, garbage?\n",
190 sizeof(struct wil6210_mbox_ring_desc
));
194 if (!wmi_addr(wil
, r
.base
) ||
195 !wmi_addr(wil
, r
.tail
) ||
196 !wmi_addr(wil
, r
.head
)) {
197 seq_puts(s
, " ??? pointers are garbage?\n");
201 for (i
= 0; i
< rsize
; i
++) {
202 struct wil6210_mbox_ring_desc d
;
203 struct wil6210_mbox_hdr hdr
;
204 size_t delta
= i
* sizeof(d
);
205 void __iomem
*x
= wil
->csr
+ HOSTADDR(r
.base
) + delta
;
207 wil_memcpy_fromio_32(&d
, x
, sizeof(d
));
209 seq_printf(s
, " [%2x] %s %s%s 0x%08x", i
,
211 (r
.tail
- r
.base
== delta
) ? "t" : " ",
212 (r
.head
- r
.base
== delta
) ? "h" : " ",
213 le32_to_cpu(d
.addr
));
214 if (0 == wmi_read_hdr(wil
, d
.addr
, &hdr
)) {
215 u16 len
= le16_to_cpu(hdr
.len
);
217 seq_printf(s
, " -> %04x %04x %04x %02x\n",
218 le16_to_cpu(hdr
.seq
), len
,
219 le16_to_cpu(hdr
.type
), hdr
.flags
);
220 if (len
<= MAX_MBOXITEM_SIZE
) {
221 unsigned char databuf
[MAX_MBOXITEM_SIZE
];
222 void __iomem
*src
= wmi_buffer(wil
, d
.addr
) +
223 sizeof(struct wil6210_mbox_hdr
);
225 * No need to check @src for validity -
226 * we already validated @d.addr while
229 wil_memcpy_fromio_32(databuf
, src
, len
);
230 wil_seq_hexdump(s
, databuf
, len
, " : ");
240 static int wil_mbox_debugfs_show(struct seq_file
*s
, void *data
)
242 struct wil6210_priv
*wil
= s
->private;
244 wil_print_ring(s
, "tx", wil
->csr
+ HOST_MBOX
+
245 offsetof(struct wil6210_mbox_ctl
, tx
));
246 wil_print_ring(s
, "rx", wil
->csr
+ HOST_MBOX
+
247 offsetof(struct wil6210_mbox_ctl
, rx
));
252 static int wil_mbox_seq_open(struct inode
*inode
, struct file
*file
)
254 return single_open(file
, wil_mbox_debugfs_show
, inode
->i_private
);
257 static const struct file_operations fops_mbox
= {
258 .open
= wil_mbox_seq_open
,
259 .release
= single_release
,
264 static int wil_debugfs_iomem_x32_set(void *data
, u64 val
)
266 writel(val
, (void __iomem
*)data
);
267 wmb(); /* make sure write propagated to HW */
272 static int wil_debugfs_iomem_x32_get(void *data
, u64
*val
)
274 *val
= readl((void __iomem
*)data
);
279 DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32
, wil_debugfs_iomem_x32_get
,
280 wil_debugfs_iomem_x32_set
, "0x%08llx\n");
282 static struct dentry
*wil_debugfs_create_iomem_x32(const char *name
,
284 struct dentry
*parent
,
287 return debugfs_create_file(name
, mode
, parent
, value
,
291 static int wil_debugfs_ulong_set(void *data
, u64 val
)
293 *(ulong
*)data
= val
;
297 static int wil_debugfs_ulong_get(void *data
, u64
*val
)
299 *val
= *(ulong
*)data
;
303 DEFINE_SIMPLE_ATTRIBUTE(wil_fops_ulong
, wil_debugfs_ulong_get
,
304 wil_debugfs_ulong_set
, "0x%llx\n");
306 static struct dentry
*wil_debugfs_create_ulong(const char *name
, umode_t mode
,
307 struct dentry
*parent
,
310 return debugfs_create_file(name
, mode
, parent
, value
, &wil_fops_ulong
);
314 * wil6210_debugfs_init_offset - create set of debugfs files
315 * @wil - driver's context, used for printing
316 * @dbg - directory on the debugfs, where files will be created
317 * @base - base address used in address calculation
318 * @tbl - table with file descriptions. Should be terminated with empty element.
320 * Creates files accordingly to the @tbl.
322 static void wil6210_debugfs_init_offset(struct wil6210_priv
*wil
,
323 struct dentry
*dbg
, void *base
,
324 const struct dbg_off
* const tbl
)
328 for (i
= 0; tbl
[i
].name
; i
++) {
331 switch (tbl
[i
].type
) {
333 f
= debugfs_create_u32(tbl
[i
].name
, tbl
[i
].mode
, dbg
,
337 f
= debugfs_create_x32(tbl
[i
].name
, tbl
[i
].mode
, dbg
,
341 f
= wil_debugfs_create_ulong(tbl
[i
].name
, tbl
[i
].mode
,
342 dbg
, base
+ tbl
[i
].off
);
345 f
= wil_debugfs_create_iomem_x32(tbl
[i
].name
,
350 f
= ERR_PTR(-EINVAL
);
352 if (IS_ERR_OR_NULL(f
))
353 wil_err(wil
, "Create file \"%s\": err %ld\n",
354 tbl
[i
].name
, PTR_ERR(f
));
358 static const struct dbg_off isr_off
[] = {
359 {"ICC", S_IRUGO
| S_IWUSR
, offsetof(struct RGF_ICR
, ICC
), doff_io32
},
360 {"ICR", S_IRUGO
| S_IWUSR
, offsetof(struct RGF_ICR
, ICR
), doff_io32
},
361 {"ICM", S_IRUGO
| S_IWUSR
, offsetof(struct RGF_ICR
, ICM
), doff_io32
},
362 {"ICS", S_IWUSR
, offsetof(struct RGF_ICR
, ICS
), doff_io32
},
363 {"IMV", S_IRUGO
| S_IWUSR
, offsetof(struct RGF_ICR
, IMV
), doff_io32
},
364 {"IMS", S_IWUSR
, offsetof(struct RGF_ICR
, IMS
), doff_io32
},
365 {"IMC", S_IWUSR
, offsetof(struct RGF_ICR
, IMC
), doff_io32
},
369 static int wil6210_debugfs_create_ISR(struct wil6210_priv
*wil
,
371 struct dentry
*parent
, u32 off
)
373 struct dentry
*d
= debugfs_create_dir(name
, parent
);
375 if (IS_ERR_OR_NULL(d
))
378 wil6210_debugfs_init_offset(wil
, d
, (void * __force
)wil
->csr
+ off
,
384 static const struct dbg_off pseudo_isr_off
[] = {
385 {"CAUSE", S_IRUGO
, HOSTADDR(RGF_DMA_PSEUDO_CAUSE
), doff_io32
},
386 {"MASK_SW", S_IRUGO
, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW
), doff_io32
},
387 {"MASK_FW", S_IRUGO
, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW
), doff_io32
},
391 static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv
*wil
,
392 struct dentry
*parent
)
394 struct dentry
*d
= debugfs_create_dir("PSEUDO_ISR", parent
);
396 if (IS_ERR_OR_NULL(d
))
399 wil6210_debugfs_init_offset(wil
, d
, (void * __force
)wil
->csr
,
405 static const struct dbg_off lgc_itr_cnt_off
[] = {
406 {"TRSH", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_CNT_TRSH
), doff_io32
},
407 {"DATA", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_CNT_DATA
), doff_io32
},
408 {"CTL", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_CNT_CRL
), doff_io32
},
412 static const struct dbg_off tx_itr_cnt_off
[] = {
413 {"TRSH", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH
),
415 {"DATA", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_TX_CNT_DATA
),
417 {"CTL", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL
),
419 {"IDL_TRSH", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_TRSH
),
421 {"IDL_DATA", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_DATA
),
423 {"IDL_CTL", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_CTL
),
428 static const struct dbg_off rx_itr_cnt_off
[] = {
429 {"TRSH", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH
),
431 {"DATA", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_RX_CNT_DATA
),
433 {"CTL", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL
),
435 {"IDL_TRSH", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_TRSH
),
437 {"IDL_DATA", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_DATA
),
439 {"IDL_CTL", S_IRUGO
| S_IWUSR
, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_CTL
),
444 static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv
*wil
,
445 struct dentry
*parent
)
447 struct dentry
*d
, *dtx
, *drx
;
449 d
= debugfs_create_dir("ITR_CNT", parent
);
450 if (IS_ERR_OR_NULL(d
))
453 dtx
= debugfs_create_dir("TX", d
);
454 drx
= debugfs_create_dir("RX", d
);
455 if (IS_ERR_OR_NULL(dtx
) || IS_ERR_OR_NULL(drx
))
458 wil6210_debugfs_init_offset(wil
, d
, (void * __force
)wil
->csr
,
461 wil6210_debugfs_init_offset(wil
, dtx
, (void * __force
)wil
->csr
,
464 wil6210_debugfs_init_offset(wil
, drx
, (void * __force
)wil
->csr
,
469 static int wil_memread_debugfs_show(struct seq_file
*s
, void *data
)
471 struct wil6210_priv
*wil
= s
->private;
472 void __iomem
*a
= wmi_buffer(wil
, cpu_to_le32(mem_addr
));
475 seq_printf(s
, "[0x%08x] = 0x%08x\n", mem_addr
, readl(a
));
477 seq_printf(s
, "[0x%08x] = INVALID\n", mem_addr
);
482 static int wil_memread_seq_open(struct inode
*inode
, struct file
*file
)
484 return single_open(file
, wil_memread_debugfs_show
, inode
->i_private
);
487 static const struct file_operations fops_memread
= {
488 .open
= wil_memread_seq_open
,
489 .release
= single_release
,
494 static ssize_t
wil_read_file_ioblob(struct file
*file
, char __user
*user_buf
,
495 size_t count
, loff_t
*ppos
)
497 enum { max_count
= 4096 };
498 struct debugfs_blob_wrapper
*blob
= file
->private_data
;
500 size_t available
= blob
->size
;
507 if (pos
>= available
|| !count
)
510 if (count
> available
- pos
)
511 count
= available
- pos
;
512 if (count
> max_count
)
515 buf
= kmalloc(count
, GFP_KERNEL
);
519 wil_memcpy_fromio_32(buf
, (const volatile void __iomem
*)blob
->data
+
522 ret
= copy_to_user(user_buf
, buf
, count
);
533 static const struct file_operations fops_ioblob
= {
534 .read
= wil_read_file_ioblob
,
536 .llseek
= default_llseek
,
540 struct dentry
*wil_debugfs_create_ioblob(const char *name
,
542 struct dentry
*parent
,
543 struct debugfs_blob_wrapper
*blob
)
545 return debugfs_create_file(name
, mode
, parent
, blob
, &fops_ioblob
);
549 static ssize_t
wil_write_file_reset(struct file
*file
, const char __user
*buf
,
550 size_t len
, loff_t
*ppos
)
552 struct wil6210_priv
*wil
= file
->private_data
;
553 struct net_device
*ndev
= wil_to_ndev(wil
);
557 * this code does NOT sync device state with the rest of system
558 * use with care, debug only!!!
562 ndev
->flags
&= ~IFF_UP
;
564 wil_reset(wil
, true);
569 static const struct file_operations fops_reset
= {
570 .write
= wil_write_file_reset
,
574 /*---write channel 1..4 to rxon for it, 0 to rxoff---*/
575 static ssize_t
wil_write_file_rxon(struct file
*file
, const char __user
*buf
,
576 size_t len
, loff_t
*ppos
)
578 struct wil6210_priv
*wil
= file
->private_data
;
583 char *kbuf
= kmalloc(len
+ 1, GFP_KERNEL
);
587 if (copy_from_user(kbuf
, buf
, len
)) {
593 rc
= kstrtol(kbuf
, 0, &channel
);
598 if ((channel
< 0) || (channel
> 4)) {
599 wil_err(wil
, "Invalid channel %ld\n", channel
);
605 rc
= wmi_set_channel(wil
, (int)channel
);
610 rc
= wmi_rxon(wil
, on
);
617 static const struct file_operations fops_rxon
= {
618 .write
= wil_write_file_rxon
,
622 /* block ack control, write:
623 * - "add <ringid> <agg_size> <timeout>" to trigger ADDBA
624 * - "del_tx <ringid> <reason>" to trigger DELBA for Tx side
625 * - "del_rx <CID> <TID> <reason>" to trigger DELBA for Rx side
627 static ssize_t
wil_write_back(struct file
*file
, const char __user
*buf
,
628 size_t len
, loff_t
*ppos
)
630 struct wil6210_priv
*wil
= file
->private_data
;
632 char *kbuf
= kmalloc(len
+ 1, GFP_KERNEL
);
639 rc
= simple_write_to_buffer(kbuf
, len
, ppos
, buf
, len
);
642 return rc
>= 0 ? -EIO
: rc
;
646 rc
= sscanf(kbuf
, "%8s %d %d %d", cmd
, &p1
, &p2
, &p3
);
654 if (0 == strcmp(cmd
, "add")) {
656 wil_err(wil
, "BACK: add require at least 2 params\n");
661 wmi_addba(wil
, p1
, p2
, p3
);
662 } else if (0 == strcmp(cmd
, "del_tx")) {
664 p2
= WLAN_REASON_QSTA_LEAVE_QBSS
;
665 wmi_delba_tx(wil
, p1
, p2
);
666 } else if (0 == strcmp(cmd
, "del_rx")) {
669 "BACK: del_rx require at least 2 params\n");
673 p3
= WLAN_REASON_QSTA_LEAVE_QBSS
;
674 wmi_delba_rx(wil
, mk_cidxtid(p1
, p2
), p3
);
676 wil_err(wil
, "BACK: Unrecognized command \"%s\"\n", cmd
);
683 static ssize_t
wil_read_back(struct file
*file
, char __user
*user_buf
,
684 size_t count
, loff_t
*ppos
)
686 static const char text
[] = "block ack control, write:\n"
687 " - \"add <ringid> <agg_size> <timeout>\" to trigger ADDBA\n"
688 "If missing, <timeout> defaults to 0\n"
689 " - \"del_tx <ringid> <reason>\" to trigger DELBA for Tx side\n"
690 " - \"del_rx <CID> <TID> <reason>\" to trigger DELBA for Rx side\n"
691 "If missing, <reason> set to \"STA_LEAVING\" (36)\n";
693 return simple_read_from_buffer(user_buf
, count
, ppos
, text
,
697 static const struct file_operations fops_back
= {
698 .read
= wil_read_back
,
699 .write
= wil_write_back
,
703 /* pmc control, write:
704 * - "alloc <num descriptors> <descriptor_size>" to allocate PMC
705 * - "free" to release memory allocated for PMC
707 static ssize_t
wil_write_pmccfg(struct file
*file
, const char __user
*buf
,
708 size_t len
, loff_t
*ppos
)
710 struct wil6210_priv
*wil
= file
->private_data
;
712 char *kbuf
= kmalloc(len
+ 1, GFP_KERNEL
);
714 int num_descs
, desc_size
;
719 rc
= simple_write_to_buffer(kbuf
, len
, ppos
, buf
, len
);
722 return rc
>= 0 ? -EIO
: rc
;
726 rc
= sscanf(kbuf
, "%8s %d %d", cmd
, &num_descs
, &desc_size
);
733 wil_err(wil
, "pmccfg: no params given\n");
737 if (0 == strcmp(cmd
, "alloc")) {
739 wil_err(wil
, "pmccfg: alloc requires 2 params\n");
742 wil_pmc_alloc(wil
, num_descs
, desc_size
);
743 } else if (0 == strcmp(cmd
, "free")) {
745 wil_err(wil
, "pmccfg: free does not have any params\n");
748 wil_pmc_free(wil
, true);
750 wil_err(wil
, "pmccfg: Unrecognized command \"%s\"\n", cmd
);
757 static ssize_t
wil_read_pmccfg(struct file
*file
, char __user
*user_buf
,
758 size_t count
, loff_t
*ppos
)
760 struct wil6210_priv
*wil
= file
->private_data
;
762 char help
[] = "pmc control, write:\n"
763 " - \"alloc <num descriptors> <descriptor_size>\" to allocate pmc\n"
764 " - \"free\" to free memory allocated for pmc\n";
766 sprintf(text
, "Last command status: %d\n\n%s",
767 wil_pmc_last_cmd_status(wil
),
770 return simple_read_from_buffer(user_buf
, count
, ppos
, text
,
774 static const struct file_operations fops_pmccfg
= {
775 .read
= wil_read_pmccfg
,
776 .write
= wil_write_pmccfg
,
780 static const struct file_operations fops_pmcdata
= {
782 .read
= wil_pmc_read
,
783 .llseek
= wil_pmc_llseek
,
787 /* Write mgmt frame to this file to send it */
788 static ssize_t
wil_write_file_txmgmt(struct file
*file
, const char __user
*buf
,
789 size_t len
, loff_t
*ppos
)
791 struct wil6210_priv
*wil
= file
->private_data
;
792 struct wiphy
*wiphy
= wil_to_wiphy(wil
);
793 struct wireless_dev
*wdev
= wil_to_wdev(wil
);
794 struct cfg80211_mgmt_tx_params params
;
796 void *frame
= kmalloc(len
, GFP_KERNEL
);
801 if (copy_from_user(frame
, buf
, len
)) {
808 params
.chan
= wdev
->preset_chandef
.chan
;
810 rc
= wil_cfg80211_mgmt_tx(wiphy
, wdev
, ¶ms
, NULL
);
813 wil_info(wil
, "%s() -> %d\n", __func__
, rc
);
818 static const struct file_operations fops_txmgmt
= {
819 .write
= wil_write_file_txmgmt
,
823 /* Write WMI command (w/o mbox header) to this file to send it
824 * WMI starts from wil6210_mbox_hdr_wmi header
826 static ssize_t
wil_write_file_wmi(struct file
*file
, const char __user
*buf
,
827 size_t len
, loff_t
*ppos
)
829 struct wil6210_priv
*wil
= file
->private_data
;
830 struct wil6210_mbox_hdr_wmi
*wmi
;
832 int cmdlen
= len
- sizeof(struct wil6210_mbox_hdr_wmi
);
839 wmi
= kmalloc(len
, GFP_KERNEL
);
843 rc
= simple_write_to_buffer(wmi
, len
, ppos
, buf
, len
);
850 cmdid
= le16_to_cpu(wmi
->id
);
852 rc1
= wmi_send(wil
, cmdid
, cmd
, cmdlen
);
855 wil_info(wil
, "%s(0x%04x[%d]) -> %d\n", __func__
, cmdid
, cmdlen
, rc1
);
860 static const struct file_operations fops_wmi
= {
861 .write
= wil_write_file_wmi
,
865 static void wil_seq_print_skb(struct seq_file
*s
, struct sk_buff
*skb
)
868 int len
= skb_headlen(skb
);
870 int nr_frags
= skb_shinfo(skb
)->nr_frags
;
872 seq_printf(s
, " len = %d\n", len
);
873 wil_seq_hexdump(s
, p
, len
, " : ");
876 seq_printf(s
, " nr_frags = %d\n", nr_frags
);
877 for (i
= 0; i
< nr_frags
; i
++) {
878 const struct skb_frag_struct
*frag
=
879 &skb_shinfo(skb
)->frags
[i
];
881 len
= skb_frag_size(frag
);
882 p
= skb_frag_address_safe(frag
);
883 seq_printf(s
, " [%2d] : len = %d\n", i
, len
);
884 wil_seq_hexdump(s
, p
, len
, " : ");
889 /*---------Tx/Rx descriptor------------*/
890 static int wil_txdesc_debugfs_show(struct seq_file
*s
, void *data
)
892 struct wil6210_priv
*wil
= s
->private;
894 bool tx
= (dbg_vring_index
< WIL6210_MAX_TX_RINGS
);
896 vring
= tx
? &wil
->vring_tx
[dbg_vring_index
] : &wil
->vring_rx
;
900 seq_printf(s
, "No Tx[%2d] VRING\n", dbg_vring_index
);
902 seq_puts(s
, "No Rx VRING\n");
906 if (dbg_txdesc_index
< vring
->size
) {
907 /* use struct vring_tx_desc for Rx as well,
908 * only field used, .dma.length, is the same
910 volatile struct vring_tx_desc
*d
=
911 &vring
->va
[dbg_txdesc_index
].tx
;
912 volatile u32
*u
= (volatile u32
*)d
;
913 struct sk_buff
*skb
= vring
->ctx
[dbg_txdesc_index
].skb
;
916 seq_printf(s
, "Tx[%2d][%3d] = {\n", dbg_vring_index
,
919 seq_printf(s
, "Rx[%3d] = {\n", dbg_txdesc_index
);
920 seq_printf(s
, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
921 u
[0], u
[1], u
[2], u
[3]);
922 seq_printf(s
, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
923 u
[4], u
[5], u
[6], u
[7]);
924 seq_printf(s
, " SKB = 0x%p\n", skb
);
928 wil_seq_print_skb(s
, skb
);
934 seq_printf(s
, "[%2d] TxDesc index (%d) >= size (%d)\n",
935 dbg_vring_index
, dbg_txdesc_index
,
938 seq_printf(s
, "RxDesc index (%d) >= size (%d)\n",
939 dbg_txdesc_index
, vring
->size
);
945 static int wil_txdesc_seq_open(struct inode
*inode
, struct file
*file
)
947 return single_open(file
, wil_txdesc_debugfs_show
, inode
->i_private
);
950 static const struct file_operations fops_txdesc
= {
951 .open
= wil_txdesc_seq_open
,
952 .release
= single_release
,
957 /*---------beamforming------------*/
958 static char *wil_bfstatus_str(u32 status
)
972 static bool is_all_zeros(void * const x_
, size_t sz
)
974 /* if reply is all-0, ignore this CID */
978 for (n
= 0; n
< sz
/ sizeof(*x
); n
++)
985 static int wil_bf_debugfs_show(struct seq_file
*s
, void *data
)
989 struct wil6210_priv
*wil
= s
->private;
990 struct wmi_notify_req_cmd cmd
= {
994 struct wil6210_mbox_hdr_wmi wmi
;
995 struct wmi_notify_req_done_event evt
;
998 for (i
= 0; i
< ARRAY_SIZE(wil
->sta
); i
++) {
1002 rc
= wmi_call(wil
, WMI_NOTIFY_REQ_CMDID
, &cmd
, sizeof(cmd
),
1003 WMI_NOTIFY_REQ_DONE_EVENTID
, &reply
,
1005 /* if reply is all-0, ignore this CID */
1006 if (rc
|| is_all_zeros(&reply
.evt
, sizeof(reply
.evt
)))
1009 status
= le32_to_cpu(reply
.evt
.status
);
1010 seq_printf(s
, "CID %d {\n"
1011 " TSF = 0x%016llx\n"
1012 " TxMCS = %2d TxTpt = %4d\n"
1014 " Status = 0x%08x %s\n"
1015 " Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n"
1016 " Goodput(rx:tx) %4d:%4d\n"
1019 le64_to_cpu(reply
.evt
.tsf
),
1020 le16_to_cpu(reply
.evt
.bf_mcs
),
1021 le32_to_cpu(reply
.evt
.tx_tpt
),
1023 status
, wil_bfstatus_str(status
),
1024 le16_to_cpu(reply
.evt
.my_rx_sector
),
1025 le16_to_cpu(reply
.evt
.my_tx_sector
),
1026 le16_to_cpu(reply
.evt
.other_rx_sector
),
1027 le16_to_cpu(reply
.evt
.other_tx_sector
),
1028 le32_to_cpu(reply
.evt
.rx_goodput
),
1029 le32_to_cpu(reply
.evt
.tx_goodput
));
1034 static int wil_bf_seq_open(struct inode
*inode
, struct file
*file
)
1036 return single_open(file
, wil_bf_debugfs_show
, inode
->i_private
);
1039 static const struct file_operations fops_bf
= {
1040 .open
= wil_bf_seq_open
,
1041 .release
= single_release
,
1043 .llseek
= seq_lseek
,
1046 /*---------SSID------------*/
1047 static ssize_t
wil_read_file_ssid(struct file
*file
, char __user
*user_buf
,
1048 size_t count
, loff_t
*ppos
)
1050 struct wil6210_priv
*wil
= file
->private_data
;
1051 struct wireless_dev
*wdev
= wil_to_wdev(wil
);
1053 return simple_read_from_buffer(user_buf
, count
, ppos
,
1054 wdev
->ssid
, wdev
->ssid_len
);
1057 static ssize_t
wil_write_file_ssid(struct file
*file
, const char __user
*buf
,
1058 size_t count
, loff_t
*ppos
)
1060 struct wil6210_priv
*wil
= file
->private_data
;
1061 struct wireless_dev
*wdev
= wil_to_wdev(wil
);
1062 struct net_device
*ndev
= wil_to_ndev(wil
);
1065 wil_err(wil
, "Unable to set SSID substring from [%d]\n",
1070 if (count
> sizeof(wdev
->ssid
)) {
1071 wil_err(wil
, "SSID too long, len = %d\n", (int)count
);
1074 if (netif_running(ndev
)) {
1075 wil_err(wil
, "Unable to change SSID on running interface\n");
1079 wdev
->ssid_len
= count
;
1080 return simple_write_to_buffer(wdev
->ssid
, wdev
->ssid_len
, ppos
,
1084 static const struct file_operations fops_ssid
= {
1085 .read
= wil_read_file_ssid
,
1086 .write
= wil_write_file_ssid
,
1087 .open
= simple_open
,
1090 /*---------temp------------*/
1091 static void print_temp(struct seq_file
*s
, const char *prefix
, u32 t
)
1096 seq_printf(s
, "%s N/A\n", prefix
);
1099 seq_printf(s
, "%s %d.%03d\n", prefix
, t
/ 1000, t
% 1000);
1104 static int wil_temp_debugfs_show(struct seq_file
*s
, void *data
)
1106 struct wil6210_priv
*wil
= s
->private;
1108 int rc
= wmi_get_temperature(wil
, &t_m
, &t_r
);
1111 seq_puts(s
, "Failed\n");
1115 print_temp(s
, "T_mac =", t_m
);
1116 print_temp(s
, "T_radio =", t_r
);
1121 static int wil_temp_seq_open(struct inode
*inode
, struct file
*file
)
1123 return single_open(file
, wil_temp_debugfs_show
, inode
->i_private
);
1126 static const struct file_operations fops_temp
= {
1127 .open
= wil_temp_seq_open
,
1128 .release
= single_release
,
1130 .llseek
= seq_lseek
,
1133 /*---------freq------------*/
1134 static int wil_freq_debugfs_show(struct seq_file
*s
, void *data
)
1136 struct wil6210_priv
*wil
= s
->private;
1137 struct wireless_dev
*wdev
= wil_to_wdev(wil
);
1138 u16 freq
= wdev
->chandef
.chan
? wdev
->chandef
.chan
->center_freq
: 0;
1140 seq_printf(s
, "Freq = %d\n", freq
);
1145 static int wil_freq_seq_open(struct inode
*inode
, struct file
*file
)
1147 return single_open(file
, wil_freq_debugfs_show
, inode
->i_private
);
1150 static const struct file_operations fops_freq
= {
1151 .open
= wil_freq_seq_open
,
1152 .release
= single_release
,
1154 .llseek
= seq_lseek
,
1157 /*---------link------------*/
1158 static int wil_link_debugfs_show(struct seq_file
*s
, void *data
)
1160 struct wil6210_priv
*wil
= s
->private;
1161 struct station_info sinfo
;
1164 for (i
= 0; i
< ARRAY_SIZE(wil
->sta
); i
++) {
1165 struct wil_sta_info
*p
= &wil
->sta
[i
];
1166 char *status
= "unknown";
1168 switch (p
->status
) {
1169 case wil_sta_unused
:
1172 case wil_sta_conn_pending
:
1173 status
= "pending ";
1175 case wil_sta_connected
:
1176 status
= "connected";
1179 seq_printf(s
, "[%d] %pM %s\n", i
, p
->addr
, status
);
1181 if (p
->status
== wil_sta_connected
) {
1182 rc
= wil_cid_fill_sinfo(wil
, i
, &sinfo
);
1186 seq_printf(s
, " Tx_mcs = %d\n", sinfo
.txrate
.mcs
);
1187 seq_printf(s
, " Rx_mcs = %d\n", sinfo
.rxrate
.mcs
);
1188 seq_printf(s
, " SQ = %d\n", sinfo
.signal
);
1195 static int wil_link_seq_open(struct inode
*inode
, struct file
*file
)
1197 return single_open(file
, wil_link_debugfs_show
, inode
->i_private
);
1200 static const struct file_operations fops_link
= {
1201 .open
= wil_link_seq_open
,
1202 .release
= single_release
,
1204 .llseek
= seq_lseek
,
1207 /*---------info------------*/
1208 static int wil_info_debugfs_show(struct seq_file
*s
, void *data
)
1210 struct wil6210_priv
*wil
= s
->private;
1211 struct net_device
*ndev
= wil_to_ndev(wil
);
1212 int is_ac
= power_supply_is_system_supplied();
1213 int rx
= atomic_xchg(&wil
->isr_count_rx
, 0);
1214 int tx
= atomic_xchg(&wil
->isr_count_tx
, 0);
1215 static ulong rxf_old
, txf_old
;
1216 ulong rxf
= ndev
->stats
.rx_packets
;
1217 ulong txf
= ndev
->stats
.tx_packets
;
1220 /* >0 : AC; 0 : battery; <0 : error */
1221 seq_printf(s
, "AC powered : %d\n", is_ac
);
1222 seq_printf(s
, "Rx irqs:packets : %8d : %8ld\n", rx
, rxf
- rxf_old
);
1223 seq_printf(s
, "Tx irqs:packets : %8d : %8ld\n", tx
, txf
- txf_old
);
1227 #define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \
1228 " " __stringify(x) : ""
1230 for (i
= 0; i
< ndev
->num_tx_queues
; i
++) {
1231 struct netdev_queue
*txq
= netdev_get_tx_queue(ndev
, i
);
1232 unsigned long state
= txq
->state
;
1234 seq_printf(s
, "Tx queue[%i] state : 0x%lx%s%s%s\n", i
, state
,
1235 CHECK_QSTATE(DRV_XOFF
),
1236 CHECK_QSTATE(STACK_XOFF
),
1237 CHECK_QSTATE(FROZEN
)
1244 static int wil_info_seq_open(struct inode
*inode
, struct file
*file
)
1246 return single_open(file
, wil_info_debugfs_show
, inode
->i_private
);
1249 static const struct file_operations fops_info
= {
1250 .open
= wil_info_seq_open
,
1251 .release
= single_release
,
1253 .llseek
= seq_lseek
,
1256 /*---------recovery------------*/
1257 /* mode = [manual|auto]
1258 * state = [idle|pending|running]
1260 static ssize_t
wil_read_file_recovery(struct file
*file
, char __user
*user_buf
,
1261 size_t count
, loff_t
*ppos
)
1263 struct wil6210_priv
*wil
= file
->private_data
;
1266 static const char * const sstate
[] = {"idle", "pending", "running"};
1268 n
= snprintf(buf
, sizeof(buf
), "mode = %s\nstate = %s\n",
1269 no_fw_recovery
? "manual" : "auto",
1270 sstate
[wil
->recovery_state
]);
1272 n
= min_t(int, n
, sizeof(buf
));
1274 return simple_read_from_buffer(user_buf
, count
, ppos
,
1278 static ssize_t
wil_write_file_recovery(struct file
*file
,
1279 const char __user
*buf_
,
1280 size_t count
, loff_t
*ppos
)
1282 struct wil6210_priv
*wil
= file
->private_data
;
1283 static const char run_command
[] = "run";
1284 char buf
[sizeof(run_command
) + 1]; /* to detect "runx" */
1287 if (wil
->recovery_state
!= fw_recovery_pending
) {
1288 wil_err(wil
, "No recovery pending\n");
1293 wil_err(wil
, "Offset [%d]\n", (int)*ppos
);
1297 if (count
> sizeof(buf
)) {
1298 wil_err(wil
, "Input too long, len = %d\n", (int)count
);
1302 rc
= simple_write_to_buffer(buf
, sizeof(buf
) - 1, ppos
, buf_
, count
);
1307 if (0 == strcmp(buf
, run_command
))
1308 wil_set_recovery_state(wil
, fw_recovery_running
);
1310 wil_err(wil
, "Bad recovery command \"%s\"\n", buf
);
1315 static const struct file_operations fops_recovery
= {
1316 .read
= wil_read_file_recovery
,
1317 .write
= wil_write_file_recovery
,
1318 .open
= simple_open
,
1321 /*---------Station matrix------------*/
1322 static void wil_print_rxtid(struct seq_file
*s
, struct wil_tid_ampdu_rx
*r
)
1325 u16 index
= ((r
->head_seq_num
- r
->ssn
) & 0xfff) % r
->buf_size
;
1326 unsigned long long drop_dup
= r
->drop_dup
, drop_old
= r
->drop_old
;
1328 seq_printf(s
, "([%2d] %3d TU) 0x%03x [", r
->buf_size
, r
->timeout
,
1330 for (i
= 0; i
< r
->buf_size
; i
++) {
1332 seq_printf(s
, "%c", r
->reorder_buf
[i
] ? 'O' : '|');
1334 seq_printf(s
, "%c", r
->reorder_buf
[i
] ? '*' : '_');
1337 "] total %llu drop %llu (dup %llu + old %llu) last 0x%03x\n",
1338 r
->total
, drop_dup
+ drop_old
, drop_dup
, drop_old
,
1342 static int wil_sta_debugfs_show(struct seq_file
*s
, void *data
)
1343 __acquires(&p
->tid_rx_lock
) __releases(&p
->tid_rx_lock
)
1345 struct wil6210_priv
*wil
= s
->private;
1348 for (i
= 0; i
< ARRAY_SIZE(wil
->sta
); i
++) {
1349 struct wil_sta_info
*p
= &wil
->sta
[i
];
1350 char *status
= "unknown";
1352 switch (p
->status
) {
1353 case wil_sta_unused
:
1356 case wil_sta_conn_pending
:
1357 status
= "pending ";
1359 case wil_sta_connected
:
1360 status
= "connected";
1363 seq_printf(s
, "[%d] %pM %s\n", i
, p
->addr
, status
);
1365 if (p
->status
== wil_sta_connected
) {
1366 spin_lock_bh(&p
->tid_rx_lock
);
1367 for (tid
= 0; tid
< WIL_STA_TID_NUM
; tid
++) {
1368 struct wil_tid_ampdu_rx
*r
= p
->tid_rx
[tid
];
1371 seq_printf(s
, "[%2d] ", tid
);
1372 wil_print_rxtid(s
, r
);
1375 spin_unlock_bh(&p
->tid_rx_lock
);
1377 "Rx invalid frame: non-data %lu, short %lu, large %lu\n",
1378 p
->stats
.rx_non_data_frame
,
1379 p
->stats
.rx_short_frame
,
1380 p
->stats
.rx_large_frame
);
1382 seq_puts(s
, "Rx/MCS:");
1383 for (mcs
= 0; mcs
< ARRAY_SIZE(p
->stats
.rx_per_mcs
);
1385 seq_printf(s
, " %lld",
1386 p
->stats
.rx_per_mcs
[mcs
]);
1394 static int wil_sta_seq_open(struct inode
*inode
, struct file
*file
)
1396 return single_open(file
, wil_sta_debugfs_show
, inode
->i_private
);
1399 static const struct file_operations fops_sta
= {
1400 .open
= wil_sta_seq_open
,
1401 .release
= single_release
,
1403 .llseek
= seq_lseek
,
1406 /*----------------*/
1407 static void wil6210_debugfs_init_blobs(struct wil6210_priv
*wil
,
1413 for (i
= 0; i
< ARRAY_SIZE(fw_mapping
); i
++) {
1414 struct debugfs_blob_wrapper
*blob
= &wil
->blobs
[i
];
1415 const struct fw_map
*map
= &fw_mapping
[i
];
1420 blob
->data
= (void * __force
)wil
->csr
+ HOSTADDR(map
->host
);
1421 blob
->size
= map
->to
- map
->from
;
1422 snprintf(name
, sizeof(name
), "blob_%s", map
->name
);
1423 wil_debugfs_create_ioblob(name
, S_IRUGO
, dbg
, blob
);
1428 static const struct {
1431 const struct file_operations
*fops
;
1433 {"mbox", S_IRUGO
, &fops_mbox
},
1434 {"vrings", S_IRUGO
, &fops_vring
},
1435 {"stations", S_IRUGO
, &fops_sta
},
1436 {"desc", S_IRUGO
, &fops_txdesc
},
1437 {"bf", S_IRUGO
, &fops_bf
},
1438 {"ssid", S_IRUGO
| S_IWUSR
, &fops_ssid
},
1439 {"mem_val", S_IRUGO
, &fops_memread
},
1440 {"reset", S_IWUSR
, &fops_reset
},
1441 {"rxon", S_IWUSR
, &fops_rxon
},
1442 {"tx_mgmt", S_IWUSR
, &fops_txmgmt
},
1443 {"wmi_send", S_IWUSR
, &fops_wmi
},
1444 {"back", S_IRUGO
| S_IWUSR
, &fops_back
},
1445 {"pmccfg", S_IRUGO
| S_IWUSR
, &fops_pmccfg
},
1446 {"pmcdata", S_IRUGO
, &fops_pmcdata
},
1447 {"temp", S_IRUGO
, &fops_temp
},
1448 {"freq", S_IRUGO
, &fops_freq
},
1449 {"link", S_IRUGO
, &fops_link
},
1450 {"info", S_IRUGO
, &fops_info
},
1451 {"recovery", S_IRUGO
| S_IWUSR
, &fops_recovery
},
1454 static void wil6210_debugfs_init_files(struct wil6210_priv
*wil
,
1459 for (i
= 0; i
< ARRAY_SIZE(dbg_files
); i
++)
1460 debugfs_create_file(dbg_files
[i
].name
, dbg_files
[i
].mode
, dbg
,
1461 wil
, dbg_files
[i
].fops
);
1464 /* interrupt control blocks */
1465 static const struct {
1469 {"USER_ICR", HOSTADDR(RGF_USER_USER_ICR
)},
1470 {"DMA_EP_TX_ICR", HOSTADDR(RGF_DMA_EP_TX_ICR
)},
1471 {"DMA_EP_RX_ICR", HOSTADDR(RGF_DMA_EP_RX_ICR
)},
1472 {"DMA_EP_MISC_ICR", HOSTADDR(RGF_DMA_EP_MISC_ICR
)},
1475 static void wil6210_debugfs_init_isr(struct wil6210_priv
*wil
,
1480 for (i
= 0; i
< ARRAY_SIZE(dbg_icr
); i
++)
1481 wil6210_debugfs_create_ISR(wil
, dbg_icr
[i
].name
, dbg
,
1482 dbg_icr
[i
].icr_off
);
1485 #define WIL_FIELD(name, mode, type) { __stringify(name), mode, \
1486 offsetof(struct wil6210_priv, name), type}
1488 /* fields in struct wil6210_priv */
1489 static const struct dbg_off dbg_wil_off
[] = {
1490 WIL_FIELD(privacy
, S_IRUGO
, doff_u32
),
1491 WIL_FIELD(status
[0], S_IRUGO
| S_IWUSR
, doff_ulong
),
1492 WIL_FIELD(fw_version
, S_IRUGO
, doff_u32
),
1493 WIL_FIELD(hw_version
, S_IRUGO
, doff_x32
),
1494 WIL_FIELD(recovery_count
, S_IRUGO
, doff_u32
),
1495 WIL_FIELD(ap_isolate
, S_IRUGO
, doff_u32
),
1499 static const struct dbg_off dbg_wil_regs
[] = {
1500 {"RGF_MAC_MTRL_COUNTER_0", S_IRUGO
, HOSTADDR(RGF_MAC_MTRL_COUNTER_0
),
1502 {"RGF_USER_USAGE_1", S_IRUGO
, HOSTADDR(RGF_USER_USAGE_1
), doff_io32
},
1506 /* static parameters */
1507 static const struct dbg_off dbg_statics
[] = {
1508 {"desc_index", S_IRUGO
| S_IWUSR
, (ulong
)&dbg_txdesc_index
, doff_u32
},
1509 {"vring_index", S_IRUGO
| S_IWUSR
, (ulong
)&dbg_vring_index
, doff_u32
},
1510 {"mem_addr", S_IRUGO
| S_IWUSR
, (ulong
)&mem_addr
, doff_u32
},
1511 {"vring_idle_trsh", S_IRUGO
| S_IWUSR
, (ulong
)&vring_idle_trsh
,
1516 int wil6210_debugfs_init(struct wil6210_priv
*wil
)
1518 struct dentry
*dbg
= wil
->debug
= debugfs_create_dir(WIL_NAME
,
1519 wil_to_wiphy(wil
)->debugfsdir
);
1521 if (IS_ERR_OR_NULL(dbg
))
1526 wil6210_debugfs_init_files(wil
, dbg
);
1527 wil6210_debugfs_init_isr(wil
, dbg
);
1528 wil6210_debugfs_init_blobs(wil
, dbg
);
1529 wil6210_debugfs_init_offset(wil
, dbg
, wil
, dbg_wil_off
);
1530 wil6210_debugfs_init_offset(wil
, dbg
, (void * __force
)wil
->csr
,
1532 wil6210_debugfs_init_offset(wil
, dbg
, NULL
, dbg_statics
);
1534 wil6210_debugfs_create_pseudo_ISR(wil
, dbg
);
1536 wil6210_debugfs_create_ITR_CNT(wil
, dbg
);
1541 void wil6210_debugfs_remove(struct wil6210_priv
*wil
)
1543 debugfs_remove_recursive(wil
->debug
);
1546 /* free pmc memory without sending command to fw, as it will
1547 * be reset on the way down anyway
1549 wil_pmc_free(wil
, false);