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