[go: nahoru, domu]

1/*
2 * Atheros CARL9170 driver
3 *
4 * debug(fs) probing
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; see the file COPYING.  If not, see
21 * http://www.gnu.org/licenses/.
22 *
23 * This file incorporates work covered by the following copyright and
24 * permission notice:
25 *    Copyright (c) 2008-2009 Atheros Communications, Inc.
26 *
27 *    Permission to use, copy, modify, and/or distribute this software for any
28 *    purpose with or without fee is hereby granted, provided that the above
29 *    copyright notice and this permission notice appear in all copies.
30 *
31 *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
32 *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
33 *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
34 *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
35 *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
36 *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37 *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38 */
39
40#include <linux/slab.h>
41#include <linux/module.h>
42#include <linux/seq_file.h>
43#include <linux/vmalloc.h>
44#include "carl9170.h"
45#include "cmd.h"
46
47#define ADD(buf, off, max, fmt, args...)				\
48	off += snprintf(&buf[off], max - off, fmt, ##args);
49
50
51struct carl9170_debugfs_fops {
52	unsigned int read_bufsize;
53	umode_t attr;
54	char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize,
55		      ssize_t *len);
56	ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size);
57	const struct file_operations fops;
58
59	enum carl9170_device_state req_dev_state;
60};
61
62static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
63				     size_t count, loff_t *ppos)
64{
65	struct carl9170_debugfs_fops *dfops;
66	struct ar9170 *ar;
67	char *buf = NULL, *res_buf = NULL;
68	ssize_t ret = 0;
69	int err = 0;
70
71	if (!count)
72		return 0;
73
74	ar = file->private_data;
75
76	if (!ar)
77		return -ENODEV;
78	dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops);
79
80	if (!dfops->read)
81		return -ENOSYS;
82
83	if (dfops->read_bufsize) {
84		buf = vmalloc(dfops->read_bufsize);
85		if (!buf)
86			return -ENOMEM;
87	}
88
89	mutex_lock(&ar->mutex);
90	if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
91		err = -ENODEV;
92		res_buf = buf;
93		goto out_free;
94	}
95
96	res_buf = dfops->read(ar, buf, dfops->read_bufsize, &ret);
97
98	if (ret > 0)
99		err = simple_read_from_buffer(userbuf, count, ppos,
100					      res_buf, ret);
101	else
102		err = ret;
103
104	WARN_ON_ONCE(dfops->read_bufsize && (res_buf != buf));
105
106out_free:
107	vfree(res_buf);
108	mutex_unlock(&ar->mutex);
109	return err;
110}
111
112static ssize_t carl9170_debugfs_write(struct file *file,
113	const char __user *userbuf, size_t count, loff_t *ppos)
114{
115	struct carl9170_debugfs_fops *dfops;
116	struct ar9170 *ar;
117	char *buf = NULL;
118	int err = 0;
119
120	if (!count)
121		return 0;
122
123	if (count > PAGE_SIZE)
124		return -E2BIG;
125
126	ar = file->private_data;
127
128	if (!ar)
129		return -ENODEV;
130	dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops);
131
132	if (!dfops->write)
133		return -ENOSYS;
134
135	buf = vmalloc(count);
136	if (!buf)
137		return -ENOMEM;
138
139	if (copy_from_user(buf, userbuf, count)) {
140		err = -EFAULT;
141		goto out_free;
142	}
143
144	if (mutex_trylock(&ar->mutex) == 0) {
145		err = -EAGAIN;
146		goto out_free;
147	}
148
149	if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
150		err = -ENODEV;
151		goto out_unlock;
152	}
153
154	err = dfops->write(ar, buf, count);
155	if (err)
156		goto out_unlock;
157
158out_unlock:
159	mutex_unlock(&ar->mutex);
160
161out_free:
162	vfree(buf);
163	return err;
164}
165
166#define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize,	\
167			       _attr, _dstate)				\
168static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
169	.read_bufsize = _read_bufsize,					\
170	.read = _read,							\
171	.write = _write,						\
172	.attr = _attr,							\
173	.req_dev_state = _dstate,					\
174	.fops = {							\
175		.open	= simple_open,					\
176		.read	= carl9170_debugfs_read,			\
177		.write	= carl9170_debugfs_write,			\
178		.owner	= THIS_MODULE					\
179	},								\
180}
181
182#define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr)	\
183	__DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize,	\
184			       _attr, CARL9170_STARTED)			\
185
186#define DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize)			\
187	DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read,	\
188			     NULL, _read_bufsize, S_IRUSR)
189
190#define DEBUGFS_DECLARE_WO_FILE(name)					\
191	DEBUGFS_DECLARE_FILE(name, NULL, carl9170_debugfs_##name ##_write,\
192			     0, S_IWUSR)
193
194#define DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize)			\
195	DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read,	\
196			     carl9170_debugfs_##name ##_write,		\
197			     _read_bufsize, S_IRUSR | S_IWUSR)
198
199#define __DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize, _dstate)		\
200	__DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read,	\
201			     carl9170_debugfs_##name ##_write,		\
202			     _read_bufsize, S_IRUSR | S_IWUSR, _dstate)
203
204#define DEBUGFS_READONLY_FILE(name, _read_bufsize, fmt, value...)	\
205static char *carl9170_debugfs_ ##name ## _read(struct ar9170 *ar,	\
206					     char *buf, size_t buf_size,\
207					     ssize_t *len)		\
208{									\
209	ADD(buf, *len, buf_size, fmt "\n", ##value);			\
210	return buf;							\
211}									\
212DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize)
213
214static char *carl9170_debugfs_mem_usage_read(struct ar9170 *ar, char *buf,
215					     size_t bufsize, ssize_t *len)
216{
217	ADD(buf, *len, bufsize, "jar: [");
218
219	spin_lock_bh(&ar->mem_lock);
220
221	*len += bitmap_scnprintf(&buf[*len], bufsize - *len,
222				  ar->mem_bitmap, ar->fw.mem_blocks);
223
224	ADD(buf, *len, bufsize, "]\n");
225
226	ADD(buf, *len, bufsize, "cookies: used:%3d / total:%3d, allocs:%d\n",
227	    bitmap_weight(ar->mem_bitmap, ar->fw.mem_blocks),
228	    ar->fw.mem_blocks, atomic_read(&ar->mem_allocs));
229
230	ADD(buf, *len, bufsize, "memory: free:%3d (%3d KiB) / total:%3d KiB)\n",
231	    atomic_read(&ar->mem_free_blocks),
232	    (atomic_read(&ar->mem_free_blocks) * ar->fw.mem_block_size) / 1024,
233	    (ar->fw.mem_blocks * ar->fw.mem_block_size) / 1024);
234
235	spin_unlock_bh(&ar->mem_lock);
236
237	return buf;
238}
239DEBUGFS_DECLARE_RO_FILE(mem_usage, 512);
240
241static char *carl9170_debugfs_qos_stat_read(struct ar9170 *ar, char *buf,
242					    size_t bufsize, ssize_t *len)
243{
244	ADD(buf, *len, bufsize, "%s QoS AC\n", modparam_noht ? "Hardware" :
245	    "Software");
246
247	ADD(buf, *len, bufsize, "[     VO            VI       "
248				 "     BE            BK      ]\n");
249
250	spin_lock_bh(&ar->tx_stats_lock);
251	ADD(buf, *len, bufsize, "[length/limit  length/limit  "
252				 "length/limit  length/limit ]\n"
253				"[   %3d/%3d       %3d/%3d    "
254				 "   %3d/%3d       %3d/%3d   ]\n\n",
255	    ar->tx_stats[0].len, ar->tx_stats[0].limit,
256	    ar->tx_stats[1].len, ar->tx_stats[1].limit,
257	    ar->tx_stats[2].len, ar->tx_stats[2].limit,
258	    ar->tx_stats[3].len, ar->tx_stats[3].limit);
259
260	ADD(buf, *len, bufsize, "[    total         total     "
261				 "    total         total    ]\n"
262				"[%10d    %10d    %10d    %10d   ]\n\n",
263	    ar->tx_stats[0].count, ar->tx_stats[1].count,
264	    ar->tx_stats[2].count, ar->tx_stats[3].count);
265
266	spin_unlock_bh(&ar->tx_stats_lock);
267
268	ADD(buf, *len, bufsize, "[  pend/waittx   pend/waittx "
269				 "  pend/waittx   pend/waittx]\n"
270				"[   %3d/%3d       %3d/%3d    "
271				 "   %3d/%3d       %3d/%3d   ]\n\n",
272	    skb_queue_len(&ar->tx_pending[0]),
273	    skb_queue_len(&ar->tx_status[0]),
274	    skb_queue_len(&ar->tx_pending[1]),
275	    skb_queue_len(&ar->tx_status[1]),
276	    skb_queue_len(&ar->tx_pending[2]),
277	    skb_queue_len(&ar->tx_status[2]),
278	    skb_queue_len(&ar->tx_pending[3]),
279	    skb_queue_len(&ar->tx_status[3]));
280
281	return buf;
282}
283DEBUGFS_DECLARE_RO_FILE(qos_stat, 512);
284
285static void carl9170_debugfs_format_frame(struct ar9170 *ar,
286	struct sk_buff *skb, const char *prefix, char *buf,
287	ssize_t *off, ssize_t bufsize)
288{
289	struct _carl9170_tx_superframe *txc = (void *) skb->data;
290	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
291	struct carl9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
292	struct ieee80211_hdr *hdr = (void *) txc->frame_data;
293
294	ADD(buf, *off, bufsize, "%s %p, c:%2x, DA:%pM, sq:%4d, mc:%.4x, "
295	    "pc:%.8x, to:%d ms\n", prefix, skb, txc->s.cookie,
296	    ieee80211_get_DA(hdr), get_seq_h(hdr),
297	    le16_to_cpu(txc->f.mac_control), le32_to_cpu(txc->f.phy_control),
298	    jiffies_to_msecs(jiffies - arinfo->timeout));
299}
300
301
302static char *carl9170_debugfs_ampdu_state_read(struct ar9170 *ar, char *buf,
303					       size_t bufsize, ssize_t *len)
304{
305	struct carl9170_sta_tid *iter;
306	struct sk_buff *skb;
307	int cnt = 0, fc;
308	int offset;
309
310	rcu_read_lock();
311	list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
312
313		spin_lock_bh(&iter->lock);
314		ADD(buf, *len, bufsize, "Entry: #%2d TID:%1d, BSN:%4d, "
315		    "SNX:%4d, HSN:%4d, BAW:%2d, state:%1d, toggles:%d\n",
316		    cnt, iter->tid, iter->bsn, iter->snx, iter->hsn,
317		    iter->max, iter->state, iter->counter);
318
319		ADD(buf, *len, bufsize, "\tWindow:  [");
320
321		*len += bitmap_scnprintf(&buf[*len], bufsize - *len,
322			iter->bitmap, CARL9170_BAW_BITS);
323
324#define BM_STR_OFF(offset)					\
325	((CARL9170_BAW_BITS - (offset) - 1) / 4 +		\
326	 (CARL9170_BAW_BITS - (offset) - 1) / 32 + 1)
327
328		ADD(buf, *len, bufsize, ",W]\n");
329
330		offset = BM_STR_OFF(0);
331		ADD(buf, *len, bufsize, "\tBase Seq: %*s\n", offset, "T");
332
333		offset = BM_STR_OFF(SEQ_DIFF(iter->snx, iter->bsn));
334		ADD(buf, *len, bufsize, "\tNext Seq: %*s\n", offset, "W");
335
336		offset = BM_STR_OFF(((int)iter->hsn - (int)iter->bsn) %
337				     CARL9170_BAW_BITS);
338		ADD(buf, *len, bufsize, "\tLast Seq: %*s\n", offset, "N");
339
340		ADD(buf, *len, bufsize, "\tPre-Aggregation reorder buffer: "
341		    " currently queued:%d\n", skb_queue_len(&iter->queue));
342
343		fc = 0;
344		skb_queue_walk(&iter->queue, skb) {
345			char prefix[32];
346
347			snprintf(prefix, sizeof(prefix), "\t\t%3d :", fc);
348			carl9170_debugfs_format_frame(ar, skb, prefix, buf,
349						      len, bufsize);
350
351			fc++;
352		}
353		spin_unlock_bh(&iter->lock);
354		cnt++;
355	}
356	rcu_read_unlock();
357
358	return buf;
359}
360DEBUGFS_DECLARE_RO_FILE(ampdu_state, 8000);
361
362static void carl9170_debugfs_queue_dump(struct ar9170 *ar, char *buf,
363	ssize_t *len, size_t bufsize, struct sk_buff_head *queue)
364{
365	struct sk_buff *skb;
366	char prefix[16];
367	int fc = 0;
368
369	spin_lock_bh(&queue->lock);
370	skb_queue_walk(queue, skb) {
371		snprintf(prefix, sizeof(prefix), "%3d :", fc);
372		carl9170_debugfs_format_frame(ar, skb, prefix, buf,
373					      len, bufsize);
374		fc++;
375	}
376	spin_unlock_bh(&queue->lock);
377}
378
379#define DEBUGFS_QUEUE_DUMP(q, qi)					\
380static char *carl9170_debugfs_##q ##_##qi ##_read(struct ar9170 *ar,	\
381	char *buf, size_t bufsize, ssize_t *len)			\
382{									\
383	carl9170_debugfs_queue_dump(ar, buf, len, bufsize, &ar->q[qi]);	\
384	return buf;							\
385}									\
386DEBUGFS_DECLARE_RO_FILE(q##_##qi, 8000);
387
388static char *carl9170_debugfs_sta_psm_read(struct ar9170 *ar, char *buf,
389					   size_t bufsize, ssize_t *len)
390{
391	ADD(buf, *len, bufsize, "psm state: %s\n", (ar->ps.off_override ?
392	    "FORCE CAM" : (ar->ps.state ? "PSM" : "CAM")));
393
394	ADD(buf, *len, bufsize, "sleep duration: %d ms.\n", ar->ps.sleep_ms);
395	ADD(buf, *len, bufsize, "last power-state transition: %d ms ago.\n",
396	    jiffies_to_msecs(jiffies - ar->ps.last_action));
397	ADD(buf, *len, bufsize, "last CAM->PSM transition: %d ms ago.\n",
398	    jiffies_to_msecs(jiffies - ar->ps.last_slept));
399
400	return buf;
401}
402DEBUGFS_DECLARE_RO_FILE(sta_psm, 160);
403
404static char *carl9170_debugfs_tx_stuck_read(struct ar9170 *ar, char *buf,
405					    size_t bufsize, ssize_t *len)
406{
407	int i;
408
409	for (i = 0; i < ar->hw->queues; i++) {
410		ADD(buf, *len, bufsize, "TX queue [%d]: %10d max:%10d ms.\n",
411		    i, ieee80211_queue_stopped(ar->hw, i) ?
412		    jiffies_to_msecs(jiffies - ar->queue_stop_timeout[i]) : 0,
413		    jiffies_to_msecs(ar->max_queue_stop_timeout[i]));
414
415		ar->max_queue_stop_timeout[i] = 0;
416	}
417
418	return buf;
419}
420DEBUGFS_DECLARE_RO_FILE(tx_stuck, 180);
421
422static char *carl9170_debugfs_phy_noise_read(struct ar9170 *ar, char *buf,
423					     size_t bufsize, ssize_t *len)
424{
425	int err;
426
427	err = carl9170_get_noisefloor(ar);
428	if (err) {
429		*len = err;
430		return buf;
431	}
432
433	ADD(buf, *len, bufsize, "Chain 0: %10d dBm, ext. chan.:%10d dBm\n",
434	    ar->noise[0], ar->noise[2]);
435	ADD(buf, *len, bufsize, "Chain 2: %10d dBm, ext. chan.:%10d dBm\n",
436	    ar->noise[1], ar->noise[3]);
437
438	return buf;
439}
440DEBUGFS_DECLARE_RO_FILE(phy_noise, 180);
441
442static char *carl9170_debugfs_vif_dump_read(struct ar9170 *ar, char *buf,
443					    size_t bufsize, ssize_t *len)
444{
445	struct carl9170_vif_info *iter;
446	int i = 0;
447
448	ADD(buf, *len, bufsize, "registered VIFs:%d \\ %d\n",
449	    ar->vifs, ar->fw.vif_num);
450
451	ADD(buf, *len, bufsize, "VIF bitmap: [");
452
453	*len += bitmap_scnprintf(&buf[*len], bufsize - *len,
454				 &ar->vif_bitmap, ar->fw.vif_num);
455
456	ADD(buf, *len, bufsize, "]\n");
457
458	rcu_read_lock();
459	list_for_each_entry_rcu(iter, &ar->vif_list, list) {
460		struct ieee80211_vif *vif = carl9170_get_vif(iter);
461		ADD(buf, *len, bufsize, "\t%d = [%s VIF, id:%d, type:%x "
462		    " mac:%pM %s]\n", i, (carl9170_get_main_vif(ar) == vif ?
463		    "Master" : " Slave"), iter->id, vif->type, vif->addr,
464		    iter->enable_beacon ? "beaconing " : "");
465		i++;
466	}
467	rcu_read_unlock();
468
469	return buf;
470}
471DEBUGFS_DECLARE_RO_FILE(vif_dump, 8000);
472
473#define UPDATE_COUNTER(ar, name)	({				\
474	u32 __tmp[ARRAY_SIZE(name##_regs)];				\
475	unsigned int __i, __err = -ENODEV;				\
476									\
477	for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) {		\
478		__tmp[__i] = name##_regs[__i].reg;			\
479		ar->debug.stats.name##_counter[__i] = 0;		\
480	}								\
481									\
482	if (IS_STARTED(ar))						\
483		__err = carl9170_read_mreg(ar, ARRAY_SIZE(name##_regs),	\
484			__tmp, ar->debug.stats.name##_counter);		\
485	(__err); })
486
487#define TALLY_SUM_UP(ar, name)	do {					\
488	unsigned int __i;						\
489									\
490	for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) {		\
491		ar->debug.stats.name##_sum[__i] +=			\
492			ar->debug.stats.name##_counter[__i];		\
493	}								\
494} while (0)
495
496#define DEBUGFS_HW_TALLY_FILE(name, f)					\
497static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar,	\
498	 char *dum, size_t bufsize, ssize_t *ret)			\
499{									\
500	char *buf;							\
501	int i, max_len, err;						\
502									\
503	max_len = ARRAY_SIZE(name##_regs) * 80;				\
504	buf = vmalloc(max_len);						\
505	if (!buf)							\
506		return NULL;						\
507									\
508	err = UPDATE_COUNTER(ar, name);					\
509	if (err) {							\
510		*ret = err;						\
511		return buf;						\
512	}								\
513									\
514	TALLY_SUM_UP(ar, name);						\
515									\
516	for (i = 0; i < ARRAY_SIZE(name##_regs); i++) {			\
517		ADD(buf, *ret, max_len, "%22s = %" f "[+%" f "]\n",	\
518		    name##_regs[i].nreg, ar->debug.stats.name ##_sum[i],\
519		    ar->debug.stats.name ##_counter[i]);		\
520	}								\
521									\
522	return buf;							\
523}									\
524DEBUGFS_DECLARE_RO_FILE(name, 0);
525
526#define DEBUGFS_HW_REG_FILE(name, f)					\
527static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar,	\
528	char *dum, size_t bufsize, ssize_t *ret)			\
529{									\
530	char *buf;							\
531	int i, max_len, err;						\
532									\
533	max_len = ARRAY_SIZE(name##_regs) * 80;				\
534	buf = vmalloc(max_len);						\
535	if (!buf)							\
536		return NULL;						\
537									\
538	err = UPDATE_COUNTER(ar, name);					\
539	if (err) {							\
540		*ret = err;						\
541		return buf;						\
542	}								\
543									\
544	for (i = 0; i < ARRAY_SIZE(name##_regs); i++) {			\
545		ADD(buf, *ret, max_len, "%22s = %" f "\n",		\
546		    name##_regs[i].nreg,				\
547		    ar->debug.stats.name##_counter[i]);			\
548	}								\
549									\
550	return buf;							\
551}									\
552DEBUGFS_DECLARE_RO_FILE(name, 0);
553
554static ssize_t carl9170_debugfs_hw_ioread32_write(struct ar9170 *ar,
555	const char *buf, size_t count)
556{
557	int err = 0, i, n = 0, max_len = 32, res;
558	unsigned int reg, tmp;
559
560	if (!count)
561		return 0;
562
563	if (count > max_len)
564		return -E2BIG;
565
566	res = sscanf(buf, "0x%X %d", &reg, &n);
567	if (res < 1) {
568		err = -EINVAL;
569		goto out;
570	}
571
572	if (res == 1)
573		n = 1;
574
575	if (n > 15) {
576		err = -EMSGSIZE;
577		goto out;
578	}
579
580	if ((reg >= 0x280000) || ((reg + (n << 2)) >= 0x280000)) {
581		err = -EADDRNOTAVAIL;
582		goto out;
583	}
584
585	if (reg & 3) {
586		err = -EINVAL;
587		goto out;
588	}
589
590	for (i = 0; i < n; i++) {
591		err = carl9170_read_reg(ar, reg + (i << 2), &tmp);
592		if (err)
593			goto out;
594
595		ar->debug.ring[ar->debug.ring_tail].reg = reg + (i << 2);
596		ar->debug.ring[ar->debug.ring_tail].value = tmp;
597		ar->debug.ring_tail++;
598		ar->debug.ring_tail %= CARL9170_DEBUG_RING_SIZE;
599	}
600
601out:
602	return err ? err : count;
603}
604
605static char *carl9170_debugfs_hw_ioread32_read(struct ar9170 *ar, char *buf,
606					       size_t bufsize, ssize_t *ret)
607{
608	int i = 0;
609
610	while (ar->debug.ring_head != ar->debug.ring_tail) {
611		ADD(buf, *ret, bufsize, "%.8x = %.8x\n",
612		    ar->debug.ring[ar->debug.ring_head].reg,
613		    ar->debug.ring[ar->debug.ring_head].value);
614
615		ar->debug.ring_head++;
616		ar->debug.ring_head %= CARL9170_DEBUG_RING_SIZE;
617
618		if (i++ == 64)
619			break;
620	}
621	ar->debug.ring_head = ar->debug.ring_tail;
622	return buf;
623}
624DEBUGFS_DECLARE_RW_FILE(hw_ioread32, CARL9170_DEBUG_RING_SIZE * 40);
625
626static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
627					  size_t count)
628{
629	int err;
630
631	if (count < 1)
632		return -EINVAL;
633
634	switch (buf[0]) {
635	case 'F':
636		ar->needs_full_reset = true;
637		break;
638
639	case 'R':
640		if (!IS_STARTED(ar)) {
641			err = -EAGAIN;
642			goto out;
643		}
644
645		ar->needs_full_reset = false;
646		break;
647
648	case 'M':
649		err = carl9170_mac_reset(ar);
650		if (err < 0)
651			count = err;
652
653		goto out;
654
655	case 'P':
656		err = carl9170_set_channel(ar, ar->hw->conf.chandef.chan,
657			cfg80211_get_chandef_type(&ar->hw->conf.chandef));
658		if (err < 0)
659			count = err;
660
661		goto out;
662
663	default:
664		return -EINVAL;
665	}
666
667	carl9170_restart(ar, CARL9170_RR_USER_REQUEST);
668
669out:
670	return count;
671}
672
673static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf,
674				       size_t bufsize, ssize_t *ret)
675{
676	ADD(buf, *ret, bufsize, "[P]hy reinit, [R]estart, [F]ull usb reset, "
677	    "[M]ac reset\n");
678	ADD(buf, *ret, bufsize, "firmware restarts:%d, last reason:%d\n",
679		ar->restart_counter, ar->last_reason);
680	ADD(buf, *ret, bufsize, "phy reinit errors:%d (%d)\n",
681		ar->total_chan_fail, ar->chan_fail);
682	ADD(buf, *ret, bufsize, "reported firmware errors:%d\n",
683		ar->fw.err_counter);
684	ADD(buf, *ret, bufsize, "reported firmware BUGs:%d\n",
685		ar->fw.bug_counter);
686	ADD(buf, *ret, bufsize, "pending restart requests:%d\n",
687		atomic_read(&ar->pending_restarts));
688	return buf;
689}
690__DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED);
691
692static const char *const erp_modes[] = {
693	[CARL9170_ERP_INVALID] = "INVALID",
694	[CARL9170_ERP_AUTO] = "Automatic",
695	[CARL9170_ERP_MAC80211] = "Set by MAC80211",
696	[CARL9170_ERP_OFF] = "Force Off",
697	[CARL9170_ERP_RTS] = "Force RTS",
698	[CARL9170_ERP_CTS] = "Force CTS"
699};
700
701static char *carl9170_debugfs_erp_read(struct ar9170 *ar, char *buf,
702				       size_t bufsize, ssize_t *ret)
703{
704	ADD(buf, *ret, bufsize, "ERP Setting: (%d) -> %s\n", ar->erp_mode,
705	    erp_modes[ar->erp_mode]);
706	return buf;
707}
708
709static ssize_t carl9170_debugfs_erp_write(struct ar9170 *ar, const char *buf,
710					  size_t count)
711{
712	int res, val;
713
714	if (count < 1)
715		return -EINVAL;
716
717	res = sscanf(buf, "%d", &val);
718	if (res != 1)
719		return -EINVAL;
720
721	if (!((val > CARL9170_ERP_INVALID) &&
722	      (val < __CARL9170_ERP_NUM)))
723		return -EINVAL;
724
725	ar->erp_mode = val;
726	return count;
727}
728
729DEBUGFS_DECLARE_RW_FILE(erp, 80);
730
731static ssize_t carl9170_debugfs_hw_iowrite32_write(struct ar9170 *ar,
732	const char *buf, size_t count)
733{
734	int err = 0, max_len = 22, res;
735	u32 reg, val;
736
737	if (!count)
738		return 0;
739
740	if (count > max_len)
741		return -E2BIG;
742
743	res = sscanf(buf, "0x%X 0x%X", &reg, &val);
744	if (res != 2) {
745		err = -EINVAL;
746		goto out;
747	}
748
749	if (reg <= 0x100000 || reg >= 0x280000) {
750		err = -EADDRNOTAVAIL;
751		goto out;
752	}
753
754	if (reg & 3) {
755		err = -EINVAL;
756		goto out;
757	}
758
759	err = carl9170_write_reg(ar, reg, val);
760	if (err)
761		goto out;
762
763out:
764	return err ? err : count;
765}
766DEBUGFS_DECLARE_WO_FILE(hw_iowrite32);
767
768DEBUGFS_HW_TALLY_FILE(hw_tx_tally, "u");
769DEBUGFS_HW_TALLY_FILE(hw_rx_tally, "u");
770DEBUGFS_HW_TALLY_FILE(hw_phy_errors, "u");
771DEBUGFS_HW_REG_FILE(hw_wlan_queue, ".8x");
772DEBUGFS_HW_REG_FILE(hw_pta_queue, ".8x");
773DEBUGFS_HW_REG_FILE(hw_ampdu_info, ".8x");
774DEBUGFS_QUEUE_DUMP(tx_status, 0);
775DEBUGFS_QUEUE_DUMP(tx_status, 1);
776DEBUGFS_QUEUE_DUMP(tx_status, 2);
777DEBUGFS_QUEUE_DUMP(tx_status, 3);
778DEBUGFS_QUEUE_DUMP(tx_pending, 0);
779DEBUGFS_QUEUE_DUMP(tx_pending, 1);
780DEBUGFS_QUEUE_DUMP(tx_pending, 2);
781DEBUGFS_QUEUE_DUMP(tx_pending, 3);
782DEBUGFS_READONLY_FILE(usb_tx_anch_urbs, 20, "%d",
783		      atomic_read(&ar->tx_anch_urbs));
784DEBUGFS_READONLY_FILE(usb_rx_anch_urbs, 20, "%d",
785		      atomic_read(&ar->rx_anch_urbs));
786DEBUGFS_READONLY_FILE(usb_rx_work_urbs, 20, "%d",
787		      atomic_read(&ar->rx_work_urbs));
788DEBUGFS_READONLY_FILE(usb_rx_pool_urbs, 20, "%d",
789		      atomic_read(&ar->rx_pool_urbs));
790
791DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d",
792		      atomic_read(&ar->tx_total_queued));
793DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d",
794		      atomic_read(&ar->tx_ampdu_scheduler));
795
796DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d",
797		      atomic_read(&ar->tx_total_pending));
798
799DEBUGFS_READONLY_FILE(tx_ampdu_list_len, 20, "%d",
800		      ar->tx_ampdu_list_len);
801
802DEBUGFS_READONLY_FILE(tx_ampdu_upload, 20, "%d",
803		      atomic_read(&ar->tx_ampdu_upload));
804
805DEBUGFS_READONLY_FILE(tx_janitor_last_run, 64, "last run:%d ms ago",
806	jiffies_to_msecs(jiffies - ar->tx_janitor_last_run));
807
808DEBUGFS_READONLY_FILE(tx_dropped, 20, "%d", ar->tx_dropped);
809
810DEBUGFS_READONLY_FILE(rx_dropped, 20, "%d", ar->rx_dropped);
811
812DEBUGFS_READONLY_FILE(sniffer_enabled, 20, "%d", ar->sniffer_enabled);
813DEBUGFS_READONLY_FILE(rx_software_decryption, 20, "%d",
814		      ar->rx_software_decryption);
815DEBUGFS_READONLY_FILE(ampdu_factor, 20, "%d",
816		      ar->current_factor);
817DEBUGFS_READONLY_FILE(ampdu_density, 20, "%d",
818		      ar->current_density);
819
820DEBUGFS_READONLY_FILE(beacon_int, 20, "%d TU", ar->global_beacon_int);
821DEBUGFS_READONLY_FILE(pretbtt, 20, "%d TU", ar->global_pretbtt);
822
823void carl9170_debugfs_register(struct ar9170 *ar)
824{
825	ar->debug_dir = debugfs_create_dir(KBUILD_MODNAME,
826		ar->hw->wiphy->debugfsdir);
827
828#define DEBUGFS_ADD(name)						\
829	debugfs_create_file(#name, carl_debugfs_##name ##_ops.attr,	\
830			    ar->debug_dir, ar,				\
831			    &carl_debugfs_##name ## _ops.fops);
832
833	DEBUGFS_ADD(usb_tx_anch_urbs);
834	DEBUGFS_ADD(usb_rx_pool_urbs);
835	DEBUGFS_ADD(usb_rx_anch_urbs);
836	DEBUGFS_ADD(usb_rx_work_urbs);
837
838	DEBUGFS_ADD(tx_total_queued);
839	DEBUGFS_ADD(tx_total_pending);
840	DEBUGFS_ADD(tx_dropped);
841	DEBUGFS_ADD(tx_stuck);
842	DEBUGFS_ADD(tx_ampdu_upload);
843	DEBUGFS_ADD(tx_ampdu_scheduler);
844	DEBUGFS_ADD(tx_ampdu_list_len);
845
846	DEBUGFS_ADD(rx_dropped);
847	DEBUGFS_ADD(sniffer_enabled);
848	DEBUGFS_ADD(rx_software_decryption);
849
850	DEBUGFS_ADD(mem_usage);
851	DEBUGFS_ADD(qos_stat);
852	DEBUGFS_ADD(sta_psm);
853	DEBUGFS_ADD(ampdu_state);
854
855	DEBUGFS_ADD(hw_tx_tally);
856	DEBUGFS_ADD(hw_rx_tally);
857	DEBUGFS_ADD(hw_phy_errors);
858	DEBUGFS_ADD(phy_noise);
859
860	DEBUGFS_ADD(hw_wlan_queue);
861	DEBUGFS_ADD(hw_pta_queue);
862	DEBUGFS_ADD(hw_ampdu_info);
863
864	DEBUGFS_ADD(ampdu_density);
865	DEBUGFS_ADD(ampdu_factor);
866
867	DEBUGFS_ADD(tx_janitor_last_run);
868
869	DEBUGFS_ADD(tx_status_0);
870	DEBUGFS_ADD(tx_status_1);
871	DEBUGFS_ADD(tx_status_2);
872	DEBUGFS_ADD(tx_status_3);
873
874	DEBUGFS_ADD(tx_pending_0);
875	DEBUGFS_ADD(tx_pending_1);
876	DEBUGFS_ADD(tx_pending_2);
877	DEBUGFS_ADD(tx_pending_3);
878
879	DEBUGFS_ADD(hw_ioread32);
880	DEBUGFS_ADD(hw_iowrite32);
881	DEBUGFS_ADD(bug);
882
883	DEBUGFS_ADD(erp);
884
885	DEBUGFS_ADD(vif_dump);
886
887	DEBUGFS_ADD(beacon_int);
888	DEBUGFS_ADD(pretbtt);
889
890#undef DEBUGFS_ADD
891}
892
893void carl9170_debugfs_unregister(struct ar9170 *ar)
894{
895	debugfs_remove_recursive(ar->debug_dir);
896}
897