blob: 8d91422106d9fbf63f55b9bd61a6281153651166 [file] [log] [blame]
Sujith88b126a2008-11-28 22:19:02 +05301/*
2 * Copyright (c) 2008 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
Sujith394cf0a2009-02-09 13:26:54 +053017#include "ath9k.h"
Sujith88b126a2008-11-28 22:19:02 +053018
19static unsigned int ath9k_debug = DBG_DEFAULT;
20module_param_named(debug, ath9k_debug, uint, 0);
21
22void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...)
23{
24 if (!sc)
25 return;
26
Sujith17d79042009-02-09 13:27:03 +053027 if (sc->debug.debug_mask & dbg_mask) {
Sujith88b126a2008-11-28 22:19:02 +053028 va_list args;
29
30 va_start(args, fmt);
31 printk(KERN_DEBUG "ath9k: ");
32 vprintk(fmt, args);
33 va_end(args);
34 }
35}
36
Sujith2a163c62008-11-28 22:21:08 +053037static int ath9k_debugfs_open(struct inode *inode, struct file *file)
38{
39 file->private_data = inode->i_private;
40 return 0;
41}
42
43static ssize_t read_file_dma(struct file *file, char __user *user_buf,
44 size_t count, loff_t *ppos)
45{
46 struct ath_softc *sc = file->private_data;
Sujithcbe61d82009-02-09 13:27:12 +053047 struct ath_hw *ah = sc->sc_ah;
Sujith2a163c62008-11-28 22:21:08 +053048 char buf[1024];
49 unsigned int len = 0;
50 u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
51 int i, qcuOffset = 0, dcuOffset = 0;
52 u32 *qcuBase = &val[0], *dcuBase = &val[4];
53
54 REG_WRITE(ah, AR_MACMISC,
55 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
56 (AR_MACMISC_MISC_OBS_BUS_1 <<
57 AR_MACMISC_MISC_OBS_BUS_MSB_S)));
58
59 len += snprintf(buf + len, sizeof(buf) - len,
60 "Raw DMA Debug values:\n");
61
62 for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
63 if (i % 4 == 0)
64 len += snprintf(buf + len, sizeof(buf) - len, "\n");
65
66 val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
67 len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ",
68 i, val[i]);
69 }
70
71 len += snprintf(buf + len, sizeof(buf) - len, "\n\n");
72 len += snprintf(buf + len, sizeof(buf) - len,
73 "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
74
75 for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
76 if (i == 8) {
77 qcuOffset = 0;
78 qcuBase++;
79 }
80
81 if (i == 6) {
82 dcuOffset = 0;
83 dcuBase++;
84 }
85
86 len += snprintf(buf + len, sizeof(buf) - len,
87 "%2d %2x %1x %2x %2x\n",
88 i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
89 (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
90 val[2] & (0x7 << (i * 3)) >> (i * 3),
91 (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
92 }
93
94 len += snprintf(buf + len, sizeof(buf) - len, "\n");
95
96 len += snprintf(buf + len, sizeof(buf) - len,
97 "qcu_stitch state: %2x qcu_fetch state: %2x\n",
98 (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
99 len += snprintf(buf + len, sizeof(buf) - len,
100 "qcu_complete state: %2x dcu_complete state: %2x\n",
101 (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
102 len += snprintf(buf + len, sizeof(buf) - len,
103 "dcu_arb state: %2x dcu_fp state: %2x\n",
104 (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
105 len += snprintf(buf + len, sizeof(buf) - len,
106 "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
107 (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
108 len += snprintf(buf + len, sizeof(buf) - len,
109 "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
110 (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
111 len += snprintf(buf + len, sizeof(buf) - len,
112 "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
113 (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
114
115 len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n",
116 REG_READ(ah, AR_OBS_BUS_1));
117 len += snprintf(buf + len, sizeof(buf) - len,
118 "AR_CR: 0x%x \n", REG_READ(ah, AR_CR));
119
120 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
121}
122
123static const struct file_operations fops_dma = {
124 .read = read_file_dma,
125 .open = ath9k_debugfs_open,
126 .owner = THIS_MODULE
127};
128
Sujith817e11d2008-12-07 21:42:44 +0530129
130void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
131{
132 if (status)
Sujith17d79042009-02-09 13:27:03 +0530133 sc->debug.stats.istats.total++;
Sujith817e11d2008-12-07 21:42:44 +0530134 if (status & ATH9K_INT_RX)
Sujith17d79042009-02-09 13:27:03 +0530135 sc->debug.stats.istats.rxok++;
Sujith817e11d2008-12-07 21:42:44 +0530136 if (status & ATH9K_INT_RXEOL)
Sujith17d79042009-02-09 13:27:03 +0530137 sc->debug.stats.istats.rxeol++;
Sujith817e11d2008-12-07 21:42:44 +0530138 if (status & ATH9K_INT_RXORN)
Sujith17d79042009-02-09 13:27:03 +0530139 sc->debug.stats.istats.rxorn++;
Sujith817e11d2008-12-07 21:42:44 +0530140 if (status & ATH9K_INT_TX)
Sujith17d79042009-02-09 13:27:03 +0530141 sc->debug.stats.istats.txok++;
Sujith817e11d2008-12-07 21:42:44 +0530142 if (status & ATH9K_INT_TXURN)
Sujith17d79042009-02-09 13:27:03 +0530143 sc->debug.stats.istats.txurn++;
Sujith817e11d2008-12-07 21:42:44 +0530144 if (status & ATH9K_INT_MIB)
Sujith17d79042009-02-09 13:27:03 +0530145 sc->debug.stats.istats.mib++;
Sujith817e11d2008-12-07 21:42:44 +0530146 if (status & ATH9K_INT_RXPHY)
Sujith17d79042009-02-09 13:27:03 +0530147 sc->debug.stats.istats.rxphyerr++;
Sujith817e11d2008-12-07 21:42:44 +0530148 if (status & ATH9K_INT_RXKCM)
Sujith17d79042009-02-09 13:27:03 +0530149 sc->debug.stats.istats.rx_keycache_miss++;
Sujith817e11d2008-12-07 21:42:44 +0530150 if (status & ATH9K_INT_SWBA)
Sujith17d79042009-02-09 13:27:03 +0530151 sc->debug.stats.istats.swba++;
Sujith817e11d2008-12-07 21:42:44 +0530152 if (status & ATH9K_INT_BMISS)
Sujith17d79042009-02-09 13:27:03 +0530153 sc->debug.stats.istats.bmiss++;
Sujith817e11d2008-12-07 21:42:44 +0530154 if (status & ATH9K_INT_BNR)
Sujith17d79042009-02-09 13:27:03 +0530155 sc->debug.stats.istats.bnr++;
Sujith817e11d2008-12-07 21:42:44 +0530156 if (status & ATH9K_INT_CST)
Sujith17d79042009-02-09 13:27:03 +0530157 sc->debug.stats.istats.cst++;
Sujith817e11d2008-12-07 21:42:44 +0530158 if (status & ATH9K_INT_GTT)
Sujith17d79042009-02-09 13:27:03 +0530159 sc->debug.stats.istats.gtt++;
Sujith817e11d2008-12-07 21:42:44 +0530160 if (status & ATH9K_INT_TIM)
Sujith17d79042009-02-09 13:27:03 +0530161 sc->debug.stats.istats.tim++;
Sujith817e11d2008-12-07 21:42:44 +0530162 if (status & ATH9K_INT_CABEND)
Sujith17d79042009-02-09 13:27:03 +0530163 sc->debug.stats.istats.cabend++;
Sujith817e11d2008-12-07 21:42:44 +0530164 if (status & ATH9K_INT_DTIMSYNC)
Sujith17d79042009-02-09 13:27:03 +0530165 sc->debug.stats.istats.dtimsync++;
Sujith817e11d2008-12-07 21:42:44 +0530166 if (status & ATH9K_INT_DTIM)
Sujith17d79042009-02-09 13:27:03 +0530167 sc->debug.stats.istats.dtim++;
Sujith817e11d2008-12-07 21:42:44 +0530168}
169
170static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
171 size_t count, loff_t *ppos)
172{
173 struct ath_softc *sc = file->private_data;
174 char buf[512];
175 unsigned int len = 0;
176
177 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530178 "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
Sujith817e11d2008-12-07 21:42:44 +0530179 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530180 "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
Sujith817e11d2008-12-07 21:42:44 +0530181 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530182 "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn);
Sujith817e11d2008-12-07 21:42:44 +0530183 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530184 "%8s: %10u\n", "TX", sc->debug.stats.istats.txok);
Sujith817e11d2008-12-07 21:42:44 +0530185 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530186 "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn);
Sujith817e11d2008-12-07 21:42:44 +0530187 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530188 "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib);
Sujith817e11d2008-12-07 21:42:44 +0530189 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530190 "%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr);
Sujith817e11d2008-12-07 21:42:44 +0530191 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530192 "%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss);
Sujith817e11d2008-12-07 21:42:44 +0530193 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530194 "%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba);
Sujith817e11d2008-12-07 21:42:44 +0530195 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530196 "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss);
Sujith817e11d2008-12-07 21:42:44 +0530197 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530198 "%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr);
Sujith817e11d2008-12-07 21:42:44 +0530199 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530200 "%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
Sujith817e11d2008-12-07 21:42:44 +0530201 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530202 "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt);
Sujith817e11d2008-12-07 21:42:44 +0530203 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530204 "%8s: %10u\n", "TIM", sc->debug.stats.istats.tim);
Sujith817e11d2008-12-07 21:42:44 +0530205 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530206 "%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend);
Sujith817e11d2008-12-07 21:42:44 +0530207 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530208 "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync);
Sujith817e11d2008-12-07 21:42:44 +0530209 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530210 "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim);
Sujith817e11d2008-12-07 21:42:44 +0530211 len += snprintf(buf + len, sizeof(buf) - len,
Sujith17d79042009-02-09 13:27:03 +0530212 "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total);
Sujith817e11d2008-12-07 21:42:44 +0530213
214 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
215}
216
217static const struct file_operations fops_interrupt = {
218 .read = read_file_interrupt,
219 .open = ath9k_debugfs_open,
220 .owner = THIS_MODULE
221};
222
Sujith7a7dec62009-01-30 14:32:09 +0530223static void ath_debug_stat_11n_rc(struct ath_softc *sc, struct sk_buff *skb)
224{
225 struct ath_tx_info_priv *tx_info_priv = NULL;
226 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
227 struct ieee80211_tx_rate *rates = tx_info->status.rates;
228 int final_ts_idx, idx;
229
230 tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
231 final_ts_idx = tx_info_priv->tx.ts_rateindex;
232 idx = sc->cur_rate_table->info[rates[final_ts_idx].idx].dot11rate;
233
Sujith17d79042009-02-09 13:27:03 +0530234 sc->debug.stats.n_rcstats[idx].success++;
Sujith7a7dec62009-01-30 14:32:09 +0530235}
236
237static void ath_debug_stat_legacy_rc(struct ath_softc *sc, struct sk_buff *skb)
238{
239 struct ath_tx_info_priv *tx_info_priv = NULL;
240 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
241 struct ieee80211_tx_rate *rates = tx_info->status.rates;
242 int final_ts_idx, idx;
243
244 tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
245 final_ts_idx = tx_info_priv->tx.ts_rateindex;
246 idx = rates[final_ts_idx].idx;
247
Sujith17d79042009-02-09 13:27:03 +0530248 sc->debug.stats.legacy_rcstats[idx].success++;
Sujith7a7dec62009-01-30 14:32:09 +0530249}
250
251void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb)
252{
253 if (conf_is_ht(&sc->hw->conf))
254 ath_debug_stat_11n_rc(sc, skb);
255 else
256 ath_debug_stat_legacy_rc(sc, skb);
257}
258
Sujith029bc432009-02-04 08:10:26 +0530259/* FIXME: legacy rates, later on .. */
260void ath_debug_stat_retries(struct ath_softc *sc, int rix,
Sujith9e712792009-02-20 15:13:20 +0530261 int xretries, int retries, u8 per)
Sujith029bc432009-02-04 08:10:26 +0530262{
263 if (conf_is_ht(&sc->hw->conf)) {
264 int idx = sc->cur_rate_table->info[rix].dot11rate;
265
Sujith17d79042009-02-09 13:27:03 +0530266 sc->debug.stats.n_rcstats[idx].xretries += xretries;
267 sc->debug.stats.n_rcstats[idx].retries += retries;
Sujith9e712792009-02-20 15:13:20 +0530268 sc->debug.stats.n_rcstats[idx].per = per;
Sujith029bc432009-02-04 08:10:26 +0530269 }
270}
271
Sujith7a7dec62009-01-30 14:32:09 +0530272static ssize_t ath_read_file_stat_11n_rc(struct file *file,
273 char __user *user_buf,
274 size_t count, loff_t *ppos)
275{
276 struct ath_softc *sc = file->private_data;
Sujith029bc432009-02-04 08:10:26 +0530277 char buf[1024];
Sujith7a7dec62009-01-30 14:32:09 +0530278 unsigned int len = 0;
279 int i = 0;
280
Sujith9e712792009-02-20 15:13:20 +0530281 len += sprintf(buf, "%7s %13s %8s %8s %6s\n\n", "Rate", "Success",
282 "Retries", "XRetries", "PER");
Sujith7a7dec62009-01-30 14:32:09 +0530283
284 for (i = 0; i <= 15; i++) {
285 len += snprintf(buf + len, sizeof(buf) - len,
Sujith9e712792009-02-20 15:13:20 +0530286 "%5s%3d: %8u %8u %8u %8u\n", "MCS", i,
Sujith17d79042009-02-09 13:27:03 +0530287 sc->debug.stats.n_rcstats[i].success,
288 sc->debug.stats.n_rcstats[i].retries,
Sujith9e712792009-02-20 15:13:20 +0530289 sc->debug.stats.n_rcstats[i].xretries,
290 sc->debug.stats.n_rcstats[i].per);
Sujith7a7dec62009-01-30 14:32:09 +0530291 }
292
293 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
294}
295
296static ssize_t ath_read_file_stat_legacy_rc(struct file *file,
297 char __user *user_buf,
298 size_t count, loff_t *ppos)
299{
300 struct ath_softc *sc = file->private_data;
301 char buf[512];
302 unsigned int len = 0;
303 int i = 0;
304
305 len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success");
306
307 for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
308 len += snprintf(buf + len, sizeof(buf) - len, "%5u: %12u\n",
309 sc->cur_rate_table->info[i].ratekbps / 1000,
Sujith17d79042009-02-09 13:27:03 +0530310 sc->debug.stats.legacy_rcstats[i].success);
Sujith7a7dec62009-01-30 14:32:09 +0530311 }
312
313 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
314}
315
316static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
317 size_t count, loff_t *ppos)
318{
319 struct ath_softc *sc = file->private_data;
320
321 if (conf_is_ht(&sc->hw->conf))
322 return ath_read_file_stat_11n_rc(file, user_buf, count, ppos);
323 else
324 return ath_read_file_stat_legacy_rc(file, user_buf, count ,ppos);
325}
326
327static const struct file_operations fops_rcstat = {
328 .read = read_file_rcstat,
329 .open = ath9k_debugfs_open,
330 .owner = THIS_MODULE
331};
Alina Friedrichsen27abe062009-01-23 05:44:21 +0100332
Jouni Malinen39d89cd2009-03-03 19:23:40 +0200333static 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
350static 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
387static 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
400static 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
408static 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
416static 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
424static 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
432static 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
438static 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
482static 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
Sujith826d2682008-11-28 22:20:23 +0530490int ath9k_init_debug(struct ath_softc *sc)
Sujith88b126a2008-11-28 22:19:02 +0530491{
Sujith17d79042009-02-09 13:27:03 +0530492 sc->debug.debug_mask = ath9k_debug;
Sujith826d2682008-11-28 22:20:23 +0530493
Sujith17d79042009-02-09 13:27:03 +0530494 sc->debug.debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
495 if (!sc->debug.debugfs_root)
Sujith826d2682008-11-28 22:20:23 +0530496 goto err;
497
Sujith17d79042009-02-09 13:27:03 +0530498 sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
499 sc->debug.debugfs_root);
500 if (!sc->debug.debugfs_phy)
Sujith826d2682008-11-28 22:20:23 +0530501 goto err;
502
Sujith17d79042009-02-09 13:27:03 +0530503 sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO,
504 sc->debug.debugfs_phy, sc, &fops_dma);
505 if (!sc->debug.debugfs_dma)
Sujith2a163c62008-11-28 22:21:08 +0530506 goto err;
507
Sujith17d79042009-02-09 13:27:03 +0530508 sc->debug.debugfs_interrupt = debugfs_create_file("interrupt",
Sujith817e11d2008-12-07 21:42:44 +0530509 S_IRUGO,
Sujith17d79042009-02-09 13:27:03 +0530510 sc->debug.debugfs_phy,
Sujith817e11d2008-12-07 21:42:44 +0530511 sc, &fops_interrupt);
Sujith17d79042009-02-09 13:27:03 +0530512 if (!sc->debug.debugfs_interrupt)
Sujith817e11d2008-12-07 21:42:44 +0530513 goto err;
514
Sujith17d79042009-02-09 13:27:03 +0530515 sc->debug.debugfs_rcstat = debugfs_create_file("rcstat",
Sujith7a7dec62009-01-30 14:32:09 +0530516 S_IRUGO,
Sujith17d79042009-02-09 13:27:03 +0530517 sc->debug.debugfs_phy,
Sujith7a7dec62009-01-30 14:32:09 +0530518 sc, &fops_rcstat);
Sujith17d79042009-02-09 13:27:03 +0530519 if (!sc->debug.debugfs_rcstat)
Sujith7a7dec62009-01-30 14:32:09 +0530520 goto err;
521
Jouni Malinen39d89cd2009-03-03 19:23:40 +0200522 sc->debug.debugfs_wiphy = debugfs_create_file(
523 "wiphy", S_IRUGO | S_IWUSR, sc->debug.debugfs_phy, sc,
524 &fops_wiphy);
525 if (!sc->debug.debugfs_wiphy)
526 goto err;
527
Sujith826d2682008-11-28 22:20:23 +0530528 return 0;
529err:
530 ath9k_exit_debug(sc);
531 return -ENOMEM;
532}
533
534void ath9k_exit_debug(struct ath_softc *sc)
535{
Jouni Malinen39d89cd2009-03-03 19:23:40 +0200536 debugfs_remove(sc->debug.debugfs_wiphy);
Sujith17d79042009-02-09 13:27:03 +0530537 debugfs_remove(sc->debug.debugfs_rcstat);
538 debugfs_remove(sc->debug.debugfs_interrupt);
539 debugfs_remove(sc->debug.debugfs_dma);
540 debugfs_remove(sc->debug.debugfs_phy);
541 debugfs_remove(sc->debug.debugfs_root);
Sujith88b126a2008-11-28 22:19:02 +0530542}