Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 
124         do_gettimeofday(&timestamp);
125 
126         if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
127                 return;
128 
129         if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
130                 DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
131                 return;
132         }
133 
134         skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + desc->data_len,
135                             GFP_ATOMIC);
136         if (!skbcopy) {
137                 DEBUG(rt2x00dev, "Failed to copy skb for dump.\n");
138                 return;
139         }
140 
141         dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
142         dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
143         dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
144         dump_hdr->desc_length = cpu_to_le32(desc->desc_len);
145         dump_hdr->data_length = cpu_to_le32(desc->data_len);
146         dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
147         dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
148         dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
149         dump_hdr->type = cpu_to_le16(desc->frame_type);
150         dump_hdr->ring_index = desc->ring->queue_idx;
151         dump_hdr->entry_index = desc->entry->entry_idx;
152         dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
153         dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
154 
155         memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len);
156         memcpy(skb_put(skbcopy, desc->data_len), desc->data, desc->data_len);
157 
158         skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
159         wake_up_interruptible(&intf->frame_dump_waitqueue);
160 
161         /*
162          * Verify that the file has not been closed while we were working.
163          */
164         if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
165                 skb_queue_purge(&intf->frame_dump_skbqueue);
166 }
167 
168 static int rt2x00debug_file_open(struct inode *inode, struct file *file)
169 {
170         struct rt2x00debug_intf *intf = inode->i_private;
171 
172         file->private_data = inode->i_private;
173 
174         if (!try_module_get(intf->debug->owner))
175                 return -EBUSY;
176 
177         return 0;
178 }
179 
180 static int rt2x00debug_file_release(struct inode *inode, struct file *file)
181 {
182         struct rt2x00debug_intf *intf = file->private_data;
183 
184         module_put(intf->debug->owner);
185 
186         return 0;
187 }
188 
189 static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
190 {
191         struct rt2x00debug_intf *intf = inode->i_private;
192         int retval;
193 
194         retval = rt2x00debug_file_open(inode, file);
195         if (retval)
196                 return retval;
197 
198         if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
199                 rt2x00debug_file_release(inode, file);
200                 return -EBUSY;
201         }
202 
203         return 0;
204 }
205 
206 static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
207 {
208         struct rt2x00debug_intf *intf = inode->i_private;
209 
210         skb_queue_purge(&intf->frame_dump_skbqueue);
211 
212         clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
213 
214         return rt2x00debug_file_release(inode, file);
215 }
216 
217 static ssize_t rt2x00debug_read_ring_dump(struct file *file,
218                                           char __user *buf,
219                                           size_t length,
220                                           loff_t *offset)
221 {
222         struct rt2x00debug_intf *intf = file->private_data;
223         struct sk_buff *skb;
224         size_t status;
225         int retval;
226 
227         if (file->f_flags & O_NONBLOCK)
228                 return -EAGAIN;
229 
230         retval =
231             wait_event_interruptible(intf->frame_dump_waitqueue,
232                                      (skb =
233                                      skb_dequeue(&intf->frame_dump_skbqueue)));
234         if (retval)
235                 return retval;
236 
237         status = min((size_t)skb->len, length);
238         if (copy_to_user(buf, skb->data, status)) {
239                 status = -EFAULT;
240                 goto exit;
241         }
242 
243         *offset += status;
244 
245 exit:
246         kfree_skb(skb);
247 
248         return status;
249 }
250 
251 static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
252                                                poll_table *wait)
253 {
254         struct rt2x00debug_intf *intf = file->private_data;
255 
256         poll_wait(file, &intf->frame_dump_waitqueue, wait);
257 
258         if (!skb_queue_empty(&intf->frame_dump_skbqueue))
259                 return POLLOUT | POLLWRNORM;
260 
261         return 0;
262 }
263 
264 static const struct file_operations rt2x00debug_fop_ring_dump = {
265         .owner          = THIS_MODULE,
266         .read           = rt2x00debug_read_ring_dump,
267         .poll           = rt2x00debug_poll_ring_dump,
268         .open           = rt2x00debug_open_ring_dump,
269         .release        = rt2x00debug_release_ring_dump,
270 };
271 
272 #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)        \
273 static ssize_t rt2x00debug_read_##__name(struct file *file,     \
274                                          char __user *buf,      \
275                                          size_t length,         \
276                                          loff_t *offset)        \
277 {                                                               \
278         struct rt2x00debug_intf *intf = file->private_data;     \
279         const struct rt2x00debug *debug = intf->debug;          \
280         char line[16];                                          \
281         size_t size;                                            \
282         __type value;                                           \
283                                                                 \
284         if (*offset)                                            \
285                 return 0;                                       \
286                                                                 \
287         if (intf->offset_##__name >= debug->__name.word_count)  \
288                 return -EINVAL;                                 \
289                                                                 \
290         debug->__name.read(intf->rt2x00dev,                     \
291                            intf->offset_##__name, &value);      \
292                                                                 \
293         size = sprintf(line, __format, value);                  \
294                                                                 \
295         if (copy_to_user(buf, line, size))                      \
296                 return -EFAULT;                                 \
297                                                                 \
298         *offset += size;                                        \
299         return size;                                            \
300 }
301 
302 #define RT2X00DEBUGFS_OPS_WRITE(__name, __type)                 \
303 static ssize_t rt2x00debug_write_##__name(struct file *file,    \
304                                           const char __user *buf,\
305                                           size_t length,        \
306                                           loff_t *offset)       \
307 {                                                               \
308         struct rt2x00debug_intf *intf = file->private_data;     \
309         const struct rt2x00debug *debug = intf->debug;          \
310         char line[16];                                          \
311         size_t size;                                            \
312         __type value;                                           \
313                                                                 \
314         if (*offset)                                            \
315                 return 0;                                       \
316                                                                 \
317         if (!capable(CAP_NET_ADMIN))                            \
318                 return -EPERM;                                  \
319                                                                 \
320         if (intf->offset_##__name >= debug->__name.word_count)  \
321                 return -EINVAL;                                 \
322                                                                 \
323         if (copy_from_user(line, buf, length))                  \
324                 return -EFAULT;                                 \
325                                                                 \
326         size = strlen(line);                                    \
327         value = simple_strtoul(line, NULL, 0);                  \
328                                                                 \
329         debug->__name.write(intf->rt2x00dev,                    \
330                             intf->offset_##__name, value);      \
331                                                                 \
332         *offset += size;                                        \
333         return size;                                            \
334 }
335 
336 #define RT2X00DEBUGFS_OPS(__name, __format, __type)             \
337 RT2X00DEBUGFS_OPS_READ(__name, __format, __type);               \
338 RT2X00DEBUGFS_OPS_WRITE(__name, __type);                        \
339                                                                 \
340 static const struct file_operations rt2x00debug_fop_##__name = {\
341         .owner          = THIS_MODULE,                          \
342         .read           = rt2x00debug_read_##__name,            \
343         .write          = rt2x00debug_write_##__name,           \
344         .open           = rt2x00debug_file_open,                \
345         .release        = rt2x00debug_file_release,             \
346 };
347 
348 RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
349 RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
350 RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
351 RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
352 
353 static ssize_t rt2x00debug_read_dev_flags(struct file *file,
354                                           char __user *buf,
355                                           size_t length,
356                                           loff_t *offset)
357 {
358         struct rt2x00debug_intf *intf = file->private_data;
359         char line[16];
360         size_t size;
361 
362         if (*offset)
363                 return 0;
364 
365         size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
366 
367         if (copy_to_user(buf, line, size))
368                 return -EFAULT;
369 
370         *offset += size;
371         return size;
372 }
373 
374 static const struct file_operations rt2x00debug_fop_dev_flags = {
375         .owner          = THIS_MODULE,
376         .read           = rt2x00debug_read_dev_flags,
377         .open           = rt2x00debug_file_open,
378         .release        = rt2x00debug_file_release,
379 };
380 
381 static struct dentry *rt2x00debug_create_file_driver(const char *name,
382                                                      struct rt2x00debug_intf
383                                                      *intf,
384                                                      struct debugfs_blob_wrapper
385                                                      *blob)
386 {
387         char *data;
388 
389         data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
390         if (!data)
391                 return NULL;
392 
393         blob->data = data;
394         data += sprintf(data, "driver: %s\n", intf->rt2x00dev->ops->name);
395         data += sprintf(data, "version: %s\n", DRV_VERSION);
396         data += sprintf(data, "compiled: %s %s\n", __DATE__, __TIME__);
397         blob->size = strlen(blob->data);
398 
399         return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
400 }
401 
402 static struct dentry *rt2x00debug_create_file_chipset(const char *name,
403                                                       struct rt2x00debug_intf
404                                                       *intf,
405                                                       struct
406                                                       debugfs_blob_wrapper
407                                                       *blob)
408 {
409         const struct rt2x00debug *debug = intf->debug;
410         char *data;
411 
412         data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
413         if (!data)
414                 return NULL;
415 
416         blob->data = data;
417         data += sprintf(data, "rt chip: %04x\n", intf->rt2x00dev->chip.rt);
418         data += sprintf(data, "rf chip: %04x\n", intf->rt2x00dev->chip.rf);
419         data += sprintf(data, "revision:%08x\n", intf->rt2x00dev->chip.rev);
420         data += sprintf(data, "\n");
421         data += sprintf(data, "csr length: %d\n", debug->csr.word_count);
422         data += sprintf(data, "eeprom length: %d\n", debug->eeprom.word_count);
423         data += sprintf(data, "bbp length: %d\n", debug->bbp.word_count);
424         data += sprintf(data, "rf length: %d\n", debug->rf.word_count);
425         blob->size = strlen(blob->data);
426 
427         return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
428 }
429 
430 void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
431 {
432         const struct rt2x00debug *debug = rt2x00dev->ops->debugfs;
433         struct rt2x00debug_intf *intf;
434 
435         intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);
436         if (!intf) {
437                 ERROR(rt2x00dev, "Failed to allocate debug handler.\n");
438                 return;
439         }
440 
441         intf->debug = debug;
442         intf->rt2x00dev = rt2x00dev;
443         rt2x00dev->debugfs_intf = intf;
444 
445         intf->driver_folder =
446             debugfs_create_dir(intf->rt2x00dev->ops->name,
447                                rt2x00dev->hw->wiphy->debugfsdir);
448         if (IS_ERR(intf->driver_folder))
449                 goto exit;
450 
451         intf->driver_entry =
452             rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
453         if (IS_ERR(intf->driver_entry))
454                 goto exit;
455 
456         intf->chipset_entry =
457             rt2x00debug_create_file_chipset("chipset",
458                                             intf, &intf->chipset_blob);
459         if (IS_ERR(intf->chipset_entry))
460                 goto exit;
461 
462         intf->dev_flags = debugfs_create_file("dev_flags", S_IRUGO,
463                                               intf->driver_folder, intf,
464                                               &rt2x00debug_fop_dev_flags);
465         if (IS_ERR(intf->dev_flags))
466                 goto exit;
467 
468         intf->register_folder =
469             debugfs_create_dir("register", intf->driver_folder);
470         if (IS_ERR(intf->register_folder))
471                 goto exit;
472 
473 #define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name)     \
474 ({                                                              \
475         (__intf)->__name##_off_entry =                          \
476             debugfs_create_u32(__stringify(__name) "_offset",   \
477                                S_IRUGO | S_IWUSR,               \
478                                (__intf)->register_folder,       \
479                                &(__intf)->offset_##__name);     \
480         if (IS_ERR((__intf)->__name##_off_entry))               \
481                 goto exit;                                      \
482                                                                 \
483         (__intf)->__name##_val_entry =                          \
484             debugfs_create_file(__stringify(__name) "_value",   \
485                                 S_IRUGO | S_IWUSR,              \
486                                 (__intf)->register_folder,      \
487                                 (__intf), &rt2x00debug_fop_##__name);\
488         if (IS_ERR((__intf)->__name##_val_entry))               \
489                 goto exit;                                      \
490 })
491 
492         RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
493         RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
494         RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
495         RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
496 
497 #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
498 
499         intf->frame_folder =
500             debugfs_create_dir("frame", intf->driver_folder);
501         if (IS_ERR(intf->frame_folder))
502                 goto exit;
503 
504         intf->frame_dump_entry =
505             debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
506                                 intf, &rt2x00debug_fop_ring_dump);
507         if (IS_ERR(intf->frame_dump_entry))
508                 goto exit;
509 
510         skb_queue_head_init(&intf->frame_dump_skbqueue);
511         init_waitqueue_head(&intf->frame_dump_waitqueue);
512 
513         return;
514 
515 exit:
516         rt2x00debug_deregister(rt2x00dev);
517         ERROR(rt2x00dev, "Failed to register debug handler.\n");
518 
519         return;
520 }
521 
522 void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
523 {
524         struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
525 
526         if (unlikely(!intf))
527                 return;
528 
529         skb_queue_purge(&intf->frame_dump_skbqueue);
530 
531         debugfs_remove(intf->frame_dump_entry);
532         debugfs_remove(intf->frame_folder);
533         debugfs_remove(intf->rf_val_entry);
534         debugfs_remove(intf->rf_off_entry);
535         debugfs_remove(intf->bbp_val_entry);
536         debugfs_remove(intf->bbp_off_entry);
537         debugfs_remove(intf->eeprom_val_entry);
538         debugfs_remove(intf->eeprom_off_entry);
539         debugfs_remove(intf->csr_val_entry);
540         debugfs_remove(intf->csr_off_entry);
541         debugfs_remove(intf->register_folder);
542         debugfs_remove(intf->dev_flags);
543         debugfs_remove(intf->chipset_entry);
544         debugfs_remove(intf->driver_entry);
545         debugfs_remove(intf->driver_folder);
546         kfree(intf->chipset_blob.data);
547         kfree(intf->driver_blob.data);
548         kfree(intf);
549 
550         rt2x00dev->debugfs_intf = NULL;
551 }
552 
  This page was automatically generated by the LXR engine.