rt2x00debug.c 19 KB

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