1203c4805SLuis R. Rodriguez /*
2203c4805SLuis R. Rodriguez * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com>
3203c4805SLuis R. Rodriguez *
4203c4805SLuis R. Rodriguez * This file is free software: you may copy, redistribute and/or modify it
5203c4805SLuis R. Rodriguez * under the terms of the GNU General Public License as published by the
6203c4805SLuis R. Rodriguez * Free Software Foundation, either version 2 of the License, or (at your
7203c4805SLuis R. Rodriguez * option) any later version.
8203c4805SLuis R. Rodriguez *
9203c4805SLuis R. Rodriguez * This file is distributed in the hope that it will be useful, but
10203c4805SLuis R. Rodriguez * WITHOUT ANY WARRANTY; without even the implied warranty of
11203c4805SLuis R. Rodriguez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12203c4805SLuis R. Rodriguez * General Public License for more details.
13203c4805SLuis R. Rodriguez *
14203c4805SLuis R. Rodriguez * You should have received a copy of the GNU General Public License
15203c4805SLuis R. Rodriguez * along with this program. If not, see <http://www.gnu.org/licenses/>.
16203c4805SLuis R. Rodriguez *
17203c4805SLuis R. Rodriguez *
18203c4805SLuis R. Rodriguez * This file incorporates work covered by the following copyright and
19203c4805SLuis R. Rodriguez * permission notice:
20203c4805SLuis R. Rodriguez *
21203c4805SLuis R. Rodriguez * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
22203c4805SLuis R. Rodriguez * Copyright (c) 2004-2005 Atheros Communications, Inc.
23203c4805SLuis R. Rodriguez * Copyright (c) 2006 Devicescape Software, Inc.
24203c4805SLuis R. Rodriguez * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
25203c4805SLuis R. Rodriguez * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
26203c4805SLuis R. Rodriguez *
27203c4805SLuis R. Rodriguez * All rights reserved.
28203c4805SLuis R. Rodriguez *
29203c4805SLuis R. Rodriguez * Redistribution and use in source and binary forms, with or without
30203c4805SLuis R. Rodriguez * modification, are permitted provided that the following conditions
31203c4805SLuis R. Rodriguez * are met:
32203c4805SLuis R. Rodriguez * 1. Redistributions of source code must retain the above copyright
33203c4805SLuis R. Rodriguez * notice, this list of conditions and the following disclaimer,
34203c4805SLuis R. Rodriguez * without modification.
35203c4805SLuis R. Rodriguez * 2. Redistributions in binary form must reproduce at minimum a disclaimer
36203c4805SLuis R. Rodriguez * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
37203c4805SLuis R. Rodriguez * redistribution must be conditioned upon including a substantially
38203c4805SLuis R. Rodriguez * similar Disclaimer requirement for further binary redistribution.
39203c4805SLuis R. Rodriguez * 3. Neither the names of the above-listed copyright holders nor the names
40203c4805SLuis R. Rodriguez * of any contributors may be used to endorse or promote products derived
41203c4805SLuis R. Rodriguez * from this software without specific prior written permission.
42203c4805SLuis R. Rodriguez *
43203c4805SLuis R. Rodriguez * Alternatively, this software may be distributed under the terms of the
44203c4805SLuis R. Rodriguez * GNU General Public License ("GPL") version 2 as published by the Free
45203c4805SLuis R. Rodriguez * Software Foundation.
46203c4805SLuis R. Rodriguez *
47203c4805SLuis R. Rodriguez * NO WARRANTY
48203c4805SLuis R. Rodriguez * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49203c4805SLuis R. Rodriguez * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50203c4805SLuis R. Rodriguez * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
51203c4805SLuis R. Rodriguez * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
52203c4805SLuis R. Rodriguez * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
53203c4805SLuis R. Rodriguez * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54203c4805SLuis R. Rodriguez * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55203c4805SLuis R. Rodriguez * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
56203c4805SLuis R. Rodriguez * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57203c4805SLuis R. Rodriguez * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
58203c4805SLuis R. Rodriguez * THE POSSIBILITY OF SUCH DAMAGES.
59203c4805SLuis R. Rodriguez */
60516304b0SJoe Perches
61516304b0SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
62516304b0SJoe Perches
63ee40fa06SPaul Gortmaker #include <linux/export.h>
646eb07cafSPaul Gortmaker #include <linux/moduleparam.h>
6532bc6d1aSStephen Rothwell #include <linux/vmalloc.h>
66203c4805SLuis R. Rodriguez
67931be260SPavel Roskin #include <linux/seq_file.h>
68931be260SPavel Roskin #include <linux/list.h>
69203c4805SLuis R. Rodriguez #include "debug.h"
70931be260SPavel Roskin #include "ath5k.h"
71931be260SPavel Roskin #include "reg.h"
72931be260SPavel Roskin #include "base.h"
73203c4805SLuis R. Rodriguez
74203c4805SLuis R. Rodriguez static unsigned int ath5k_debug;
75203c4805SLuis R. Rodriguez module_param_named(debug, ath5k_debug, uint, 0);
76203c4805SLuis R. Rodriguez
77203c4805SLuis R. Rodriguez
78203c4805SLuis R. Rodriguez /* debugfs: registers */
79203c4805SLuis R. Rodriguez
80203c4805SLuis R. Rodriguez struct reg {
81203c4805SLuis R. Rodriguez const char *name;
82203c4805SLuis R. Rodriguez int addr;
83203c4805SLuis R. Rodriguez };
84203c4805SLuis R. Rodriguez
85203c4805SLuis R. Rodriguez #define REG_STRUCT_INIT(r) { #r, r }
86203c4805SLuis R. Rodriguez
87203c4805SLuis R. Rodriguez /* just a few random registers, might want to add more */
88203c4805SLuis R. Rodriguez static const struct reg regs[] = {
89203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_CR),
90203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_RXDP),
91203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_CFG),
92203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_IER),
93203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_BCR),
94203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_RTSD0),
95203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_RTSD1),
96203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_TXCFG),
97203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_RXCFG),
98203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_RXJLA),
99203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_MIBC),
100203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_TOPS),
101203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_RXNOFRM),
102203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_TXNOFRM),
103203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_RPGTO),
104203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_RFCNT),
105203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_MISC),
106203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
107203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_ISR),
108203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_PISR),
109203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SISR0),
110203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SISR1),
111203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SISR2),
112203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SISR3),
113203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SISR4),
114203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_IMR),
115203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_PIMR),
116203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SIMR0),
117203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SIMR1),
118203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SIMR2),
119203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SIMR3),
120203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SIMR4),
121203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_DCM_ADDR),
122203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_DCCFG),
123203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_CCFG),
124203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_CPC0),
125203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_CPC1),
126203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_CPC2),
127203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_CPC3),
128203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_CPCOVF),
129203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_RESET_CTL),
130203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SLEEP_CTL),
131203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_INTPEND),
132203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SFR),
133203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_PCICFG),
134203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_GPIOCR),
135203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_GPIODO),
136203c4805SLuis R. Rodriguez REG_STRUCT_INIT(AR5K_SREV),
137203c4805SLuis R. Rodriguez };
138203c4805SLuis R. Rodriguez
reg_start(struct seq_file * seq,loff_t * pos)139203c4805SLuis R. Rodriguez static void *reg_start(struct seq_file *seq, loff_t *pos)
140203c4805SLuis R. Rodriguez {
141203c4805SLuis R. Rodriguez return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL;
142203c4805SLuis R. Rodriguez }
143203c4805SLuis R. Rodriguez
reg_stop(struct seq_file * seq,void * p)144203c4805SLuis R. Rodriguez static void reg_stop(struct seq_file *seq, void *p)
145203c4805SLuis R. Rodriguez {
146203c4805SLuis R. Rodriguez /* nothing to do */
147203c4805SLuis R. Rodriguez }
148203c4805SLuis R. Rodriguez
reg_next(struct seq_file * seq,void * p,loff_t * pos)149203c4805SLuis R. Rodriguez static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
150203c4805SLuis R. Rodriguez {
151203c4805SLuis R. Rodriguez ++*pos;
152203c4805SLuis R. Rodriguez return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL;
153203c4805SLuis R. Rodriguez }
154203c4805SLuis R. Rodriguez
reg_show(struct seq_file * seq,void * p)155203c4805SLuis R. Rodriguez static int reg_show(struct seq_file *seq, void *p)
156203c4805SLuis R. Rodriguez {
157e0d687bdSPavel Roskin struct ath5k_hw *ah = seq->private;
158203c4805SLuis R. Rodriguez struct reg *r = p;
159203c4805SLuis R. Rodriguez seq_printf(seq, "%-25s0x%08x\n", r->name,
160e0d687bdSPavel Roskin ath5k_hw_reg_read(ah, r->addr));
161203c4805SLuis R. Rodriguez return 0;
162203c4805SLuis R. Rodriguez }
163203c4805SLuis R. Rodriguez
164aac352d6SLiu Shixin static const struct seq_operations registers_sops = {
165203c4805SLuis R. Rodriguez .start = reg_start,
166203c4805SLuis R. Rodriguez .next = reg_next,
167203c4805SLuis R. Rodriguez .stop = reg_stop,
168203c4805SLuis R. Rodriguez .show = reg_show
169203c4805SLuis R. Rodriguez };
170203c4805SLuis R. Rodriguez
171aac352d6SLiu Shixin DEFINE_SEQ_ATTRIBUTE(registers);
172203c4805SLuis R. Rodriguez
173203c4805SLuis R. Rodriguez /* debugfs: beacons */
174203c4805SLuis R. Rodriguez
read_file_beacon(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)175203c4805SLuis R. Rodriguez static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
176203c4805SLuis R. Rodriguez size_t count, loff_t *ppos)
177203c4805SLuis R. Rodriguez {
178e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
179203c4805SLuis R. Rodriguez char buf[500];
180203c4805SLuis R. Rodriguez unsigned int len = 0;
181203c4805SLuis R. Rodriguez unsigned int v;
182203c4805SLuis R. Rodriguez u64 tsf;
183203c4805SLuis R. Rodriguez
184e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_BEACON);
185dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
186203c4805SLuis R. Rodriguez "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
187203c4805SLuis R. Rodriguez "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
188203c4805SLuis R. Rodriguez (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
189203c4805SLuis R. Rodriguez
190dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",
191e0d687bdSPavel Roskin "AR5K_LAST_TSTP", ath5k_hw_reg_read(ah, AR5K_LAST_TSTP));
192203c4805SLuis R. Rodriguez
193dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",
194e0d687bdSPavel Roskin "AR5K_BEACON_CNT", ath5k_hw_reg_read(ah, AR5K_BEACON_CNT));
195203c4805SLuis R. Rodriguez
196e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_TIMER0);
197dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
198203c4805SLuis R. Rodriguez "AR5K_TIMER0 (TBTT)", v, v);
199203c4805SLuis R. Rodriguez
200e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_TIMER1);
201dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
202203c4805SLuis R. Rodriguez "AR5K_TIMER1 (DMA)", v, v >> 3);
203203c4805SLuis R. Rodriguez
204e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_TIMER2);
205dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
206203c4805SLuis R. Rodriguez "AR5K_TIMER2 (SWBA)", v, v >> 3);
207203c4805SLuis R. Rodriguez
208e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_TIMER3);
209dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",
210203c4805SLuis R. Rodriguez "AR5K_TIMER3 (ATIM)", v, v);
211203c4805SLuis R. Rodriguez
212e0d687bdSPavel Roskin tsf = ath5k_hw_get_tsf64(ah);
213dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
214203c4805SLuis R. Rodriguez "TSF\t\t0x%016llx\tTU: %08x\n",
215203c4805SLuis R. Rodriguez (unsigned long long)tsf, TSF_TO_TU(tsf));
216203c4805SLuis R. Rodriguez
2172189d13fSDan Carpenter if (len > sizeof(buf))
2182189d13fSDan Carpenter len = sizeof(buf);
2192189d13fSDan Carpenter
220203c4805SLuis R. Rodriguez return simple_read_from_buffer(user_buf, count, ppos, buf, len);
221203c4805SLuis R. Rodriguez }
222203c4805SLuis R. Rodriguez
write_file_beacon(struct file * file,const char __user * userbuf,size_t count,loff_t * ppos)223203c4805SLuis R. Rodriguez static ssize_t write_file_beacon(struct file *file,
224203c4805SLuis R. Rodriguez const char __user *userbuf,
225203c4805SLuis R. Rodriguez size_t count, loff_t *ppos)
226203c4805SLuis R. Rodriguez {
227e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
228203c4805SLuis R. Rodriguez char buf[20];
229203c4805SLuis R. Rodriguez
2308aada63cSDjalal Harouni count = min_t(size_t, count, sizeof(buf) - 1);
2318aada63cSDjalal Harouni if (copy_from_user(buf, userbuf, count))
232203c4805SLuis R. Rodriguez return -EFAULT;
233203c4805SLuis R. Rodriguez
2348aada63cSDjalal Harouni buf[count] = '\0';
235203c4805SLuis R. Rodriguez if (strncmp(buf, "disable", 7) == 0) {
236203c4805SLuis R. Rodriguez AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
237516304b0SJoe Perches pr_info("debugfs disable beacons\n");
238203c4805SLuis R. Rodriguez } else if (strncmp(buf, "enable", 6) == 0) {
239203c4805SLuis R. Rodriguez AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
240516304b0SJoe Perches pr_info("debugfs enable beacons\n");
241203c4805SLuis R. Rodriguez }
242203c4805SLuis R. Rodriguez return count;
243203c4805SLuis R. Rodriguez }
244203c4805SLuis R. Rodriguez
245203c4805SLuis R. Rodriguez static const struct file_operations fops_beacon = {
246203c4805SLuis R. Rodriguez .read = read_file_beacon,
247203c4805SLuis R. Rodriguez .write = write_file_beacon,
248234e3405SStephen Boyd .open = simple_open,
249203c4805SLuis R. Rodriguez .owner = THIS_MODULE,
2506038f373SArnd Bergmann .llseek = default_llseek,
251203c4805SLuis R. Rodriguez };
252203c4805SLuis R. Rodriguez
253203c4805SLuis R. Rodriguez
254203c4805SLuis R. Rodriguez /* debugfs: reset */
255203c4805SLuis R. Rodriguez
write_file_reset(struct file * file,const char __user * userbuf,size_t count,loff_t * ppos)256203c4805SLuis R. Rodriguez static ssize_t write_file_reset(struct file *file,
257203c4805SLuis R. Rodriguez const char __user *userbuf,
258203c4805SLuis R. Rodriguez size_t count, loff_t *ppos)
259203c4805SLuis R. Rodriguez {
260e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
261e0d687bdSPavel Roskin ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "debug file triggered reset\n");
262e0d687bdSPavel Roskin ieee80211_queue_work(ah->hw, &ah->reset_work);
263203c4805SLuis R. Rodriguez return count;
264203c4805SLuis R. Rodriguez }
265203c4805SLuis R. Rodriguez
266203c4805SLuis R. Rodriguez static const struct file_operations fops_reset = {
267203c4805SLuis R. Rodriguez .write = write_file_reset,
268234e3405SStephen Boyd .open = simple_open,
269203c4805SLuis R. Rodriguez .owner = THIS_MODULE,
2706038f373SArnd Bergmann .llseek = noop_llseek,
271203c4805SLuis R. Rodriguez };
272203c4805SLuis R. Rodriguez
273203c4805SLuis R. Rodriguez
274203c4805SLuis R. Rodriguez /* debugfs: debug level */
275203c4805SLuis R. Rodriguez
276203c4805SLuis R. Rodriguez static const struct {
277203c4805SLuis R. Rodriguez enum ath5k_debug_level level;
278203c4805SLuis R. Rodriguez const char *name;
279203c4805SLuis R. Rodriguez const char *desc;
280203c4805SLuis R. Rodriguez } dbg_info[] = {
281203c4805SLuis R. Rodriguez { ATH5K_DEBUG_RESET, "reset", "reset and initialization" },
282203c4805SLuis R. Rodriguez { ATH5K_DEBUG_INTR, "intr", "interrupt handling" },
283203c4805SLuis R. Rodriguez { ATH5K_DEBUG_MODE, "mode", "mode init/setup" },
284203c4805SLuis R. Rodriguez { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" },
285203c4805SLuis R. Rodriguez { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" },
286203c4805SLuis R. Rodriguez { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" },
287203c4805SLuis R. Rodriguez { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" },
288203c4805SLuis R. Rodriguez { ATH5K_DEBUG_LED, "led", "LED management" },
289203c4805SLuis R. Rodriguez { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
290b3a28e68SNick Kossifidis { ATH5K_DEBUG_DMA, "dma", "dma start/stop" },
2912111ac0dSBruno Randolf { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" },
292b4c52612SBob Copeland { ATH5K_DEBUG_DESC, "desc", "descriptor chains" },
293203c4805SLuis R. Rodriguez { ATH5K_DEBUG_ANY, "all", "show all debug levels" },
294203c4805SLuis R. Rodriguez };
295203c4805SLuis R. Rodriguez
read_file_debug(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)296203c4805SLuis R. Rodriguez static ssize_t read_file_debug(struct file *file, char __user *user_buf,
297203c4805SLuis R. Rodriguez size_t count, loff_t *ppos)
298203c4805SLuis R. Rodriguez {
299e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
300203c4805SLuis R. Rodriguez char buf[700];
301203c4805SLuis R. Rodriguez unsigned int len = 0;
302203c4805SLuis R. Rodriguez unsigned int i;
303203c4805SLuis R. Rodriguez
304dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
305e0d687bdSPavel Roskin "DEBUG LEVEL: 0x%08x\n\n", ah->debug.level);
306203c4805SLuis R. Rodriguez
307203c4805SLuis R. Rodriguez for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) {
308dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
309203c4805SLuis R. Rodriguez "%10s %c 0x%08x - %s\n", dbg_info[i].name,
310e0d687bdSPavel Roskin ah->debug.level & dbg_info[i].level ? '+' : ' ',
311203c4805SLuis R. Rodriguez dbg_info[i].level, dbg_info[i].desc);
312203c4805SLuis R. Rodriguez }
313dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
314203c4805SLuis R. Rodriguez "%10s %c 0x%08x - %s\n", dbg_info[i].name,
315e0d687bdSPavel Roskin ah->debug.level == dbg_info[i].level ? '+' : ' ',
316203c4805SLuis R. Rodriguez dbg_info[i].level, dbg_info[i].desc);
317203c4805SLuis R. Rodriguez
3182189d13fSDan Carpenter if (len > sizeof(buf))
3192189d13fSDan Carpenter len = sizeof(buf);
3202189d13fSDan Carpenter
321203c4805SLuis R. Rodriguez return simple_read_from_buffer(user_buf, count, ppos, buf, len);
322203c4805SLuis R. Rodriguez }
323203c4805SLuis R. Rodriguez
write_file_debug(struct file * file,const char __user * userbuf,size_t count,loff_t * ppos)324203c4805SLuis R. Rodriguez static ssize_t write_file_debug(struct file *file,
325203c4805SLuis R. Rodriguez const char __user *userbuf,
326203c4805SLuis R. Rodriguez size_t count, loff_t *ppos)
327203c4805SLuis R. Rodriguez {
328e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
329203c4805SLuis R. Rodriguez unsigned int i;
330203c4805SLuis R. Rodriguez char buf[20];
331203c4805SLuis R. Rodriguez
3328aada63cSDjalal Harouni count = min_t(size_t, count, sizeof(buf) - 1);
3338aada63cSDjalal Harouni if (copy_from_user(buf, userbuf, count))
334203c4805SLuis R. Rodriguez return -EFAULT;
335203c4805SLuis R. Rodriguez
3368aada63cSDjalal Harouni buf[count] = '\0';
337203c4805SLuis R. Rodriguez for (i = 0; i < ARRAY_SIZE(dbg_info); i++) {
338203c4805SLuis R. Rodriguez if (strncmp(buf, dbg_info[i].name,
339203c4805SLuis R. Rodriguez strlen(dbg_info[i].name)) == 0) {
340e0d687bdSPavel Roskin ah->debug.level ^= dbg_info[i].level; /* toggle bit */
341203c4805SLuis R. Rodriguez break;
342203c4805SLuis R. Rodriguez }
343203c4805SLuis R. Rodriguez }
344203c4805SLuis R. Rodriguez return count;
345203c4805SLuis R. Rodriguez }
346203c4805SLuis R. Rodriguez
347203c4805SLuis R. Rodriguez static const struct file_operations fops_debug = {
348203c4805SLuis R. Rodriguez .read = read_file_debug,
349203c4805SLuis R. Rodriguez .write = write_file_debug,
350234e3405SStephen Boyd .open = simple_open,
351203c4805SLuis R. Rodriguez .owner = THIS_MODULE,
3526038f373SArnd Bergmann .llseek = default_llseek,
353203c4805SLuis R. Rodriguez };
354203c4805SLuis R. Rodriguez
355203c4805SLuis R. Rodriguez
356604eeaddSBruno Randolf /* debugfs: antenna */
357604eeaddSBruno Randolf
read_file_antenna(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)358604eeaddSBruno Randolf static ssize_t read_file_antenna(struct file *file, char __user *user_buf,
359604eeaddSBruno Randolf size_t count, loff_t *ppos)
360604eeaddSBruno Randolf {
361e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
362604eeaddSBruno Randolf char buf[700];
363604eeaddSBruno Randolf unsigned int len = 0;
364604eeaddSBruno Randolf unsigned int i;
365604eeaddSBruno Randolf unsigned int v;
366604eeaddSBruno Randolf
367dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",
368e0d687bdSPavel Roskin ah->ah_ant_mode);
369dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",
370e0d687bdSPavel Roskin ah->ah_def_ant);
371dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",
372e0d687bdSPavel Roskin ah->ah_tx_ant);
373604eeaddSBruno Randolf
374dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");
375e0d687bdSPavel Roskin for (i = 1; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
376dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
377604eeaddSBruno Randolf "[antenna %d]\t%d\t%d\n",
378e0d687bdSPavel Roskin i, ah->stats.antenna_rx[i], ah->stats.antenna_tx[i]);
379604eeaddSBruno Randolf }
380dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",
381e0d687bdSPavel Roskin ah->stats.antenna_rx[0], ah->stats.antenna_tx[0]);
382604eeaddSBruno Randolf
383e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
384dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
385604eeaddSBruno Randolf "\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);
386604eeaddSBruno Randolf
387e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
388dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
389604eeaddSBruno Randolf "AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",
390604eeaddSBruno Randolf (v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0);
391dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
392604eeaddSBruno Randolf "AR5K_STA_ID1_DESC_ANTENNA\t%d\n",
393604eeaddSBruno Randolf (v & AR5K_STA_ID1_DESC_ANTENNA) != 0);
394dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
395604eeaddSBruno Randolf "AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",
396604eeaddSBruno Randolf (v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0);
397dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
398604eeaddSBruno Randolf "AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",
399604eeaddSBruno Randolf (v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);
400604eeaddSBruno Randolf
401e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL);
402dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
403604eeaddSBruno Randolf "\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",
404604eeaddSBruno Randolf (v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);
405604eeaddSBruno Randolf
406e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_PHY_RESTART);
407dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
408604eeaddSBruno Randolf "AR5K_PHY_RESTART_DIV_GC\t\t%x\n",
409604eeaddSBruno Randolf (v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);
410604eeaddSBruno Randolf
411e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ANT_DIV);
412dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
413604eeaddSBruno Randolf "AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",
414604eeaddSBruno Randolf (v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);
415604eeaddSBruno Randolf
416e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_0);
417dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
4180ca74027SBruno Randolf "\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);
419e0d687bdSPavel Roskin v = ath5k_hw_reg_read(ah, AR5K_PHY_ANT_SWITCH_TABLE_1);
420dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
4210ca74027SBruno Randolf "AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);
4220ca74027SBruno Randolf
4232189d13fSDan Carpenter if (len > sizeof(buf))
4242189d13fSDan Carpenter len = sizeof(buf);
4252189d13fSDan Carpenter
426604eeaddSBruno Randolf return simple_read_from_buffer(user_buf, count, ppos, buf, len);
427604eeaddSBruno Randolf }
428604eeaddSBruno Randolf
write_file_antenna(struct file * file,const char __user * userbuf,size_t count,loff_t * ppos)429604eeaddSBruno Randolf static ssize_t write_file_antenna(struct file *file,
430604eeaddSBruno Randolf const char __user *userbuf,
431604eeaddSBruno Randolf size_t count, loff_t *ppos)
432604eeaddSBruno Randolf {
433e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
434604eeaddSBruno Randolf unsigned int i;
435604eeaddSBruno Randolf char buf[20];
436604eeaddSBruno Randolf
4378aada63cSDjalal Harouni count = min_t(size_t, count, sizeof(buf) - 1);
4388aada63cSDjalal Harouni if (copy_from_user(buf, userbuf, count))
439604eeaddSBruno Randolf return -EFAULT;
440604eeaddSBruno Randolf
4418aada63cSDjalal Harouni buf[count] = '\0';
442604eeaddSBruno Randolf if (strncmp(buf, "diversity", 9) == 0) {
443e0d687bdSPavel Roskin ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT);
444516304b0SJoe Perches pr_info("debug: enable diversity\n");
445604eeaddSBruno Randolf } else if (strncmp(buf, "fixed-a", 7) == 0) {
446e0d687bdSPavel Roskin ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A);
447516304b0SJoe Perches pr_info("debug: fixed antenna A\n");
448604eeaddSBruno Randolf } else if (strncmp(buf, "fixed-b", 7) == 0) {
449e0d687bdSPavel Roskin ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B);
450516304b0SJoe Perches pr_info("debug: fixed antenna B\n");
451604eeaddSBruno Randolf } else if (strncmp(buf, "clear", 5) == 0) {
452e0d687bdSPavel Roskin for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) {
453e0d687bdSPavel Roskin ah->stats.antenna_rx[i] = 0;
454e0d687bdSPavel Roskin ah->stats.antenna_tx[i] = 0;
455604eeaddSBruno Randolf }
456516304b0SJoe Perches pr_info("debug: cleared antenna stats\n");
457604eeaddSBruno Randolf }
458604eeaddSBruno Randolf return count;
459604eeaddSBruno Randolf }
460604eeaddSBruno Randolf
461604eeaddSBruno Randolf static const struct file_operations fops_antenna = {
462604eeaddSBruno Randolf .read = read_file_antenna,
463604eeaddSBruno Randolf .write = write_file_antenna,
464234e3405SStephen Boyd .open = simple_open,
465604eeaddSBruno Randolf .owner = THIS_MODULE,
4666038f373SArnd Bergmann .llseek = default_llseek,
467604eeaddSBruno Randolf };
468604eeaddSBruno Randolf
46987fd2e6cSBen Greear /* debugfs: misc */
47087fd2e6cSBen Greear
read_file_misc(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)47187fd2e6cSBen Greear static ssize_t read_file_misc(struct file *file, char __user *user_buf,
47287fd2e6cSBen Greear size_t count, loff_t *ppos)
47387fd2e6cSBen Greear {
474e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
47587fd2e6cSBen Greear char buf[700];
47687fd2e6cSBen Greear unsigned int len = 0;
477e0d687bdSPavel Roskin u32 filt = ath5k_hw_get_rx_filter(ah);
47887fd2e6cSBen Greear
479dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",
480e0d687bdSPavel Roskin ah->bssidmask);
481dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",
48287fd2e6cSBen Greear filt);
48387fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_UCAST)
484dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " UCAST");
48587fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_MCAST)
486dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " MCAST");
48787fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_BCAST)
488dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " BCAST");
48987fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_CONTROL)
490dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL");
49187fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_BEACON)
492dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " BEACON");
49387fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_PROM)
494dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " PROM");
49587fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_XRPOLL)
496dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " XRPOLL");
49787fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_PROBEREQ)
498dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
49987fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_PHYERR_5212)
500dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");
50187fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_RADARERR_5212)
502dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");
50387fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_PHYERR_5211)
50487fd2e6cSBen Greear snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");
50587fd2e6cSBen Greear if (filt & AR5K_RX_FILTER_RADARERR_5211)
506dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, " RADARERR-5211");
50787fd2e6cSBen Greear
508dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",
509e0d687bdSPavel Roskin ath_opmode_to_string(ah->opmode), ah->opmode);
51092c68a66SBen Greear
51187fd2e6cSBen Greear if (len > sizeof(buf))
51287fd2e6cSBen Greear len = sizeof(buf);
51387fd2e6cSBen Greear
51487fd2e6cSBen Greear return simple_read_from_buffer(user_buf, count, ppos, buf, len);
51587fd2e6cSBen Greear }
51687fd2e6cSBen Greear
51787fd2e6cSBen Greear static const struct file_operations fops_misc = {
51887fd2e6cSBen Greear .read = read_file_misc,
519234e3405SStephen Boyd .open = simple_open,
52087fd2e6cSBen Greear .owner = THIS_MODULE,
52187fd2e6cSBen Greear };
52287fd2e6cSBen Greear
523604eeaddSBruno Randolf
5247644395fSBruno Randolf /* debugfs: frameerrors */
5257644395fSBruno Randolf
read_file_frameerrors(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)5267644395fSBruno Randolf static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
5277644395fSBruno Randolf size_t count, loff_t *ppos)
5287644395fSBruno Randolf {
529e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
530e0d687bdSPavel Roskin struct ath5k_statistics *st = &ah->stats;
5317644395fSBruno Randolf char buf[700];
5327644395fSBruno Randolf unsigned int len = 0;
533da35111aSBruno Randolf int i;
5347644395fSBruno Randolf
535dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
5367644395fSBruno Randolf "RX\n---------------------\n");
537dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",
5387644395fSBruno Randolf st->rxerr_crc,
5397644395fSBruno Randolf st->rx_all_count > 0 ?
5407644395fSBruno Randolf st->rxerr_crc * 100 / st->rx_all_count : 0);
541dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",
5427644395fSBruno Randolf st->rxerr_phy,
5437644395fSBruno Randolf st->rx_all_count > 0 ?
5447644395fSBruno Randolf st->rxerr_phy * 100 / st->rx_all_count : 0);
545da35111aSBruno Randolf for (i = 0; i < 32; i++) {
546da35111aSBruno Randolf if (st->rxerr_phy_code[i])
547dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
5485d882c97SBen Greear " phy_err[%u]\t%u\n",
549da35111aSBruno Randolf i, st->rxerr_phy_code[i]);
550da35111aSBruno Randolf }
551da35111aSBruno Randolf
552dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
5537644395fSBruno Randolf st->rxerr_fifo,
5547644395fSBruno Randolf st->rx_all_count > 0 ?
5557644395fSBruno Randolf st->rxerr_fifo * 100 / st->rx_all_count : 0);
556dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",
5577644395fSBruno Randolf st->rxerr_decrypt,
5587644395fSBruno Randolf st->rx_all_count > 0 ?
5597644395fSBruno Randolf st->rxerr_decrypt * 100 / st->rx_all_count : 0);
560dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",
5617644395fSBruno Randolf st->rxerr_mic,
5627644395fSBruno Randolf st->rx_all_count > 0 ?
5637644395fSBruno Randolf st->rxerr_mic * 100 / st->rx_all_count : 0);
564dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",
5657644395fSBruno Randolf st->rxerr_proc,
5667644395fSBruno Randolf st->rx_all_count > 0 ?
5677644395fSBruno Randolf st->rxerr_proc * 100 / st->rx_all_count : 0);
568dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",
5697644395fSBruno Randolf st->rxerr_jumbo,
5707644395fSBruno Randolf st->rx_all_count > 0 ?
5717644395fSBruno Randolf st->rxerr_jumbo * 100 / st->rx_all_count : 0);
572dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",
5737644395fSBruno Randolf st->rx_all_count);
574dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",
575b72acddbSBen Greear st->rx_bytes_count);
5767644395fSBruno Randolf
577dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
5787644395fSBruno Randolf "\nTX\n---------------------\n");
579dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",
5807644395fSBruno Randolf st->txerr_retry,
5817644395fSBruno Randolf st->tx_all_count > 0 ?
5827644395fSBruno Randolf st->txerr_retry * 100 / st->tx_all_count : 0);
583dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",
5847644395fSBruno Randolf st->txerr_fifo,
5857644395fSBruno Randolf st->tx_all_count > 0 ?
5867644395fSBruno Randolf st->txerr_fifo * 100 / st->tx_all_count : 0);
587dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",
5887644395fSBruno Randolf st->txerr_filt,
5897644395fSBruno Randolf st->tx_all_count > 0 ?
5907644395fSBruno Randolf st->txerr_filt * 100 / st->tx_all_count : 0);
591dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",
5927644395fSBruno Randolf st->tx_all_count);
593dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",
594b72acddbSBen Greear st->tx_bytes_count);
5957644395fSBruno Randolf
5962189d13fSDan Carpenter if (len > sizeof(buf))
5972189d13fSDan Carpenter len = sizeof(buf);
5982189d13fSDan Carpenter
5997644395fSBruno Randolf return simple_read_from_buffer(user_buf, count, ppos, buf, len);
6007644395fSBruno Randolf }
6017644395fSBruno Randolf
write_file_frameerrors(struct file * file,const char __user * userbuf,size_t count,loff_t * ppos)6027644395fSBruno Randolf static ssize_t write_file_frameerrors(struct file *file,
6037644395fSBruno Randolf const char __user *userbuf,
6047644395fSBruno Randolf size_t count, loff_t *ppos)
6057644395fSBruno Randolf {
606e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
607e0d687bdSPavel Roskin struct ath5k_statistics *st = &ah->stats;
6087644395fSBruno Randolf char buf[20];
6097644395fSBruno Randolf
6108aada63cSDjalal Harouni count = min_t(size_t, count, sizeof(buf) - 1);
6118aada63cSDjalal Harouni if (copy_from_user(buf, userbuf, count))
6127644395fSBruno Randolf return -EFAULT;
6137644395fSBruno Randolf
6148aada63cSDjalal Harouni buf[count] = '\0';
6157644395fSBruno Randolf if (strncmp(buf, "clear", 5) == 0) {
6167644395fSBruno Randolf st->rxerr_crc = 0;
6177644395fSBruno Randolf st->rxerr_phy = 0;
6187644395fSBruno Randolf st->rxerr_fifo = 0;
6197644395fSBruno Randolf st->rxerr_decrypt = 0;
6207644395fSBruno Randolf st->rxerr_mic = 0;
6217644395fSBruno Randolf st->rxerr_proc = 0;
6227644395fSBruno Randolf st->rxerr_jumbo = 0;
6237644395fSBruno Randolf st->rx_all_count = 0;
6247644395fSBruno Randolf st->txerr_retry = 0;
6257644395fSBruno Randolf st->txerr_fifo = 0;
6267644395fSBruno Randolf st->txerr_filt = 0;
6277644395fSBruno Randolf st->tx_all_count = 0;
628516304b0SJoe Perches pr_info("debug: cleared frameerrors stats\n");
6297644395fSBruno Randolf }
6307644395fSBruno Randolf return count;
6317644395fSBruno Randolf }
6327644395fSBruno Randolf
6337644395fSBruno Randolf static const struct file_operations fops_frameerrors = {
6347644395fSBruno Randolf .read = read_file_frameerrors,
6357644395fSBruno Randolf .write = write_file_frameerrors,
636234e3405SStephen Boyd .open = simple_open,
6377644395fSBruno Randolf .owner = THIS_MODULE,
6386038f373SArnd Bergmann .llseek = default_llseek,
6397644395fSBruno Randolf };
6407644395fSBruno Randolf
6417644395fSBruno Randolf
6422111ac0dSBruno Randolf /* debugfs: ani */
6432111ac0dSBruno Randolf
read_file_ani(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)6442111ac0dSBruno Randolf static ssize_t read_file_ani(struct file *file, char __user *user_buf,
6452111ac0dSBruno Randolf size_t count, loff_t *ppos)
6462111ac0dSBruno Randolf {
647e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
648e0d687bdSPavel Roskin struct ath5k_statistics *st = &ah->stats;
649e0d687bdSPavel Roskin struct ath5k_ani_state *as = &ah->ani_state;
6502111ac0dSBruno Randolf
6512111ac0dSBruno Randolf char buf[700];
6522111ac0dSBruno Randolf unsigned int len = 0;
6532111ac0dSBruno Randolf
654dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6552111ac0dSBruno Randolf "HW has PHY error counters:\t%s\n",
656e0d687bdSPavel Roskin ah->ah_capabilities.cap_has_phyerr_counters ?
6572111ac0dSBruno Randolf "yes" : "no");
658dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6592111ac0dSBruno Randolf "HW max spur immunity level:\t%d\n",
6602111ac0dSBruno Randolf as->max_spur_level);
661dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6622111ac0dSBruno Randolf "\nANI state\n--------------------------------------------\n");
663dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");
6642111ac0dSBruno Randolf switch (as->ani_mode) {
6652111ac0dSBruno Randolf case ATH5K_ANI_MODE_OFF:
666dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "OFF\n");
6672111ac0dSBruno Randolf break;
6682111ac0dSBruno Randolf case ATH5K_ANI_MODE_MANUAL_LOW:
669dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6702111ac0dSBruno Randolf "MANUAL LOW\n");
6712111ac0dSBruno Randolf break;
6722111ac0dSBruno Randolf case ATH5K_ANI_MODE_MANUAL_HIGH:
673dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6742111ac0dSBruno Randolf "MANUAL HIGH\n");
6752111ac0dSBruno Randolf break;
6762111ac0dSBruno Randolf case ATH5K_ANI_MODE_AUTO:
677dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "AUTO\n");
6782111ac0dSBruno Randolf break;
6792111ac0dSBruno Randolf default:
680dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6812111ac0dSBruno Randolf "??? (not good)\n");
6822111ac0dSBruno Randolf break;
6832111ac0dSBruno Randolf }
684dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6852111ac0dSBruno Randolf "noise immunity level:\t\t%d\n",
6862111ac0dSBruno Randolf as->noise_imm_level);
687dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6882111ac0dSBruno Randolf "spur immunity level:\t\t%d\n",
6892111ac0dSBruno Randolf as->spur_level);
690dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
691e4bbf2f5SPavel Roskin "firstep level:\t\t\t%d\n",
6922111ac0dSBruno Randolf as->firstep_level);
693dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6942111ac0dSBruno Randolf "OFDM weak signal detection:\t%s\n",
6952111ac0dSBruno Randolf as->ofdm_weak_sig ? "on" : "off");
696dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
6972111ac0dSBruno Randolf "CCK weak signal detection:\t%s\n",
6982111ac0dSBruno Randolf as->cck_weak_sig ? "on" : "off");
6992111ac0dSBruno Randolf
700dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
7012111ac0dSBruno Randolf "\nMIB INTERRUPTS:\t\t%u\n",
7022111ac0dSBruno Randolf st->mib_intr);
703dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
7042111ac0dSBruno Randolf "beacon RSSI average:\t%d\n",
70546f26ddfSJohannes Berg (int)ewma_beacon_rssi_read(&ah->ah_beacon_rssi_avg));
7067109ca5cSFelix Fietkau
7077109ca5cSFelix Fietkau #define CC_PRINT(_struct, _field) \
7087109ca5cSFelix Fietkau _struct._field, \
7097109ca5cSFelix Fietkau _struct.cycles > 0 ? \
7107109ca5cSFelix Fietkau _struct._field * 100 / _struct.cycles : 0
7117109ca5cSFelix Fietkau
712dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
713e4bbf2f5SPavel Roskin "profcnt tx\t\t%u\t(%d%%)\n",
7147109ca5cSFelix Fietkau CC_PRINT(as->last_cc, tx_frame));
715dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
716e4bbf2f5SPavel Roskin "profcnt rx\t\t%u\t(%d%%)\n",
7177109ca5cSFelix Fietkau CC_PRINT(as->last_cc, rx_frame));
718dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
719e4bbf2f5SPavel Roskin "profcnt busy\t\t%u\t(%d%%)\n",
7207109ca5cSFelix Fietkau CC_PRINT(as->last_cc, rx_busy));
7217109ca5cSFelix Fietkau #undef CC_PRINT
722dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",
7237109ca5cSFelix Fietkau as->last_cc.cycles);
724dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
7252111ac0dSBruno Randolf "listen time\t\t%d\tlast: %d\n",
7262111ac0dSBruno Randolf as->listen_time, as->last_listen);
727dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
7282111ac0dSBruno Randolf "OFDM errors\t\t%u\tlast: %u\tsum: %u\n",
7292111ac0dSBruno Randolf as->ofdm_errors, as->last_ofdm_errors,
7302111ac0dSBruno Randolf as->sum_ofdm_errors);
731dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
7322111ac0dSBruno Randolf "CCK errors\t\t%u\tlast: %u\tsum: %u\n",
7332111ac0dSBruno Randolf as->cck_errors, as->last_cck_errors,
7342111ac0dSBruno Randolf as->sum_cck_errors);
735dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
7362111ac0dSBruno Randolf "AR5K_PHYERR_CNT1\t%x\t(=%d)\n",
737e0d687bdSPavel Roskin ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1),
7382111ac0dSBruno Randolf ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
739e0d687bdSPavel Roskin ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)));
740dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
7412111ac0dSBruno Randolf "AR5K_PHYERR_CNT2\t%x\t(=%d)\n",
742e0d687bdSPavel Roskin ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2),
7432111ac0dSBruno Randolf ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -
744e0d687bdSPavel Roskin ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)));
7452111ac0dSBruno Randolf
7462189d13fSDan Carpenter if (len > sizeof(buf))
7472189d13fSDan Carpenter len = sizeof(buf);
7482189d13fSDan Carpenter
7492111ac0dSBruno Randolf return simple_read_from_buffer(user_buf, count, ppos, buf, len);
7502111ac0dSBruno Randolf }
7512111ac0dSBruno Randolf
write_file_ani(struct file * file,const char __user * userbuf,size_t count,loff_t * ppos)7522111ac0dSBruno Randolf static ssize_t write_file_ani(struct file *file,
7532111ac0dSBruno Randolf const char __user *userbuf,
7542111ac0dSBruno Randolf size_t count, loff_t *ppos)
7552111ac0dSBruno Randolf {
756e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
7572111ac0dSBruno Randolf char buf[20];
7582111ac0dSBruno Randolf
7598aada63cSDjalal Harouni count = min_t(size_t, count, sizeof(buf) - 1);
7608aada63cSDjalal Harouni if (copy_from_user(buf, userbuf, count))
7612111ac0dSBruno Randolf return -EFAULT;
7622111ac0dSBruno Randolf
7638aada63cSDjalal Harouni buf[count] = '\0';
7642111ac0dSBruno Randolf if (strncmp(buf, "sens-low", 8) == 0) {
765e0d687bdSPavel Roskin ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_HIGH);
7662111ac0dSBruno Randolf } else if (strncmp(buf, "sens-high", 9) == 0) {
767e0d687bdSPavel Roskin ath5k_ani_init(ah, ATH5K_ANI_MODE_MANUAL_LOW);
7682111ac0dSBruno Randolf } else if (strncmp(buf, "ani-off", 7) == 0) {
769e0d687bdSPavel Roskin ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF);
7702111ac0dSBruno Randolf } else if (strncmp(buf, "ani-on", 6) == 0) {
771e0d687bdSPavel Roskin ath5k_ani_init(ah, ATH5K_ANI_MODE_AUTO);
7722111ac0dSBruno Randolf } else if (strncmp(buf, "noise-low", 9) == 0) {
773e0d687bdSPavel Roskin ath5k_ani_set_noise_immunity_level(ah, 0);
7742111ac0dSBruno Randolf } else if (strncmp(buf, "noise-high", 10) == 0) {
775e0d687bdSPavel Roskin ath5k_ani_set_noise_immunity_level(ah,
7762111ac0dSBruno Randolf ATH5K_ANI_MAX_NOISE_IMM_LVL);
7772111ac0dSBruno Randolf } else if (strncmp(buf, "spur-low", 8) == 0) {
778e0d687bdSPavel Roskin ath5k_ani_set_spur_immunity_level(ah, 0);
7792111ac0dSBruno Randolf } else if (strncmp(buf, "spur-high", 9) == 0) {
780e0d687bdSPavel Roskin ath5k_ani_set_spur_immunity_level(ah,
781e0d687bdSPavel Roskin ah->ani_state.max_spur_level);
7822111ac0dSBruno Randolf } else if (strncmp(buf, "fir-low", 7) == 0) {
783e0d687bdSPavel Roskin ath5k_ani_set_firstep_level(ah, 0);
7842111ac0dSBruno Randolf } else if (strncmp(buf, "fir-high", 8) == 0) {
785e0d687bdSPavel Roskin ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL);
7862111ac0dSBruno Randolf } else if (strncmp(buf, "ofdm-off", 8) == 0) {
787e0d687bdSPavel Roskin ath5k_ani_set_ofdm_weak_signal_detection(ah, false);
7882111ac0dSBruno Randolf } else if (strncmp(buf, "ofdm-on", 7) == 0) {
789e0d687bdSPavel Roskin ath5k_ani_set_ofdm_weak_signal_detection(ah, true);
7902111ac0dSBruno Randolf } else if (strncmp(buf, "cck-off", 7) == 0) {
791e0d687bdSPavel Roskin ath5k_ani_set_cck_weak_signal_detection(ah, false);
7922111ac0dSBruno Randolf } else if (strncmp(buf, "cck-on", 6) == 0) {
793e0d687bdSPavel Roskin ath5k_ani_set_cck_weak_signal_detection(ah, true);
7942111ac0dSBruno Randolf }
7952111ac0dSBruno Randolf return count;
7962111ac0dSBruno Randolf }
7972111ac0dSBruno Randolf
7982111ac0dSBruno Randolf static const struct file_operations fops_ani = {
7992111ac0dSBruno Randolf .read = read_file_ani,
8002111ac0dSBruno Randolf .write = write_file_ani,
801234e3405SStephen Boyd .open = simple_open,
8022111ac0dSBruno Randolf .owner = THIS_MODULE,
8036038f373SArnd Bergmann .llseek = default_llseek,
8042111ac0dSBruno Randolf };
8052111ac0dSBruno Randolf
8062111ac0dSBruno Randolf
8073cfd43f4SBruno Randolf /* debugfs: queues etc */
8083cfd43f4SBruno Randolf
read_file_queue(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)8093cfd43f4SBruno Randolf static ssize_t read_file_queue(struct file *file, char __user *user_buf,
8103cfd43f4SBruno Randolf size_t count, loff_t *ppos)
8113cfd43f4SBruno Randolf {
812e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
8133cfd43f4SBruno Randolf char buf[700];
8143cfd43f4SBruno Randolf unsigned int len = 0;
8153cfd43f4SBruno Randolf
8163cfd43f4SBruno Randolf struct ath5k_txq *txq;
8173cfd43f4SBruno Randolf struct ath5k_buf *bf, *bf0;
818cfddc11cSBruno Randolf int i, n;
8193cfd43f4SBruno Randolf
820dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
821e0d687bdSPavel Roskin "available txbuffers: %d\n", ah->txbuf_len);
8223cfd43f4SBruno Randolf
823e0d687bdSPavel Roskin for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
824e0d687bdSPavel Roskin txq = &ah->txqs[i];
8253cfd43f4SBruno Randolf
826dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
8273cfd43f4SBruno Randolf "%02d: %ssetup\n", i, txq->setup ? "" : "not ");
8283cfd43f4SBruno Randolf
8293cfd43f4SBruno Randolf if (!txq->setup)
8303cfd43f4SBruno Randolf continue;
8313cfd43f4SBruno Randolf
832cfddc11cSBruno Randolf n = 0;
833cfddc11cSBruno Randolf spin_lock_bh(&txq->lock);
8343cfd43f4SBruno Randolf list_for_each_entry_safe(bf, bf0, &txq->q, list)
8353cfd43f4SBruno Randolf n++;
836cfddc11cSBruno Randolf spin_unlock_bh(&txq->lock);
837cfddc11cSBruno Randolf
838dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
839cfddc11cSBruno Randolf " len: %d bufs: %d\n", txq->txq_len, n);
840dfb252c7STakashi Iwai len += scnprintf(buf + len, sizeof(buf) - len,
841923e5b3dSBruno Randolf " stuck: %d\n", txq->txq_stuck);
8423cfd43f4SBruno Randolf }
8433cfd43f4SBruno Randolf
8442189d13fSDan Carpenter if (len > sizeof(buf))
8452189d13fSDan Carpenter len = sizeof(buf);
8462189d13fSDan Carpenter
8473cfd43f4SBruno Randolf return simple_read_from_buffer(user_buf, count, ppos, buf, len);
8483cfd43f4SBruno Randolf }
8493cfd43f4SBruno Randolf
write_file_queue(struct file * file,const char __user * userbuf,size_t count,loff_t * ppos)8503cfd43f4SBruno Randolf static ssize_t write_file_queue(struct file *file,
8513cfd43f4SBruno Randolf const char __user *userbuf,
8523cfd43f4SBruno Randolf size_t count, loff_t *ppos)
8533cfd43f4SBruno Randolf {
854e0d687bdSPavel Roskin struct ath5k_hw *ah = file->private_data;
8553cfd43f4SBruno Randolf char buf[20];
8563cfd43f4SBruno Randolf
8578aada63cSDjalal Harouni count = min_t(size_t, count, sizeof(buf) - 1);
8588aada63cSDjalal Harouni if (copy_from_user(buf, userbuf, count))
8593cfd43f4SBruno Randolf return -EFAULT;
8603cfd43f4SBruno Randolf
8618aada63cSDjalal Harouni buf[count] = '\0';
8623cfd43f4SBruno Randolf if (strncmp(buf, "start", 5) == 0)
863e0d687bdSPavel Roskin ieee80211_wake_queues(ah->hw);
8643cfd43f4SBruno Randolf else if (strncmp(buf, "stop", 4) == 0)
865e0d687bdSPavel Roskin ieee80211_stop_queues(ah->hw);
8663cfd43f4SBruno Randolf
8673cfd43f4SBruno Randolf return count;
8683cfd43f4SBruno Randolf }
8693cfd43f4SBruno Randolf
8703cfd43f4SBruno Randolf
8713cfd43f4SBruno Randolf static const struct file_operations fops_queue = {
8723cfd43f4SBruno Randolf .read = read_file_queue,
8733cfd43f4SBruno Randolf .write = write_file_queue,
874234e3405SStephen Boyd .open = simple_open,
8753cfd43f4SBruno Randolf .owner = THIS_MODULE,
8766038f373SArnd Bergmann .llseek = default_llseek,
8773cfd43f4SBruno Randolf };
8783cfd43f4SBruno Randolf
879db906eb2SJade Bilkey /* debugfs: eeprom */
880db906eb2SJade Bilkey
881db906eb2SJade Bilkey struct eeprom_private {
882db906eb2SJade Bilkey u16 *buf;
883db906eb2SJade Bilkey int len;
884db906eb2SJade Bilkey };
885db906eb2SJade Bilkey
open_file_eeprom(struct inode * inode,struct file * file)886db906eb2SJade Bilkey static int open_file_eeprom(struct inode *inode, struct file *file)
887db906eb2SJade Bilkey {
888db906eb2SJade Bilkey struct eeprom_private *ep;
889db906eb2SJade Bilkey struct ath5k_hw *ah = inode->i_private;
890db906eb2SJade Bilkey bool res;
891db906eb2SJade Bilkey int i, ret;
892af8a9a67SSergey Ryazanov u32 eesize; /* NB: in 16-bit words */
893db906eb2SJade Bilkey u16 val, *buf;
894db906eb2SJade Bilkey
895db906eb2SJade Bilkey /* Get eeprom size */
896db906eb2SJade Bilkey
897db906eb2SJade Bilkey res = ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_UPPER, &val);
898db906eb2SJade Bilkey if (!res)
899db906eb2SJade Bilkey return -EACCES;
900db906eb2SJade Bilkey
901db906eb2SJade Bilkey if (val == 0) {
902db906eb2SJade Bilkey eesize = AR5K_EEPROM_INFO_MAX + AR5K_EEPROM_INFO_BASE;
903db906eb2SJade Bilkey } else {
904db906eb2SJade Bilkey eesize = (val & AR5K_EEPROM_SIZE_UPPER_MASK) <<
905db906eb2SJade Bilkey AR5K_EEPROM_SIZE_ENDLOC_SHIFT;
906db906eb2SJade Bilkey ath5k_hw_nvram_read(ah, AR5K_EEPROM_SIZE_LOWER, &val);
907db906eb2SJade Bilkey eesize = eesize | val;
908db906eb2SJade Bilkey }
909db906eb2SJade Bilkey
910db906eb2SJade Bilkey if (eesize > 4096)
911db906eb2SJade Bilkey return -EINVAL;
912db906eb2SJade Bilkey
913db906eb2SJade Bilkey /* Create buffer and read in eeprom */
914db906eb2SJade Bilkey
91542bc47b3SKees Cook buf = vmalloc(array_size(eesize, 2));
916db906eb2SJade Bilkey if (!buf) {
917db906eb2SJade Bilkey ret = -ENOMEM;
918db906eb2SJade Bilkey goto err;
919db906eb2SJade Bilkey }
920db906eb2SJade Bilkey
921db906eb2SJade Bilkey for (i = 0; i < eesize; ++i) {
9228fed6823SColin Ian King if (!ath5k_hw_nvram_read(ah, i, &val)) {
9238fed6823SColin Ian King ret = -EIO;
9248fed6823SColin Ian King goto freebuf;
9258fed6823SColin Ian King }
926db906eb2SJade Bilkey buf[i] = val;
927db906eb2SJade Bilkey }
928db906eb2SJade Bilkey
929db906eb2SJade Bilkey /* Create private struct and assign to file */
930db906eb2SJade Bilkey
931db906eb2SJade Bilkey ep = kmalloc(sizeof(*ep), GFP_KERNEL);
932db906eb2SJade Bilkey if (!ep) {
933db906eb2SJade Bilkey ret = -ENOMEM;
934db906eb2SJade Bilkey goto freebuf;
935db906eb2SJade Bilkey }
936db906eb2SJade Bilkey
937db906eb2SJade Bilkey ep->buf = buf;
938af8a9a67SSergey Ryazanov ep->len = eesize * 2;
939db906eb2SJade Bilkey
940db906eb2SJade Bilkey file->private_data = (void *)ep;
941db906eb2SJade Bilkey
942db906eb2SJade Bilkey return 0;
943db906eb2SJade Bilkey
944db906eb2SJade Bilkey freebuf:
945db906eb2SJade Bilkey vfree(buf);
946db906eb2SJade Bilkey err:
947db906eb2SJade Bilkey return ret;
948db906eb2SJade Bilkey
949db906eb2SJade Bilkey }
950db906eb2SJade Bilkey
read_file_eeprom(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)951db906eb2SJade Bilkey static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
952db906eb2SJade Bilkey size_t count, loff_t *ppos)
953db906eb2SJade Bilkey {
954db906eb2SJade Bilkey struct eeprom_private *ep = file->private_data;
955db906eb2SJade Bilkey
956db906eb2SJade Bilkey return simple_read_from_buffer(user_buf, count, ppos, ep->buf, ep->len);
957db906eb2SJade Bilkey }
958db906eb2SJade Bilkey
release_file_eeprom(struct inode * inode,struct file * file)959db906eb2SJade Bilkey static int release_file_eeprom(struct inode *inode, struct file *file)
960db906eb2SJade Bilkey {
961db906eb2SJade Bilkey struct eeprom_private *ep = file->private_data;
962db906eb2SJade Bilkey
963db906eb2SJade Bilkey vfree(ep->buf);
964db906eb2SJade Bilkey kfree(ep);
965db906eb2SJade Bilkey
966db906eb2SJade Bilkey return 0;
967db906eb2SJade Bilkey }
968db906eb2SJade Bilkey
969db906eb2SJade Bilkey static const struct file_operations fops_eeprom = {
970db906eb2SJade Bilkey .open = open_file_eeprom,
971db906eb2SJade Bilkey .read = read_file_eeprom,
972db906eb2SJade Bilkey .release = release_file_eeprom,
973db906eb2SJade Bilkey .owner = THIS_MODULE,
974db906eb2SJade Bilkey };
975db906eb2SJade Bilkey
9763cfd43f4SBruno Randolf
977203c4805SLuis R. Rodriguez void
ath5k_debug_init_device(struct ath5k_hw * ah)978e0d687bdSPavel Roskin ath5k_debug_init_device(struct ath5k_hw *ah)
979203c4805SLuis R. Rodriguez {
9805b7916adSFelix Fietkau struct dentry *phydir;
9815b7916adSFelix Fietkau
982e0d687bdSPavel Roskin ah->debug.level = ath5k_debug;
983203c4805SLuis R. Rodriguez
984e0d687bdSPavel Roskin phydir = debugfs_create_dir("ath5k", ah->hw->wiphy->debugfsdir);
985203c4805SLuis R. Rodriguez
9862ef00c53SJoe Perches debugfs_create_file("debug", 0600, phydir, ah, &fops_debug);
987aac352d6SLiu Shixin debugfs_create_file("registers", 0400, phydir, ah, ®isters_fops);
9882ef00c53SJoe Perches debugfs_create_file("beacon", 0600, phydir, ah, &fops_beacon);
9892ef00c53SJoe Perches debugfs_create_file("reset", 0200, phydir, ah, &fops_reset);
9902ef00c53SJoe Perches debugfs_create_file("antenna", 0600, phydir, ah, &fops_antenna);
9912ef00c53SJoe Perches debugfs_create_file("misc", 0400, phydir, ah, &fops_misc);
9922ef00c53SJoe Perches debugfs_create_file("eeprom", 0400, phydir, ah, &fops_eeprom);
9932ef00c53SJoe Perches debugfs_create_file("frameerrors", 0600, phydir, ah, &fops_frameerrors);
9942ef00c53SJoe Perches debugfs_create_file("ani", 0600, phydir, ah, &fops_ani);
9952ef00c53SJoe Perches debugfs_create_file("queue", 0600, phydir, ah, &fops_queue);
9962ef00c53SJoe Perches debugfs_create_bool("32khz_clock", 0600, phydir,
997e0d687bdSPavel Roskin &ah->ah_use_32khz_clock);
998203c4805SLuis R. Rodriguez }
999203c4805SLuis R. Rodriguez
1000203c4805SLuis R. Rodriguez /* functions used in other places */
1001203c4805SLuis R. Rodriguez
1002203c4805SLuis R. Rodriguez void
ath5k_debug_dump_bands(struct ath5k_hw * ah)1003e0d687bdSPavel Roskin ath5k_debug_dump_bands(struct ath5k_hw *ah)
1004203c4805SLuis R. Rodriguez {
1005203c4805SLuis R. Rodriguez unsigned int b, i;
1006203c4805SLuis R. Rodriguez
1007e0d687bdSPavel Roskin if (likely(!(ah->debug.level & ATH5K_DEBUG_DUMPBANDS)))
1008203c4805SLuis R. Rodriguez return;
1009203c4805SLuis R. Rodriguez
101057fbcce3SJohannes Berg for (b = 0; b < NUM_NL80211_BANDS; b++) {
1011e0d687bdSPavel Roskin struct ieee80211_supported_band *band = &ah->sbands[b];
1012aba74530SDavid S. Miller char bname[6];
1013203c4805SLuis R. Rodriguez switch (band->band) {
101457fbcce3SJohannes Berg case NL80211_BAND_2GHZ:
1015203c4805SLuis R. Rodriguez strcpy(bname, "2 GHz");
1016203c4805SLuis R. Rodriguez break;
101757fbcce3SJohannes Berg case NL80211_BAND_5GHZ:
1018203c4805SLuis R. Rodriguez strcpy(bname, "5 GHz");
1019203c4805SLuis R. Rodriguez break;
1020203c4805SLuis R. Rodriguez default:
1021203c4805SLuis R. Rodriguez printk(KERN_DEBUG "Band not supported: %d\n",
1022203c4805SLuis R. Rodriguez band->band);
1023203c4805SLuis R. Rodriguez return;
1024203c4805SLuis R. Rodriguez }
1025203c4805SLuis R. Rodriguez printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
1026203c4805SLuis R. Rodriguez band->n_channels, band->n_bitrates);
1027203c4805SLuis R. Rodriguez printk(KERN_DEBUG " channels:\n");
1028203c4805SLuis R. Rodriguez for (i = 0; i < band->n_channels; i++)
1029203c4805SLuis R. Rodriguez printk(KERN_DEBUG " %3d %d %.4x %.4x\n",
1030203c4805SLuis R. Rodriguez ieee80211_frequency_to_channel(
1031203c4805SLuis R. Rodriguez band->channels[i].center_freq),
1032203c4805SLuis R. Rodriguez band->channels[i].center_freq,
1033203c4805SLuis R. Rodriguez band->channels[i].hw_value,
1034203c4805SLuis R. Rodriguez band->channels[i].flags);
1035203c4805SLuis R. Rodriguez printk(KERN_DEBUG " rates:\n");
1036203c4805SLuis R. Rodriguez for (i = 0; i < band->n_bitrates; i++)
1037203c4805SLuis R. Rodriguez printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n",
1038203c4805SLuis R. Rodriguez band->bitrates[i].bitrate,
1039203c4805SLuis R. Rodriguez band->bitrates[i].hw_value,
1040203c4805SLuis R. Rodriguez band->bitrates[i].flags,
1041203c4805SLuis R. Rodriguez band->bitrates[i].hw_value_short);
1042203c4805SLuis R. Rodriguez }
1043203c4805SLuis R. Rodriguez }
1044203c4805SLuis R. Rodriguez
1045203c4805SLuis R. Rodriguez static inline void
ath5k_debug_printrxbuf(struct ath5k_buf * bf,int done,struct ath5k_rx_status * rs)1046203c4805SLuis R. Rodriguez ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
1047203c4805SLuis R. Rodriguez struct ath5k_rx_status *rs)
1048203c4805SLuis R. Rodriguez {
1049203c4805SLuis R. Rodriguez struct ath5k_desc *ds = bf->desc;
1050203c4805SLuis R. Rodriguez struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
1051203c4805SLuis R. Rodriguez
1052203c4805SLuis R. Rodriguez printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
1053203c4805SLuis R. Rodriguez ds, (unsigned long long)bf->daddr,
1054203c4805SLuis R. Rodriguez ds->ds_link, ds->ds_data,
1055203c4805SLuis R. Rodriguez rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
105662412a8fSBruno Randolf rd->rx_stat.rx_status_0, rd->rx_stat.rx_status_1,
1057203c4805SLuis R. Rodriguez !done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
1058203c4805SLuis R. Rodriguez }
1059203c4805SLuis R. Rodriguez
1060203c4805SLuis R. Rodriguez void
ath5k_debug_printrxbuffs(struct ath5k_hw * ah)1061e0d687bdSPavel Roskin ath5k_debug_printrxbuffs(struct ath5k_hw *ah)
1062203c4805SLuis R. Rodriguez {
1063203c4805SLuis R. Rodriguez struct ath5k_desc *ds;
1064203c4805SLuis R. Rodriguez struct ath5k_buf *bf;
1065203c4805SLuis R. Rodriguez struct ath5k_rx_status rs = {};
1066203c4805SLuis R. Rodriguez int status;
1067203c4805SLuis R. Rodriguez
1068e0d687bdSPavel Roskin if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
1069203c4805SLuis R. Rodriguez return;
1070203c4805SLuis R. Rodriguez
1071265faaddSBruno Randolf printk(KERN_DEBUG "rxdp %x, rxlink %p\n",
1072e0d687bdSPavel Roskin ath5k_hw_get_rxdp(ah), ah->rxlink);
1073203c4805SLuis R. Rodriguez
1074e0d687bdSPavel Roskin spin_lock_bh(&ah->rxbuflock);
1075e0d687bdSPavel Roskin list_for_each_entry(bf, &ah->rxbuf, list) {
1076203c4805SLuis R. Rodriguez ds = bf->desc;
1077203c4805SLuis R. Rodriguez status = ah->ah_proc_rx_desc(ah, ds, &rs);
1078203c4805SLuis R. Rodriguez if (!status)
1079203c4805SLuis R. Rodriguez ath5k_debug_printrxbuf(bf, status == 0, &rs);
1080203c4805SLuis R. Rodriguez }
1081e0d687bdSPavel Roskin spin_unlock_bh(&ah->rxbuflock);
1082203c4805SLuis R. Rodriguez }
1083203c4805SLuis R. Rodriguez
1084203c4805SLuis R. Rodriguez void
ath5k_debug_printtxbuf(struct ath5k_hw * ah,struct ath5k_buf * bf)1085e0d687bdSPavel Roskin ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
1086203c4805SLuis R. Rodriguez {
1087203c4805SLuis R. Rodriguez struct ath5k_desc *ds = bf->desc;
1088203c4805SLuis R. Rodriguez struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
1089203c4805SLuis R. Rodriguez struct ath5k_tx_status ts = {};
1090203c4805SLuis R. Rodriguez int done;
1091203c4805SLuis R. Rodriguez
1092e0d687bdSPavel Roskin if (likely(!(ah->debug.level & ATH5K_DEBUG_DESC)))
1093203c4805SLuis R. Rodriguez return;
1094203c4805SLuis R. Rodriguez
1095e0d687bdSPavel Roskin done = ah->ah_proc_tx_desc(ah, bf->desc, &ts);
1096203c4805SLuis R. Rodriguez
1097203c4805SLuis R. Rodriguez printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
1098203c4805SLuis R. Rodriguez "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
1099203c4805SLuis R. Rodriguez ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
1100203c4805SLuis R. Rodriguez td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
1101203c4805SLuis R. Rodriguez td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
1102203c4805SLuis R. Rodriguez done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
1103203c4805SLuis R. Rodriguez }
1104