diff options
Diffstat (limited to 'drivers/net/wireless/ath5k/debug.c')
-rw-r--r-- | drivers/net/wireless/ath5k/debug.c | 469 |
1 files changed, 469 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c new file mode 100644 index 000000000000..4ba649e20269 --- /dev/null +++ b/drivers/net/wireless/ath5k/debug.c | |||
@@ -0,0 +1,469 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com> | ||
3 | * | ||
4 | * This file is free software: you may copy, redistribute and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation, either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | * | ||
9 | * This file is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | * | ||
18 | * This file incorporates work covered by the following copyright and | ||
19 | * permission notice: | ||
20 | * | ||
21 | * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting | ||
22 | * Copyright (c) 2004-2005 Atheros Communications, Inc. | ||
23 | * Copyright (c) 2006 Devicescape Software, Inc. | ||
24 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
25 | * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> | ||
26 | * | ||
27 | * All rights reserved. | ||
28 | * | ||
29 | * Redistribution and use in source and binary forms, with or without | ||
30 | * modification, are permitted provided that the following conditions | ||
31 | * are met: | ||
32 | * 1. Redistributions of source code must retain the above copyright | ||
33 | * notice, this list of conditions and the following disclaimer, | ||
34 | * without modification. | ||
35 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
36 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
37 | * redistribution must be conditioned upon including a substantially | ||
38 | * similar Disclaimer requirement for further binary redistribution. | ||
39 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
40 | * of any contributors may be used to endorse or promote products derived | ||
41 | * from this software without specific prior written permission. | ||
42 | * | ||
43 | * Alternatively, this software may be distributed under the terms of the | ||
44 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
45 | * Software Foundation. | ||
46 | * | ||
47 | * NO WARRANTY | ||
48 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
49 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
50 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
51 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
52 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
53 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
54 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
55 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
56 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
58 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
59 | */ | ||
60 | |||
61 | #include "debug.h" | ||
62 | #include "base.h" | ||
63 | |||
64 | static unsigned int ath5k_debug; | ||
65 | module_param_named(debug, ath5k_debug, uint, 0); | ||
66 | |||
67 | |||
68 | #if ATH5K_DEBUG | ||
69 | |||
70 | #include <linux/seq_file.h> | ||
71 | #include "reg.h" | ||
72 | |||
73 | static struct dentry *ath5k_global_debugfs; | ||
74 | |||
75 | static int ath5k_debugfs_open(struct inode *inode, struct file *file) | ||
76 | { | ||
77 | file->private_data = inode->i_private; | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | |||
82 | /* debugfs: registers */ | ||
83 | |||
84 | struct reg { | ||
85 | char *name; | ||
86 | int addr; | ||
87 | }; | ||
88 | |||
89 | #define REG_STRUCT_INIT(r) { #r, r } | ||
90 | |||
91 | /* just a few random registers, might want to add more */ | ||
92 | static struct reg regs[] = { | ||
93 | REG_STRUCT_INIT(AR5K_CR), | ||
94 | REG_STRUCT_INIT(AR5K_RXDP), | ||
95 | REG_STRUCT_INIT(AR5K_CFG), | ||
96 | REG_STRUCT_INIT(AR5K_IER), | ||
97 | REG_STRUCT_INIT(AR5K_BCR), | ||
98 | REG_STRUCT_INIT(AR5K_RTSD0), | ||
99 | REG_STRUCT_INIT(AR5K_RTSD1), | ||
100 | REG_STRUCT_INIT(AR5K_TXCFG), | ||
101 | REG_STRUCT_INIT(AR5K_RXCFG), | ||
102 | REG_STRUCT_INIT(AR5K_RXJLA), | ||
103 | REG_STRUCT_INIT(AR5K_MIBC), | ||
104 | REG_STRUCT_INIT(AR5K_TOPS), | ||
105 | REG_STRUCT_INIT(AR5K_RXNOFRM), | ||
106 | REG_STRUCT_INIT(AR5K_TXNOFRM), | ||
107 | REG_STRUCT_INIT(AR5K_RPGTO), | ||
108 | REG_STRUCT_INIT(AR5K_RFCNT), | ||
109 | REG_STRUCT_INIT(AR5K_MISC), | ||
110 | REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT), | ||
111 | REG_STRUCT_INIT(AR5K_ISR), | ||
112 | REG_STRUCT_INIT(AR5K_PISR), | ||
113 | REG_STRUCT_INIT(AR5K_SISR0), | ||
114 | REG_STRUCT_INIT(AR5K_SISR1), | ||
115 | REG_STRUCT_INIT(AR5K_SISR2), | ||
116 | REG_STRUCT_INIT(AR5K_SISR3), | ||
117 | REG_STRUCT_INIT(AR5K_SISR4), | ||
118 | REG_STRUCT_INIT(AR5K_IMR), | ||
119 | REG_STRUCT_INIT(AR5K_PIMR), | ||
120 | REG_STRUCT_INIT(AR5K_SIMR0), | ||
121 | REG_STRUCT_INIT(AR5K_SIMR1), | ||
122 | REG_STRUCT_INIT(AR5K_SIMR2), | ||
123 | REG_STRUCT_INIT(AR5K_SIMR3), | ||
124 | REG_STRUCT_INIT(AR5K_SIMR4), | ||
125 | REG_STRUCT_INIT(AR5K_DCM_ADDR), | ||
126 | REG_STRUCT_INIT(AR5K_DCCFG), | ||
127 | REG_STRUCT_INIT(AR5K_CCFG), | ||
128 | REG_STRUCT_INIT(AR5K_CPC0), | ||
129 | REG_STRUCT_INIT(AR5K_CPC1), | ||
130 | REG_STRUCT_INIT(AR5K_CPC2), | ||
131 | REG_STRUCT_INIT(AR5K_CPC3), | ||
132 | REG_STRUCT_INIT(AR5K_CPCORN), | ||
133 | REG_STRUCT_INIT(AR5K_RESET_CTL), | ||
134 | REG_STRUCT_INIT(AR5K_SLEEP_CTL), | ||
135 | REG_STRUCT_INIT(AR5K_INTPEND), | ||
136 | REG_STRUCT_INIT(AR5K_SFR), | ||
137 | REG_STRUCT_INIT(AR5K_PCICFG), | ||
138 | REG_STRUCT_INIT(AR5K_GPIOCR), | ||
139 | REG_STRUCT_INIT(AR5K_GPIODO), | ||
140 | REG_STRUCT_INIT(AR5K_SREV), | ||
141 | }; | ||
142 | |||
143 | static void *reg_start(struct seq_file *seq, loff_t *pos) | ||
144 | { | ||
145 | return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL; | ||
146 | } | ||
147 | |||
148 | static void reg_stop(struct seq_file *seq, void *p) | ||
149 | { | ||
150 | /* nothing to do */ | ||
151 | } | ||
152 | |||
153 | static void *reg_next(struct seq_file *seq, void *p, loff_t *pos) | ||
154 | { | ||
155 | ++*pos; | ||
156 | return *pos < ARRAY_SIZE(regs) ? ®s[*pos] : NULL; | ||
157 | } | ||
158 | |||
159 | static int reg_show(struct seq_file *seq, void *p) | ||
160 | { | ||
161 | struct ath5k_softc *sc = seq->private; | ||
162 | struct reg *r = p; | ||
163 | seq_printf(seq, "%-25s0x%08x\n", r->name, | ||
164 | ath5k_hw_reg_read(sc->ah, r->addr)); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static struct seq_operations register_seq_ops = { | ||
169 | .start = reg_start, | ||
170 | .next = reg_next, | ||
171 | .stop = reg_stop, | ||
172 | .show = reg_show | ||
173 | }; | ||
174 | |||
175 | static int open_file_registers(struct inode *inode, struct file *file) | ||
176 | { | ||
177 | struct seq_file *s; | ||
178 | int res; | ||
179 | res = seq_open(file, ®ister_seq_ops); | ||
180 | if (res == 0) { | ||
181 | s = file->private_data; | ||
182 | s->private = inode->i_private; | ||
183 | } | ||
184 | return res; | ||
185 | } | ||
186 | |||
187 | static const struct file_operations fops_registers = { | ||
188 | .open = open_file_registers, | ||
189 | .read = seq_read, | ||
190 | .llseek = seq_lseek, | ||
191 | .release = seq_release, | ||
192 | .owner = THIS_MODULE, | ||
193 | }; | ||
194 | |||
195 | |||
196 | /* debugfs: TSF */ | ||
197 | |||
198 | static ssize_t read_file_tsf(struct file *file, char __user *user_buf, | ||
199 | size_t count, loff_t *ppos) | ||
200 | { | ||
201 | struct ath5k_softc *sc = file->private_data; | ||
202 | char buf[100]; | ||
203 | snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); | ||
204 | return simple_read_from_buffer(user_buf, count, ppos, buf, 19); | ||
205 | } | ||
206 | |||
207 | static ssize_t write_file_tsf(struct file *file, | ||
208 | const char __user *userbuf, | ||
209 | size_t count, loff_t *ppos) | ||
210 | { | ||
211 | struct ath5k_softc *sc = file->private_data; | ||
212 | if (strncmp(userbuf, "reset", 5) == 0) { | ||
213 | ath5k_hw_reset_tsf(sc->ah); | ||
214 | printk(KERN_INFO "debugfs reset TSF\n"); | ||
215 | } | ||
216 | return count; | ||
217 | } | ||
218 | |||
219 | static const struct file_operations fops_tsf = { | ||
220 | .read = read_file_tsf, | ||
221 | .write = write_file_tsf, | ||
222 | .open = ath5k_debugfs_open, | ||
223 | .owner = THIS_MODULE, | ||
224 | }; | ||
225 | |||
226 | |||
227 | /* debugfs: beacons */ | ||
228 | |||
229 | static ssize_t read_file_beacon(struct file *file, char __user *user_buf, | ||
230 | size_t count, loff_t *ppos) | ||
231 | { | ||
232 | struct ath5k_softc *sc = file->private_data; | ||
233 | struct ath5k_hw *ah = sc->ah; | ||
234 | char buf[1000]; | ||
235 | int len = 0; | ||
236 | unsigned int v; | ||
237 | u64 tsf; | ||
238 | |||
239 | v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON); | ||
240 | len += snprintf(buf+len, sizeof(buf)-len, | ||
241 | "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n", | ||
242 | "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD, | ||
243 | (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S); | ||
244 | |||
245 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n", | ||
246 | "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP)); | ||
247 | |||
248 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n", | ||
249 | "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT)); | ||
250 | |||
251 | v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0); | ||
252 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", | ||
253 | "AR5K_TIMER0 (TBTT)", v, v); | ||
254 | |||
255 | v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1); | ||
256 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", | ||
257 | "AR5K_TIMER1 (DMA)", v, v >> 3); | ||
258 | |||
259 | v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2); | ||
260 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", | ||
261 | "AR5K_TIMER2 (SWBA)", v, v >> 3); | ||
262 | |||
263 | v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3); | ||
264 | len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", | ||
265 | "AR5K_TIMER3 (ATIM)", v, v); | ||
266 | |||
267 | tsf = ath5k_hw_get_tsf64(sc->ah); | ||
268 | len += snprintf(buf+len, sizeof(buf)-len, | ||
269 | "TSF\t\t0x%016llx\tTU: %08x\n", tsf, TSF_TO_TU(tsf)); | ||
270 | |||
271 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
272 | } | ||
273 | |||
274 | static ssize_t write_file_beacon(struct file *file, | ||
275 | const char __user *userbuf, | ||
276 | size_t count, loff_t *ppos) | ||
277 | { | ||
278 | struct ath5k_softc *sc = file->private_data; | ||
279 | struct ath5k_hw *ah = sc->ah; | ||
280 | |||
281 | if (strncmp(userbuf, "disable", 7) == 0) { | ||
282 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); | ||
283 | printk(KERN_INFO "debugfs disable beacons\n"); | ||
284 | } else if (strncmp(userbuf, "enable", 6) == 0) { | ||
285 | AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); | ||
286 | printk(KERN_INFO "debugfs enable beacons\n"); | ||
287 | } | ||
288 | return count; | ||
289 | } | ||
290 | |||
291 | static const struct file_operations fops_beacon = { | ||
292 | .read = read_file_beacon, | ||
293 | .write = write_file_beacon, | ||
294 | .open = ath5k_debugfs_open, | ||
295 | .owner = THIS_MODULE, | ||
296 | }; | ||
297 | |||
298 | |||
299 | /* debugfs: reset */ | ||
300 | |||
301 | static ssize_t write_file_reset(struct file *file, | ||
302 | const char __user *userbuf, | ||
303 | size_t count, loff_t *ppos) | ||
304 | { | ||
305 | struct ath5k_softc *sc = file->private_data; | ||
306 | tasklet_schedule(&sc->restq); | ||
307 | return count; | ||
308 | } | ||
309 | |||
310 | static const struct file_operations fops_reset = { | ||
311 | .write = write_file_reset, | ||
312 | .open = ath5k_debugfs_open, | ||
313 | .owner = THIS_MODULE, | ||
314 | }; | ||
315 | |||
316 | |||
317 | /* init */ | ||
318 | |||
319 | void | ||
320 | ath5k_debug_init(void) | ||
321 | { | ||
322 | ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL); | ||
323 | } | ||
324 | |||
325 | void | ||
326 | ath5k_debug_init_device(struct ath5k_softc *sc) | ||
327 | { | ||
328 | sc->debug.level = ath5k_debug; | ||
329 | sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), | ||
330 | ath5k_global_debugfs); | ||
331 | sc->debug.debugfs_debug = debugfs_create_u32("debug", | ||
332 | 0666, sc->debug.debugfs_phydir, &sc->debug.level); | ||
333 | |||
334 | sc->debug.debugfs_registers = debugfs_create_file("registers", 0444, | ||
335 | sc->debug.debugfs_phydir, | ||
336 | sc, &fops_registers); | ||
337 | |||
338 | sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666, | ||
339 | sc->debug.debugfs_phydir, | ||
340 | sc, &fops_tsf); | ||
341 | |||
342 | sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666, | ||
343 | sc->debug.debugfs_phydir, | ||
344 | sc, &fops_beacon); | ||
345 | |||
346 | sc->debug.debugfs_reset = debugfs_create_file("reset", 0222, | ||
347 | sc->debug.debugfs_phydir, | ||
348 | sc, &fops_reset); | ||
349 | } | ||
350 | |||
351 | void | ||
352 | ath5k_debug_finish(void) | ||
353 | { | ||
354 | debugfs_remove(ath5k_global_debugfs); | ||
355 | } | ||
356 | |||
357 | void | ||
358 | ath5k_debug_finish_device(struct ath5k_softc *sc) | ||
359 | { | ||
360 | debugfs_remove(sc->debug.debugfs_debug); | ||
361 | debugfs_remove(sc->debug.debugfs_registers); | ||
362 | debugfs_remove(sc->debug.debugfs_tsf); | ||
363 | debugfs_remove(sc->debug.debugfs_beacon); | ||
364 | debugfs_remove(sc->debug.debugfs_reset); | ||
365 | debugfs_remove(sc->debug.debugfs_phydir); | ||
366 | } | ||
367 | |||
368 | |||
369 | /* functions used in other places */ | ||
370 | |||
371 | void | ||
372 | ath5k_debug_dump_modes(struct ath5k_softc *sc, struct ieee80211_hw_mode *modes) | ||
373 | { | ||
374 | unsigned int m, i; | ||
375 | |||
376 | if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPMODES))) | ||
377 | return; | ||
378 | |||
379 | for (m = 0; m < NUM_DRIVER_MODES; m++) { | ||
380 | printk(KERN_DEBUG "Mode %u: channels %d, rates %d\n", m, | ||
381 | modes[m].num_channels, modes[m].num_rates); | ||
382 | printk(KERN_DEBUG " channels:\n"); | ||
383 | for (i = 0; i < modes[m].num_channels; i++) | ||
384 | printk(KERN_DEBUG " %3d %d %.4x %.4x\n", | ||
385 | modes[m].channels[i].chan, | ||
386 | modes[m].channels[i].freq, | ||
387 | modes[m].channels[i].val, | ||
388 | modes[m].channels[i].flag); | ||
389 | printk(KERN_DEBUG " rates:\n"); | ||
390 | for (i = 0; i < modes[m].num_rates; i++) | ||
391 | printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n", | ||
392 | modes[m].rates[i].rate, | ||
393 | modes[m].rates[i].val, | ||
394 | modes[m].rates[i].flags, | ||
395 | modes[m].rates[i].val2); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | static inline void | ||
400 | ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done) | ||
401 | { | ||
402 | struct ath5k_desc *ds = bf->desc; | ||
403 | |||
404 | printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n", | ||
405 | ds, (unsigned long long)bf->daddr, | ||
406 | ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1, | ||
407 | ds->ds_hw[0], ds->ds_hw[1], | ||
408 | !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!'); | ||
409 | } | ||
410 | |||
411 | void | ||
412 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | ||
413 | { | ||
414 | struct ath5k_desc *ds; | ||
415 | struct ath5k_buf *bf; | ||
416 | int status; | ||
417 | |||
418 | if (likely(!(sc->debug.level & | ||
419 | (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL)))) | ||
420 | return; | ||
421 | |||
422 | printk(KERN_DEBUG "rx queue %x, link %p\n", | ||
423 | ath5k_hw_get_rx_buf(ah), sc->rxlink); | ||
424 | |||
425 | spin_lock_bh(&sc->rxbuflock); | ||
426 | list_for_each_entry(bf, &sc->rxbuf, list) { | ||
427 | ds = bf->desc; | ||
428 | status = ah->ah_proc_rx_desc(ah, ds); | ||
429 | if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL)) | ||
430 | ath5k_debug_printrxbuf(bf, status == 0); | ||
431 | } | ||
432 | spin_unlock_bh(&sc->rxbuflock); | ||
433 | } | ||
434 | |||
435 | void | ||
436 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
437 | struct sk_buff *skb, const char *prefix, int tx) | ||
438 | { | ||
439 | char buf[16]; | ||
440 | |||
441 | if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) || | ||
442 | (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX))))) | ||
443 | return; | ||
444 | |||
445 | snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix); | ||
446 | |||
447 | print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data, | ||
448 | min(200U, skb->len)); | ||
449 | |||
450 | printk(KERN_DEBUG "\n"); | ||
451 | } | ||
452 | |||
453 | void | ||
454 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, | ||
455 | struct ath5k_buf *bf, int done) | ||
456 | { | ||
457 | struct ath5k_desc *ds = bf->desc; | ||
458 | |||
459 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) | ||
460 | return; | ||
461 | |||
462 | printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " | ||
463 | "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, | ||
464 | ds->ds_data, ds->ds_ctl0, ds->ds_ctl1, | ||
465 | ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3], | ||
466 | !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!'); | ||
467 | } | ||
468 | |||
469 | #endif /* if ATH5K_DEBUG */ | ||