rsi_91x_debugfs.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * Copyright (c) 2014 Redpine Signals 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. #include "rsi_debugfs.h"
  17. #include "rsi_sdio.h"
  18. /**
  19. * rsi_sdio_stats_read() - This function returns the sdio status of the driver.
  20. * @seq: Pointer to the sequence file structure.
  21. * @data: Pointer to the data.
  22. *
  23. * Return: 0 on success, -1 on failure.
  24. */
  25. static int rsi_sdio_stats_read(struct seq_file *seq, void *data)
  26. {
  27. struct rsi_common *common = seq->private;
  28. struct rsi_hw *adapter = common->priv;
  29. struct rsi_91x_sdiodev *dev = adapter->rsi_dev;
  30. seq_printf(seq, "total_sdio_interrupts: %d\n",
  31. dev->rx_info.sdio_int_counter);
  32. seq_printf(seq, "sdio_msdu_pending_intr_count: %d\n",
  33. dev->rx_info.total_sdio_msdu_pending_intr);
  34. seq_printf(seq, "sdio_buff_full_count : %d\n",
  35. dev->rx_info.buf_full_counter);
  36. seq_printf(seq, "sdio_buf_semi_full_count %d\n",
  37. dev->rx_info.buf_semi_full_counter);
  38. seq_printf(seq, "sdio_unknown_intr_count: %d\n",
  39. dev->rx_info.total_sdio_unknown_intr);
  40. /* RX Path Stats */
  41. seq_printf(seq, "BUFFER FULL STATUS : %d\n",
  42. dev->rx_info.buffer_full);
  43. seq_printf(seq, "SEMI BUFFER FULL STATUS : %d\n",
  44. dev->rx_info.semi_buffer_full);
  45. seq_printf(seq, "MGMT BUFFER FULL STATUS : %d\n",
  46. dev->rx_info.mgmt_buffer_full);
  47. seq_printf(seq, "BUFFER FULL COUNTER : %d\n",
  48. dev->rx_info.buf_full_counter);
  49. seq_printf(seq, "BUFFER SEMI FULL COUNTER : %d\n",
  50. dev->rx_info.buf_semi_full_counter);
  51. seq_printf(seq, "MGMT BUFFER FULL COUNTER : %d\n",
  52. dev->rx_info.mgmt_buf_full_counter);
  53. return 0;
  54. }
  55. /**
  56. * rsi_sdio_stats_open() - This function calls single open function of seq_file
  57. * to open file and read contents from it.
  58. * @inode: Pointer to the inode structure.
  59. * @file: Pointer to the file structure.
  60. *
  61. * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
  62. */
  63. static int rsi_sdio_stats_open(struct inode *inode,
  64. struct file *file)
  65. {
  66. return single_open(file, rsi_sdio_stats_read, inode->i_private);
  67. }
  68. /**
  69. * rsi_version_read() - This function gives driver and firmware version number.
  70. * @seq: Pointer to the sequence file structure.
  71. * @data: Pointer to the data.
  72. *
  73. * Return: 0 on success, -1 on failure.
  74. */
  75. static int rsi_version_read(struct seq_file *seq, void *data)
  76. {
  77. struct rsi_common *common = seq->private;
  78. seq_printf(seq, "LMAC : %d.%d.%d.%d\n",
  79. common->lmac_ver.major,
  80. common->lmac_ver.minor,
  81. common->lmac_ver.release_num,
  82. common->lmac_ver.patch_num);
  83. return 0;
  84. }
  85. /**
  86. * rsi_version_open() - This function calls single open function of seq_file to
  87. * open file and read contents from it.
  88. * @inode: Pointer to the inode structure.
  89. * @file: Pointer to the file structure.
  90. *
  91. * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
  92. */
  93. static int rsi_version_open(struct inode *inode,
  94. struct file *file)
  95. {
  96. return single_open(file, rsi_version_read, inode->i_private);
  97. }
  98. /**
  99. * rsi_stats_read() - This function return the status of the driver.
  100. * @seq: Pointer to the sequence file structure.
  101. * @data: Pointer to the data.
  102. *
  103. * Return: 0 on success, -1 on failure.
  104. */
  105. static int rsi_stats_read(struct seq_file *seq, void *data)
  106. {
  107. struct rsi_common *common = seq->private;
  108. static const unsigned char fsm_state[][32] = {
  109. "FSM_FW_NOT_LOADED",
  110. "FSM_CARD_NOT_READY",
  111. "FSM_COMMON_DEV_PARAMS_SENT",
  112. "FSM_BOOT_PARAMS_SENT",
  113. "FSM_EEPROM_READ_MAC_ADDR",
  114. "FSM_EEPROM_READ_RF_TYPE",
  115. "FSM_RESET_MAC_SENT",
  116. "FSM_RADIO_CAPS_SENT",
  117. "FSM_BB_RF_PROG_SENT",
  118. "FSM_MAC_INIT_DONE"
  119. };
  120. seq_puts(seq, "==> RSI STA DRIVER STATUS <==\n");
  121. seq_puts(seq, "DRIVER_FSM_STATE: ");
  122. BUILD_BUG_ON(ARRAY_SIZE(fsm_state) != NUM_FSM_STATES);
  123. if (common->fsm_state <= FSM_MAC_INIT_DONE)
  124. seq_printf(seq, "%s", fsm_state[common->fsm_state]);
  125. seq_printf(seq, "(%d)\n\n", common->fsm_state);
  126. /* Mgmt TX Path Stats */
  127. seq_printf(seq, "total_mgmt_pkt_send : %d\n",
  128. common->tx_stats.total_tx_pkt_send[MGMT_SOFT_Q]);
  129. seq_printf(seq, "total_mgmt_pkt_queued : %d\n",
  130. skb_queue_len(&common->tx_queue[MGMT_SOFT_Q]));
  131. seq_printf(seq, "total_mgmt_pkt_freed : %d\n",
  132. common->tx_stats.total_tx_pkt_freed[MGMT_SOFT_Q]);
  133. /* Data TX Path Stats */
  134. seq_printf(seq, "total_data_vo_pkt_send: %8d\t",
  135. common->tx_stats.total_tx_pkt_send[VO_Q]);
  136. seq_printf(seq, "total_data_vo_pkt_queued: %8d\t",
  137. skb_queue_len(&common->tx_queue[VO_Q]));
  138. seq_printf(seq, "total_vo_pkt_freed: %8d\n",
  139. common->tx_stats.total_tx_pkt_freed[VO_Q]);
  140. seq_printf(seq, "total_data_vi_pkt_send: %8d\t",
  141. common->tx_stats.total_tx_pkt_send[VI_Q]);
  142. seq_printf(seq, "total_data_vi_pkt_queued: %8d\t",
  143. skb_queue_len(&common->tx_queue[VI_Q]));
  144. seq_printf(seq, "total_vi_pkt_freed: %8d\n",
  145. common->tx_stats.total_tx_pkt_freed[VI_Q]);
  146. seq_printf(seq, "total_data_be_pkt_send: %8d\t",
  147. common->tx_stats.total_tx_pkt_send[BE_Q]);
  148. seq_printf(seq, "total_data_be_pkt_queued: %8d\t",
  149. skb_queue_len(&common->tx_queue[BE_Q]));
  150. seq_printf(seq, "total_be_pkt_freed: %8d\n",
  151. common->tx_stats.total_tx_pkt_freed[BE_Q]);
  152. seq_printf(seq, "total_data_bk_pkt_send: %8d\t",
  153. common->tx_stats.total_tx_pkt_send[BK_Q]);
  154. seq_printf(seq, "total_data_bk_pkt_queued: %8d\t",
  155. skb_queue_len(&common->tx_queue[BK_Q]));
  156. seq_printf(seq, "total_bk_pkt_freed: %8d\n",
  157. common->tx_stats.total_tx_pkt_freed[BK_Q]);
  158. seq_puts(seq, "\n");
  159. return 0;
  160. }
  161. /**
  162. * rsi_stats_open() - This function calls single open function of seq_file to
  163. * open file and read contents from it.
  164. * @inode: Pointer to the inode structure.
  165. * @file: Pointer to the file structure.
  166. *
  167. * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
  168. */
  169. static int rsi_stats_open(struct inode *inode,
  170. struct file *file)
  171. {
  172. return single_open(file, rsi_stats_read, inode->i_private);
  173. }
  174. /**
  175. * rsi_debug_zone_read() - This function display the currently enabled debug zones.
  176. * @seq: Pointer to the sequence file structure.
  177. * @data: Pointer to the data.
  178. *
  179. * Return: 0 on success, -1 on failure.
  180. */
  181. static int rsi_debug_zone_read(struct seq_file *seq, void *data)
  182. {
  183. rsi_dbg(FSM_ZONE, "%x: rsi_enabled zone", rsi_zone_enabled);
  184. seq_printf(seq, "The zones available are %#x\n",
  185. rsi_zone_enabled);
  186. return 0;
  187. }
  188. /**
  189. * rsi_debug_read() - This function calls single open function of seq_file to
  190. * open file and read contents from it.
  191. * @inode: Pointer to the inode structure.
  192. * @file: Pointer to the file structure.
  193. *
  194. * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
  195. */
  196. static int rsi_debug_read(struct inode *inode,
  197. struct file *file)
  198. {
  199. return single_open(file, rsi_debug_zone_read, inode->i_private);
  200. }
  201. /**
  202. * rsi_debug_zone_write() - This function writes into hal queues as per user
  203. * requirement.
  204. * @filp: Pointer to the file structure.
  205. * @buff: Pointer to the character buffer.
  206. * @len: Length of the data to be written into buffer.
  207. * @data: Pointer to the data.
  208. *
  209. * Return: len: Number of bytes read.
  210. */
  211. static ssize_t rsi_debug_zone_write(struct file *filp,
  212. const char __user *buff,
  213. size_t len,
  214. loff_t *data)
  215. {
  216. unsigned long dbg_zone;
  217. int ret;
  218. if (!len)
  219. return 0;
  220. ret = kstrtoul_from_user(buff, len, 16, &dbg_zone);
  221. if (ret)
  222. return ret;
  223. rsi_zone_enabled = dbg_zone;
  224. return len;
  225. }
  226. #define FOPS(fopen) { \
  227. .owner = THIS_MODULE, \
  228. .open = (fopen), \
  229. .read = seq_read, \
  230. .llseek = seq_lseek, \
  231. }
  232. #define FOPS_RW(fopen, fwrite) { \
  233. .owner = THIS_MODULE, \
  234. .open = (fopen), \
  235. .read = seq_read, \
  236. .llseek = seq_lseek, \
  237. .write = (fwrite), \
  238. }
  239. static const struct rsi_dbg_files dev_debugfs_files[] = {
  240. {"version", 0644, FOPS(rsi_version_open),},
  241. {"stats", 0644, FOPS(rsi_stats_open),},
  242. {"debug_zone", 0666, FOPS_RW(rsi_debug_read, rsi_debug_zone_write),},
  243. {"sdio_stats", 0644, FOPS(rsi_sdio_stats_open),},
  244. };
  245. /**
  246. * rsi_init_dbgfs() - This function initializes the dbgfs entry.
  247. * @adapter: Pointer to the adapter structure.
  248. *
  249. * Return: 0 on success, -1 on failure.
  250. */
  251. int rsi_init_dbgfs(struct rsi_hw *adapter)
  252. {
  253. struct rsi_common *common = adapter->priv;
  254. struct rsi_debugfs *dev_dbgfs;
  255. char devdir[6];
  256. int ii;
  257. const struct rsi_dbg_files *files;
  258. dev_dbgfs = kzalloc_obj(*dev_dbgfs);
  259. if (!dev_dbgfs)
  260. return -ENOMEM;
  261. adapter->dfsentry = dev_dbgfs;
  262. snprintf(devdir, sizeof(devdir), "%s",
  263. wiphy_name(adapter->hw->wiphy));
  264. dev_dbgfs->subdir = debugfs_create_dir(devdir, NULL);
  265. for (ii = 0; ii < adapter->num_debugfs_entries; ii++) {
  266. files = &dev_debugfs_files[ii];
  267. dev_dbgfs->rsi_files[ii] =
  268. debugfs_create_file(files->name,
  269. files->perms,
  270. dev_dbgfs->subdir,
  271. common,
  272. &files->fops);
  273. }
  274. return 0;
  275. }
  276. EXPORT_SYMBOL_GPL(rsi_init_dbgfs);
  277. /**
  278. * rsi_remove_dbgfs() - Removes the previously created dbgfs file entries
  279. * in the reverse order of creation.
  280. * @adapter: Pointer to the adapter structure.
  281. *
  282. * Return: None.
  283. */
  284. void rsi_remove_dbgfs(struct rsi_hw *adapter)
  285. {
  286. struct rsi_debugfs *dev_dbgfs = adapter->dfsentry;
  287. if (!dev_dbgfs)
  288. return;
  289. debugfs_remove_recursive(dev_dbgfs->subdir);
  290. }
  291. EXPORT_SYMBOL_GPL(rsi_remove_dbgfs);