]> Pileus Git - ~andy/linux/blob - drivers/net/wireless/rt2x00/rt2x00debug.c
e72c98133c05b94f7d08208f2f91bd1944d44d5f
[~andy/linux] / drivers / net / wireless / rt2x00 / rt2x00debug.c
1 /*
2         Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
3         <http://rt2x00.serialmonkey.com>
4
5         This program is free software; you can redistribute it and/or modify
6         it under the terms of the GNU General Public License as published by
7         the Free Software Foundation; either version 2 of the License, or
8         (at your option) any later version.
9
10         This program is distributed in the hope that it will be useful,
11         but WITHOUT ANY WARRANTY; without even the implied warranty of
12         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13         GNU General Public License for more details.
14
15         You should have received a copy of the GNU General Public License
16         along with this program; if not, write to the
17         Free Software Foundation, Inc.,
18         59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 /*
22         Module: rt2x00lib
23         Abstract: rt2x00 debugfs specific routines.
24  */
25
26 #include <linux/debugfs.h>
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/poll.h>
30 #include <linux/uaccess.h>
31
32 #include "rt2x00.h"
33 #include "rt2x00lib.h"
34 #include "rt2x00dump.h"
35
36 #define PRINT_LINE_LEN_MAX 32
37
38 struct rt2x00debug_intf {
39         /*
40          * Pointer to driver structure where
41          * this debugfs entry belongs to.
42          */
43         struct rt2x00_dev *rt2x00dev;
44
45         /*
46          * Reference to the rt2x00debug structure
47          * which can be used to communicate with
48          * the registers.
49          */
50         const struct rt2x00debug *debug;
51
52         /*
53          * Debugfs entries for:
54          * - driver folder
55          *   - driver file
56          *   - chipset file
57          *   - device flags file
58          *   - register folder
59          *     - csr offset/value files
60          *     - eeprom offset/value files
61          *     - bbp offset/value files
62          *     - rf offset/value files
63          *   - frame dump folder
64          *     - frame dump file
65          */
66         struct dentry *driver_folder;
67         struct dentry *driver_entry;
68         struct dentry *chipset_entry;
69         struct dentry *dev_flags;
70         struct dentry *register_folder;
71         struct dentry *csr_off_entry;
72         struct dentry *csr_val_entry;
73         struct dentry *eeprom_off_entry;
74         struct dentry *eeprom_val_entry;
75         struct dentry *bbp_off_entry;
76         struct dentry *bbp_val_entry;
77         struct dentry *rf_off_entry;
78         struct dentry *rf_val_entry;
79         struct dentry *frame_folder;
80         struct dentry *frame_dump_entry;
81
82         /*
83          * The frame dump file only allows a single reader,
84          * so we need to store the current state here.
85          */
86         unsigned long frame_dump_flags;
87 #define FRAME_DUMP_FILE_OPEN    1
88
89         /*
90          * We queue each frame before dumping it to the user,
91          * per read command we will pass a single skb structure
92          * so we should be prepared to queue multiple sk buffers
93          * before sending it to userspace.
94          */
95         struct sk_buff_head frame_dump_skbqueue;
96         wait_queue_head_t frame_dump_waitqueue;
97
98         /*
99          * Driver and chipset files will use a data buffer
100          * that has been created in advance. This will simplify
101          * the code since we can use the debugfs functions.
102          */
103         struct debugfs_blob_wrapper driver_blob;
104         struct debugfs_blob_wrapper chipset_blob;
105
106         /*
107          * Requested offset for each register type.
108          */
109         unsigned int offset_csr;
110         unsigned int offset_eeprom;
111         unsigned int offset_bbp;
112         unsigned int offset_rf;
113 };
114
115 void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
116                             struct sk_buff *skb)
117 {
118         struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
119         struct skb_desc *desc = get_skb_desc(skb);
120         struct sk_buff *skbcopy;
121         struct rt2x00dump_hdr *dump_hdr;
122         struct timeval timestamp;
123         unsigned int ring_index;
124         unsigned int entry_index;
125
126         do_gettimeofday(&timestamp);
127         ring_index = ARRAY_INDEX(desc->ring, rt2x00dev->rx);
128         entry_index = ARRAY_INDEX(desc->entry, desc->ring->entry);
129
130         if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
131                 return;
132
133         if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
134                 DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
135                 return;
136         }
137
138         skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + desc->data_len,
139                             GFP_ATOMIC);
140         if (!skbcopy) {
141                 DEBUG(rt2x00dev, "Failed to copy skb for dump.\n");
142                 return;
143         }
144
145         dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
146         dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
147         dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
148         dump_hdr->desc_length = cpu_to_le32(desc->desc_len);
149         dump_hdr->data_length = cpu_to_le32(desc->data_len);
150         dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
151         dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
152         dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
153         dump_hdr->type = cpu_to_le16(desc->frame_type);
154         dump_hdr->ring_index = ring_index;
155         dump_hdr->entry_index = entry_index;
156         dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
157         dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
158
159         memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len);
160         memcpy(skb_put(skbcopy, desc->data_len), desc->data, desc->data_len);
161
162         skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
163         wake_up_interruptible(&intf->frame_dump_waitqueue);
164
165         /*
166          * Verify that the file has not been closed while we were working.
167          */
168         if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
169                 skb_queue_purge(&intf->frame_dump_skbqueue);
170 }
171
172 static int rt2x00debug_file_open(struct inode *inode, struct file *file)
173 {
174         struct rt2x00debug_intf *intf = inode->i_private;
175
176         file->private_data = inode->i_private;
177
178         if (!try_module_get(intf->debug->owner))
179                 return -EBUSY;
180
181         return 0;
182 }
183
184 static int rt2x00debug_file_release(struct inode *inode, struct file *file)
185 {
186         struct rt2x00debug_intf *intf = file->private_data;
187
188         module_put(intf->debug->owner);
189
190         return 0;
191 }
192
193 static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
194 {
195         struct rt2x00debug_intf *intf = inode->i_private;
196         int retval;
197
198         retval = rt2x00debug_file_open(inode, file);
199         if (retval)
200                 return retval;
201
202         if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
203                 rt2x00debug_file_release(inode, file);
204                 return -EBUSY;
205         }
206
207         return 0;
208 }
209
210 static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
211 {
212         struct rt2x00debug_intf *intf = inode->i_private;
213
214         skb_queue_purge(&intf->frame_dump_skbqueue);
215
216         clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
217
218         return rt2x00debug_file_release(inode, file);
219 }
220
221 static ssize_t rt2x00debug_read_ring_dump(struct file *file,
222                                           char __user *buf,
223                                           size_t length,
224                                           loff_t *offset)
225 {
226         struct rt2x00debug_intf *intf = file->private_data;
227         struct sk_buff *skb;
228         size_t status;
229         int retval;
230
231         if (file->f_flags & O_NONBLOCK)
232                 return -EAGAIN;
233
234         retval =
235             wait_event_interruptible(intf->frame_dump_waitqueue,
236                                      (skb =
237                                      skb_dequeue(&intf->frame_dump_skbqueue)));
238         if (retval)
239                 return retval;
240
241         status = min((size_t)skb->len, length);
242         if (copy_to_user(buf, skb->data, status)) {
243                 status = -EFAULT;
244                 goto exit;
245         }
246
247         *offset += status;
248
249 exit:
250         kfree_skb(skb);
251
252         return status;
253 }
254
255 static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
256                                                poll_table *wait)
257 {
258         struct rt2x00debug_intf *intf = file->private_data;
259
260         poll_wait(file, &intf->frame_dump_waitqueue, wait);
261
262         if (!skb_queue_empty(&intf->frame_dump_skbqueue))
263                 return POLLOUT | POLLWRNORM;
264
265         return 0;
266 }
267
268 static const struct file_operations rt2x00debug_fop_ring_dump = {
269         .owner          = THIS_MODULE,
270         .read           = rt2x00debug_read_ring_dump,
271         .poll           = rt2x00debug_poll_ring_dump,
272         .open           = rt2x00debug_open_ring_dump,
273         .release        = rt2x00debug_release_ring_dump,
274 };
275
276 #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)        \
277 static ssize_t rt2x00debug_read_##__name(struct file *file,     \
278                                          char __user *buf,      \
279                                          size_t length,         \
280                                          loff_t *offset)        \
281 {                                                               \
282         struct rt2x00debug_intf *intf = file->private_data;     \
283         const struct rt2x00debug *debug = intf->debug;          \
284         char line[16];                                          \
285         size_t size;                                            \
286         __type value;                                           \
287                                                                 \
288         if (*offset)                                            \
289                 return 0;                                       \
290                                                                 \
291         if (intf->offset_##__name >= debug->__name.word_count)  \
292                 return -EINVAL;                                 \
293                                                                 \
294         debug->__name.read(intf->rt2x00dev,                     \
295                            intf->offset_##__name, &value);      \
296                                                                 \
297         size = sprintf(line, __format, value);                  \
298                                                                 \
299         if (copy_to_user(buf, line, size))                      \
300                 return -EFAULT;                                 \
301                                                                 \
302         *offset += size;                                        \
303         return size;                                            \
304 }
305
306 #define RT2X00DEBUGFS_OPS_WRITE(__name, __type)                 \
307 static ssize_t rt2x00debug_write_##__name(struct file *file,    \
308                                           const char __user *buf,\
309                                           size_t length,        \
310                                           loff_t *offset)       \
311 {                                                               \
312         struct rt2x00debug_intf *intf = file->private_data;     \
313         const struct rt2x00debug *debug = intf->debug;          \
314         char line[16];                                          \
315         size_t size;                                            \
316         __type value;                                           \
317                                                                 \
318         if (*offset)                                            \
319                 return 0;                                       \
320                                                                 \
321         if (!capable(CAP_NET_ADMIN))                            \
322                 return -EPERM;                                  \
323                                                                 \
324         if (intf->offset_##__name >= debug->__name.word_count)  \
325                 return -EINVAL;                                 \
326                                                                 \
327         if (copy_from_user(line, buf, length))                  \
328                 return -EFAULT;                                 \
329                                                                 \
330         size = strlen(line);                                    \
331         value = simple_strtoul(line, NULL, 0);                  \
332                                                                 \
333         debug->__name.write(intf->rt2x00dev,                    \
334                             intf->offset_##__name, value);      \
335                                                                 \
336         *offset += size;                                        \
337         return size;                                            \
338 }
339
340 #define RT2X00DEBUGFS_OPS(__name, __format, __type)             \
341 RT2X00DEBUGFS_OPS_READ(__name, __format, __type);               \
342 RT2X00DEBUGFS_OPS_WRITE(__name, __type);                        \
343                                                                 \
344 static const struct file_operations rt2x00debug_fop_##__name = {\
345         .owner          = THIS_MODULE,                          \
346         .read           = rt2x00debug_read_##__name,            \
347         .write          = rt2x00debug_write_##__name,           \
348         .open           = rt2x00debug_file_open,                \
349         .release        = rt2x00debug_file_release,             \
350 };
351
352 RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
353 RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
354 RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
355 RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
356
357 static ssize_t rt2x00debug_read_dev_flags(struct file *file,
358                                           char __user *buf,
359                                           size_t length,
360                                           loff_t *offset)
361 {
362         struct rt2x00debug_intf *intf = file->private_data;
363         char line[16];
364         size_t size;
365
366         if (*offset)
367                 return 0;
368
369         size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
370
371         if (copy_to_user(buf, line, size))
372                 return -EFAULT;
373
374         *offset += size;
375         return size;
376 }
377
378 static const struct file_operations rt2x00debug_fop_dev_flags = {
379         .owner          = THIS_MODULE,
380         .read           = rt2x00debug_read_dev_flags,
381         .open           = rt2x00debug_file_open,
382         .release        = rt2x00debug_file_release,
383 };
384
385 static struct dentry *rt2x00debug_create_file_driver(const char *name,
386                                                      struct rt2x00debug_intf
387                                                      *intf,
388                                                      struct debugfs_blob_wrapper
389                                                      *blob)
390 {
391         char *data;
392
393         data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
394         if (!data)
395                 return NULL;
396
397         blob->data = data;
398         data += sprintf(data, "driver: %s\n", intf->rt2x00dev->ops->name);
399         data += sprintf(data, "version: %s\n", DRV_VERSION);
400         data += sprintf(data, "compiled: %s %s\n", __DATE__, __TIME__);
401         blob->size = strlen(blob->data);
402
403         return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
404 }
405
406 static struct dentry *rt2x00debug_create_file_chipset(const char *name,
407                                                       struct rt2x00debug_intf
408                                                       *intf,
409                                                       struct
410                                                       debugfs_blob_wrapper
411                                                       *blob)
412 {
413         const struct rt2x00debug *debug = intf->debug;
414         char *data;
415
416         data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
417         if (!data)
418                 return NULL;
419
420         data += sprintf(data, "rt chip: %04x\n", intf->rt2x00dev->chip.rt);
421         data += sprintf(data, "rf chip: %04x\n", intf->rt2x00dev->chip.rf);
422         data += sprintf(data, "revision:%08x\n", intf->rt2x00dev->chip.rev);
423         data += sprintf(data, "\n");
424         data += sprintf(data, "csr length: %d\n", debug->csr.word_count);
425         data += sprintf(data, "eeprom length: %d\n", debug->eeprom.word_count);
426         data += sprintf(data, "bbp length: %d\n", debug->bbp.word_count);
427         data += sprintf(data, "rf length: %d\n", debug->rf.word_count);
428
429         blob->data = data;
430         blob->size = strlen(data);
431
432         return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
433 }
434
435 void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
436 {
437         const struct rt2x00debug *debug = rt2x00dev->ops->debugfs;
438         struct rt2x00debug_intf *intf;
439
440         intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);
441         if (!intf) {
442                 ERROR(rt2x00dev, "Failed to allocate debug handler.\n");
443                 return;
444         }
445
446         intf->debug = debug;
447         intf->rt2x00dev = rt2x00dev;
448         rt2x00dev->debugfs_intf = intf;
449
450         intf->driver_folder =
451             debugfs_create_dir(intf->rt2x00dev->ops->name,
452                                rt2x00dev->hw->wiphy->debugfsdir);
453         if (IS_ERR(intf->driver_folder))
454                 goto exit;
455
456         intf->driver_entry =
457             rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
458         if (IS_ERR(intf->driver_entry))
459                 goto exit;
460
461         intf->chipset_entry =
462             rt2x00debug_create_file_chipset("chipset",
463                                             intf, &intf->chipset_blob);
464         if (IS_ERR(intf->chipset_entry))
465                 goto exit;
466
467         intf->dev_flags = debugfs_create_file("dev_flags", S_IRUGO,
468                                               intf->driver_folder, intf,
469                                               &rt2x00debug_fop_dev_flags);
470         if (IS_ERR(intf->dev_flags))
471                 goto exit;
472
473         intf->register_folder =
474             debugfs_create_dir("register", intf->driver_folder);
475         if (IS_ERR(intf->register_folder))
476                 goto exit;
477
478 #define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name)     \
479 ({                                                              \
480         (__intf)->__name##_off_entry =                          \
481             debugfs_create_u32(__stringify(__name) "_offset",   \
482                                S_IRUGO | S_IWUSR,               \
483                                (__intf)->register_folder,       \
484                                &(__intf)->offset_##__name);     \
485         if (IS_ERR((__intf)->__name##_off_entry))               \
486                 goto exit;                                      \
487                                                                 \
488         (__intf)->__name##_val_entry =                          \
489             debugfs_create_file(__stringify(__name) "_value",   \
490                                 S_IRUGO | S_IWUSR,              \
491                                 (__intf)->register_folder,      \
492                                 (__intf), &rt2x00debug_fop_##__name);\
493         if (IS_ERR((__intf)->__name##_val_entry))               \
494                 goto exit;                                      \
495 })
496
497         RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
498         RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
499         RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
500         RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
501
502 #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
503
504         intf->frame_folder =
505             debugfs_create_dir("frame", intf->driver_folder);
506         if (IS_ERR(intf->frame_folder))
507                 goto exit;
508
509         intf->frame_dump_entry =
510             debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
511                                 intf, &rt2x00debug_fop_ring_dump);
512         if (IS_ERR(intf->frame_dump_entry))
513                 goto exit;
514
515         skb_queue_head_init(&intf->frame_dump_skbqueue);
516         init_waitqueue_head(&intf->frame_dump_waitqueue);
517
518         return;
519
520 exit:
521         rt2x00debug_deregister(rt2x00dev);
522         ERROR(rt2x00dev, "Failed to register debug handler.\n");
523
524         return;
525 }
526
527 void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
528 {
529         struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
530
531         if (unlikely(!intf))
532                 return;
533
534         skb_queue_purge(&intf->frame_dump_skbqueue);
535
536         debugfs_remove(intf->frame_dump_entry);
537         debugfs_remove(intf->frame_folder);
538         debugfs_remove(intf->rf_val_entry);
539         debugfs_remove(intf->rf_off_entry);
540         debugfs_remove(intf->bbp_val_entry);
541         debugfs_remove(intf->bbp_off_entry);
542         debugfs_remove(intf->eeprom_val_entry);
543         debugfs_remove(intf->eeprom_off_entry);
544         debugfs_remove(intf->csr_val_entry);
545         debugfs_remove(intf->csr_off_entry);
546         debugfs_remove(intf->register_folder);
547         debugfs_remove(intf->dev_flags);
548         debugfs_remove(intf->chipset_entry);
549         debugfs_remove(intf->driver_entry);
550         debugfs_remove(intf->driver_folder);
551         kfree(intf->chipset_blob.data);
552         kfree(intf->driver_blob.data);
553         kfree(intf);
554
555         rt2x00dev->debugfs_intf = NULL;
556 }