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