1 /*
2  * Copyright (c) 2008-2009 Atheros Communications 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 <asm/unaligned.h>
18 
19 #include "ath9k.h"
20 
21 #define REG_WRITE_D(_ah, _reg, _val) \
22 	ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
23 #define REG_READ_D(_ah, _reg) \
24 	ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
25 
26 static struct dentry *ath9k_debugfs_root;
27 
28 static int ath9k_debugfs_open(struct inode *inode, struct file *file)
29 {
30 	file->private_data = inode->i_private;
31 	return 0;
32 }
33 
34 #ifdef CONFIG_ATH_DEBUG
35 
36 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
37 			     size_t count, loff_t *ppos)
38 {
39 	struct ath_softc *sc = file->private_data;
40 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
41 	char buf[32];
42 	unsigned int len;
43 
44 	len = snprintf(buf, sizeof(buf), "0x%08x\n", common->debug_mask);
45 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
46 }
47 
48 static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
49 			     size_t count, loff_t *ppos)
50 {
51 	struct ath_softc *sc = file->private_data;
52 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
53 	unsigned long mask;
54 	char buf[32];
55 	ssize_t len;
56 
57 	len = min(count, sizeof(buf) - 1);
58 	if (copy_from_user(buf, user_buf, len))
59 		return -EINVAL;
60 
61 	buf[len] = '\0';
62 	if (strict_strtoul(buf, 0, &mask))
63 		return -EINVAL;
64 
65 	common->debug_mask = mask;
66 	return count;
67 }
68 
69 static const struct file_operations fops_debug = {
70 	.read = read_file_debug,
71 	.write = write_file_debug,
72 	.open = ath9k_debugfs_open,
73 	.owner = THIS_MODULE
74 };
75 
76 #endif
77 
78 static ssize_t read_file_dma(struct file *file, char __user *user_buf,
79 			     size_t count, loff_t *ppos)
80 {
81 	struct ath_softc *sc = file->private_data;
82 	struct ath_hw *ah = sc->sc_ah;
83 	char buf[1024];
84 	unsigned int len = 0;
85 	u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
86 	int i, qcuOffset = 0, dcuOffset = 0;
87 	u32 *qcuBase = &val[0], *dcuBase = &val[4];
88 
89 	ath9k_ps_wakeup(sc);
90 
91 	REG_WRITE_D(ah, AR_MACMISC,
92 		  ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
93 		   (AR_MACMISC_MISC_OBS_BUS_1 <<
94 		    AR_MACMISC_MISC_OBS_BUS_MSB_S)));
95 
96 	len += snprintf(buf + len, sizeof(buf) - len,
97 			"Raw DMA Debug values:\n");
98 
99 	for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
100 		if (i % 4 == 0)
101 			len += snprintf(buf + len, sizeof(buf) - len, "\n");
102 
103 		val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32)));
104 		len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ",
105 				i, val[i]);
106 	}
107 
108 	len += snprintf(buf + len, sizeof(buf) - len, "\n\n");
109 	len += snprintf(buf + len, sizeof(buf) - len,
110 			"Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
111 
112 	for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
113 		if (i == 8) {
114 			qcuOffset = 0;
115 			qcuBase++;
116 		}
117 
118 		if (i == 6) {
119 			dcuOffset = 0;
120 			dcuBase++;
121 		}
122 
123 		len += snprintf(buf + len, sizeof(buf) - len,
124 			"%2d          %2x      %1x     %2x           %2x\n",
125 			i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
126 			(*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
127 			val[2] & (0x7 << (i * 3)) >> (i * 3),
128 			(*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
129 	}
130 
131 	len += snprintf(buf + len, sizeof(buf) - len, "\n");
132 
133 	len += snprintf(buf + len, sizeof(buf) - len,
134 		"qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
135 		(val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
136 	len += snprintf(buf + len, sizeof(buf) - len,
137 		"qcu_complete state: %2x    dcu_complete state:     %2x\n",
138 		(val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
139 	len += snprintf(buf + len, sizeof(buf) - len,
140 		"dcu_arb state:      %2x    dcu_fp state:           %2x\n",
141 		(val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
142 	len += snprintf(buf + len, sizeof(buf) - len,
143 		"chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
144 		(val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
145 	len += snprintf(buf + len, sizeof(buf) - len,
146 		"txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
147 		(val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
148 	len += snprintf(buf + len, sizeof(buf) - len,
149 		"txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
150 		(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
151 
152 	len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n",
153 			REG_READ_D(ah, AR_OBS_BUS_1));
154 	len += snprintf(buf + len, sizeof(buf) - len,
155 			"AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR));
156 
157 	ath9k_ps_restore(sc);
158 
159 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
160 }
161 
162 static const struct file_operations fops_dma = {
163 	.read = read_file_dma,
164 	.open = ath9k_debugfs_open,
165 	.owner = THIS_MODULE
166 };
167 
168 
169 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
170 {
171 	if (status)
172 		sc->debug.stats.istats.total++;
173 	if (status & ATH9K_INT_RX)
174 		sc->debug.stats.istats.rxok++;
175 	if (status & ATH9K_INT_RXEOL)
176 		sc->debug.stats.istats.rxeol++;
177 	if (status & ATH9K_INT_RXORN)
178 		sc->debug.stats.istats.rxorn++;
179 	if (status & ATH9K_INT_TX)
180 		sc->debug.stats.istats.txok++;
181 	if (status & ATH9K_INT_TXURN)
182 		sc->debug.stats.istats.txurn++;
183 	if (status & ATH9K_INT_MIB)
184 		sc->debug.stats.istats.mib++;
185 	if (status & ATH9K_INT_RXPHY)
186 		sc->debug.stats.istats.rxphyerr++;
187 	if (status & ATH9K_INT_RXKCM)
188 		sc->debug.stats.istats.rx_keycache_miss++;
189 	if (status & ATH9K_INT_SWBA)
190 		sc->debug.stats.istats.swba++;
191 	if (status & ATH9K_INT_BMISS)
192 		sc->debug.stats.istats.bmiss++;
193 	if (status & ATH9K_INT_BNR)
194 		sc->debug.stats.istats.bnr++;
195 	if (status & ATH9K_INT_CST)
196 		sc->debug.stats.istats.cst++;
197 	if (status & ATH9K_INT_GTT)
198 		sc->debug.stats.istats.gtt++;
199 	if (status & ATH9K_INT_TIM)
200 		sc->debug.stats.istats.tim++;
201 	if (status & ATH9K_INT_CABEND)
202 		sc->debug.stats.istats.cabend++;
203 	if (status & ATH9K_INT_DTIMSYNC)
204 		sc->debug.stats.istats.dtimsync++;
205 	if (status & ATH9K_INT_DTIM)
206 		sc->debug.stats.istats.dtim++;
207 }
208 
209 static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
210 				   size_t count, loff_t *ppos)
211 {
212 	struct ath_softc *sc = file->private_data;
213 	char buf[512];
214 	unsigned int len = 0;
215 
216 	len += snprintf(buf + len, sizeof(buf) - len,
217 		"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
218 	len += snprintf(buf + len, sizeof(buf) - len,
219 		"%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
220 	len += snprintf(buf + len, sizeof(buf) - len,
221 		"%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn);
222 	len += snprintf(buf + len, sizeof(buf) - len,
223 		"%8s: %10u\n", "TX", sc->debug.stats.istats.txok);
224 	len += snprintf(buf + len, sizeof(buf) - len,
225 		"%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn);
226 	len += snprintf(buf + len, sizeof(buf) - len,
227 		"%8s: %10u\n", "MIB", sc->debug.stats.istats.mib);
228 	len += snprintf(buf + len, sizeof(buf) - len,
229 		"%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr);
230 	len += snprintf(buf + len, sizeof(buf) - len,
231 		"%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss);
232 	len += snprintf(buf + len, sizeof(buf) - len,
233 		"%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba);
234 	len += snprintf(buf + len, sizeof(buf) - len,
235 		"%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss);
236 	len += snprintf(buf + len, sizeof(buf) - len,
237 		"%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr);
238 	len += snprintf(buf + len, sizeof(buf) - len,
239 		"%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
240 	len += snprintf(buf + len, sizeof(buf) - len,
241 		"%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt);
242 	len += snprintf(buf + len, sizeof(buf) - len,
243 		"%8s: %10u\n", "TIM", sc->debug.stats.istats.tim);
244 	len += snprintf(buf + len, sizeof(buf) - len,
245 		"%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend);
246 	len += snprintf(buf + len, sizeof(buf) - len,
247 		"%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync);
248 	len += snprintf(buf + len, sizeof(buf) - len,
249 		"%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim);
250 	len += snprintf(buf + len, sizeof(buf) - len,
251 		"%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total);
252 
253 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
254 }
255 
256 static const struct file_operations fops_interrupt = {
257 	.read = read_file_interrupt,
258 	.open = ath9k_debugfs_open,
259 	.owner = THIS_MODULE
260 };
261 
262 void ath_debug_stat_rc(struct ath_softc *sc, int final_rate)
263 {
264 	struct ath_rc_stats *stats;
265 
266 	stats = &sc->debug.stats.rcstats[final_rate];
267 	stats->success++;
268 }
269 
270 void ath_debug_stat_retries(struct ath_softc *sc, int rix,
271 			    int xretries, int retries, u8 per)
272 {
273 	struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix];
274 
275 	stats->xretries += xretries;
276 	stats->retries += retries;
277 	stats->per = per;
278 }
279 
280 static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
281 				size_t count, loff_t *ppos)
282 {
283 	struct ath_softc *sc = file->private_data;
284 	char *buf;
285 	unsigned int len = 0, max;
286 	int i = 0;
287 	ssize_t retval;
288 
289 	if (sc->cur_rate_table == NULL)
290 		return 0;
291 
292 	max = 80 + sc->cur_rate_table->rate_cnt * 64;
293 	buf = kmalloc(max + 1, GFP_KERNEL);
294 	if (buf == NULL)
295 		return 0;
296 	buf[max] = 0;
297 
298 	len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success",
299 		       "Retries", "XRetries", "PER");
300 
301 	for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
302 		u32 ratekbps = sc->cur_rate_table->info[i].ratekbps;
303 		struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i];
304 
305 		len += snprintf(buf + len, max - len,
306 			"%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000,
307 			(ratekbps % 1000) / 100, stats->success,
308 			stats->retries, stats->xretries,
309 			stats->per);
310 	}
311 
312 	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
313 	kfree(buf);
314 	return retval;
315 }
316 
317 static const struct file_operations fops_rcstat = {
318 	.read = read_file_rcstat,
319 	.open = ath9k_debugfs_open,
320 	.owner = THIS_MODULE
321 };
322 
323 static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
324 {
325 	switch (state) {
326 	case ATH_WIPHY_INACTIVE:
327 		return "INACTIVE";
328 	case ATH_WIPHY_ACTIVE:
329 		return "ACTIVE";
330 	case ATH_WIPHY_PAUSING:
331 		return "PAUSING";
332 	case ATH_WIPHY_PAUSED:
333 		return "PAUSED";
334 	case ATH_WIPHY_SCAN:
335 		return "SCAN";
336 	}
337 	return "?";
338 }
339 
340 static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
341 			       size_t count, loff_t *ppos)
342 {
343 	struct ath_softc *sc = file->private_data;
344 	char buf[512];
345 	unsigned int len = 0;
346 	int i;
347 	u8 addr[ETH_ALEN];
348 
349 	len += snprintf(buf + len, sizeof(buf) - len,
350 			"primary: %s (%s chan=%d ht=%d)\n",
351 			wiphy_name(sc->pri_wiphy->hw->wiphy),
352 			ath_wiphy_state_str(sc->pri_wiphy->state),
353 			sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht);
354 	for (i = 0; i < sc->num_sec_wiphy; i++) {
355 		struct ath_wiphy *aphy = sc->sec_wiphy[i];
356 		if (aphy == NULL)
357 			continue;
358 		len += snprintf(buf + len, sizeof(buf) - len,
359 				"secondary: %s (%s chan=%d ht=%d)\n",
360 				wiphy_name(aphy->hw->wiphy),
361 				ath_wiphy_state_str(aphy->state),
362 				aphy->chan_idx, aphy->chan_is_ht);
363 	}
364 
365 	put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr);
366 	put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
367 	len += snprintf(buf + len, sizeof(buf) - len,
368 			"addr: %pM\n", addr);
369 	put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_BSSMSKL), addr);
370 	put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4);
371 	len += snprintf(buf + len, sizeof(buf) - len,
372 			"addrmask: %pM\n", addr);
373 
374 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
375 }
376 
377 static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name)
378 {
379 	int i;
380 	if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0)
381 		return sc->pri_wiphy;
382 	for (i = 0; i < sc->num_sec_wiphy; i++) {
383 		struct ath_wiphy *aphy = sc->sec_wiphy[i];
384 		if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0)
385 			return aphy;
386 	}
387 	return NULL;
388 }
389 
390 static int del_wiphy(struct ath_softc *sc, const char *name)
391 {
392 	struct ath_wiphy *aphy = get_wiphy(sc, name);
393 	if (!aphy)
394 		return -ENOENT;
395 	return ath9k_wiphy_del(aphy);
396 }
397 
398 static int pause_wiphy(struct ath_softc *sc, const char *name)
399 {
400 	struct ath_wiphy *aphy = get_wiphy(sc, name);
401 	if (!aphy)
402 		return -ENOENT;
403 	return ath9k_wiphy_pause(aphy);
404 }
405 
406 static int unpause_wiphy(struct ath_softc *sc, const char *name)
407 {
408 	struct ath_wiphy *aphy = get_wiphy(sc, name);
409 	if (!aphy)
410 		return -ENOENT;
411 	return ath9k_wiphy_unpause(aphy);
412 }
413 
414 static int select_wiphy(struct ath_softc *sc, const char *name)
415 {
416 	struct ath_wiphy *aphy = get_wiphy(sc, name);
417 	if (!aphy)
418 		return -ENOENT;
419 	return ath9k_wiphy_select(aphy);
420 }
421 
422 static int schedule_wiphy(struct ath_softc *sc, const char *msec)
423 {
424 	ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0));
425 	return 0;
426 }
427 
428 static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf,
429 				size_t count, loff_t *ppos)
430 {
431 	struct ath_softc *sc = file->private_data;
432 	char buf[50];
433 	size_t len;
434 
435 	len = min(count, sizeof(buf) - 1);
436 	if (copy_from_user(buf, user_buf, len))
437 		return -EFAULT;
438 	buf[len] = '\0';
439 	if (len > 0 && buf[len - 1] == '\n')
440 		buf[len - 1] = '\0';
441 
442 	if (strncmp(buf, "add", 3) == 0) {
443 		int res = ath9k_wiphy_add(sc);
444 		if (res < 0)
445 			return res;
446 	} else if (strncmp(buf, "del=", 4) == 0) {
447 		int res = del_wiphy(sc, buf + 4);
448 		if (res < 0)
449 			return res;
450 	} else if (strncmp(buf, "pause=", 6) == 0) {
451 		int res = pause_wiphy(sc, buf + 6);
452 		if (res < 0)
453 			return res;
454 	} else if (strncmp(buf, "unpause=", 8) == 0) {
455 		int res = unpause_wiphy(sc, buf + 8);
456 		if (res < 0)
457 			return res;
458 	} else if (strncmp(buf, "select=", 7) == 0) {
459 		int res = select_wiphy(sc, buf + 7);
460 		if (res < 0)
461 			return res;
462 	} else if (strncmp(buf, "schedule=", 9) == 0) {
463 		int res = schedule_wiphy(sc, buf + 9);
464 		if (res < 0)
465 			return res;
466 	} else
467 		return -EOPNOTSUPP;
468 
469 	return count;
470 }
471 
472 static const struct file_operations fops_wiphy = {
473 	.read = read_file_wiphy,
474 	.write = write_file_wiphy,
475 	.open = ath9k_debugfs_open,
476 	.owner = THIS_MODULE
477 };
478 
479 #define PR(str, elem)							\
480 	do {								\
481 		len += snprintf(buf + len, size - len,			\
482 				"%s%13u%11u%10u%10u\n", str,		\
483 		sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BE]].elem, \
484 		sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \
485 		sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \
486 		sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \
487 } while(0)
488 
489 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
490 			      size_t count, loff_t *ppos)
491 {
492 	struct ath_softc *sc = file->private_data;
493 	char *buf;
494 	unsigned int len = 0, size = 2048;
495 	ssize_t retval = 0;
496 
497 	buf = kzalloc(size, GFP_KERNEL);
498 	if (buf == NULL)
499 		return 0;
500 
501 	len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
502 
503 	PR("MPDUs Queued:    ", queued);
504 	PR("MPDUs Completed: ", completed);
505 	PR("Aggregates:      ", a_aggr);
506 	PR("AMPDUs Queued:   ", a_queued);
507 	PR("AMPDUs Completed:", a_completed);
508 	PR("AMPDUs Retried:  ", a_retries);
509 	PR("AMPDUs XRetried: ", a_xretries);
510 	PR("FIFO Underrun:   ", fifo_underrun);
511 	PR("TXOP Exceeded:   ", xtxop);
512 	PR("TXTIMER Expiry:  ", timer_exp);
513 	PR("DESC CFG Error:  ", desc_cfg_err);
514 	PR("DATA Underrun:   ", data_underrun);
515 	PR("DELIM Underrun:  ", delim_underrun);
516 
517 	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
518 	kfree(buf);
519 
520 	return retval;
521 }
522 
523 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
524 		       struct ath_buf *bf)
525 {
526 	struct ath_desc *ds = bf->bf_desc;
527 
528 	if (bf_isampdu(bf)) {
529 		if (bf_isxretried(bf))
530 			TX_STAT_INC(txq->axq_qnum, a_xretries);
531 		else
532 			TX_STAT_INC(txq->axq_qnum, a_completed);
533 	} else {
534 		TX_STAT_INC(txq->axq_qnum, completed);
535 	}
536 
537 	if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)
538 		TX_STAT_INC(txq->axq_qnum, fifo_underrun);
539 	if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP)
540 		TX_STAT_INC(txq->axq_qnum, xtxop);
541 	if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED)
542 		TX_STAT_INC(txq->axq_qnum, timer_exp);
543 	if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR)
544 		TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
545 	if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN)
546 		TX_STAT_INC(txq->axq_qnum, data_underrun);
547 	if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN)
548 		TX_STAT_INC(txq->axq_qnum, delim_underrun);
549 }
550 
551 static const struct file_operations fops_xmit = {
552 	.read = read_file_xmit,
553 	.open = ath9k_debugfs_open,
554 	.owner = THIS_MODULE
555 };
556 
557 int ath9k_init_debug(struct ath_hw *ah)
558 {
559 	struct ath_common *common = ath9k_hw_common(ah);
560 	struct ath_softc *sc = (struct ath_softc *) common->priv;
561 
562 	if (!ath9k_debugfs_root)
563 		return -ENOENT;
564 
565 	sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
566 						      ath9k_debugfs_root);
567 	if (!sc->debug.debugfs_phy)
568 		goto err;
569 
570 #ifdef CONFIG_ATH_DEBUG
571 	sc->debug.debugfs_debug = debugfs_create_file("debug",
572 		S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug);
573 	if (!sc->debug.debugfs_debug)
574 		goto err;
575 #endif
576 
577 	sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR,
578 				       sc->debug.debugfs_phy, sc, &fops_dma);
579 	if (!sc->debug.debugfs_dma)
580 		goto err;
581 
582 	sc->debug.debugfs_interrupt = debugfs_create_file("interrupt",
583 						     S_IRUSR,
584 						     sc->debug.debugfs_phy,
585 						     sc, &fops_interrupt);
586 	if (!sc->debug.debugfs_interrupt)
587 		goto err;
588 
589 	sc->debug.debugfs_rcstat = debugfs_create_file("rcstat",
590 						  S_IRUSR,
591 						  sc->debug.debugfs_phy,
592 						  sc, &fops_rcstat);
593 	if (!sc->debug.debugfs_rcstat)
594 		goto err;
595 
596 	sc->debug.debugfs_wiphy = debugfs_create_file(
597 		"wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc,
598 		&fops_wiphy);
599 	if (!sc->debug.debugfs_wiphy)
600 		goto err;
601 
602 	sc->debug.debugfs_xmit = debugfs_create_file("xmit",
603 						     S_IRUSR,
604 						     sc->debug.debugfs_phy,
605 						     sc, &fops_xmit);
606 	if (!sc->debug.debugfs_xmit)
607 		goto err;
608 
609 	return 0;
610 err:
611 	ath9k_exit_debug(ah);
612 	return -ENOMEM;
613 }
614 
615 void ath9k_exit_debug(struct ath_hw *ah)
616 {
617 	struct ath_common *common = ath9k_hw_common(ah);
618 	struct ath_softc *sc = (struct ath_softc *) common->priv;
619 
620 	debugfs_remove(sc->debug.debugfs_xmit);
621 	debugfs_remove(sc->debug.debugfs_wiphy);
622 	debugfs_remove(sc->debug.debugfs_rcstat);
623 	debugfs_remove(sc->debug.debugfs_interrupt);
624 	debugfs_remove(sc->debug.debugfs_dma);
625 	debugfs_remove(sc->debug.debugfs_debug);
626 	debugfs_remove(sc->debug.debugfs_phy);
627 }
628 
629 int ath9k_debug_create_root(void)
630 {
631 	ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
632 	if (!ath9k_debugfs_root)
633 		return -ENOENT;
634 
635 	return 0;
636 }
637 
638 void ath9k_debug_remove_root(void)
639 {
640 	debugfs_remove(ath9k_debugfs_root);
641 	ath9k_debugfs_root = NULL;
642 }
643