xref: /linux/drivers/net/wireless/ath/ath9k/debug.c (revision 5bdef865eb358b6f3760e25e591ae115e9eeddef)
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 static unsigned int ath9k_debug = DBG_DEFAULT;
22 module_param_named(debug, ath9k_debug, uint, 0);
23 
24 static struct dentry *ath9k_debugfs_root;
25 
26 void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...)
27 {
28 	if (!sc)
29 		return;
30 
31 	if (sc->debug.debug_mask & dbg_mask) {
32 		va_list args;
33 
34 		va_start(args, fmt);
35 		printk(KERN_DEBUG "ath9k: ");
36 		vprintk(fmt, args);
37 		va_end(args);
38 	}
39 }
40 
41 static int ath9k_debugfs_open(struct inode *inode, struct file *file)
42 {
43 	file->private_data = inode->i_private;
44 	return 0;
45 }
46 
47 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
48 			     size_t count, loff_t *ppos)
49 {
50 	struct ath_softc *sc = file->private_data;
51 	char buf[32];
52 	unsigned int len;
53 
54 	len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.debug_mask);
55 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
56 }
57 
58 static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
59 			     size_t count, loff_t *ppos)
60 {
61 	struct ath_softc *sc = file->private_data;
62 	unsigned long mask;
63 	char buf[32];
64 	ssize_t len;
65 
66 	len = min(count, sizeof(buf) - 1);
67 	if (copy_from_user(buf, user_buf, len))
68 		return -EINVAL;
69 
70 	buf[len] = '\0';
71 	if (strict_strtoul(buf, 0, &mask))
72 		return -EINVAL;
73 
74 	sc->debug.debug_mask = mask;
75 	return count;
76 }
77 
78 static const struct file_operations fops_debug = {
79 	.read = read_file_debug,
80 	.write = write_file_debug,
81 	.open = ath9k_debugfs_open,
82 	.owner = THIS_MODULE
83 };
84 
85 static ssize_t read_file_dma(struct file *file, char __user *user_buf,
86 			     size_t count, loff_t *ppos)
87 {
88 	struct ath_softc *sc = file->private_data;
89 	struct ath_hw *ah = sc->sc_ah;
90 	char buf[1024];
91 	unsigned int len = 0;
92 	u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
93 	int i, qcuOffset = 0, dcuOffset = 0;
94 	u32 *qcuBase = &val[0], *dcuBase = &val[4];
95 
96 	REG_WRITE(ah, AR_MACMISC,
97 		  ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
98 		   (AR_MACMISC_MISC_OBS_BUS_1 <<
99 		    AR_MACMISC_MISC_OBS_BUS_MSB_S)));
100 
101 	len += snprintf(buf + len, sizeof(buf) - len,
102 			"Raw DMA Debug values:\n");
103 
104 	for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
105 		if (i % 4 == 0)
106 			len += snprintf(buf + len, sizeof(buf) - len, "\n");
107 
108 		val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
109 		len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ",
110 				i, val[i]);
111 	}
112 
113 	len += snprintf(buf + len, sizeof(buf) - len, "\n\n");
114 	len += snprintf(buf + len, sizeof(buf) - len,
115 			"Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
116 
117 	for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
118 		if (i == 8) {
119 			qcuOffset = 0;
120 			qcuBase++;
121 		}
122 
123 		if (i == 6) {
124 			dcuOffset = 0;
125 			dcuBase++;
126 		}
127 
128 		len += snprintf(buf + len, sizeof(buf) - len,
129 			"%2d          %2x      %1x     %2x           %2x\n",
130 			i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
131 			(*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
132 			val[2] & (0x7 << (i * 3)) >> (i * 3),
133 			(*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
134 	}
135 
136 	len += snprintf(buf + len, sizeof(buf) - len, "\n");
137 
138 	len += snprintf(buf + len, sizeof(buf) - len,
139 		"qcu_stitch state:   %2x    qcu_fetch state:        %2x\n",
140 		(val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
141 	len += snprintf(buf + len, sizeof(buf) - len,
142 		"qcu_complete state: %2x    dcu_complete state:     %2x\n",
143 		(val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
144 	len += snprintf(buf + len, sizeof(buf) - len,
145 		"dcu_arb state:      %2x    dcu_fp state:           %2x\n",
146 		(val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
147 	len += snprintf(buf + len, sizeof(buf) - len,
148 		"chan_idle_dur:     %3d    chan_idle_dur_valid:     %1d\n",
149 		(val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
150 	len += snprintf(buf + len, sizeof(buf) - len,
151 		"txfifo_valid_0:      %1d    txfifo_valid_1:          %1d\n",
152 		(val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
153 	len += snprintf(buf + len, sizeof(buf) - len,
154 		"txfifo_dcu_num_0:   %2d    txfifo_dcu_num_1:       %2d\n",
155 		(val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
156 
157 	len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n",
158 			REG_READ(ah, AR_OBS_BUS_1));
159 	len += snprintf(buf + len, sizeof(buf) - len,
160 			"AR_CR: 0x%x \n", REG_READ(ah, AR_CR));
161 
162 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
163 }
164 
165 static const struct file_operations fops_dma = {
166 	.read = read_file_dma,
167 	.open = ath9k_debugfs_open,
168 	.owner = THIS_MODULE
169 };
170 
171 
172 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
173 {
174 	if (status)
175 		sc->debug.stats.istats.total++;
176 	if (status & ATH9K_INT_RX)
177 		sc->debug.stats.istats.rxok++;
178 	if (status & ATH9K_INT_RXEOL)
179 		sc->debug.stats.istats.rxeol++;
180 	if (status & ATH9K_INT_RXORN)
181 		sc->debug.stats.istats.rxorn++;
182 	if (status & ATH9K_INT_TX)
183 		sc->debug.stats.istats.txok++;
184 	if (status & ATH9K_INT_TXURN)
185 		sc->debug.stats.istats.txurn++;
186 	if (status & ATH9K_INT_MIB)
187 		sc->debug.stats.istats.mib++;
188 	if (status & ATH9K_INT_RXPHY)
189 		sc->debug.stats.istats.rxphyerr++;
190 	if (status & ATH9K_INT_RXKCM)
191 		sc->debug.stats.istats.rx_keycache_miss++;
192 	if (status & ATH9K_INT_SWBA)
193 		sc->debug.stats.istats.swba++;
194 	if (status & ATH9K_INT_BMISS)
195 		sc->debug.stats.istats.bmiss++;
196 	if (status & ATH9K_INT_BNR)
197 		sc->debug.stats.istats.bnr++;
198 	if (status & ATH9K_INT_CST)
199 		sc->debug.stats.istats.cst++;
200 	if (status & ATH9K_INT_GTT)
201 		sc->debug.stats.istats.gtt++;
202 	if (status & ATH9K_INT_TIM)
203 		sc->debug.stats.istats.tim++;
204 	if (status & ATH9K_INT_CABEND)
205 		sc->debug.stats.istats.cabend++;
206 	if (status & ATH9K_INT_DTIMSYNC)
207 		sc->debug.stats.istats.dtimsync++;
208 	if (status & ATH9K_INT_DTIM)
209 		sc->debug.stats.istats.dtim++;
210 }
211 
212 static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
213 				   size_t count, loff_t *ppos)
214 {
215 	struct ath_softc *sc = file->private_data;
216 	char buf[512];
217 	unsigned int len = 0;
218 
219 	len += snprintf(buf + len, sizeof(buf) - len,
220 		"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
221 	len += snprintf(buf + len, sizeof(buf) - len,
222 		"%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
223 	len += snprintf(buf + len, sizeof(buf) - len,
224 		"%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn);
225 	len += snprintf(buf + len, sizeof(buf) - len,
226 		"%8s: %10u\n", "TX", sc->debug.stats.istats.txok);
227 	len += snprintf(buf + len, sizeof(buf) - len,
228 		"%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn);
229 	len += snprintf(buf + len, sizeof(buf) - len,
230 		"%8s: %10u\n", "MIB", sc->debug.stats.istats.mib);
231 	len += snprintf(buf + len, sizeof(buf) - len,
232 		"%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr);
233 	len += snprintf(buf + len, sizeof(buf) - len,
234 		"%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss);
235 	len += snprintf(buf + len, sizeof(buf) - len,
236 		"%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba);
237 	len += snprintf(buf + len, sizeof(buf) - len,
238 		"%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss);
239 	len += snprintf(buf + len, sizeof(buf) - len,
240 		"%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr);
241 	len += snprintf(buf + len, sizeof(buf) - len,
242 		"%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
243 	len += snprintf(buf + len, sizeof(buf) - len,
244 		"%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt);
245 	len += snprintf(buf + len, sizeof(buf) - len,
246 		"%8s: %10u\n", "TIM", sc->debug.stats.istats.tim);
247 	len += snprintf(buf + len, sizeof(buf) - len,
248 		"%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend);
249 	len += snprintf(buf + len, sizeof(buf) - len,
250 		"%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync);
251 	len += snprintf(buf + len, sizeof(buf) - len,
252 		"%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim);
253 	len += snprintf(buf + len, sizeof(buf) - len,
254 		"%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total);
255 
256 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
257 }
258 
259 static const struct file_operations fops_interrupt = {
260 	.read = read_file_interrupt,
261 	.open = ath9k_debugfs_open,
262 	.owner = THIS_MODULE
263 };
264 
265 void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
266 {
267 	struct ath_tx_info_priv *tx_info_priv = NULL;
268 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
269 	struct ieee80211_tx_rate *rates = tx_info->status.rates;
270 	int final_ts_idx, idx;
271 	struct ath_rc_stats *stats;
272 
273 	tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
274 	final_ts_idx = tx_info_priv->tx.ts_rateindex;
275 	idx = rates[final_ts_idx].idx;
276 	stats = &sc->debug.stats.rcstats[idx];
277 	stats->success++;
278 }
279 
280 void ath_debug_stat_retries(struct ath_softc *sc, int rix,
281 			    int xretries, int retries, u8 per)
282 {
283 	struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix];
284 
285 	stats->xretries += xretries;
286 	stats->retries += retries;
287 	stats->per = per;
288 }
289 
290 static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
291 				size_t count, loff_t *ppos)
292 {
293 	struct ath_softc *sc = file->private_data;
294 	char *buf;
295 	unsigned int len = 0, max;
296 	int i = 0;
297 	ssize_t retval;
298 
299 	if (sc->cur_rate_table == NULL)
300 		return 0;
301 
302 	max = 80 + sc->cur_rate_table->rate_cnt * 64;
303 	buf = kmalloc(max + 1, GFP_KERNEL);
304 	if (buf == NULL)
305 		return 0;
306 	buf[max] = 0;
307 
308 	len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success",
309 		       "Retries", "XRetries", "PER");
310 
311 	for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
312 		u32 ratekbps = sc->cur_rate_table->info[i].ratekbps;
313 		struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i];
314 
315 		len += snprintf(buf + len, max - len,
316 			"%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000,
317 			(ratekbps % 1000) / 100, stats->success,
318 			stats->retries, stats->xretries,
319 			stats->per);
320 	}
321 
322 	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
323 	kfree(buf);
324 	return retval;
325 }
326 
327 static const struct file_operations fops_rcstat = {
328 	.read = read_file_rcstat,
329 	.open = ath9k_debugfs_open,
330 	.owner = THIS_MODULE
331 };
332 
333 static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
334 {
335 	switch (state) {
336 	case ATH_WIPHY_INACTIVE:
337 		return "INACTIVE";
338 	case ATH_WIPHY_ACTIVE:
339 		return "ACTIVE";
340 	case ATH_WIPHY_PAUSING:
341 		return "PAUSING";
342 	case ATH_WIPHY_PAUSED:
343 		return "PAUSED";
344 	case ATH_WIPHY_SCAN:
345 		return "SCAN";
346 	}
347 	return "?";
348 }
349 
350 static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
351 			       size_t count, loff_t *ppos)
352 {
353 	struct ath_softc *sc = file->private_data;
354 	char buf[512];
355 	unsigned int len = 0;
356 	int i;
357 	u8 addr[ETH_ALEN];
358 
359 	len += snprintf(buf + len, sizeof(buf) - len,
360 			"primary: %s (%s chan=%d ht=%d)\n",
361 			wiphy_name(sc->pri_wiphy->hw->wiphy),
362 			ath_wiphy_state_str(sc->pri_wiphy->state),
363 			sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht);
364 	for (i = 0; i < sc->num_sec_wiphy; i++) {
365 		struct ath_wiphy *aphy = sc->sec_wiphy[i];
366 		if (aphy == NULL)
367 			continue;
368 		len += snprintf(buf + len, sizeof(buf) - len,
369 				"secondary: %s (%s chan=%d ht=%d)\n",
370 				wiphy_name(aphy->hw->wiphy),
371 				ath_wiphy_state_str(aphy->state),
372 				aphy->chan_idx, aphy->chan_is_ht);
373 	}
374 
375 	put_unaligned_le32(REG_READ(sc->sc_ah, AR_STA_ID0), addr);
376 	put_unaligned_le16(REG_READ(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
377 	len += snprintf(buf + len, sizeof(buf) - len,
378 			"addr: %pM\n", addr);
379 	put_unaligned_le32(REG_READ(sc->sc_ah, AR_BSSMSKL), addr);
380 	put_unaligned_le16(REG_READ(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4);
381 	len += snprintf(buf + len, sizeof(buf) - len,
382 			"addrmask: %pM\n", addr);
383 
384 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
385 }
386 
387 static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name)
388 {
389 	int i;
390 	if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0)
391 		return sc->pri_wiphy;
392 	for (i = 0; i < sc->num_sec_wiphy; i++) {
393 		struct ath_wiphy *aphy = sc->sec_wiphy[i];
394 		if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0)
395 			return aphy;
396 	}
397 	return NULL;
398 }
399 
400 static int del_wiphy(struct ath_softc *sc, const char *name)
401 {
402 	struct ath_wiphy *aphy = get_wiphy(sc, name);
403 	if (!aphy)
404 		return -ENOENT;
405 	return ath9k_wiphy_del(aphy);
406 }
407 
408 static int pause_wiphy(struct ath_softc *sc, const char *name)
409 {
410 	struct ath_wiphy *aphy = get_wiphy(sc, name);
411 	if (!aphy)
412 		return -ENOENT;
413 	return ath9k_wiphy_pause(aphy);
414 }
415 
416 static int unpause_wiphy(struct ath_softc *sc, const char *name)
417 {
418 	struct ath_wiphy *aphy = get_wiphy(sc, name);
419 	if (!aphy)
420 		return -ENOENT;
421 	return ath9k_wiphy_unpause(aphy);
422 }
423 
424 static int select_wiphy(struct ath_softc *sc, const char *name)
425 {
426 	struct ath_wiphy *aphy = get_wiphy(sc, name);
427 	if (!aphy)
428 		return -ENOENT;
429 	return ath9k_wiphy_select(aphy);
430 }
431 
432 static int schedule_wiphy(struct ath_softc *sc, const char *msec)
433 {
434 	ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0));
435 	return 0;
436 }
437 
438 static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf,
439 				size_t count, loff_t *ppos)
440 {
441 	struct ath_softc *sc = file->private_data;
442 	char buf[50];
443 	size_t len;
444 
445 	len = min(count, sizeof(buf) - 1);
446 	if (copy_from_user(buf, user_buf, len))
447 		return -EFAULT;
448 	buf[len] = '\0';
449 	if (len > 0 && buf[len - 1] == '\n')
450 		buf[len - 1] = '\0';
451 
452 	if (strncmp(buf, "add", 3) == 0) {
453 		int res = ath9k_wiphy_add(sc);
454 		if (res < 0)
455 			return res;
456 	} else if (strncmp(buf, "del=", 4) == 0) {
457 		int res = del_wiphy(sc, buf + 4);
458 		if (res < 0)
459 			return res;
460 	} else if (strncmp(buf, "pause=", 6) == 0) {
461 		int res = pause_wiphy(sc, buf + 6);
462 		if (res < 0)
463 			return res;
464 	} else if (strncmp(buf, "unpause=", 8) == 0) {
465 		int res = unpause_wiphy(sc, buf + 8);
466 		if (res < 0)
467 			return res;
468 	} else if (strncmp(buf, "select=", 7) == 0) {
469 		int res = select_wiphy(sc, buf + 7);
470 		if (res < 0)
471 			return res;
472 	} else if (strncmp(buf, "schedule=", 9) == 0) {
473 		int res = schedule_wiphy(sc, buf + 9);
474 		if (res < 0)
475 			return res;
476 	} else
477 		return -EOPNOTSUPP;
478 
479 	return count;
480 }
481 
482 static const struct file_operations fops_wiphy = {
483 	.read = read_file_wiphy,
484 	.write = write_file_wiphy,
485 	.open = ath9k_debugfs_open,
486 	.owner = THIS_MODULE
487 };
488 
489 
490 int ath9k_init_debug(struct ath_softc *sc)
491 {
492 	sc->debug.debug_mask = ath9k_debug;
493 
494 	if (!ath9k_debugfs_root)
495 		return -ENOENT;
496 
497 	sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
498 						      ath9k_debugfs_root);
499 	if (!sc->debug.debugfs_phy)
500 		goto err;
501 
502 	sc->debug.debugfs_debug = debugfs_create_file("debug",
503 		S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug);
504 	if (!sc->debug.debugfs_debug)
505 		goto err;
506 
507 	sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO,
508 				       sc->debug.debugfs_phy, sc, &fops_dma);
509 	if (!sc->debug.debugfs_dma)
510 		goto err;
511 
512 	sc->debug.debugfs_interrupt = debugfs_create_file("interrupt",
513 						     S_IRUGO,
514 						     sc->debug.debugfs_phy,
515 						     sc, &fops_interrupt);
516 	if (!sc->debug.debugfs_interrupt)
517 		goto err;
518 
519 	sc->debug.debugfs_rcstat = debugfs_create_file("rcstat",
520 						  S_IRUGO,
521 						  sc->debug.debugfs_phy,
522 						  sc, &fops_rcstat);
523 	if (!sc->debug.debugfs_rcstat)
524 		goto err;
525 
526 	sc->debug.debugfs_wiphy = debugfs_create_file(
527 		"wiphy", S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc,
528 		&fops_wiphy);
529 	if (!sc->debug.debugfs_wiphy)
530 		goto err;
531 
532 	return 0;
533 err:
534 	ath9k_exit_debug(sc);
535 	return -ENOMEM;
536 }
537 
538 void ath9k_exit_debug(struct ath_softc *sc)
539 {
540 	debugfs_remove(sc->debug.debugfs_wiphy);
541 	debugfs_remove(sc->debug.debugfs_rcstat);
542 	debugfs_remove(sc->debug.debugfs_interrupt);
543 	debugfs_remove(sc->debug.debugfs_dma);
544 	debugfs_remove(sc->debug.debugfs_debug);
545 	debugfs_remove(sc->debug.debugfs_phy);
546 }
547 
548 int ath9k_debug_create_root(void)
549 {
550 	ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
551 	if (!ath9k_debugfs_root)
552 		return -ENOENT;
553 
554 	return 0;
555 }
556 
557 void ath9k_debug_remove_root(void)
558 {
559 	debugfs_remove(ath9k_debugfs_root);
560 	ath9k_debugfs_root = NULL;
561 }
562