wil6210: use bitmap API for "status"
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / ath / wil6210 / debugfs.c
1 /*
2  * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
3  *
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.
7  *
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.
15  */
16
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>
23
24 #include "wil6210.h"
25 #include "wmi.h"
26 #include "txrx.h"
27
28 /* Nasty hack. Better have per device instances */
29 static u32 mem_addr;
30 static u32 dbg_txdesc_index;
31 static u32 dbg_vring_index; /* 24+ for Rx, 0..23 for Tx */
32
33 enum dbg_off_type {
34         doff_u32 = 0,
35         doff_x32 = 1,
36         doff_ulong = 2,
37         doff_io32 = 3,
38 };
39
40 /* offset to "wil" */
41 struct dbg_off {
42         const char *name;
43         umode_t mode;
44         ulong off;
45         enum dbg_off_type type;
46 };
47
48 static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
49                             const char *name, struct vring *vring,
50                             char _s, char _h)
51 {
52         void __iomem *x = wmi_addr(wil, vring->hwtail);
53         u32 v;
54
55         seq_printf(s, "VRING %s = {\n", name);
56         seq_printf(s, "  pa     = %pad\n", &vring->pa);
57         seq_printf(s, "  va     = 0x%p\n", vring->va);
58         seq_printf(s, "  size   = %d\n", vring->size);
59         seq_printf(s, "  swtail = %d\n", vring->swtail);
60         seq_printf(s, "  swhead = %d\n", vring->swhead);
61         seq_printf(s, "  hwtail = [0x%08x] -> ", vring->hwtail);
62         if (x) {
63                 v = ioread32(x);
64                 seq_printf(s, "0x%08x = %d\n", v, v);
65         } else {
66                 seq_puts(s, "???\n");
67         }
68
69         if (vring->va && (vring->size < 1025)) {
70                 uint i;
71
72                 for (i = 0; i < vring->size; i++) {
73                         volatile struct vring_tx_desc *d = &vring->va[i].tx;
74
75                         if ((i % 64) == 0 && (i != 0))
76                                 seq_puts(s, "\n");
77                         seq_printf(s, "%c", (d->dma.status & BIT(0)) ?
78                                         _s : (vring->ctx[i].skb ? _h : 'h'));
79                 }
80                 seq_puts(s, "\n");
81         }
82         seq_puts(s, "}\n");
83 }
84
85 static int wil_vring_debugfs_show(struct seq_file *s, void *data)
86 {
87         uint i;
88         struct wil6210_priv *wil = s->private;
89
90         wil_print_vring(s, wil, "rx", &wil->vring_rx, 'S', '_');
91
92         for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
93                 struct vring *vring = &wil->vring_tx[i];
94                 struct vring_tx_data *txdata = &wil->vring_tx_data[i];
95
96                 if (vring->va) {
97                         int cid = wil->vring2cid_tid[i][0];
98                         int tid = wil->vring2cid_tid[i][1];
99                         u32 swhead = vring->swhead;
100                         u32 swtail = vring->swtail;
101                         int used = (vring->size + swhead - swtail)
102                                    % vring->size;
103                         int avail = vring->size - used - 1;
104                         char name[10];
105                         /* performance monitoring */
106                         cycles_t now = get_cycles();
107                         uint64_t idle = txdata->idle * 100;
108                         uint64_t total = now - txdata->begin;
109
110                         do_div(idle, total);
111                         txdata->begin = now;
112                         txdata->idle = 0ULL;
113
114                         snprintf(name, sizeof(name), "tx_%2d", i);
115
116                         seq_printf(s,
117                                    "\n%pM CID %d TID %d BACK([%d] %d TU A%s) [%3d|%3d] idle %3d%%\n",
118                                    wil->sta[cid].addr, cid, tid,
119                                    txdata->agg_wsize, txdata->agg_timeout,
120                                    txdata->agg_amsdu ? "+" : "-",
121                                    used, avail, (int)idle);
122
123                         wil_print_vring(s, wil, name, vring, '_', 'H');
124                 }
125         }
126
127         return 0;
128 }
129
130 static int wil_vring_seq_open(struct inode *inode, struct file *file)
131 {
132         return single_open(file, wil_vring_debugfs_show, inode->i_private);
133 }
134
135 static const struct file_operations fops_vring = {
136         .open           = wil_vring_seq_open,
137         .release        = single_release,
138         .read           = seq_read,
139         .llseek         = seq_lseek,
140 };
141
142 static void wil_print_ring(struct seq_file *s, const char *prefix,
143                            void __iomem *off)
144 {
145         struct wil6210_priv *wil = s->private;
146         struct wil6210_mbox_ring r;
147         int rsize;
148         uint i;
149
150         wil_memcpy_fromio_32(&r, off, sizeof(r));
151         wil_mbox_ring_le2cpus(&r);
152         /*
153          * we just read memory block from NIC. This memory may be
154          * garbage. Check validity before using it.
155          */
156         rsize = r.size / sizeof(struct wil6210_mbox_ring_desc);
157
158         seq_printf(s, "ring %s = {\n", prefix);
159         seq_printf(s, "  base = 0x%08x\n", r.base);
160         seq_printf(s, "  size = 0x%04x bytes -> %d entries\n", r.size, rsize);
161         seq_printf(s, "  tail = 0x%08x\n", r.tail);
162         seq_printf(s, "  head = 0x%08x\n", r.head);
163         seq_printf(s, "  entry size = %d\n", r.entry_size);
164
165         if (r.size % sizeof(struct wil6210_mbox_ring_desc)) {
166                 seq_printf(s, "  ??? size is not multiple of %zd, garbage?\n",
167                            sizeof(struct wil6210_mbox_ring_desc));
168                 goto out;
169         }
170
171         if (!wmi_addr(wil, r.base) ||
172             !wmi_addr(wil, r.tail) ||
173             !wmi_addr(wil, r.head)) {
174                 seq_puts(s, "  ??? pointers are garbage?\n");
175                 goto out;
176         }
177
178         for (i = 0; i < rsize; i++) {
179                 struct wil6210_mbox_ring_desc d;
180                 struct wil6210_mbox_hdr hdr;
181                 size_t delta = i * sizeof(d);
182                 void __iomem *x = wil->csr + HOSTADDR(r.base) + delta;
183
184                 wil_memcpy_fromio_32(&d, x, sizeof(d));
185
186                 seq_printf(s, "  [%2x] %s %s%s 0x%08x", i,
187                            d.sync ? "F" : "E",
188                            (r.tail - r.base == delta) ? "t" : " ",
189                            (r.head - r.base == delta) ? "h" : " ",
190                            le32_to_cpu(d.addr));
191                 if (0 == wmi_read_hdr(wil, d.addr, &hdr)) {
192                         u16 len = le16_to_cpu(hdr.len);
193
194                         seq_printf(s, " -> %04x %04x %04x %02x\n",
195                                    le16_to_cpu(hdr.seq), len,
196                                    le16_to_cpu(hdr.type), hdr.flags);
197                         if (len <= MAX_MBOXITEM_SIZE) {
198                                 int n = 0;
199                                 char printbuf[16 * 3 + 2];
200                                 unsigned char databuf[MAX_MBOXITEM_SIZE];
201                                 void __iomem *src = wmi_buffer(wil, d.addr) +
202                                         sizeof(struct wil6210_mbox_hdr);
203                                 /*
204                                  * No need to check @src for validity -
205                                  * we already validated @d.addr while
206                                  * reading header
207                                  */
208                                 wil_memcpy_fromio_32(databuf, src, len);
209                                 while (n < len) {
210                                         int l = min(len - n, 16);
211
212                                         hex_dump_to_buffer(databuf + n, l,
213                                                            16, 1, printbuf,
214                                                            sizeof(printbuf),
215                                                            false);
216                                         seq_printf(s, "      : %s\n", printbuf);
217                                         n += l;
218                                 }
219                         }
220                 } else {
221                         seq_puts(s, "\n");
222                 }
223         }
224  out:
225         seq_puts(s, "}\n");
226 }
227
228 static int wil_mbox_debugfs_show(struct seq_file *s, void *data)
229 {
230         struct wil6210_priv *wil = s->private;
231
232         wil_print_ring(s, "tx", wil->csr + HOST_MBOX +
233                        offsetof(struct wil6210_mbox_ctl, tx));
234         wil_print_ring(s, "rx", wil->csr + HOST_MBOX +
235                        offsetof(struct wil6210_mbox_ctl, rx));
236
237         return 0;
238 }
239
240 static int wil_mbox_seq_open(struct inode *inode, struct file *file)
241 {
242         return single_open(file, wil_mbox_debugfs_show, inode->i_private);
243 }
244
245 static const struct file_operations fops_mbox = {
246         .open           = wil_mbox_seq_open,
247         .release        = single_release,
248         .read           = seq_read,
249         .llseek         = seq_lseek,
250 };
251
252 static int wil_debugfs_iomem_x32_set(void *data, u64 val)
253 {
254         iowrite32(val, (void __iomem *)data);
255         wmb(); /* make sure write propagated to HW */
256
257         return 0;
258 }
259
260 static int wil_debugfs_iomem_x32_get(void *data, u64 *val)
261 {
262         *val = ioread32((void __iomem *)data);
263
264         return 0;
265 }
266
267 DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get,
268                         wil_debugfs_iomem_x32_set, "0x%08llx\n");
269
270 static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
271                                                    umode_t mode,
272                                                    struct dentry *parent,
273                                                    void *value)
274 {
275         return debugfs_create_file(name, mode, parent, value,
276                                    &fops_iomem_x32);
277 }
278
279 static int wil_debugfs_ulong_set(void *data, u64 val)
280 {
281         *(ulong *)data = val;
282         return 0;
283 }
284
285 static int wil_debugfs_ulong_get(void *data, u64 *val)
286 {
287         *val = *(ulong *)data;
288         return 0;
289 }
290
291 DEFINE_SIMPLE_ATTRIBUTE(wil_fops_ulong, wil_debugfs_ulong_get,
292                         wil_debugfs_ulong_set, "%llu\n");
293
294 static struct dentry *wil_debugfs_create_ulong(const char *name, umode_t mode,
295                                                struct dentry *parent,
296                                                ulong *value)
297 {
298         return debugfs_create_file(name, mode, parent, value, &wil_fops_ulong);
299 }
300
301 /**
302  * wil6210_debugfs_init_offset - create set of debugfs files
303  * @wil - driver's context, used for printing
304  * @dbg - directory on the debugfs, where files will be created
305  * @base - base address used in address calculation
306  * @tbl - table with file descriptions. Should be terminated with empty element.
307  *
308  * Creates files accordingly to the @tbl.
309  */
310 static void wil6210_debugfs_init_offset(struct wil6210_priv *wil,
311                                         struct dentry *dbg, void *base,
312                                         const struct dbg_off * const tbl)
313 {
314         int i;
315
316         for (i = 0; tbl[i].name; i++) {
317                 struct dentry *f;
318
319                 switch (tbl[i].type) {
320                 case doff_u32:
321                         f = debugfs_create_u32(tbl[i].name, tbl[i].mode, dbg,
322                                                base + tbl[i].off);
323                         break;
324                 case doff_x32:
325                         f = debugfs_create_x32(tbl[i].name, tbl[i].mode, dbg,
326                                                base + tbl[i].off);
327                         break;
328                 case doff_ulong:
329                         f = wil_debugfs_create_ulong(tbl[i].name, tbl[i].mode,
330                                                      dbg, base + tbl[i].off);
331                         break;
332                 case doff_io32:
333                         f = wil_debugfs_create_iomem_x32(tbl[i].name,
334                                                          tbl[i].mode, dbg,
335                                                          base + tbl[i].off);
336                         break;
337                 default:
338                         f = ERR_PTR(-EINVAL);
339                 }
340                 if (IS_ERR_OR_NULL(f))
341                         wil_err(wil, "Create file \"%s\": err %ld\n",
342                                 tbl[i].name, PTR_ERR(f));
343         }
344 }
345
346 static const struct dbg_off isr_off[] = {
347         {"ICC", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICC), doff_io32},
348         {"ICR", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICR), doff_io32},
349         {"ICM", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICM), doff_io32},
350         {"ICS",           S_IWUSR, offsetof(struct RGF_ICR, ICS), doff_io32},
351         {"IMV", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, IMV), doff_io32},
352         {"IMS",           S_IWUSR, offsetof(struct RGF_ICR, IMS), doff_io32},
353         {"IMC",           S_IWUSR, offsetof(struct RGF_ICR, IMC), doff_io32},
354         {},
355 };
356
357 static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil,
358                                       const char *name,
359                                       struct dentry *parent, u32 off)
360 {
361         struct dentry *d = debugfs_create_dir(name, parent);
362
363         if (IS_ERR_OR_NULL(d))
364                 return -ENODEV;
365
366         wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr + off,
367                                     isr_off);
368
369         return 0;
370 }
371
372 static const struct dbg_off pseudo_isr_off[] = {
373         {"CAUSE",   S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE), doff_io32},
374         {"MASK_SW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW), doff_io32},
375         {"MASK_FW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW), doff_io32},
376         {},
377 };
378
379 static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil,
380                                              struct dentry *parent)
381 {
382         struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent);
383
384         if (IS_ERR_OR_NULL(d))
385                 return -ENODEV;
386
387         wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr,
388                                     pseudo_isr_off);
389
390         return 0;
391 }
392
393 static const struct dbg_off itr_cnt_off[] = {
394         {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32},
395         {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32},
396         {"CTL",  S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32},
397         {},
398 };
399
400 static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil,
401                                           struct dentry *parent)
402 {
403         struct dentry *d = debugfs_create_dir("ITR_CNT", parent);
404
405         if (IS_ERR_OR_NULL(d))
406                 return -ENODEV;
407
408         wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr,
409                                     itr_cnt_off);
410
411         return 0;
412 }
413
414 static int wil_memread_debugfs_show(struct seq_file *s, void *data)
415 {
416         struct wil6210_priv *wil = s->private;
417         void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr));
418
419         if (a)
420                 seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a));
421         else
422                 seq_printf(s, "[0x%08x] = INVALID\n", mem_addr);
423
424         return 0;
425 }
426
427 static int wil_memread_seq_open(struct inode *inode, struct file *file)
428 {
429         return single_open(file, wil_memread_debugfs_show, inode->i_private);
430 }
431
432 static const struct file_operations fops_memread = {
433         .open           = wil_memread_seq_open,
434         .release        = single_release,
435         .read           = seq_read,
436         .llseek         = seq_lseek,
437 };
438
439 static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
440                                     size_t count, loff_t *ppos)
441 {
442         enum { max_count = 4096 };
443         struct debugfs_blob_wrapper *blob = file->private_data;
444         loff_t pos = *ppos;
445         size_t available = blob->size;
446         void *buf;
447         size_t ret;
448
449         if (pos < 0)
450                 return -EINVAL;
451
452         if (pos >= available || !count)
453                 return 0;
454
455         if (count > available - pos)
456                 count = available - pos;
457         if (count > max_count)
458                 count = max_count;
459
460         buf = kmalloc(count, GFP_KERNEL);
461         if (!buf)
462                 return -ENOMEM;
463
464         wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data +
465                              pos, count);
466
467         ret = copy_to_user(user_buf, buf, count);
468         kfree(buf);
469         if (ret == count)
470                 return -EFAULT;
471
472         count -= ret;
473         *ppos = pos + count;
474
475         return count;
476 }
477
478 static const struct file_operations fops_ioblob = {
479         .read =         wil_read_file_ioblob,
480         .open =         simple_open,
481         .llseek =       default_llseek,
482 };
483
484 static
485 struct dentry *wil_debugfs_create_ioblob(const char *name,
486                                          umode_t mode,
487                                          struct dentry *parent,
488                                          struct debugfs_blob_wrapper *blob)
489 {
490         return debugfs_create_file(name, mode, parent, blob, &fops_ioblob);
491 }
492
493 /*---reset---*/
494 static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
495                                     size_t len, loff_t *ppos)
496 {
497         struct wil6210_priv *wil = file->private_data;
498         struct net_device *ndev = wil_to_ndev(wil);
499
500         /**
501          * BUG:
502          * this code does NOT sync device state with the rest of system
503          * use with care, debug only!!!
504          */
505         rtnl_lock();
506         dev_close(ndev);
507         ndev->flags &= ~IFF_UP;
508         rtnl_unlock();
509         wil_reset(wil);
510
511         return len;
512 }
513
514 static const struct file_operations fops_reset = {
515         .write = wil_write_file_reset,
516         .open  = simple_open,
517 };
518
519 /*---write channel 1..4 to rxon for it, 0 to rxoff---*/
520 static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
521                                    size_t len, loff_t *ppos)
522 {
523         struct wil6210_priv *wil = file->private_data;
524         int rc;
525         long channel;
526         bool on;
527
528         char *kbuf = kmalloc(len + 1, GFP_KERNEL);
529
530         if (!kbuf)
531                 return -ENOMEM;
532         if (copy_from_user(kbuf, buf, len)) {
533                 kfree(kbuf);
534                 return -EIO;
535         }
536
537         kbuf[len] = '\0';
538         rc = kstrtol(kbuf, 0, &channel);
539         kfree(kbuf);
540         if (rc)
541                 return rc;
542
543         if ((channel < 0) || (channel > 4)) {
544                 wil_err(wil, "Invalid channel %ld\n", channel);
545                 return -EINVAL;
546         }
547         on = !!channel;
548
549         if (on) {
550                 rc = wmi_set_channel(wil, (int)channel);
551                 if (rc)
552                         return rc;
553         }
554
555         rc = wmi_rxon(wil, on);
556         if (rc)
557                 return rc;
558
559         return len;
560 }
561
562 static const struct file_operations fops_rxon = {
563         .write = wil_write_file_rxon,
564         .open  = simple_open,
565 };
566
567 /* block ack for vring 0
568  * write 0 to it to trigger DELBA
569  * write positive agg_wsize to trigger ADDBA
570  */
571 static ssize_t wil_write_addba(struct file *file, const char __user *buf,
572                                size_t len, loff_t *ppos)
573 {
574         struct wil6210_priv *wil = file->private_data;
575         int rc;
576         uint agg_wsize;
577         char *kbuf = kmalloc(len + 1, GFP_KERNEL);
578
579         if (!kbuf)
580                 return -ENOMEM;
581
582         rc = simple_write_to_buffer(kbuf, len, ppos, buf, len);
583         if (rc != len) {
584                 kfree(kbuf);
585                 return rc >= 0 ? -EIO : rc;
586         }
587
588         kbuf[len] = '\0';
589         rc = kstrtouint(kbuf, 0, &agg_wsize);
590         kfree(kbuf);
591
592         if (rc)
593                 return rc;
594
595         if (!wil->vring_tx[0].va)
596                 return -EINVAL;
597
598         if (agg_wsize > 0)
599                 wmi_addba(wil, 0, agg_wsize, 0);
600         else
601                 wmi_delba_tx(wil, 0, 0);
602
603         return len;
604 }
605
606 static const struct file_operations fops_addba = {
607         .write = wil_write_addba,
608         .open  = simple_open,
609 };
610
611 /*---tx_mgmt---*/
612 /* Write mgmt frame to this file to send it */
613 static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
614                                      size_t len, loff_t *ppos)
615 {
616         struct wil6210_priv *wil = file->private_data;
617         struct wiphy *wiphy = wil_to_wiphy(wil);
618         struct wireless_dev *wdev = wil_to_wdev(wil);
619         struct cfg80211_mgmt_tx_params params;
620         int rc;
621         void *frame = kmalloc(len, GFP_KERNEL);
622
623         if (!frame)
624                 return -ENOMEM;
625
626         if (copy_from_user(frame, buf, len)) {
627                 kfree(frame);
628                 return -EIO;
629         }
630
631         params.buf = frame;
632         params.len = len;
633         params.chan = wdev->preset_chandef.chan;
634
635         rc = wil_cfg80211_mgmt_tx(wiphy, wdev, &params, NULL);
636
637         kfree(frame);
638         wil_info(wil, "%s() -> %d\n", __func__, rc);
639
640         return len;
641 }
642
643 static const struct file_operations fops_txmgmt = {
644         .write = wil_write_file_txmgmt,
645         .open  = simple_open,
646 };
647
648 /* Write WMI command (w/o mbox header) to this file to send it
649  * WMI starts from wil6210_mbox_hdr_wmi header
650  */
651 static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
652                                   size_t len, loff_t *ppos)
653 {
654         struct wil6210_priv *wil = file->private_data;
655         struct wil6210_mbox_hdr_wmi *wmi;
656         void *cmd;
657         int cmdlen = len - sizeof(struct wil6210_mbox_hdr_wmi);
658         u16 cmdid;
659         int rc, rc1;
660
661         if (cmdlen <= 0)
662                 return -EINVAL;
663
664         wmi = kmalloc(len, GFP_KERNEL);
665         if (!wmi)
666                 return -ENOMEM;
667
668         rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
669         if (rc < 0) {
670                 kfree(wmi);
671                 return rc;
672         }
673
674         cmd = &wmi[1];
675         cmdid = le16_to_cpu(wmi->id);
676
677         rc1 = wmi_send(wil, cmdid, cmd, cmdlen);
678         kfree(wmi);
679
680         wil_info(wil, "%s(0x%04x[%d]) -> %d\n", __func__, cmdid, cmdlen, rc1);
681
682         return rc;
683 }
684
685 static const struct file_operations fops_wmi = {
686         .write = wil_write_file_wmi,
687         .open  = simple_open,
688 };
689
690 static void wil_seq_hexdump(struct seq_file *s, void *p, int len,
691                             const char *prefix)
692 {
693         char printbuf[16 * 3 + 2];
694         int i = 0;
695
696         while (i < len) {
697                 int l = min(len - i, 16);
698
699                 hex_dump_to_buffer(p + i, l, 16, 1, printbuf,
700                                    sizeof(printbuf), false);
701                 seq_printf(s, "%s%s\n", prefix, printbuf);
702                 i += l;
703         }
704 }
705
706 static void wil_seq_print_skb(struct seq_file *s, struct sk_buff *skb)
707 {
708         int i = 0;
709         int len = skb_headlen(skb);
710         void *p = skb->data;
711         int nr_frags = skb_shinfo(skb)->nr_frags;
712
713         seq_printf(s, "    len = %d\n", len);
714         wil_seq_hexdump(s, p, len, "      : ");
715
716         if (nr_frags) {
717                 seq_printf(s, "    nr_frags = %d\n", nr_frags);
718                 for (i = 0; i < nr_frags; i++) {
719                         const struct skb_frag_struct *frag =
720                                         &skb_shinfo(skb)->frags[i];
721
722                         len = skb_frag_size(frag);
723                         p = skb_frag_address_safe(frag);
724                         seq_printf(s, "    [%2d] : len = %d\n", i, len);
725                         wil_seq_hexdump(s, p, len, "      : ");
726                 }
727         }
728 }
729
730 /*---------Tx/Rx descriptor------------*/
731 static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
732 {
733         struct wil6210_priv *wil = s->private;
734         struct vring *vring;
735         bool tx = (dbg_vring_index < WIL6210_MAX_TX_RINGS);
736
737         vring = tx ? &wil->vring_tx[dbg_vring_index] : &wil->vring_rx;
738
739         if (!vring->va) {
740                 if (tx)
741                         seq_printf(s, "No Tx[%2d] VRING\n", dbg_vring_index);
742                 else
743                         seq_puts(s, "No Rx VRING\n");
744                 return 0;
745         }
746
747         if (dbg_txdesc_index < vring->size) {
748                 /* use struct vring_tx_desc for Rx as well,
749                  * only field used, .dma.length, is the same
750                  */
751                 volatile struct vring_tx_desc *d =
752                                 &vring->va[dbg_txdesc_index].tx;
753                 volatile u32 *u = (volatile u32 *)d;
754                 struct sk_buff *skb = vring->ctx[dbg_txdesc_index].skb;
755
756                 if (tx)
757                         seq_printf(s, "Tx[%2d][%3d] = {\n", dbg_vring_index,
758                                    dbg_txdesc_index);
759                 else
760                         seq_printf(s, "Rx[%3d] = {\n", dbg_txdesc_index);
761                 seq_printf(s, "  MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
762                            u[0], u[1], u[2], u[3]);
763                 seq_printf(s, "  DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
764                            u[4], u[5], u[6], u[7]);
765                 seq_printf(s, "  SKB = 0x%p\n", skb);
766
767                 if (skb) {
768                         skb_get(skb);
769                         wil_seq_print_skb(s, skb);
770                         kfree_skb(skb);
771                 }
772                 seq_puts(s, "}\n");
773         } else {
774                 if (tx)
775                         seq_printf(s, "[%2d] TxDesc index (%d) >= size (%d)\n",
776                                    dbg_vring_index, dbg_txdesc_index,
777                                    vring->size);
778                 else
779                         seq_printf(s, "RxDesc index (%d) >= size (%d)\n",
780                                    dbg_txdesc_index, vring->size);
781         }
782
783         return 0;
784 }
785
786 static int wil_txdesc_seq_open(struct inode *inode, struct file *file)
787 {
788         return single_open(file, wil_txdesc_debugfs_show, inode->i_private);
789 }
790
791 static const struct file_operations fops_txdesc = {
792         .open           = wil_txdesc_seq_open,
793         .release        = single_release,
794         .read           = seq_read,
795         .llseek         = seq_lseek,
796 };
797
798 /*---------beamforming------------*/
799 static char *wil_bfstatus_str(u32 status)
800 {
801         switch (status) {
802         case 0:
803                 return "Failed";
804         case 1:
805                 return "OK";
806         case 2:
807                 return "Retrying";
808         default:
809                 return "??";
810         }
811 }
812
813 static bool is_all_zeros(void * const x_, size_t sz)
814 {
815         /* if reply is all-0, ignore this CID */
816         u32 *x = x_;
817         int n;
818
819         for (n = 0; n < sz / sizeof(*x); n++)
820                 if (x[n])
821                         return false;
822
823         return true;
824 }
825
826 static int wil_bf_debugfs_show(struct seq_file *s, void *data)
827 {
828         int rc;
829         int i;
830         struct wil6210_priv *wil = s->private;
831         struct wmi_notify_req_cmd cmd = {
832                 .interval_usec = 0,
833         };
834         struct {
835                 struct wil6210_mbox_hdr_wmi wmi;
836                 struct wmi_notify_req_done_event evt;
837         } __packed reply;
838
839         for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
840                 u32 status;
841
842                 cmd.cid = i;
843                 rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
844                               WMI_NOTIFY_REQ_DONE_EVENTID, &reply,
845                               sizeof(reply), 20);
846                 /* if reply is all-0, ignore this CID */
847                 if (rc || is_all_zeros(&reply.evt, sizeof(reply.evt)))
848                         continue;
849
850                 status = le32_to_cpu(reply.evt.status);
851                 seq_printf(s, "CID %d {\n"
852                            "  TSF = 0x%016llx\n"
853                            "  TxMCS = %2d TxTpt = %4d\n"
854                            "  SQI = %4d\n"
855                            "  Status = 0x%08x %s\n"
856                            "  Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n"
857                            "  Goodput(rx:tx) %4d:%4d\n"
858                            "}\n",
859                            i,
860                            le64_to_cpu(reply.evt.tsf),
861                            le16_to_cpu(reply.evt.bf_mcs),
862                            le32_to_cpu(reply.evt.tx_tpt),
863                            reply.evt.sqi,
864                            status, wil_bfstatus_str(status),
865                            le16_to_cpu(reply.evt.my_rx_sector),
866                            le16_to_cpu(reply.evt.my_tx_sector),
867                            le16_to_cpu(reply.evt.other_rx_sector),
868                            le16_to_cpu(reply.evt.other_tx_sector),
869                            le32_to_cpu(reply.evt.rx_goodput),
870                            le32_to_cpu(reply.evt.tx_goodput));
871         }
872         return 0;
873 }
874
875 static int wil_bf_seq_open(struct inode *inode, struct file *file)
876 {
877         return single_open(file, wil_bf_debugfs_show, inode->i_private);
878 }
879
880 static const struct file_operations fops_bf = {
881         .open           = wil_bf_seq_open,
882         .release        = single_release,
883         .read           = seq_read,
884         .llseek         = seq_lseek,
885 };
886
887 /*---------SSID------------*/
888 static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf,
889                                   size_t count, loff_t *ppos)
890 {
891         struct wil6210_priv *wil = file->private_data;
892         struct wireless_dev *wdev = wil_to_wdev(wil);
893
894         return simple_read_from_buffer(user_buf, count, ppos,
895                                        wdev->ssid, wdev->ssid_len);
896 }
897
898 static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf,
899                                    size_t count, loff_t *ppos)
900 {
901         struct wil6210_priv *wil = file->private_data;
902         struct wireless_dev *wdev = wil_to_wdev(wil);
903         struct net_device *ndev = wil_to_ndev(wil);
904
905         if (*ppos != 0) {
906                 wil_err(wil, "Unable to set SSID substring from [%d]\n",
907                         (int)*ppos);
908                 return -EINVAL;
909         }
910
911         if (count > sizeof(wdev->ssid)) {
912                 wil_err(wil, "SSID too long, len = %d\n", (int)count);
913                 return -EINVAL;
914         }
915         if (netif_running(ndev)) {
916                 wil_err(wil, "Unable to change SSID on running interface\n");
917                 return -EINVAL;
918         }
919
920         wdev->ssid_len = count;
921         return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos,
922                                       buf, count);
923 }
924
925 static const struct file_operations fops_ssid = {
926         .read = wil_read_file_ssid,
927         .write = wil_write_file_ssid,
928         .open  = simple_open,
929 };
930
931 /*---------temp------------*/
932 static void print_temp(struct seq_file *s, const char *prefix, u32 t)
933 {
934         switch (t) {
935         case 0:
936         case ~(u32)0:
937                 seq_printf(s, "%s N/A\n", prefix);
938         break;
939         default:
940                 seq_printf(s, "%s %d.%03d\n", prefix, t / 1000, t % 1000);
941                 break;
942         }
943 }
944
945 static int wil_temp_debugfs_show(struct seq_file *s, void *data)
946 {
947         struct wil6210_priv *wil = s->private;
948         u32 t_m, t_r;
949         int rc = wmi_get_temperature(wil, &t_m, &t_r);
950
951         if (rc) {
952                 seq_puts(s, "Failed\n");
953                 return 0;
954         }
955
956         print_temp(s, "T_mac   =", t_m);
957         print_temp(s, "T_radio =", t_r);
958
959         return 0;
960 }
961
962 static int wil_temp_seq_open(struct inode *inode, struct file *file)
963 {
964         return single_open(file, wil_temp_debugfs_show, inode->i_private);
965 }
966
967 static const struct file_operations fops_temp = {
968         .open           = wil_temp_seq_open,
969         .release        = single_release,
970         .read           = seq_read,
971         .llseek         = seq_lseek,
972 };
973
974 /*---------freq------------*/
975 static int wil_freq_debugfs_show(struct seq_file *s, void *data)
976 {
977         struct wil6210_priv *wil = s->private;
978         struct wireless_dev *wdev = wil_to_wdev(wil);
979         u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
980
981         seq_printf(s, "Freq = %d\n", freq);
982
983         return 0;
984 }
985
986 static int wil_freq_seq_open(struct inode *inode, struct file *file)
987 {
988         return single_open(file, wil_freq_debugfs_show, inode->i_private);
989 }
990
991 static const struct file_operations fops_freq = {
992         .open           = wil_freq_seq_open,
993         .release        = single_release,
994         .read           = seq_read,
995         .llseek         = seq_lseek,
996 };
997
998 /*---------link------------*/
999 static int wil_link_debugfs_show(struct seq_file *s, void *data)
1000 {
1001         struct wil6210_priv *wil = s->private;
1002         struct station_info sinfo;
1003         int i, rc;
1004
1005         for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
1006                 struct wil_sta_info *p = &wil->sta[i];
1007                 char *status = "unknown";
1008
1009                 switch (p->status) {
1010                 case wil_sta_unused:
1011                         status = "unused   ";
1012                         break;
1013                 case wil_sta_conn_pending:
1014                         status = "pending  ";
1015                         break;
1016                 case wil_sta_connected:
1017                         status = "connected";
1018                         break;
1019                 }
1020                 seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
1021                            (p->data_port_open ? " data_port_open" : ""));
1022
1023                 if (p->status == wil_sta_connected) {
1024                         rc = wil_cid_fill_sinfo(wil, i, &sinfo);
1025                         if (rc)
1026                                 return rc;
1027
1028                         seq_printf(s, "  Tx_mcs = %d\n", sinfo.txrate.mcs);
1029                         seq_printf(s, "  Rx_mcs = %d\n", sinfo.rxrate.mcs);
1030                         seq_printf(s, "  SQ     = %d\n", sinfo.signal);
1031                 }
1032         }
1033
1034         return 0;
1035 }
1036
1037 static int wil_link_seq_open(struct inode *inode, struct file *file)
1038 {
1039         return single_open(file, wil_link_debugfs_show, inode->i_private);
1040 }
1041
1042 static const struct file_operations fops_link = {
1043         .open           = wil_link_seq_open,
1044         .release        = single_release,
1045         .read           = seq_read,
1046         .llseek         = seq_lseek,
1047 };
1048
1049 /*---------info------------*/
1050 static int wil_info_debugfs_show(struct seq_file *s, void *data)
1051 {
1052         struct wil6210_priv *wil = s->private;
1053         struct net_device *ndev = wil_to_ndev(wil);
1054         int is_ac = power_supply_is_system_supplied();
1055         int rx = atomic_xchg(&wil->isr_count_rx, 0);
1056         int tx = atomic_xchg(&wil->isr_count_tx, 0);
1057         static ulong rxf_old, txf_old;
1058         ulong rxf = ndev->stats.rx_packets;
1059         ulong txf = ndev->stats.tx_packets;
1060         unsigned int i;
1061
1062         /* >0 : AC; 0 : battery; <0 : error */
1063         seq_printf(s, "AC powered : %d\n", is_ac);
1064         seq_printf(s, "Rx irqs:packets : %8d : %8ld\n", rx, rxf - rxf_old);
1065         seq_printf(s, "Tx irqs:packets : %8d : %8ld\n", tx, txf - txf_old);
1066         rxf_old = rxf;
1067         txf_old = txf;
1068
1069 #define CHECK_QSTATE(x) (state & BIT(__QUEUE_STATE_ ## x)) ? \
1070         " " __stringify(x) : ""
1071
1072         for (i = 0; i < ndev->num_tx_queues; i++) {
1073                 struct netdev_queue *txq = netdev_get_tx_queue(ndev, i);
1074                 unsigned long state = txq->state;
1075
1076                 seq_printf(s, "Tx queue[%i] state : 0x%lx%s%s%s\n", i, state,
1077                            CHECK_QSTATE(DRV_XOFF),
1078                            CHECK_QSTATE(STACK_XOFF),
1079                            CHECK_QSTATE(FROZEN)
1080                           );
1081         }
1082 #undef CHECK_QSTATE
1083         return 0;
1084 }
1085
1086 static int wil_info_seq_open(struct inode *inode, struct file *file)
1087 {
1088         return single_open(file, wil_info_debugfs_show, inode->i_private);
1089 }
1090
1091 static const struct file_operations fops_info = {
1092         .open           = wil_info_seq_open,
1093         .release        = single_release,
1094         .read           = seq_read,
1095         .llseek         = seq_lseek,
1096 };
1097
1098 /*---------recovery------------*/
1099 /* mode = [manual|auto]
1100  * state = [idle|pending|running]
1101  */
1102 static ssize_t wil_read_file_recovery(struct file *file, char __user *user_buf,
1103                                       size_t count, loff_t *ppos)
1104 {
1105         struct wil6210_priv *wil = file->private_data;
1106         char buf[80];
1107         int n;
1108         static const char * const sstate[] = {"idle", "pending", "running"};
1109
1110         n = snprintf(buf, sizeof(buf), "mode = %s\nstate = %s\n",
1111                      no_fw_recovery ? "manual" : "auto",
1112                      sstate[wil->recovery_state]);
1113
1114         n = min_t(int, n, sizeof(buf));
1115
1116         return simple_read_from_buffer(user_buf, count, ppos,
1117                                        buf, n);
1118 }
1119
1120 static ssize_t wil_write_file_recovery(struct file *file,
1121                                        const char __user *buf_,
1122                                        size_t count, loff_t *ppos)
1123 {
1124         struct wil6210_priv *wil = file->private_data;
1125         static const char run_command[] = "run";
1126         char buf[sizeof(run_command) + 1]; /* to detect "runx" */
1127         ssize_t rc;
1128
1129         if (wil->recovery_state != fw_recovery_pending) {
1130                 wil_err(wil, "No recovery pending\n");
1131                 return -EINVAL;
1132         }
1133
1134         if (*ppos != 0) {
1135                 wil_err(wil, "Offset [%d]\n", (int)*ppos);
1136                 return -EINVAL;
1137         }
1138
1139         if (count > sizeof(buf)) {
1140                 wil_err(wil, "Input too long, len = %d\n", (int)count);
1141                 return -EINVAL;
1142         }
1143
1144         rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, buf_, count);
1145         if (rc < 0)
1146                 return rc;
1147
1148         buf[rc] = '\0';
1149         if (0 == strcmp(buf, run_command))
1150                 wil_set_recovery_state(wil, fw_recovery_running);
1151         else
1152                 wil_err(wil, "Bad recovery command \"%s\"\n", buf);
1153
1154         return rc;
1155 }
1156
1157 static const struct file_operations fops_recovery = {
1158         .read = wil_read_file_recovery,
1159         .write = wil_write_file_recovery,
1160         .open  = simple_open,
1161 };
1162
1163 /*---------Station matrix------------*/
1164 static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
1165 {
1166         int i;
1167         u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size;
1168
1169         seq_printf(s, "([%2d] %3d TU) 0x%03x [", r->buf_size, r->timeout,
1170                    r->head_seq_num);
1171         for (i = 0; i < r->buf_size; i++) {
1172                 if (i == index)
1173                         seq_printf(s, "%c", r->reorder_buf[i] ? 'O' : '|');
1174                 else
1175                         seq_printf(s, "%c", r->reorder_buf[i] ? '*' : '_');
1176         }
1177         seq_printf(s, "] last drop 0x%03x\n", r->ssn_last_drop);
1178 }
1179
1180 static int wil_sta_debugfs_show(struct seq_file *s, void *data)
1181 {
1182         struct wil6210_priv *wil = s->private;
1183         int i, tid;
1184         unsigned long flags;
1185
1186         for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
1187                 struct wil_sta_info *p = &wil->sta[i];
1188                 char *status = "unknown";
1189
1190                 switch (p->status) {
1191                 case wil_sta_unused:
1192                         status = "unused   ";
1193                         break;
1194                 case wil_sta_conn_pending:
1195                         status = "pending  ";
1196                         break;
1197                 case wil_sta_connected:
1198                         status = "connected";
1199                         break;
1200                 }
1201                 seq_printf(s, "[%d] %pM %s%s\n", i, p->addr, status,
1202                            (p->data_port_open ? " data_port_open" : ""));
1203
1204                 if (p->status == wil_sta_connected) {
1205                         spin_lock_irqsave(&p->tid_rx_lock, flags);
1206                         for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
1207                                 struct wil_tid_ampdu_rx *r = p->tid_rx[tid];
1208
1209                                 if (r) {
1210                                         seq_printf(s, "[%2d] ", tid);
1211                                         wil_print_rxtid(s, r);
1212                                 }
1213                         }
1214                         spin_unlock_irqrestore(&p->tid_rx_lock, flags);
1215                 }
1216         }
1217
1218         return 0;
1219 }
1220
1221 static int wil_sta_seq_open(struct inode *inode, struct file *file)
1222 {
1223         return single_open(file, wil_sta_debugfs_show, inode->i_private);
1224 }
1225
1226 static const struct file_operations fops_sta = {
1227         .open           = wil_sta_seq_open,
1228         .release        = single_release,
1229         .read           = seq_read,
1230         .llseek         = seq_lseek,
1231 };
1232
1233 /*----------------*/
1234 static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
1235                                        struct dentry *dbg)
1236 {
1237         int i;
1238         char name[32];
1239
1240         for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
1241                 struct debugfs_blob_wrapper *blob = &wil->blobs[i];
1242                 const struct fw_map *map = &fw_mapping[i];
1243
1244                 if (!map->name)
1245                         continue;
1246
1247                 blob->data = (void * __force)wil->csr + HOSTADDR(map->host);
1248                 blob->size = map->to - map->from;
1249                 snprintf(name, sizeof(name), "blob_%s", map->name);
1250                 wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob);
1251         }
1252 }
1253
1254 /* misc files */
1255 static const struct {
1256         const char *name;
1257         umode_t mode;
1258         const struct file_operations *fops;
1259 } dbg_files[] = {
1260         {"mbox",        S_IRUGO,                &fops_mbox},
1261         {"vrings",      S_IRUGO,                &fops_vring},
1262         {"stations",    S_IRUGO,                &fops_sta},
1263         {"desc",        S_IRUGO,                &fops_txdesc},
1264         {"bf",          S_IRUGO,                &fops_bf},
1265         {"ssid",        S_IRUGO | S_IWUSR,      &fops_ssid},
1266         {"mem_val",     S_IRUGO,                &fops_memread},
1267         {"reset",                 S_IWUSR,      &fops_reset},
1268         {"rxon",                  S_IWUSR,      &fops_rxon},
1269         {"tx_mgmt",               S_IWUSR,      &fops_txmgmt},
1270         {"wmi_send",              S_IWUSR,      &fops_wmi},
1271         {"addba",                 S_IWUSR,      &fops_addba},
1272         {"temp",        S_IRUGO,                &fops_temp},
1273         {"freq",        S_IRUGO,                &fops_freq},
1274         {"link",        S_IRUGO,                &fops_link},
1275         {"info",        S_IRUGO,                &fops_info},
1276         {"recovery",    S_IRUGO | S_IWUSR,      &fops_recovery},
1277 };
1278
1279 static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
1280                                        struct dentry *dbg)
1281 {
1282         int i;
1283
1284         for (i = 0; i < ARRAY_SIZE(dbg_files); i++)
1285                 debugfs_create_file(dbg_files[i].name, dbg_files[i].mode, dbg,
1286                                     wil, dbg_files[i].fops);
1287 }
1288
1289 /* interrupt control blocks */
1290 static const struct {
1291         const char *name;
1292         u32 icr_off;
1293 } dbg_icr[] = {
1294         {"USER_ICR",            HOSTADDR(RGF_USER_USER_ICR)},
1295         {"DMA_EP_TX_ICR",       HOSTADDR(RGF_DMA_EP_TX_ICR)},
1296         {"DMA_EP_RX_ICR",       HOSTADDR(RGF_DMA_EP_RX_ICR)},
1297         {"DMA_EP_MISC_ICR",     HOSTADDR(RGF_DMA_EP_MISC_ICR)},
1298 };
1299
1300 static void wil6210_debugfs_init_isr(struct wil6210_priv *wil,
1301                                      struct dentry *dbg)
1302 {
1303         int i;
1304
1305         for (i = 0; i < ARRAY_SIZE(dbg_icr); i++)
1306                 wil6210_debugfs_create_ISR(wil, dbg_icr[i].name, dbg,
1307                                            dbg_icr[i].icr_off);
1308 }
1309
1310 #define WIL_FIELD(name, mode, type) { __stringify(name), mode, \
1311         offsetof(struct wil6210_priv, name), type}
1312
1313 /* fields in struct wil6210_priv */
1314 static const struct dbg_off dbg_wil_off[] = {
1315         WIL_FIELD(secure_pcp,   S_IRUGO | S_IWUSR,      doff_u32),
1316         WIL_FIELD(status[0],    S_IRUGO | S_IWUSR,      doff_ulong),
1317         WIL_FIELD(fw_version,   S_IRUGO,                doff_u32),
1318         WIL_FIELD(hw_version,   S_IRUGO,                doff_x32),
1319         WIL_FIELD(recovery_count, S_IRUGO,              doff_u32),
1320         {},
1321 };
1322
1323 static const struct dbg_off dbg_wil_regs[] = {
1324         {"RGF_MAC_MTRL_COUNTER_0", S_IRUGO, HOSTADDR(RGF_MAC_MTRL_COUNTER_0),
1325                 doff_io32},
1326         {"RGF_USER_USAGE_1", S_IRUGO, HOSTADDR(RGF_USER_USAGE_1), doff_io32},
1327         {},
1328 };
1329
1330 /* static parameters */
1331 static const struct dbg_off dbg_statics[] = {
1332         {"desc_index",  S_IRUGO | S_IWUSR, (ulong)&dbg_txdesc_index, doff_u32},
1333         {"vring_index", S_IRUGO | S_IWUSR, (ulong)&dbg_vring_index, doff_u32},
1334         {"mem_addr",    S_IRUGO | S_IWUSR, (ulong)&mem_addr, doff_u32},
1335         {},
1336 };
1337
1338 int wil6210_debugfs_init(struct wil6210_priv *wil)
1339 {
1340         struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
1341                         wil_to_wiphy(wil)->debugfsdir);
1342
1343         if (IS_ERR_OR_NULL(dbg))
1344                 return -ENODEV;
1345
1346         wil6210_debugfs_init_files(wil, dbg);
1347         wil6210_debugfs_init_isr(wil, dbg);
1348         wil6210_debugfs_init_blobs(wil, dbg);
1349         wil6210_debugfs_init_offset(wil, dbg, wil, dbg_wil_off);
1350         wil6210_debugfs_init_offset(wil, dbg, (void * __force)wil->csr,
1351                                     dbg_wil_regs);
1352         wil6210_debugfs_init_offset(wil, dbg, NULL, dbg_statics);
1353
1354         wil6210_debugfs_create_pseudo_ISR(wil, dbg);
1355
1356         wil6210_debugfs_create_ITR_CNT(wil, dbg);
1357
1358         return 0;
1359 }
1360
1361 void wil6210_debugfs_remove(struct wil6210_priv *wil)
1362 {
1363         debugfs_remove_recursive(wil->debug);
1364         wil->debug = NULL;
1365 }